]> andersk Git - splint.git/blame_incremental - src/usymtab.c
Fixed internal error that occured if user tried to load a lcd file they created for...
[splint.git] / src / usymtab.c
... / ...
CommitLineData
1/*
2** Splint - annotation-assisted static program checker
3** Copyright (C) 1994-2002 University of Virginia,
4** Massachusetts Institute of Technology
5**
6** This program is free software; you can redistribute it and/or modify it
7** under the terms of the GNU General Public License as published by the
8** Free Software Foundation; either version 2 of the License, or (at your
9** option) any later version.
10**
11** This program is distributed in the hope that it will be useful, but
12** WITHOUT ANY WARRANTY; without even the implied warranty of
13** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14** General Public License for more details.
15**
16** The GNU General Public License is available from http://www.gnu.org/ or
17** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18** MA 02111-1307, USA.
19**
20** For information on splint: info@splint.org
21** To report a bug: splint-bug@splint.org
22** For more information: http://www.splint.org
23*/
24/*
25** usymtab
26**
27** Lexically scoped symbol table.
28**
29** Unlike a normal symbol table, this table splits to reflect branches.
30**
31** This is necessary since symbol table entries also reflect
32** some state information, like initialization, that may be
33** different on different branches.
34**
35** For each control structure we split:
36**
37** { } - a normal scope (no control) US_NORMAL
38**
39** if <pred> { } - US_TBRANCH true branch
40** while <pred> { } US_FBRANCH else branch
41**
42** switch <pred> { } - US_SWITCH
43**
44** case x: - case scope US_CBRANCH
45** Should be kept in a separate table, because of
46** weird C syntax.
47*/
48
49# include "splintMacros.nf"
50# include "basic.h"
51# include "structNames.h"
52# include "exprChecks.h"
53# include "transferChecks.h"
54
55/* Needed to install macros when loading libraries */
56
57# include "cpplib.h"
58# include "cpperror.h"
59# include "cpphash.h"
60
61/*
62** Keep track of type definitions inside a function.
63*/
64
65static uentryList functypes = uentryList_undefined;
66
67static bool dbgfree = FALSE;
68static bool dbgload = TRUE;
69
70/*@access ekind@*/
71
72/*
73** Hack to prevent shadow errors from appearing when function parameters
74** are entered into a new scope.
75*/
76
77static bool noshadowerror = FALSE;
78
79/*
80** Constraint: static variables can live in 1 or > 2.
81**
82** except for tags. All tags must be at the global level.
83** Static tags are handled in a kludgey way.
84*/
85
86/*
87** utab is the universal symbol table
88** globtab is the global environment of utab
89** oldtab is needed for conversions in dumping (after sorting the table)
90**
91** there can be only one usymtab!
92*/
93
94static /*@checkedstrict@*/ /*@owned@*/ /*@notnull@*/ usymtab utab;
95
96/* Reachable environments from from utab */
97static /*@checkedstrict@*/ /*@notnull@*/ /*@dependent@*/ usymtab globtab;
98static /*@checkedstrict@*/ /*@dependent@*/ usymtab filetab;
99
100/* Used for sorting for dumpage. */
101static /*@checkedstrict@*/ /*@owned@*/ usymtab oldtab;
102
103static int usymtab_lexicalLevel (void) /*@globals utab@*/ ;
104static bool usymtab_isAltDefinitelyNull (sRef p_s) /*@globals utab@*/ ;
105static void refTable_free (/*@only@*/ /*@null@*/ refTable p_x, int p_nentries);
106static ctype usymtab_suFieldsType (uentryList p_f, bool p_isStruct) /*@globals globtab@*/ ;
107
108extern int usymtab_getCurrentDepth (void) /*@globals utab@*/
109{
110 return utab->lexlevel;
111}
112
113static void
114usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab p_u)
115 /*@globals globtab, utab, filetab@*/ /*@modifies p_u@*/ ;
116
117static bool usymtab_isDefinitelyNullAux (sRef p_s) /*@globals utab@*/ ;
118static /*@only@*/ cstring usymtab_unparseStackTab (usymtab p_t);
119static /*@exposed@*/ /*@dependent@*/ uentry
120 usymtab_getRefTab (/*@notnull@*/ usymtab p_u, int p_level, usymId p_index);
121
122# ifdef S_SPLINT_S
123/* These are not used anymore... */
124static /*@unused@*/ /*@only@*/ cstring
125 usymtab_unparseLocalAux (/*@notnull@*/ usymtab p_s);
126static /*@unused@*/ /*@only@*/ cstring
127 usymtab_unparseLocalList (/*@notnull@*/ usymtab p_s);
128# endif
129
130static /*@only@*/ cstring usymtab_typeName (/*@notnull@*/ usymtab p_t);
131static void usymtab_handleParams (void)
132 /*@globals utab, globtab, filetab@*/
133 /*@modifies utab@*/ ;
134
135static /*@exposed@*/ /*@dependent@*/ uentry
136 usymtab_addRefEntry (/*@notnull@*/ usymtab p_s, cstring p_k);
137static /*@exposed@*/ /*@dependent@*/ usymtab
138 usymtab_dropEnv (/*@notnull@*/ usymtab p_s);
139static /*@exposed@*/ /*@dependent@*/ uentry
140 usymtab_getRefNoisy (/*@notnull@*/ usymtab p_s, int p_level, usymId p_index);
141
142static /*@exposed@*/ /*@dependent@*/ uentry
143 usymtab_lookupQuietAux (usymtab p_s, cstring p_k, bool p_noalt);
144
145static /*@exposed@*/ /*@dependent@*/ uentry
146 usymtab_lookupQuiet (usymtab p_s, cstring p_k);
147
148static /*@exposed@*/ /*@dependent@*/ uentry
149 usymtab_lookupQuietNoAlt (usymtab p_s, cstring p_k);
150
151static void usymtab_printAllAux (usymtab p_s) /*@modifies g_warningstream@*/ ;
152static int usymtab_getIndex (/*@notnull@*/ usymtab p_s, cstring p_k);
153static /*@exposed@*/ uentry usymtab_fetchIndex (/*@notnull@*/ usymtab p_s, int p_i);
154static /*@exposed@*/ uentry
155 usymtab_lookupAux (usymtab p_s, cstring p_k);
156static /*@exposed@*/ /*@dependent@*/ /*@notnull@*/ usymtab
157 usymtab_getFileTab (void) /*@globals filetab@*/ ;
158static int refTable_lookup (/*@notnull@*/ usymtab p_ut, int p_level, int p_index);
159static bool usymtab_mustBreak (usymtab p_s);
160static bool usymtab_mustEscape (usymtab p_s);
161
162static void recordFunctionType (uentry ue)
163{
164 llassert (uentry_isDatatype (ue) || uentry_isAnyTag (ue)
165 || uentry_isEnumConstant (ue));
166 DPRINTF (("Function type: %s", uentry_unparseFull (ue)));
167 /*@-temptrans@*/
168 functypes = uentryList_add (functypes, ue);
169 /*@=temptrans@*/
170}
171
172static void clearFunctionTypes (void)
173 /*@modifies globtab@*/
174{
175 uentryList_elements (functypes, el)
176 {
177 if (cstring_isDefined (uentry_rawName (el)))
178 {
179 if (cstringTable_isDefined (globtab->htable))
180 {
181 cstringTable_remove (globtab->htable, uentry_rawName (el));
182 }
183
184 uentry_setName (el, cstring_undefined);
185 }
186
187 /*@access uentry@*/
188 llassert (uentry_isValid (el));
189 el->sref = sRef_undefined;
190 /*@noaccess uentry@*/
191 } end_uentryList_elements ;
192
193 uentryList_clear (functypes);
194}
195
196static /*@falsewhennull@*/ bool usymtab_isBranch (usymtab u)
197{
198 return (usymtab_isDefined (u) &&
199 (u->kind == US_TBRANCH || u->kind == US_FBRANCH
200 || u->kind == US_CBRANCH || u->kind == US_SWITCH));
201}
202
203static bool usymtab_mustBreak (usymtab s)
204{
205 llassert (s != GLOBAL_ENV);
206 return (s->mustBreak);
207}
208
209static bool usymtab_mustEscape (usymtab s)
210{
211 llassert (s != GLOBAL_ENV);
212 return (exitkind_mustEscape (s->exitCode));
213}
214
215void usymtab_setMustBreak ()
216 /*@modifies utab@*/
217{
218 llassert (utab != GLOBAL_ENV);
219 utab->mustBreak = TRUE;
220}
221
222void usymtab_setExitCode (exitkind ex)
223 /*@modifies utab@*/
224{
225 llassert (utab != GLOBAL_ENV);
226
227 utab->exitCode = ex;
228
229 if (exitkind_mustEscape (ex))
230 {
231 utab->mustBreak = TRUE;
232 }
233}
234
235bool usymtab_isAltDefinitelyNullDeep (sRef s)
236{
237 return (sRef_deepPred (usymtab_isAltDefinitelyNull, s));
238}
239
240static bool usymtab_isAltDefinitelyNull (sRef s)
241 /*@globals utab@*/
242{
243 guardSet t;
244 bool res;
245
246 t = utab->guards;
247
248 llassert (utab->env != NULL);
249
250 /*@-mods@*/ /* These modifications are cancelled. */
251 utab->guards = utab->env->guards;
252 utab->env->guards = t;
253 /*@=mods@*/
254
255 llassert (usymtab_isDefined (utab));
256 res = usymtab_isDefinitelyNull (s);
257
258 /*
259 ** This reports a spurious error. It is okay, because of
260 ** the nesting relationship of usymtab environments.
261 */
262
263 /*@-mods@*/ /* Cancelling modifications. */
264 /*@i1@*/ utab->env->guards = utab->guards;
265 /*@i1@*/ utab->guards = t;
266 /*@=mods@*/
267
268 return res;
269}
270
271static /*@notnull@*/ /*@special@*/ usymtab
272 usymtab_create (uskind kind, /*@keep@*/ usymtab env, bool nextlevel)
273 /*@defines result@*/
274 /*@post:isnull result->htable, result->guards, result->aliases@*/
275{
276 usymtab t = (usymtab) dmalloc (sizeof (*t));
277
278 t->nentries = 0;
279 t->nspace = CBASESIZE;
280 t->entries = (uentry *) dmalloc (sizeof (*t->entries) * CBASESIZE);
281
282 /* We only use a reftable for branch-level symbol tables.
283 */
284
285 t->reftable = (nextlevel
286 ? NULL
287 : (refentry *) dmalloc (sizeof (*t->reftable) * CBASESIZE));
288
289 t->kind = kind;
290 t->lexlevel = (env == GLOBAL_ENV ? 0 : env->lexlevel) + (nextlevel ? 1 : 0);
291
292 t->env = env;
293 t->htable = NULL;
294
295 t->guards = guardSet_undefined;
296 t->aliases = aliasTable_undefined;
297
298 t->mustBreak = FALSE;
299 t->exitCode = XK_NEVERESCAPE;
300
301 return t;
302}
303
304/*
305** constructors
306*/
307
308static /*@only@*/ /*@notnull@*/ usymtab
309 usymtab_createRoot (void) /*@modifies nothing@*/
310{
311 usymtab u = (usymtab) dmalloc (sizeof (*u));
312
313 u->nentries = 0;
314 u->nspace = CGLOBBASESIZE;
315 u->entries = (uentry *) dmalloc (sizeof (*u->entries) * CGLOBBASESIZE);
316 u->env = GLOBAL_ENV;
317 u->lexlevel = 0;
318 u->htable = cstringTable_create (CGLOBHASHSIZE);
319 u->reftable = NULL;
320
321 u->guards = guardSet_new ();
322 u->aliases = aliasTable_new ();
323
324 u->mustBreak = FALSE;
325 u->exitCode = XK_NEVERESCAPE;
326 u->kind = US_NORMAL;
327
328 return (u);
329}
330
331void
332usymtab_initMod (void)
333 /*@globals undef utab, undef oldtab, undef globtab, undef filetab @*/
334 /*@modifies utab, globtab, filetab, oldtab @*/
335{
336 utab = usymtab_createRoot ();
337 globtab = utab;
338 filetab = usymtab_undefined;
339 oldtab = usymtab_undefined;
340}
341
342
343void
344usymtab_initGlobalMarker () /*@globals globtab@*/
345{
346 if (uentry_isValid (usymtab_lookupAux (globtab, GLOBAL_MARKER_NAME)))
347 {
348 ; /* Already entered from load table. */
349 }
350 else
351 {
352 usymtab_addGlobalEntry (uentry_makeGlobalMarker ());
353 }
354}
355
356/*
357** utab should be empty? (requires?)
358**
359** Adds bool types to symbol table (these are built in for now)
360** Only do this is there is no library!
361*/
362
363void
364usymtab_initBool ()
365{
366 DPRINTF (("Init bool!"));
367
368 if (context_getFlag (FLG_NOLIB))
369 {
370 ctype boolt = ctype_bool;
371 /* evs 2000-07-24: bool is now treated as abstract (always) */
372
373 uentry boolentry = uentry_makeBoolDatatype (YES);
374 usymtab_supGlobalEntry (boolentry);
375 context_addBoolAccess ();
376
377 /*
378 ** We supply values 0 and 1 for the constants, so things like
379 ** while (TRUE) can be interpreted correctly.
380 */
381
382 usymtab_supGlobalEntry
383 (uentry_makeConstantValue (context_getFalseName (), boolt,
384 fileloc_getBuiltin (), FALSE,
385 multiVal_makeInt (0)));
386
387 usymtab_supGlobalEntry
388 (uentry_makeConstantValue (context_getTrueName (), boolt,
389 fileloc_getBuiltin (), FALSE,
390 multiVal_makeInt (1)));
391 }
392}
393
394/*
395** mutators
396*/
397
398static void
399usymtab_grow (/*@notnull@*/ usymtab s)
400{
401 int i;
402 o_uentry *oldsyms = s->entries;
403
404 s->nspace = CBASESIZE;
405 s->entries = (uentry *) dmalloc (sizeof (*s->entries)
406 * (s->nentries + s->nspace));
407
408 for (i = 0; i < s->nentries; i++)
409 {
410 s->entries[i] = oldsyms[i];
411 }
412
413 sfree (oldsyms);
414
415 if (s->reftable != NULL)
416 {
417 refTable oldRefs = s->reftable;
418
419 s->reftable = (refentry *) dmalloc (sizeof (*s->reftable)
420 * (s->nentries + CBASESIZE + 1));
421
422 for (i = 0; i < s->nentries; i++)
423 {
424 s->reftable[i] = oldRefs[i];
425 }
426
427 /*@-compdestroy@*/
428 sfree (oldRefs);
429 /*@=compdestroy@*/
430 }
431
432}
433
434static void
435usymtab_addEntryQuiet (/*@notnull@*/ usymtab s, /*@keep@*/ uentry e)
436{
437 if (!(s->lexlevel > fileScope || !sRef_modInFunction ()))
438 {
439 if (uentry_isDatatype (e)
440 || uentry_isFunction (e)
441 || uentry_isAnyTag (e)
442 || uentry_isEnumConstant (e)
443 || context_inMacro ())
444 {
445 /*
446 ** Not a bug. Code like,
447 ** int f (void) { typedef int tint; ... }
448 ** is legal.
449 */
450
451 /* was nothing here! */
452 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
453 }
454 else
455 {
456 llparseerror
457 (cstring_makeLiteral ("Declaration outside function scope"));
458
459 llcontbug (message ("usymtab_addEntryQuiet: inconsistent state "
460 "(lexlevel = %d, modFunction = %s) adding: %q",
461 s->lexlevel, bool_unparse (sRef_modInFunction ()),
462 uentry_unparse (e)));
463 sRef_setGlobalScope ();
464 /* make sure the sRef is not bashed! */
465 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
466 }
467 }
468
469 if (s->nspace <= 0)
470 {
471 usymtab_grow (s);
472 }
473
474 s->nspace--;
475 s->entries[s->nentries] = e;
476
477# ifdef DOANNOTS
478 if (s == globtab || s == filetab)
479 {
480 if (!fileloc_isLib (g_currentloc))
481 {
482 uentry_tallyAnnots (e, AN_UNKNOWN);
483 }
484 }
485# endif
486
487 if (cstringTable_isDefined (s->htable))
488 {
489 cstringTable_insert (s->htable, cstring_copy (uentry_rawName (e)), s->nentries);
490 }
491
492 s->nentries++;
493}
494
495static /*@observer@*/ uentry /*@alt void@*/
496usymtab_addEntryBase (/*@notnull@*/ usymtab s, /*@only@*/ uentry e)
497{
498 /*
499 ** In theory, we shouldn't need this test because it this is
500 ** only called when a library is being read, and it shouldn't
501 ** ever have a duplicate entry. In practice, its safer to
502 ** leave it in, though.
503 */
504
505 uentry old;
506
507 if (uentry_isValid (old = usymtab_lookupQuiet (s, uentry_rawName (e))))
508 {
509 DPRINTF (("Duplicate entry: %s", uentry_unparse (e)));
510 uentry_free (e); /* duplicate */
511 return old;
512 }
513 else
514 {
515 int thisentry = s->nentries;
516
517 if (uentry_isVar (e))
518 {
519 uentry_setSref (e, sRef_makeCvar (globScope, thisentry,
520 uentry_getType (e),
521 stateInfo_makeLoc (uentry_whereLast (e))));
522 }
523
524 usymtab_addEntryQuiet (s, e);
525 return e;
526 }
527}
528
529
530static /*@observer@*/ uentry /*@alt void@*/
531usymtab_addEntryAlways (/*@notnull@*/ usymtab s, /*@only@*/ uentry e)
532{
533 /*
534 ** In theory, we shouldn't need this test because it this is
535 ** only called when a library is being read, and it shouldn't
536 ** ever have a duplicate entry. In practice, its safer to
537 ** leave it in, though.
538 */
539
540 uentry old;
541 int thisentry = s->nentries;
542
543 if (uentry_isValid (old = usymtab_lookupQuiet (s, uentry_rawName (e))))
544 {
545 llcontbug
546 (message ("Duplicate entry in load library: %s. "
547 "Old entry: %q. New entry: %q",
548 uentry_rawName (e),
549 uentry_unparseFull (old),
550 uentry_unparseFull (e)));
551
552 uentry_setName (e, message ("__x_%s", uentry_rawName (e)));
553 /* This shouldn't happen...unless the library is bad! */
554 }
555
556
557 if (uentry_isVar (e) && !uentry_isGlobalMarker (e))
558 {
559 uentry_setSref (e, sRef_makeCvar (globScope, thisentry,
560 uentry_getType (e),
561 stateInfo_makeLoc (uentry_whereLast (e))));
562 }
563
564 usymtab_addEntryQuiet (s, e);
565 return e;
566}
567
568static usymId
569usymtab_addEntryAux (/*@notnull@*/ usymtab st, /*@keep@*/ uentry e, bool isSref)
570 /*@globals globtab@*/
571 /*@modifies st, e@*/
572{
573 usymId thisentry = st->nentries;
574
575 llassert (!uentry_isElipsisMarker (e));
576
577 /*
578 ** not true for tags
579 ** llassert (usymtab_lookupSafe (uentry_rawName (e)) == uentry_undefined);
580 **/
581
582 llassertprint (uentry_isAnyTag (e) ? st == globtab : TRUE,
583 ("non-global tag: %s / %d", uentry_unparseFull (e), st->lexlevel));
584
585 if (st->lexlevel == fileScope
586 && (!(uentry_isStatic (e)) || uentry_isAnyTag (e)))
587 {
588 st = globtab;
589 }
590
591 if (isSref)
592 {
593 ctype ct = uentry_getType (e);
594
595 if (uentry_isFunction (e) && ctype_isFunction (ct))
596 {
597 ct = ctype_getReturnType (ct);
598 }
599
600 if (uentry_isStatic (e))
601 {
602 sRef sr = sRef_makeCvar (st->lexlevel, thisentry, ct, stateInfo_makeLoc (uentry_whereLast (e)));
603
604 if (sRef_isStack (sr) || sRef_isLocalState (sr))
605 {
606 sRef_setAliasKind (sr, AK_STATIC, uentry_whereLast (e));
607 sRef_setDefined (sr, uentry_whereLast (e));
608 }
609
610 uentry_setSref (e, sr);
611 }
612 else
613 {
614 uentry_setSref (e, sRef_makeCvar (st->lexlevel, thisentry, ct, stateInfo_makeLoc (uentry_whereLast (e))));
615 }
616 }
617
618 if (uentry_isDatatype (e))
619 {
620
621 uentry_setDatatype (e, thisentry);
622 }
623
624 if (uentry_isFunction (e))
625 {
626 ctype ct = uentry_getType (e);
627
628 if (ctype_isFunction (ct)
629 && uentryList_isMissingParams (ctype_argsFunction (ct)))
630 {
631 if (uentry_isDeclared (e))
632 {
633 voptgenerror
634 (FLG_NOPARAMS,
635 message ("Function %q declared without parameter list",
636 uentry_getName (e)),
637 uentry_whereDeclared (e));
638 }
639 else
640 {
641 voptgenerror
642 (FLG_NOPARAMS,
643 message ("Function %q specified without parameter list",
644 uentry_getName (e)),
645 uentry_whereSpecified (e));
646 }
647 }
648 }
649
650 if (st == globtab && !uentry_isSpecified (e))
651 {
652 exprChecks_checkExport (e);
653 }
654
655 uentry_checkName (e);
656
657 usymtab_addEntryQuiet (st, e);
658 DPRINTF (("Adding entry: [%p] %s", e, uentry_unparseFull (e)));
659 return (thisentry);
660}
661
662usymId
663usymtab_addEntry (uentry e)
664 /*@globals utab, globtab@*/
665 /*@modifies utab, e@*/
666{
667 llassertprint (!usymtab_exists (uentry_rawName (e)),
668 ("Entry already exists: %s", uentry_unparse (e)));
669
670 return usymtab_addEntryAux (utab, e, FALSE);
671}
672
673void
674usymtab_addGlobalEntry (uentry e)
675 /*@modifies globtab, e@*/
676{
677 DPRINTF (("Add global: %s / %s", uentry_unparse (e), bool_unparse (uentry_isForward (e))));
678
679 (void) usymtab_addEntryAux (globtab, e, FALSE);
680}
681
682/*
683** supercede and replace entry use elements of entries array, and
684** assign an element to a new value, and then free the old value.
685** Need -deparrays to avoid errors for this.
686*/
687
688/*@-deparrays@*/
689
690static usymId
691usymtab_supEntryAux (/*@notnull@*/ usymtab st,
692 /*@only@*/ uentry e, bool isSref)
693 /*@globals globtab, filetab@*/
694 /*@modifies st, globtab, e@*/
695{
696 cstring ename = uentry_rawName (e);
697 bool staticEntry = FALSE;
698 int eindex;
699
700 DPRINTF (("Sup entry aux: %s", uentry_unparseFull (e)));
701
702 /* static tags in global scope */
703 if (st->lexlevel == fileScope
704 && (!(uentry_isStatic (e)) || uentry_isAnyTag (e)))
705 {
706 eindex = usymtab_getIndex (st, ename);
707
708 if (eindex != NOT_FOUND)
709 {
710 uentry ce = st->entries[eindex];
711
712 if (optgenerror
713 (FLG_SHADOW,
714 message ("%s %q shadows static declaration",
715 ekind_capName (uentry_getKind (e)),
716 uentry_getName (e)),
717 uentry_whereDeclared (e)))
718 {
719 uentry_showWhereLast (ce);
720 }
721
722 if (eindex == st->nentries - 1)
723 {
724 ;
725 }
726 else
727 {
728 st->entries[eindex] = st->entries[st->nentries - 1];
729 }
730
731 if (cstringTable_isDefined (st->htable))
732 {
733 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
734 cstring_copy (uentry_rawName (e)));
735 }
736
737 uentry_free (ce);
738 st->nentries--;
739 }
740
741 st = globtab;
742 }
743
744 if (uentry_isStatic (e)) {
745 if (uentry_isFunction (e)) {
746 /*
747 ** Static function declarations are at the file level,
748 ** even if they are in a deeper scope.
749 */
750
751 st = usymtab_getFileTab ();
752 staticEntry = TRUE;
753 } else {
754 if (!uentry_isAnyTag (e) && st == globtab)
755 {
756 st = usymtab_getFileTab ();
757 staticEntry = TRUE;
758 DPRINTF (("Static entry!"));
759 }
760 }
761 }
762
763 eindex = usymtab_getIndex (st, ename);
764
765 if (eindex != NOT_FOUND)
766 {
767 uentry ce = st->entries[eindex];
768
769 DPRINTF (("Found entry: %s", uentry_unparse (ce)));
770
771 if (uentry_isPriv (ce)
772 /* || (fileloc_isImport (uentry_whereSpecified (ce))) */
773 || (uentry_isStatic (ce)
774 && uentry_isAnyTag (ce)
775 && (uentry_isDeclared (ce)
776 && !fileloc_sameFile (uentry_whereDefined (ce),
777 uentry_whereDefined (e)))))
778 {
779 /*
780 ** overload entry
781 ** if overloading import should do some checks!
782 */
783
784 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
785
786 DPRINTF (("Overloading!"));
787
788 st->entries[eindex] = e;
789
790 if (uentry_isDatatype (e))
791 {
792 uentry_setDatatype (e, eindex);
793 }
794
795 if (st == globtab && !uentry_isSpecified (e))
796 {
797 exprChecks_checkExport (e);
798 }
799
800 if (cstringTable_isDefined (st->htable))
801 {
802 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
803 cstring_copy (uentry_rawName (e)));
804 }
805
806 uentry_free (ce);
807 ce = e;
808 }
809 else if (uentry_isSpecified (ce))
810 {
811 if (uentry_isSpecified (e))
812 {
813 DPRINTF (("Here we are: %s", uentry_unparseFull (e)));
814
815 if (fileloc_isImport (uentry_whereSpecified (ce)))
816 {
817 if (cstringTable_isDefined (st->htable))
818 {
819 cstringTable_replaceKey (st->htable,
820 uentry_rawName (ce),
821 cstring_copy (uentry_rawName (e)));
822 }
823
824 uentry_free (ce);
825 st->entries[eindex] = e;
826 ce = e;
827
828 if (uentry_isDatatype (e)) uentry_setDatatype (e, eindex);
829 }
830 else
831 {
832 if (fileloc_isImport (uentry_whereSpecified (e)))
833 {
834 uentry_free (e);
835 }
836 else
837 {
838 /* Respecification errors already reported */
839 DPRINTF (("Respecification: %s / %s",
840 fileloc_unparse (uentry_whereSpecified (e)),
841 bool_unparse (fileloc_isSpec (uentry_whereSpecified (e)))));
842
843 if (uentry_isDatatype (e))
844 {
845 uentry_setDatatype (e, eindex);
846 }
847
848 if (cstringTable_isDefined (st->htable))
849 {
850 cstringTable_replaceKey (st->htable,
851 uentry_rawName (ce),
852 cstring_copy (uentry_rawName (e)));
853 }
854
855 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
856 uentry_free (ce);
857 st->entries[eindex] = e;
858 ce = e;
859 }
860 }
861 }
862 else /* e not specified */
863 {
864 DPRINTF (("Merging..."));
865
866 if (uentry_isDeclared (ce))
867 {
868 /* evans 2001-08-26
869 No - this can happen for internal typedefs
870 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
871 */
872
873 DPRINTF (("Merge defn"));
874 uentry_mergeDefinition (ce, e);
875 }
876 else
877 {
878 /* evans 2001-08-26
879 No - this can happen for internal typedefs
880 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
881 */
882
883 DPRINTF (("Merge entries..."));
884 uentry_mergeEntries (ce, e);
885 DPRINTF (("After: %s", uentry_unparseFull (ce)));
886 }
887 }
888 }
889 else /* ce not specified */
890 {
891 if (!(st->lexlevel > fileScope || !sRef_modInFunction ()))
892 {
893 if (uentry_isDatatype (e) || uentry_isAnyTag (e)
894 || uentry_isEnumConstant (e)
895 || uentry_isStatic (e)) /* bug fix from Brian St. Pierre */
896 {
897 ; /*
898 ** Not a bug. Code like,
899 ** int f (void) { typedef int tint; ... }
900 ** is legal.
901 */
902 }
903 else
904 {
905 llcontbug (message ("usymtab_supEntryAux: inconsistent state "
906 "(lexlevel = %d, modFunction = %s) adding: %q",
907 st->lexlevel, bool_unparse (sRef_modInFunction ()),
908 uentry_unparse (e)));
909
910 if (sRef_modInFunction ())
911 {
912 /* make sure the sRef is not bashed! */
913 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
914 }
915 }
916 }
917
918 DPRINTF (("Merge.."));
919 uentry_mergeDefinition (ce, e);
920 }
921
922 if (isSref)
923 {
924 ctype ct = uentry_getType (ce);
925
926 if (uentry_isFunction (ce) && ctype_isFunction (ct))
927 {
928 ct = ctype_getReturnType (ct);
929 }
930
931 uentry_setSref (ce, sRef_makeCvar (st->lexlevel, eindex, ct, stateInfo_makeLoc (uentry_whereLast (ce))));
932 }
933 }
934 else /* no previous entry */
935 {
936 uentry outer;
937
938 if (st->lexlevel == globScope
939 && !uentry_isStatic (e)
940 && !uentry_isExtern (e)
941 && usymtab_isDefined (filetab))
942 {
943 /*
944 ** check if there is a static entry: (i.e.,
945 **
946 ** static int f ();
947 ** ...
948 ** int f ();
949 */
950
951 eindex = usymtab_getIndex (filetab, ename);
952
953 if (eindex != NOT_FOUND)
954 {
955 uentry ce = filetab->entries[eindex];
956
957 uentry_setStatic (e);
958 uentry_mergeDefinition (ce, e);
959 staticEntry = TRUE;
960 goto exitPoint;
961 }
962 }
963
964 outer = usymtab_lookupQuiet (st->env, ename);
965
966 DPRINTF (("New : [%p] %s", e, uentry_unparseFull (e)));
967 DPRINTF (("Outer: [%p] %s", outer, uentry_unparseFull (outer)));
968
969 /*
970 ** no previous definition, add the new one
971 */
972
973 if (!noshadowerror
974 && uentry_isValid (outer)
975 && !(uentry_isYield (e) || uentry_isYield (outer))
976 && fileloc_isDefined (uentry_whereLast (e))
977 && !fileloc_isXHFile (uentry_whereLast (e))
978 && fileloc_isDefined (uentry_whereLast (outer))
979 && !fileloc_isXHFile (uentry_whereLast (outer)))
980 {
981 if (!uentry_sameKind (outer, e))
982 {
983 ; /* no error */
984 }
985 else
986 {
987 if (ctype_isUnknown (uentry_getType (outer))
988 || uentry_isForward (outer))
989 {
990 ;
991 }
992 else
993 {
994 if (optgenerror
995 (FLG_SHADOW,
996 message ("%s %q shadows outer declaration",
997 ekind_capName (uentry_getKind (e)),
998 uentry_getName (e)),
999 uentry_whereLast (e)))
1000 {
1001 uentry_showWhereLast (outer);
1002 }
1003 }
1004 }
1005 }
1006
1007 if (st == globtab && context_getFlag (FLG_NEWDECL))
1008 {
1009 voptgenerror
1010 (FLG_NEWDECL,
1011 message ("New declaration: %q", uentry_getName (e)),
1012 uentry_whereLast (e));
1013 }
1014
1015 eindex = usymtab_addEntryAux (st, e, isSref);
1016 }
1017
1018 exitPoint:
1019 return (staticEntry ? USYMIDINVALID : eindex);
1020}
1021
1022# ifndef NOLCL
1023static void
1024usymtab_replaceEntryAux (/*@notnull@*/ usymtab st, /*@only@*/ uentry e)
1025 /*@globals globtab@*/ /*@modifies st, e@*/
1026{
1027 cstring ename = uentry_rawName (e);
1028 int eindex;
1029
1030 /* static tags in global scope */
1031 eindex = usymtab_getIndex (st, ename);
1032
1033 if (eindex != NOT_FOUND)
1034 {
1035 uentry ce = st->entries[eindex];
1036
1037 if (cstringTable_isDefined (st->htable))
1038 {
1039 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
1040 cstring_copy (uentry_rawName (e)));
1041 }
1042
1043 uentry_free (ce);
1044 st->entries[eindex] = e;
1045 }
1046 else
1047 {
1048 eindex = usymtab_addEntryAux (st, e, FALSE);
1049 }
1050}
1051# endif
1052
1053/*@=deparrays@*/
1054
1055void usymtab_supEntry (uentry e)
1056 /*@globals utab, filetab, globtab@*/
1057 /*@modifies utab, globtab, e@*/
1058{
1059 (void) usymtab_supEntryAux (utab, e, FALSE);
1060}
1061
1062/*
1063** this should be lots more efficient!
1064*/
1065
1066static /*@exposed@*/ uentry
1067 usymtab_supEntryReturnAux (/*@notnull@*/ usymtab tab,
1068 /*@only@*/ uentry e, bool isref)
1069 /*@globals globtab, filetab@*/
1070 /*@modifies tab, globtab, e@*/
1071{
1072 cstring rawName = cstring_copy (uentry_rawName (e));
1073 bool stat = (tab == globtab) && uentry_isStatic (e);
1074 uentry ret;
1075
1076 (void) usymtab_supEntryAux (tab, e, isref);
1077
1078 if (stat)
1079 {
1080 ret = usymtab_lookupAux (filetab, rawName);
1081 }
1082 else
1083 {
1084 ret = usymtab_lookupAux (tab, rawName);
1085
1086 if (uentry_isInvalid (ret) && usymtab_isDefined (filetab))
1087 {
1088 ret = usymtab_lookupAux (filetab, rawName);
1089 }
1090 }
1091
1092 cstring_free (rawName);
1093 return ret;
1094}
1095
1096/*@dependent@*/ /*@exposed@*/ uentry
1097 usymtab_supEntryReturn (/*@only@*/ uentry e)
1098 /*@globals utab, filetab, globtab@*/
1099 /*@modifies utab, globtab, e@*/
1100{
1101 return (usymtab_supEntryReturnAux (utab, e, FALSE));
1102}
1103
1104/*@dependent@*/ /*@exposed@*/ uentry
1105 usymtab_supEntrySrefReturn (/*@only@*/ uentry e)
1106 /*@globals utab, globtab, filetab@*/
1107 /*@modifies utab, globtab, e@*/
1108{
1109 return (usymtab_supEntryReturnAux (utab, e, TRUE));
1110}
1111
1112/*@dependent@*/ /*@exposed@*/ uentry
1113 usymtab_supGlobalEntryReturn (uentry e)
1114 /*@globals globtab, filetab@*/
1115 /*@modifies globtab, e@*/
1116{
1117 uentry ret;
1118
1119 ret = usymtab_supEntryReturnAux (globtab, e, FALSE);
1120
1121 /*
1122 ** We need to keep track of internal function declarations, so
1123 ** we can remove them from the symbol table after exiting this
1124 ** function. This is a bit bogus, of course.
1125 */
1126
1127 if (sRef_modInFunction ())
1128 {
1129 recordFunctionType (ret);
1130 }
1131
1132 return (ret);
1133}
1134
1135ctype
1136usymtab_supTypeEntry (/*@only@*/ uentry e)
1137 /*@globals globtab, filetab@*/
1138 /*@modifies globtab, e@*/
1139{
1140 usymId uid;
1141 ctype ret;
1142
1143 if (uentry_isAbstractDatatype (e))
1144 {
1145 uid = usymtab_supAbstractTypeEntry (e, FALSE);
1146 ret = ctype_createAbstract (uid);
1147 }
1148 else
1149 {
1150 uid = usymtab_supEntryAux (globtab, e, FALSE);
1151 ret = ctype_createUser (uid);
1152 }
1153
1154 if (sRef_modInFunction ())
1155 {
1156 recordFunctionType (globtab->entries[uid]);
1157 }
1158
1159 return ret;
1160}
1161
1162uentry
1163usymtab_supReturnTypeEntry (/*@only@*/ uentry e)
1164 /*@globals globtab, filetab@*/
1165 /*@modifies globtab@*/
1166{
1167 usymId uid;
1168
1169 DPRINTF (("Abstract? %s", uentry_unparseFull (e)));
1170
1171 if (uentry_isAbstractDatatype (e))
1172 {
1173 uid = usymtab_supAbstractTypeEntry (e, FALSE);
1174 }
1175 else if (uentry_isMaybeAbstract (e) && context_getFlag (FLG_IMPABSTRACT))
1176 {
1177 bool maybeabs = TRUE;
1178 cstring sname = uentry_getName (e);
1179 uentry ue = usymtab_lookupGlobSafe (sname);
1180 cstring_free (sname);
1181
1182 if (uentry_isValid (ue))
1183 {
1184 DPRINTF (("Lookup: %s", uentry_unparseFull (ue)));
1185
1186 if (uentry_isDatatype (ue))
1187 {
1188 if (uentry_isMaybeAbstract (ue))
1189 {
1190 ;
1191 }
1192 else
1193 {
1194 maybeabs = FALSE;
1195 }
1196 }
1197 else
1198 {
1199 DPRINTF (("Not datatype!"));
1200 }
1201 }
1202
1203 if (maybeabs)
1204 {
1205 uentry ux;
1206 uid = usymtab_supAbstractTypeEntry (e, FALSE);
1207 ux = usymtab_getTypeEntry (uid);
1208 uentry_setAbstract (ux);
1209 }
1210 else
1211 {
1212 uid = usymtab_supEntryAux (globtab, e, FALSE);
1213 e = usymtab_getTypeEntry (uid);
1214
1215 if (uentry_isMaybeAbstract (e))
1216 {
1217 uentry_setConcrete (e);
1218 }
1219 }
1220 }
1221 else
1222 {
1223 uid = usymtab_supEntryAux (globtab, e, FALSE);
1224 e = usymtab_getTypeEntry (uid);
1225
1226 if (uentry_isMaybeAbstract (e))
1227 {
1228 uentry_setConcrete (e);
1229 }
1230 }
1231
1232 if (sRef_modInFunction ())
1233 {
1234 recordFunctionType (globtab->entries[uid]);
1235 }
1236
1237 return (globtab->entries[uid]);
1238}
1239
1240usymId
1241usymtab_supAbstractTypeEntry (/*@only@*/ uentry e, bool dodef)
1242 /*@globals globtab, filetab@*/
1243 /*@modifies globtab, e@*/
1244{
1245 usymId uid;
1246 uentry ue;
1247
1248 uid = usymtab_supEntryAux (globtab, e, FALSE);
1249 ue = usymtab_getTypeEntry (uid);
1250
1251 if (dodef)
1252 {
1253 uentry_setDatatype (ue, uid);
1254 }
1255
1256 if (context_getFlag (FLG_ACCESSMODULE)) /* was accessfile */
1257 {
1258 context_addFileAccessType (uid);
1259 }
1260
1261 if (sRef_modInFunction ())
1262 {
1263 recordFunctionType (globtab->entries[uid]);
1264 }
1265
1266 return (uid);
1267}
1268
1269# ifndef NOLCL
1270usymId
1271usymtab_supExposedTypeEntry (/*@only@*/ uentry e, bool dodef)
1272 /*@globals globtab, filetab@*/
1273 /*@modifies globtab, e@*/
1274{
1275 usymId uid;
1276
1277 uid = usymtab_supEntryAux (globtab, e, FALSE);
1278
1279 if (dodef)
1280 {
1281 uentry ue = usymtab_getTypeEntry (uid);
1282
1283 uentry_setDatatype (ue, uid);
1284 }
1285
1286 if (sRef_modInFunction ())
1287 {
1288 recordFunctionType (globtab->entries[uid]);
1289 }
1290
1291 return (uid);
1292}
1293# endif
1294
1295ctype
1296usymtab_supForwardTypeEntry (/*@only@*/ uentry e)
1297 /*@globals globtab, filetab@*/
1298 /*@modifies globtab, e@*/
1299{
1300 usymId uid = usymtab_supEntryAux (globtab, e, FALSE);
1301 uentry ue = usymtab_getTypeEntry (uid);
1302
1303 uentry_setDatatype (ue, uid);
1304
1305 if (sRef_modInFunction ())
1306 {
1307 recordFunctionType (globtab->entries[uid]);
1308 }
1309
1310 return (uentry_getAbstractType (ue));
1311}
1312
1313void
1314 usymtab_supEntrySref (uentry e)
1315 /*@globals utab, globtab, filetab@*/
1316 /*@modifies utab, globtab, e@*/
1317{
1318 sRef old = uentry_getSref (e);
1319
1320 if (sRef_isType (old))
1321 {
1322 uentry ue = usymtab_supEntryReturnAux (utab, e, TRUE);
1323
1324 /*@access uentry@*/
1325 if (uentry_isValid (ue))
1326 {
1327 sRef uref = uentry_getSref (ue);
1328
1329 sRef_mergeStateQuiet (uref, old);
1330 sRef_clearDerived (uref);
1331 }
1332 /*@noaccess uentry@*/
1333 }
1334 else if (sRef_isKnown (old))
1335 {
1336 usymtab_supEntry (e);
1337 }
1338 else
1339 {
1340 (void) usymtab_supEntryAux (utab, e, TRUE);
1341 }
1342}
1343
1344void usymtab_supGlobalEntry (/*@only@*/ uentry e)
1345 /*@globals globtab, filetab@*/
1346 /*@modifies globtab, filetab, e@*/
1347{
1348 usymId uid;
1349
1350 DPRINTF (("Sup global entry: %s", uentry_unparse (e)));
1351
1352 uid = usymtab_supEntryAux (globtab, e, FALSE);
1353
1354 if (sRef_modInFunction ())
1355 {
1356 recordFunctionType (globtab->entries[uid]);
1357 }
1358}
1359
1360uentry
1361 usymtab_supReturnFileEntry (/*@only@*/ uentry e)
1362 /*@globals filetab, globtab@*/
1363 /*@modifies filetab, globtab, e@*/
1364{
1365 llassert (filetab != usymtab_undefined);
1366 DPRINTF (("File entry: %s", uentry_unparse (e)));
1367 return (usymtab_supEntryReturnAux (filetab, e, FALSE));
1368}
1369
1370/*
1371** observers
1372*/
1373
1374bool
1375usymtab_inDeepScope () /*@globals utab@*/
1376{
1377 return (utab->lexlevel > paramsScope);
1378}
1379
1380static int
1381usymtab_getIndex (/*@notnull@*/ usymtab s, cstring k)
1382{
1383 int i;
1384
1385 DPRINTF (("Lookup %s", k));
1386
1387 if (cstringTable_isDefined (s->htable))
1388 {
1389 i = cstringTable_lookup (s->htable, k);
1390 return i;
1391 }
1392 else
1393 {
1394 for (i = 0; i < s->nentries; i++)
1395 {
1396 uentry current = s->entries[i];
1397
1398 DPRINTF (("Check %d: %s", i, uentry_rawName (current)));
1399
1400 if (!uentry_isUndefined (current)
1401 && cstring_equal (uentry_rawName (current), k))
1402 {
1403 return i;
1404 }
1405 }
1406
1407 return NOT_FOUND;
1408 }
1409}
1410
1411static uentry
1412usymtab_fetchIndex (/*@notnull@*/ usymtab s, int i)
1413{
1414 llassert (i >= 0 && i < s->nentries);
1415 return (s->entries[i]);
1416}
1417
1418usymId
1419usymtab_getTypeId (cstring k) /*@globals globtab@*/
1420{
1421 usymId uid = usymtab_getIndex (globtab, k);
1422
1423 if (uid == NOT_FOUND) return USYMIDINVALID;
1424
1425 if (!(uentry_isDatatype (usymtab_getTypeEntry (uid)))) {
1426 return USYMIDINVALID;
1427 }
1428
1429 return uid;
1430}
1431
1432/*@dependent@*/ uentry
1433usymtab_lookupStructTag (cstring k)
1434{
1435 cstring sname = makeStruct (k);
1436 uentry ue = usymtab_lookupGlob (sname);
1437
1438 cstring_free (sname);
1439 return (ue);
1440}
1441
1442/*@dependent@*/ uentry
1443usymtab_lookupUnionTag (cstring k)
1444{
1445 cstring uname = makeUnion (k);
1446 uentry res = usymtab_lookupGlob (uname);
1447
1448 cstring_free (uname);
1449 return res;
1450}
1451
1452/*@dependent@*/ uentry
1453usymtab_lookupEnumTag (cstring k)
1454{
1455 cstring ename = makeEnum (k);
1456 uentry res = usymtab_lookupGlob (ename);
1457
1458 cstring_free (ename);
1459 return res;
1460}
1461
1462usymId
1463usymtab_getId (cstring k) /*@globals globtab@*/
1464{
1465 usymId uid = usymtab_getIndex (globtab, k);
1466 uentry ue;
1467
1468 if (uid == NOT_FOUND)
1469 {
1470 return USYMIDINVALID;
1471 }
1472
1473 ue = usymtab_getGlobalEntry (uid);
1474
1475 if (uentry_isPriv (ue))
1476 {
1477 return USYMIDINVALID;
1478 }
1479
1480 return uid;
1481}
1482
1483static /*@exposed@*/ uentry
1484usymtab_getEntryAux (/*@notnull@*/ usymtab s, usymId uid)
1485{
1486 llassert (uid != USYMIDINVALID);
1487
1488 if (uid < 0 || uid >= s->nentries)
1489 {
1490 llcontbug (message ("usymtab_getEntry: out of range: level = %d [%d]",
1491 s->lexlevel, uid));
1492 return uentry_undefined;
1493 }
1494
1495 llassertprint (uentry_isValid (s->entries[uid]),
1496 ("entry undefined: %d", uid));
1497
1498 return s->entries[uid];
1499}
1500
1501/*@dependent@*/ /*@observer@*/ uentry
1502 usymtab_getGlobalEntry (usymId uid)
1503 /*@globals utab, globtab@*/
1504{
1505 if (dbgfree) return (uentry_undefined);
1506
1507 if (utab->lexlevel > paramsScope)
1508 {
1509 /* need to do this the awkward way, since it could be in conditional scope */
1510 return (usymtab_lookupSafe (uentry_rawName (globtab->entries[uid])));
1511 }
1512 else
1513 {
1514 return (globtab->entries[uid]);
1515 }
1516}
1517
1518/*@dependent@*/ /*@exposed@*/ uentry
1519 usymtab_getTypeEntry (usymId uid)
1520 /*@globals globtab@*/
1521{
1522 if (dbgload)
1523 {
1524 if (uid >= 0 && uid < globtab->nentries)
1525 {
1526 return (globtab->entries[uid]);
1527 }
1528 else
1529 {
1530 return (uentry_undefined);
1531 }
1532 }
1533 else
1534 {
1535 llassert (uid >= 0 && uid < globtab->nentries);
1536 return (globtab->entries[uid]);
1537 }
1538}
1539
1540/*
1541** in load files
1542*/
1543
1544/*@dependent@*/ /*@exposed@*/ uentry
1545 usymtab_getTypeEntrySafe (usymId uid)
1546 /*@globals globtab@*/
1547{
1548 if (uid < 0 || uid >= globtab->nentries)
1549 {
1550 return uentry_undefined;
1551 }
1552
1553 return (globtab->entries[uid]);
1554}
1555
1556bool
1557 usymtab_isBoolType (usymId uid)
1558 /*@globals globtab@*/
1559{
1560 llassert (uid >= 0 && uid < globtab->nentries);
1561
1562 return (cstring_equal (uentry_rawName (globtab->entries[uid]),
1563 context_getBoolName ()));
1564}
1565
1566cstring
1567usymtab_getTypeEntryName (usymId uid)
1568 /*@globals globtab@*/
1569{
1570 uentry ue;
1571
1572 if (dbgfree)
1573 {
1574 return (cstring_makeLiteral ("<freetype>"));
1575 }
1576
1577 ue = usymtab_getTypeEntry (uid);
1578
1579 if (dbgload && !uentry_isValid (ue))
1580 {
1581 return (message ("<missing type: %d>", uid));
1582 }
1583
1584 llassertprint (uentry_isValid (ue), ("type undefined: %d", uid));
1585
1586 return (uentry_getName (ue));
1587}
1588
1589# if 0
1590/*@unused@*/ static void
1591usymtab_rehash (/*@notnull@*/ usymtab s)
1592{
1593 int i;
1594
1595 if (cstringTable_isDefined (s->htable))
1596 {
1597 cstringTable_free (s->htable);
1598 }
1599
1600 s->htable = cstringTable_create (LLAHSHSIZE);
1601
1602 for (i = 0; i < s->nentries; i++)
1603 {
1604 cstringTable_insert (s->htable, cstring_copy (uentry_rawName (s->entries[i])), i);
1605 }
1606}
1607# endif
1608
1609/*
1610** superficial copy of usymtab
1611**
1612** DO copy spec entries
1613*/
1614
1615static /*@only@*/ /*@notnull@*/ usymtab
1616usymtab_shallowCopy (/*@notnull@*/ usymtab s) /*@*/
1617{
1618 usymtab copytab = usymtab_createRoot ();
1619 int i;
1620
1621 for (i = 0; i < s->nentries; i++)
1622 {
1623 usymtab_addEntryBase (copytab, s->entries[i]);
1624 }
1625
1626 return copytab;
1627}
1628
1629static void
1630usymtab_shallowFree (/*@only@*/ /*@notnull@*/ usymtab s)
1631{
1632 aliasTable_free (s->aliases);
1633 refTable_free (s->reftable, s->nentries);
1634 sfree (s->entries);
1635 /*@-compdestroy@*/ sfree (s); /*@=compdestroy@*/
1636}
1637
1638/*
1639** converts usymId from old table to sorted one
1640*/
1641
1642usymId
1643 usymtab_convertId (usymId uid)
1644 /*@globals oldtab, utab@*/
1645{
1646 uentry ue;
1647 usymId ret;
1648 cstring name;
1649
1650 llassert (usymtab_isDefined (oldtab));
1651
1652 ue = usymtab_getEntryAux (oldtab, uid);
1653
1654 llassertprint (uentry_isValid (ue), ("convertId: undefined: %d", uid));
1655
1656 name = uentry_rawName (ue);
1657
1658 ret = usymtab_getIndex (utab, name);
1659 llassert (ret == uid); /*! for now, no rehash! */
1660 DPRINTF (("Convert: %s [%d] -> %s [%d]",
1661 uentry_unparse (ue), uid,
1662 uentry_unparse (utab->entries[ret]), ret));
1663
1664 llassertprint (ret != USYMIDINVALID, ("convertId: return is invalid"));
1665
1666 return (ret);
1667}
1668
1669void
1670usymtab_prepareDump (void)
1671 /*@globals oldtab, utab@*/
1672 /*@modifies oldtab, utab@*/
1673{
1674 llassert (usymtab_inGlobalScope ());
1675 llassert (oldtab == usymtab_undefined);
1676
1677 /*
1678 DPRINTF (("Preparing to dump:"));
1679 usymtab_printAll ();
1680 */
1681
1682 oldtab = usymtab_shallowCopy (utab);
1683
1684 /*
1685 ** alpha compare - make sure order is same on different platforms
1686 ** error messages appear in same order
1687 */
1688
1689 /*
1690 qsort (utab->entries, (size_t)utab->nentries,
1691 sizeof (*utab->entries),
1692 (int (*)(const void *, const void *)) uentry_xcomparealpha);
1693
1694 usymtab_rehash (utab);
1695 */
1696
1697 /*
1698 DPRINTF (("After rehash:"));
1699 usymtab_printAll ();
1700 */
1701}
1702
1703void usymtab_dump (FILE *fout)
1704 /*@globals utab, oldtab@*/
1705{
1706 int i;
1707 bool neednl = FALSE;
1708 uentry lastentry = uentry_undefined;
1709 ekind lastekind = KINVALID;
1710 int linelen = 0;
1711
1712 /*
1713 ** must call prepareDump first
1714 */
1715
1716 llassert (oldtab != usymtab_undefined);
1717
1718 for (i = 0; i < utab->nentries; i++)
1719 {
1720 uentry thisentry = utab->entries[i];
1721 ekind thisekind = uentry_getKind (thisentry);
1722
1723 if (!uentry_hasRealName (thisentry))
1724 {
1725 llassert (uentry_isGlobalMarker (thisentry));
1726
1727 if (neednl)
1728 {
1729 check (fputc ('\n', fout) == (int) '\n');
1730 }
1731
1732 fprintf (fout, "*%d (GlobalMarker)\n", KGLOBALMARKER);
1733 lastekind = KINVALID;
1734 linelen = 0;
1735 neednl = FALSE;
1736 }
1737 else
1738 {
1739 if (thisekind != lastekind)
1740 {
1741 if (neednl)
1742 {
1743 check (fputc ('\n', fout) == (int) '\n');
1744 }
1745
1746 neednl = FALSE;
1747 lastentry = uentry_undefined;
1748 fprintf (fout, "*%d (%s)\n", ekind_toInt (thisekind),
1749 cstring_toCharsSafe (ekind_capName (thisekind)));
1750 lastekind = thisekind;
1751 linelen = 0;
1752 }
1753
1754 /*
1755 ** evans - 2001-02-18 - added the - 48 fudge factor...
1756 ** extra characters dumped, but I haven't counded them carefully...
1757 */
1758
1759 if (uentry_isInvalid (lastentry) || !uentry_equiv (lastentry, thisentry)
1760 || (linelen > (MAX_DUMP_LINE_LENGTH - (2 * MAX_NAME_LENGTH) - 48)))
1761 {
1762 cstring cdump;
1763
1764 DPRINTF (("Dumping entry: %d", i));
1765 cdump = message ("^%d %q", i, uentry_dump (thisentry));
1766 /* was: cdump = uentry_dump (thisentry)); */
1767
1768 lastentry = thisentry;
1769 if (neednl)
1770 {
1771 check (fputc ('\n', fout) == (int) '\n');
1772 linelen = 0;
1773 }
1774
1775 linelen += cstring_length (cdump);
1776
1777 /* no new line here! */
1778 if (cstring_length (cdump) > 0)
1779 {
1780 check (fputs (cstring_toCharsSafe (cdump), fout) != EOF);
1781 }
1782
1783 cstring_free (cdump);
1784 neednl = TRUE;
1785 }
1786 else
1787 {
1788 cstring cdump = uentry_rawName (thisentry);
1789 DPRINTF (("Raw name: %s", cdump));
1790 linelen += (cstring_length (cdump) + 1);
1791 fprintf (fout, "#%s", cstring_toCharsSafe (cdump));
1792 }
1793 }
1794 }
1795
1796 if (neednl)
1797 {
1798 check (fputc ('\n', fout) == (int) '\n');
1799 }
1800
1801 lastekind = KINVALID;
1802
1803 fprintf(fout, ";; Library constraints\n");
1804
1805 /*drl July 27 added this so that libraries without
1806 buffer constraints would be handled correctly.
1807 I'm trying to do this without breaking older libraries.
1808
1809 Splint should still be able to handle libraries without this message.
1810 */
1811
1812
1813 fprintf(fout, "start_Buffer_Constraints\n");
1814
1815 for (i = 0; i < utab->nentries; i++)
1816 {
1817 uentry thisentry = utab->entries[i];
1818
1819 if (uentry_isFunction (thisentry) )
1820 {
1821 constraintList preconditions;
1822 constraintList postconditions;
1823
1824 preconditions = uentry_getFcnPreconditions (thisentry);
1825 postconditions = uentry_getFcnPostconditions (thisentry);
1826
1827 if ( constraintList_isDefined(preconditions) ||
1828 constraintList_isDefined(postconditions) )
1829 {
1830 fprintf(fout,"%s\n", cstring_toCharsSafe (uentry_rawName(thisentry) ) );
1831 if (constraintList_isDefined(preconditions) )
1832 {
1833 fprintf(fout,"pre:\n");
1834 constraintList_dump(preconditions, fout);
1835 fprintf (fout, ";; end precondition constraints\n" );
1836 constraintList_free(preconditions);
1837 }
1838 else
1839 {
1840 fprintf(fout,"pre:EMPTY\n");
1841 }
1842 if (constraintList_isDefined(postconditions) )
1843 {
1844 fprintf(fout,"post:\n");
1845 constraintList_dump(postconditions, fout);
1846 fprintf (fout, ";; end precondition constraints\n" );
1847 constraintList_free(postconditions);
1848 }
1849 else
1850 {
1851 fprintf(fout,"post:EMPTY\n");
1852 }
1853 }
1854
1855 }
1856 }
1857}
1858
1859
1860void usymtab_load (FILE *f)
1861 /*@globals utab, globtab@*/
1862 /*@modifies utab, *f@*/
1863{
1864 char *s = mstring_create (MAX_DUMP_LINE_LENGTH);
1865 char *os = s;
1866 ekind kind = KINVALID;
1867 fileloc loc = g_currentloc;
1868 char c;
1869 uentry ue;
1870
1871 dbgload = TRUE;
1872
1873 llassert (utab == globtab);
1874 llassert (utab->nentries == 0);
1875
1876 while (((s = reader_readLine (f, s, MAX_DUMP_LINE_LENGTH)) != NULL)
1877 && *s == ';')
1878 {
1879 /* ignore ; comments */ ;
1880 }
1881
1882 while (s != NULL && *s != ';')
1883 {
1884 int index;
1885
1886 if (*s == '*')
1887 {
1888 int ek;
1889 s++;
1890 ek = reader_getInt (&s);
1891
1892 if (ek == KGLOBALMARKER)
1893 {
1894 uentry lue = uentry_makeGlobalMarker ();
1895 DPRINTF (("Adding global marker: %s", uentry_unparseFull (lue)));
1896 usymtab_addEntryAlways (utab, lue);
1897 kind = KINVALID;
1898 goto nextiter;
1899 }
1900 else
1901 {
1902 kind = ekind_fromInt (ek);
1903 goto nextiter;
1904 }
1905 }
1906
1907 if (*s == '$')
1908 {
1909 llfatalerror
1910 (cstring_makeLiteral
1911 ("Library is in obsolete format. Use splint +whichlib "
1912 "to see which library is being loaded."));
1913 }
1914
1915 if (reader_optCheckChar (&s, '^'))
1916 {
1917 index = reader_getInt (&s);
1918 }
1919 else
1920 {
1921 index = -1;
1922 }
1923
1924 llassert (kind != KINVALID);
1925 ue = uentry_undump (kind, loc, &s);
1926
1927 llassert (utab->nentries == index || index == -1);
1928
1929 if (uentry_isValid (ue))
1930 {
1931 int lastindex = utab->nentries;
1932 ue = usymtab_addEntryAlways (utab, ue);
1933
1934
1935# if 0
1936 if (uentry_isConstant (ue)) /*@i23! isPreProcessorMacro */
1937 {
1938 cstring uname = uentry_getName (ue);
1939
1940 /* Also check its a macro... */
1941 DPRINTF (("Installing: %s", uname));
1942
1943 cpphash_installMacro
1944 (mstring_copy (cstring_toCharsSafe (uname)),
1945 cstring_length (uname),
1946 cpplib_createDefinition (message ("%s 255", uname),
1947 loc,
1948 FALSE, FALSE).defn,
1949 cpphash_hashCode (cstring_toCharsSafe (uname),
1950 cstring_length (uname),
1951 CPP_HASHSIZE));
1952
1953 DPRINTF (("After install: %s", uname));
1954 }
1955# endif
1956
1957 if (utab->nentries != lastindex + 1)
1958 {
1959 DPRINTF (("No add: %s", uentry_unparseFull (ue)));
1960 BADBRANCH;
1961 }
1962 /*@-branchstate@*/
1963 }
1964 /*@=branchstate@*/
1965
1966 /*
1967 ** now, any other names are the same uentry
1968 */
1969
1970 while (*(s++) == '#')
1971 {
1972 cstring name = cstring_fromCharsO (reader_getWord (&s));
1973 uentry nue = uentry_nameCopy (name, ue);
1974 /*
1975 DPRINTF (("Name copy: %s", uentry_unparseFull (nue)));
1976 BADBRANCH;
1977 */
1978
1979 usymtab_addEntryAlways (utab, nue);
1980 }
1981
1982 while ((c = *s) != '\0' && (c !='\n'))
1983 {
1984 if (c != ' ' || c != '\t')
1985 {
1986 llbuglit ("Junk in load file");
1987 }
1988
1989 s++;
1990 }
1991
1992 nextiter:
1993 {
1994 s = reader_readLine (f, os, MAX_DUMP_LINE_LENGTH);
1995 }
1996 }
1997
1998 /*DRL added 6/21/01
1999 to handle reading of buffer overflow related constraints
2000 */
2001 while (fgets (s, MAX_DUMP_LINE_LENGTH, f) != NULL
2002 && *s == ';')
2003 {
2004 ; /* ignore ;-comments */
2005 }
2006
2007 /*drl July 27 added this so that libraries without
2008 buffer constraints would be handled correctly.
2009 I'm trying to do this without breaking older libraries*/
2010
2011 /*check for "optional" start buffer constraints message*/
2012 if (cstring_compareLit(s, "start_Buffer_Constraints") )
2013 {
2014 fgets (s, MAX_DUMP_LINE_LENGTH, f);
2015 }
2016
2017 while (s != NULL && *s != ';')
2018 {
2019 constraintList preconditions;
2020 constraintList postconditions;
2021
2022 cstring name = cstring_fromChars(reader_getWord(&s) );
2023 cstring temp;
2024 ue = usymtab_lookup ( name );
2025
2026 cstring_free(name);
2027
2028 preconditions = constraintList_undefined;
2029 postconditions = constraintList_undefined;
2030
2031 if (!uentry_isValid(ue) )
2032 {
2033 llfatalbug ((message("Invalid uentry for %s library file may be corrupted", cstring_fromChars(s) ) ));
2034 }
2035 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2036
2037 temp = cstring_fromChars (reader_getWord(&s) );
2038
2039 if (cstring_compareLit (temp,"pre:") == 0 )
2040 {
2041 preconditions = constraintList_undump (f);
2042 }
2043 else
2044 {
2045 if (cstring_compareLit (temp,"pre:EMPTY") != 0 )
2046 llfatalbug ((message("Error reading library file pre:EMPTY expected but got %s", temp ) ));
2047 }
2048
2049 cstring_free(temp);
2050
2051 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2052
2053 temp = cstring_fromChars(reader_getWord(&s) );
2054 if (cstring_compareLit (temp, "post:") == 0 )
2055 {
2056 postconditions = constraintList_undump (f);
2057 }
2058 else
2059 {
2060 if (cstring_compareLit (temp, "post:EMPTY") != 0 )
2061 llfatalbug ((message("Error reading library file post:EMPTY expected but got %s", temp ) ));
2062 }
2063
2064 cstring_free (temp);
2065
2066 uentry_setPreconditions (ue, functionConstraint_createBufferConstraint (preconditions));
2067 uentry_setPostconditions (ue, functionConstraint_createBufferConstraint (postconditions));
2068
2069 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2070 }
2071
2072 dbgload = FALSE;
2073 sfree (os);
2074}
2075
2076/*
2077** file scope for static variables
2078*/
2079
2080void
2081usymtab_enterFile ()
2082 /*@globals utab, globtab, filetab@*/
2083 /*@modifies filetab@*/
2084{
2085 llassert (utab == globtab);
2086
2087 # if 0
2088 /* check globals */
2089
2090 usymtab_entries (globtab, ue)
2091 {
2092 if (sRef_hasDerived (uentry_getSref (ue)))
2093 {
2094 fprintf (g_warningstream, "Derived Global: %s\n", uentry_unparse (ue));
2095 fprintf (g_warningstream, "sRef: %s\n", sRef_unparseFull (ue->sref));
2096 }
2097 } end_usymtab_entries ;
2098
2099 # endif
2100
2101 usymtab_enterScope ();
2102 filetab = utab;
2103}
2104
2105void
2106usymtab_exitFile ()
2107 /*@globals utab, filetab@*/
2108 /*@modifies filetab, utab@*/
2109{
2110
2111 llassert (utab->lexlevel == 1);
2112
2113 usymtab_exitScope (exprNode_undefined);
2114 filetab = NULL;
2115}
2116
2117void
2118usymtab_enterScope ()
2119 /*@globals utab, globtab, filetab@*/
2120 /*@modifies utab@*/
2121{
2122 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
2123
2124 /* unconditional scope: optimize to avoid copy */
2125 t->aliases = aliasTable_copy (utab->aliases);
2126 utab = t;
2127
2128 llassert (usymtab_isDefined (t->env));
2129
2130 if (t->env->lexlevel == paramsScope && context_inFunctionLike ())
2131 {
2132 noshadowerror = TRUE;
2133 usymtab_handleParams ();
2134 noshadowerror = FALSE;
2135 }
2136}
2137
2138/*
2139** setup external references:
2140** o only, unique params alias external args
2141** o other params may alias anything of their type
2142*/
2143
2144static void
2145usymtab_handleParams (void)
2146 /*@globals utab, globtab, filetab@*/
2147 /*@modifies utab, globtab@*/
2148{
2149 usymtab ptab = utab->env;
2150 uentry fcn = context_getHeader ();
2151
2152 usymtab_entries (ptab, param)
2153 {
2154 uentry ue;
2155
2156 if (!uentry_isYield (param))
2157 {
2158 sRef uref;
2159 sRef pref = uentry_getSref (param);
2160
2161 /* Could be a global. */
2162
2163 if (uentry_isAnyParam (param))
2164 {
2165 ue = uentry_makeVariable (fixParamName (uentry_rawName (param)),
2166 uentry_getType (param),
2167 fileloc_copy (uentry_whereDeclared (param)),
2168 FALSE);
2169
2170 uentry_copyState (ue, param);
2171 uentry_setRefParam (ue);
2172
2173 ue = usymtab_supEntrySrefReturn (ue);
2174
2175 /* must be after supercede! */
2176
2177 if (!sRef_stateKnown (pref))
2178 {
2179 uentry_setDefState (ue, SS_DEFINED);
2180 uentry_setDefState (param, SS_DEFINED);
2181 }
2182 else
2183 {
2184 if (sRef_isStateSpecial (pref))
2185 {
2186 uentry_setDefState (ue, SS_SPECIAL); /* ALLOCATED); */
2187 /* evans 2002-01-01: should be unnecessary, the pre clauses
2188 ** set the state if necessary.
2189 */
2190 }
2191 else
2192 {
2193 uentry_setDefState (ue, sRef_getDefState (pref));
2194 }
2195 }
2196
2197 uref = uentry_getSref (ue);
2198
2199 if (sRef_isStack (uref))
2200 {
2201 alkind pkind = sRef_getAliasKind (pref);
2202
2203 if (alkind_isKnown (pkind) && !alkind_isLocal (pkind)
2204 && !alkind_isStack (pkind))
2205 {
2206 sRef_setAliasKind (uref, pkind, fileloc_undefined);
2207 sRef_setOrigAliasKind (uref, pkind);
2208 }
2209 else
2210 {
2211 sRef_setAliasKind (uref, AK_IMPTEMP, fileloc_undefined);
2212 sRef_setOrigAliasKind (uref, AK_IMPTEMP);
2213
2214 if (uentry_isOut (param))
2215 {
2216 ;
2217 }
2218 else
2219 {
2220 sRef_setDefined (uref, fileloc_undefined);
2221 }
2222 }
2223
2224 }
2225
2226 usymtab_addMustAlias (uref, pref);
2227
2228 if (!(uentry_isOnly (param) || uentry_isUnique (param)))
2229 {
2230 /*
2231 ** This is needed for detecting possibly aliased parameters.
2232 */
2233
2234 sRef s = sRef_makeExternal (uref);
2235 usymtab_addMustAlias (uref, s);
2236 }
2237
2238 if (sRef_isKillRef (pref))
2239 {
2240 sRef_setAliasKind (uref, AK_NEWREF, fileloc_undefined);
2241 sRef_setOrigAliasKind (uref, AK_KILLREF);
2242 }
2243 else if (sRef_isRefCounted (uref))
2244 {
2245 sRef_setOrigAliasKind (uref, AK_REFCOUNTED);
2246 }
2247 else
2248 {
2249 /* was AK_UNIQUE */
2250 sRef_setOrigAliasKind (uref, AK_LOCAL);
2251 }
2252 }
2253 else
2254 {
2255 }
2256 }
2257 } end_usymtab_entries;
2258
2259
2260 if (uentry_hasStateClauseList (fcn))
2261 {
2262 stateClauseList clauses = uentry_getStateClauseList (fcn);
2263
2264 stateClauseList_preElements (clauses, cl)
2265 {
2266 fileloc loc = stateClause_loc (cl);
2267 sRefSet osrs = sRefSet_undefined;
2268 sRefSet srs;
2269
2270 if (stateClause_isGlobal (cl))
2271 {
2272 DPRINTF (("Global Marker: %s",
2273 sRef_unparseFull (usymtab_lookupGlobalMarker ())));
2274 llassert (sRef_isGlobalMarker (usymtab_lookupGlobalMarker ()));
2275 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
2276 osrs = srs;
2277 }
2278 else
2279 {
2280 srs = stateClause_getRefs (cl);
2281 }
2282
2283 sRefSet_elements (srs, el)
2284 {
2285 sRef base = sRef_getRootBase (el);
2286 sRef sb = sRef_updateSref (el);
2287
2288 if (sRef_isResult (base))
2289 {
2290 ; /* nothing to do before */
2291 }
2292 else if (sRef_isParam (base) || sRef_isGlobalMarker (base))
2293 {
2294 if (stateClause_setsMetaState (cl))
2295 {
2296 /* copied from exprNode.c:3040 */
2297 qual ql = stateClause_getMetaQual (cl);
2298 annotationInfo ainfo = qual_getAnnotationInfo (ql);
2299 metaStateInfo minfo = annotationInfo_getState (ainfo);
2300 cstring key = metaStateInfo_getName (minfo);
2301 int mvalue = annotationInfo_getValue (ainfo);
2302
2303 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
2304
2305 if (sRef_isResult (base))
2306 {
2307 BADBRANCH;
2308 }
2309 else
2310 {
2311 sRef_setMetaStateValueComplete (sb, key, mvalue, loc);
2312 }
2313 }
2314 else
2315 {
2316 sRefMod modf = stateClause_getEntryFunction (cl);
2317
2318 if (modf != NULL)
2319 {
2320 sRefSet aliases = usymtab_allAliases (sb);
2321
2322 modf (sb, loc);
2323
2324 sRefSet_elements (aliases, sr)
2325 {
2326 modf (sr, loc);
2327 } end_sRefSet_elements ;
2328
2329 sRefSet_free (aliases);
2330 }
2331 }
2332 }
2333 else
2334 {
2335 if (sRef_isValid (base))
2336 {
2337 DPRINTF (("Base: %s", sRef_unparseFull (base)));
2338 BADBRANCH;
2339 }
2340 }
2341 } end_sRefSet_elements ;
2342 } end_stateClauseList_preElements ;
2343 }
2344}
2345
2346void
2347usymtab_enterFunctionScope (uentry fcn)
2348 /*@globals utab, filetab, globtab@*/
2349 /*@modifies utab@*/
2350{
2351 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
2352
2353 DPRINTF (("Enter function: %s", uentry_unparse (fcn)));
2354
2355 if (utab->lexlevel != fileScope)
2356 {
2357 if (utab->lexlevel > fileScope)
2358 {
2359 llparseerror (cstring_makeLiteral ("New function scope inside function"));
2360
2361 while (utab->lexlevel > fileScope)
2362 {
2363 /*@i@*/ utab = usymtab_dropEnv (utab);
2364 /*@-branchstate@*/
2365 }
2366 /*@=branchstate@*/
2367 }
2368 else
2369 {
2370 llfatalbug (cstring_makeLiteral ("New function not inside file."));
2371 }
2372 /*@-branchstate@*/ } /*@=branchstate@*/
2373
2374 utab = t;
2375
2376 DPRINTF (("Globs: %s", globSet_unparse (uentry_getGlobs (fcn))));
2377
2378 globSet_allElements (uentry_getGlobs (fcn), el)
2379 {
2380 DPRINTF (("Here we go: %s", sRef_unparseFull (el)));
2381
2382 if (sRef_isUndefGlob (el))
2383 {
2384 int index = sRef_getScopeIndex (el);
2385 sRef sr = sRef_updateSref (el);
2386 fileloc loc = uentry_whereEarliest (fcn);
2387
2388 DPRINTF (("update: %s", sRef_unparseFull (sr)));
2389 DPRINTF (("Undef!"));
2390 if (sRef_isFileStatic (el))
2391 {
2392 ctype ct = sRef_getType (el);
2393 uentry ue;
2394
2395 llassert (usymtab_isDefined (filetab));
2396
2397 ue = usymtab_fetchIndex (filetab, index);
2398
2399 if (ctype_isRealArray (ct) || ctype_isRealSU (ct))
2400 {
2401 sRef_setAllocated (sr, loc);
2402 }
2403 else
2404 {
2405 sRef_setUndefined (sr, loc);
2406 }
2407 }
2408 else
2409 {
2410 uentry ue = globtab->entries[index];
2411 ctype ct = uentry_getType (ue);
2412
2413 if (ctype_isArray (ct) || ctype_isSU (ct))
2414 {
2415 sRef_setAllocated (sr, loc);
2416 }
2417 else
2418 {
2419 sRef_setUndefined (sr, loc);
2420 }
2421 }
2422 }
2423 else if (sRef_isAllocated (el))
2424 {
2425 sRef sr = sRef_updateSref (el);
2426 fileloc loc = uentry_whereEarliest (fcn);
2427
2428 sRef_setAllocated (sr, loc);
2429 }
2430 else if (sRef_isPartial (el))
2431 {
2432 sRef sr = sRef_updateSref (el);
2433 fileloc loc = uentry_whereEarliest (fcn);
2434
2435 sRef_setPartial (sr, loc);
2436 }
2437 else
2438 {
2439 /*
2440 sRef sr = sRef_updateSref (el);
2441 fileloc loc = uentry_whereEarliest (fcn);
2442
2443 sRef_setDefined (sr, loc);
2444 */
2445
2446 /* defined */
2447 /* shouldn't need to do anything! */
2448 }
2449 } end_globSet_allElements;
2450
2451 DPRINTF (("Globs after: %s", globSet_unparse (uentry_getGlobs (fcn))));
2452# ifdef DEBUGSPLINT
2453 usymtab_checkAllValid ();
2454# endif
2455}
2456
2457static void
2458usymtab_caseBranch (void)
2459 /*@modifies utab@*/
2460{
2461 usymtab t = usymtab_create (US_CBRANCH, utab, FALSE);
2462 utab = t;
2463}
2464
2465void
2466usymtab_switchBranch (/*@unused@*/ exprNode s)
2467 /*@modifies utab@*/
2468{
2469 usymtab t = usymtab_create (US_SWITCH, utab, FALSE);
2470
2471 t->aliases = aliasTable_copy (utab->aliases);
2472 utab = t;
2473}
2474
2475void
2476usymtab_trueBranch (/*@only@*/ guardSet guards)
2477 /*@modifies utab@*/
2478{
2479 usymtab t = usymtab_create (US_TBRANCH, utab, FALSE);
2480
2481 /*
2482 ** not true! (could be in a macro)
2483 **
2484 ** llassertprint (utab->lexlevel > paramsScope,
2485 ** ("not in scope: %s", usymtab_unparseLocal ()));
2486 **
2487 */
2488
2489 guardSet_free (t->guards);
2490 t->guards = guards;
2491
2492 aliasTable_free (t->aliases);
2493 t->aliases = aliasTable_copy (utab->aliases);
2494
2495 utab = t;
2496}
2497
2498/*
2499** consider,
2500**
2501** { int a; if (...) a = 3; < a may be undefined here!
2502**
2503*/
2504
2505void
2506usymtab_popTrueBranch (exprNode pred, exprNode expr, clause cl) /*@modifies utab@*/
2507{
2508 /*
2509 ** add a false branch
2510 ** (could be done more efficiently as a special case, but
2511 ** it is better to only maintain one version of the code)
2512 */
2513
2514 if (utab->kind != US_TBRANCH
2515 && context_inIterDef ())
2516 {
2517 usymtab_exitScope (expr);
2518 }
2519 else
2520 {
2521 DPRINTF (("pop true branch.."));
2522 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2523 usymtab_popBranches (pred, expr, exprNode_undefined, TRUE, cl);
2524 }
2525}
2526
2527void
2528usymtab_popCaseBranch () /*@modifies utab@*/
2529{
2530 llassert (utab->kind == US_CBRANCH);
2531 usymtab_quietPlainExitScope ();
2532}
2533
2534void
2535usymtab_popTrueExecBranch (exprNode pred, exprNode expr, clause cl)
2536{
2537 /*
2538 ** add a false branch that must return --- that is,
2539 ** the true branch is always executed!
2540 */
2541
2542 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2543 usymtab_popBranches (pred, expr, exprNode_makeMustExit (), FALSE, cl);
2544}
2545
2546void
2547usymtab_popOrBranch (exprNode pred, exprNode expr)
2548 /*@modifies utab@*/
2549{
2550 bool mustReturn;
2551 usymtab env = utab->env;
2552 usymtab otab = utab;
2553 int i = 0;
2554
2555 llassert (env != NULL);
2556
2557 if (exprNode_isError (expr))
2558 {
2559 mustReturn = FALSE;
2560 }
2561 else
2562 {
2563 mustReturn = exprNode_mustEscape (expr);
2564 }
2565
2566
2567 llassert (utab->kind == US_TBRANCH);
2568
2569 /*
2570 ** merge each entry in table with its original
2571 ** unless execution cannot continue after this branch
2572 */
2573
2574 for (i = 0; i < utab->nentries; i++)
2575 {
2576 uentry current = utab->entries[i];
2577 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2578
2579 uentry_mergeState (old, current, exprNode_loc (expr),
2580 mustReturn, FALSE, TRUE, ORCLAUSE);
2581 }
2582
2583
2584 if (mustReturn)
2585 {
2586 env->guards = guardSet_levelUnionFree (env->guards,
2587 guardSet_invert (exprNode_getGuards (pred)),
2588 env->lexlevel);
2589 }
2590 else
2591 {
2592 env->aliases = aliasTable_levelUnion (env->aliases, otab->aliases, env->lexlevel);
2593 }
2594
2595 /* env is now utab */
2596 usymtab_quietPlainExitScope ();
2597}
2598
2599/*
2600** case syntax in C is very unrestricted. This is unfortunate.
2601**
2602** A switch case is ended either by a new case or default, or
2603** a close } that may close the switch or some other control
2604** structure.
2605*/
2606
2607bool
2608usymtab_newCase (/*@unused@*/ exprNode pred, exprNode last)
2609 /*@modifies utab@*/
2610{
2611 bool mustBreak = usymtab_mustBreak (utab);
2612 bool mustReturn = usymtab_mustEscape (utab);
2613 usymtab stab = utab;
2614
2615 DPRINTF (("New case!"));
2616
2617 /*
2618 ** Find last case (or outer switch)
2619 */
2620
2621 while (stab->kind != US_CBRANCH && stab->kind != US_SWITCH)
2622 {
2623 stab = stab->env;
2624 llassert (stab != GLOBAL_ENV);
2625 }
2626
2627 while (stab->kind == US_CBRANCH)
2628 {
2629 stab = stab->env;
2630 llassert (stab != GLOBAL_ENV);
2631 }
2632
2633 /*
2634 ** if its a fall through case, merge in outside entries and last case.
2635 **
2636 ** e.g.,
2637 ** ...
2638 ** switch
2639 ** case 1: x = 3; <fall through>
2640 ** case 2: << x may not be defined
2641 **
2642 */
2643
2644 if (!mustBreak && !mustReturn && utab->kind == US_CBRANCH)
2645 {
2646 llassert (stab->kind == US_SWITCH || stab->kind == US_NORMAL);
2647
2648 usymtab_entries (utab, ue) /* but, keep track of used variables */
2649 {
2650 uentry old = usymtab_lookupAux (stab, uentry_rawName (ue));
2651
2652 llassert (uentry_isValid (old));
2653
2654 /* modifies ue, not old */
2655
2656 uentry_mergeState (ue, old, exprNode_loc (last),
2657 FALSE, FALSE, TRUE, CASECLAUSE);
2658 } end_usymtab_entries;
2659
2660 utab->aliases = aliasTable_levelUnion (utab->aliases,
2661 stab->aliases, utab->lexlevel);
2662
2663 /*
2664 ** No need for a new branch.
2665 */
2666
2667 return FALSE;
2668 }
2669 else
2670 {
2671 usymtab_caseBranch ();
2672 /*@-mustfree@*/ /*< utab->aliases >*/
2673 utab->aliases = aliasTable_copy (stab->aliases);
2674 /*@=mustfree@*/
2675
2676 return TRUE;
2677 }
2678}
2679
2680/*
2681** for && (both pred and expr are executed)
2682*/
2683
2684void
2685usymtab_popAndBranch (exprNode pred, /*@unused@*/ exprNode expr)
2686 /*@modifies utab@*/
2687{
2688 usymtab env = utab->env;
2689 usymtab otab= utab;
2690 int i = 0;
2691
2692 llassert (utab->kind == US_TBRANCH);
2693
2694 /*
2695 ** merge each entry in table with its original
2696 ** unless execution cannot continue after this branch
2697 */
2698
2699 for (i = 0; i < utab->nentries; i++)
2700 {
2701 uentry current = utab->entries[i];
2702 sRef tref = uentry_getSref (current);
2703 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2704 sRef oref = uentry_getSref (old);
2705
2706 /* note that is current is in a nested branch,
2707 it may create a "new" old entry. */
2708
2709 llassert (uentry_isValid (old));
2710 uentry_mergeState (old, current, exprNode_loc (expr),
2711 FALSE, FALSE, TRUE, ANDCLAUSE);
2712
2713 /*
2714 ** if is it defined by the second clause, then it should be defined.
2715 */
2716
2717 if (sRef_isAnyDefined (tref)
2718 && (sRef_isAllocated (oref) || sRef_isStateUndefined (oref)))
2719 {
2720 sRef_setDefined (oref, g_currentloc);
2721 }
2722 }
2723
2724 utab->guards = guardSet_levelUnionFree (utab->guards,
2725 guardSet_invert (exprNode_getGuards (pred)),
2726 utab->lexlevel);
2727 utab->aliases = aliasTable_levelUnion (utab->aliases, otab->aliases, utab->lexlevel);
2728
2729 usymtab_quietPlainExitScope ();
2730
2731 }
2732
2733/*
2734** Stack should be [ US_CBRANCH+ US_SWITCH ]
2735** Only branches which do not return (except possibly the last branch) are included.
2736**
2737** Conditionally merge state from all CBRANCHes.
2738**
2739** If allpaths is TRUE, then all possible executions go through some switch
2740** case, and the original scope is not merged.
2741*/
2742
2743void
2744usymtab_exitSwitch (/*@unused@*/ exprNode sw, bool allpaths)
2745 /*@modifies utab@*/
2746{
2747 usymtab ttab = utab;
2748 usymtab stab = ttab;
2749 usymtab ltab = ttab;
2750 bool lastMustReturn = usymtab_mustEscape (utab);
2751 int i;
2752
2753
2754 while (stab->kind == US_CBRANCH)
2755 {
2756 stab = stab->env;
2757 llassert (stab != GLOBAL_ENV);
2758 }
2759
2760 while (stab->kind == US_NORMAL)
2761 {
2762 stab = stab->env;
2763 llassert (stab != GLOBAL_ENV);
2764 }
2765
2766 llassert (stab->kind == US_SWITCH);
2767
2768 /* go to the scope outside the switch (US_SWITCH is just a marker! */
2769 stab = stab->env;
2770 llassert (stab != GLOBAL_ENV);
2771
2772
2773 ttab = ttab->env;
2774 llassert (usymtab_isDefined (ttab));
2775
2776 if (ttab->kind == US_CBRANCH)
2777 {
2778 /* was quietPlainExitScope --- but, can't free it yet! */
2779 utab = utab->env;
2780 llassert (utab != GLOBAL_ENV);
2781
2782 while (ttab->kind == US_CBRANCH)
2783 {
2784 /*
2785 ** (from popTrueBranch)
2786 */
2787
2788 bool mustReturn = usymtab_mustEscape (ttab);
2789 bool mustBreak = usymtab_mustBreak (ttab);
2790
2791 usymtab_entries (ttab, current)
2792 {
2793 uentry old = /*@-compmempass@*/ usymtab_lookupAux (ltab, uentry_rawName (current));
2794 /*@=compmempass@*/
2795
2796 /*
2797 ** note that is this is in a nested branch,
2798 ** it may create a "new" old entry.
2799 */
2800
2801 if (uentry_isValid (old))
2802 {
2803 if (lastMustReturn)
2804 {
2805 uentry_mergeUses (current, old);
2806 uentry_setState (old, current);
2807 }
2808 else
2809 {
2810 uentry_mergeState (old, current, exprNode_loc (sw),
2811 mustReturn, FALSE, TRUE, SWITCHCLAUSE);
2812 }
2813 }
2814 else
2815 {
2816 ;
2817 }
2818 } end_usymtab_entries;
2819
2820 /*
2821 ** if entry is not in symbol table for this case, merge with pre-switch
2822 ** table
2823 */
2824
2825 if (!mustReturn && !mustBreak)
2826 {
2827 usymtab_entries (stab, current)
2828 {
2829 if (usymtab_getIndex (ttab, uentry_rawName (current)) == NOT_FOUND)
2830 {
2831 uentry old = /*@-compmempass@*/
2832 usymtab_lookupAux (ltab, uentry_rawName (current));
2833 /*@=compmempass@*/
2834
2835 llassert (uentry_isValid (old));
2836 uentry_mergeState (old, current, exprNode_loc (sw),
2837 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2838 }
2839 } end_usymtab_entries;
2840 }
2841
2842 ltab->env = ttab->env;
2843 ttab = ltab->env;
2844
2845 /*
2846 ** Suprious error, becuase of environments.
2847 */
2848
2849 /*@i1@*/ utab = ltab;
2850
2851 lastMustReturn = FALSE;
2852 /*@-branchstate@*/
2853 }
2854 }
2855 /*@=branchstate@*/
2856
2857 /*
2858 ** now, there is one US_CBRANCH. Merge this with the stab.
2859 */
2860
2861
2862 for (i = 0; i < ltab->nentries; i++)
2863 {
2864 uentry current = ltab->entries[i];
2865 uentry old = usymtab_lookupAux (stab, uentry_rawName (current));
2866
2867 /* note that is this is in a nested branch,
2868 it may create a "new" old entry. */
2869
2870
2871 if (uentry_isValid (old))
2872 {
2873 if (allpaths)
2874 {
2875 uentry_mergeUses (current, old);
2876 uentry_setState (old, current);
2877 }
2878 else
2879 {
2880 uentry_mergeState (old, current, exprNode_loc (sw),
2881 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2882 }
2883 }
2884 else
2885 {
2886 }
2887 }
2888
2889 /*
2890 ** exit the switch
2891 */
2892
2893
2894 /*
2895 ** switch may or may not be followed by a new scope
2896 */
2897
2898 if (utab->kind == US_SWITCH)
2899 {
2900 usymtab_quietPlainExitScope ();
2901 }
2902 else
2903 {
2904 usymtab_quietPlainExitScope ();
2905 llassert (utab->kind == US_SWITCH);
2906 usymtab_quietPlainExitScope ();
2907 }
2908
2909 }
2910
2911static void
2912updateNullState (sRef el, /*@notnull@*/ usymtab ttab,
2913 /*@notnull@*/ usymtab ftab, bool trueGuard)
2914{
2915 sRef base = sRef_getRootBase (el);
2916 int level = sRef_lexLevel (base);
2917
2918 if (sRef_isCvar (base))
2919 {
2920 usymId index = sRef_getScopeIndex (base);
2921 uentry ue = usymtab_getRefTab (ttab, level, index);
2922
2923 if (!uentry_isLset (ue))
2924 {
2925 sRef sr = uentry_getSref (ue);
2926
2927 if (trueGuard)
2928 {
2929 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2930 }
2931 else
2932 {
2933 if (!guardSet_isGuarded (ttab->guards, el)
2934 && !sRef_isNotNull (sr))
2935 {
2936 DPRINTF (("Here! %s / %s",
2937 sRef_unparseFull (sr),
2938 sRef_unparseFull (el)));
2939 sRef_setDerivNullState (sr, el, NS_DEFNULL);
2940 }
2941 }
2942 }
2943 else
2944 {
2945 ;
2946 }
2947
2948 ue = usymtab_getRefTab (ftab, level, index);
2949
2950 if (!uentry_isLset (ue))
2951 {
2952 sRef sr = uentry_getSref (ue);
2953
2954 if (!trueGuard) /* yikes! forgot the ! */
2955 {
2956 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2957 }
2958 else
2959 {
2960
2961 if (!guardSet_isGuarded (ftab->guards, el)
2962 && !sRef_isNotNull (sr))
2963 {
2964 sRef_setDerivNullState (sr, el, NS_DEFNULL);
2965 }
2966 }
2967 }
2968 else
2969 {
2970 ;
2971 }
2972 }
2973}
2974
2975void
2976usymtab_popBranches (exprNode pred, exprNode tbranch, exprNode fbranch,
2977 bool isOpt, clause cl)
2978 /*@modifies utab@*/
2979{
2980 int i = 0;
2981 usymtab ftab = utab;
2982 usymtab ttab = utab->env;
2983
2984 fileloc loc;
2985 usymtab env;
2986 guardSet guards = exprNode_getGuards (pred);
2987 sRefSet tguards = guardSet_getTrueGuards (guards);
2988 sRefSet fguards = guardSet_getFalseGuards (guards);
2989 bool mustReturnT = exprNode_mustEscape (tbranch);
2990 bool mustReturnF = exprNode_mustEscape (fbranch);
2991
2992 DPRINTF (("Pop branches: %s [mustreturn: %s/%s]", exprNode_unparse (pred),
2993 bool_unparse (mustReturnT),
2994 bool_unparse (mustReturnF)));
2995
2996 if (exprNode_isDefined (fbranch))
2997 {
2998 loc = exprNode_loc (fbranch);
2999 }
3000 else
3001 {
3002 loc = exprNode_loc (tbranch);
3003 }
3004
3005 llassert (usymtab_isDefined (ttab));
3006
3007 env = ttab->env;
3008
3009 llassert (usymtab_isDefined (env));
3010 llassert (ftab->kind == US_FBRANCH);
3011 llassert (ttab->kind == US_TBRANCH);
3012
3013 /*
3014 ** For each element that is true guarded (i.e., if (x != NULL))
3015 ** make x = null in false branch,
3016 ** and x = notnull in true branch.
3017 ** unless x was set locally in that branch.
3018 ** For each element that is false guarded (x == NULL)
3019 ** make x = null in true, notnull in false.
3020 **
3021 ** For each element that is either guarded (pred(x))
3022 **
3023 */
3024
3025 sRefSet_allElements (tguards, el)
3026 {
3027 updateNullState (el, ttab, ftab, TRUE);
3028 } end_sRefSet_allElements;
3029
3030 sRefSet_allElements (fguards, el)
3031 {
3032 updateNullState (el, ttab, ftab, FALSE);
3033 } end_sRefSet_allElements;
3034
3035 /*
3036 **
3037 ** if an entry is in both true and false, merge the entries,
3038 ** then replace original with new state.
3039 **
3040 ** if an entry is in one table, merge it with the original.
3041 */
3042
3043 DPRINTF (("ftab: %d", ftab->nentries));
3044
3045 for (i = 0; i < ftab->nentries; i++)
3046 {
3047 uentry fthis = ftab->entries[i];
3048 uentry old = usymtab_lookupAux (env, uentry_rawName (fthis));
3049 int tindex = usymtab_getIndex (ttab, uentry_rawName (fthis));
3050
3051 DPRINTF (("Entry: %s / %s", uentry_unparseFull (fthis), uentry_unparseFull (old)));
3052
3053 if (uentry_isUndefined (old))
3054 {
3055 /* possible entry was added as an undefined id */
3056 DPRINTF (("Undefined! %s", uentry_rawName (fthis)));
3057 continue;
3058 }
3059
3060 if (tindex != NOT_FOUND)
3061 {
3062 uentry tthis = ttab->entries[tindex];
3063
3064 /* note that is this is in a nested branch,
3065 it may create a "new" old entry. */
3066
3067 if (!mustReturnF)
3068 {
3069 if (!mustReturnT)
3070 {
3071 uentry_mergeState (fthis, tthis, loc,
3072 mustReturnT, FALSE, FALSE, cl);
3073 }
3074 else
3075 {
3076 uentry_mergeUses (fthis, tthis);
3077 }
3078
3079 uentry_setState (old, fthis);
3080
3081 /*@-mustfree@*/
3082 }
3083 /*@=mustfree@*/
3084 else
3085 {
3086 uentry_setState (old, tthis);
3087 uentry_mergeState (old, fthis, loc, mustReturnF,
3088 TRUE, FALSE, cl);
3089 }
3090
3091 ttab->entries[tindex] = uentry_undefined;
3092 uentry_free (tthis);
3093 }
3094 else
3095 {
3096 uentry_mergeState (old, fthis, loc, mustReturnF, TRUE, FALSE, cl);
3097 }
3098 }
3099
3100 for (i = 0; i < ttab->nentries; i++)
3101 {
3102 uentry current = ttab->entries[i];
3103
3104 DPRINTF (("ttab: %s", uentry_unparseFull (current)));
3105
3106 if (!uentry_isUndefined (current))
3107 {
3108 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
3109
3110 DPRINTF (("Old: %s", uentry_unparseFull (old)));
3111
3112 if (uentry_isUndefined (old))
3113 {
3114 llcontbug (message ("Undefined entry: %s", uentry_rawName (current)));
3115 continue;
3116 }
3117
3118 if (mustReturnF)
3119 {
3120 uentry_mergeUses (current, old);
3121 uentry_setState (old, current);
3122 }
3123 else
3124 {
3125 /*
3126 ** Assumes false branch is a fall-through if
3127 ** fbranch is not defined. This is true, unless
3128 ** where was some greivous error in processing
3129 ** the else branch of an if-then, in which case
3130 ** this is probably the right thing to do anyway.
3131 */
3132
3133 uentry_mergeState (old, current, loc, mustReturnT,
3134 FALSE, isOpt, cl);
3135 }
3136
3137 DPRINTF (("==> %s", uentry_unparseFull (old)));
3138 }
3139 }
3140
3141 /*
3142 ** Plain levelUnion doesn't work, since we need to use the sRef's in env->aliases
3143 ** if they are present.
3144 */
3145
3146 llassert (NOALIAS (env->aliases, ttab->aliases));
3147 llassert (NOALIAS (env->aliases, ftab->aliases));
3148
3149 aliasTable_free (env->aliases);
3150
3151 env->aliases = aliasTable_levelUnionNew (ttab->aliases,
3152 ftab->aliases, env->lexlevel);
3153
3154 aliasTable_fixSrefs (env->aliases);
3155
3156 DPRINTF (("Aliases: %s", aliasTable_unparse (env->aliases)));
3157
3158 /* exit true and false scopes */
3159 usymtab_quietPlainExitScope ();
3160 usymtab_quietPlainExitScope ();
3161
3162 if (mustReturnT)
3163 {
3164 utab->guards = guardSet_levelUnionFree
3165 (utab->guards,
3166 guardSet_invert (exprNode_getGuards (pred)),
3167 utab->lexlevel);
3168 }
3169
3170 if (mustReturnF)
3171 {
3172 utab->guards = guardSet_levelUnion (utab->guards,
3173 exprNode_getGuards (pred),
3174 utab->lexlevel);
3175 }
3176
3177 DPRINTF (("Here."));
3178}
3179
3180static void usymtab_fixCases (void) /*@modifies utab@*/ {
3181 while (utab->kind == US_CBRANCH)
3182 {
3183 usymtab_quietPlainExitScope ();
3184 }
3185
3186 llassert (utab->kind != US_CBRANCH);
3187}
3188
3189void
3190usymtab_altBranch (/*@only@*/ guardSet guards)
3191 /*@modifies utab@*/
3192{
3193 usymtab t;
3194 usymtab parent = utab->env;
3195
3196 t = usymtab_create (US_FBRANCH, utab, FALSE);
3197
3198 /*
3199 ** If we are in a case, need to close it. The C syntax
3200 ** is very liberal, so this kludge is necessary.
3201 */
3202
3203 usymtab_fixCases ();
3204
3205 DPRINTF (("Current kind: %s", usymtab_unparseStack ()));
3206
3207 llassert (utab->kind == US_TBRANCH);
3208 llassert (parent != GLOBAL_ENV);
3209
3210 guardSet_free (t->guards);
3211 t->guards = guards;
3212
3213 aliasTable_free (t->aliases);
3214 t->aliases = aliasTable_copy (parent->aliases);
3215
3216 utab = t;
3217}
3218
3219void
3220usymtab_allDefined (void)
3221 /*@globals utab, globtab@*/
3222{
3223 int i;
3224
3225 llassert (utab == globtab);
3226
3227 for (i = 0; i < utab->nentries; i++)
3228 {
3229 uentry e = utab->entries[i];
3230
3231 if (uentry_isPriv (e))
3232 {
3233 ; /* no need to define it */
3234 }
3235 else
3236 {
3237 if (context_getFlag (FLG_SPECUNDECL))
3238 {
3239 fileloc sloc = uentry_whereSpecified (e);
3240 fileloc dloc = uentry_whereDeclared (e);
3241
3242 if (fileloc_isDefined (sloc)
3243 && !uentry_isFakeTag (e)
3244 && !fileloc_isDefined (dloc))
3245 {
3246 voptgenerror
3247 (FLG_SPECUNDECL,
3248 message ("%s %q specified but not declared",
3249 ekind_capName (uentry_getKind (e)),
3250 uentry_getName (e)),
3251 sloc);
3252 }
3253 }
3254
3255 if (!uentry_isCodeDefined (e))
3256 {
3257 fileloc dloc = uentry_whereDeclared (e);
3258
3259 if (fileloc_isLib (dloc) || fileloc_isXHFile (dloc))
3260 {
3261 ;
3262 }
3263 else if (fileloc_isDefined (dloc))
3264 {
3265 if (!uentry_isAnyTag (e))
3266 {
3267 if (fileloc_isUser (dloc))
3268 {
3269 voptgenerror
3270 (FLG_DECLUNDEF,
3271 message ("%s %q declared but not defined",
3272 ekind_capName (uentry_getKind (e)),
3273 uentry_getName (e)),
3274 dloc);
3275 DPRINTF (("decl: %s", uentry_unparseFull (e)));
3276 }
3277 }
3278 }
3279 else
3280 {
3281 fileloc sloc = uentry_whereSpecified (e);
3282
3283 if (fileloc_isDefined (sloc)
3284 && !fileloc_isImport (sloc)
3285 && !fileloc_isLib (sloc)
3286 && !fileloc_isPreproc (sloc)
3287 && !uentry_isFakeTag (e))
3288 {
3289 if (uentry_isVariable (e) || uentry_isFunction (e))
3290 {
3291 voptgenerror
3292 (FLG_SPECUNDEF,
3293 message ("%s %q specified but not declared or defined",
3294 ekind_capName (uentry_getKind (e)),
3295 uentry_getName (e)),
3296 sloc);
3297 }
3298 else
3299 {
3300 voptgenerror
3301 (FLG_SPECUNDEF,
3302 message ("%s %q specified but not defined",
3303 ekind_capName (uentry_getKind (e)),
3304 uentry_getName (e)),
3305 sloc);
3306 }
3307 }
3308 }
3309 }
3310 }
3311 }
3312}
3313
3314void usymtab_exportHeader (void)
3315 /*@globals utab@*/
3316{
3317 int i;
3318
3319 for (i = 0; i < utab->nentries; i++)
3320 {
3321 uentry ce = utab->entries[i];
3322
3323 if (!uentry_isDatatype (ce)
3324 && !uentry_isAnyTag (ce)
3325 && !uentry_isEitherConstant (ce) && !uentry_isStatic (ce)
3326 && !uentry_isExternal (ce)
3327 && !uentry_isForward (ce))
3328 {
3329 fileloc fwhere = uentry_whereDeclared (ce);
3330
3331 if (fileloc_isUndefined (fwhere)
3332 && uentry_isFunction (ce))
3333 {
3334 fwhere = uentry_whereDefined (ce);
3335 }
3336
3337 if (fileloc_isDefined (fwhere)
3338 && !fileloc_isHeader (fwhere)
3339 && !fileloc_isXHFile (fwhere)
3340 && !(fileloc_isSpecialFile (fwhere)
3341 && !context_getFlag (FLG_UNUSEDSPECIAL)))
3342 {
3343 if (uentry_isVariable (ce))
3344 {
3345 if (optgenerror
3346 (FLG_EXPORTHEADERVAR,
3347 message ("%s %q exported but not declared in header file",
3348 ekind_capName (uentry_getKind (ce)),
3349 uentry_getName (ce)),
3350 fwhere))
3351 {
3352 uentry_showDefSpecInfo (ce, fwhere);
3353 }
3354 }
3355 else
3356 {
3357 if (!uentry_isIter (ce)
3358 && !uentry_isEndIter (ce)
3359 && !uentry_isExpandedMacro (ce))
3360 {
3361 if (uentry_isFunction (ce)
3362 && cstring_equalLit (uentry_rawName (ce), "main"))
3363 {
3364 ; /* no error for main */
3365 }
3366 else
3367 {
3368 if (optgenerror
3369 (FLG_EXPORTHEADER,
3370 message ("%s %q exported but not declared "
3371 "in header file",
3372 ekind_capName (uentry_getKind (ce)),
3373 uentry_getName (ce)),
3374 fwhere))
3375 {
3376 uentry_showDefSpecInfo (ce, fwhere);
3377 }
3378 }
3379 }
3380 }
3381 }
3382 }
3383 }
3384}
3385
3386void usymtab_exportLocal (void)
3387 /*@globals utab@*/
3388{
3389 int i;
3390
3391 for (i = 0; i < utab->nentries; i++)
3392 {
3393 uentry ce = utab->entries[i];
3394
3395 if (!uentry_isDatatype (ce) && !uentry_isAnyTag (ce)
3396 && !uentry_isEitherConstant (ce)
3397 && !uentry_isIter (ce)
3398 && !uentry_isEndIter (ce)
3399 && !uentry_isExpandedMacro (ce)
3400 && uentry_isUsed (ce))
3401 {
3402 /* check static uses */
3403 filelocList fuses = uentry_getUses (ce);
3404 fileloc mod = uentry_whereDefined (ce);
3405 bool ok = filelocList_isEmpty (fuses);
3406 fileloc fwhere = uentry_whereDeclared (ce);
3407
3408 if (fileloc_isSpecialFile (fwhere)
3409 && !context_getFlag (FLG_UNUSEDSPECIAL))
3410 {
3411 ok = TRUE; /* no errors for special files */
3412 }
3413 else
3414 {
3415 filelocList_elements (fuses, uloc)
3416 {
3417 if (fileloc_isUndefined (uloc) || !fileloc_sameModule (uloc, mod))
3418 {
3419 ok = TRUE;
3420 /*@innerbreak@*/ break;
3421 }
3422 } end_filelocList_elements;
3423 }
3424
3425 if (!ok)
3426 {
3427 if (optgenerror
3428 (FLG_EXPORTLOCAL,
3429 message ("%s exported but not used outside %s: %q",
3430 ekind_capName (uentry_getKind (ce)),
3431 fileloc_getBase (mod),
3432 uentry_getName (ce)),
3433 fwhere))
3434 {
3435 uentry_showDefSpecInfo (ce, fwhere);
3436 }
3437 }
3438 }
3439 }
3440}
3441
3442void
3443usymtab_allUsed (void)
3444 /*@globals utab@*/
3445{
3446 int i;
3447 bool isFileStatic = usymtab_inFileScope ();
3448 cstring last_file = cstring_undefined;
3449
3450 for (i = 0; i < utab->nentries; i++)
3451 {
3452 bool hasError = FALSE;
3453 uentry ce = utab->entries[i];
3454 fileloc fwhere = uentry_whereDeclared (ce);
3455
3456 if (fileloc_isUndefined (fwhere))
3457 {
3458 fwhere = uentry_whereDefined (ce);
3459 }
3460
3461 if (fileloc_isInvalid (fwhere)
3462 || fileloc_isLib (fwhere)
3463 || fileloc_isBuiltin (fwhere)
3464 || ((fileloc_isSpecialFile (fwhere)
3465 || fileloc_isSpecialFile (uentry_whereDefined (ce)))
3466 && !context_getFlag (FLG_UNUSEDSPECIAL)))
3467 {
3468 ;
3469 }
3470 else if (!uentry_wasUsed (ce) && !uentry_isAnyTag (ce))
3471 {
3472 cstring fname = fileloc_filename (fwhere);
3473
3474 if (cstring_isUndefined (last_file))
3475 {
3476 last_file = fname;
3477 }
3478 else if (cstring_equal (fname, last_file))
3479 {
3480 }
3481 else
3482 {
3483 cleanupMessages ();
3484 last_file = fname;
3485 }
3486
3487 if (uentry_isParam (ce))
3488 {
3489 if (context_inMacro ())
3490 {
3491 sRef cref = uentry_getSref (ce);
3492
3493 if (uentry_isYield (ce))
3494 {
3495 ; /* no checks (for now) */
3496 }
3497 else if (sRef_isSafe (cref))
3498 {
3499 ; /* no error */
3500 }
3501 else
3502 {
3503 if (uentry_hasRealName (ce))
3504 {
3505 hasError =
3506 optgenerror (FLG_MACROPARAMS,
3507 message ("Macro parameter %q not used",
3508 uentry_getName (ce)),
3509 fwhere);
3510 }
3511 }
3512 }
3513 else
3514 {
3515 if (cstring_equalFree (uentry_getName (ce),
3516 cstring_makeLiteral ("...")))
3517 {
3518 ;
3519 }
3520 else
3521 {
3522 hasError = optgenerror (FLG_PARAMUNUSED,
3523 message ("Parameter %q not used",
3524 uentry_getName (ce)),
3525 fwhere);
3526 }
3527 }
3528 } /* isParam */
3529 else if (uentry_isFunction (ce) || uentry_isIter (ce))
3530 {
3531 if (fileloc_isUser (fwhere))
3532 {
3533 hasError = optgenerror
3534 (FLG_FUNCUNUSED,
3535 message ("%q %q declared but not used",
3536 cstring_makeLiteral
3537 (uentry_isIter (ce) ? "Iterator"
3538 : (isFileStatic ? "File static function" : "Function")),
3539 uentry_getName (ce)),
3540 fwhere);
3541 }
3542 }
3543 else if (uentry_isEndIter (ce))
3544 {
3545 ; /* no error (already reported for iter */
3546 }
3547 else if (uentry_isEnumConstant (ce))
3548 {
3549 if (fileloc_isUser (fwhere))
3550 {
3551 hasError = optgenerror
3552 (FLG_ENUMMEMUNUSED,
3553 message ("Enum member %q not used",
3554 uentry_getName (ce)),
3555 fwhere);
3556 }
3557 }
3558 else if (uentry_isConstant (ce))
3559 {
3560 if (fileloc_isUser (fwhere))
3561 {
3562 hasError = optgenerror
3563 (FLG_CONSTUNUSED,
3564 message ("Constant %q declared but not used",
3565 uentry_getName (ce)),
3566 fwhere);
3567 }
3568 }
3569 else if (uentry_isDatatype (ce))
3570 {
3571 if (fileloc_isUser (fwhere))
3572 {
3573 hasError = optgenerror
3574 (FLG_TYPEUNUSED,
3575 message ("Type %q declared but not used",
3576 uentry_getName (ce)),
3577 fwhere);
3578 }
3579 }
3580 else if (!uentry_isRefParam (ce) && !uentry_isExpandedMacro (ce))
3581 { /* errors for ref params will be reported in the next scope */
3582 llassertprint (uentry_isVar (ce),
3583 ("ce: %s", uentry_unparseFull (ce)));
3584
3585 if (ctype_isFunction (uentry_getType (ce)))
3586 {
3587 if (fileloc_isUser (fwhere))
3588 {
3589 hasError = optgenerror
3590 (FLG_FUNCUNUSED,
3591 message ("%q %q declared but not used",
3592 cstring_makeLiteral
3593 (isFileStatic ? "File static function"
3594 : "Function"),
3595 uentry_getName (ce)),
3596 fwhere);
3597 }
3598 }
3599 else
3600 {
3601 if (fileloc_isUser (fwhere))
3602 {
3603
3604
3605 hasError = optgenerror
3606 (FLG_VARUNUSED,
3607 message ("%q %q declared but not used",
3608 cstring_makeLiteral
3609 (isFileStatic ? "File static variable"
3610 : "Variable"),
3611 uentry_getName (ce)),
3612 fwhere);
3613 }
3614 }
3615 }
3616 else
3617 {
3618 ; /* no errors */
3619 }
3620 } /* unused */
3621 else if ((uentry_isDatatype (ce) || uentry_isAnyTag (ce)))
3622 { /* check all fields */
3623 ctype ct = uentry_getRealType (ce);
3624
3625
3626 while (ctype_isAP (ct))
3627 {
3628 ct = ctype_getBaseType (ct);
3629 }
3630
3631 if (ctype_isSU (ct))
3632 {
3633 uentryList fields = ctype_getFields (ct);
3634
3635 uentryList_elements (fields, field)
3636 {
3637 if (!uentry_isUsed (field))
3638 {
3639 if (uentry_hasName (ce))
3640 {
3641 hasError |= optgenerror
3642 (FLG_FIELDUNUSED,
3643 message ("Field %q of %s %q declared but not used",
3644 uentry_getName (field),
3645 cstring_makeLiteralTemp
3646 (ctype_isStruct (ct) ? "structure" : "union"),
3647 uentry_getName (ce)),
3648 uentry_whereEarliest (field));
3649 }
3650 else
3651 {
3652 /*
3653 ** evans 2001-06-08
3654 ** Can't report these errors for unnamed structs.
3655 ** No way to tell when there are multiple consistent
3656 ** unnamed structure types. (Could go through table
3657 ** and mark them all unused...)
3658
3659 hasError |= optgenerror
3660 (FLG_FIELDUNUSED,
3661 message ("Field %q of unnamed %s declared but not used",
3662 uentry_getName (field),
3663 cstring_makeLiteralTemp
3664 (ctype_isStruct (ct) ? "structure" : "union")),
3665 uentry_whereEarliest (field));
3666
3667 */
3668 }
3669
3670 uentry_setUsed (field, fileloc_undefined);
3671 }
3672 } end_uentryList_elements;
3673 }
3674 }
3675 else
3676 {
3677 ; /* no errors */
3678 }
3679
3680 if (hasError)
3681 {
3682 if (uentry_isParam (ce) && context_inMacro ())
3683 {
3684 if (fileloc_isDefined (uentry_whereSpecified (ce)))
3685 {
3686 uentry_showWhereSpecified (ce);
3687 }
3688 }
3689 else
3690 {
3691 uentry_showDefSpecInfo (ce, fwhere);
3692 }
3693
3694 uentry_setUsed (ce, fileloc_undefined);
3695 }
3696 }
3697}
3698
3699static void
3700checkGlobalReturn (uentry glob, sRef orig)
3701{
3702 sRef sr = uentry_getSref (glob);
3703
3704 DPRINTF (("Check global return: %s / orig: %s / sr: %s",
3705 uentry_unparseFull (glob),
3706 sRef_unparseFull (orig),
3707 sRef_unparseFull (sr)));
3708
3709 DPRINTF (("Is killed: %s", bool_unparse (sRef_isKilledGlob (orig))));
3710
3711 if (context_getFlag (FLG_GLOBSTATE))
3712 {
3713 DPRINTF (("Is killed: %s", sRef_unparseFull (orig)));
3714
3715 if (sRef_isKilledGlob (orig))
3716 {
3717 if (sRef_isStateUndefined (sr)
3718 || sRef_isUnuseable (sr)
3719 || sRef_isStateUnknown (sr)
3720 || sRef_isDead (sr))
3721 {
3722 ;
3723 }
3724 else
3725 {
3726 ctype ct = ctype_realType (uentry_getType (glob));
3727
3728 DPRINTF (("Check global destroyed: %s", uentry_unparseFull (glob)));
3729
3730 if (ctype_isVisiblySharable (ct))
3731 {
3732 if (optgenerror
3733 (FLG_GLOBSTATE,
3734 message
3735 ("Killed global %q (type %s) not released before return",
3736 uentry_getName (glob),
3737 ctype_unparse (ct)),
3738 g_currentloc))
3739 {
3740 sRef_showStateInfo (sr);
3741 }
3742 }
3743 else
3744 {
3745 sRef_protectDerivs ();
3746 (void) transferChecks_globalDestroyed (sr, g_currentloc);
3747 sRef_clearProtectDerivs ();
3748 }
3749 }
3750 }
3751 else
3752 {
3753 if (sRef_isStateUndefined (sr))
3754 {
3755 if (optgenerror (FLG_GLOBSTATE,
3756 message
3757 ("Function returns with global %q undefined",
3758 uentry_getName (glob)),
3759 g_currentloc))
3760 {
3761 sRef_showStateInfo (sr);
3762 }
3763 }
3764 else
3765 {
3766 if (sRef_isDead (sr) || sRef_isKept (sr))
3767 {
3768 if (optgenerror
3769 (FLG_GLOBSTATE,
3770 message ("Function returns with global %q "
3771 "referencing %s storage",
3772 uentry_getName (glob),
3773 cstring_makeLiteralTemp (sRef_isDead (sr) ? "released" : "kept")),
3774 g_currentloc))
3775 {
3776 if (sRef_isKept (sr))
3777 {
3778 sRef_showAliasInfo (sr);
3779 }
3780 else
3781 {
3782 sRef_showStateInfo (sr);
3783 }
3784
3785 sRef_setDefState (sr, SS_UNKNOWN, fileloc_undefined);
3786 }
3787 }
3788
3789 if (ctype_isRealPointer (uentry_getType (glob))
3790 && sRef_possiblyNull (sr)
3791 && !uentry_possiblyNull (glob))
3792 {
3793 if (optgenerror
3794 (FLG_GLOBSTATE,
3795 message ("Function returns with non-null global %q "
3796 "referencing null storage",
3797 uentry_getName (glob)),
3798 g_currentloc))
3799 {
3800 sRef_showNullInfo (sr);
3801 }
3802 }
3803 else
3804 {
3805 DPRINTF (("Check transfer: %s", uentry_unparseFull (glob)));
3806 transferChecks_globalReturn (glob);
3807 }
3808 }
3809 }
3810 }
3811}
3812
3813/*
3814** remember: check alias globals
3815*/
3816
3817void usymtab_checkFinalScope (bool isReturn)
3818 /*@globals utab@*/
3819{
3820 bool mustFree = context_getFlag (FLG_MUSTFREEONLY) || context_getFlag (FLG_MUSTFREEFRESH); /*@i423 remove this mustFree */
3821 bool mustDefine = context_getFlag (FLG_MUSTDEFINE);
3822 /* bool mustNotAlias = context_getFlag (FLG_MUSTNOTALIAS); */
3823 sRefSet checked = sRefSet_new ();
3824 usymtab stab = utab;
3825 int i;
3826
3827 /*
3828 ** need to check all scopes out to function parameters.
3829 */
3830
3831 do
3832 {
3833 for (i = 0; i < stab->nentries; i++)
3834 {
3835 uentry ce = stab->entries[i];
3836 sRef sr = uentry_getSref (ce);
3837 sRef rb = sRef_getRootBase (sr);
3838 valueTable tvalues;
3839
3840 /*
3841 ** Shouldn't check if shadow checked in deeper scope:
3842 */
3843
3844 if (stab != utab)
3845 {
3846 uentry oue = usymtab_lookupQuietNoAlt (utab, uentry_observeRealName (ce));
3847
3848 if (!uentry_sameObject (ce, oue))
3849 {
3850 DPRINTF (("Skipping outer entry: %s / %s", uentry_unparseFull (ce),
3851 uentry_unparseFull (oue)));
3852 /*@i32 what if it is one an alternate branch? */
3853 /*@innercontinue@*/ continue;
3854 }
3855 }
3856
3857 DPRINTF (("Here check final scope: %s", uentry_unparseFull (ce)));
3858
3859 if (ctype_isFunction (uentry_getType (ce)))
3860 {
3861 /*@innercontinue@*/ continue;
3862 }
3863
3864 if (uentry_isAnyParam (ce)
3865 || uentry_isRefParam (ce)
3866 || sRef_isFileOrGlobalScope (rb))
3867 {
3868 /* Don't do the loseref check...but should check state! */
3869 DPRINTF (("Skipping check 1"));
3870 }
3871 else if (sRef_isDefinitelyNull (sr)
3872 || usymtab_isDefinitelyNull (sr))
3873 {
3874 /*
3875 ** No state reference errors for definitely null references.
3876 */
3877
3878 DPRINTF (("Skipping check 2"));
3879 }
3880 else
3881 {
3882 DPRINTF (("Lose ref: %s / %s", uentry_unparse (ce),
3883 sRef_unparseFull (sr)));
3884
3885 tvalues = sRef_getValueTable (sr);
3886
3887 valueTable_elements (tvalues, fkey, fval) {
3888 metaStateInfo minfo;
3889 cstring msg = cstring_undefined;
3890 int nval;
3891
3892 minfo = context_lookupMetaStateInfo (fkey);
3893 llassert (metaStateInfo_isDefined (minfo));
3894
3895 if (stateValue_isError (fval)
3896 || sRef_isStateUndefined (sr)) /* No errors for undefined state */
3897 {
3898 DPRINTF (("Skipping check 3"));
3899 }
3900 else
3901 {
3902 DPRINTF (("Check: %s / %s / %s", fkey,
3903 metaStateInfo_unparse (minfo),
3904 stateValue_unparse (fval)));
3905
3906 minfo = context_lookupMetaStateInfo (fkey);
3907
3908 nval = stateCombinationTable_lookupLoseReference
3909 (metaStateInfo_getTransferTable (minfo),
3910 stateValue_getValue (fval), &msg);
3911
3912 if (cstring_isDefined (msg))
3913 {
3914 /*@i32 print extra info for assignments@*/
3915 DPRINTF (("From: %s", sRef_unparseFull (sr)));
3916 DPRINTF (("Null? %s / %s",
3917 bool_unparse (sRef_isDefinitelyNull (sr)),
3918 bool_unparse (usymtab_isGuarded (sr))));
3919
3920 if (optgenerror
3921 (FLG_STATETRANSFER,
3922 message
3923 ("%s loses reference %q in invalid state %q (%s)",
3924 cstring_makeLiteralTemp (isReturn ? "Return" : "Scope exit"),
3925 uentry_getName (ce),
3926 stateValue_unparseValue (fval, minfo),
3927 msg),
3928 g_currentloc))
3929 {
3930 stateValue_show (fval, minfo);
3931 }
3932 else
3933 {
3934 DPRINTF (("Suppressed transfer error: %s", msg));
3935 }
3936 }
3937 }
3938 } end_valueTable_elements;
3939 }
3940
3941 DPRINTF (("Here 1"));
3942
3943 if (mustFree)
3944 {
3945 DPRINTF (("Check mustfree entry: %s", uentry_unparseFull (ce)));
3946
3947 if (!sRefSet_member (checked, sr) && !sRef_isFileOrGlobalScope (rb))
3948 {
3949 if (ctype_isRealSU (uentry_getType (ce))
3950 && !uentry_isAnyParam (ce)
3951 && !uentry_isRefParam (ce)
3952 && !uentry_isStatic (ce)
3953 && !sRef_isDependent (sr)
3954 && !sRef_isOwned (sr))
3955 {
3956 sRefSet als = usymtab_allAliases (sr);
3957
3958 if (sRefSet_isEmpty (als))
3959 {
3960 transferChecks_localDestroyed (sr, g_currentloc);
3961 }
3962 else
3963 {
3964 /* aliased, no problem */ ;
3965 }
3966
3967 sRefSet_free (als);
3968 }
3969 else if
3970 (!uentry_isStatic (ce)
3971 && ((sRef_isNewRef (sr))
3972 || (((sRef_isOnly (sr) || sRef_isFresh (sr)
3973 || sRef_isKeep (sr) || sRef_isOwned (sr))
3974 && !sRef_isDead (sr))
3975 && (!sRef_definitelyNull (sr))
3976 && (!usymtab_isDefinitelyNull (sr)))))
3977 {
3978 bool hasError = TRUE;
3979
3980 DPRINTF (("Checking: %s", sRef_unparseFull (sr)));
3981
3982 /*
3983 ** If its a scope exit, check if there is an alias.
3984 ** If so, make it only. If not, there is an error.
3985 */
3986
3987 if (!isReturn)
3988 {
3989 if (transferChecks_canLoseReference (sr, g_currentloc))
3990 {
3991 DPRINTF (("Can lose!"));
3992 hasError = FALSE;
3993 }
3994 }
3995
3996 if (hasError)
3997 {
3998 if (sRef_hasLastReference (sr))
3999 {
4000 sRef ar = sRef_getAliasInfoRef (sr);
4001
4002 if (optgenerror
4003 (sRef_isFresh (ar) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4004 message
4005 ("Last reference %q to %s storage %qnot %q before %q",
4006 sRef_unparse (sr),
4007 alkind_unparse (sRef_getAliasKind (sr)),
4008 sRef_unparseOpt (ar),
4009 cstring_makeLiteral (sRef_isKeep (sr)
4010 ? "transferred" : "released"),
4011 cstring_makeLiteral (isReturn
4012 ? "return" : "scope exit")),
4013 g_currentloc))
4014 {
4015 sRef_showRefLost (sr);
4016 }
4017 }
4018 else if (sRef_isNewRef (sr))
4019 {
4020 if (optgenerror
4021 (sRef_isFresh (sr) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4022 message
4023 ("%q %q not released before %q",
4024 cstring_makeLiteral
4025 (alkind_isKillRef (sRef_getOrigAliasKind (sr))
4026 ? "Kill reference parameter" : "New reference"),
4027 uentry_getName (ce),
4028 cstring_makeLiteral (isReturn
4029 ? "return" : "scope exit")),
4030 g_currentloc))
4031 {
4032 sRef_showAliasInfo (sr);
4033 }
4034 }
4035 else
4036 {
4037 if (ctype_isRealSU (sRef_getType (sr)))
4038 {
4039 transferChecks_structDestroyed (sr, g_currentloc);
4040 }
4041 else
4042 {
4043 DPRINTF (("Here we are: %s", sRef_unparseFull (sr)));
4044
4045 if (optgenerror
4046 (sRef_isFresh (sr) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4047 message
4048 ("%s storage %q not %q before %q",
4049 alkind_capName (sRef_getAliasKind (sr)),
4050 uentry_getName (ce),
4051 cstring_makeLiteral (sRef_isKeep (sr)
4052 ? "transferred" : "released"),
4053 cstring_makeLiteral (isReturn
4054 ? "return" : "scope exit")),
4055 g_currentloc))
4056 {
4057 sRef_showAliasInfo (sr);
4058 DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
4059 }
4060 }
4061 }
4062 }
4063 }
4064 else
4065 {
4066 ;
4067 }
4068 }
4069 }
4070
4071 if (mustDefine && uentry_isOut (ce))
4072 {
4073 /* No error if its dead (either only or error already reported */
4074 if (!sRef_isReallyDefined (sr) && !sRef_isDead (sr))
4075 {
4076 voptgenerror
4077 (FLG_MUSTDEFINE,
4078 message ("Out storage %q not defined before %q",
4079 uentry_getName (ce),
4080 cstring_makeLiteral
4081 (isReturn ? "return" : "scope exit")),
4082 g_currentloc);
4083
4084 DPRINTF (("sr: %s", sRef_unparseFull (sr)));
4085 }
4086 }
4087
4088 /*
4089 ** also check state is okay
4090 */
4091
4092 if (usymtab_lexicalLevel () > functionScope
4093 && uentry_isVariable (ce)
4094 && (sRef_isLocalVar (sr)
4095 && (sRef_isDependent (sr) || sRef_isLocalState (sr))))
4096 {
4097 sRefSet ab = usymtab_aliasedBy (sr);
4098
4099 /* should do something more efficient here */
4100
4101 if (sRefSet_isEmpty (ab))
4102 {
4103 /* and no local ref */
4104 DPRINTF (("Check lose ref: %s", uentry_unparseFull (ce)));
4105 transferChecks_loseReference (ce);
4106 }
4107 else
4108 {
4109 ;
4110 }
4111
4112 sRefSet_free (ab);
4113 }
4114 else
4115 {
4116 ;
4117 }
4118
4119 checked = sRefSet_insert (checked, sr);
4120 }
4121
4122 llassert (usymtab_isDefined (stab->env));
4123
4124 if (usymtab_isBranch (stab))
4125 {
4126 stab = usymtab_dropEnv (stab);
4127 }
4128 else
4129 {
4130 stab = stab->env;
4131 }
4132
4133 llassert (stab != usymtab_undefined);
4134 } while (isReturn && (stab->lexlevel >= paramsScope));
4135
4136 sRefSet_free (checked);
4137
4138 /*
4139 ** for returns:
4140 ** all globals are appropriately defined
4141 ** all parameters are appropriately defined
4142 ** special clauses are followed
4143 */
4144
4145 if (isReturn || (utab->lexlevel == paramsScope))
4146 {
4147 uentry fcn = context_getHeader ();
4148 uentryList params = context_getParams ();
4149 globSet uglobs = context_getUsedGlobs ();
4150 globSet sglobs = context_getGlobs ();
4151
4152 if (isReturn && context_maybeSet (FLG_GLOBALIAS))
4153 {
4154 aliasTable_checkGlobs (utab->aliases);
4155 }
4156
4157 /*
4158 ** state clauses (ensures, defines, sets, allocates, releases)
4159 */
4160
4161 if (uentry_hasStateClauseList (fcn))
4162 {
4163 stateClauseList clauses = uentry_getStateClauseList (fcn);
4164
4165 stateClauseList_elements (clauses, cl)
4166 {
4167 if (stateClause_isAfter (cl) && !stateClause_isGlobal (cl))
4168 {
4169 if (stateClause_setsMetaState (cl))
4170 {
4171 sRefSet rfs = stateClause_getRefs (cl);
4172 qual q = stateClause_getMetaQual (cl);
4173 annotationInfo ainfo = qual_getAnnotationInfo (q);
4174 metaStateInfo minfo = annotationInfo_getState (ainfo);
4175 cstring key = metaStateInfo_getName (minfo);
4176 int mvalue = annotationInfo_getValue (ainfo);
4177
4178 DPRINTF (("Post meta state clause: %s", stateClause_unparse (cl)));
4179
4180 sRefSet_elements (rfs, el)
4181 {
4182 sRef base = sRef_getRootBase (el);
4183
4184 if (sRef_isResult (base))
4185 {
4186 /*
4187 ** This is checked for return transfers.
4188 */
4189 ;
4190 }
4191 else if (sRef_isParam (base) || sRef_isGlobalMarker (base))
4192 {
4193 sRef sr = sRef_updateSref (base);
4194 sr = sRef_fixBase (el, sr);
4195
4196 if (!sRef_checkMetaStateValue (sr, key, mvalue))
4197 {
4198 if (optgenerror
4199 (FLG_STATETRANSFER,
4200 message
4201 ("Ensures clause not satisfied%q (state is %q): %q",
4202 sRef_isGlobalMarker (sr)
4203 ? message ("")
4204 : message (" by %q", sRef_unparse (sr)),
4205 stateValue_unparseValue (sRef_getMetaStateValue (sr, key),
4206 minfo),
4207 stateClause_unparse (cl)),
4208 g_currentloc))
4209 {
4210 sRef_showMetaStateInfo (sr, key);
4211 }
4212 }
4213 }
4214 else
4215 {
4216 if (sRef_isMeaningful (el))
4217 {
4218 BADBRANCH;
4219 }
4220 }
4221 } end_sRefSet_elements ;
4222 }
4223 else
4224 {
4225 /* evs - 2000 07 10 - added this */
4226 sRefTest tst = stateClause_getPostTestFunction (cl);
4227 sRefSet rfs = stateClause_getRefs (cl);
4228
4229 sRefSet_elements (rfs, el)
4230 {
4231 sRef base = sRef_getRootBase (el);
4232
4233 if (sRef_isResult (base))
4234 {
4235 /*
4236 ** This is checked for return transfers.
4237 */
4238
4239 ;
4240 }
4241 else if (sRef_isParam (base))
4242 {
4243 sRef sr = sRef_updateSref (base);
4244 sr = sRef_fixBase (el, sr);
4245
4246 if (tst != NULL && !tst (sr))
4247 {
4248 if (optgenerror
4249 (stateClause_postErrorCode (cl),
4250 message ("%s storage %qcorresponds to "
4251 "storage listed in %q clause",
4252 stateClause_postErrorString (cl, sr),
4253 sRef_unparseOpt (sr),
4254 stateClause_unparseKind (cl)),
4255 g_currentloc))
4256 {
4257 sRefShower ss = stateClause_getPostTestShower (cl);
4258
4259 if (ss != NULL)
4260 {
4261 ss (sr);
4262 }
4263
4264 DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
4265 }
4266 }
4267 }
4268 else
4269 {
4270 if (sRef_isMeaningful (el))
4271 {
4272 BADBRANCH;
4273 }
4274 }
4275 } end_sRefSet_elements ;
4276 }
4277 }
4278 } end_stateClauseList_elements ;
4279 }
4280
4281 /*
4282 ** check parameters on return
4283 */
4284
4285 uentryList_elements (params, arg)
4286 {
4287 if (!uentry_isElipsisMarker (arg))
4288 {
4289 ctype rt = ctype_realType (uentry_getType (arg));
4290
4291 if (ctype_isMutable (rt) || ctype_isSU (rt))
4292 {
4293 uentry param = usymtab_lookupQuiet (utab, uentry_rawName (arg));
4294 DPRINTF (("Check param return: %s", uentry_unparseFull (param)));
4295 transferChecks_paramReturn (param);
4296 }
4297 }
4298 } end_uentryList_elements;
4299
4300 DPRINTF (("Check global return: %s",
4301 globSet_unparse (sglobs)));
4302
4303 globSet_allElements (sglobs, el)
4304 {
4305 sRef orig = el; /*! sRef_updateSref (el); */ /*!!!*/
4306 uentry current = sRef_getUentry (el);
4307
4308 DPRINTF (("Check global return: %s / %s", sRef_unparseFull (el),
4309 uentry_unparseFull (current)));
4310
4311 if (uentry_isVariable (current) && !uentry_isRealFunction (current))
4312 {
4313 checkGlobalReturn (current, orig);
4314 }
4315 } end_globSet_allElements;
4316
4317 globSet_allElements (uglobs, el)
4318 {
4319 if (!globSet_member (sglobs, el))
4320 {
4321 uentry current = sRef_getUentry (el);
4322
4323 if (uentry_isVariable (current)
4324 && !uentry_isRealFunction (current))
4325 {
4326 checkGlobalReturn (current, sRef_undefined);
4327 }
4328 }
4329 } end_globSet_allElements;
4330 }
4331}
4332
4333void
4334usymtab_quietExitScope (fileloc loc)
4335 /*@globals utab, globtab, filetab; @*/
4336 /*@modifies utab@*/
4337{
4338 usymtab t = utab->env;
4339
4340 if (utab->reftable != NULL)
4341 {
4342 int i;
4343
4344 for (i = 0; i < utab->nentries; i++)
4345 {
4346 uentry current = utab->entries[i];
4347 uentry old = usymtab_lookupAux (t, uentry_rawName (current));
4348
4349 uentry_mergeState (old, current, loc, FALSE, FALSE, FALSE, NOCLAUSE);
4350 }
4351 }
4352
4353 llassert (t != NULL);
4354
4355 if (t->lexlevel > paramsScope)
4356 {
4357 t->guards = guardSet_levelUnion (t->guards, utab->guards, t->lexlevel);
4358 t->aliases = aliasTable_levelUnionSeq (t->aliases, utab->aliases,
4359 t->lexlevel);
4360 utab->aliases = aliasTable_undefined;
4361 }
4362
4363 t->mustBreak = utab->mustBreak;
4364 t->exitCode = utab->exitCode;
4365
4366 usymtab_freeLevel (utab);
4367
4368 utab = t;
4369
4370# ifdef DEBUGSPLINT
4371 usymtab_checkAllValid ();
4372# endif
4373}
4374
4375/*
4376** Exit a scope with no checking, lose alias states.
4377** (When should this be used?)
4378*/
4379
4380void usymtab_quietPlainExitScope (void)
4381 /*@globals utab, globtab, filetab@*/
4382 /*@modifies utab@*/
4383{
4384 usymtab t = utab->env;
4385
4386 llassert (t != NULL);
4387 llassert (NOALIAS (utab->aliases, t->aliases));
4388 usymtab_freeLevel (utab);
4389 utab = t;
4390}
4391
4392void usymtab_exitScope (exprNode expr)
4393 /*@globals utab, filetab, globtab@*/
4394 /*@modifies utab, globtab@*/
4395{
4396 usymtab ctab = usymtab_undefined;
4397 usymtab lctab = usymtab_undefined;
4398 bool mustReturn = exprNode_mustEscape (expr);
4399
4400 DPRINTF (("Exit scope"));
4401
4402 if (utab->kind == US_CBRANCH)
4403 {
4404 /*
4405 ** save the case branches, remove the first non-cbranch
4406 */
4407
4408 ctab = utab;
4409
4410 while (utab->kind == US_CBRANCH)
4411 {
4412 lctab = utab;
4413 utab = utab->env;
4414 llassert (utab != GLOBAL_ENV);
4415 }
4416 }
4417
4418 if (utab->kind == US_TBRANCH || utab->kind == US_FBRANCH
4419 || utab->kind == US_CBRANCH || utab->kind == US_SWITCH)
4420 {
4421 if (context_inMacro ())
4422 {
4423 /* evs 2000-07-25 */
4424 /* Unparseable macro may end inside nested scope. Deal with it. */
4425
4426 llerror (FLG_SYNTAX,
4427 message ("Problem parsing macro body of %s (unbalanced scopes). "
4428 "Attempting to recover, recommend /*@notfunction@*/ before "
4429 "macro definition.",
4430 context_inFunctionName ()));
4431
4432 while (utab->kind == US_TBRANCH
4433 || utab->kind == US_FBRANCH
4434 || utab->kind == US_CBRANCH
4435 || utab->kind == US_SWITCH)
4436 {
4437 utab = utab->env;
4438 llassert (utab != GLOBAL_ENV);
4439 }
4440 } else
4441 {
4442 llcontbug (message ("exitScope: in branch: %q", usymtab_unparseStack ()));
4443 /*@-branchstate@*/
4444 } /*@=branchstate@*/
4445 }
4446
4447 /*
4448 ** check all variables in scope were used
4449 */
4450
4451 /*
4452 ** bogus errors if this is the normal inside a switch,
4453 ** since cases have not been merged yet. Should probably
4454 ** still check this, but I'm too lazy at the moment...
4455 */
4456
4457 llassertfatal (utab->env != GLOBAL_ENV);
4458
4459 if (utab->env->kind != US_SWITCH)
4460 {
4461 usymtab_allUsed ();
4462 }
4463
4464 /*
4465 ** check aliasing: all only params are released (dead)
4466 ** definition: all out params are defined, all modified params
4467 ** are completely defined
4468 **
4469 ** NOTE: note for exiting paramsScope, since checkReturn should be
4470 ** called first.
4471 */
4472
4473 if (!mustReturn && (usymtab_lexicalLevel () > functionScope))
4474 {
4475 /*
4476 ** should only call this is end of scope is reachable...
4477 */
4478
4479 usymtab_checkFinalScope (FALSE);
4480 }
4481
4482 if (usymtab_lexicalLevel () == paramsScope && context_inFunctionLike ())
4483 {
4484 /*
4485 ** leaving a function, need to fix up globals
4486 */
4487
4488 uentryList params = context_getParams ();
4489 globSet globs = context_getUsedGlobs ();
4490
4491 uentryList_elements (params, ue)
4492 {
4493 uentry_fixupSref (ue);
4494 } end_uentryList_elements;
4495
4496 clearFunctionTypes ();
4497
4498 DPRINTF (("Fixing up globals: %s", globSet_unparse (globs)));
4499
4500 globSet_allElements (globs, el)
4501 {
4502 DPRINTF (("Fix: %s", sRef_unparseDebug (el)));
4503
4504 if (sRef_isCvar (el))
4505 {
4506 uentry current;
4507 int index = sRef_getScopeIndex (el);
4508
4509 if (sRef_isFileStatic (el))
4510 {
4511 llassert (usymtab_isDefined (filetab));
4512 current = usymtab_fetchIndex (filetab, index);
4513 }
4514 else
4515 {
4516 current = usymtab_fetchIndex (globtab, index);
4517 }
4518
4519 if (uentry_isVariable (current))
4520 {
4521 DPRINTF (("Fixup: %s", uentry_unparse (current)));
4522 uentry_fixupSref (current);
4523 }
4524 else
4525 {
4526 DPRINTF (("Clear: %s", uentry_getSref (current)));
4527 sRef_clearDerived (uentry_getSref (current));
4528 }
4529 }
4530
4531 sRef_clearDerived (el); /* evans 2002-03-14 - this is the likely source of many crashes! */
4532 } end_globSet_allElements;
4533 }
4534
4535 usymtab_quietExitScope (exprNode_loc (expr));
4536
4537 if (lctab != usymtab_undefined)
4538 {
4539 /*@i@*/ lctab->env = utab;
4540 /*@i@*/ utab = ctab;
4541 /*@-branchstate@*/ } /*@=branchstate@*/
4542 /*@-globstate@*/
4543
4544
4545# ifdef DEBUGSPLINT
4546 usymtab_checkAllValid ();
4547# endif
4548/*@i523@*/ }
4549/*@=globstate@*/
4550
4551/*
4552** yikes! don't let the '170 kids see this one...
4553*/
4554
4555int
4556uentry_directParamNo (uentry ue)
4557{
4558 if (uentry_isVar (ue))
4559 {
4560 sRef sr = uentry_getSref (ue);
4561
4562 if (sRef_lexLevel (sr) == functionScope)
4563 {
4564 int index = sRef_getScopeIndex (sr);
4565
4566 if (index < uentryList_size (context_getParams ()))
4567 {
4568 return index;
4569 }
4570 }
4571 }
4572 return -1;
4573}
4574
4575/*@dependent@*/ /*@exposed@*/ uentry
4576 usymtab_getParam (int paramno)
4577 /*@globals utab@*/
4578{
4579 /*
4580 ** requires in a function context (checked)
4581 **
4582 ** depends on no nested functions --- the function
4583 ** parameters are ALWAYS one scope inside the global scope
4584 ** and entered in order!
4585 */
4586 usymtab s = utab;
4587
4588 if (!context_inFunctionLike ())
4589 llfatalbug (message ("usymtab_getParam: not in function context: %q",
4590 context_unparse ()));
4591
4592 while (s->lexlevel > paramsScope)
4593 {
4594 s = s->env;
4595 }
4596
4597 llassert (usymtab_isDefined (s));
4598
4599 if (paramno >= s->nentries)
4600 {
4601 /*
4602 ** Parse errors lead to this.
4603 */
4604
4605 uentry err = uentry_makeVariableLoc (cstring_makeLiteralTemp ("<error>"),
4606 ctype_unknown);
4607
4608 uentry_markOwned (err);
4609 return (err);
4610 }
4611
4612 return (s->entries[paramno]);
4613}
4614
4615static /*@dependent@*/ /*@exposed@*/ uentry
4616usymtab_getRefTab (/*@notnull@*/ usymtab u, int level, usymId index)
4617{
4618 uentry ue;
4619
4620 ue = usymtab_getRefNoisy (u, level, index);
4621
4622 if (uentry_isUndefined (ue))
4623 {
4624 llbug (message ("usymtab_getRef: out of range: %d. level = %d",
4625 index, level));
4626 }
4627
4628 return ue;
4629}
4630
4631static /*@dependent@*/ /*@exposed@*/ usymtab
4632 usymtab_dropEnv (/*@notnull@*/ usymtab s)
4633{
4634 if (s->kind == US_CBRANCH)
4635 {
4636 usymtab t = s;
4637
4638 do
4639 {
4640 t = s;
4641 s = s->env;
4642 llassert (s != GLOBAL_ENV);
4643 } while (s->kind == US_CBRANCH);
4644 /* drop all cases (except in nested scopes */
4645
4646 s = t;
4647 llassert (s != GLOBAL_ENV);
4648 }
4649
4650 if (s->kind == US_FBRANCH)
4651 {
4652 s = s->env; /* skip the true branch */
4653 llassert (usymtab_isDefined (s));
4654 llassert (s->kind == US_TBRANCH);
4655 }
4656
4657 llassert (s != GLOBAL_ENV);
4658 s = s->env;
4659
4660 return s;
4661}
4662
4663/*@dependent@*/ /*@exposed@*/ uentry
4664 usymtab_getRefQuiet (int level, usymId index)
4665 /*@globals utab@*/
4666{
4667 usymtab s = utab;
4668
4669
4670 llassert (s != NULL);
4671 llassert (index >= 0);
4672
4673 if (level > s->lexlevel)
4674 {
4675 return uentry_undefined;
4676 }
4677
4678 llassertprint (level <= s->lexlevel, ("level: %d / lexlevel: %d",
4679 level, s->lexlevel));
4680
4681 while (s->lexlevel > level)
4682 {
4683 if (usymtab_isBranch (s))
4684 {
4685 int eindex = refTable_lookup (s, level, index);
4686
4687 if (eindex != NOT_FOUND)
4688 {
4689 return (s->entries[eindex]);
4690 }
4691 }
4692
4693 s = usymtab_dropEnv (s);
4694 }
4695
4696 while (usymtab_isBranch (s) && s->lexlevel == level)
4697 {
4698 int eindex = refTable_lookup (s, level, index);
4699
4700 if (eindex != NOT_FOUND)
4701 {
4702 return (s->entries[eindex]);
4703 }
4704
4705 s = usymtab_dropEnv (s);
4706 }
4707
4708 if (index >= s->nentries)
4709 {
4710 return uentry_undefined;
4711 }
4712
4713 llassert (!uentry_isUndefined (s->entries[index]));
4714
4715 return s->entries[index];
4716}
4717
4718static /*@dependent@*/ /*@exposed@*/ uentry
4719usymtab_getRefNoisy (/*@notnull@*/ usymtab s, int level, usymId index)
4720{
4721 usymtab otab = s;
4722 uentry ue = uentry_undefined;
4723
4724 llassert (index >= 0);
4725
4726 while (s->lexlevel > level)
4727 {
4728 if (usymtab_isBranch (s))
4729 {
4730 int eindex = refTable_lookup (s, level, index);
4731
4732 if (eindex != NOT_FOUND)
4733 {
4734 ue = s->entries[eindex];
4735
4736 if (s != otab)
4737 {
4738 while (!usymtab_isBranch (otab))
4739 {
4740 otab = usymtab_dropEnv (otab);
4741 llassert (otab != GLOBAL_ENV);
4742 }
4743
4744 if (refTable_lookup (otab, level, index) == NOT_FOUND)
4745 {
4746 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4747 }
4748 else
4749 {
4750 ;
4751 }
4752 }
4753
4754 return ue;
4755 }
4756 }
4757
4758 s = usymtab_dropEnv (s);
4759 }
4760
4761 llassert (usymtab_isDefined (s));
4762
4763 while (usymtab_isBranch (s) && s->lexlevel == level)
4764 {
4765 int eindex = refTable_lookup (s, level, index);
4766
4767
4768 if (eindex != NOT_FOUND)
4769 {
4770 ue = s->entries[eindex];
4771
4772 if (s != otab)
4773 {
4774 while (!usymtab_isBranch (otab))
4775 {
4776 otab = usymtab_dropEnv (otab);
4777 llassert (otab != GLOBAL_ENV);
4778 }
4779
4780 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4781 }
4782 else
4783 {
4784 ;
4785 }
4786
4787 return ue;
4788 }
4789
4790 s = usymtab_dropEnv (s);
4791 }
4792
4793 if (s->lexlevel == level && (index < s->nentries))
4794 {
4795 ue = s->entries[index];
4796
4797 if (uentry_isValid (ue))
4798 {
4799 if (s != otab)
4800 {
4801 while (!usymtab_isBranch (otab))
4802 {
4803 otab = usymtab_dropEnv (otab);
4804
4805 if (otab == GLOBAL_ENV)
4806 {
4807 return ue;
4808 }
4809 }
4810
4811 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4812 }
4813 else
4814 {
4815 }
4816 }
4817
4818 return ue;
4819 }
4820
4821
4822 if (index >= s->nentries)
4823 {
4824 return uentry_undefined;
4825 }
4826
4827 llassert (!uentry_isUndefined (s->entries[index]));
4828
4829 return s->entries[index];
4830}
4831
4832/*
4833** looking up entries
4834**
4835** If entry is inside a branch, then copy it, and put it into
4836** the branch table.
4837*/
4838
4839static
4840int refTable_lookup (/*@notnull@*/ usymtab ut, int level, int index)
4841{
4842 refTable rt = ut->reftable;
4843 int i;
4844
4845 llassert (rt != NULL);
4846
4847 for (i = 0; i < ut->nentries; i++)
4848 {
4849 if (rt[i]->level == level && rt[i]->index == index)
4850 {
4851 return i;
4852 }
4853 }
4854
4855 return NOT_FOUND;
4856}
4857
4858static
4859/*@only@*/ refentry refentry_create (int level, int index)
4860{
4861 refentry r = (refentry) dmalloc (sizeof (*r));
4862
4863 r->level = level;
4864 r->index = index;
4865
4866 return r;
4867}
4868
4869static /*@dependent@*/ /*@exposed@*/ uentry
4870usymtab_addRefEntry (/*@notnull@*/ usymtab s, cstring k)
4871{
4872 int eindex;
4873 usymtab ut = s;
4874
4875 if (ut->reftable == NULL)
4876 {
4877 DPRINTF (("Adding ref entry without reftable: %s", k));
4878 return uentry_undefined;
4879 }
4880
4881 llassert (ut->reftable != NULL);
4882
4883 while (s != GLOBAL_ENV)
4884 {
4885 eindex = usymtab_getIndex (s, k);
4886
4887 if (eindex != NOT_FOUND)
4888 {
4889 uentry current = s->entries[eindex];
4890
4891 if (uentry_isVar (current) && !ctype_isFunction (uentry_getType (current)))
4892 {
4893 uentry ue;
4894
4895 DPRINTF (("Here: copying %s", uentry_unparse (current)));
4896 ue = uentry_copy (current);
4897 DPRINTF (("Here: copying %s", uentry_unparse (ue)));
4898 usymtab_addEntryQuiet (ut, ue);
4899 DPRINTF (("Okay..."));
4900
4901 if (s->reftable != NULL)
4902 {
4903 refentry ref = s->reftable[eindex];
4904
4905 ut->reftable[ut->nentries - 1]
4906 = refentry_create (ref->level, ref->index);
4907 }
4908 else
4909 {
4910 ut->reftable[ut->nentries - 1]
4911 = refentry_create (s->lexlevel, eindex);
4912 }
4913
4914 return (ue);
4915 }
4916 else
4917 {
4918 return (current);
4919 }
4920 }
4921
4922 s = usymtab_dropEnv (s);
4923 }
4924
4925 return uentry_undefined;
4926}
4927
4928static uentry usymtab_lookupAux (usymtab s, cstring k)
4929{
4930 DPRINTF (("Lookup: %s", k));
4931
4932 while (s != GLOBAL_ENV)
4933 {
4934 int eindex = usymtab_getIndex (s, k);
4935
4936 if (eindex != NOT_FOUND)
4937 {
4938 uentry ret = s->entries[eindex];
4939# if 0
4940
4941
4942 if (s->kind == US_TBRANCH
4943 || s->kind == US_FBRANCH
4944 || s->kind == US_CBRANCH)
4945 /* uentry_isGlobalVariable (ret) && os->lexlevel > fileScope) */
4946 {
4947 uentry ret;
4948 DPRINTF (("Adding global ref entry: %s", k));
4949 ret = usymtab_addRefEntry (os, k);
4950 DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
4951 return ret;
4952 }
4953
4954# endif
4955 DPRINTF (("Found: %s", uentry_unparseFull (ret)));
4956 return (ret);
4957 }
4958
4959 if (s->kind == US_TBRANCH || s->kind == US_FBRANCH
4960 || s->kind == US_CBRANCH)
4961 {
4962 /* why isn't this os??? */
4963 uentry ret = usymtab_addRefEntry (s, k);
4964 DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
4965 return ret;
4966 }
4967
4968 s = s->env;
4969 }
4970
4971 return uentry_undefined;
4972}
4973
4974static /*@dependent@*/ /*@exposed@*/ uentry
4975usymtab_lookupQuietAux (usymtab s, cstring k, bool noalt)
4976{
4977 int eindex;
4978
4979 while (s != GLOBAL_ENV)
4980 {
4981 eindex = usymtab_getIndex (s, k);
4982
4983 if (eindex != NOT_FOUND)
4984 {
4985 uentry ret = s->entries[eindex];
4986 return (ret);
4987 }
4988
4989 if (noalt && usymtab_isBranch (s))
4990 {
4991 s = usymtab_dropEnv (s);
4992 }
4993 else
4994 {
4995 llassert (s != NULL); /*@i523 should not need this? */
4996 s = s->env;
4997 }
4998 }
4999
5000 return uentry_undefined;
5001}
5002
5003static /*@exposed@*/ /*@dependent@*/ uentry
5004usymtab_lookupQuiet (usymtab s, cstring k)
5005{
5006 return usymtab_lookupQuietAux (s, k, FALSE);
5007}
5008
5009static /*@exposed@*/ /*@dependent@*/ uentry
5010usymtab_lookupQuietNoAlt (usymtab s, cstring k)
5011{
5012 return usymtab_lookupQuietAux (s, k, TRUE);
5013}
5014
5015/*@dependent@*/ /*@observer@*/ uentry
5016 usymtab_lookupSafe (cstring k)
5017 /*@globals utab@*/
5018{
5019 DPRINTF (("Lookup safe: %s", k));
5020 return (usymtab_lookupAux (utab, k));
5021}
5022
5023uentry
5024 usymtab_lookupExpose (cstring k)
5025 /*@globals utab@*/
5026{
5027 uentry ce = usymtab_lookupAux (utab, k);
5028
5029 if (uentry_isUndefined (ce))
5030 {
5031 llfatalbug (message ("usymtab_lookup: not found: *%s*", k));
5032 }
5033
5034 if (uentry_isPriv (ce))
5035 {
5036 llfatalbug (message ("usymtab_lookup: private: *%s*", k));
5037 }
5038
5039 return ce;
5040}
5041
5042uentry usymtab_lookupExposeGlob (cstring k)
5043{
5044 return (usymtab_lookupGlobSafe (k));
5045}
5046
5047uentry usymtab_lookupGlob (cstring k)
5048 /*@globals globtab@*/
5049{
5050 uentry ce = usymtab_lookupAux (globtab, k);
5051
5052 if (uentry_isUndefined (ce))
5053 llfatalbug (message ("usymtab_lookup: not found: %s", k));
5054
5055 if (uentry_isPriv (ce))
5056 llfatalbug (message ("usymtab_lookup: private: %s", k));
5057
5058 DPRINTF (("Lookup global: %s", uentry_unparseFull (ce)));
5059 return ce;
5060}
5061
5062/*@observer@*/ uentry
5063 usymtab_lookupGlobSafe (cstring k)
5064 /*@globals globtab@*/
5065{
5066 uentry ce = usymtab_lookupAux (globtab, k);
5067 DPRINTF (("Lookup global: %s", uentry_unparseFull (ce)));
5068 return ce;
5069}
5070
5071uentry usymtab_lookupEither (cstring k)
5072 /*@globals utab@*/
5073{
5074 uentry ce = usymtab_lookupSafe (k);
5075
5076 if (uentry_isUndefined (ce))
5077 llfatalerror (message ("usymtab_lookup: not found: %s", k));
5078
5079 DPRINTF (("Lookup either: %s", uentry_unparseFull (ce)));
5080 return ce;
5081}
5082
5083# ifndef NOLCL
5084ctype
5085usymtab_lookupType (cstring k)
5086 /*@globals globtab@*/
5087{
5088 usymId uid = usymtab_getTypeId (k);
5089
5090 if (uid == USYMIDINVALID)
5091 {
5092 llcontbug (message ("usymtab_lookupType: not found: %s", k));
5093 return ctype_unknown;
5094 }
5095
5096 return (uentry_getRealType (usymtab_getTypeEntry (uid)));
5097}
5098# endif
5099
5100ctype
5101usymtab_lookupAbstractType (cstring k) /*@globals globtab@*/
5102{
5103 usymId uid = usymtab_getTypeId (k);
5104
5105 if (uid == USYMIDINVALID)
5106 {
5107 llcontbug (message ("usymtab_lookupType: not found: %s", k));
5108 return ctype_unknown;
5109 }
5110
5111 return (uentry_getAbstractType (usymtab_getTypeEntry (uid)));
5112}
5113
5114/*
5115** if there is an unnamed lcl-specified struct tag matching
5116** the uentryList, return its datatype. Otherwise, returns
5117** ctype_undefined.
5118*/
5119
5120ctype
5121usymtab_structFieldsType (uentryList f)
5122 /*@globals globtab@*/
5123{
5124 return (usymtab_suFieldsType (f, TRUE));
5125}
5126
5127ctype
5128usymtab_unionFieldsType (uentryList f)
5129 /*@globals globtab@*/
5130{
5131 return (usymtab_suFieldsType (f, FALSE));
5132}
5133
5134static ctype
5135usymtab_suFieldsType (uentryList f, bool isStruct)
5136 /*@globals globtab@*/
5137{
5138 int i;
5139
5140 DPRINTF (("Fields: %s", uentryList_unparse (f)));
5141
5142 if (fileloc_isSpec (g_currentloc))
5143 {
5144 return (ctype_undefined);
5145 }
5146
5147 for (i = 0; i < globtab->nentries; i++)
5148 {
5149 uentry current = globtab->entries[i];
5150
5151 if ((isStruct
5152 ? uentry_isStructTag (current) : uentry_isUnionTag (current)))
5153 {
5154 if (isFakeTag (uentry_rawName (current)))
5155 {
5156 ctype ct = uentry_getType (current);
5157
5158 DPRINTF (("Check: %s", ctype_unparse (ct)));
5159
5160 if ((isStruct ? ctype_isStruct (ct) : ctype_isUnion (ct))
5161 &&
5162 (uentry_isSpecified (current)
5163 && uentryList_equivFields (f, ctype_getFields (ct))))
5164 {
5165 return uentry_getAbstractType (current);
5166 }
5167 else
5168 {
5169 ;
5170 }
5171 }
5172 }
5173 }
5174
5175 return ctype_undefined;
5176}
5177
5178ctype
5179 usymtab_enumEnumNameListType (enumNameList f)
5180 /*@globals globtab@*/
5181{
5182 int i;
5183
5184 for (i = 0; i < globtab->nentries; i++)
5185 {
5186 uentry current = globtab->entries[i];
5187
5188 if (uentry_isEnumTag (current))
5189 {
5190 if (isFakeTag (uentry_rawName (current)))
5191 {
5192 ctype ct = uentry_getType (current);
5193
5194 if (ctype_isEnum (ct) && (enumNameList_match (f, ctype_elist (ct))))
5195 {
5196 return uentry_getType (current);
5197 }
5198 }
5199 }
5200 }
5201
5202 return ctype_undefined;
5203}
5204
5205bool
5206usymtab_exists (cstring k)
5207 /*@globals utab@*/
5208{
5209 uentry ce = usymtab_lookupSafe (k);
5210 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5211}
5212
5213bool
5214usymtab_existsReal (cstring k)
5215 /*@globals utab@*/
5216{
5217 uentry ce = usymtab_lookupSafe (k);
5218
5219 return (!(uentry_isUndefined (ce))
5220 && !(uentry_isPriv (ce))
5221 && !(uentry_isExpandedMacro (ce)));
5222}
5223
5224bool
5225 usymtab_existsGlob (cstring k)
5226 /*@globals globtab@*/
5227{
5228 uentry ce = usymtab_lookupAux (globtab, k);
5229
5230 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5231}
5232
5233# ifndef NOLCL
5234bool
5235usymtab_existsEither (cstring k)
5236 /*@globals utab@*/
5237{
5238 uentry ce = usymtab_lookupAux (utab, k);
5239
5240 return (uentry_isValid (ce));
5241}
5242
5243bool
5244 usymtab_existsGlobEither (cstring k)
5245 /*@globals globtab@*/
5246{
5247 uentry ce = usymtab_lookupAux (globtab, k);
5248
5249 return (uentry_isValid (ce));
5250}
5251# endif
5252
5253bool
5254usymtab_existsType (cstring k)
5255 /*@globals globtab@*/
5256{
5257 uentry ce = usymtab_lookupAux (globtab, k);
5258
5259 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && uentry_isDatatype (ce));
5260}
5261
5262bool
5263usymtab_existsTypeEither (cstring k)
5264 /*@globals globtab@*/
5265{
5266 uentry ce;
5267 ce = usymtab_lookupAux (globtab, k);
5268 return (uentry_isValid (ce) && uentry_isDatatype (ce));
5269}
5270
5271bool
5272usymtab_existsStructTag (cstring k) /*@globals globtab@*/
5273{
5274 cstring sname = makeStruct (k);
5275 uentry ce = usymtab_lookupAux (globtab, sname);
5276 cstring_free (sname);
5277 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5278}
5279
5280bool
5281usymtab_existsUnionTag (cstring k) /*@globals globtab@*/
5282{
5283 cstring uname = makeUnion (k);
5284 uentry ce = usymtab_lookupAux (globtab, uname);
5285
5286 cstring_free (uname);
5287
5288 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5289}
5290
5291bool
5292usymtab_existsEnumTag (cstring k) /*@globals globtab@*/
5293{
5294 cstring ename = makeEnum (k);
5295 uentry ce = usymtab_lookupAux (globtab, ename);
5296
5297 cstring_free (ename);
5298 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5299}
5300
5301# ifndef NOLCL
5302bool usymtab_existsVar (cstring k)
5303 /*@globals utab@*/
5304{
5305 uentry ce = usymtab_lookupSafe (k);
5306
5307 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && (uentry_isVar (ce)));
5308}
5309# endif
5310
5311/*
5312** destructors
5313*/
5314
5315static void
5316refTable_free (/*@only@*/ /*@null@*/ refTable x, int nentries)
5317{
5318 if (x != NULL)
5319 {
5320 int i;
5321
5322 for (i = 0; i < nentries; i++)
5323 {
5324 sfree (x[i]);
5325 }
5326
5327 sfree (x);
5328 }
5329}
5330
5331static void
5332usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab u)
5333 /*@globals globtab, utab, filetab@*/
5334{
5335 int i;
5336
5337 aliasTable_free (u->aliases);
5338
5339 refTable_free (u->reftable, u->nentries);
5340
5341 if (u == filetab || u == globtab)
5342 {
5343 for (i = 0; i < u->nentries; i++)
5344 {
5345 uentry_freeComplete (u->entries[i]);
5346 }
5347 }
5348 else
5349 {
5350 for (i = 0; i < u->nentries; i++)
5351 {
5352 uentry_free (u->entries[i]);
5353 }
5354 }
5355
5356 guardSet_free (u->guards);
5357 sfree (u->entries);
5358
5359 if (u != globtab
5360 && u != utab
5361 && u != filetab)
5362 {
5363 llassert (!cstringTable_isDefined (u->htable));
5364 sfree (u);
5365 }
5366
5367/*@-mustfree@*/
5368} /*@=mustfree@*/
5369
5370static void
5371usymtab_freeAux (/*@only@*/ usymtab u)
5372 /*@globals globtab, utab, filetab@*/
5373 /*@modifies u@*/
5374{
5375 while (u != GLOBAL_ENV)
5376 {
5377 usymtab t = u->env;
5378 usymtab_freeLevel (u);
5379 u = t;
5380 /*@-branchstate@*/
5381 }
5382 /*@=branchstate@*/
5383}
5384
5385void usymtab_free ()
5386 /*@globals killed utab, globtab, filetab@*/
5387 /*@modifies utab@*/
5388{
5389 dbgfree = TRUE;
5390 usymtab_freeAux (utab);
5391}
5392
5393static int usymtab_lexicalLevel (void) /*@globals utab@*/
5394{
5395 return (utab->lexlevel);
5396}
5397
5398bool usymtab_inGlobalScope () /*@globals utab, globtab@*/
5399{
5400 return (utab == globtab);
5401}
5402
5403bool usymtab_inFileScope () /*@globals utab@*/
5404{
5405 return (utab->lexlevel == fileScope);
5406}
5407
5408bool usymtab_inFunctionScope () /*@globals utab@*/
5409{
5410 return (utab->lexlevel == functionScope);
5411}
5412
5413# ifndef NOLCL
5414void
5415usymtab_replaceEntry (uentry s)
5416 /*@globals utab, globtab@*/
5417 /*@modifies utab, s@*/
5418{
5419 usymtab_replaceEntryAux (utab, s);
5420}
5421# endif
5422
5423bool
5424usymtab_matchForwardStruct (usymId u1, usymId u2)
5425 /*@globals globtab@*/
5426{
5427 uentry ue1 = usymtab_getTypeEntry (u1);
5428 uentry ue2 = usymtab_getTypeEntry (u2);
5429
5430 if (uentry_isAnyTag (ue2))
5431 {
5432 ctype reptype = uentry_getType (ue1);
5433
5434 if (ctype_isPointer (reptype))
5435 {
5436 ctype repbase = ctype_getBaseType (reptype);
5437
5438 if (ctype_isUA (repbase))
5439 {
5440 typeId rtuid = ctype_typeId (repbase);
5441
5442 if (u2 == rtuid) return TRUE;
5443
5444 if (usymId_isValid (rtuid))
5445 {
5446 reptype = uentry_getType (usymtab_getTypeEntry (rtuid));
5447
5448 return (ctype_isUA (reptype) && (u2 == (ctype_typeId (reptype))));
5449 }
5450 }
5451 }
5452 }
5453
5454 return FALSE;
5455}
5456
5457void usymtab_addGuards (guardSet guards)
5458 /*@modifies utab@*/
5459{
5460 utab->guards = guardSet_union (utab->guards, guards);
5461 }
5462
5463static bool usymtab_isGuardedAux (sRef s)
5464 /*@globals utab@*/
5465{
5466 usymtab tab = utab;
5467 sRef base = sRef_getRootBase (s);
5468 int lowlevel = paramsScope;
5469 int baselevel = sRef_lexLevel (base);
5470
5471 if (sRef_isCvar (base))
5472 {
5473 lowlevel = baselevel;
5474 if (lowlevel < paramsScope) lowlevel = paramsScope;
5475 }
5476
5477 while (tab->lexlevel >= lowlevel)
5478 {
5479 DPRINTF (("Is guarded? [%s] %s",
5480 guardSet_unparse (tab->guards),
5481 sRef_unparseFull (s)));
5482
5483 if (guardSet_isGuarded (tab->guards, s))
5484 {
5485 /*
5486 if (!sRef_definitelyNull (s))
5487 {
5488 sRef_setNotNull (s, fileloc_undefined);
5489 }
5490 */
5491 return TRUE;
5492 }
5493
5494 tab = usymtab_dropEnv (tab);
5495 }
5496
5497 return FALSE;
5498}
5499
5500void usymtab_unguard (sRef s) /*@modifies utab@*/
5501{
5502 usymtab tab = utab;
5503 sRef base = sRef_getRootBase (s);
5504 int lowlevel = paramsScope;
5505 int baselevel = sRef_lexLevel (base);
5506
5507 if (sRef_isCvar (base))
5508 {
5509 lowlevel = baselevel;
5510 if (lowlevel < paramsScope) lowlevel = paramsScope;
5511 }
5512
5513 while (tab->lexlevel >= lowlevel)
5514 {
5515 if (guardSet_isGuarded (tab->guards, s))
5516 {
5517 guardSet_delete (tab->guards, s);
5518 }
5519
5520 tab = usymtab_dropEnv (tab);
5521 }
5522}
5523
5524bool usymtab_isGuarded (sRef s)
5525{
5526 DPRINTF (("Is guarded? %s", sRef_unparseFull (s)));
5527 return (sRef_aliasCompleteSimplePred (usymtab_isGuardedAux, s));
5528}
5529
5530bool usymtab_isDefinitelyNull (sRef s)
5531{
5532 return (sRef_aliasCheckSimplePred (usymtab_isDefinitelyNullAux, s));
5533}
5534
5535bool usymtab_isDefinitelyNullDeep (sRef s)
5536{
5537 return (sRef_deepPred (usymtab_isDefinitelyNull, s));
5538}
5539
5540static bool usymtab_isDefinitelyNullAux (sRef s)
5541 /*@globals utab@*/
5542{
5543 usymtab tab = utab;
5544 sRef base = sRef_getRootBase (s);
5545 int lowlevel = paramsScope;
5546
5547 if (sRef_isCvar (base))
5548 {
5549 lowlevel = sRef_lexLevel (base);
5550 if (lowlevel < paramsScope) lowlevel = paramsScope;
5551 }
5552
5553 while (tab->lexlevel >= lowlevel)
5554 {
5555 if (guardSet_mustBeNull (tab->guards, s))
5556 {
5557 return TRUE;
5558 }
5559
5560 while (tab->kind == US_CBRANCH)
5561 {
5562 tab = tab->env;
5563 }
5564
5565 llassert (usymtab_isDefined (tab));
5566
5567 if (tab->kind == US_FBRANCH)
5568 {
5569 tab = tab->env;
5570 llassert (tab->kind == US_TBRANCH);
5571 }
5572
5573 tab = tab->env;
5574 }
5575
5576 return FALSE;
5577}
5578
5579void
5580usymtab_printGuards ()
5581 /*@globals utab, globtab@*/
5582{
5583 usymtab ttab = utab;
5584
5585 while (ttab != globtab)
5586 {
5587 llmsg (message ("Guards [%d]: %q", ttab->lexlevel,
5588 guardSet_unparse (ttab->guards)));
5589 ttab = ttab->env;
5590 }
5591}
5592
5593void
5594usymtab_displayAllUses ()
5595 /*@globals utab, globtab@*/
5596{
5597 usymtab copy;
5598
5599 /* only in top scope */
5600 llassert (utab == globtab);
5601
5602 /* need a copy, so order is not messed up by sort! */
5603 copy = usymtab_shallowCopy (globtab);
5604
5605 qsort (copy->entries, (size_t)copy->nentries,
5606 sizeof (*copy->entries), (int (*)(const void *, const void *)) uentry_xcompareuses);
5607
5608 usymtab_entries (copy, ue)
5609 {
5610 if (uentry_isValid (ue) && !uentry_isGlobalMarker (ue))
5611 {
5612 filelocList uses = uentry_getUses (ue);
5613 int size = filelocList_realSize (uses);
5614
5615 if (fileloc_isDefined (uentry_whereDefined (ue))
5616 && !fileloc_isLib (uentry_whereDefined (ue))
5617 && (size > 0))
5618 {
5619 llmsg (message ("%q (%q), %d use%&:\n %q",
5620 uentry_getName (ue),
5621 fileloc_unparse (uentry_whereDefined (ue)),
5622 size, filelocList_unparseUses (uses)));
5623 }
5624 }
5625 } end_usymtab_entries;
5626
5627 usymtab_shallowFree (copy);
5628}
5629
5630static /*@dependent@*/ /*@exposed@*/ usymtab
5631usymtab_getFileTab ()
5632 /*@globals filetab@*/
5633{
5634 llassert (filetab != NULL);
5635
5636 return filetab;
5637}
5638
5639/*@only@*/ cstring
5640usymtab_unparseStack ()
5641 /*@globals utab@*/
5642{
5643 return (usymtab_unparseStackTab (utab));
5644}
5645
5646static /*@only@*/ cstring
5647usymtab_unparseStackTab (usymtab t)
5648{
5649 bool firstOne = TRUE;
5650 cstring ret = cstring_makeLiteral ("[");
5651
5652 while (t != GLOBAL_ENV)
5653 {
5654 if (firstOne)
5655 {
5656 ret = message ("%q %q", ret, usymtab_typeName (t));
5657 firstOne = FALSE;
5658 }
5659 else
5660 {
5661 ret = message ("%q, %q", ret, usymtab_typeName (t));
5662 }
5663 t = t->env;
5664 }
5665
5666 ret = message ("%q ]", ret);
5667 return ret;
5668}
5669
5670static /*@only@*/ cstring
5671usymtab_typeName (/*@notnull@*/ usymtab t)
5672{
5673 switch (t->kind)
5674 {
5675 case US_GLOBAL: return cstring_makeLiteral ("global");
5676 case US_NORMAL: return cstring_makeLiteral ("normal");
5677 case US_TBRANCH: return cstring_makeLiteral ("true");
5678 case US_FBRANCH: return cstring_makeLiteral ("false");
5679 case US_CBRANCH: return cstring_makeLiteral ("case");
5680 case US_SWITCH: return cstring_makeLiteral ("switch");
5681 }
5682
5683 BADEXIT;
5684}
5685
5686void usymtab_addMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5687 /*@modifies utab@*/
5688{
5689 if (!sRef_similar (s, al))
5690 {
5691 usymtab_addForceMustAlias (s, al);
5692 }
5693}
5694
5695/*
5696** Same as usymtab_addMustAlias, except does not check sRef_isSimilar.
5697*/
5698
5699void usymtab_addForceMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5700 /*@modifies utab@*/
5701{
5702 /* evans 2002-03-3: was sRef_isMeaningful -- but we need to keep aliases for new storage also! */
5703 if (sRef_isMeaningful (s)
5704 && sRef_isMeaningful (al)
5705 && !(sRef_isConst (s) || sRef_isConst (al))
5706 && !(sRef_isAddress (al) && sRef_isDirectParam (sRef_getBase (al))))
5707 {
5708 utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
5709 DPRINTF (("Must alias: %s", aliasTable_unparse (utab->aliases)));
5710
5711 /*
5712 ** for local variable, aliasing is symmetric
5713 */
5714
5715 if (sRef_isLocalVar (s) && sRef_isLocalVar (al))
5716 {
5717 utab->aliases = aliasTable_addMustAlias (utab->aliases, al, s);
5718 }
5719 }
5720 else
5721 {
5722 DPRINTF (("Not aliasing! %s / %s", sRef_unparseFull (s), sRef_unparseFull (al)));
5723 DPRINTF (("meaningful: %d %d", sRef_isMeaningful (s), sRef_isMeaningful (al)));
5724 }
5725}
5726
5727void usymtab_addReallyForceMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5728 /*@modifies utab@*/
5729{
5730 utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
5731}
5732
5733void usymtab_clearAlias (sRef s)
5734 /*@modifies utab, s@*/
5735{
5736
5737 aliasTable_clearAliases (utab->aliases, s);
5738}
5739
5740sRefSet usymtab_allAliases (sRef s)
5741 /*@globals utab@*/
5742{
5743 if (sRef_isSomewhatMeaningful (s))
5744 {
5745 sRefSet ret;
5746
5747 ret = sRefSet_unionFree (aliasTable_aliasedBy (utab->aliases, s),
5748 aliasTable_canAlias (utab->aliases, s));
5749 return (ret);
5750 }
5751 else
5752 {
5753 DPRINTF (("NOT A MEANINGFUL SREF!"));
5754 return sRefSet_undefined;
5755 }
5756}
5757
5758/*@only@*/ sRefSet usymtab_canAlias (sRef s)
5759 /*@globals utab@*/
5760{
5761 if (sRef_isSomewhatMeaningful (s))
5762 {
5763 sRefSet res = aliasTable_canAlias (utab->aliases, s);
5764 return res;
5765 }
5766
5767 return sRefSet_undefined;
5768}
5769
5770/*@only@*/ sRefSet usymtab_aliasedBy (sRef s)
5771 /*@globals utab@*/
5772{
5773 return (aliasTable_aliasedBy (utab->aliases, s));
5774}
5775
5776/*@only@*/ cstring usymtab_unparseAliases ()
5777 /*@globals utab@*/
5778{
5779 return (aliasTable_unparse (utab->aliases));
5780}
5781
5782/*
5783** Debugging routines:
5784** okay to leak storage here, only for debugging
5785*/
5786
5787/*@-mustfree@*/
5788
5789void
5790usymtab_printOut (void)
5791 /*@globals utab@*/
5792{
5793 int i;
5794 usymtab s = utab;
5795 int depth = 0;
5796 char *ind = mstring_copy (" ");
5797
5798 fprintf (g_warningstream, "<<< [symbol table] >>>\n");
5799
5800 while (s != GLOBAL_ENV && s->env != GLOBAL_ENV)
5801 {
5802 cstring tname = usymtab_typeName (s);
5803
5804 if (depth < 5)
5805 {
5806 ind[depth * 3 + 1] = '\0';
5807 }
5808
5809 fprintf (g_warningstream, "level: %d (%s)\n", s->lexlevel,
5810 cstring_toCharsSafe (tname));
5811
5812 cstring_free (tname);
5813
5814 for (i = 0; i < s->nentries; i++)
5815 {
5816 cstring us = uentry_unparseFull (s->entries[i]);
5817 fprintf (g_warningstream, "%s\n", cstring_toCharsSafe (us));
5818 cstring_free (us);
5819 }
5820
5821 if (s->reftable != NULL && s->nentries > 0)
5822 {
5823 fprintf (g_warningstream, "\t<< Ref table >>\n");
5824
5825 for (i = 0; i < s->nentries; i++)
5826 {
5827 fprintf (g_warningstream, "\t%s %3d: %d, %d\n", ind, i,
5828 s->reftable[i]->level,
5829 s->reftable[i]->index);
5830 }
5831 }
5832
5833 ind[depth * 3 + 1] = ' ';
5834 depth++;
5835 s = s->env;
5836 }
5837 fprintf (g_warningstream, "<<< end usymtab >>>\n");
5838 mstring_free (ind);
5839 return;
5840}
5841
5842void
5843usymtab_printTypes ()
5844 /*@globals globtab@*/
5845{
5846 usymtab_printAllAux (globtab);
5847}
5848
5849void
5850usymtab_printAll (void)
5851 /*@globals utab@*/
5852{
5853 usymtab_printAllAux (utab);
5854}
5855
5856static void
5857usymtab_printAllAux (usymtab s)
5858 /*@modifies g_warningstream@*/
5859{
5860 int i;
5861 int depth = 0;
5862 char *ind = mstring_copy (" ");
5863
5864 printf ("[[[ usymtab ]]]");
5865
5866 while (s != GLOBAL_ENV)
5867 {
5868 if (depth < 5)
5869 ind[depth * 3 + 1] = '\0';
5870
5871 if (s->env == GLOBAL_ENV)
5872 {
5873 int looplow;
5874
5875 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5876 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5877 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5878
5879 looplow = 0;
5880
5881 for (i = looplow; i < s->nentries; i++)
5882 {
5883 printf ("%s%3d. %s\n", ind, i,
5884 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5885 }
5886 }
5887 else
5888 {
5889 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5890 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5891 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5892
5893 for (i = 0; i < s->nentries; i++)
5894 {
5895 printf ("%s%3d %s\n", ind, i,
5896 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5897 }
5898 }
5899
5900 ind[depth * 3 + 1] = ' ';
5901 depth++;
5902 s = s->env;
5903 }
5904 printf ("----------\n");
5905}
5906
5907void
5908usymtab_printComplete ()
5909 /*@globals utab@*/
5910{
5911 int i;
5912 int depth = 0;
5913 char *ind = mstring_copy (" ");
5914 usymtab s = utab;
5915
5916 while (s != GLOBAL_ENV)
5917 {
5918 if (depth < 5)
5919 {
5920 ind[depth * 3 + 1] = '\0';
5921 }
5922
5923 if (s->env == GLOBAL_ENV)
5924 {
5925 int looplow;
5926
5927 printf ("level: %d\n", s->lexlevel);
5928
5929 looplow = 0;
5930
5931 for (i = looplow; i < s->nentries; i++)
5932 {
5933 printf ("%s%3d %s\n", ind, i,
5934 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5935 }
5936 }
5937 else
5938 {
5939 printf ("level: %d\n", s->lexlevel);
5940 for (i = 0; i < s->nentries; i++)
5941 {
5942 printf ("%s%3d %s\n", ind, i,
5943 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5944 }
5945 }
5946
5947 ind[depth * 3 + 1] = ' ';
5948 depth++;
5949 s = s->env;
5950 }
5951
5952 printf ("----------\n");
5953 mstring_free (ind);
5954}
5955
5956# ifdef S_SPLINT_S
5957static /*@only@*/ cstring /*@unused@*/
5958usymtab_unparseLocalAux (/*@notnull@*/ usymtab s)
5959{
5960 cstring c = message ("lexlevel: %d\n", s->lexlevel);
5961 int i;
5962
5963 for (i = 0; i < s->nentries; i++)
5964 {
5965 c = message ("%q\n%q", c, uentry_unparseFull (s->entries[i]));
5966 }
5967
5968 c = message ("%q\n=========", c);
5969 return (c);
5970}
5971
5972static cstring /*@unused@*/ /*@only@*/
5973usymtab_unparseLocalList (/*@notnull@*/ usymtab s)
5974{
5975 cstring c = message ("[%d/%s/%s] ", s->lexlevel,
5976 bool_unparse (s->mustBreak),
5977 exitkind_unparse (s->exitCode));
5978 int i;
5979
5980 for (i = 0; i < s->nentries; i++)
5981 {
5982 sRef sr = uentry_getSref (s->entries[i]);
5983
5984 if (i == 0)
5985 {
5986 c = message ("%q: %q [%b]", c, uentry_getName (s->entries[i]),
5987 sRef_isStateDefined (sr));
5988 }
5989 else
5990 {
5991 c = message ("%q, %q [%b]", c, uentry_getName (s->entries[i]),
5992 sRef_isStateDefined (sr));
5993 }
5994
5995 }
5996
5997 return (c);
5998}
5999# endif
6000
6001void
6002usymtab_printLocal (void)
6003 /*@globals utab@*/
6004{
6005 int i;
6006 usymtab s = utab;
6007
6008 printf ("lexlevel: %d\n", s->lexlevel);
6009
6010 for (i = 0; i < s->nentries; i++)
6011 {
6012 printf ("%s\n", cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
6013 }
6014
6015 while (s->lexlevel > 1)
6016 {
6017 s = s->env;
6018 }
6019
6020 llassert (usymtab_isDefined (s));
6021
6022 printf ("Params:\n");
6023
6024 for (i = 0; i < s->nentries; i++)
6025 {
6026 printf ("%d: %s\n", i,
6027 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
6028 }
6029}
6030/*@=mustfree@*/
6031
6032static bool checkDistinctExternalName (uentry e)
6033 /*@globals globtab@*/
6034 /*@modifies *g_warningstream@*/
6035{
6036 size_t checklen = size_fromInt (context_getValue (FLG_EXTERNALNAMELEN));
6037 bool ignorecase = context_getFlag (FLG_EXTERNALNAMECASEINSENSITIVE);
6038 bool gotone = FALSE;
6039 bool extras = FALSE;
6040 bool hasError = FALSE;
6041 cstring name = uentry_rawName (e);
6042 usymtab st = globtab;
6043
6044 if (checklen == 0)
6045 {
6046 ;
6047 }
6048 else
6049 {
6050 if (uentry_isAnyTag (e))
6051 {
6052 checklen++; /* the tag marker doesn't count */
6053 }
6054 }
6055
6056 usymtab_entries (st, oe)
6057 {
6058 if (uentry_sameObject (oe, e))
6059 {
6060 continue;
6061 }
6062
6063 if (checklen == 0)
6064 {
6065 if (cstring_equalCaseInsensitive (uentry_rawName (oe), name))
6066 {
6067 if (gotone)
6068 {
6069 extras = TRUE;
6070 break;
6071 }
6072
6073 if (optgenerror
6074 (FLG_DISTINCTEXTERNALNAMES,
6075 message
6076 ("External identifier %q is not distinguishable from %q "
6077 "because alphabetical case is ignored",
6078 uentry_getName (e),
6079 uentry_getName (oe)),
6080 uentry_whereLast (e)))
6081 {
6082 uentry_showWhereAny (oe);
6083 uentry_setHasNameError (oe);
6084 gotone = TRUE;
6085 }
6086 }
6087 }
6088 else
6089 {
6090 if (ignorecase)
6091 {
6092 if (cstring_equalLenCaseInsensitive (uentry_rawName (oe),
6093 name, checklen))
6094 {
6095 if (gotone)
6096 {
6097 extras = TRUE;
6098 break;
6099 }
6100
6101 if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6102 {
6103 if (optgenerror
6104 (FLG_DISTINCTEXTERNALNAMES,
6105 /*@-sefparams@*/
6106 message
6107 ("External identifier %q is not distinguishable from %q "
6108 "in the first %d characters (%q)",
6109 uentry_getName (e),
6110 uentry_getName (oe),
6111 size_toInt (checklen),
6112 cstring_clip (uentry_getName (e), checklen)),
6113 /*@=sefparams@*/
6114 uentry_whereLast (e)))
6115 {
6116 uentry_showWhereAny (oe);
6117 uentry_setHasNameError (oe);
6118 gotone = TRUE;
6119 }
6120 }
6121 else
6122 {
6123 if (gotone)
6124 {
6125 extras = TRUE;
6126 break;
6127 }
6128
6129 if (optgenerror
6130 (FLG_DISTINCTEXTERNALNAMES,
6131 message
6132 ("External identifier %q is not distinguishable from %q "
6133 "in the first %d characters because alphabetical case "
6134 "is ignored",
6135 uentry_getName (e),
6136 uentry_getName (oe),
6137 size_toInt (checklen)),
6138 uentry_whereLast (e)))
6139 {
6140 uentry_showWhereAny (oe);
6141 uentry_setHasNameError (oe);
6142 gotone = TRUE;
6143 }
6144 }
6145 }
6146 }
6147 else if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6148 {
6149 if (gotone)
6150 {
6151 extras = TRUE;
6152 break;
6153 }
6154
6155 if (optgenerror
6156 (FLG_DISTINCTEXTERNALNAMES,
6157 /*@-sefparams@*/
6158 message
6159 ("External identifier %q is not distinguishable from %q "
6160 "in the first %d characters (%q)",
6161 uentry_getName (e),
6162 uentry_getName (oe),
6163 size_toInt (checklen),
6164 cstring_clip (uentry_getName (e), checklen)),
6165 /*@=sefparams@*/
6166 uentry_whereLast (e)))
6167 {
6168 uentry_showWhereAny (oe);
6169 uentry_setHasNameError (oe);
6170 gotone = TRUE;
6171 }
6172 }
6173 else
6174 {
6175 ; /* okay */
6176 }
6177 }
6178 } end_usymtab_entries ;
6179
6180 hasError = gotone;
6181
6182 if (extras)
6183 {
6184 llgenindentmsgnoloc
6185 (cstring_makeLiteral ("One or more additional "
6186 "indistinguishable external "
6187 "names not reported"));
6188 }
6189
6190 return hasError;
6191}
6192
6193static bool checkDistinctInternalName (uentry e)
6194 /*@globals utab@*/
6195 /*@modifies *g_warningstream@*/
6196{
6197 usymtab ttab = utab;
6198 cstring name = uentry_rawName (e);
6199 size_t numchars = size_fromInt (context_getValue (FLG_INTERNALNAMELEN));
6200 bool caseinsensitive = context_getFlag (FLG_INTERNALNAMECASEINSENSITIVE);
6201 bool lookalike = context_getFlag (FLG_INTERNALNAMELOOKALIKE);
6202
6203 if (uentry_isAnyTag (e) && (numchars != 0))
6204 {
6205 numchars++; /* the tag marker doesn't count */
6206 }
6207
6208 while (usymtab_isDefined (ttab))
6209 {
6210 usymtab_entries (ttab, oe)
6211 {
6212 if (uentry_sameObject (oe, e))
6213 {
6214 /*@innercontinue@*/ continue;
6215 }
6216
6217 switch (cstring_genericEqual
6218 (name, uentry_rawName (oe),
6219 numchars, caseinsensitive, lookalike))
6220 {
6221 case CGE_DISTINCT: /* okay */
6222 /*@switchbreak@*/
6223 break;
6224 case CGE_SAME:
6225 if (cstring_equal (name, uentry_rawName (oe)))
6226 {
6227 ; /* got a shadow error */
6228 }
6229 else
6230 {
6231 if (optgenerror
6232 (FLG_DISTINCTINTERNALNAMES,
6233 /*@-sefparams@*/
6234 message
6235 ("Internal identifier %q is not distinguishable from %q "
6236 "in the first %d characters (%q)",
6237 uentry_getName (e),
6238 uentry_getName (oe),
6239 size_toInt (numchars),
6240 cstring_clip (uentry_getName (e), numchars)),
6241 /*@=sefparams@*/
6242 uentry_whereLast (e)))
6243 {
6244 uentry_showWhereAny (oe);
6245 uentry_setHasNameError (oe);
6246 return TRUE;
6247 }
6248 }
6249 /*@switchbreak@*/
6250 break;
6251 case CGE_CASE:
6252 if (numchars == 0 || (cstring_length (name) <= numchars))
6253 {
6254 if (optgenerror
6255 (FLG_DISTINCTINTERNALNAMES,
6256 message
6257 ("Internal identifier %q is not distinguishable from %q "
6258 "without case sensitivity",
6259 uentry_getName (e),
6260 uentry_getName (oe)),
6261 uentry_whereLast (e)))
6262 {
6263 uentry_showWhereAny (oe);
6264 uentry_setHasNameError (oe);
6265 return TRUE;
6266 }
6267 }
6268 else
6269 {
6270 if (optgenerror
6271 (FLG_DISTINCTINTERNALNAMES,
6272 message
6273 ("Internal identifier %q is not distinguishable from %q "
6274 "in the first %d characters without case sensitivity",
6275 uentry_getName (e),
6276 uentry_getName (oe),
6277 size_toInt (numchars)),
6278 uentry_whereLast (e)))
6279 {
6280 uentry_showWhereAny (oe);
6281 uentry_setHasNameError (oe);
6282 return TRUE;
6283 }
6284 }
6285 /*@switchbreak@*/
6286 break;
6287 case CGE_LOOKALIKE:
6288 if (numchars == 0
6289 || (cstring_length (name) <= numchars))
6290 {
6291 if (optgenerror
6292 (FLG_DISTINCTINTERNALNAMES,
6293 message
6294 ("Internal identifier %q is not distinguishable from %q "
6295 "except by lookalike characters",
6296 uentry_getName (e),
6297 uentry_getName (oe)),
6298 uentry_whereLast (e)))
6299 {
6300 uentry_showWhereAny (oe);
6301 uentry_setHasNameError (oe);
6302 return TRUE;
6303 }
6304 }
6305 else
6306 {
6307 if (optgenerror
6308 (FLG_DISTINCTINTERNALNAMES,
6309 message
6310 ("Internal identifier %q is not distinguishable from %q "
6311 "in the first %d characters except by lookalike characters",
6312 uentry_getName (e),
6313 uentry_getName (oe),
6314 size_toInt (numchars)),
6315 uentry_whereLast (e)))
6316 {
6317 uentry_showWhereAny (oe);
6318 uentry_setHasNameError (oe);
6319 return TRUE;
6320 }
6321 }
6322 }
6323 } end_usymtab_entries ;
6324
6325 ttab = ttab->env;
6326 }
6327
6328 return FALSE;
6329}
6330
6331void usymtab_checkDistinctName (uentry e, int scope)
6332 /*@globals utab, globtab@*/
6333{
6334 bool hasError = FALSE;
6335 fileloc where = uentry_whereLast (e);
6336
6337 if (!fileloc_isPreproc (where) && !fileloc_isBuiltin (where))
6338 {
6339 if (scope == globScope)
6340 {
6341 if (context_getFlag (FLG_DISTINCTEXTERNALNAMES))
6342 {
6343 hasError = checkDistinctExternalName (e);
6344 }
6345 }
6346
6347 if (!hasError && context_getFlag (FLG_DISTINCTINTERNALNAMES))
6348 {
6349 hasError = checkDistinctInternalName (e);
6350 }
6351 }
6352
6353 if (hasError)
6354 {
6355 uentry_setHasNameError (e);
6356 }
6357}
6358
6359/*@exposed@*/ sRef usymtab_lookupGlobalMarker (void) /*@globals utab@*/
6360{
6361 uentry ue;
6362
6363 ue = usymtab_lookupAux (utab, GLOBAL_MARKER_NAME);
6364 llassert (uentry_isValid (ue));
6365
6366 return uentry_getSref (ue);
6367}
6368
6369
6370# ifdef DEBUGSPLINT
6371/*
6372** For debugging only
6373*/
6374
6375void
6376usymtab_checkAllValid () /*@globals utab@*/
6377{
6378 usymtab tab = utab;
6379
6380 while (tab != GLOBAL_ENV)
6381 {
6382 int i;
6383
6384 for (i = 0; i < utab->nentries; i++)
6385 {
6386 uentry e = utab->entries[i];
6387
6388 uentry_checkValid (e);
6389 }
6390
6391 aliasTable_checkValid (tab->aliases);
6392 tab = tab->env;
6393 }
6394}
6395# endif
6396
6397
6398
6399
6400
6401
This page took 0.147796 seconds and 5 git commands to generate.