2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2001 University of Virginia,
4 ** Massachusetts Institute of Technology
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.
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.
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.
20 ** For information on lclint: lclint-request@cs.virginia.edu
21 ** To report a bug: lclint-bug@cs.virginia.edu
22 ** For more information: http://www.splint.org
27 ** Lexically scoped symbol table.
29 ** Unlike a normal symbol table, this table splits to reflect branches.
31 ** This is necessary since symbol table entries also reflect
32 ** some state information, like initialization, that may be
33 ** different on different branches.
35 ** For each control structure we split:
37 ** { } - a normal scope (no control) US_NORMAL
39 ** if <pred> { } - US_TBRANCH true branch
40 ** while <pred> { } US_FBRANCH else branch
42 ** switch <pred> { } - US_SWITCH
44 ** case x: - case scope US_CBRANCH
45 ** Should be kept in a separate table, because of
49 # include "lclintMacros.nf"
51 # include "structNames.h"
52 # include "exprChecks.h"
53 # include "transferChecks.h"
56 ** Keep track of type definitions inside a function.
59 static uentryList functypes = uentryList_undefined;
61 static bool dbgfree = FALSE;
62 static bool dbgload = TRUE;
67 ** Hack to prevent shadow errors from appearing when function parameters
68 ** are entered into a new scope.
71 static bool noshadowerror = FALSE;
74 ** Constraint: static variables can live in 1 or > 2.
76 ** except for tags. All tags must be at the global level.
77 ** Static tags are handled in a kludgey way.
81 ** utab is the universal symbol table
82 ** globtab is the global environment of utab
83 ** oldtab is needed for conversions in dumping (after sorting the table)
85 ** there can be only one usymtab!
88 static /*@checkedstrict@*/ /*@owned@*/ /*@notnull@*/ usymtab utab;
90 /* Reachable environments from from utab */
91 static /*@checkedstrict@*/ /*@notnull@*/ /*@dependent@*/ usymtab globtab;
92 static /*@checkedstrict@*/ /*@dependent@*/ usymtab filetab;
94 /* Used for sorting for dumpage. */
95 static /*@checkedstrict@*/ /*@owned@*/ usymtab oldtab;
97 static int usymtab_lexicalLevel (void) /*@globals utab@*/ ;
98 static bool usymtab_isAltDefinitelyNull (sRef p_s) /*@globals utab@*/ ;
99 static void refTable_free (/*@only@*/ /*@null@*/ refTable p_x, int p_nentries);
100 static ctype usymtab_suFieldsType (uentryList p_f, bool p_isStruct) /*@globals globtab@*/ ;
102 extern int usymtab_getCurrentDepth (void) /*@globals utab@*/
104 return utab->lexlevel;
108 usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab p_u)
109 /*@globals globtab, utab, filetab@*/ /*@modifies p_u@*/ ;
111 static bool usymtab_isDefinitelyNullAux (sRef p_s) /*@globals utab@*/ ;
112 static /*@only@*/ cstring usymtab_unparseStackTab (usymtab p_t);
113 static /*@exposed@*/ /*@dependent@*/ uentry
114 usymtab_getRefTab (/*@notnull@*/ usymtab p_u, int p_level, usymId p_index);
117 /* These are not used anymore... */
118 static /*@unused@*/ /*@only@*/ cstring
119 usymtab_unparseLocalAux (/*@notnull@*/ usymtab p_s);
120 static /*@unused@*/ /*@only@*/ cstring
121 usymtab_unparseLocalList (/*@notnull@*/ usymtab p_s);
124 static /*@only@*/ cstring usymtab_typeName (/*@notnull@*/ usymtab p_t);
125 static void usymtab_handleParams (void)
126 /*@globals utab, globtab, filetab@*/
127 /*@modifies utab@*/ ;
129 static /*@exposed@*/ /*@dependent@*/ uentry
130 usymtab_addRefEntry (/*@notnull@*/ usymtab p_s, cstring p_k);
131 static /*@exposed@*/ /*@dependent@*/ usymtab
132 usymtab_dropEnv (/*@notnull@*/ usymtab p_s);
133 static /*@exposed@*/ /*@dependent@*/ uentry
134 usymtab_getRefNoisy (/*@notnull@*/ usymtab p_s, int p_level, usymId p_index);
136 static /*@exposed@*/ /*@dependent@*/ uentry
137 usymtab_lookupQuietAux (usymtab p_s, cstring p_k, bool p_noalt);
139 static /*@exposed@*/ /*@dependent@*/ uentry
140 usymtab_lookupQuiet (usymtab p_s, cstring p_k);
142 static /*@exposed@*/ /*@dependent@*/ uentry
143 usymtab_lookupQuietNoAlt (usymtab p_s, cstring p_k);
145 static void usymtab_printAllAux (usymtab p_s) /*@modifies g_msgstream@*/ ;
146 static int usymtab_getIndex (/*@notnull@*/ usymtab p_s, cstring p_k);
147 static /*@exposed@*/ uentry usymtab_fetchIndex (/*@notnull@*/ usymtab p_s, int p_i);
148 static /*@exposed@*/ uentry
149 usymtab_lookupAux (usymtab p_s, cstring p_k);
150 static /*@exposed@*/ /*@dependent@*/ /*@notnull@*/ usymtab
151 usymtab_getFileTab (void) /*@globals filetab@*/ ;
152 static int refTable_lookup (/*@notnull@*/ usymtab p_ut, int p_level, int p_index);
153 static bool usymtab_mustBreak (usymtab p_s);
154 static bool usymtab_mustEscape (usymtab p_s);
156 static void recordFunctionType (uentry ue)
158 llassert (uentry_isDatatype (ue) || uentry_isAnyTag (ue)
159 || uentry_isEnumConstant (ue));
160 DPRINTF (("Function type: %s", uentry_unparseFull (ue)));
162 functypes = uentryList_add (functypes, ue);
166 static void clearFunctionTypes (void)
167 /*@modifies globtab@*/
169 uentryList_elements (functypes, el)
171 if (cstring_isDefined (uentry_rawName (el)))
173 if (cstringTable_isDefined (globtab->htable))
175 cstringTable_remove (globtab->htable, uentry_rawName (el));
178 uentry_setName (el, cstring_undefined);
182 llassert (uentry_isValid (el));
183 el->sref = sRef_undefined;
184 /*@noaccess uentry@*/
185 } end_uentryList_elements ;
187 uentryList_clear (functypes);
190 static /*@falsenull@*/ bool usymtab_isBranch (usymtab u)
192 return (usymtab_isDefined (u) &&
193 (u->kind == US_TBRANCH || u->kind == US_FBRANCH
194 || u->kind == US_CBRANCH || u->kind == US_SWITCH));
197 static bool usymtab_mustBreak (usymtab s)
199 llassert (s != GLOBAL_ENV);
200 return (s->mustBreak);
203 static bool usymtab_mustEscape (usymtab s)
205 llassert (s != GLOBAL_ENV);
206 return (exitkind_mustEscape (s->exitCode));
209 void usymtab_setMustBreak ()
212 llassert (utab != GLOBAL_ENV);
213 utab->mustBreak = TRUE;
216 void usymtab_setExitCode (exitkind ex)
219 llassert (utab != GLOBAL_ENV);
223 if (exitkind_mustEscape (ex))
225 utab->mustBreak = TRUE;
229 bool usymtab_isAltDefinitelyNullDeep (sRef s)
231 return (sRef_deepPred (usymtab_isAltDefinitelyNull, s));
234 static bool usymtab_isAltDefinitelyNull (sRef s)
242 llassert (utab->env != NULL);
244 /*@-mods@*/ /* These modifications are cancelled. */
245 utab->guards = utab->env->guards;
246 utab->env->guards = t;
249 llassert (usymtab_isDefined (utab));
250 res = usymtab_isDefinitelyNull (s);
253 ** This reports a spurious error. It is okay, because of
254 ** the nesting relationship of usymtab environments.
257 /*@-mods@*/ /* Cancelling modifications. */
258 /*@i1@*/ utab->env->guards = utab->guards;
259 /*@i1@*/ utab->guards = t;
265 static /*@notnull@*/ /*@special@*/ usymtab
266 usymtab_create (uskind kind, /*@keep@*/ usymtab env, bool nextlevel)
268 /*@post:isnull result->htable, result->guards, result->aliases@*/
270 usymtab t = (usymtab) dmalloc (sizeof (*t));
273 t->nspace = CBASESIZE;
274 t->entries = (uentry *) dmalloc (sizeof (*t->entries) * CBASESIZE);
276 /* We only use a reftable for branch-level symbol tables.
279 t->reftable = (nextlevel
281 : (refentry *) dmalloc (sizeof (*t->reftable) * CBASESIZE));
284 t->lexlevel = (env == GLOBAL_ENV ? 0 : env->lexlevel) + (nextlevel ? 1 : 0);
289 t->guards = guardSet_undefined;
290 t->aliases = aliasTable_undefined;
292 t->mustBreak = FALSE;
293 t->exitCode = XK_NEVERESCAPE;
302 static /*@only@*/ /*@notnull@*/ usymtab
303 usymtab_createRoot (void) /*@modifies nothing@*/
305 usymtab u = (usymtab) dmalloc (sizeof (*u));
308 u->nspace = CGLOBBASESIZE;
309 u->entries = (uentry *) dmalloc (sizeof (*u->entries) * CGLOBBASESIZE);
312 u->htable = cstringTable_create (CGLOBHASHSIZE);
315 u->guards = guardSet_new ();
316 u->aliases = aliasTable_new ();
318 u->mustBreak = FALSE;
319 u->exitCode = XK_NEVERESCAPE;
326 usymtab_initMod (void)
327 /*@globals undef utab, undef oldtab, undef globtab, undef filetab @*/
328 /*@modifies utab, globtab, filetab, oldtab @*/
330 utab = usymtab_createRoot ();
332 filetab = usymtab_undefined;
333 oldtab = usymtab_undefined;
338 usymtab_initGlobalMarker () /*@globals globtab@*/
340 if (uentry_isValid (usymtab_lookupAux (globtab, GLOBAL_MARKER_NAME)))
342 ; /* Already entered from load table. */
346 usymtab_addGlobalEntry (uentry_makeGlobalMarker ());
351 ** utab should be empty? (requires?)
353 ** Adds bool types to symbol table (these are built in for now)
354 ** Only do this is there is no library!
360 if (context_getFlag (FLG_NOLIB))
362 ctype boolt = ctype_bool;
363 /* evs 2000-07-24: bool is now treated as abstract (always) */
365 uentry boolentry = uentry_makeBoolDatatype (YES);
366 usymtab_supGlobalEntry (boolentry);
367 context_addBoolAccess ();
370 ** We supply values 0 and 1 for the constants, so things like
371 ** while (TRUE) can be interpreted correctly.
374 usymtab_supGlobalEntry
375 (uentry_makeConstantAux (context_getFalseName (), boolt,
376 fileloc_getBuiltin (), FALSE,
377 multiVal_makeInt (0)));
378 usymtab_supGlobalEntry
379 (uentry_makeConstantAux (context_getTrueName (), boolt,
380 fileloc_getBuiltin (), FALSE,
381 multiVal_makeInt (1)));
390 usymtab_grow (/*@notnull@*/ usymtab s)
393 o_uentry *oldsyms = s->entries;
395 s->nspace = CBASESIZE;
396 s->entries = (uentry *) dmalloc (sizeof (*s->entries)
397 * (s->nentries + s->nspace));
399 for (i = 0; i < s->nentries; i++)
401 s->entries[i] = oldsyms[i];
406 if (s->reftable != NULL)
408 refTable oldRefs = s->reftable;
410 s->reftable = (refentry *) dmalloc (sizeof (*s->reftable)
411 * (s->nentries + CBASESIZE + 1));
413 for (i = 0; i < s->nentries; i++)
415 s->reftable[i] = oldRefs[i];
426 usymtab_addEntryQuiet (/*@notnull@*/ usymtab s, /*@keep@*/ uentry e)
428 if (!(s->lexlevel > fileScope || !sRef_modInFunction ()))
430 if (uentry_isDatatype (e)
431 || uentry_isFunction (e)
432 || uentry_isAnyTag (e)
433 || uentry_isEnumConstant (e)
434 || context_inMacro ())
437 ** Not a bug. Code like,
438 ** int f (void) { typedef int tint; ... }
442 /* was nothing here! */
443 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
448 (cstring_makeLiteral ("Declaration outside function scope"));
450 llcontbug (message ("usymtab_addEntryQuiet: inconsistent state "
451 "(lexlevel = %d, modFunction = %s) adding: %q",
452 s->lexlevel, bool_unparse (sRef_modInFunction ()),
453 uentry_unparse (e)));
454 sRef_setGlobalScope ();
455 /* make sure the sRef is not bashed! */
456 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
466 s->entries[s->nentries] = e;
469 if (s == globtab || s == filetab)
471 if (!fileloc_isLib (g_currentloc))
473 uentry_tallyAnnots (e, AN_UNKNOWN);
478 if (cstringTable_isDefined (s->htable))
480 cstringTable_insert (s->htable, cstring_copy (uentry_rawName (e)), s->nentries);
486 static /*@observer@*/ uentry /*@alt void@*/
487 usymtab_addEntryBase (/*@notnull@*/ usymtab s, /*@only@*/ uentry e)
490 ** In theory, we shouldn't need this test because it this is
491 ** only called when a library is being read, and it shouldn't
492 ** ever have a duplicate entry. In practice, its safer to
493 ** leave it in, though.
498 if (uentry_isValid (old = usymtab_lookupQuiet (s, uentry_rawName (e))))
500 DPRINTF (("Duplicate entry: %s", uentry_unparse (e)));
501 uentry_free (e); /* duplicate */
506 int thisentry = s->nentries;
508 if (uentry_isVar (e))
510 uentry_setSref (e, sRef_makeCvar (globScope, thisentry,
512 stateInfo_makeLoc (uentry_whereLast (e))));
515 usymtab_addEntryQuiet (s, e);
521 static /*@observer@*/ uentry /*@alt void@*/
522 usymtab_addEntryAlways (/*@notnull@*/ usymtab s, /*@only@*/ uentry e)
525 ** In theory, we shouldn't need this test because it this is
526 ** only called when a library is being read, and it shouldn't
527 ** ever have a duplicate entry. In practice, its safer to
528 ** leave it in, though.
532 int thisentry = s->nentries;
534 if (uentry_isValid (old = usymtab_lookupQuiet (s, uentry_rawName (e))))
537 (message ("Duplicate entry in load library: %s. "
538 "Old entry: %q. New entry: %q",
540 uentry_unparseFull (old),
541 uentry_unparseFull (e)));
543 uentry_setName (e, message ("__x_%s", uentry_rawName (e)));
544 /* This shouldn't happen...unless the library is bad! */
548 if (uentry_isVar (e) && !uentry_isGlobalMarker (e))
550 uentry_setSref (e, sRef_makeCvar (globScope, thisentry,
552 stateInfo_makeLoc (uentry_whereLast (e))));
555 usymtab_addEntryQuiet (s, e);
560 usymtab_addEntryAux (/*@notnull@*/ usymtab st, /*@keep@*/ uentry e, bool isSref)
561 /*@globals globtab@*/
564 usymId thisentry = st->nentries;
566 llassert (!uentry_isElipsisMarker (e));
570 ** llassert (usymtab_lookupSafe (uentry_rawName (e)) == uentry_undefined);
573 llassertprint (uentry_isAnyTag (e) ? st == globtab : TRUE,
574 ("non-global tag: %s / %d", uentry_unparseFull (e), st->lexlevel));
576 if (st->lexlevel == fileScope
577 && (!(uentry_isStatic (e)) || uentry_isAnyTag (e)))
584 ctype ct = uentry_getType (e);
586 if (uentry_isFunction (e) && ctype_isFunction (ct))
588 ct = ctype_getReturnType (ct);
591 if (uentry_isStatic (e))
593 sRef sr = sRef_makeCvar (st->lexlevel, thisentry, ct, stateInfo_makeLoc (uentry_whereLast (e)));
595 if (sRef_isStack (sr) || sRef_isLocalState (sr))
597 sRef_setAliasKind (sr, AK_STATIC, uentry_whereLast (e));
598 sRef_setDefined (sr, uentry_whereLast (e));
601 uentry_setSref (e, sr);
605 uentry_setSref (e, sRef_makeCvar (st->lexlevel, thisentry, ct, stateInfo_makeLoc (uentry_whereLast (e))));
609 if (uentry_isDatatype (e))
612 uentry_setDatatype (e, thisentry);
615 if (uentry_isFunction (e))
617 ctype ct = uentry_getType (e);
619 if (ctype_isFunction (ct)
620 && uentryList_isMissingParams (ctype_argsFunction (ct)))
622 if (uentry_isDeclared (e))
626 message ("Function %q declared without parameter list",
628 uentry_whereDeclared (e));
634 message ("Function %q specified without parameter list",
636 uentry_whereSpecified (e));
641 if (st == globtab && !uentry_isSpecified (e))
643 exprChecks_checkExport (e);
646 uentry_checkName (e);
648 usymtab_addEntryQuiet (st, e);
649 DPRINTF (("Adding entry: [%p] %s", e, uentry_unparseFull (e)));
654 usymtab_addEntry (uentry e)
655 /*@globals utab, globtab@*/
656 /*@modifies utab, e@*/
658 llassertprint (!usymtab_exists (uentry_rawName (e)),
659 ("Entry already exists: %s", uentry_unparse (e)));
661 return usymtab_addEntryAux (utab, e, FALSE);
665 usymtab_addGlobalEntry (uentry e)
666 /*@modifies globtab, e@*/
668 DPRINTF (("Add global: %s / %s", uentry_unparse (e), bool_unparse (uentry_isForward (e))));
670 (void) usymtab_addEntryAux (globtab, e, FALSE);
674 ** supercede and replace entry use elements of entries array, and
675 ** assign an element to a new value, and then free the old value.
676 ** Need -deparrays to avoid errors for this.
682 usymtab_supEntryAux (/*@notnull@*/ usymtab st,
683 /*@only@*/ uentry e, bool isSref)
684 /*@globals globtab, filetab@*/
685 /*@modifies st, globtab, e@*/
687 cstring ename = uentry_rawName (e);
688 bool staticEntry = FALSE;
691 DPRINTF (("Sup entry aux: %s", uentry_unparseFull (e)));
693 /* static tags in global scope */
694 if (st->lexlevel == fileScope
695 && (!(uentry_isStatic (e)) || uentry_isAnyTag (e)))
697 eindex = usymtab_getIndex (st, ename);
699 if (eindex != NOT_FOUND)
701 uentry ce = st->entries[eindex];
705 message ("%s %q shadows static declaration",
706 ekind_capName (uentry_getKind (e)),
708 uentry_whereDeclared (e)))
710 uentry_showWhereLast (ce);
713 if (eindex == st->nentries - 1)
719 st->entries[eindex] = st->entries[st->nentries - 1];
722 if (cstringTable_isDefined (st->htable))
724 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
725 cstring_copy (uentry_rawName (e)));
735 if (uentry_isStatic (e)) {
736 if (uentry_isFunction (e)) {
738 ** Static function declarations are at the file level,
739 ** even if they are in a deeper scope.
742 st = usymtab_getFileTab ();
745 if (!uentry_isAnyTag (e) && st == globtab)
747 st = usymtab_getFileTab ();
749 DPRINTF (("Static entry!"));
754 DPRINTF (("Using symtab: %s", usymtab_unparseLocalAux (st)));
756 eindex = usymtab_getIndex (st, ename);
758 if (eindex != NOT_FOUND)
760 uentry ce = st->entries[eindex];
762 DPRINTF (("Found entry: %s", uentry_unparse (ce)));
764 if (uentry_isPriv (ce)
765 /* || (fileloc_isImport (uentry_whereSpecified (ce))) */
766 || (uentry_isStatic (ce)
767 && uentry_isAnyTag (ce)
768 && (uentry_isDeclared (ce)
769 && !fileloc_sameFile (uentry_whereDefined (ce),
770 uentry_whereDefined (e)))))
774 ** if overloading import should do some checks!
777 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
779 DPRINTF (("Overloading!"));
781 st->entries[eindex] = e;
783 if (uentry_isDatatype (e))
785 uentry_setDatatype (e, eindex);
788 if (st == globtab && !uentry_isSpecified (e))
790 exprChecks_checkExport (e);
793 if (cstringTable_isDefined (st->htable))
795 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
796 cstring_copy (uentry_rawName (e)));
802 else if (uentry_isSpecified (ce))
804 if (uentry_isSpecified (e))
806 DPRINTF (("Here we are: %s", uentry_unparseFull (e)));
808 if (fileloc_isImport (uentry_whereSpecified (ce)))
810 if (cstringTable_isDefined (st->htable))
812 cstringTable_replaceKey (st->htable,
814 cstring_copy (uentry_rawName (e)));
818 st->entries[eindex] = e;
821 if (uentry_isDatatype (e)) uentry_setDatatype (e, eindex);
825 if (fileloc_isImport (uentry_whereSpecified (e)))
831 /* Respecification errors already reported */
832 DPRINTF (("Respecification: %s / %s",
833 fileloc_unparse (uentry_whereSpecified (e)),
834 bool_unparse (fileloc_isSpec (uentry_whereSpecified (e)))));
836 if (uentry_isDatatype (e))
838 uentry_setDatatype (e, eindex);
841 if (cstringTable_isDefined (st->htable))
843 cstringTable_replaceKey (st->htable,
845 cstring_copy (uentry_rawName (e)));
848 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
850 st->entries[eindex] = e;
855 else /* e not specified */
857 DPRINTF (("Merging..."));
859 if (uentry_isDeclared (ce))
862 No - this can happen for internal typedefs
863 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
866 DPRINTF (("Merge defn"));
867 uentry_mergeDefinition (ce, e);
872 No - this can happen for internal typedefs
873 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
876 DPRINTF (("Merge entries..."));
877 uentry_mergeEntries (ce, e);
878 DPRINTF (("After: %s", uentry_unparseFull (ce)));
882 else /* ce not specified */
884 if (!(st->lexlevel > fileScope || !sRef_modInFunction ()))
886 if (uentry_isDatatype (e) || uentry_isAnyTag (e)
887 || uentry_isEnumConstant (e))
890 ** Not a bug. Code like,
891 ** int f (void) { typedef int tint; ... }
897 llcontbug (message ("usymtab_supEntryAux: inconsistent state "
898 "(lexlevel = %d, modFunction = %s) adding: %q",
899 st->lexlevel, bool_unparse (sRef_modInFunction ()),
900 uentry_unparse (e)));
902 if (sRef_modInFunction ())
904 /* make sure the sRef is not bashed! */
905 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
910 DPRINTF (("Merge.."));
911 uentry_mergeDefinition (ce, e);
916 ctype ct = uentry_getType (ce);
918 if (uentry_isFunction (ce) && ctype_isFunction (ct))
920 ct = ctype_getReturnType (ct);
923 uentry_setSref (ce, sRef_makeCvar (st->lexlevel, eindex, ct, stateInfo_makeLoc (uentry_whereLast (ce))));
926 else /* no previous entry */
930 if (st->lexlevel == globScope
931 && !uentry_isStatic (e)
932 && !uentry_isExtern (e)
933 && usymtab_isDefined (filetab))
936 ** check if there is a static entry: (i.e.,
943 eindex = usymtab_getIndex (filetab, ename);
945 if (eindex != NOT_FOUND)
947 uentry ce = filetab->entries[eindex];
949 uentry_setStatic (e);
950 uentry_mergeDefinition (ce, e);
956 outer = usymtab_lookupQuiet (st->env, ename);
958 DPRINTF (("New : [%p] %s", e, uentry_unparseFull (e)));
959 DPRINTF (("Outer: [%p] %s", outer, uentry_unparseFull (outer)));
962 ** no previous definition, add the new one
966 && uentry_isValid (outer)
967 && !(uentry_isYield (e) || uentry_isYield (outer))
968 && fileloc_isDefined (uentry_whereLast (e))
969 && !fileloc_isXHFile (uentry_whereLast (e))
970 && fileloc_isDefined (uentry_whereLast (outer))
971 && !fileloc_isXHFile (uentry_whereLast (outer)))
973 if (!uentry_sameKind (outer, e))
979 if (ctype_isUnknown (uentry_getType (outer))
980 || uentry_isForward (outer))
988 message ("%s %q shadows outer declaration",
989 ekind_capName (uentry_getKind (e)),
991 uentry_whereLast (e)))
993 uentry_showWhereLast (outer);
999 if (st == globtab && context_getFlag (FLG_NEWDECL))
1003 message ("New declaration: %q", uentry_getName (e)),
1004 uentry_whereLast (e));
1007 eindex = usymtab_addEntryAux (st, e, isSref);
1011 return (staticEntry ? USYMIDINVALID : eindex);
1016 usymtab_replaceEntryAux (/*@notnull@*/ usymtab st, /*@only@*/ uentry e)
1017 /*@globals globtab@*/ /*@modifies st, e@*/
1019 cstring ename = uentry_rawName (e);
1022 /* static tags in global scope */
1023 eindex = usymtab_getIndex (st, ename);
1025 if (eindex != NOT_FOUND)
1027 uentry ce = st->entries[eindex];
1029 if (cstringTable_isDefined (st->htable))
1031 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
1032 cstring_copy (uentry_rawName (e)));
1036 st->entries[eindex] = e;
1040 eindex = usymtab_addEntryAux (st, e, FALSE);
1047 void usymtab_supEntry (uentry e)
1048 /*@globals utab, filetab, globtab@*/
1049 /*@modifies utab, globtab, e@*/
1051 (void) usymtab_supEntryAux (utab, e, FALSE);
1055 ** this should be lots more efficient!
1058 static /*@exposed@*/ uentry
1059 usymtab_supEntryReturnAux (/*@notnull@*/ usymtab tab,
1060 /*@only@*/ uentry e, bool isref)
1061 /*@globals globtab, filetab@*/
1062 /*@modifies tab, globtab, e@*/
1064 cstring rawName = cstring_copy (uentry_rawName (e));
1065 bool stat = (tab == globtab) && uentry_isStatic (e);
1068 (void) usymtab_supEntryAux (tab, e, isref);
1072 ret = usymtab_lookupAux (filetab, rawName);
1076 ret = usymtab_lookupAux (tab, rawName);
1078 if (uentry_isInvalid (ret) && usymtab_isDefined (filetab))
1080 ret = usymtab_lookupAux (filetab, rawName);
1084 cstring_free (rawName);
1088 /*@dependent@*/ /*@exposed@*/ uentry
1089 usymtab_supEntryReturn (/*@only@*/ uentry e)
1090 /*@globals utab, filetab, globtab@*/
1091 /*@modifies utab, globtab, e@*/
1093 return (usymtab_supEntryReturnAux (utab, e, FALSE));
1096 /*@dependent@*/ /*@exposed@*/ uentry
1097 usymtab_supEntrySrefReturn (/*@only@*/ uentry e)
1098 /*@globals utab, globtab, filetab@*/
1099 /*@modifies utab, globtab, e@*/
1101 return (usymtab_supEntryReturnAux (utab, e, TRUE));
1104 /*@dependent@*/ /*@exposed@*/ uentry
1105 usymtab_supGlobalEntryReturn (uentry e)
1106 /*@globals globtab, filetab@*/
1107 /*@modifies globtab, e@*/
1111 ret = usymtab_supEntryReturnAux (globtab, e, FALSE);
1114 ** We need to keep track of internal function declarations, so
1115 ** we can remove them from the symbol table after exiting this
1116 ** function. This is a bit bogus, of course.
1119 if (sRef_modInFunction ())
1121 recordFunctionType (ret);
1128 usymtab_supTypeEntry (/*@only@*/ uentry e)
1129 /*@globals globtab, filetab@*/
1130 /*@modifies globtab, e@*/
1135 if (uentry_isAbstractDatatype (e))
1137 uid = usymtab_supAbstractTypeEntry (e, FALSE);
1138 ret = ctype_createAbstract (uid);
1142 uid = usymtab_supEntryAux (globtab, e, FALSE);
1143 ret = ctype_createUser (uid);
1146 if (sRef_modInFunction ())
1148 recordFunctionType (globtab->entries[uid]);
1155 usymtab_supReturnTypeEntry (/*@only@*/ uentry e)
1156 /*@globals globtab, filetab@*/
1157 /*@modifies globtab@*/
1161 DPRINTF (("Abstract? %s", uentry_unparseFull (e)));
1163 if (uentry_isAbstractDatatype (e))
1165 uid = usymtab_supAbstractTypeEntry (e, FALSE);
1167 else if (uentry_isMaybeAbstract (e) && context_getFlag (FLG_IMPABSTRACT))
1169 bool maybeabs = TRUE;
1170 cstring sname = uentry_getName (e);
1171 uentry ue = usymtab_lookupGlobSafe (sname);
1172 cstring_free (sname);
1174 if (uentry_isValid (ue))
1176 DPRINTF (("Lookup: %s", uentry_unparseFull (ue)));
1178 if (uentry_isDatatype (ue))
1180 if (uentry_isMaybeAbstract (ue))
1191 DPRINTF (("Not datatype!"));
1198 uid = usymtab_supAbstractTypeEntry (e, FALSE);
1199 ux = usymtab_getTypeEntry (uid);
1200 uentry_setAbstract (ux);
1204 uid = usymtab_supEntryAux (globtab, e, FALSE);
1205 e = usymtab_getTypeEntry (uid);
1207 if (uentry_isMaybeAbstract (e))
1209 uentry_setConcrete (e);
1215 uid = usymtab_supEntryAux (globtab, e, FALSE);
1216 e = usymtab_getTypeEntry (uid);
1218 if (uentry_isMaybeAbstract (e))
1220 uentry_setConcrete (e);
1224 if (sRef_modInFunction ())
1226 recordFunctionType (globtab->entries[uid]);
1229 return (globtab->entries[uid]);
1233 usymtab_supAbstractTypeEntry (/*@only@*/ uentry e, bool dodef)
1234 /*@globals globtab, filetab@*/
1235 /*@modifies globtab, e@*/
1240 uid = usymtab_supEntryAux (globtab, e, FALSE);
1241 ue = usymtab_getTypeEntry (uid);
1245 uentry_setDatatype (ue, uid);
1248 if (context_getFlag (FLG_ACCESSMODULE)) /* was accessfile */
1250 context_addFileAccessType (uid);
1253 if (sRef_modInFunction ())
1255 recordFunctionType (globtab->entries[uid]);
1263 usymtab_supExposedTypeEntry (/*@only@*/ uentry e, bool dodef)
1264 /*@globals globtab, filetab@*/
1265 /*@modifies globtab, e@*/
1269 uid = usymtab_supEntryAux (globtab, e, FALSE);
1273 uentry ue = usymtab_getTypeEntry (uid);
1275 uentry_setDatatype (ue, uid);
1278 if (sRef_modInFunction ())
1280 recordFunctionType (globtab->entries[uid]);
1288 usymtab_supForwardTypeEntry (/*@only@*/ uentry e)
1289 /*@globals globtab, filetab@*/
1290 /*@modifies globtab, e@*/
1292 usymId uid = usymtab_supEntryAux (globtab, e, FALSE);
1293 uentry ue = usymtab_getTypeEntry (uid);
1295 uentry_setDatatype (ue, uid);
1297 if (sRef_modInFunction ())
1299 recordFunctionType (globtab->entries[uid]);
1302 return (uentry_getAbstractType (ue));
1306 usymtab_supEntrySref (uentry e)
1307 /*@globals utab, globtab, filetab@*/
1308 /*@modifies utab, globtab, e@*/
1310 sRef old = uentry_getSref (e);
1313 if (sRef_isType (old))
1315 uentry ue = usymtab_supEntryReturnAux (utab, e, TRUE);
1318 if (uentry_isValid (ue))
1320 sRef uref = uentry_getSref (ue);
1322 sRef_mergeStateQuiet (uref, old);
1323 sRef_clearDerived (uref);
1325 /*@noaccess uentry@*/
1327 else if (sRef_isKnown (old))
1329 usymtab_supEntry (e);
1333 (void) usymtab_supEntryAux (utab, e, TRUE);
1337 void usymtab_supGlobalEntry (/*@only@*/ uentry e)
1338 /*@globals globtab, filetab@*/
1339 /*@modifies globtab, filetab, e@*/
1343 DPRINTF (("Sup global entry: %s", uentry_unparse (e)));
1345 uid = usymtab_supEntryAux (globtab, e, FALSE);
1347 if (sRef_modInFunction ())
1349 recordFunctionType (globtab->entries[uid]);
1354 usymtab_supReturnFileEntry (/*@only@*/ uentry e)
1355 /*@globals filetab, globtab@*/
1356 /*@modifies filetab, globtab, e@*/
1358 llassert (filetab != usymtab_undefined);
1359 DPRINTF (("File entry: %s", uentry_unparse (e)));
1360 return (usymtab_supEntryReturnAux (filetab, e, FALSE));
1368 usymtab_inDeepScope () /*@globals utab@*/
1370 return (utab->lexlevel > paramsScope);
1374 usymtab_getIndex (/*@notnull@*/ usymtab s, cstring k)
1378 DPRINTF (("Lookup %s", k));
1380 if (cstringTable_isDefined (s->htable))
1382 i = cstringTable_lookup (s->htable, k);
1387 for (i = 0; i < s->nentries; i++)
1389 uentry current = s->entries[i];
1391 DPRINTF (("Check %d: %s", i, uentry_rawName (current)));
1393 if (!uentry_isUndefined (current)
1394 && cstring_equal (uentry_rawName (current), k))
1405 usymtab_fetchIndex (/*@notnull@*/ usymtab s, int i)
1407 llassert (i >= 0 && i < s->nentries);
1408 return (s->entries[i]);
1412 usymtab_getTypeId (cstring k) /*@globals globtab@*/
1414 usymId uid = usymtab_getIndex (globtab, k);
1416 if (uid == NOT_FOUND) return USYMIDINVALID;
1418 if (!(uentry_isDatatype (usymtab_getTypeEntry (uid)))) {
1419 return USYMIDINVALID;
1425 /*@dependent@*/ uentry
1426 usymtab_lookupStructTag (cstring k)
1428 cstring sname = makeStruct (k);
1429 uentry ue = usymtab_lookupGlob (sname);
1431 cstring_free (sname);
1435 /*@dependent@*/ uentry
1436 usymtab_lookupUnionTag (cstring k)
1438 cstring uname = makeUnion (k);
1439 uentry res = usymtab_lookupGlob (uname);
1441 cstring_free (uname);
1445 /*@dependent@*/ uentry
1446 usymtab_lookupEnumTag (cstring k)
1448 cstring ename = makeEnum (k);
1449 uentry res = usymtab_lookupGlob (ename);
1451 cstring_free (ename);
1456 usymtab_getId (cstring k) /*@globals globtab@*/
1458 usymId uid = usymtab_getIndex (globtab, k);
1461 if (uid == NOT_FOUND)
1463 return USYMIDINVALID;
1466 ue = usymtab_getGlobalEntry (uid);
1468 if (uentry_isPriv (ue))
1470 return USYMIDINVALID;
1476 static /*@exposed@*/ uentry
1477 usymtab_getEntryAux (/*@notnull@*/ usymtab s, usymId uid)
1479 llassert (uid != USYMIDINVALID);
1481 if (uid < 0 || uid >= s->nentries)
1483 llcontbug (message ("usymtab_getEntry: out of range: level = %d [%d]",
1485 return uentry_undefined;
1488 llassertprint (uentry_isValid (s->entries[uid]),
1489 ("entry undefined: %d", uid));
1491 return s->entries[uid];
1494 /*@dependent@*/ /*@observer@*/ uentry
1495 usymtab_getGlobalEntry (usymId uid)
1496 /*@globals utab, globtab@*/
1498 if (dbgfree) return (uentry_undefined);
1500 if (utab->lexlevel > paramsScope)
1502 /* need to do this the awkward way, since it could be in conditional scope */
1503 return (usymtab_lookupSafe (uentry_rawName (globtab->entries[uid])));
1507 return (globtab->entries[uid]);
1511 /*@dependent@*/ /*@exposed@*/ uentry
1512 usymtab_getTypeEntry (usymId uid)
1513 /*@globals globtab@*/
1517 if (uid >= 0 && uid < globtab->nentries)
1519 return (globtab->entries[uid]);
1523 return (uentry_undefined);
1528 llassert (uid >= 0 && uid < globtab->nentries);
1529 return (globtab->entries[uid]);
1537 /*@dependent@*/ /*@exposed@*/ uentry
1538 usymtab_getTypeEntrySafe (usymId uid)
1539 /*@globals globtab@*/
1541 if (uid < 0 || uid >= globtab->nentries)
1543 return uentry_undefined;
1546 return (globtab->entries[uid]);
1550 usymtab_isBoolType (usymId uid)
1551 /*@globals globtab@*/
1553 llassert (uid >= 0 && uid < globtab->nentries);
1555 return (cstring_equal (uentry_rawName (globtab->entries[uid]),
1556 context_getBoolName ()));
1560 usymtab_getTypeEntryName (usymId uid)
1561 /*@globals globtab@*/
1567 return (cstring_makeLiteral ("<freetype>"));
1570 ue = usymtab_getTypeEntry (uid);
1572 if (dbgload && !uentry_isValid (ue))
1574 return (message ("<missing type: %d>", uid));
1577 llassertprint (uentry_isValid (ue), ("type undefined: %d", uid));
1579 return (uentry_getName (ue));
1583 /*@unused@*/ static void
1584 usymtab_rehash (/*@notnull@*/ usymtab s)
1588 if (cstringTable_isDefined (s->htable))
1590 cstringTable_free (s->htable);
1593 s->htable = cstringTable_create (LLHASHSIZE);
1595 for (i = 0; i < s->nentries; i++)
1597 cstringTable_insert (s->htable, cstring_copy (uentry_rawName (s->entries[i])), i);
1603 ** superficial copy of usymtab
1605 ** DO copy spec entries
1608 static /*@only@*/ /*@notnull@*/ usymtab
1609 usymtab_shallowCopy (/*@notnull@*/ usymtab s) /*@*/
1611 usymtab copytab = usymtab_createRoot ();
1614 for (i = 0; i < s->nentries; i++)
1616 usymtab_addEntryBase (copytab, s->entries[i]);
1623 usymtab_shallowFree (/*@only@*/ /*@notnull@*/ usymtab s)
1625 aliasTable_free (s->aliases);
1626 refTable_free (s->reftable, s->nentries);
1628 /*@-compdestroy@*/ sfree (s); /*@=compdestroy@*/
1632 ** converts usymId from old table to sorted one
1636 usymtab_convertId (usymId uid)
1637 /*@globals oldtab, utab@*/
1643 llassert (usymtab_isDefined (oldtab));
1645 ue = usymtab_getEntryAux (oldtab, uid);
1647 llassertprint (uentry_isValid (ue), ("convertId: undefined: %d", uid));
1649 name = uentry_rawName (ue);
1651 ret = usymtab_getIndex (utab, name);
1652 llassert (ret == uid); /*! for now, no rehash! */
1653 DPRINTF (("Convert: %s [%d] -> %s [%d]",
1654 uentry_unparse (ue), uid,
1655 uentry_unparse (utab->entries[ret]), ret));
1657 llassertprint (ret != USYMIDINVALID, ("convertId: return is invalid"));
1663 usymtab_prepareDump (void)
1664 /*@globals oldtab, utab@*/
1665 /*@modifies oldtab, utab@*/
1667 llassert (usymtab_inGlobalScope ());
1668 llassert (oldtab == usymtab_undefined);
1671 DPRINTF (("Preparing to dump:"));
1672 usymtab_printAll ();
1675 oldtab = usymtab_shallowCopy (utab);
1678 ** alpha compare - make sure order is same on different platforms
1679 ** error messages appear in same order
1683 qsort (utab->entries, (size_t)utab->nentries,
1684 sizeof (*utab->entries),
1685 (int (*)(const void *, const void *)) uentry_xcomparealpha);
1687 usymtab_rehash (utab);
1691 DPRINTF (("After rehash:"));
1692 usymtab_printAll ();
1696 void usymtab_dump (FILE *fout)
1697 /*@globals utab, oldtab@*/
1700 bool neednl = FALSE;
1701 uentry lastentry = uentry_undefined;
1702 ekind lastekind = KINVALID;
1706 ** must call prepareDump first
1709 llassert (oldtab != usymtab_undefined);
1711 for (i = 0; i < utab->nentries; i++)
1713 uentry thisentry = utab->entries[i];
1714 ekind thisekind = uentry_getKind (thisentry);
1716 if (!uentry_hasRealName (thisentry))
1718 llassert (uentry_isGlobalMarker (thisentry));
1722 check (fputc ('\n', fout) == (int) '\n');
1725 fprintf (fout, "*%d (GlobalMarker)\n", KGLOBALMARKER);
1726 lastekind = KINVALID;
1732 if (thisekind != lastekind)
1736 check (fputc ('\n', fout) == (int) '\n');
1740 lastentry = uentry_undefined;
1741 fprintf (fout, "*%d (%s)\n", ekind_toInt (thisekind),
1742 cstring_toCharsSafe (ekind_capName (thisekind)));
1743 lastekind = thisekind;
1748 ** evans - 2001-02-18 - added the - 48 fudge factor...
1749 ** extra characters dumped, but I haven't counded them carefully...
1752 if (uentry_isInvalid (lastentry) || !uentry_equiv (lastentry, thisentry)
1753 || (linelen > (MAX_DUMP_LINE_LENGTH - (2 * MAX_NAME_LENGTH) - 48)))
1757 DPRINTF (("Dumping entry: %d", i));
1758 cdump = message ("^%d %q", i, uentry_dump (thisentry));
1759 /* was: cdump = uentry_dump (thisentry)); */
1761 lastentry = thisentry;
1764 check (fputc ('\n', fout) == (int) '\n');
1768 linelen += cstring_length (cdump);
1770 /* no new line here! */
1771 if (cstring_length (cdump) > 0)
1773 check (fputs (cstring_toCharsSafe (cdump), fout) != EOF);
1776 cstring_free (cdump);
1781 cstring cdump = uentry_rawName (thisentry);
1782 DPRINTF (("Raw name: %s", cdump));
1783 linelen += (cstring_length (cdump) + 1);
1784 fprintf (fout, "#%s", cstring_toCharsSafe (cdump));
1791 check (fputc ('\n', fout) == (int) '\n');
1794 lastekind = KINVALID;
1796 fprintf(fout, ";; Library constraints\n");
1797 for (i = 0; i < utab->nentries; i++)
1799 uentry thisentry = utab->entries[i];
1801 if (uentry_isFunction (thisentry) )
1803 constraintList preconditions;
1804 constraintList postconditions;
1806 preconditions = uentry_getFcnPreconditions (thisentry);
1807 postconditions = uentry_getFcnPostconditions (thisentry);
1809 if ( constraintList_isDefined(preconditions) ||
1810 constraintList_isDefined(postconditions) )
1812 fprintf(fout,"%s\n", cstring_toCharsSafe (uentry_rawName(thisentry) ) );
1813 if (constraintList_isDefined(preconditions) )
1815 fprintf(fout,"pre:\n");
1816 constraintList_dump(preconditions, fout);
1817 fprintf (fout, ";; end precondition constraints\n" );
1818 constraintList_free(preconditions);
1822 fprintf(fout,"pre:EMPTY\n");
1824 if (constraintList_isDefined(postconditions) )
1826 fprintf(fout,"post:\n");
1827 constraintList_dump(postconditions, fout);
1828 fprintf (fout, ";; end precondition constraints\n" );
1829 constraintList_free(postconditions);
1833 fprintf(fout,"post:EMPTY\n");
1844 void usymtab_load (FILE *f)
1845 /*@globals utab, globtab@*/
1846 /*@modifies utab, *f@*/
1848 char *s = mstring_create (MAX_DUMP_LINE_LENGTH);
1850 ekind kind = KINVALID;
1851 fileloc loc = g_currentloc;
1857 llassert (utab == globtab);
1858 llassert (utab->nentries == 0);
1860 while (((s = reader_readLine (f, s, MAX_DUMP_LINE_LENGTH)) != NULL)
1863 /* ignore ; comments */ ;
1866 while (s != NULL && *s != ';')
1874 ek = reader_getInt (&s);
1876 if (ek == KGLOBALMARKER)
1878 uentry lue = uentry_makeGlobalMarker ();
1879 DPRINTF (("Adding global marker: %s", uentry_unparseFull (lue)));
1880 usymtab_addEntryAlways (utab, lue);
1886 kind = ekind_fromInt (ek);
1894 (cstring_makeLiteral
1895 ("Library is in obsolete format. Use lclint +whichlib "
1896 "to see which library is being loaded."));
1899 if (reader_optCheckChar (&s, '^'))
1901 index = reader_getInt (&s);
1908 llassert (kind != KINVALID);
1909 ue = uentry_undump (kind, loc, &s);
1911 llassert (utab->nentries == index || index == -1);
1913 if (uentry_isValid (ue))
1915 int lastindex = utab->nentries;
1916 ue = usymtab_addEntryAlways (utab, ue);
1917 if (utab->nentries != lastindex + 1)
1919 DPRINTF (("No add: %s", uentry_unparseFull (ue)));
1927 ** now, any other names are the same uentry
1930 while (*(s++) == '#')
1932 cstring name = cstring_fromCharsO (reader_getWord (&s));
1933 uentry nue = uentry_nameCopy (name, ue);
1935 DPRINTF (("Name copy: %s", uentry_unparseFull (nue)));
1939 usymtab_addEntryAlways (utab, nue);
1942 while ((c = *s) != '\0' && (c !='\n'))
1944 if (c != ' ' || c != '\t')
1946 llbuglit ("Junk in load file");
1954 s = reader_readLine (f, os, MAX_DUMP_LINE_LENGTH);
1959 to handle reading of buffer overflow related constraints
1961 while (fgets (s, MAX_DUMP_LINE_LENGTH, f) != NULL
1964 ; /* ignore ;-comments */
1967 while (s != NULL && *s != ';')
1969 constraintList preconditions;
1970 constraintList postconditions;
1972 cstring name = cstring_fromChars(reader_getWord(&s) );
1974 ue = usymtab_lookup ( name );
1978 preconditions = constraintList_undefined;
1979 postconditions = constraintList_undefined;
1981 if (!uentry_isValid(ue) )
1983 llfatalbug ((message("Invalid uentry for %s library file may be corrupted", cstring_fromChars(s) ) ));
1985 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
1987 temp = cstring_fromChars (reader_getWord(&s) );
1989 if (cstring_compareLit (temp,"pre:") == 0 )
1991 preconditions = constraintList_undump (f);
1995 if (cstring_compareLit (temp,"pre:EMPTY") != 0 )
1996 llfatalbug ((message("Error reading library file pre:EMPTY expected but got %s", temp ) ));
2001 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2003 temp = cstring_fromChars(reader_getWord(&s) );
2004 if (cstring_compareLit (temp, "post:") == 0 )
2006 postconditions = constraintList_undump (f);
2010 if (cstring_compareLit (temp, "post:EMPTY") != 0 )
2011 llfatalbug ((message("Error reading library file post:EMPTY expected but got %s", temp ) ));
2014 cstring_free (temp);
2016 uentry_setPreconditions (ue, functionConstraint_createBufferConstraint (preconditions));
2017 uentry_setPostconditions (ue, functionConstraint_createBufferConstraint (postconditions));
2019 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2027 ** file scope for static variables
2031 usymtab_enterFile ()
2032 /*@globals utab, globtab, filetab@*/
2033 /*@modifies filetab@*/
2035 llassert (utab == globtab);
2040 usymtab_entries (globtab, ue)
2042 if (sRef_hasDerived (uentry_getSref (ue)))
2044 fprintf (g_msgstream, "Derived Global: %s\n", uentry_unparse (ue));
2045 fprintf (g_msgstream, "sRef: %s\n", sRef_unparseFull (ue->sref));
2047 } end_usymtab_entries ;
2051 usymtab_enterScope ();
2057 /*@globals utab, filetab@*/
2058 /*@modifies filetab, utab@*/
2061 llassert (utab->lexlevel == 1);
2063 usymtab_exitScope (exprNode_undefined);
2068 usymtab_enterScope ()
2069 /*@globals utab, globtab, filetab@*/
2072 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
2074 /* unconditional scope: optimize to avoid copy */
2075 t->aliases = aliasTable_copy (utab->aliases);
2078 llassert (usymtab_isDefined (t->env));
2080 if (t->env->lexlevel == paramsScope && context_inFunctionLike ())
2082 noshadowerror = TRUE;
2083 usymtab_handleParams ();
2084 noshadowerror = FALSE;
2089 ** setup external references:
2090 ** o only, unique params alias external args
2091 ** o other params may alias anything of their type
2095 usymtab_handleParams (void)
2096 /*@globals utab, globtab, filetab@*/
2097 /*@modifies utab, globtab@*/
2099 usymtab ptab = utab->env;
2100 uentry fcn = context_getHeader ();
2102 usymtab_entries (ptab, param)
2106 if (!uentry_isYield (param))
2109 sRef pref = uentry_getSref (param);
2111 /* Could be a global. */
2113 if (uentry_isAnyParam (param))
2115 ue = uentry_makeVariable (fixParamName (uentry_rawName (param)),
2116 uentry_getType (param),
2117 fileloc_copy (uentry_whereDeclared (param)),
2120 uentry_copyState (ue, param);
2121 uentry_setRefParam (ue);
2123 ue = usymtab_supEntrySrefReturn (ue);
2125 /* must be after supercede! */
2127 if (!sRef_stateKnown (pref))
2129 uentry_setDefState (ue, SS_DEFINED);
2130 uentry_setDefState (param, SS_DEFINED);
2134 if (sRef_isStateSpecial (pref))
2136 uentry_setDefState (ue, SS_ALLOCATED);
2140 uentry_setDefState (ue, sRef_getDefState (pref));
2144 uref = uentry_getSref (ue);
2146 if (sRef_isStack (uref))
2148 alkind pkind = sRef_getAliasKind (pref);
2150 if (alkind_isKnown (pkind) && !alkind_isLocal (pkind)
2151 && !alkind_isStack (pkind))
2153 sRef_setAliasKind (uref, pkind, fileloc_undefined);
2154 sRef_setOrigAliasKind (uref, pkind);
2158 sRef_setAliasKind (uref, AK_IMPTEMP, fileloc_undefined);
2159 sRef_setOrigAliasKind (uref, AK_IMPTEMP);
2161 if (uentry_isOut (param))
2167 sRef_setDefined (uref, fileloc_undefined);
2173 usymtab_addMustAlias (uref, pref);
2175 if (!(uentry_isOnly (param) || uentry_isUnique (param)))
2178 ** This is needed for detecting possibly aliased parameters.
2181 sRef s = sRef_makeExternal (uref);
2182 usymtab_addMustAlias (uref, s);
2185 if (sRef_isKillRef (pref))
2187 sRef_setAliasKind (uref, AK_NEWREF, fileloc_undefined);
2188 sRef_setOrigAliasKind (uref, AK_KILLREF);
2190 else if (sRef_isRefCounted (uref))
2192 sRef_setOrigAliasKind (uref, AK_REFCOUNTED);
2197 sRef_setOrigAliasKind (uref, AK_LOCAL);
2204 } end_usymtab_entries;
2207 if (uentry_hasStateClauseList (fcn))
2209 stateClauseList clauses = uentry_getStateClauseList (fcn);
2211 stateClauseList_preElements (clauses, cl)
2213 fileloc loc = stateClause_loc (cl);
2214 sRefSet osrs = sRefSet_undefined;
2217 if (stateClause_isGlobal (cl))
2219 DPRINTF (("Global Marker: %s",
2220 sRef_unparseFull (usymtab_lookupGlobalMarker ())));
2221 llassert (sRef_isGlobalMarker (usymtab_lookupGlobalMarker ()));
2222 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
2227 srs = stateClause_getRefs (cl);
2230 sRefSet_elements (srs, el)
2232 sRef base = sRef_getRootBase (el);
2233 sRef sb = sRef_updateSref (el);
2235 if (sRef_isResult (base))
2237 ; /* nothing to do before */
2239 else if (sRef_isParam (base) || sRef_isGlobalMarker (base))
2241 if (stateClause_setsMetaState (cl))
2243 /* copied from exprNode.c:3040 */
2244 qual ql = stateClause_getMetaQual (cl);
2245 annotationInfo ainfo = qual_getAnnotationInfo (ql);
2246 metaStateInfo minfo = annotationInfo_getState (ainfo);
2247 cstring key = metaStateInfo_getName (minfo);
2248 int mvalue = annotationInfo_getValue (ainfo);
2250 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
2252 if (sRef_isResult (base))
2258 sRef_setMetaStateValueComplete (sb, key, mvalue, loc);
2263 sRefMod modf = stateClause_getEntryFunction (cl);
2267 sRefSet aliases = usymtab_allAliases (sb);
2271 sRefSet_elements (aliases, sr)
2274 } end_sRefSet_elements ;
2276 sRefSet_free (aliases);
2282 if (sRef_isValid (base))
2284 DPRINTF (("Base: %s", sRef_unparseFull (base)));
2288 } end_sRefSet_elements ;
2289 } end_stateClauseList_preElements ;
2294 usymtab_enterFunctionScope (uentry fcn)
2295 /*@globals utab, filetab, globtab@*/
2298 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
2300 if (utab->lexlevel != fileScope)
2302 if (utab->lexlevel > fileScope)
2304 llparseerror (cstring_makeLiteral ("New function scope inside function"));
2306 while (utab->lexlevel > fileScope)
2308 /*@i@*/ utab = usymtab_dropEnv (utab);
2315 llfatalbug (cstring_makeLiteral ("New function not inside file."));
2317 /*@-branchstate@*/ } /*@=branchstate@*/
2321 DPRINTF (("Globs: %s", globSet_unparse (uentry_getGlobs (fcn))));
2323 globSet_allElements (uentry_getGlobs (fcn), el)
2325 DPRINTF (("Here we go: %s", sRef_unparseFull (el)));
2327 if (sRef_isUndefGlob (el))
2329 int index = sRef_getScopeIndex (el);
2330 sRef sr = sRef_updateSref (el);
2331 fileloc loc = uentry_whereEarliest (fcn);
2333 DPRINTF (("update: %s", sRef_unparseFull (sr)));
2334 DPRINTF (("Undef!"));
2335 if (sRef_isFileStatic (el))
2337 ctype ct = sRef_getType (el);
2340 llassert (usymtab_isDefined (filetab));
2342 ue = usymtab_fetchIndex (filetab, index);
2344 if (ctype_isRealArray (ct) || ctype_isRealSU (ct))
2346 sRef_setAllocated (sr, loc);
2350 sRef_setUndefined (sr, loc);
2355 uentry ue = globtab->entries[index];
2356 ctype ct = uentry_getType (ue);
2358 if (ctype_isArray (ct) || ctype_isSU (ct))
2360 sRef_setAllocated (sr, loc);
2364 sRef_setUndefined (sr, loc);
2368 else if (sRef_isAllocated (el))
2370 sRef sr = sRef_updateSref (el);
2371 fileloc loc = uentry_whereEarliest (fcn);
2373 sRef_setAllocated (sr, loc);
2375 else if (sRef_isPartial (el))
2377 sRef sr = sRef_updateSref (el);
2378 fileloc loc = uentry_whereEarliest (fcn);
2380 sRef_setPartial (sr, loc);
2385 sRef sr = sRef_updateSref (el);
2386 fileloc loc = uentry_whereEarliest (fcn);
2388 sRef_setDefined (sr, loc);
2392 /* shouldn't need to do anything! */
2394 } end_globSet_allElements;
2396 DPRINTF (("Globs after: %s", globSet_unparse (uentry_getGlobs (fcn))));
2400 usymtab_caseBranch (void)
2403 usymtab t = usymtab_create (US_CBRANCH, utab, FALSE);
2408 usymtab_switchBranch (/*@unused@*/ exprNode s)
2411 usymtab t = usymtab_create (US_SWITCH, utab, FALSE);
2413 t->aliases = aliasTable_copy (utab->aliases);
2418 usymtab_trueBranch (/*@only@*/ guardSet guards)
2421 usymtab t = usymtab_create (US_TBRANCH, utab, FALSE);
2424 ** not true! (could be in a macro)
2426 ** llassertprint (utab->lexlevel > paramsScope,
2427 ** ("not in scope: %s", usymtab_unparseLocal ()));
2431 guardSet_free (t->guards);
2434 aliasTable_free (t->aliases);
2435 t->aliases = aliasTable_copy (utab->aliases);
2443 ** { int a; if (...) a = 3; < a may be undefined here!
2448 usymtab_popTrueBranch (exprNode pred, exprNode expr, clause cl) /*@modifies utab@*/
2451 ** add a false branch
2452 ** (could be done more efficiently as a special case, but
2453 ** it is better to only maintain one version of the code)
2456 if (utab->kind != US_TBRANCH
2457 && context_inIterDef ())
2459 usymtab_exitScope (expr);
2463 DPRINTF (("pop true branch.."));
2464 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2465 usymtab_popBranches (pred, expr, exprNode_undefined, TRUE, cl);
2470 usymtab_popCaseBranch () /*@modifies utab@*/
2472 llassert (utab->kind == US_CBRANCH);
2473 usymtab_quietPlainExitScope ();
2477 usymtab_popTrueExecBranch (exprNode pred, exprNode expr, clause cl)
2480 ** add a false branch that must return --- that is,
2481 ** the true branch is always executed!
2484 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2485 usymtab_popBranches (pred, expr, exprNode_makeMustExit (), FALSE, cl);
2489 usymtab_popOrBranch (exprNode pred, exprNode expr)
2493 usymtab env = utab->env;
2494 usymtab otab = utab;
2497 llassert (env != NULL);
2499 if (exprNode_isError (expr))
2505 mustReturn = exprNode_mustEscape (expr);
2509 llassert (utab->kind == US_TBRANCH);
2512 ** merge each entry in table with its original
2513 ** unless execution cannot continue after this branch
2516 for (i = 0; i < utab->nentries; i++)
2518 uentry current = utab->entries[i];
2519 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2521 uentry_mergeState (old, current, exprNode_loc (expr),
2522 mustReturn, FALSE, TRUE, ORCLAUSE);
2528 env->guards = guardSet_levelUnionFree (env->guards,
2529 guardSet_invert (exprNode_getGuards (pred)),
2534 env->aliases = aliasTable_levelUnion (env->aliases, otab->aliases, env->lexlevel);
2537 /* env is now utab */
2538 usymtab_quietPlainExitScope ();
2542 ** case syntax in C is very unrestricted. This is unfortunate.
2544 ** A switch case is ended either by a new case or default, or
2545 ** a close } that may close the switch or some other control
2550 usymtab_newCase (/*@unused@*/ exprNode pred, exprNode last)
2553 bool mustBreak = usymtab_mustBreak (utab);
2554 bool mustReturn = usymtab_mustEscape (utab);
2555 usymtab stab = utab;
2558 ** Find last case (or outer switch)
2561 while (stab->kind != US_CBRANCH && stab->kind != US_SWITCH)
2564 llassert (stab != GLOBAL_ENV);
2569 while (stab->kind == US_CBRANCH)
2572 llassert (stab != GLOBAL_ENV);
2576 ** if its a fall through case, merge in outside entries and last case.
2581 ** case 1: x = 3; <fall through>
2582 ** case 2: << x may not be defined
2586 if (!mustBreak && !mustReturn && utab->kind == US_CBRANCH)
2588 llassert (stab->kind == US_SWITCH || stab->kind == US_NORMAL);
2590 usymtab_entries (utab, ue) /* but, keep track of used variables */
2592 uentry old = usymtab_lookupAux (stab, uentry_rawName (ue));
2594 llassert (uentry_isValid (old));
2596 /* modifies ue, not old */
2598 uentry_mergeState (ue, old, exprNode_loc (last),
2599 FALSE, FALSE, TRUE, CASECLAUSE);
2600 } end_usymtab_entries;
2602 utab->aliases = aliasTable_levelUnion (utab->aliases,
2603 stab->aliases, utab->lexlevel);
2606 ** No need for a new branch.
2613 usymtab_caseBranch ();
2614 /*@-mustfree@*/ /*< utab->aliases >*/
2615 utab->aliases = aliasTable_copy (stab->aliases);
2623 ** for && (both pred and expr are executed)
2627 usymtab_popAndBranch (exprNode pred, /*@unused@*/ exprNode expr)
2630 usymtab env = utab->env;
2634 llassert (utab->kind == US_TBRANCH);
2637 ** merge each entry in table with its original
2638 ** unless execution cannot continue after this branch
2641 for (i = 0; i < utab->nentries; i++)
2643 uentry current = utab->entries[i];
2644 sRef tref = uentry_getSref (current);
2645 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2646 sRef oref = uentry_getSref (old);
2648 /* note that is current is in a nested branch,
2649 it may create a "new" old entry. */
2651 llassert (uentry_isValid (old));
2652 uentry_mergeState (old, current, exprNode_loc (expr),
2653 FALSE, FALSE, TRUE, ANDCLAUSE);
2656 ** if is it defined by the second clause, then it should be defined.
2659 if (sRef_isAnyDefined (tref)
2660 && (sRef_isAllocated (oref) || sRef_isStateUndefined (oref)))
2662 sRef_setDefined (oref, g_currentloc);
2666 utab->guards = guardSet_levelUnionFree (utab->guards,
2667 guardSet_invert (exprNode_getGuards (pred)),
2669 utab->aliases = aliasTable_levelUnion (utab->aliases, otab->aliases, utab->lexlevel);
2671 usymtab_quietPlainExitScope ();
2676 ** Stack should be [ US_CBRANCH+ US_SWITCH ]
2677 ** Only branches which do not return (except possibly the last branch) are included.
2679 ** Conditionally merge state from all CBRANCHes.
2681 ** If allpaths is TRUE, then all possible executions go through some switch
2682 ** case, and the original scope is not merged.
2686 usymtab_exitSwitch (/*@unused@*/ exprNode sw, bool allpaths)
2689 usymtab ttab = utab;
2690 usymtab stab = ttab;
2691 usymtab ltab = ttab;
2692 bool lastMustReturn = usymtab_mustEscape (utab);
2696 while (stab->kind == US_CBRANCH)
2699 llassert (stab != GLOBAL_ENV);
2702 while (stab->kind == US_NORMAL)
2705 llassert (stab != GLOBAL_ENV);
2708 llassert (stab->kind == US_SWITCH);
2710 /* go to the scope outside the switch (US_SWITCH is just a marker! */
2712 llassert (stab != GLOBAL_ENV);
2716 llassert (usymtab_isDefined (ttab));
2718 if (ttab->kind == US_CBRANCH)
2720 /* was quietPlainExitScope --- but, can't free it yet! */
2722 llassert (utab != GLOBAL_ENV);
2724 while (ttab->kind == US_CBRANCH)
2727 ** (from popTrueBranch)
2730 bool mustReturn = usymtab_mustEscape (ttab);
2731 bool mustBreak = usymtab_mustBreak (ttab);
2733 usymtab_entries (ttab, current)
2735 uentry old = /*@-compmempass@*/ usymtab_lookupAux (ltab, uentry_rawName (current));
2739 ** note that is this is in a nested branch,
2740 ** it may create a "new" old entry.
2743 if (uentry_isValid (old))
2747 uentry_mergeUses (current, old);
2748 uentry_setState (old, current);
2752 uentry_mergeState (old, current, exprNode_loc (sw),
2753 mustReturn, FALSE, TRUE, SWITCHCLAUSE);
2760 } end_usymtab_entries;
2763 ** if entry is not in symbol table for this case, merge with pre-switch
2767 if (!mustReturn && !mustBreak)
2769 usymtab_entries (stab, current)
2771 if (usymtab_getIndex (ttab, uentry_rawName (current)) == NOT_FOUND)
2773 uentry old = /*@-compmempass@*/
2774 usymtab_lookupAux (ltab, uentry_rawName (current));
2777 llassert (uentry_isValid (old));
2778 uentry_mergeState (old, current, exprNode_loc (sw),
2779 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2781 } end_usymtab_entries;
2784 ltab->env = ttab->env;
2788 ** Suprious error, becuase of environments.
2791 /*@i1@*/ utab = ltab;
2793 lastMustReturn = FALSE;
2800 ** now, there is one US_CBRANCH. Merge this with the stab.
2804 for (i = 0; i < ltab->nentries; i++)
2806 uentry current = ltab->entries[i];
2807 uentry old = usymtab_lookupAux (stab, uentry_rawName (current));
2809 /* note that is this is in a nested branch,
2810 it may create a "new" old entry. */
2813 if (uentry_isValid (old))
2817 uentry_mergeUses (current, old);
2818 uentry_setState (old, current);
2822 uentry_mergeState (old, current, exprNode_loc (sw),
2823 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2837 ** switch may or may not be followed by a new scope
2840 if (utab->kind == US_SWITCH)
2842 usymtab_quietPlainExitScope ();
2846 usymtab_quietPlainExitScope ();
2847 llassert (utab->kind == US_SWITCH);
2848 usymtab_quietPlainExitScope ();
2854 updateNullState (sRef el, /*@notnull@*/ usymtab ttab,
2855 /*@notnull@*/ usymtab ftab, bool trueGuard)
2857 sRef base = sRef_getRootBase (el);
2858 int level = sRef_lexLevel (base);
2860 if (sRef_isCvar (base))
2862 usymId index = sRef_getScopeIndex (base);
2863 uentry ue = usymtab_getRefTab (ttab, level, index);
2865 if (!uentry_isLset (ue))
2867 sRef sr = uentry_getSref (ue);
2871 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2875 if (!guardSet_isGuarded (ttab->guards, el)
2876 && !sRef_isNotNull (sr))
2878 sRef_setDerivNullState (sr, el, NS_DEFNULL);
2886 ue = usymtab_getRefTab (ftab, level, index);
2888 if (!uentry_isLset (ue))
2890 sRef sr = uentry_getSref (ue);
2893 if (!trueGuard) /* yikes! forgot the ! */
2895 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2900 if (!guardSet_isGuarded (ftab->guards, el)
2901 && !sRef_isNotNull (sr))
2903 sRef_setDerivNullState (sr, el, NS_DEFNULL);
2915 usymtab_popBranches (exprNode pred, exprNode tbranch, exprNode fbranch,
2916 bool isOpt, clause cl)
2920 usymtab ftab = utab;
2921 usymtab ttab = utab->env;
2925 guardSet guards = exprNode_getGuards (pred);
2926 sRefSet tguards = guardSet_getTrueGuards (guards);
2927 sRefSet fguards = guardSet_getFalseGuards (guards);
2928 bool mustReturnT = exprNode_mustEscape (tbranch);
2929 bool mustReturnF = exprNode_mustEscape (fbranch);
2931 DPRINTF (("Pop branches: %s [mustreturn: %s/%s]", exprNode_unparse (pred),
2932 bool_unparse (mustReturnT),
2933 bool_unparse (mustReturnF)));
2935 if (exprNode_isDefined (fbranch))
2937 loc = exprNode_loc (fbranch);
2941 loc = exprNode_loc (tbranch);
2944 llassert (usymtab_isDefined (ttab));
2948 llassert (usymtab_isDefined (env));
2949 llassert (ftab->kind == US_FBRANCH);
2950 llassert (ttab->kind == US_TBRANCH);
2953 ** For each element that is true guarded (i.e., if (x != NULL))
2954 ** make x = null in false branch,
2955 ** and x = notnull in true branch.
2956 ** unless x was set locally in that branch.
2957 ** For each element that is false guarded (x == NULL)
2958 ** make x = null in true, notnull in false.
2960 ** For each element that is either guarded (pred(x))
2964 sRefSet_allElements (tguards, el)
2966 updateNullState (el, ttab, ftab, TRUE);
2967 } end_sRefSet_allElements;
2969 sRefSet_allElements (fguards, el)
2971 updateNullState (el, ttab, ftab, FALSE);
2972 } end_sRefSet_allElements;
2976 ** if an entry is in both true and false, merge the entries,
2977 ** then replace original with new state.
2979 ** if an entry is in one table, merge it with the original.
2982 DPRINTF (("ftab: %d", ftab->nentries));
2984 for (i = 0; i < ftab->nentries; i++)
2986 uentry fthis = ftab->entries[i];
2987 uentry old = usymtab_lookupAux (env, uentry_rawName (fthis));
2988 int tindex = usymtab_getIndex (ttab, uentry_rawName (fthis));
2990 DPRINTF (("Entry: %s / %s", uentry_unparseFull (fthis), uentry_unparseFull (old)));
2992 if (uentry_isUndefined (old))
2994 /* possible entry was added as an undefined id */
2995 DPRINTF (("Undefined! %s", uentry_rawName (fthis)));
2999 if (tindex != NOT_FOUND)
3001 uentry tthis = ttab->entries[tindex];
3003 /* note that is this is in a nested branch,
3004 it may create a "new" old entry. */
3010 uentry_mergeState (fthis, tthis, loc,
3011 mustReturnT, FALSE, FALSE, cl);
3015 uentry_mergeUses (fthis, tthis);
3018 uentry_setState (old, fthis);
3025 uentry_setState (old, tthis);
3026 uentry_mergeState (old, fthis, loc, mustReturnF,
3030 ttab->entries[tindex] = uentry_undefined;
3031 uentry_free (tthis);
3035 uentry_mergeState (old, fthis, loc, mustReturnF, TRUE, FALSE, cl);
3039 for (i = 0; i < ttab->nentries; i++)
3041 uentry current = ttab->entries[i];
3043 DPRINTF (("ttab: %s", uentry_unparseFull (current)));
3045 if (!uentry_isUndefined (current))
3047 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
3049 DPRINTF (("Old: %s", uentry_unparseFull (old)));
3051 if (uentry_isUndefined (old))
3053 llcontbug (message ("Undefined entry: %s", uentry_rawName (current)));
3059 uentry_mergeUses (current, old);
3060 uentry_setState (old, current);
3065 ** Assumes false branch is a fall-through if
3066 ** fbranch is not defined. This is true, unless
3067 ** where was some greivous error in processing
3068 ** the else branch of an if-then, in which case
3069 ** this is probably the right thing to do anyway.
3072 uentry_mergeState (old, current, loc, mustReturnT,
3076 DPRINTF (("==> %s", uentry_unparseFull (old)));
3081 ** Plain levelUnion doesn't work, since we need to use the sRef's in env->aliases
3082 ** if they are present.
3085 llassert (NOALIAS (env->aliases, ttab->aliases));
3086 llassert (NOALIAS (env->aliases, ftab->aliases));
3088 aliasTable_free (env->aliases);
3090 env->aliases = aliasTable_levelUnionNew (ttab->aliases,
3091 ftab->aliases, env->lexlevel);
3093 aliasTable_fixSrefs (env->aliases);
3095 DPRINTF (("Aliases: %s", aliasTable_unparse (env->aliases)));
3097 /* exit true and false scopes */
3098 usymtab_quietPlainExitScope ();
3099 usymtab_quietPlainExitScope ();
3103 utab->guards = guardSet_levelUnionFree
3105 guardSet_invert (exprNode_getGuards (pred)),
3111 utab->guards = guardSet_levelUnion (utab->guards,
3112 exprNode_getGuards (pred),
3116 DPRINTF (("Here."));
3119 static void usymtab_fixCases (void) /*@modifies utab@*/ {
3120 while (utab->kind == US_CBRANCH)
3122 usymtab_quietPlainExitScope ();
3125 llassert (utab->kind != US_CBRANCH);
3129 usymtab_altBranch (/*@only@*/ guardSet guards)
3133 usymtab parent = utab->env;
3135 t = usymtab_create (US_FBRANCH, utab, FALSE);
3138 ** If we are in a case, need to close it. The C syntax
3139 ** is very liberal, so this kludge is necessary.
3142 usymtab_fixCases ();
3144 DPRINTF (("Current kind: %s", usymtab_unparseStack ()));
3146 llassert (utab->kind == US_TBRANCH);
3147 llassert (parent != GLOBAL_ENV);
3149 guardSet_free (t->guards);
3152 aliasTable_free (t->aliases);
3153 t->aliases = aliasTable_copy (parent->aliases);
3159 usymtab_allDefined (void)
3160 /*@globals utab, globtab@*/
3164 llassert (utab == globtab);
3166 for (i = 0; i < utab->nentries; i++)
3168 uentry e = utab->entries[i];
3170 if (uentry_isPriv (e))
3172 ; /* no need to define it */
3176 if (context_getFlag (FLG_SPECUNDECL))
3178 fileloc sloc = uentry_whereSpecified (e);
3179 fileloc dloc = uentry_whereDeclared (e);
3181 if (fileloc_isDefined (sloc)
3182 && !uentry_isFakeTag (e)
3183 && !fileloc_isDefined (dloc))
3187 message ("%s %q specified but not declared",
3188 ekind_capName (uentry_getKind (e)),
3189 uentry_getName (e)),
3194 if (!uentry_isCodeDefined (e))
3196 fileloc dloc = uentry_whereDeclared (e);
3198 if (fileloc_isLib (dloc) || fileloc_isXHFile (dloc))
3202 else if (fileloc_isDefined (dloc))
3204 if (!uentry_isAnyTag (e))
3206 if (fileloc_isUser (dloc))
3210 message ("%s %q declared but not defined",
3211 ekind_capName (uentry_getKind (e)),
3212 uentry_getName (e)),
3214 DPRINTF (("decl: %s", uentry_unparseFull (e)));
3220 fileloc sloc = uentry_whereSpecified (e);
3222 if (fileloc_isDefined (sloc)
3223 && !fileloc_isImport (sloc)
3224 && !fileloc_isLib (sloc)
3225 && !fileloc_isPreproc (sloc)
3226 && !uentry_isFakeTag (e))
3228 if (uentry_isVariable (e) || uentry_isFunction (e))
3232 message ("%s %q specified but not declared or defined",
3233 ekind_capName (uentry_getKind (e)),
3234 uentry_getName (e)),
3241 message ("%s %q specified but not defined",
3242 ekind_capName (uentry_getKind (e)),
3243 uentry_getName (e)),
3253 void usymtab_exportHeader (void)
3258 for (i = 0; i < utab->nentries; i++)
3260 uentry ce = utab->entries[i];
3262 if (!uentry_isDatatype (ce)
3263 && !uentry_isAnyTag (ce)
3264 && !uentry_isEitherConstant (ce) && !uentry_isStatic (ce)
3265 && !uentry_isExternal (ce)
3266 && !uentry_isForward (ce))
3268 fileloc fwhere = uentry_whereDeclared (ce);
3270 if (fileloc_isUndefined (fwhere)
3271 && uentry_isFunction (ce))
3273 fwhere = uentry_whereDefined (ce);
3276 if (fileloc_isDefined (fwhere)
3277 && !fileloc_isHeader (fwhere)
3278 && !fileloc_isXHFile (fwhere)
3279 && !(fileloc_isSpecialFile (fwhere)
3280 && !context_getFlag (FLG_UNUSEDSPECIAL)))
3282 if (uentry_isVariable (ce))
3285 (FLG_EXPORTHEADERVAR,
3286 message ("%s %q exported but not declared in header file",
3287 ekind_capName (uentry_getKind (ce)),
3288 uentry_getName (ce)),
3291 uentry_showDefSpecInfo (ce, fwhere);
3296 if (!uentry_isIter (ce)
3297 && !uentry_isEndIter (ce)
3298 && !uentry_isExpandedMacro (ce))
3300 if (uentry_isFunction (ce)
3301 && cstring_equalLit (uentry_rawName (ce), "main"))
3303 ; /* no error for main */
3309 message ("%s %q exported but not declared "
3311 ekind_capName (uentry_getKind (ce)),
3312 uentry_getName (ce)),
3315 uentry_showDefSpecInfo (ce, fwhere);
3325 void usymtab_exportLocal (void)
3330 for (i = 0; i < utab->nentries; i++)
3332 uentry ce = utab->entries[i];
3334 if (!uentry_isDatatype (ce) && !uentry_isAnyTag (ce)
3335 && !uentry_isEitherConstant (ce)
3336 && !uentry_isIter (ce)
3337 && !uentry_isEndIter (ce)
3338 && !uentry_isExpandedMacro (ce)
3339 && uentry_isUsed (ce))
3341 /* check static uses */
3342 filelocList fuses = uentry_getUses (ce);
3343 fileloc mod = uentry_whereDefined (ce);
3344 bool ok = filelocList_isEmpty (fuses);
3345 fileloc fwhere = uentry_whereDeclared (ce);
3347 if (fileloc_isSpecialFile (fwhere)
3348 && !context_getFlag (FLG_UNUSEDSPECIAL))
3350 ok = TRUE; /* no errors for special files */
3354 filelocList_elements (fuses, uloc)
3356 if (fileloc_isUndefined (uloc) || !fileloc_sameModule (uloc, mod))
3359 /*@innerbreak@*/ break;
3361 } end_filelocList_elements;
3368 message ("%s exported but not used outside %s: %q",
3369 ekind_capName (uentry_getKind (ce)),
3370 fileloc_getBase (mod),
3371 uentry_getName (ce)),
3374 uentry_showDefSpecInfo (ce, fwhere);
3382 usymtab_allUsed (void)
3386 bool isFileStatic = usymtab_inFileScope ();
3387 cstring last_file = cstring_undefined;
3389 for (i = 0; i < utab->nentries; i++)
3391 bool hasError = FALSE;
3392 uentry ce = utab->entries[i];
3393 fileloc fwhere = uentry_whereDeclared (ce);
3395 if (fileloc_isUndefined (fwhere))
3397 fwhere = uentry_whereDefined (ce);
3400 if (fileloc_isInvalid (fwhere)
3401 || fileloc_isLib (fwhere)
3402 || fileloc_isBuiltin (fwhere)
3403 || ((fileloc_isSpecialFile (fwhere)
3404 || fileloc_isSpecialFile (uentry_whereDefined (ce)))
3405 && !context_getFlag (FLG_UNUSEDSPECIAL)))
3409 else if (!uentry_wasUsed (ce) && !uentry_isAnyTag (ce))
3411 cstring fname = fileloc_filename (fwhere);
3413 if (cstring_isUndefined (last_file))
3417 else if (cstring_equal (fname, last_file))
3426 if (uentry_isParam (ce))
3428 if (context_inMacro ())
3430 sRef cref = uentry_getSref (ce);
3432 if (uentry_isYield (ce))
3434 ; /* no checks (for now) */
3436 else if (sRef_isSafe (cref))
3442 if (uentry_hasRealName (ce))
3445 optgenerror (FLG_MACROPARAMS,
3446 message ("Macro parameter %q not used",
3447 uentry_getName (ce)),
3454 if (cstring_equalFree (uentry_getName (ce),
3455 cstring_makeLiteral ("...")))
3461 hasError = optgenerror (FLG_PARAMUNUSED,
3462 message ("Parameter %q not used",
3463 uentry_getName (ce)),
3468 else if (uentry_isFunction (ce) || uentry_isIter (ce))
3470 if (fileloc_isUser (fwhere))
3472 hasError = optgenerror
3474 message ("%q %q declared but not used",
3476 (uentry_isIter (ce) ? "Iterator"
3477 : (isFileStatic ? "File static function" : "Function")),
3478 uentry_getName (ce)),
3482 else if (uentry_isEndIter (ce))
3484 ; /* no error (already reported for iter */
3486 else if (uentry_isEnumConstant (ce))
3488 if (fileloc_isUser (fwhere))
3490 hasError = optgenerror
3492 message ("Enum member %q not used",
3493 uentry_getName (ce)),
3497 else if (uentry_isConstant (ce))
3499 if (fileloc_isUser (fwhere))
3501 hasError = optgenerror
3503 message ("Constant %q declared but not used",
3504 uentry_getName (ce)),
3508 else if (uentry_isDatatype (ce))
3510 if (fileloc_isUser (fwhere))
3512 hasError = optgenerror
3514 message ("Type %q declared but not used",
3515 uentry_getName (ce)),
3519 else if (!uentry_isRefParam (ce) && !uentry_isExpandedMacro (ce))
3520 { /* errors for ref params will be reported in the next scope */
3521 llassertprint (uentry_isVar (ce),
3522 ("ce: %s", uentry_unparseFull (ce)));
3524 if (ctype_isFunction (uentry_getType (ce)))
3526 if (fileloc_isUser (fwhere))
3528 hasError = optgenerror
3530 message ("%q %q declared but not used",
3532 (isFileStatic ? "File static function"
3534 uentry_getName (ce)),
3540 if (fileloc_isUser (fwhere))
3544 hasError = optgenerror
3546 message ("%q %q declared but not used",
3548 (isFileStatic ? "File static variable"
3550 uentry_getName (ce)),
3560 else if ((uentry_isDatatype (ce) || uentry_isAnyTag (ce)))
3561 { /* check all fields */
3562 ctype ct = uentry_getRealType (ce);
3565 while (ctype_isAP (ct))
3567 ct = ctype_getBaseType (ct);
3570 if (ctype_isSU (ct))
3572 uentryList fields = ctype_getFields (ct);
3574 uentryList_elements (fields, field)
3576 if (!uentry_isUsed (field))
3578 if (uentry_hasName (ce))
3580 hasError |= optgenerror
3582 message ("Field %q of %s %q declared but not used",
3583 uentry_getName (field),
3584 cstring_makeLiteralTemp
3585 (ctype_isStruct (ct) ? "structure" : "union"),
3586 uentry_getName (ce)),
3587 uentry_whereEarliest (field));
3593 ** Can't report these errors for unnamed structs.
3594 ** No way to tell when there are multiple consistent
3595 ** unnamed structure types. (Could go through table
3596 ** and mark them all unused...)
3598 hasError |= optgenerror
3600 message ("Field %q of unnamed %s declared but not used",
3601 uentry_getName (field),
3602 cstring_makeLiteralTemp
3603 (ctype_isStruct (ct) ? "structure" : "union")),
3604 uentry_whereEarliest (field));
3609 uentry_setUsed (field, fileloc_undefined);
3611 } end_uentryList_elements;
3621 if (uentry_isParam (ce) && context_inMacro ())
3623 if (fileloc_isDefined (uentry_whereSpecified (ce)))
3625 uentry_showWhereSpecified (ce);
3630 uentry_showDefSpecInfo (ce, fwhere);
3633 uentry_setUsed (ce, fileloc_undefined);
3639 checkGlobalReturn (uentry glob, sRef orig)
3641 sRef sr = uentry_getSref (glob);
3643 DPRINTF (("Check global return: %s / orig: %s / sr: %s",
3644 uentry_unparseFull (glob),
3645 sRef_unparseFull (orig),
3646 sRef_unparseFull (sr)));
3648 DPRINTF (("Is killed: %s", bool_unparse (sRef_isKilledGlob (orig))));
3650 if (context_getFlag (FLG_GLOBSTATE))
3652 DPRINTF (("Is killed: %s", sRef_unparseFull (orig)));
3654 if (sRef_isKilledGlob (orig))
3656 if (sRef_isStateUndefined (sr)
3657 || sRef_isUnuseable (sr)
3658 || sRef_isStateUnknown (sr)
3659 || sRef_isDead (sr))
3665 ctype ct = ctype_realType (uentry_getType (glob));
3667 if (ctype_isVisiblySharable (ct))
3672 ("Killed global %q (type %s) not released before return",
3673 uentry_getName (glob),
3674 ctype_unparse (ct)),
3677 sRef_showStateInfo (sr);
3682 sRef_protectDerivs ();
3683 (void) checkGlobalDestroyed (sr, g_currentloc);
3684 sRef_clearProtectDerivs ();
3690 if (sRef_isStateUndefined (sr))
3692 if (optgenerror (FLG_GLOBSTATE,
3694 ("Function returns with global %q undefined",
3695 uentry_getName (glob)),
3698 sRef_showStateInfo (sr);
3703 if (sRef_isDead (sr) || sRef_isKept (sr))
3707 message ("Function returns with global %q "
3708 "referencing %s storage",
3709 uentry_getName (glob),
3710 cstring_makeLiteralTemp (sRef_isDead (sr) ? "released" : "kept")),
3713 if (sRef_isKept (sr))
3715 sRef_showAliasInfo (sr);
3719 sRef_showStateInfo (sr);
3722 sRef_setDefState (sr, SS_UNKNOWN, fileloc_undefined);
3726 if (ctype_isRealPointer (uentry_getType (glob))
3727 && sRef_possiblyNull (sr)
3728 && !uentry_possiblyNull (glob))
3732 message ("Function returns with non-null global %q "
3733 "referencing null storage",
3734 uentry_getName (glob)),
3737 sRef_showNullInfo (sr);
3742 checkGlobReturn (glob);
3750 ** remember: check alias globals
3753 void usymtab_checkFinalScope (bool isReturn)
3756 bool mustFree = context_getFlag (FLG_MUSTFREE);
3757 bool mustDefine = context_getFlag (FLG_MUSTDEFINE);
3758 /* bool mustNotAlias = context_getFlag (FLG_MUSTNOTALIAS); */
3759 sRefSet checked = sRefSet_new ();
3760 usymtab stab = utab;
3764 ** need to check all scopes out to function parameters.
3769 for (i = 0; i < stab->nentries; i++)
3771 uentry ce = stab->entries[i];
3772 sRef sr = uentry_getSref (ce);
3773 sRef rb = sRef_getRootBase (sr);
3777 ** Shouldn't check if shadow checked in deeper scope:
3782 uentry oue = usymtab_lookupQuietNoAlt (utab, uentry_observeRealName (ce));
3784 if (!uentry_sameObject (ce, oue))
3786 DPRINTF (("Skipping outer entry: %s / %s", uentry_unparseFull (ce),
3787 uentry_unparseFull (oue)));
3788 /*@i32 what if it is one an alternate branch? */
3789 /*@innercontinue@*/ continue;
3793 DPRINTF (("Here check final scope: %s", uentry_unparseFull (ce)));
3795 if (ctype_isFunction (uentry_getType (ce)))
3797 /*@innercontinue@*/ continue;
3800 if (uentry_isAnyParam (ce)
3801 || uentry_isRefParam (ce)
3802 || sRef_isFileOrGlobalScope (rb))
3804 /* Don't do the loseref check...but should check state! */
3806 else if (sRef_isDefinitelyNull (sr)
3807 || usymtab_isDefinitelyNull (sr))
3810 ** No state reference errors for definitely null references.
3815 DPRINTF (("Lose ref: %s / %s", uentry_unparse (ce),
3816 sRef_unparseFull (sr)));
3818 tvalues = sRef_getValueTable (sr);
3820 valueTable_elements (tvalues, fkey, fval) {
3821 metaStateInfo minfo;
3822 cstring msg = cstring_undefined;
3825 minfo = context_lookupMetaStateInfo (fkey);
3826 llassert (metaStateInfo_isDefined (minfo));
3828 if (stateValue_isError (fval)
3829 || sRef_isStateUndefined (sr)) /* No errors for undefined state */
3835 DPRINTF (("Check: %s / %s / %s", fkey,
3836 metaStateInfo_unparse (minfo),
3837 stateValue_unparse (fval)));
3839 minfo = context_lookupMetaStateInfo (fkey);
3841 nval = stateCombinationTable_lookupLoseReference
3842 (metaStateInfo_getTransferTable (minfo),
3843 stateValue_getValue (fval), &msg);
3845 if (cstring_isDefined (msg))
3847 /*@i32 print extra info for assignments@*/
3848 DPRINTF (("From: %s", sRef_unparseFull (sr)));
3849 DPRINTF (("Null? %s / %s",
3850 bool_unparse (sRef_isDefinitelyNull (sr)),
3851 bool_unparse (usymtab_isGuarded (sr))));
3856 ("%s loses reference %q in invalid state %q (%s)",
3857 cstring_makeLiteralTemp (isReturn ? "Return" : "Scope exit"),
3858 uentry_getName (ce),
3859 stateValue_unparseValue (fval, minfo),
3863 stateValue_show (fval, minfo);
3867 DPRINTF (("Suppressed transfer error: %s", msg));
3871 } end_valueTable_elements;
3876 DPRINTF (("Check entry: %s", uentry_unparseFull (ce)));
3878 if (!sRefSet_member (checked, sr) && !sRef_isFileOrGlobalScope (rb))
3880 if (ctype_isRealSU (uentry_getType (ce))
3881 && !uentry_isAnyParam (ce)
3882 && !uentry_isRefParam (ce)
3883 && !uentry_isStatic (ce)
3884 && !sRef_isDependent (sr)
3885 && !sRef_isOwned (sr))
3887 sRefSet als = usymtab_allAliases (sr);
3889 if (sRefSet_isEmpty (als))
3891 checkLocalDestroyed (sr, g_currentloc);
3895 /* aliased, no problem */ ;
3901 (!uentry_isStatic (ce)
3902 && ((sRef_isNewRef (sr))
3903 || (((sRef_isOnly (sr) || sRef_isFresh (sr)
3904 || sRef_isKeep (sr) || sRef_isOwned (sr))
3905 && !sRef_isDead (sr))
3906 && (!sRef_definitelyNull (sr))
3907 && (!usymtab_isDefinitelyNull (sr)))))
3909 bool hasError = TRUE;
3911 DPRINTF (("Checking: %s", sRef_unparseFull (sr)));
3914 ** If its a scope exit, check if there is an alias.
3915 ** If so, make it only. If not, there is an error.
3920 if (canLoseReference (sr, g_currentloc))
3922 DPRINTF (("Can lose!"));
3929 if (sRef_hasLastReference (sr))
3931 sRef ar = sRef_getAliasInfoRef (sr);
3936 ("Last reference %q to %s storage %qnot %q before %q",
3938 alkind_unparse (sRef_getAliasKind (sr)),
3939 sRef_unparseOpt (ar),
3940 cstring_makeLiteral (sRef_isKeep (sr)
3941 ? "transferred" : "released"),
3942 cstring_makeLiteral (isReturn
3943 ? "return" : "scope exit")),
3946 sRef_showRefLost (sr);
3949 else if (sRef_isNewRef (sr))
3954 ("%q %q not released before %q",
3956 (alkind_isKillRef (sRef_getOrigAliasKind (sr))
3957 ? "Kill reference parameter" : "New reference"),
3958 uentry_getName (ce),
3959 cstring_makeLiteral (isReturn
3960 ? "return" : "scope exit")),
3963 sRef_showAliasInfo (sr);
3968 if (ctype_isRealSU (sRef_getType (sr)))
3970 checkStructDestroyed (sr, g_currentloc);
3974 DPRINTF (("Here we are: %s", sRef_unparseFull (sr)));
3979 ("%s storage %q not %q before %q",
3980 alkind_capName (sRef_getAliasKind (sr)),
3981 uentry_getName (ce),
3982 cstring_makeLiteral (sRef_isKeep (sr)
3983 ? "transferred" : "released"),
3984 cstring_makeLiteral (isReturn
3985 ? "return" : "scope exit")),
3988 sRef_showAliasInfo (sr);
3989 DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
4000 else if (mustDefine && uentry_isOut (ce))
4002 if (!ynm_toBoolStrict (sRef_isReadable (sr)))
4006 message ("Out storage %q not defined before %q",
4007 uentry_getName (ce),
4009 (isReturn ? "return" : "scope exit")),
4012 /* uentry_showWhereDeclared (ce); */
4021 ** also check state is okay
4024 if (usymtab_lexicalLevel () > functionScope
4025 && uentry_isVariable (ce)
4026 && (sRef_isLocalVar (sr)
4027 && (sRef_isDependent (sr) || sRef_isLocalState (sr))))
4029 sRefSet ab = usymtab_aliasedBy (sr);
4031 /* should do something more efficient here */
4033 if (sRefSet_isEmpty (ab))
4035 /* and no local ref */
4036 DPRINTF (("Check lose ref: %s", uentry_unparseFull (ce)));
4051 checked = sRefSet_insert (checked, sr);
4055 llassert (usymtab_isDefined (stab->env));
4057 if (usymtab_isBranch (stab))
4059 stab = usymtab_dropEnv (stab);
4066 llassert (stab != usymtab_undefined);
4067 } while (isReturn && (stab->lexlevel >= paramsScope));
4069 sRefSet_free (checked);
4073 ** all globals are appropriately defined
4074 ** all parameters are appropriately defined
4075 ** special clauses are followed
4078 if (isReturn || (utab->lexlevel == paramsScope))
4080 uentry fcn = context_getHeader ();
4081 uentryList params = context_getParams ();
4082 globSet uglobs = context_getUsedGlobs ();
4083 globSet sglobs = context_getGlobs ();
4085 if (isReturn && context_maybeSet (FLG_GLOBALIAS))
4087 aliasTable_checkGlobs (utab->aliases);
4091 ** state clauses (ensures, defines, sets, allocates, releases)
4094 if (uentry_hasStateClauseList (fcn))
4096 stateClauseList clauses = uentry_getStateClauseList (fcn);
4098 stateClauseList_elements (clauses, cl)
4100 if (stateClause_isAfter (cl) && !stateClause_isGlobal (cl))
4102 if (stateClause_setsMetaState (cl))
4104 sRefSet rfs = stateClause_getRefs (cl);
4105 qual q = stateClause_getMetaQual (cl);
4106 annotationInfo ainfo = qual_getAnnotationInfo (q);
4107 metaStateInfo minfo = annotationInfo_getState (ainfo);
4108 cstring key = metaStateInfo_getName (minfo);
4109 int mvalue = annotationInfo_getValue (ainfo);
4111 DPRINTF (("Post meta state clause: %s", stateClause_unparse (cl)));
4113 sRefSet_elements (rfs, el)
4115 sRef base = sRef_getRootBase (el);
4117 if (sRef_isResult (base))
4120 ** This is checked for return transfers.
4124 else if (sRef_isParam (base) || sRef_isGlobalMarker (base))
4126 sRef sr = sRef_updateSref (base);
4127 sr = sRef_fixBase (el, sr);
4129 if (!sRef_checkMetaStateValue (sr, key, mvalue))
4134 ("Ensures clause not satisfied%q (state is %q): %q",
4135 sRef_isGlobalMarker (sr)
4137 : message (" by %q", sRef_unparse (sr)),
4138 stateValue_unparseValue (sRef_getMetaStateValue (sr, key),
4140 stateClause_unparse (cl)),
4143 sRef_showMetaStateInfo (sr, key);
4149 if (sRef_isMeaningful (el))
4154 } end_sRefSet_elements ;
4158 /* evs - 2000 07 10 - added this */
4159 sRefTest tst = stateClause_getPostTestFunction (cl);
4160 sRefSet rfs = stateClause_getRefs (cl);
4162 sRefSet_elements (rfs, el)
4164 sRef base = sRef_getRootBase (el);
4166 if (sRef_isResult (base))
4169 ** This is checked for return transfers.
4174 else if (sRef_isParam (base))
4176 sRef sr = sRef_updateSref (base);
4177 sr = sRef_fixBase (el, sr);
4179 if (tst != NULL && !tst (sr))
4182 (stateClause_postErrorCode (cl),
4183 message ("%s storage %qcorresponds to "
4184 "storage listed in %q clause",
4185 stateClause_postErrorString (cl, sr),
4186 sRef_unparseOpt (sr),
4187 stateClause_unparseKind (cl)),
4190 sRefShower ss = stateClause_getPostTestShower (cl);
4197 DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
4203 if (sRef_isMeaningful (el))
4208 } end_sRefSet_elements ;
4211 } end_stateClauseList_elements ;
4215 ** check parameters on return
4218 uentryList_elements (params, arg)
4220 if (!uentry_isElipsisMarker (arg))
4222 ctype rt = ctype_realType (uentry_getType (arg));
4224 if (ctype_isMutable (rt) || ctype_isSU (rt))
4226 uentry param = usymtab_lookupQuiet (utab, uentry_rawName (arg));
4227 DPRINTF (("Check param return: %s", uentry_unparseFull (param)));
4228 checkParamReturn (param);
4231 } end_uentryList_elements;
4233 DPRINTF (("Check global return: %s",
4234 globSet_unparse (sglobs)));
4236 globSet_allElements (sglobs, el)
4238 sRef orig = el; /*! sRef_updateSref (el); */ /*!!!*/
4239 uentry current = sRef_getUentry (el);
4241 DPRINTF (("Check global return: %s / %s", sRef_unparseFull (el),
4242 uentry_unparseFull (current)));
4244 if (uentry_isVariable (current) && !uentry_isRealFunction (current))
4246 checkGlobalReturn (current, orig);
4248 } end_globSet_allElements;
4250 globSet_allElements (uglobs, el)
4252 if (!globSet_member (sglobs, el))
4254 uentry current = sRef_getUentry (el);
4256 if (uentry_isVariable (current)
4257 && !uentry_isRealFunction (current))
4259 checkGlobalReturn (current, sRef_undefined);
4262 } end_globSet_allElements;
4267 usymtab_quietExitScope (fileloc loc)
4268 /*@globals utab, globtab, filetab; @*/
4271 usymtab t = utab->env;
4273 if (utab->reftable != NULL)
4277 for (i = 0; i < utab->nentries; i++)
4279 uentry current = utab->entries[i];
4280 uentry old = usymtab_lookupAux (t, uentry_rawName (current));
4282 uentry_mergeState (old, current, loc, FALSE, FALSE, FALSE, NOCLAUSE);
4286 llassert (t != NULL);
4288 if (t->lexlevel > paramsScope)
4290 t->guards = guardSet_levelUnion (t->guards, utab->guards, t->lexlevel);
4291 t->aliases = aliasTable_levelUnionSeq (t->aliases, utab->aliases,
4293 utab->aliases = aliasTable_undefined;
4296 t->mustBreak = utab->mustBreak;
4297 t->exitCode = utab->exitCode;
4299 usymtab_freeLevel (utab);
4305 ** Exit a scope with no checking, lose alias states.
4306 ** (When should this be used?)
4309 void usymtab_quietPlainExitScope (void)
4310 /*@globals utab, globtab, filetab@*/
4313 usymtab t = utab->env;
4315 llassert (t != NULL);
4316 llassert (NOALIAS (utab->aliases, t->aliases));
4317 usymtab_freeLevel (utab);
4321 void usymtab_exitScope (exprNode expr)
4322 /*@globals utab, filetab, globtab@*/
4323 /*@modifies utab, globtab@*/
4325 usymtab ctab = usymtab_undefined;
4326 usymtab lctab = usymtab_undefined;
4327 bool mustReturn = exprNode_mustEscape (expr);
4329 DPRINTF (("Exit scope"));
4331 if (utab->kind == US_CBRANCH)
4334 ** save the case branches, remove the first non-cbranch
4339 while (utab->kind == US_CBRANCH)
4343 llassert (utab != GLOBAL_ENV);
4347 if (utab->kind == US_TBRANCH || utab->kind == US_FBRANCH
4348 || utab->kind == US_CBRANCH || utab->kind == US_SWITCH) {
4350 if (context_inMacro ()) {
4351 /* evs 2000-07-25 */
4352 /* Unparseable macro may end inside nested scope. Deal with it. */
4354 llerror (FLG_SYNTAX,
4355 message ("Problem parsing macro body of %s (unbalanced scopes). "
4356 "Attempting to recover, recommend /*@notfunction@*/ before "
4357 "macro definition.",
4358 context_inFunctionName ()));
4360 while (utab->kind == US_TBRANCH
4361 || utab->kind == US_FBRANCH
4362 || utab->kind == US_CBRANCH
4363 || utab->kind == US_SWITCH)
4366 llassert (utab != GLOBAL_ENV);
4369 llcontbug (message ("exitScope: in branch: %q", usymtab_unparseStack ()));
4371 } /*@=branchstate@*/
4375 ** check all variables in scope were used
4379 ** bogus errors if this is the normal inside a switch,
4380 ** since cases have not been merged yet. Should probably
4381 ** still check this, but I'm too lazy at the moment...
4384 llassertfatal (utab->env != GLOBAL_ENV);
4386 if (utab->env->kind != US_SWITCH)
4392 ** check aliasing: all only params are released (dead)
4393 ** definition: all out params are defined, all modified params
4394 ** are completely defined
4396 ** NOTE: note for exiting paramsScope, since checkReturn should be
4400 if (!mustReturn && (usymtab_lexicalLevel () > functionScope))
4403 ** should only call this is end of scope is reachable...
4406 usymtab_checkFinalScope (FALSE);
4409 if (usymtab_lexicalLevel () == paramsScope && context_inFunctionLike ())
4412 ** leaving a function, need to fix up globals
4415 uentryList params = context_getParams ();
4416 globSet globs = context_getUsedGlobs ();
4419 uentryList_elements (params, ue)
4421 uentry_fixupSref (ue);
4422 } end_uentryList_elements;
4424 clearFunctionTypes ();
4427 globSet_allElements (globs, el)
4429 if (sRef_isCvar (el))
4432 int index = sRef_getScopeIndex (el);
4434 if (sRef_isFileStatic (el))
4436 llassert (usymtab_isDefined (filetab));
4437 current = usymtab_fetchIndex (filetab, index);
4441 current = usymtab_fetchIndex (globtab, index);
4444 if (uentry_isVariable (current))
4446 uentry_fixupSref (current);
4450 sRef_clearDerived (uentry_getSref (current));
4453 } end_globSet_allElements;
4456 usymtab_quietExitScope (exprNode_loc (expr));
4458 if (lctab != usymtab_undefined)
4460 /*@i@*/ lctab->env = utab;
4461 /*@i@*/ utab = ctab;
4462 /*@-branchstate@*/ } /*@=branchstate@*/
4468 ** yikes! don't let the '170 kids see this one...
4472 uentry_directParamNo (uentry ue)
4474 if (uentry_isVar (ue))
4476 sRef sr = uentry_getSref (ue);
4478 if (sRef_lexLevel (sr) == functionScope)
4483 llassert (sr->info != NULL);
4484 llassert (sr->info->cvar != NULL);
4485 index = sr->info->cvar->index;
4488 if (index < uentryList_size (context_getParams ()))
4497 /*@dependent@*/ /*@exposed@*/ uentry
4498 usymtab_getParam (int paramno)
4502 ** requires in a function context (checked)
4504 ** depends on no nested functions --- the function
4505 ** parameters are ALWAYS one scope inside the global scope
4506 ** and entered in order!
4510 if (!context_inFunctionLike ())
4511 llfatalbug (message ("usymtab_getParam: not in function context: %q",
4512 context_unparse ()));
4514 while (s->lexlevel > paramsScope)
4519 llassert (usymtab_isDefined (s));
4521 if (paramno >= s->nentries)
4524 ** Parse errors lead to this.
4527 uentry err = uentry_makeVariableLoc (cstring_makeLiteralTemp ("<error>"),
4530 uentry_markOwned (err);
4534 return (s->entries[paramno]);
4537 static /*@dependent@*/ /*@exposed@*/ uentry
4538 usymtab_getRefTab (/*@notnull@*/ usymtab u, int level, usymId index)
4542 ue = usymtab_getRefNoisy (u, level, index);
4544 if (uentry_isUndefined (ue))
4546 llbug (message ("usymtab_getRef: out of range: %d. level = %d",
4553 static /*@dependent@*/ /*@exposed@*/ usymtab
4554 usymtab_dropEnv (/*@notnull@*/ usymtab s)
4556 if (s->kind == US_CBRANCH)
4564 llassert (s != GLOBAL_ENV);
4565 } while (s->kind == US_CBRANCH);
4566 /* drop all cases (except in nested scopes */
4569 llassert (s != GLOBAL_ENV);
4572 if (s->kind == US_FBRANCH)
4574 s = s->env; /* skip the true branch */
4575 llassert (usymtab_isDefined (s));
4576 llassert (s->kind == US_TBRANCH);
4579 llassert (s != GLOBAL_ENV);
4585 /*@dependent@*/ /*@exposed@*/ uentry
4586 usymtab_getRefQuiet (int level, usymId index)
4592 llassert (s != NULL);
4593 llassert (index >= 0);
4595 if (level > s->lexlevel)
4597 return uentry_undefined;
4600 llassertprint (level <= s->lexlevel, ("level: %d / lexlevel: %d",
4601 level, s->lexlevel));
4603 while (s->lexlevel > level)
4605 if (usymtab_isBranch (s))
4607 int eindex = refTable_lookup (s, level, index);
4609 if (eindex != NOT_FOUND)
4611 return (s->entries[eindex]);
4615 s = usymtab_dropEnv (s);
4618 while (usymtab_isBranch (s) && s->lexlevel == level)
4620 int eindex = refTable_lookup (s, level, index);
4622 if (eindex != NOT_FOUND)
4624 return (s->entries[eindex]);
4627 s = usymtab_dropEnv (s);
4630 if (index >= s->nentries)
4632 return uentry_undefined;
4635 llassert (!uentry_isUndefined (s->entries[index]));
4637 return s->entries[index];
4640 static /*@dependent@*/ /*@exposed@*/ uentry
4641 usymtab_getRefNoisy (/*@notnull@*/ usymtab s, int level, usymId index)
4644 uentry ue = uentry_undefined;
4646 llassert (index >= 0);
4648 while (s->lexlevel > level)
4650 if (usymtab_isBranch (s))
4652 int eindex = refTable_lookup (s, level, index);
4654 if (eindex != NOT_FOUND)
4656 ue = s->entries[eindex];
4660 while (!usymtab_isBranch (otab))
4662 otab = usymtab_dropEnv (otab);
4663 llassert (otab != GLOBAL_ENV);
4666 if (refTable_lookup (otab, level, index) == NOT_FOUND)
4668 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4680 s = usymtab_dropEnv (s);
4683 llassert (usymtab_isDefined (s));
4685 while (usymtab_isBranch (s) && s->lexlevel == level)
4687 int eindex = refTable_lookup (s, level, index);
4690 if (eindex != NOT_FOUND)
4692 ue = s->entries[eindex];
4696 while (!usymtab_isBranch (otab))
4698 otab = usymtab_dropEnv (otab);
4699 llassert (otab != GLOBAL_ENV);
4702 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4712 s = usymtab_dropEnv (s);
4715 if (s->lexlevel == level && (index < s->nentries))
4717 ue = s->entries[index];
4719 if (uentry_isValid (ue))
4723 while (!usymtab_isBranch (otab))
4725 otab = usymtab_dropEnv (otab);
4727 if (otab == GLOBAL_ENV)
4733 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4744 if (index >= s->nentries)
4746 return uentry_undefined;
4749 llassert (!uentry_isUndefined (s->entries[index]));
4751 return s->entries[index];
4755 ** looking up entries
4757 ** If entry is inside a branch, then copy it, and put it into
4758 ** the branch table.
4762 int refTable_lookup (/*@notnull@*/ usymtab ut, int level, int index)
4764 refTable rt = ut->reftable;
4767 llassert (rt != NULL);
4769 for (i = 0; i < ut->nentries; i++)
4771 if (rt[i]->level == level && rt[i]->index == index)
4781 /*@only@*/ refentry refentry_create (int level, int index)
4783 refentry r = (refentry) dmalloc (sizeof (*r));
4791 static /*@dependent@*/ /*@exposed@*/ uentry
4792 usymtab_addRefEntry (/*@notnull@*/ usymtab s, cstring k)
4797 if (ut->reftable == NULL)
4799 DPRINTF (("Adding ref entry without reftable: %s", k));
4800 return uentry_undefined;
4803 llassert (ut->reftable != NULL);
4805 while (s != GLOBAL_ENV)
4807 eindex = usymtab_getIndex (s, k);
4809 if (eindex != NOT_FOUND)
4811 uentry current = s->entries[eindex];
4813 if (uentry_isVar (current) && !ctype_isFunction (uentry_getType (current)))
4817 DPRINTF (("Here: copying %s", uentry_unparse (current)));
4818 ue = uentry_copy (current);
4819 DPRINTF (("Here: copying %s", uentry_unparse (ue)));
4820 usymtab_addEntryQuiet (ut, ue);
4821 DPRINTF (("Okay..."));
4823 if (s->reftable != NULL)
4825 refentry ref = s->reftable[eindex];
4827 ut->reftable[ut->nentries - 1]
4828 = refentry_create (ref->level, ref->index);
4832 ut->reftable[ut->nentries - 1]
4833 = refentry_create (s->lexlevel, eindex);
4844 s = usymtab_dropEnv (s);
4847 return uentry_undefined;
4850 static uentry usymtab_lookupAux (usymtab s, cstring k)
4852 DPRINTF (("Lookup: %s", k));
4854 while (s != GLOBAL_ENV)
4856 int eindex = usymtab_getIndex (s, k);
4858 if (eindex != NOT_FOUND)
4860 uentry ret = s->entries[eindex];
4864 if (s->kind == US_TBRANCH
4865 || s->kind == US_FBRANCH
4866 || s->kind == US_CBRANCH)
4867 /* uentry_isGlobalVariable (ret) && os->lexlevel > fileScope) */
4870 DPRINTF (("Adding global ref entry: %s", k));
4871 ret = usymtab_addRefEntry (os, k);
4872 DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
4877 DPRINTF (("Found: %s", uentry_unparseFull (ret)));
4881 if (s->kind == US_TBRANCH || s->kind == US_FBRANCH
4882 || s->kind == US_CBRANCH)
4884 /* why isn't this os??? */
4885 uentry ret = usymtab_addRefEntry (s, k);
4886 DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
4893 return uentry_undefined;
4896 static /*@dependent@*/ /*@exposed@*/ uentry
4897 usymtab_lookupQuietAux (usymtab s, cstring k, bool noalt)
4901 while (s != GLOBAL_ENV)
4903 eindex = usymtab_getIndex (s, k);
4905 if (eindex != NOT_FOUND)
4907 uentry ret = s->entries[eindex];
4911 if (noalt && usymtab_isBranch (s))
4913 s = usymtab_dropEnv (s);
4921 return uentry_undefined;
4924 static /*@exposed@*/ /*@dependent@*/ uentry
4925 usymtab_lookupQuiet (usymtab s, cstring k)
4927 return usymtab_lookupQuietAux (s, k, FALSE);
4930 static /*@exposed@*/ /*@dependent@*/ uentry
4931 usymtab_lookupQuietNoAlt (usymtab s, cstring k)
4933 return usymtab_lookupQuietAux (s, k, TRUE);
4936 /*@dependent@*/ /*@observer@*/ uentry
4937 usymtab_lookupSafe (cstring k)
4940 DPRINTF (("Lookup safe: %s", k));
4941 return (usymtab_lookupAux (utab, k));
4945 usymtab_lookupExpose (cstring k)
4948 uentry ce = usymtab_lookupAux (utab, k);
4950 if (uentry_isUndefined (ce))
4952 llfatalbug (message ("usymtab_lookup: not found: *%s*", k));
4955 if (uentry_isPriv (ce))
4957 llfatalbug (message ("usymtab_lookup: private: *%s*", k));
4963 uentry usymtab_lookupExposeGlob (cstring k)
4965 return (usymtab_lookupGlobSafe (k));
4968 uentry usymtab_lookupGlob (cstring k)
4969 /*@globals globtab@*/
4971 uentry ce = usymtab_lookupAux (globtab, k);
4973 if (uentry_isUndefined (ce))
4974 llfatalbug (message ("usymtab_lookup: not found: %s", k));
4976 if (uentry_isPriv (ce))
4977 llfatalbug (message ("usymtab_lookup: private: %s", k));
4982 /*@observer@*/ uentry
4983 usymtab_lookupGlobSafe (cstring k)
4984 /*@globals globtab@*/
4986 uentry ce = usymtab_lookupAux (globtab, k);
4991 uentry usymtab_lookupEither (cstring k)
4994 uentry ce = usymtab_lookupSafe (k);
4996 if (uentry_isUndefined (ce))
4997 llfatalerror (message ("usymtab_lookup: not found: %s", k));
5004 usymtab_lookupType (cstring k)
5005 /*@globals globtab@*/
5007 usymId uid = usymtab_getTypeId (k);
5009 if (uid == USYMIDINVALID)
5011 llcontbug (message ("usymtab_lookupType: not found: %s", k));
5012 return ctype_unknown;
5015 return (uentry_getRealType (usymtab_getTypeEntry (uid)));
5020 usymtab_lookupAbstractType (cstring k) /*@globals globtab@*/
5022 usymId uid = usymtab_getTypeId (k);
5024 if (uid == USYMIDINVALID)
5026 llcontbug (message ("usymtab_lookupType: not found: %s", k));
5027 return ctype_unknown;
5030 return (uentry_getAbstractType (usymtab_getTypeEntry (uid)));
5034 ** if there is an unnamed lcl-specified struct tag matching
5035 ** the uentryList, return its datatype. Otherwise, returns
5040 usymtab_structFieldsType (uentryList f)
5041 /*@globals globtab@*/
5043 return (usymtab_suFieldsType (f, TRUE));
5047 usymtab_unionFieldsType (uentryList f)
5048 /*@globals globtab@*/
5050 return (usymtab_suFieldsType (f, FALSE));
5054 usymtab_suFieldsType (uentryList f, bool isStruct)
5055 /*@globals globtab@*/
5059 DPRINTF (("Fields: %s", uentryList_unparse (f)));
5061 if (fileloc_isSpec (g_currentloc))
5063 return (ctype_undefined);
5066 for (i = 0; i < globtab->nentries; i++)
5068 uentry current = globtab->entries[i];
5071 ? uentry_isStructTag (current) : uentry_isUnionTag (current)))
5073 if (isFakeTag (uentry_rawName (current)))
5075 ctype ct = uentry_getType (current);
5077 DPRINTF (("Check: %s", ctype_unparse (ct)));
5079 if ((isStruct ? ctype_isStruct (ct) : ctype_isUnion (ct))
5081 (uentry_isSpecified (current)
5082 && uentryList_equivFields (f, ctype_getFields (ct))))
5084 return uentry_getAbstractType (current);
5094 return ctype_undefined;
5098 usymtab_enumEnumNameListType (enumNameList f)
5099 /*@globals globtab@*/
5103 for (i = 0; i < globtab->nentries; i++)
5105 uentry current = globtab->entries[i];
5107 if (uentry_isEnumTag (current))
5109 if (isFakeTag (uentry_rawName (current)))
5111 ctype ct = uentry_getType (current);
5113 if (ctype_isEnum (ct) && (enumNameList_match (f, ctype_elist (ct))))
5115 return uentry_getType (current);
5121 return ctype_undefined;
5125 usymtab_exists (cstring k)
5128 uentry ce = usymtab_lookupSafe (k);
5129 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5133 usymtab_existsReal (cstring k)
5136 uentry ce = usymtab_lookupSafe (k);
5138 return (!(uentry_isUndefined (ce))
5139 && !(uentry_isPriv (ce))
5140 && !(uentry_isExpandedMacro (ce)));
5144 usymtab_existsGlob (cstring k)
5145 /*@globals globtab@*/
5147 uentry ce = usymtab_lookupAux (globtab, k);
5149 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5154 usymtab_existsEither (cstring k)
5157 uentry ce = usymtab_lookupAux (utab, k);
5159 return (uentry_isValid (ce));
5163 usymtab_existsGlobEither (cstring k)
5164 /*@globals globtab@*/
5166 uentry ce = usymtab_lookupAux (globtab, k);
5168 return (uentry_isValid (ce));
5173 usymtab_existsType (cstring k)
5174 /*@globals globtab@*/
5176 uentry ce = usymtab_lookupAux (globtab, k);
5178 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && uentry_isDatatype (ce));
5182 usymtab_existsTypeEither (cstring k)
5183 /*@globals globtab@*/
5186 ce = usymtab_lookupAux (globtab, k);
5187 return (uentry_isValid (ce) && uentry_isDatatype (ce));
5191 usymtab_existsStructTag (cstring k) /*@globals globtab@*/
5193 cstring sname = makeStruct (k);
5194 uentry ce = usymtab_lookupAux (globtab, sname);
5195 cstring_free (sname);
5196 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5200 usymtab_existsUnionTag (cstring k) /*@globals globtab@*/
5202 cstring uname = makeUnion (k);
5203 uentry ce = usymtab_lookupAux (globtab, uname);
5205 cstring_free (uname);
5207 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5211 usymtab_existsEnumTag (cstring k) /*@globals globtab@*/
5213 cstring ename = makeEnum (k);
5214 uentry ce = usymtab_lookupAux (globtab, ename);
5216 cstring_free (ename);
5217 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5221 bool usymtab_existsVar (cstring k)
5224 uentry ce = usymtab_lookupSafe (k);
5226 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && (uentry_isVar (ce)));
5235 refTable_free (/*@only@*/ /*@null@*/ refTable x, int nentries)
5241 for (i = 0; i < nentries; i++)
5251 usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab u)
5252 /*@globals globtab, utab, filetab@*/
5256 aliasTable_free (u->aliases);
5258 refTable_free (u->reftable, u->nentries);
5260 if (u == filetab || u == globtab)
5262 for (i = 0; i < u->nentries; i++)
5264 uentry_freeComplete (u->entries[i]);
5269 for (i = 0; i < u->nentries; i++)
5271 uentry_free (u->entries[i]);
5275 guardSet_free (u->guards);
5282 llassert (!cstringTable_isDefined (u->htable));
5290 usymtab_freeAux (/*@only@*/ usymtab u)
5291 /*@globals globtab, utab, filetab@*/
5294 while (u != GLOBAL_ENV)
5297 usymtab_freeLevel (u);
5304 void usymtab_free ()
5305 /*@globals killed utab, globtab, filetab@*/
5309 usymtab_freeAux (utab);
5312 static int usymtab_lexicalLevel (void) /*@globals utab@*/
5314 return (utab->lexlevel);
5317 bool usymtab_inGlobalScope () /*@globals utab, globtab@*/
5319 return (utab == globtab);
5322 bool usymtab_inFileScope () /*@globals utab@*/
5324 return (utab->lexlevel == fileScope);
5327 bool usymtab_inFunctionScope () /*@globals utab@*/
5329 return (utab->lexlevel == functionScope);
5334 usymtab_replaceEntry (uentry s)
5335 /*@globals utab, globtab@*/
5336 /*@modifies utab, s@*/
5338 usymtab_replaceEntryAux (utab, s);
5343 usymtab_matchForwardStruct (usymId u1, usymId u2)
5344 /*@globals globtab@*/
5346 uentry ue1 = usymtab_getTypeEntry (u1);
5347 uentry ue2 = usymtab_getTypeEntry (u2);
5349 if (uentry_isAnyTag (ue2))
5351 ctype reptype = uentry_getType (ue1);
5353 if (ctype_isPointer (reptype))
5355 ctype repbase = ctype_getBaseType (reptype);
5357 if (ctype_isUA (repbase))
5359 typeId rtuid = ctype_typeId (repbase);
5361 if (u2 == rtuid) return TRUE;
5363 if (usymId_isValid (rtuid))
5365 reptype = uentry_getType (usymtab_getTypeEntry (rtuid));
5367 return (ctype_isUA (reptype) && (u2 == (ctype_typeId (reptype))));
5376 void usymtab_addGuards (guardSet guards)
5379 utab->guards = guardSet_union (utab->guards, guards);
5382 static bool usymtab_isGuardedAux (sRef s)
5386 sRef base = sRef_getRootBase (s);
5387 int lowlevel = paramsScope;
5388 int baselevel = sRef_lexLevel (base);
5390 if (sRef_isCvar (base))
5392 lowlevel = baselevel;
5393 if (lowlevel < paramsScope) lowlevel = paramsScope;
5396 while (tab->lexlevel >= lowlevel)
5398 DPRINTF (("Is guarded? [%s] %s",
5399 guardSet_unparse (tab->guards),
5400 sRef_unparseFull (s)));
5402 if (guardSet_isGuarded (tab->guards, s))
5405 if (!sRef_definitelyNull (s))
5407 sRef_setNotNull (s, fileloc_undefined);
5413 tab = usymtab_dropEnv (tab);
5419 void usymtab_unguard (sRef s) /*@modifies utab@*/
5422 sRef base = sRef_getRootBase (s);
5423 int lowlevel = paramsScope;
5424 int baselevel = sRef_lexLevel (base);
5426 if (sRef_isCvar (base))
5428 lowlevel = baselevel;
5429 if (lowlevel < paramsScope) lowlevel = paramsScope;
5432 while (tab->lexlevel >= lowlevel)
5434 if (guardSet_isGuarded (tab->guards, s))
5436 guardSet_delete (tab->guards, s);
5439 tab = usymtab_dropEnv (tab);
5443 bool usymtab_isGuarded (sRef s)
5445 DPRINTF (("Is guarded? %s", sRef_unparseFull (s)));
5446 return (sRef_aliasCompleteSimplePred (usymtab_isGuardedAux, s));
5449 bool usymtab_isDefinitelyNull (sRef s)
5451 return (sRef_aliasCheckSimplePred (usymtab_isDefinitelyNullAux, s));
5454 bool usymtab_isDefinitelyNullDeep (sRef s)
5456 return (sRef_deepPred (usymtab_isDefinitelyNull, s));
5459 static bool usymtab_isDefinitelyNullAux (sRef s)
5463 sRef base = sRef_getRootBase (s);
5464 int lowlevel = paramsScope;
5466 if (sRef_isCvar (base))
5468 lowlevel = sRef_lexLevel (base);
5469 if (lowlevel < paramsScope) lowlevel = paramsScope;
5472 while (tab->lexlevel >= lowlevel)
5474 if (guardSet_mustBeNull (tab->guards, s))
5479 while (tab->kind == US_CBRANCH)
5484 llassert (usymtab_isDefined (tab));
5486 if (tab->kind == US_FBRANCH)
5489 llassert (tab->kind == US_TBRANCH);
5499 usymtab_printGuards ()
5500 /*@globals utab, globtab@*/
5502 usymtab ttab = utab;
5504 while (ttab != globtab)
5506 llmsg (message ("Guards [%d]: %q", ttab->lexlevel,
5507 guardSet_unparse (ttab->guards)));
5513 usymtab_displayAllUses ()
5514 /*@globals utab, globtab@*/
5518 /* only in top scope */
5519 llassert (utab == globtab);
5521 /* need a copy, so order is not messed up by sort! */
5522 copy = usymtab_shallowCopy (globtab);
5524 qsort (copy->entries, (size_t)copy->nentries,
5525 sizeof (*copy->entries), (int (*)(const void *, const void *)) uentry_xcompareuses);
5527 usymtab_entries (copy, ue)
5529 if (uentry_isValid (ue))
5531 filelocList uses = uentry_getUses (ue);
5532 int size = filelocList_realSize (uses);
5534 if (fileloc_isDefined (uentry_whereDefined (ue))
5535 && !fileloc_isLib (uentry_whereDefined (ue))
5538 llmsg (message ("%q (%q), %d use%&:\n %q",
5539 uentry_getName (ue),
5540 fileloc_unparse (uentry_whereDefined (ue)),
5541 size, filelocList_unparseUses (uses)));
5544 } end_usymtab_entries;
5546 usymtab_shallowFree (copy);
5549 static /*@dependent@*/ /*@exposed@*/ usymtab
5550 usymtab_getFileTab ()
5551 /*@globals filetab@*/
5553 llassert (filetab != NULL);
5559 usymtab_unparseStack ()
5562 return (usymtab_unparseStackTab (utab));
5565 static /*@only@*/ cstring
5566 usymtab_unparseStackTab (usymtab t)
5568 bool firstOne = TRUE;
5569 cstring ret = cstring_makeLiteral ("[");
5571 while (t != GLOBAL_ENV)
5575 ret = message ("%q %q", ret, usymtab_typeName (t));
5580 ret = message ("%q, %q", ret, usymtab_typeName (t));
5585 ret = message ("%q ]", ret);
5589 static /*@only@*/ cstring
5590 usymtab_typeName (/*@notnull@*/ usymtab t)
5594 case US_GLOBAL: return cstring_makeLiteral ("global");
5595 case US_NORMAL: return cstring_makeLiteral ("normal");
5596 case US_TBRANCH: return cstring_makeLiteral ("true");
5597 case US_FBRANCH: return cstring_makeLiteral ("false");
5598 case US_CBRANCH: return cstring_makeLiteral ("case");
5599 case US_SWITCH: return cstring_makeLiteral ("switch");
5605 void usymtab_addMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5608 if (!sRef_similar (s, al))
5610 usymtab_addForceMustAlias (s, al);
5615 ** Same as usymtab_addMustAlias, except does not check sRef_isSimilar.
5618 void usymtab_addForceMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5621 if (sRef_isMeaningful (s)
5622 && sRef_isMeaningful (al)
5623 && !(sRef_isConst (s) || sRef_isConst (al))
5624 && !(sRef_isAddress (al) && sRef_isDirectParam (sRef_getBase (al))))
5626 utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
5627 DPRINTF (("Must alias: %s", aliasTable_unparse (utab->aliases)));
5630 ** for local variable, aliasing is symmetric
5633 if (sRef_isLocalVar (s) && sRef_isLocalVar (al))
5635 utab->aliases = aliasTable_addMustAlias (utab->aliases, al, s);
5644 void usymtab_clearAlias (sRef s)
5645 /*@modifies utab, s@*/
5648 aliasTable_clearAliases (utab->aliases, s);
5651 sRefSet usymtab_allAliases (sRef s)
5654 if (sRef_isMeaningful (s))
5658 ret = sRefSet_unionFree (aliasTable_aliasedBy (utab->aliases, s),
5659 aliasTable_canAlias (utab->aliases, s));
5664 DPRINTF (("NOT A MEANINGFUL SREF!"));
5665 return sRefSet_undefined;
5669 /*@only@*/ sRefSet usymtab_canAlias (sRef s)
5672 if (sRef_isMeaningful (s))
5674 sRefSet res = aliasTable_canAlias (utab->aliases, s);
5678 return sRefSet_undefined;
5681 /*@only@*/ sRefSet usymtab_aliasedBy (sRef s)
5684 return (aliasTable_aliasedBy (utab->aliases, s));
5687 /*@only@*/ cstring usymtab_unparseAliases ()
5690 return (aliasTable_unparse (utab->aliases));
5694 ** Debugging routines:
5695 ** okay to leak storage here, only for debugging
5701 usymtab_printOut (void)
5707 char *ind = mstring_copy (" ");
5709 fprintf (g_msgstream, "<<< [symbol table] >>>\n");
5711 while (s != GLOBAL_ENV && s->env != GLOBAL_ENV)
5713 cstring tname = usymtab_typeName (s);
5717 ind[depth * 3 + 1] = '\0';
5720 fprintf (g_msgstream, "level: %d (%s)\n", s->lexlevel,
5721 cstring_toCharsSafe (tname));
5723 cstring_free (tname);
5725 for (i = 0; i < s->nentries; i++)
5727 cstring us = uentry_unparseFull (s->entries[i]);
5728 fprintf (g_msgstream, "%s\n", cstring_toCharsSafe (us));
5732 if (s->reftable != NULL && s->nentries > 0)
5734 fprintf (g_msgstream, "\t<< Ref table >>\n");
5736 for (i = 0; i < s->nentries; i++)
5738 fprintf (g_msgstream, "\t%s %3d: %d, %d\n", ind, i,
5739 s->reftable[i]->level,
5740 s->reftable[i]->index);
5744 ind[depth * 3 + 1] = ' ';
5748 fprintf (g_msgstream, "<<< end usymtab >>>\n");
5754 usymtab_printTypes ()
5755 /*@globals globtab@*/
5757 usymtab_printAllAux (globtab);
5761 usymtab_printAll (void)
5764 usymtab_printAllAux (utab);
5768 usymtab_printAllAux (usymtab s)
5769 /*@modifies g_msgstream@*/
5773 char *ind = mstring_copy (" ");
5775 printf ("[[[ usymtab ]]]");
5777 while (s != GLOBAL_ENV)
5780 ind[depth * 3 + 1] = '\0';
5782 if (s->env == GLOBAL_ENV)
5786 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5787 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5788 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5792 for (i = looplow; i < s->nentries; i++)
5794 printf ("%s%3d. %s\n", ind, i,
5795 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5800 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5801 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5802 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5804 for (i = 0; i < s->nentries; i++)
5806 printf ("%s%3d %s\n", ind, i,
5807 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5811 ind[depth * 3 + 1] = ' ';
5815 printf ("----------\n");
5819 usymtab_printComplete ()
5824 char *ind = mstring_copy (" ");
5827 while (s != GLOBAL_ENV)
5831 ind[depth * 3 + 1] = '\0';
5834 if (s->env == GLOBAL_ENV)
5838 printf ("level: %d\n", s->lexlevel);
5842 for (i = looplow; i < s->nentries; i++)
5844 printf ("%s%3d %s\n", ind, i,
5845 cstring_toCharsSafe (uentry_unparse (s->entries[i])));
5850 printf ("level: %d\n", s->lexlevel);
5851 for (i = 0; i < s->nentries; i++)
5853 printf ("%s%3d %s\n", ind, i,
5854 cstring_toCharsSafe (uentry_unparse (s->entries[i])));
5858 ind[depth * 3 + 1] = ' ';
5863 printf ("----------\n");
5868 static /*@only@*/ cstring /*@unused@*/
5869 usymtab_unparseLocalAux (/*@notnull@*/ usymtab s)
5871 cstring c = message ("lexlevel: %d\n", s->lexlevel);
5874 for (i = 0; i < s->nentries; i++)
5876 c = message ("%q\n%q", c, uentry_unparseFull (s->entries[i]));
5879 c = message ("%q\n=========", c);
5883 static cstring /*@unused@*/ /*@only@*/
5884 usymtab_unparseLocalList (/*@notnull@*/ usymtab s)
5886 cstring c = message ("[%d/%s/%s] ", s->lexlevel,
5887 bool_unparse (s->mustBreak),
5888 exitkind_unparse (s->exitCode));
5891 for (i = 0; i < s->nentries; i++)
5893 sRef sr = uentry_getSref (s->entries[i]);
5897 c = message ("%q: %q [%b]", c, uentry_getName (s->entries[i]),
5898 sRef_isStateDefined (sr));
5902 c = message ("%q, %q [%b]", c, uentry_getName (s->entries[i]),
5903 sRef_isStateDefined (sr));
5913 usymtab_printLocal (void)
5919 printf ("lexlevel: %d\n", s->lexlevel);
5921 for (i = 0; i < s->nentries; i++)
5923 printf ("%s\n", cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5926 while (s->lexlevel > 1)
5931 llassert (usymtab_isDefined (s));
5933 printf ("Params:\n");
5935 for (i = 0; i < s->nentries; i++)
5937 printf ("%d: %s\n", i,
5938 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5943 static bool checkDistinctExternalName (uentry e)
5944 /*@globals globtab@*/
5945 /*@modifies *g_msgstream@*/
5947 int checklen = context_getValue (FLG_EXTERNALNAMELEN);
5948 bool ignorecase = context_getFlag (FLG_EXTERNALNAMECASEINSENSITIVE);
5949 bool gotone = FALSE;
5950 bool extras = FALSE;
5951 bool hasError = FALSE;
5952 cstring name = uentry_rawName (e);
5953 usymtab st = globtab;
5961 if (uentry_isAnyTag (e))
5963 checklen++; /* the tag marker doesn't count */
5967 usymtab_entries (st, oe)
5969 if (uentry_sameObject (oe, e))
5976 if (cstring_equalCaseInsensitive (uentry_rawName (oe), name))
5985 (FLG_DISTINCTEXTERNALNAMES,
5987 ("External identifier %q is not distinguishable from %q "
5988 "because alphabetical case is ignored",
5990 uentry_getName (oe)),
5991 uentry_whereLast (e)))
5993 uentry_showWhereAny (oe);
5994 uentry_setHasNameError (oe);
6003 if (cstring_equalLenCaseInsensitive (uentry_rawName (oe),
6012 if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6015 (FLG_DISTINCTEXTERNALNAMES,
6018 ("External identifier %q is not distinguishable from %q "
6019 "in the first %d characters (%q)",
6021 uentry_getName (oe),
6023 cstring_clip (uentry_getName (e), checklen)),
6025 uentry_whereLast (e)))
6027 uentry_showWhereAny (oe);
6028 uentry_setHasNameError (oe);
6041 (FLG_DISTINCTEXTERNALNAMES,
6043 ("External identifier %q is not distinguishable from %q "
6044 "in the first %d characters because alphabetical case "
6047 uentry_getName (oe),
6049 uentry_whereLast (e)))
6051 uentry_showWhereAny (oe);
6052 uentry_setHasNameError (oe);
6058 else if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6067 (FLG_DISTINCTEXTERNALNAMES,
6070 ("External identifier %q is not distinguishable from %q "
6071 "in the first %d characters (%q)",
6073 uentry_getName (oe),
6075 cstring_clip (uentry_getName (e), checklen)),
6077 uentry_whereLast (e)))
6079 uentry_showWhereAny (oe);
6080 uentry_setHasNameError (oe);
6089 } end_usymtab_entries ;
6096 (cstring_makeLiteral ("One or more additional "
6097 "indistinguishable external "
6098 "names not reported"));
6104 static bool checkDistinctInternalName (uentry e)
6106 /*@modifies *g_msgstream@*/
6108 usymtab ttab = utab;
6109 cstring name = uentry_rawName (e);
6110 int numchars = context_getValue (FLG_INTERNALNAMELEN);
6111 bool caseinsensitive = context_getFlag (FLG_INTERNALNAMECASEINSENSITIVE);
6112 bool lookalike = context_getFlag (FLG_INTERNALNAMELOOKALIKE);
6114 if (uentry_isAnyTag (e) && (numchars != 0))
6116 numchars++; /* the tag marker doesn't count */
6119 while (usymtab_isDefined (ttab))
6121 usymtab_entries (ttab, oe)
6123 if (uentry_sameObject (oe, e))
6125 /*@innercontinue@*/ continue;
6128 switch (cstring_genericEqual
6129 (name, uentry_rawName (oe),
6130 numchars, caseinsensitive, lookalike))
6132 case CGE_DISTINCT: /* okay */
6136 if (cstring_equal (name, uentry_rawName (oe)))
6138 ; /* got a shadow error */
6143 (FLG_DISTINCTINTERNALNAMES,
6146 ("Internal identifier %q is not distinguishable from %q "
6147 "in the first %d characters (%q)",
6149 uentry_getName (oe),
6151 cstring_clip (uentry_getName (e), numchars)),
6153 uentry_whereLast (e)))
6155 uentry_showWhereAny (oe);
6156 uentry_setHasNameError (oe);
6164 || (cstring_length (name) <= numchars))
6167 (FLG_DISTINCTINTERNALNAMES,
6169 ("Internal identifier %q is not distinguishable from %q "
6170 "without case sensitivity",
6172 uentry_getName (oe)),
6173 uentry_whereLast (e)))
6175 uentry_showWhereAny (oe);
6176 uentry_setHasNameError (oe);
6183 (FLG_DISTINCTINTERNALNAMES,
6185 ("Internal identifier %q is not distinguishable from %q "
6186 "in the first %d characters without case sensitivity",
6188 uentry_getName (oe),
6190 uentry_whereLast (e)))
6192 uentry_showWhereAny (oe);
6193 uentry_setHasNameError (oe);
6201 || (cstring_length (name) <= numchars))
6204 (FLG_DISTINCTINTERNALNAMES,
6206 ("Internal identifier %q is not distinguishable from %q "
6207 "except by lookalike characters",
6209 uentry_getName (oe)),
6210 uentry_whereLast (e)))
6212 uentry_showWhereAny (oe);
6213 uentry_setHasNameError (oe);
6220 (FLG_DISTINCTINTERNALNAMES,
6222 ("Internal identifier %q is not distinguishable from %q "
6223 "in the first %d characters except by lookalike characters",
6225 uentry_getName (oe),
6227 uentry_whereLast (e)))
6229 uentry_showWhereAny (oe);
6230 uentry_setHasNameError (oe);
6235 } end_usymtab_entries ;
6243 void usymtab_checkDistinctName (uentry e, int scope)
6244 /*@globals utab, globtab@*/
6246 bool hasError = FALSE;
6247 fileloc where = uentry_whereLast (e);
6249 if (!fileloc_isPreproc (where) && !fileloc_isBuiltin (where))
6251 if (scope == globScope)
6253 if (context_getFlag (FLG_DISTINCTEXTERNALNAMES))
6255 hasError = checkDistinctExternalName (e);
6259 if (!hasError && context_getFlag (FLG_DISTINCTINTERNALNAMES))
6261 hasError = checkDistinctInternalName (e);
6267 uentry_setHasNameError (e);
6271 /*@exposed@*/ sRef usymtab_lookupGlobalMarker (void) /*@globals utab@*/
6275 ue = usymtab_lookupAux (utab, GLOBAL_MARKER_NAME);
6276 llassert (uentry_isValid (ue));
6278 return uentry_getSref (ue);