2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 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 splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
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 "splintMacros.nf"
51 # include "structNames.h"
52 # include "exprChecks.h"
53 # include "transferChecks.h"
55 /* Needed to install macros when loading libraries */
58 # include "cpperror.h"
62 ** Keep track of type definitions inside a function.
65 static uentryList functypes = uentryList_undefined;
67 static bool dbgfree = FALSE;
68 static bool dbgload = TRUE;
73 ** Hack to prevent shadow errors from appearing when function parameters
74 ** are entered into a new scope.
77 static bool noshadowerror = FALSE;
80 ** Constraint: static variables can live in 1 or > 2.
82 ** except for tags. All tags must be at the global level.
83 ** Static tags are handled in a kludgey way.
87 ** utab is the universal symbol table
88 ** globtab is the global environment of utab
89 ** oldtab is needed for conversions in dumping (after sorting the table)
91 ** there can be only one usymtab!
94 static /*@checkedstrict@*/ /*@owned@*/ /*@notnull@*/ usymtab utab;
96 /* Reachable environments from from utab */
97 static /*@checkedstrict@*/ /*@notnull@*/ /*@dependent@*/ usymtab globtab;
98 static /*@checkedstrict@*/ /*@dependent@*/ usymtab filetab;
100 /* Used for sorting for dumpage. */
101 static /*@checkedstrict@*/ /*@owned@*/ usymtab oldtab;
103 static int usymtab_lexicalLevel (void) /*@globals utab@*/ ;
104 static bool usymtab_isAltDefinitelyNull (sRef p_s) /*@globals utab@*/ ;
105 static void refTable_free (/*@only@*/ /*@null@*/ refTable p_x, int p_nentries);
106 static ctype usymtab_suFieldsType (uentryList p_f, bool p_isStruct) /*@globals globtab@*/ ;
108 static void usymtab_freeAux (/*@only@*/ usymtab p_u)
109 /*@globals globtab, utab, filetab@*/
112 extern int usymtab_getCurrentDepth (void) /*@globals utab@*/
114 return utab->lexlevel;
118 usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab p_u)
119 /*@globals globtab, utab, filetab@*/ /*@modifies p_u@*/ ;
121 static bool usymtab_isDefinitelyNullAux (sRef p_s) /*@globals utab@*/ ;
122 static /*@only@*/ cstring usymtab_unparseStackTab (usymtab p_t);
123 static /*@exposed@*/ /*@dependent@*/ uentry
124 usymtab_getRefTab (/*@notnull@*/ usymtab p_u, int p_level, usymId p_index);
127 /* These are not used anymore... */
128 static /*@unused@*/ /*@only@*/ cstring
129 usymtab_unparseLocalAux (/*@notnull@*/ usymtab p_s);
130 static /*@unused@*/ /*@only@*/ cstring
131 usymtab_unparseLocalList (/*@notnull@*/ usymtab p_s);
134 static /*@only@*/ cstring usymtab_typeName (/*@notnull@*/ usymtab p_t);
135 static void usymtab_handleParams (void)
136 /*@globals utab, globtab, filetab@*/
137 /*@modifies utab@*/ ;
139 static /*@exposed@*/ /*@dependent@*/ uentry
140 usymtab_addRefEntry (/*@notnull@*/ usymtab p_s, cstring p_k);
141 static /*@exposed@*/ /*@dependent@*/ usymtab
142 usymtab_dropEnv (/*@notnull@*/ usymtab p_s);
143 static /*@exposed@*/ /*@dependent@*/ uentry
144 usymtab_getRefNoisy (/*@notnull@*/ usymtab p_s, int p_level, usymId p_index);
146 static /*@exposed@*/ /*@dependent@*/ uentry
147 usymtab_lookupQuietAux (usymtab p_s, cstring p_k, bool p_noalt);
149 static /*@exposed@*/ /*@dependent@*/ uentry
150 usymtab_lookupQuiet (usymtab p_s, cstring p_k);
152 static /*@exposed@*/ /*@dependent@*/ uentry
153 usymtab_lookupQuietNoAlt (usymtab p_s, cstring p_k);
155 static void usymtab_printAllAux (usymtab p_s) /*@modifies g_warningstream@*/ ;
157 /*@function bool usymtab_indexFound (usymId) @*/
158 # define usymtab_indexFound(u) ((u) != usymId_notfound)
160 static usymId usymtab_getIndex (/*@notnull@*/ usymtab p_s, cstring p_k);
161 static /*@exposed@*/ uentry usymtab_fetchIndex (/*@notnull@*/ usymtab p_s, usymId p_ui);
162 static /*@exposed@*/ uentry usymtab_lookupAux (usymtab p_s, cstring p_k);
164 static /*@exposed@*/ /*@dependent@*/ /*@notnull@*/
165 usymtab usymtab_getFileTab (void) /*@globals filetab@*/ ;
167 static int refTable_lookup (/*@notnull@*/ usymtab p_ut, int p_level, usymId p_index);
168 static bool usymtab_mustBreak (usymtab p_s);
169 static bool usymtab_mustEscape (usymtab p_s);
171 static void recordFunctionType (uentry ue)
173 llassert (uentry_isDatatype (ue) || uentry_isAnyTag (ue)
174 || uentry_isEnumConstant (ue));
175 DPRINTF (("Function type: %s", uentry_unparseFull (ue)));
177 functypes = uentryList_add (functypes, ue);
181 static void clearFunctionTypes (void)
182 /*@modifies globtab@*/
184 uentryList_elements (functypes, el)
186 if (cstring_isDefined (uentry_rawName (el)))
188 if (cstringTable_isDefined (globtab->htable))
190 cstringTable_remove (globtab->htable, uentry_rawName (el));
193 uentry_setName (el, cstring_undefined);
197 llassert (uentry_isValid (el));
198 el->sref = sRef_undefined;
199 /*@noaccess uentry@*/
200 } end_uentryList_elements ;
202 uentryList_clear (functypes);
205 static /*@falsewhennull@*/ bool usymtab_isBranch (usymtab u)
207 return (usymtab_isDefined (u) &&
208 (u->kind == US_TBRANCH || u->kind == US_FBRANCH
209 || u->kind == US_CBRANCH || u->kind == US_SWITCH));
212 static bool usymtab_mustBreak (usymtab s)
214 llassert (s != GLOBAL_ENV);
215 return (s->mustBreak);
218 static bool usymtab_mustEscape (usymtab s)
220 llassert (s != GLOBAL_ENV);
221 return (exitkind_mustEscape (s->exitCode));
224 void usymtab_setMustBreak ()
227 llassert (utab != GLOBAL_ENV);
228 utab->mustBreak = TRUE;
231 void usymtab_setExitCode (exitkind ex)
234 llassert (utab != GLOBAL_ENV);
238 if (exitkind_mustEscape (ex))
240 utab->mustBreak = TRUE;
244 bool usymtab_isAltDefinitelyNullDeep (sRef s)
246 return (sRef_deepPred (usymtab_isAltDefinitelyNull, s));
249 static bool usymtab_isAltDefinitelyNull (sRef s)
257 llassert (utab->env != NULL);
259 /*@-mods@*/ /* These modifications are cancelled. */
260 utab->guards = utab->env->guards;
261 utab->env->guards = t;
264 llassert (usymtab_isDefined (utab));
265 res = usymtab_isDefinitelyNull (s);
268 ** This reports a spurious error. It is okay, because of
269 ** the nesting relationship of usymtab environments.
272 /*@-mods@*/ /* Cancelling modifications. */
273 /*@i1@*/ utab->env->guards = utab->guards;
274 /*@i1@*/ utab->guards = t;
280 static /*@notnull@*/ /*@special@*/ usymtab
281 usymtab_create (uskind kind, /*@keep@*/ usymtab env, bool nextlevel)
283 /*@post:isnull result->htable, result->guards, result->aliases@*/
285 usymtab t = (usymtab) dmalloc (sizeof (*t));
288 t->nspace = CBASESIZE;
289 t->entries = (uentry *) dmalloc (sizeof (*t->entries) * CBASESIZE);
291 /* We only use a reftable for branch-level symbol tables.
294 t->reftable = (nextlevel
296 : (refentry *) dmalloc (sizeof (*t->reftable) * CBASESIZE));
299 t->lexlevel = (env == GLOBAL_ENV ? 0 : env->lexlevel) + (nextlevel ? 1 : 0);
304 t->guards = guardSet_undefined;
305 t->aliases = aliasTable_undefined;
307 t->mustBreak = FALSE;
308 t->exitCode = XK_NEVERESCAPE;
310 DPRINTF (("Create usymtab [%p]", t));
318 static /*@only@*/ /*@notnull@*/ usymtab
319 usymtab_createRoot (void) /*@modifies nothing@*/
321 usymtab u = (usymtab) dmalloc (sizeof (*u));
324 u->nspace = CGLOBBASESIZE;
325 u->entries = (uentry *) dmalloc (sizeof (*u->entries) * CGLOBBASESIZE);
328 u->htable = cstringTable_create (CGLOBHASHSIZE);
331 u->guards = guardSet_new ();
332 u->aliases = aliasTable_new ();
334 u->mustBreak = FALSE;
335 u->exitCode = XK_NEVERESCAPE;
342 usymtab_initMod (void)
343 /*@globals undef utab, undef oldtab, undef globtab, undef filetab @*/
344 /*@modifies utab, globtab, filetab, oldtab @*/
346 utab = usymtab_createRoot ();
348 filetab = usymtab_undefined;
349 oldtab = usymtab_undefined;
353 usymtab_destroyMod (void) /*@modifies utab, globtab, filetab@*/ /*@globals killed utab@*/
355 DPRINTF (("Destroy usymtab [%p]: %d", utab, utab->nentries));
356 usymtab_freeAux (utab);
357 utab = usymtab_undefined;
362 usymtab_initGlobalMarker () /*@globals globtab@*/
364 if (uentry_isValid (usymtab_lookupAux (globtab, GLOBAL_MARKER_NAME)))
366 ; /* Already entered from load table. */
370 usymtab_addGlobalEntry (uentry_makeGlobalMarker ());
375 ** utab should be empty? (requires?)
377 ** Adds bool types to symbol table (these are built in for now)
378 ** Only do this is there is no library!
384 DPRINTF (("Init bool!"));
386 if (context_getFlag (FLG_NOLIB))
388 ctype boolt = ctype_bool;
389 /* evs 2000-07-24: bool is now treated as abstract (always) */
391 uentry boolentry = uentry_makeBoolDatatype (qual_createAbstract ());
392 usymtab_supGlobalEntry (boolentry);
393 context_addBoolAccess ();
396 ** We supply values 0 and 1 for the constants, so things like
397 ** while (TRUE) can be interpreted correctly.
400 usymtab_supGlobalEntry
401 (uentry_makeConstantValue (context_getFalseName (), boolt,
402 fileloc_getBuiltin (), FALSE,
403 multiVal_makeInt (0)));
405 usymtab_supGlobalEntry
406 (uentry_makeConstantValue (context_getTrueName (), boolt,
407 fileloc_getBuiltin (), FALSE,
408 multiVal_makeInt (1)));
417 usymtab_grow (/*@notnull@*/ usymtab s)
420 o_uentry *oldsyms = s->entries;
422 s->nspace = CBASESIZE;
423 s->entries = (uentry *) dmalloc (sizeof (*s->entries)
424 * (s->nentries + s->nspace));
426 for (i = 0; i < s->nentries; i++)
428 s->entries[i] = oldsyms[i];
433 if (s->reftable != NULL)
435 refTable oldRefs = s->reftable;
437 s->reftable = (refentry *) dmalloc (sizeof (*s->reftable)
438 * (s->nentries + CBASESIZE + 1));
440 for (i = 0; i < s->nentries; i++)
442 s->reftable[i] = oldRefs[i];
453 usymtab_addEntryQuiet (/*@notnull@*/ usymtab s, /*@keep@*/ uentry e)
455 if (!(s->lexlevel > fileScope || !sRef_modInFunction ()))
457 if (uentry_isDatatype (e)
458 || uentry_isFunction (e)
459 || uentry_isAnyTag (e)
460 || uentry_isEnumConstant (e)
461 || context_inMacro ())
464 ** Not a bug. Code like,
465 ** int f (void) { typedef int tint; ... }
469 /* was nothing here! */
470 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
475 (cstring_makeLiteral ("Declaration outside function scope"));
477 llcontbug (message ("usymtab_addEntryQuiet: inconsistent state "
478 "(lexlevel = %d, modFunction = %s) adding: %q",
479 s->lexlevel, bool_unparse (sRef_modInFunction ()),
480 uentry_unparse (e)));
481 sRef_setGlobalScope ();
482 /* make sure the sRef is not bashed! */
483 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
493 s->entries[s->nentries] = e;
496 if (s == globtab || s == filetab)
498 if (!fileloc_isLib (g_currentloc))
500 uentry_tallyAnnots (e, AN_UNKNOWN);
505 if (cstringTable_isDefined (s->htable))
507 cstringTable_insert (s->htable, cstring_copy (uentry_rawName (e)), s->nentries);
513 static /*@observer@*/ uentry /*@alt void@*/
514 usymtab_addEntryBase (/*@notnull@*/ usymtab s, /*@only@*/ uentry e)
517 ** In theory, we shouldn't need this test because it this is
518 ** only called when a library is being read, and it shouldn't
519 ** ever have a duplicate entry. In practice, its safer to
520 ** leave it in, though.
525 if (uentry_isValid (old = usymtab_lookupQuiet (s, uentry_rawName (e))))
527 DPRINTF (("Duplicate entry: %s", uentry_unparse (e)));
528 uentry_free (e); /* duplicate */
533 usymId thisentry = usymId_fromInt (s->nentries);
535 if (uentry_isVar (e))
538 (e, sRef_makeCvar (globScope, thisentry,
540 stateInfo_makeLoc (uentry_whereLast (e), SA_DECLARED)));
543 usymtab_addEntryQuiet (s, e);
549 static /*@observer@*/ uentry /*@alt void@*/
550 usymtab_addEntryAlways (/*@notnull@*/ usymtab s, /*@only@*/ uentry e)
553 ** In theory, we shouldn't need this test because it this is
554 ** only called when a library is being read, and it shouldn't
555 ** ever have a duplicate entry. In practice, its safer to
556 ** leave it in, though.
560 usymId thisentry = usymId_fromInt (s->nentries);
562 if (uentry_isValid (old = usymtab_lookupQuiet (s, uentry_rawName (e))))
565 (message ("Duplicate entry in load library: %s. "
566 "Old entry: %q. New entry: %q",
568 uentry_unparseFull (old),
569 uentry_unparseFull (e)));
571 uentry_setName (e, message ("__x_%s", uentry_rawName (e)));
572 /* This shouldn't happen...unless the library is bad! */
576 if (uentry_isVar (e) && !uentry_isGlobalMarker (e))
579 (e, sRef_makeCvar (globScope, thisentry,
581 stateInfo_makeLoc (uentry_whereLast (e), SA_DECLARED)));
584 usymtab_addEntryQuiet (s, e);
589 usymtab_addEntryAux (/*@notnull@*/ usymtab st, /*@keep@*/ uentry e, bool isSref)
590 /*@globals globtab@*/
593 usymId thisentry = usymId_fromInt (st->nentries);
595 llassert (!uentry_isElipsisMarker (e));
599 ** llassert (usymtab_lookupSafe (uentry_rawName (e)) == uentry_undefined);
602 llassertprint (uentry_isAnyTag (e) ? st == globtab : TRUE,
603 ("non-global tag: %s / %d", uentry_unparseFull (e), st->lexlevel));
605 if (st->lexlevel == fileScope
606 && (!(uentry_isStatic (e)) || uentry_isAnyTag (e)))
613 ctype ct = uentry_getType (e);
615 if (uentry_isFunction (e) && ctype_isFunction (ct))
617 ct = ctype_getReturnType (ct);
620 if (uentry_isStatic (e))
622 sRef sr = sRef_makeCvar (st->lexlevel, thisentry, ct,
623 stateInfo_makeLoc (uentry_whereLast (e), SA_DECLARED));
625 if (sRef_isStack (sr) || sRef_isLocalState (sr))
627 sRef_setAliasKind (sr, AK_STATIC, uentry_whereLast (e));
628 sRef_setDefined (sr, uentry_whereLast (e));
631 uentry_setSref (e, sr);
636 (e, sRef_makeCvar (st->lexlevel, thisentry, ct,
637 stateInfo_makeLoc (uentry_whereLast (e), SA_DECLARED)));
641 if (uentry_isDatatype (e))
643 uentry_setDatatype (e, typeId_fromUsymId (thisentry));
646 if (uentry_isFunction (e))
648 ctype ct = uentry_getType (e);
650 if (ctype_isFunction (ct)
651 && uentryList_isMissingParams (ctype_argsFunction (ct)))
653 if (uentry_isDeclared (e))
657 message ("Function %q declared without parameter list",
659 uentry_whereDeclared (e));
665 message ("Function %q specified without parameter list",
667 uentry_whereSpecified (e));
672 if (st == globtab && !uentry_isSpecified (e))
674 exprChecks_checkExport (e);
677 uentry_checkName (e);
679 usymtab_addEntryQuiet (st, e);
680 DPRINTF (("Adding entry: [%p] %s", e, uentry_unparseFull (e)));
685 usymtab_addEntry (uentry e)
686 /*@globals utab, globtab@*/
687 /*@modifies utab, e@*/
689 llassertprint (!usymtab_exists (uentry_rawName (e)),
690 ("Entry already exists: %s", uentry_unparse (e)));
692 return usymtab_addEntryAux (utab, e, FALSE);
696 usymtab_addGlobalEntry (uentry e)
697 /*@modifies globtab, e@*/
699 DPRINTF (("Add global: %s / %s", uentry_unparse (e), bool_unparse (uentry_isForward (e))));
701 (void) usymtab_addEntryAux (globtab, e, FALSE);
705 ** supercede and replace entry use elements of entries array, and
706 ** assign an element to a new value, and then free the old value.
707 ** Need -deparrays to avoid errors for this.
713 usymtab_supEntryAux (/*@notnull@*/ usymtab st,
714 /*@only@*/ uentry e, bool isSref)
715 /*@globals globtab, filetab@*/
716 /*@modifies st, globtab, e@*/
718 cstring ename = uentry_rawName (e);
719 bool staticEntry = FALSE;
722 DPRINTF (("Sup entry aux: %s", uentry_unparseFull (e)));
724 /* static tags in global scope */
725 if (st->lexlevel == fileScope
726 && (!(uentry_isStatic (e)) || uentry_isAnyTag (e)))
728 eindex = usymtab_getIndex (st, ename);
730 if (usymtab_indexFound (eindex))
732 uentry ce = st->entries[eindex];
736 message ("%s %q shadows static declaration",
737 ekind_capName (uentry_getKind (e)),
739 uentry_whereDeclared (e)))
741 uentry_showWhereLast (ce);
744 if (eindex == usymId_fromInt (st->nentries - 1))
750 st->entries[eindex] = st->entries[st->nentries - 1];
753 if (cstringTable_isDefined (st->htable))
755 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
756 cstring_copy (uentry_rawName (e)));
766 if (uentry_isStatic (e)) {
767 if (uentry_isFunction (e)) {
769 ** Static function declarations are at the file level,
770 ** even if they are in a deeper scope.
773 st = usymtab_getFileTab ();
776 if (!uentry_isAnyTag (e) && st == globtab)
778 st = usymtab_getFileTab ();
780 DPRINTF (("Static entry!"));
785 eindex = usymtab_getIndex (st, ename);
787 if (usymtab_indexFound (eindex))
789 uentry ce = st->entries[eindex];
791 DPRINTF (("Found entry: %s", uentry_unparse (ce)));
793 if (uentry_isPriv (ce)
794 /* || (fileloc_isImport (uentry_whereSpecified (ce))) */
795 || (uentry_isStatic (ce)
796 && uentry_isAnyTag (ce)
797 && (uentry_isDeclared (ce)
798 && !fileloc_sameFile (uentry_whereDefined (ce),
799 uentry_whereDefined (e)))))
803 ** if overloading import should do some checks!
806 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
808 DPRINTF (("Overloading!"));
810 st->entries[eindex] = e;
812 if (uentry_isDatatype (e))
814 uentry_setDatatype (e, typeId_fromUsymId (eindex));
817 if (st == globtab && !uentry_isSpecified (e))
819 exprChecks_checkExport (e);
822 if (cstringTable_isDefined (st->htable))
824 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
825 cstring_copy (uentry_rawName (e)));
831 else if (uentry_isSpecified (ce))
833 if (uentry_isSpecified (e))
835 DPRINTF (("Here we are: %s", uentry_unparseFull (e)));
837 if (fileloc_isImport (uentry_whereSpecified (ce)))
839 if (cstringTable_isDefined (st->htable))
841 cstringTable_replaceKey (st->htable,
843 cstring_copy (uentry_rawName (e)));
847 st->entries[eindex] = e;
850 if (uentry_isDatatype (e)) uentry_setDatatype (e, typeId_fromUsymId (eindex));
854 if (fileloc_isImport (uentry_whereSpecified (e)))
860 /* Respecification errors already reported */
861 DPRINTF (("Respecification: %s / %s",
862 fileloc_unparse (uentry_whereSpecified (e)),
863 bool_unparse (fileloc_isSpec (uentry_whereSpecified (e)))));
865 if (uentry_isDatatype (e))
867 uentry_setDatatype (e, typeId_fromUsymId (eindex));
870 if (cstringTable_isDefined (st->htable))
872 cstringTable_replaceKey (st->htable,
874 cstring_copy (uentry_rawName (e)));
877 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
879 st->entries[eindex] = e;
884 else /* e not specified */
886 DPRINTF (("Merging..."));
888 if (uentry_isDeclared (ce))
891 No - this can happen for internal typedefs
892 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
895 DPRINTF (("Merge defn"));
896 uentry_mergeDefinition (ce, e);
901 No - this can happen for internal typedefs
902 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
905 DPRINTF (("Merge entries..."));
906 uentry_mergeEntries (ce, e);
907 DPRINTF (("After: %s", uentry_unparseFull (ce)));
911 else /* ce not specified */
913 if (!(st->lexlevel > fileScope || !sRef_modInFunction ()))
915 if (uentry_isDatatype (e) || uentry_isAnyTag (e)
916 || uentry_isEnumConstant (e)
917 || uentry_isStatic (e)) /* bug fix from Brian St. Pierre */
920 ** Not a bug. Code like,
921 ** int f (void) { typedef int tint; ... }
927 llcontbug (message ("usymtab_supEntryAux: inconsistent state "
928 "(lexlevel = %d, modFunction = %s) adding: %q",
929 st->lexlevel, bool_unparse (sRef_modInFunction ()),
930 uentry_unparse (e)));
932 if (sRef_modInFunction ())
934 /* make sure the sRef is not bashed! */
935 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
940 DPRINTF (("Merge.."));
941 uentry_mergeDefinition (ce, e);
946 ctype ct = uentry_getType (ce);
948 if (uentry_isFunction (ce) && ctype_isFunction (ct))
950 ct = ctype_getReturnType (ct);
954 (ce, sRef_makeCvar (st->lexlevel, eindex, ct,
955 stateInfo_makeLoc (uentry_whereLast (ce), SA_DECLARED)));
958 else /* no previous entry */
962 if (st->lexlevel == globScope
963 && !uentry_isStatic (e)
964 && !uentry_isExtern (e)
965 && usymtab_isDefined (filetab))
968 ** check if there is a static entry: (i.e.,
975 eindex = usymtab_getIndex (filetab, ename);
977 if (usymtab_indexFound (eindex))
979 uentry ce = filetab->entries[eindex];
981 uentry_setStatic (e);
982 uentry_mergeDefinition (ce, e);
988 outer = usymtab_lookupQuiet (st->env, ename);
990 DPRINTF (("New : [%p] %s", e, uentry_unparseFull (e)));
991 DPRINTF (("Outer: [%p] %s", outer, uentry_unparseFull (outer)));
994 ** no previous definition, add the new one
998 && uentry_isValid (outer)
999 && !(uentry_isYield (e) || uentry_isYield (outer))
1000 && fileloc_isDefined (uentry_whereLast (e))
1001 && !fileloc_isXHFile (uentry_whereLast (e))
1002 && fileloc_isDefined (uentry_whereLast (outer))
1003 && !fileloc_isXHFile (uentry_whereLast (outer)))
1005 if (!uentry_sameKind (outer, e))
1011 if (ctype_isUnknown (uentry_getType (outer))
1012 || uentry_isForward (outer))
1020 message ("%s %q shadows outer declaration",
1021 ekind_capName (uentry_getKind (e)),
1022 uentry_getName (e)),
1023 uentry_whereLast (e)))
1025 uentry_showWhereLast (outer);
1031 if (st == globtab && context_getFlag (FLG_NEWDECL))
1035 message ("New declaration: %q", uentry_getName (e)),
1036 uentry_whereLast (e));
1039 eindex = usymtab_addEntryAux (st, e, isSref);
1043 return (staticEntry ? usymId_invalid : eindex);
1047 usymtab_replaceEntryAux (/*@notnull@*/ usymtab st, /*@only@*/ uentry e)
1048 /*@globals globtab@*/ /*@modifies st, e@*/
1050 cstring ename = uentry_rawName (e);
1053 /* static tags in global scope */
1054 eindex = usymtab_getIndex (st, ename);
1056 if (usymtab_indexFound (eindex))
1058 uentry ce = st->entries[eindex];
1060 if (cstringTable_isDefined (st->htable))
1062 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
1063 cstring_copy (uentry_rawName (e)));
1067 st->entries[eindex] = e;
1071 eindex = usymtab_addEntryAux (st, e, FALSE);
1077 void usymtab_supEntry (uentry e)
1078 /*@globals utab, filetab, globtab@*/
1079 /*@modifies utab, globtab, e@*/
1081 (void) usymtab_supEntryAux (utab, e, FALSE);
1085 ** this should be lots more efficient!
1088 static /*@exposed@*/ uentry
1089 usymtab_supEntryReturnAux (/*@notnull@*/ usymtab tab,
1090 /*@only@*/ uentry e, bool isref)
1091 /*@globals globtab, filetab@*/
1092 /*@modifies tab, globtab, e@*/
1094 cstring rawName = cstring_copy (uentry_rawName (e));
1095 bool stat = (tab == globtab) && uentry_isStatic (e);
1098 (void) usymtab_supEntryAux (tab, e, isref);
1102 ret = usymtab_lookupAux (filetab, rawName);
1106 ret = usymtab_lookupAux (tab, rawName);
1108 if (uentry_isInvalid (ret) && usymtab_isDefined (filetab))
1110 ret = usymtab_lookupAux (filetab, rawName);
1114 cstring_free (rawName);
1118 /*@dependent@*/ /*@exposed@*/ uentry
1119 usymtab_supEntryReturn (/*@only@*/ uentry e)
1120 /*@globals utab, filetab, globtab@*/
1121 /*@modifies utab, globtab, e@*/
1123 return (usymtab_supEntryReturnAux (utab, e, FALSE));
1126 /*@dependent@*/ /*@exposed@*/ uentry
1127 usymtab_supEntrySrefReturn (/*@only@*/ uentry e)
1128 /*@globals utab, globtab, filetab@*/
1129 /*@modifies utab, globtab, e@*/
1131 return (usymtab_supEntryReturnAux (utab, e, TRUE));
1134 /*@dependent@*/ /*@exposed@*/ uentry
1135 usymtab_supGlobalEntryReturn (uentry e)
1136 /*@globals globtab, filetab@*/
1137 /*@modifies globtab, e@*/
1141 ret = usymtab_supEntryReturnAux (globtab, e, FALSE);
1144 ** We need to keep track of internal function declarations, so
1145 ** we can remove them from the symbol table after exiting this
1146 ** function. This is a bit bogus, of course.
1149 if (sRef_modInFunction ())
1151 recordFunctionType (ret);
1158 usymtab_supTypeEntry (/*@only@*/ uentry e)
1159 /*@globals globtab, filetab@*/
1160 /*@modifies globtab, e@*/
1165 if (uentry_isAbstractDatatype (e))
1167 typeId tid = usymtab_supAbstractTypeEntry (e, FALSE);
1168 ret = ctype_createAbstract (tid);
1169 uid = typeId_toUsymId (tid);
1173 uid = usymtab_supEntryAux (globtab, e, FALSE);
1174 ret = ctype_createUser (typeId_fromUsymId (uid));
1177 if (sRef_modInFunction ())
1179 recordFunctionType (globtab->entries[uid]);
1186 usymtab_supReturnTypeEntry (/*@only@*/ uentry e)
1187 /*@globals globtab, filetab@*/
1188 /*@modifies globtab@*/
1192 DPRINTF (("Abstract? %s", uentry_unparseFull (e)));
1194 if (uentry_isAbstractDatatype (e))
1196 uid = typeId_toUsymId (usymtab_supAbstractTypeEntry (e, FALSE));
1198 else if (uentry_isMaybeAbstract (e) && context_getFlag (FLG_IMPABSTRACT))
1200 bool maybeabs = TRUE;
1201 cstring sname = uentry_getName (e);
1202 uentry ue = usymtab_lookupGlobSafe (sname);
1203 cstring_free (sname);
1205 if (uentry_isValid (ue))
1207 DPRINTF (("Lookup: %s", uentry_unparseFull (ue)));
1209 if (uentry_isDatatype (ue))
1211 if (uentry_isMaybeAbstract (ue))
1222 DPRINTF (("Not datatype!"));
1229 typeId tid = usymtab_supAbstractTypeEntry (e, FALSE);
1230 ux = usymtab_getTypeEntry (tid);
1231 uentry_setAbstract (ux);
1232 uid = typeId_toUsymId (tid);
1236 uid = usymtab_supEntryAux (globtab, e, FALSE);
1237 e = usymtab_getTypeEntry (typeId_fromUsymId (uid));
1239 if (uentry_isMaybeAbstract (e))
1241 uentry_setConcrete (e);
1247 uid = usymtab_supEntryAux (globtab, e, FALSE);
1248 e = usymtab_getTypeEntry (typeId_fromUsymId (uid));
1250 /*? evans 2002-12-16 removed this? it doesn't make sense
1251 if (uentry_isMaybeAbstract (e))
1253 uentry_setConcrete (e);
1258 if (sRef_modInFunction ())
1260 recordFunctionType (globtab->entries[uid]);
1263 return (globtab->entries[uid]);
1267 usymtab_supAbstractTypeEntry (/*@only@*/ uentry e, bool dodef)
1268 /*@globals globtab, filetab@*/
1269 /*@modifies globtab, e@*/
1274 uid = typeId_fromUsymId (usymtab_supEntryAux (globtab, e, FALSE));
1275 ue = usymtab_getTypeEntry (uid);
1279 uentry_setDatatype (ue, uid);
1282 if (context_getFlag (FLG_ACCESSMODULE)) /* was accessfile */
1284 context_addFileAccessType (uid);
1287 if (sRef_modInFunction ())
1289 recordFunctionType (globtab->entries[uid]);
1296 usymtab_supExposedTypeEntry (/*@only@*/ uentry e, bool dodef)
1297 /*@globals globtab, filetab@*/
1298 /*@modifies globtab, e@*/
1302 uid = typeId_fromUsymId (usymtab_supEntryAux (globtab, e, FALSE));
1306 uentry ue = usymtab_getTypeEntry (uid);
1308 uentry_setDatatype (ue, uid);
1311 if (sRef_modInFunction ())
1313 recordFunctionType (globtab->entries[uid]);
1320 usymtab_supForwardTypeEntry (/*@only@*/ uentry e)
1321 /*@globals globtab, filetab@*/
1322 /*@modifies globtab, e@*/
1324 typeId uid = typeId_fromUsymId (usymtab_supEntryAux (globtab, e, FALSE));
1325 uentry ue = usymtab_getTypeEntry (uid);
1327 uentry_setDatatype (ue, uid);
1329 if (sRef_modInFunction ())
1331 recordFunctionType (globtab->entries[uid]);
1334 return (uentry_getAbstractType (ue));
1338 usymtab_supEntrySref (uentry e)
1339 /*@globals utab, globtab, filetab@*/
1340 /*@modifies utab, globtab, e@*/
1342 sRef old = uentry_getSref (e);
1344 if (sRef_isType (old))
1346 uentry ue = usymtab_supEntryReturnAux (utab, e, TRUE);
1349 if (uentry_isValid (ue))
1351 sRef uref = uentry_getSref (ue);
1353 sRef_mergeStateQuiet (uref, old);
1354 sRef_clearDerived (uref);
1356 /*@noaccess uentry@*/
1358 else if (sRef_isKnown (old))
1360 usymtab_supEntry (e);
1364 (void) usymtab_supEntryAux (utab, e, TRUE);
1368 void usymtab_supGlobalEntry (/*@only@*/ uentry e)
1369 /*@globals globtab, filetab@*/
1370 /*@modifies globtab, filetab, e@*/
1374 DPRINTF (("Sup global entry: %s", uentry_unparse (e)));
1376 uid = usymtab_supEntryAux (globtab, e, FALSE);
1378 if (sRef_modInFunction ())
1380 recordFunctionType (globtab->entries[uid]);
1385 usymtab_supReturnFileEntry (/*@only@*/ uentry e)
1386 /*@globals filetab, globtab@*/
1387 /*@modifies filetab, globtab, e@*/
1389 llassert (filetab != usymtab_undefined);
1390 DPRINTF (("File entry: %s", uentry_unparse (e)));
1391 return (usymtab_supEntryReturnAux (filetab, e, FALSE));
1399 usymtab_inDeepScope () /*@globals utab@*/
1401 return (utab->lexlevel > paramsScope);
1405 usymtab_getIndex (/*@notnull@*/ usymtab s, cstring k)
1409 DPRINTF (("Lookup %s", k));
1411 if (cstringTable_isDefined (s->htable))
1413 i = cstringTable_lookup (s->htable, k);
1414 return usymId_fromInt (i);
1418 for (i = 0; i < s->nentries; i++)
1420 uentry current = s->entries[i];
1422 DPRINTF (("Check %d: %s", i, uentry_rawName (current)));
1424 if (!uentry_isUndefined (current)
1425 && cstring_equal (uentry_rawName (current), k))
1427 return usymId_fromInt (i);
1431 return usymId_notfound;
1436 usymtab_fetchIndex (/*@notnull@*/ usymtab s, usymId ui)
1438 int i = usymId_toInt (ui);
1439 llassert (i >= 0 && i < s->nentries);
1440 return (s->entries[i]);
1444 usymtab_getTypeId (cstring k) /*@globals globtab@*/
1446 usymId uid = usymtab_getIndex (globtab, k);
1448 if (!usymtab_indexFound (uid)
1449 || !(uentry_isDatatype (usymtab_getTypeEntry (typeId_fromUsymId (uid)))))
1452 return typeId_invalid;
1456 return typeId_fromUsymId (uid);
1460 /*@dependent@*/ uentry
1461 usymtab_lookupStructTag (cstring k)
1463 cstring sname = makeStruct (k);
1464 uentry ue = usymtab_lookupGlob (sname);
1466 cstring_free (sname);
1470 /*@dependent@*/ uentry
1471 usymtab_lookupUnionTag (cstring k)
1473 cstring uname = makeUnion (k);
1474 uentry res = usymtab_lookupGlob (uname);
1476 cstring_free (uname);
1480 /*@dependent@*/ uentry
1481 usymtab_lookupEnumTag (cstring k)
1483 cstring ename = makeEnum (k);
1484 uentry res = usymtab_lookupGlob (ename);
1486 cstring_free (ename);
1491 usymtab_getId (cstring k) /*@globals globtab@*/
1493 usymId uid = usymtab_getIndex (globtab, k);
1496 if (!usymtab_indexFound (uid))
1498 return usymId_invalid;
1501 ue = usymtab_getGlobalEntry (uid);
1503 if (uentry_isPriv (ue))
1505 return usymId_invalid;
1511 static /*@exposed@*/ uentry
1512 usymtab_getEntryAux (/*@notnull@*/ usymtab s, usymId uid)
1514 llassert (uid != usymId_invalid);
1516 if (uid < 0 || uid >= usymId_fromInt (s->nentries))
1518 llcontbug (message ("usymtab_getEntry: out of range: level = %d [%d]",
1520 return uentry_undefined;
1523 llassertprint (uentry_isValid (s->entries[uid]),
1524 ("entry undefined: %d", uid));
1526 return s->entries[uid];
1529 /*@dependent@*/ /*@observer@*/ uentry
1530 usymtab_getGlobalEntry (usymId uid)
1531 /*@globals utab, globtab@*/
1533 if (dbgfree) return (uentry_undefined);
1535 if (utab->lexlevel > paramsScope)
1537 /* need to do this the awkward way, since it could be in conditional scope */
1538 return (usymtab_lookupSafe (uentry_rawName (globtab->entries[uid])));
1542 return (globtab->entries[uid]);
1546 /*@dependent@*/ /*@exposed@*/ uentry usymtab_getTypeEntry (typeId uid)
1547 /*@globals globtab@*/
1551 if (uid >= 0 && uid < typeId_fromInt (globtab->nentries))
1553 return (globtab->entries[uid]);
1557 return (uentry_undefined);
1562 llassert (uid >= 0 && uid < typeId_fromInt (globtab->nentries));
1563 return (globtab->entries[uid]);
1571 /*@dependent@*/ /*@exposed@*/ uentry usymtab_getTypeEntrySafe (typeId uid)
1572 /*@globals globtab@*/
1574 if (uid < 0 || uid >= typeId_fromInt (globtab->nentries))
1576 return uentry_undefined;
1579 return (globtab->entries[uid]);
1582 bool usymtab_isBoolType (typeId uid)
1583 /*@globals globtab@*/
1585 llassert (uid >= 0 && uid < typeId_fromInt (globtab->nentries));
1587 return (cstring_equal (uentry_rawName (globtab->entries[uid]),
1588 context_getBoolName ()));
1591 cstring usymtab_getTypeEntryName (typeId uid)
1592 /*@globals globtab@*/
1598 return (cstring_makeLiteral ("<freetype>"));
1601 ue = usymtab_getTypeEntry (uid);
1603 if (dbgload && !uentry_isValid (ue))
1605 return (message ("<missing type: %d>", uid));
1608 llassertprint (uentry_isValid (ue), ("type undefined: %d", uid));
1610 return (uentry_getName (ue));
1614 /*@unused@*/ static void
1615 usymtab_rehash (/*@notnull@*/ usymtab s)
1619 if (cstringTable_isDefined (s->htable))
1621 cstringTable_free (s->htable);
1624 s->htable = cstringTable_create (LLAHSHSIZE);
1626 for (i = 0; i < s->nentries; i++)
1628 cstringTable_insert (s->htable, cstring_copy (uentry_rawName (s->entries[i])), i);
1634 ** superficial copy of usymtab
1636 ** DO copy spec entries
1639 static /*@only@*/ /*@notnull@*/ usymtab
1640 usymtab_shallowCopy (/*@notnull@*/ usymtab s) /*@*/
1642 usymtab copytab = usymtab_createRoot ();
1645 for (i = 0; i < s->nentries; i++)
1647 usymtab_addEntryBase (copytab, s->entries[i]);
1654 usymtab_shallowFree (/*@only@*/ /*@notnull@*/ usymtab s)
1656 aliasTable_free (s->aliases);
1657 refTable_free (s->reftable, s->nentries);
1659 /*@-compdestroy@*/ sfree (s); /*@=compdestroy@*/
1662 usymId usymtab_convertTypeId (typeId uid)
1664 return usymtab_convertId (typeId_toUsymId (uid));
1668 ** usymtab_convertId: converts usymId from old table to sorted one
1671 usymId usymtab_convertId (usymId uid)
1672 /*@globals oldtab, utab@*/
1678 llassert (usymtab_isDefined (oldtab));
1680 ue = usymtab_getEntryAux (oldtab, uid);
1682 llassertprint (uentry_isValid (ue), ("convertId: undefined: %d", uid));
1684 name = uentry_rawName (ue);
1686 ret = usymtab_getIndex (utab, name);
1687 llassert (ret == uid); /*! for now, no rehash! */
1688 DPRINTF (("Convert: %s [%d] -> %s [%d]",
1689 uentry_unparse (ue), uid,
1690 uentry_unparse (utab->entries[ret]), ret));
1692 llassertprint (ret != usymId_invalid, ("convertId: return is invalid"));
1698 usymtab_prepareDump (void)
1699 /*@globals oldtab, utab@*/
1700 /*@modifies oldtab, utab@*/
1702 llassert (usymtab_inGlobalScope ());
1703 llassert (oldtab == usymtab_undefined);
1706 DPRINTF (("Preparing to dump:"));
1707 usymtab_printAll ();
1710 oldtab = usymtab_shallowCopy (utab);
1713 ** alpha compare - make sure order is same on different platforms
1714 ** error messages appear in same order
1718 qsort (utab->entries, (size_t)utab->nentries,
1719 sizeof (*utab->entries),
1720 (int (*)(const void *, const void *)) uentry_xcomparealpha);
1722 usymtab_rehash (utab);
1726 DPRINTF (("After rehash:"));
1727 usymtab_printAll ();
1731 void usymtab_dump (FILE *fout)
1732 /*@globals utab, oldtab@*/
1735 bool neednl = FALSE;
1736 uentry lastentry = uentry_undefined;
1737 ekind lastekind = KINVALID;
1741 ** must call prepareDump first
1744 llassert (oldtab != usymtab_undefined);
1746 for (i = 0; i < utab->nentries; i++)
1748 uentry thisentry = utab->entries[i];
1749 ekind thisekind = uentry_getKind (thisentry);
1751 if (!uentry_hasRealName (thisentry))
1753 llassert (uentry_isGlobalMarker (thisentry));
1757 check (fputc ('\n', fout) == (int) '\n');
1760 fprintf (fout, "*%d (GlobalMarker)\n", KGLOBALMARKER);
1761 lastekind = KINVALID;
1767 if (thisekind != lastekind)
1771 check (fputc ('\n', fout) == (int) '\n');
1775 lastentry = uentry_undefined;
1776 fprintf (fout, "*%d (%s)\n", ekind_toInt (thisekind),
1777 cstring_toCharsSafe (ekind_capName (thisekind)));
1778 lastekind = thisekind;
1783 ** evans - 2001-02-18 - added the - 48 fudge factor...
1784 ** extra characters dumped, but I haven't counded them carefully...
1787 if (uentry_isInvalid (lastentry) || !uentry_equiv (lastentry, thisentry)
1788 || (linelen > (MAX_DUMP_LINE_LENGTH - (2 * MAX_NAME_LENGTH) - 48)))
1792 DPRINTF (("Dumping entry: %d", i));
1793 cdump = message ("^%d %q", i, uentry_dump (thisentry));
1794 /* was: cdump = uentry_dump (thisentry)); */
1796 lastentry = thisentry;
1799 check (fputc ('\n', fout) == (int) '\n');
1803 linelen += cstring_length (cdump);
1805 /* no new line here! */
1806 if (cstring_length (cdump) > 0)
1808 check (fputs (cstring_toCharsSafe (cdump), fout) != EOF);
1811 cstring_free (cdump);
1816 cstring cdump = uentry_rawName (thisentry);
1817 DPRINTF (("Raw name: %s", cdump));
1818 linelen += (cstring_length (cdump) + 1);
1819 fprintf (fout, "#%s", cstring_toCharsSafe (cdump));
1826 check (fputc ('\n', fout) == (int) '\n');
1829 lastekind = KINVALID;
1831 fprintf(fout, ";; Library constraints\n");
1833 /*drl July 27 added this so that libraries without
1834 buffer constraints would be handled correctly.
1835 I'm trying to do this without breaking older libraries.
1837 Splint should still be able to handle libraries without this message.
1841 fprintf(fout, "start_Buffer_Constraints\n");
1843 for (i = 0; i < utab->nentries; i++)
1845 uentry thisentry = utab->entries[i];
1847 if (uentry_isFunction (thisentry) )
1849 constraintList preconditions;
1850 constraintList postconditions;
1852 preconditions = uentry_getFcnPreconditions (thisentry);
1853 postconditions = uentry_getFcnPostconditions (thisentry);
1855 if ( constraintList_isDefined(preconditions) ||
1856 constraintList_isDefined(postconditions) )
1858 fprintf(fout,"%s\n", cstring_toCharsSafe (uentry_rawName(thisentry) ) );
1859 if (constraintList_isDefined(preconditions) )
1861 fprintf(fout,"pre:\n");
1862 constraintList_dump(preconditions, fout);
1863 fprintf (fout, ";; end precondition constraints\n" );
1864 constraintList_free(preconditions);
1868 fprintf(fout,"pre:EMPTY\n");
1870 if (constraintList_isDefined(postconditions) )
1872 fprintf(fout,"post:\n");
1873 constraintList_dump(postconditions, fout);
1874 fprintf (fout, ";; end precondition constraints\n" );
1875 constraintList_free(postconditions);
1879 fprintf(fout,"post:EMPTY\n");
1888 void usymtab_load (FILE *f)
1889 /*@globals utab, globtab@*/
1890 /*@modifies utab, *f@*/
1892 char *s = mstring_create (MAX_DUMP_LINE_LENGTH);
1894 ekind kind = KINVALID;
1895 fileloc loc = g_currentloc;
1901 llassert (utab == globtab);
1902 llassert (utab->nentries == 0);
1904 while (((s = reader_readLine (f, s, MAX_DUMP_LINE_LENGTH)) != NULL)
1907 /* ignore ; comments */ ;
1910 while (s != NULL && *s != ';')
1918 ek = reader_getInt (&s);
1920 if (ek == KGLOBALMARKER)
1922 uentry lue = uentry_makeGlobalMarker ();
1923 DPRINTF (("Adding global marker: %s", uentry_unparseFull (lue)));
1924 usymtab_addEntryAlways (utab, lue);
1930 kind = ekind_fromInt (ek);
1938 (cstring_makeLiteral
1939 ("Library is in obsolete format. Use splint +whichlib "
1940 "to see which library is being loaded."));
1943 if (reader_optCheckChar (&s, '^'))
1945 index = reader_getInt (&s);
1952 llassert (kind != KINVALID);
1953 ue = uentry_undump (kind, loc, &s);
1955 llassert (utab->nentries == index || index == -1);
1957 if (uentry_isValid (ue))
1959 int lastindex = utab->nentries;
1960 ue = usymtab_addEntryAlways (utab, ue);
1964 if (uentry_isConstant (ue)) /*@i23! isPreProcessorMacro */
1966 cstring uname = uentry_getName (ue);
1968 /* Also check its a macro... */
1969 DPRINTF (("Installing: %s", uname));
1971 cpphash_installMacro
1972 (mstring_copy (cstring_toCharsSafe (uname)),
1973 cstring_length (uname),
1974 cpplib_createDefinition (message ("%s 255", uname),
1977 cpphash_hashCode (cstring_toCharsSafe (uname),
1978 cstring_length (uname),
1981 DPRINTF (("After install: %s", uname));
1985 if (utab->nentries != lastindex + 1)
1987 DPRINTF (("No add: %s", uentry_unparseFull (ue)));
1995 ** now, any other names are the same uentry
1998 while (*(s++) == '#')
2000 cstring name = cstring_fromCharsO (reader_getWord (&s));
2001 uentry nue = uentry_nameCopy (name, ue);
2003 DPRINTF (("Name copy: %s", uentry_unparseFull (nue)));
2007 usymtab_addEntryAlways (utab, nue);
2010 while ((c = *s) != '\0' && (c !='\n'))
2012 if (c != ' ' || c != '\t')
2014 llbuglit ("Junk in load file");
2022 s = reader_readLine (f, os, MAX_DUMP_LINE_LENGTH);
2027 to handle reading of buffer overflow related constraints
2029 while (fgets (s, MAX_DUMP_LINE_LENGTH, f) != NULL
2032 ; /* ignore ;-comments */
2035 /*drl July 27 added this so that libraries without
2036 buffer constraints would be handled correctly.
2037 I'm trying to do this without breaking older libraries*/
2039 /*check for "optional" start buffer constraints message*/
2041 if (mstring_equalPrefix (s, "start_Buffer_Constraints"))
2043 (void) fgets (s, MAX_DUMP_LINE_LENGTH, f);
2046 while (s != NULL && *s != ';')
2048 constraintList preconditions;
2049 constraintList postconditions;
2050 cstring name = cstring_fromChars (reader_getWord (&s));
2053 ue = usymtab_lookup (name);
2054 cstring_free (name);
2056 preconditions = constraintList_undefined;
2057 postconditions = constraintList_undefined;
2059 if (!uentry_isValid(ue) )
2061 llfatalbug ((message("Invalid uentry for %s library file may be corrupted", cstring_fromChars(s) ) ));
2063 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2065 temp = cstring_fromChars (reader_getWord(&s) );
2067 if (cstring_compareLit (temp,"pre:") == 0 )
2069 preconditions = constraintList_undump (f);
2073 if (cstring_compareLit (temp,"pre:EMPTY") != 0 )
2074 llfatalbug ((message("Error reading library file pre:EMPTY expected but got %s", temp ) ));
2079 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2081 temp = cstring_fromChars(reader_getWord(&s) );
2082 if (cstring_compareLit (temp, "post:") == 0 )
2084 postconditions = constraintList_undump (f);
2088 if (cstring_compareLit (temp, "post:EMPTY") != 0 )
2089 llfatalbug ((message("Error reading library file post:EMPTY expected but got %s", temp ) ));
2092 cstring_free (temp);
2094 uentry_setPreconditions (ue, functionConstraint_createBufferConstraint (preconditions));
2095 uentry_setPostconditions (ue, functionConstraint_createBufferConstraint (postconditions));
2097 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2105 ** file scope for static variables
2109 usymtab_enterFile ()
2110 /*@globals utab, globtab, filetab@*/
2111 /*@modifies filetab@*/
2113 llassert (utab == globtab);
2118 usymtab_entries (globtab, ue)
2120 if (sRef_hasDerived (uentry_getSref (ue)))
2122 fprintf (g_warningstream, "Derived Global: %s\n", uentry_unparse (ue));
2123 fprintf (g_warningstream, "sRef: %s\n", sRef_unparseFull (ue->sref));
2125 } end_usymtab_entries ;
2129 usymtab_enterScope ();
2135 /*@globals utab, filetab@*/
2136 /*@modifies filetab, utab@*/
2139 llassert (utab->lexlevel == 1);
2141 usymtab_exitScope (exprNode_undefined);
2146 usymtab_enterScope ()
2147 /*@globals utab, globtab, filetab@*/
2150 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
2152 /* unconditional scope: optimize to avoid copy */
2153 t->aliases = aliasTable_copy (utab->aliases);
2156 llassert (usymtab_isDefined (t->env));
2158 if (t->env->lexlevel == paramsScope && context_inFunctionLike ())
2160 noshadowerror = TRUE;
2161 usymtab_handleParams ();
2162 noshadowerror = FALSE;
2167 ** setup external references:
2168 ** o only, unique params alias external args
2169 ** o other params may alias anything of their type
2173 usymtab_handleParams (void)
2174 /*@globals utab, globtab, filetab@*/
2175 /*@modifies utab, globtab@*/
2177 usymtab ptab = utab->env;
2178 uentry fcn = context_getHeader ();
2180 usymtab_entries (ptab, param)
2184 if (!uentry_isYield (param))
2187 sRef pref = uentry_getSref (param);
2189 /* Could be a global. */
2191 if (uentry_isAnyParam (param))
2193 ue = uentry_makeVariable (fixParamName (uentry_rawName (param)),
2194 uentry_getType (param),
2195 fileloc_copy (uentry_whereDeclared (param)),
2198 uentry_copyState (ue, param);
2199 uentry_setRefParam (ue);
2201 ue = usymtab_supEntrySrefReturn (ue);
2203 /* must be after supercede! */
2205 if (!sRef_stateKnown (pref))
2207 uentry_setDefState (ue, SS_DEFINED);
2208 uentry_setDefState (param, SS_DEFINED);
2212 if (sRef_isStateSpecial (pref))
2214 uentry_setDefState (ue, SS_SPECIAL); /* ALLOCATED); */
2215 /* evans 2002-01-01: should be unnecessary, the pre clauses
2216 ** set the state if necessary.
2221 uentry_setDefState (ue, sRef_getDefState (pref));
2225 uref = uentry_getSref (ue);
2227 if (sRef_isStack (uref))
2229 alkind pkind = sRef_getAliasKind (pref);
2231 if (alkind_isKnown (pkind) && !alkind_isLocal (pkind)
2232 && !alkind_isStack (pkind))
2234 sRef_setAliasKind (uref, pkind, fileloc_undefined);
2235 sRef_setOrigAliasKind (uref, pkind);
2239 sRef_setAliasKind (uref, AK_IMPTEMP, fileloc_undefined);
2240 sRef_setOrigAliasKind (uref, AK_IMPTEMP);
2242 if (uentry_isOut (param))
2248 sRef_setDefined (uref, fileloc_undefined);
2254 usymtab_addMustAlias (uref, pref);
2256 if (!(uentry_isOnly (param) || uentry_isUnique (param)))
2259 ** This is needed for detecting possibly aliased parameters.
2262 sRef s = sRef_makeExternal (uref);
2263 usymtab_addMustAlias (uref, s);
2266 if (sRef_isKillRef (pref))
2268 sRef_setAliasKind (uref, AK_NEWREF, fileloc_undefined);
2269 sRef_setOrigAliasKind (uref, AK_KILLREF);
2271 else if (sRef_isRefCounted (uref))
2273 sRef_setOrigAliasKind (uref, AK_REFCOUNTED);
2278 sRef_setOrigAliasKind (uref, AK_LOCAL);
2285 } end_usymtab_entries;
2288 if (uentry_hasStateClauseList (fcn))
2290 stateClauseList clauses = uentry_getStateClauseList (fcn);
2292 stateClauseList_preElements (clauses, cl)
2294 fileloc loc = stateClause_loc (cl);
2295 sRefSet osrs = sRefSet_undefined;
2298 if (stateClause_isGlobal (cl))
2300 DPRINTF (("Global Marker: %s",
2301 sRef_unparseFull (usymtab_lookupGlobalMarker ())));
2302 llassert (sRef_isGlobalMarker (usymtab_lookupGlobalMarker ()));
2303 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
2308 srs = stateClause_getRefs (cl);
2311 sRefSet_elements (srs, el)
2313 sRef base = sRef_getRootBase (el);
2314 sRef sb = sRef_updateSref (el);
2316 if (sRef_isResult (base))
2318 ; /* nothing to do before */
2320 else if (sRef_isParam (base) || sRef_isGlobalMarker (base))
2322 if (stateClause_setsMetaState (cl))
2324 /* copied from exprNode.c:3040 */
2325 qual ql = stateClause_getMetaQual (cl);
2326 annotationInfo ainfo = qual_getAnnotationInfo (ql);
2327 metaStateInfo minfo = annotationInfo_getState (ainfo);
2328 cstring key = metaStateInfo_getName (minfo);
2329 int mvalue = annotationInfo_getValue (ainfo);
2331 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
2333 if (sRef_isResult (base))
2339 sRef_setMetaStateValueComplete (sb, key, mvalue, loc);
2344 sRefMod modf = stateClause_getEntryFunction (cl);
2348 sRefSet aliases = usymtab_allAliases (sb);
2352 sRefSet_elements (aliases, sr)
2355 } end_sRefSet_elements ;
2357 sRefSet_free (aliases);
2363 if (sRef_isValid (base))
2365 DPRINTF (("Base: %s", sRef_unparseFull (base)));
2369 } end_sRefSet_elements ;
2370 } end_stateClauseList_preElements ;
2375 usymtab_enterFunctionScope (uentry fcn)
2376 /*@globals utab, filetab, globtab@*/
2379 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
2381 DPRINTF (("Enter function: %s", uentry_unparse (fcn)));
2383 if (utab->lexlevel != fileScope)
2385 if (utab->lexlevel > fileScope)
2387 llparseerror (cstring_makeLiteral ("New function scope inside function"));
2389 while (utab->lexlevel > fileScope)
2391 /*@i@*/ utab = usymtab_dropEnv (utab);
2398 llfatalbug (cstring_makeLiteral ("New function not inside file."));
2400 /*@-branchstate@*/ } /*@=branchstate@*/
2404 DPRINTF (("Globs: %s", globSet_unparse (uentry_getGlobs (fcn))));
2406 globSet_allElements (uentry_getGlobs (fcn), el)
2408 DPRINTF (("Here we go: %s", sRef_unparseFull (el)));
2410 if (sRef_isUndefGlob (el))
2412 usymId index = sRef_getScopeIndex (el);
2413 sRef sr = sRef_updateSref (el);
2414 fileloc loc = uentry_whereEarliest (fcn);
2416 DPRINTF (("update: %s", sRef_unparseFull (sr)));
2417 DPRINTF (("Undef!"));
2418 if (sRef_isFileStatic (el))
2420 ctype ct = sRef_getType (el);
2423 llassert (usymtab_isDefined (filetab));
2425 ue = usymtab_fetchIndex (filetab, index);
2427 if (ctype_isRealArray (ct) || ctype_isRealSU (ct))
2429 sRef_setAllocated (sr, loc);
2433 sRef_setUndefined (sr, loc);
2438 uentry ue = globtab->entries[index];
2439 ctype ct = uentry_getType (ue);
2441 if (ctype_isArray (ct) || ctype_isSU (ct))
2443 sRef_setAllocated (sr, loc);
2447 sRef_setUndefined (sr, loc);
2451 else if (sRef_isAllocated (el))
2453 sRef sr = sRef_updateSref (el);
2454 fileloc loc = uentry_whereEarliest (fcn);
2456 sRef_setAllocated (sr, loc);
2458 else if (sRef_isPartial (el))
2460 sRef sr = sRef_updateSref (el);
2461 fileloc loc = uentry_whereEarliest (fcn);
2463 sRef_setPartial (sr, loc);
2468 sRef sr = sRef_updateSref (el);
2469 fileloc loc = uentry_whereEarliest (fcn);
2471 sRef_setDefined (sr, loc);
2475 /* shouldn't need to do anything! */
2477 } end_globSet_allElements;
2479 DPRINTF (("Globs after: %s", globSet_unparse (uentry_getGlobs (fcn))));
2481 usymtab_checkAllValid ();
2486 usymtab_caseBranch (void)
2489 usymtab t = usymtab_create (US_CBRANCH, utab, FALSE);
2494 usymtab_switchBranch (/*@unused@*/ exprNode s)
2497 usymtab t = usymtab_create (US_SWITCH, utab, FALSE);
2499 t->aliases = aliasTable_copy (utab->aliases);
2504 usymtab_trueBranch (/*@only@*/ guardSet guards)
2507 usymtab t = usymtab_create (US_TBRANCH, utab, FALSE);
2510 ** not true! (could be in a macro)
2512 ** llassertprint (utab->lexlevel > paramsScope,
2513 ** ("not in scope: %s", usymtab_unparseLocal ()));
2517 guardSet_free (t->guards);
2520 aliasTable_free (t->aliases);
2521 t->aliases = aliasTable_copy (utab->aliases);
2529 ** { int a; if (...) a = 3; < a may be undefined here!
2534 usymtab_popTrueBranch (exprNode pred, exprNode expr, clause cl) /*@modifies utab@*/
2537 ** add a false branch
2538 ** (could be done more efficiently as a special case, but
2539 ** it is better to only maintain one version of the code)
2542 if (utab->kind != US_TBRANCH
2543 && context_inIterDef ())
2545 usymtab_exitScope (expr);
2549 DPRINTF (("pop true branch.."));
2550 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2551 usymtab_popBranches (pred, expr, exprNode_undefined, TRUE, cl);
2556 usymtab_popCaseBranch () /*@modifies utab@*/
2558 llassert (utab->kind == US_CBRANCH);
2559 usymtab_quietPlainExitScope ();
2563 usymtab_popTrueExecBranch (exprNode pred, exprNode expr, clause cl)
2566 ** add a false branch that must return --- that is,
2567 ** the true branch is always executed!
2570 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2571 usymtab_popBranches (pred, expr, exprNode_makeMustExit (), FALSE, cl);
2575 usymtab_popOrBranch (exprNode pred, exprNode expr)
2579 usymtab env = utab->env;
2580 usymtab otab = utab;
2583 llassert (env != NULL);
2585 if (exprNode_isError (expr))
2591 mustReturn = exprNode_mustEscape (expr);
2595 llassert (utab->kind == US_TBRANCH);
2598 ** merge each entry in table with its original
2599 ** unless execution cannot continue after this branch
2602 for (i = 0; i < utab->nentries; i++)
2604 uentry current = utab->entries[i];
2605 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2607 uentry_mergeState (old, current, exprNode_loc (expr),
2608 mustReturn, FALSE, TRUE, ORCLAUSE);
2614 env->guards = guardSet_levelUnionFree (env->guards,
2615 guardSet_invert (exprNode_getGuards (pred)),
2620 env->aliases = aliasTable_levelUnion (env->aliases, otab->aliases, env->lexlevel);
2623 /* env is now utab */
2624 usymtab_quietPlainExitScope ();
2628 ** case syntax in C is very unrestricted. This is unfortunate.
2630 ** A switch case is ended either by a new case or default, or
2631 ** a close } that may close the switch or some other control
2636 usymtab_newCase (/*@unused@*/ exprNode pred, exprNode last)
2639 bool mustBreak = usymtab_mustBreak (utab);
2640 bool mustReturn = usymtab_mustEscape (utab);
2641 usymtab stab = utab;
2643 DPRINTF (("New case!"));
2646 ** Find last case (or outer switch)
2649 while (stab->kind != US_CBRANCH && stab->kind != US_SWITCH)
2652 llassert (stab != GLOBAL_ENV);
2655 while (stab->kind == US_CBRANCH)
2658 llassert (stab != GLOBAL_ENV);
2662 ** if its a fall through case, merge in outside entries and last case.
2667 ** case 1: x = 3; <fall through>
2668 ** case 2: << x may not be defined
2672 if (!mustBreak && !mustReturn && utab->kind == US_CBRANCH)
2674 llassert (stab->kind == US_SWITCH || stab->kind == US_NORMAL);
2676 usymtab_entries (utab, ue) /* but, keep track of used variables */
2678 uentry old = usymtab_lookupAux (stab, uentry_rawName (ue));
2680 llassert (uentry_isValid (old));
2682 /* modifies ue, not old */
2684 uentry_mergeState (ue, old, exprNode_loc (last),
2685 FALSE, FALSE, TRUE, CASECLAUSE);
2686 } end_usymtab_entries;
2688 utab->aliases = aliasTable_levelUnion (utab->aliases,
2689 stab->aliases, utab->lexlevel);
2692 ** No need for a new branch.
2699 usymtab_caseBranch ();
2700 /*@-mustfree@*/ /*< utab->aliases >*/
2701 utab->aliases = aliasTable_copy (stab->aliases);
2709 ** for && (both pred and expr are executed)
2713 usymtab_popAndBranch (exprNode pred, /*@unused@*/ exprNode expr)
2716 usymtab env = utab->env;
2720 llassert (utab->kind == US_TBRANCH);
2723 ** merge each entry in table with its original
2724 ** unless execution cannot continue after this branch
2727 for (i = 0; i < utab->nentries; i++)
2729 uentry current = utab->entries[i];
2730 sRef tref = uentry_getSref (current);
2731 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2732 sRef oref = uentry_getSref (old);
2734 /* note that is current is in a nested branch,
2735 it may create a "new" old entry. */
2737 llassert (uentry_isValid (old));
2738 uentry_mergeState (old, current, exprNode_loc (expr),
2739 FALSE, FALSE, TRUE, ANDCLAUSE);
2742 ** if is it defined by the second clause, then it should be defined.
2745 if (sRef_isAnyDefined (tref)
2746 && (sRef_isAllocated (oref) || sRef_isStateUndefined (oref)))
2748 sRef_setDefined (oref, g_currentloc);
2752 DPRINTF (("Popping and: %s / %s",
2753 guardSet_unparse (utab->guards),
2754 guardSet_unparse (exprNode_getGuards (pred))));
2756 utab->guards = guardSet_levelUnionFree (utab->guards,
2757 guardSet_invert (exprNode_getGuards (pred)),
2759 utab->aliases = aliasTable_levelUnion (utab->aliases, otab->aliases, utab->lexlevel);
2761 usymtab_quietPlainExitScope ();
2766 ** Stack should be [ US_CBRANCH+ US_SWITCH ]
2767 ** Only branches which do not return (except possibly the last branch) are included.
2769 ** Conditionally merge state from all CBRANCHes.
2771 ** If allpaths is TRUE, then all possible executions go through some switch
2772 ** case, and the original scope is not merged.
2776 usymtab_exitSwitch (/*@unused@*/ exprNode sw, bool allpaths)
2779 usymtab ttab = utab;
2780 usymtab stab = ttab;
2781 usymtab ltab = ttab;
2782 bool lastMustReturn = usymtab_mustEscape (utab);
2786 while (stab->kind == US_CBRANCH)
2789 llassert (stab != GLOBAL_ENV);
2792 while (stab->kind == US_NORMAL)
2795 llassert (stab != GLOBAL_ENV);
2798 llassert (stab->kind == US_SWITCH);
2800 /* go to the scope outside the switch (US_SWITCH is just a marker! */
2802 llassert (stab != GLOBAL_ENV);
2806 llassert (usymtab_isDefined (ttab));
2808 if (ttab->kind == US_CBRANCH)
2810 /* was quietPlainExitScope --- but, can't free it yet! */
2812 llassert (utab != GLOBAL_ENV);
2814 while (ttab->kind == US_CBRANCH)
2817 ** (from popTrueBranch)
2820 bool mustReturn = usymtab_mustEscape (ttab);
2821 bool mustBreak = usymtab_mustBreak (ttab);
2823 usymtab_entries (ttab, current)
2825 uentry old = /*@-compmempass@*/ usymtab_lookupAux (ltab, uentry_rawName (current));
2829 ** note that is this is in a nested branch,
2830 ** it may create a "new" old entry.
2833 if (uentry_isValid (old))
2837 uentry_mergeUses (current, old);
2838 uentry_setState (old, current);
2842 uentry_mergeState (old, current, exprNode_loc (sw),
2843 mustReturn, FALSE, TRUE, SWITCHCLAUSE);
2850 } end_usymtab_entries;
2853 ** if entry is not in symbol table for this case, merge with pre-switch
2857 if (!mustReturn && !mustBreak)
2859 usymtab_entries (stab, current)
2861 if (!usymtab_indexFound (usymtab_getIndex (ttab, uentry_rawName (current))))
2863 uentry old = /*@-compmempass@*/
2864 usymtab_lookupAux (ltab, uentry_rawName (current));
2867 llassert (uentry_isValid (old));
2868 uentry_mergeState (old, current, exprNode_loc (sw),
2869 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2871 } end_usymtab_entries;
2874 ltab->env = ttab->env;
2878 ** Suprious error, becuase of environments.
2881 /*@i1@*/ utab = ltab;
2883 lastMustReturn = FALSE;
2890 ** now, there is one US_CBRANCH. Merge this with the stab.
2894 for (i = 0; i < ltab->nentries; i++)
2896 uentry current = ltab->entries[i];
2897 uentry old = usymtab_lookupAux (stab, uentry_rawName (current));
2899 /* note that is this is in a nested branch,
2900 it may create a "new" old entry. */
2903 if (uentry_isValid (old))
2907 uentry_mergeUses (current, old);
2908 uentry_setState (old, current);
2912 uentry_mergeState (old, current, exprNode_loc (sw),
2913 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2927 ** switch may or may not be followed by a new scope
2930 if (utab->kind == US_SWITCH)
2932 usymtab_quietPlainExitScope ();
2936 usymtab_quietPlainExitScope ();
2937 llassert (utab->kind == US_SWITCH);
2938 usymtab_quietPlainExitScope ();
2944 updateNullState (sRef el, /*@notnull@*/ usymtab ttab,
2945 /*@notnull@*/ usymtab ftab, bool trueGuard)
2947 sRef base = sRef_getRootBase (el);
2948 int level = sRef_lexLevel (base);
2950 if (sRef_isCvar (base))
2952 usymId index = sRef_getScopeIndex (base);
2953 uentry ue = usymtab_getRefTab (ttab, level, index);
2955 if (!uentry_isLset (ue))
2957 sRef sr = uentry_getSref (ue);
2961 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2965 if (!guardSet_isGuarded (ttab->guards, el)
2966 && !sRef_isNotNull (sr))
2968 DPRINTF (("Here! %s / %s",
2969 sRef_unparseFull (sr),
2970 sRef_unparseFull (el)));
2971 sRef_setDerivNullState (sr, el, NS_DEFNULL);
2980 ue = usymtab_getRefTab (ftab, level, index);
2982 if (!uentry_isLset (ue))
2984 sRef sr = uentry_getSref (ue);
2986 if (!trueGuard) /* yikes! forgot the ! */
2988 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2993 if (!guardSet_isGuarded (ftab->guards, el)
2994 && !sRef_isNotNull (sr))
2996 sRef_setDerivNullState (sr, el, NS_DEFNULL);
3008 usymtab_popBranches (exprNode pred, exprNode tbranch, exprNode fbranch,
3009 bool isOpt, clause cl)
3013 usymtab ftab = utab;
3014 usymtab ttab = utab->env;
3018 guardSet guards = exprNode_getGuards (pred);
3019 sRefSet tguards = guardSet_getTrueGuards (guards);
3020 sRefSet fguards = guardSet_getFalseGuards (guards);
3021 bool mustReturnT = exprNode_mustEscape (tbranch);
3022 bool mustReturnF = exprNode_mustEscape (fbranch);
3024 DPRINTF (("Pop branches: %s [mustreturn: %s/%s]", exprNode_unparse (pred),
3025 bool_unparse (mustReturnT),
3026 bool_unparse (mustReturnF)));
3028 if (exprNode_isDefined (fbranch))
3030 loc = exprNode_loc (fbranch);
3034 loc = exprNode_loc (tbranch);
3037 llassert (usymtab_isDefined (ttab));
3041 llassert (usymtab_isDefined (env));
3042 llassert (ftab->kind == US_FBRANCH);
3043 llassert (ttab->kind == US_TBRANCH);
3046 ** For each element that is true guarded (i.e., if (x != NULL))
3047 ** make x = null in false branch,
3048 ** and x = notnull in true branch.
3049 ** unless x was set locally in that branch.
3050 ** For each element that is false guarded (x == NULL)
3051 ** make x = null in true, notnull in false.
3053 ** For each element that is either guarded (pred(x))
3057 sRefSet_allElements (tguards, el)
3059 updateNullState (el, ttab, ftab, TRUE);
3060 } end_sRefSet_allElements;
3062 sRefSet_allElements (fguards, el)
3064 updateNullState (el, ttab, ftab, FALSE);
3065 } end_sRefSet_allElements;
3069 ** if an entry is in both true and false, merge the entries,
3070 ** then replace original with new state.
3072 ** if an entry is in one table, merge it with the original.
3075 DPRINTF (("ftab: %d", ftab->nentries));
3077 for (i = 0; i < ftab->nentries; i++)
3079 uentry fthis = ftab->entries[i];
3080 uentry old = usymtab_lookupAux (env, uentry_rawName (fthis));
3081 usymId tindex = usymtab_getIndex (ttab, uentry_rawName (fthis));
3083 DPRINTF (("Entry: %s / %s", uentry_unparseFull (fthis), uentry_unparseFull (old)));
3085 if (uentry_isUndefined (old))
3087 /* possible entry was added as an undefined id */
3088 DPRINTF (("Undefined! %s", uentry_rawName (fthis)));
3092 if (usymtab_indexFound (tindex))
3094 uentry tthis = ttab->entries[tindex];
3096 /* note that is this is in a nested branch,
3097 it may create a "new" old entry. */
3103 uentry_mergeState (fthis, tthis, loc,
3104 mustReturnT, FALSE, FALSE, cl);
3108 uentry_mergeUses (fthis, tthis);
3111 uentry_setState (old, fthis);
3118 uentry_setState (old, tthis);
3119 uentry_mergeState (old, fthis, loc, mustReturnF,
3123 ttab->entries[tindex] = uentry_undefined;
3124 uentry_free (tthis);
3128 uentry_mergeState (old, fthis, loc, mustReturnF, TRUE, FALSE, cl);
3132 for (i = 0; i < ttab->nentries; i++)
3134 uentry current = ttab->entries[i];
3136 DPRINTF (("ttab: %s", uentry_unparseFull (current)));
3138 if (!uentry_isUndefined (current))
3140 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
3142 DPRINTF (("Old: %s", uentry_unparseFull (old)));
3144 if (uentry_isUndefined (old))
3146 llcontbug (message ("Undefined entry: %s", uentry_rawName (current)));
3152 uentry_mergeUses (current, old);
3153 uentry_setState (old, current);
3158 ** Assumes false branch is a fall-through if
3159 ** fbranch is not defined. This is true, unless
3160 ** where was some greivous error in processing
3161 ** the else branch of an if-then, in which case
3162 ** this is probably the right thing to do anyway.
3165 uentry_mergeState (old, current, loc, mustReturnT,
3169 DPRINTF (("==> %s", uentry_unparseFull (old)));
3174 ** Plain levelUnion doesn't work, since we need to use the sRef's in env->aliases
3175 ** if they are present.
3178 llassert (NOALIAS (env->aliases, ttab->aliases));
3179 llassert (NOALIAS (env->aliases, ftab->aliases));
3181 aliasTable_free (env->aliases);
3183 env->aliases = aliasTable_levelUnionNew (ttab->aliases,
3184 ftab->aliases, env->lexlevel);
3186 aliasTable_fixSrefs (env->aliases);
3188 DPRINTF (("Aliases: %s", aliasTable_unparse (env->aliases)));
3190 /* exit true and false scopes */
3191 usymtab_quietPlainExitScope ();
3192 usymtab_quietPlainExitScope ();
3196 utab->guards = guardSet_levelUnionFree
3198 guardSet_invert (exprNode_getGuards (pred)),
3204 utab->guards = guardSet_levelUnion (utab->guards,
3205 exprNode_getGuards (pred),
3209 DPRINTF (("Here."));
3212 static void usymtab_fixCases (void) /*@modifies utab@*/ {
3213 while (utab->kind == US_CBRANCH)
3215 usymtab_quietPlainExitScope ();
3218 llassert (utab->kind != US_CBRANCH);
3222 usymtab_altBranch (/*@only@*/ guardSet guards)
3226 usymtab parent = utab->env;
3228 t = usymtab_create (US_FBRANCH, utab, FALSE);
3231 ** If we are in a case, need to close it. The C syntax
3232 ** is very liberal, so this kludge is necessary.
3235 usymtab_fixCases ();
3237 DPRINTF (("Current kind: %s", usymtab_unparseStack ()));
3239 llassert (utab->kind == US_TBRANCH);
3240 llassert (parent != GLOBAL_ENV);
3242 guardSet_free (t->guards);
3245 aliasTable_free (t->aliases);
3246 t->aliases = aliasTable_copy (parent->aliases);
3252 usymtab_allDefined (void)
3253 /*@globals utab, globtab@*/
3257 llassert (utab == globtab);
3259 for (i = 0; i < utab->nentries; i++)
3261 uentry e = utab->entries[i];
3263 if (uentry_isPriv (e))
3265 ; /* no need to define it */
3269 if (context_getFlag (FLG_SPECUNDECL))
3271 fileloc sloc = uentry_whereSpecified (e);
3272 fileloc dloc = uentry_whereDeclared (e);
3274 if (fileloc_isDefined (sloc)
3275 && !uentry_isFakeTag (e)
3276 && !fileloc_isDefined (dloc))
3280 message ("%s %q specified but not declared",
3281 ekind_capName (uentry_getKind (e)),
3282 uentry_getName (e)),
3287 if (!uentry_isCodeDefined (e))
3289 fileloc dloc = uentry_whereDeclared (e);
3291 if (fileloc_isLib (dloc) || fileloc_isXHFile (dloc))
3295 else if (fileloc_isDefined (dloc))
3297 if (!uentry_isAnyTag (e))
3299 if (fileloc_isUser (dloc))
3303 message ("%s %q declared but not defined",
3304 ekind_capName (uentry_getKind (e)),
3305 uentry_getName (e)),
3307 DPRINTF (("decl: %s", uentry_unparseFull (e)));
3313 fileloc sloc = uentry_whereSpecified (e);
3315 if (fileloc_isDefined (sloc)
3316 && !fileloc_isImport (sloc)
3317 && !fileloc_isLib (sloc)
3318 && !fileloc_isPreproc (sloc)
3319 && !uentry_isFakeTag (e))
3321 if (uentry_isVariable (e) || uentry_isFunction (e))
3325 message ("%s %q specified but not declared or defined",
3326 ekind_capName (uentry_getKind (e)),
3327 uentry_getName (e)),
3334 message ("%s %q specified but not defined",
3335 ekind_capName (uentry_getKind (e)),
3336 uentry_getName (e)),
3346 void usymtab_exportHeader (void)
3351 for (i = 0; i < utab->nentries; i++)
3353 uentry ce = utab->entries[i];
3355 if (!uentry_isDatatype (ce)
3356 && !uentry_isAnyTag (ce)
3357 && !uentry_isEitherConstant (ce) && !uentry_isStatic (ce)
3358 && !uentry_isExternal (ce)
3359 && !uentry_isForward (ce))
3361 fileloc fwhere = uentry_whereDeclared (ce);
3363 if (fileloc_isUndefined (fwhere)
3364 && uentry_isFunction (ce))
3366 fwhere = uentry_whereDefined (ce);
3369 if (fileloc_isDefined (fwhere)
3370 && !fileloc_isHeader (fwhere)
3371 && !fileloc_isXHFile (fwhere)
3372 && !(fileloc_isSpecialFile (fwhere)
3373 && !context_getFlag (FLG_UNUSEDSPECIAL)))
3375 if (uentry_isVariable (ce))
3378 (FLG_EXPORTHEADERVAR,
3379 message ("%s %q exported but not declared in header file",
3380 ekind_capName (uentry_getKind (ce)),
3381 uentry_getName (ce)),
3384 uentry_showDefSpecInfo (ce, fwhere);
3389 if (!uentry_isIter (ce)
3390 && !uentry_isEndIter (ce)
3391 && !uentry_isExpandedMacro (ce))
3393 if (uentry_isFunction (ce)
3394 && cstring_equalLit (uentry_rawName (ce), "main"))
3396 ; /* no error for main */
3402 message ("%s %q exported but not declared "
3404 ekind_capName (uentry_getKind (ce)),
3405 uentry_getName (ce)),
3408 uentry_showDefSpecInfo (ce, fwhere);
3418 void usymtab_exportLocal (void)
3423 for (i = 0; i < utab->nentries; i++)
3425 uentry ce = utab->entries[i];
3427 if (!uentry_isDatatype (ce) && !uentry_isAnyTag (ce)
3428 && !uentry_isEitherConstant (ce)
3429 && !uentry_isIter (ce)
3430 && !uentry_isEndIter (ce)
3431 && !uentry_isExpandedMacro (ce)
3432 && uentry_isUsed (ce))
3434 /* check static uses */
3435 filelocList fuses = uentry_getUses (ce);
3436 fileloc mod = uentry_whereDefined (ce);
3437 bool ok = filelocList_isEmpty (fuses);
3438 fileloc fwhere = uentry_whereDeclared (ce);
3440 if (fileloc_isSpecialFile (fwhere)
3441 && !context_getFlag (FLG_UNUSEDSPECIAL))
3443 ok = TRUE; /* no errors for special files */
3447 filelocList_elements (fuses, uloc)
3449 if (fileloc_isUndefined (uloc) || !fileloc_sameModule (uloc, mod))
3452 /*@innerbreak@*/ break;
3454 } end_filelocList_elements;
3461 message ("%s exported but not used outside %s: %q",
3462 ekind_capName (uentry_getKind (ce)),
3463 fileloc_getBase (mod),
3464 uentry_getName (ce)),
3467 uentry_showDefSpecInfo (ce, fwhere);
3475 usymtab_allUsed (void)
3479 bool isFileStatic = usymtab_inFileScope ();
3480 cstring last_file = cstring_undefined;
3482 for (i = 0; i < utab->nentries; i++)
3484 bool hasError = FALSE;
3485 uentry ce = utab->entries[i];
3486 fileloc fwhere = uentry_whereDeclared (ce);
3488 if (fileloc_isUndefined (fwhere))
3490 fwhere = uentry_whereDefined (ce);
3493 if (fileloc_isInvalid (fwhere)
3494 || fileloc_isLib (fwhere)
3495 || fileloc_isBuiltin (fwhere)
3496 || ((fileloc_isSpecialFile (fwhere)
3497 || fileloc_isSpecialFile (uentry_whereDefined (ce)))
3498 && !context_getFlag (FLG_UNUSEDSPECIAL)))
3502 else if (!uentry_wasUsed (ce) && !uentry_isAnyTag (ce))
3504 cstring fname = fileloc_filename (fwhere);
3506 if (cstring_isUndefined (last_file))
3510 else if (cstring_equal (fname, last_file))
3519 if (uentry_isParam (ce))
3521 if (context_inMacro ())
3523 sRef cref = uentry_getSref (ce);
3525 if (uentry_isYield (ce))
3527 ; /* no checks (for now) */
3529 else if (sRef_isSafe (cref))
3535 if (uentry_hasRealName (ce))
3538 optgenerror (FLG_MACROPARAMS,
3539 message ("Macro parameter %q not used",
3540 uentry_getName (ce)),
3547 if (cstring_equalFree (uentry_getName (ce),
3548 cstring_makeLiteral ("...")))
3554 hasError = optgenerror (FLG_PARAMUNUSED,
3555 message ("Parameter %q not used",
3556 uentry_getName (ce)),
3561 else if (uentry_isFunction (ce) || uentry_isIter (ce))
3563 if (fileloc_isUser (fwhere))
3565 hasError = optgenerror
3567 message ("%q %q declared but not used",
3569 (uentry_isIter (ce) ? "Iterator"
3570 : (isFileStatic ? "File static function" : "Function")),
3571 uentry_getName (ce)),
3575 else if (uentry_isEndIter (ce))
3577 ; /* no error (already reported for iter */
3579 else if (uentry_isEnumConstant (ce))
3581 if (fileloc_isUser (fwhere))
3583 hasError = optgenerror
3585 message ("Enum member %q not used",
3586 uentry_getName (ce)),
3590 else if (uentry_isConstant (ce))
3592 if (fileloc_isUser (fwhere))
3594 hasError = optgenerror
3596 message ("Constant %q declared but not used",
3597 uentry_getName (ce)),
3601 else if (uentry_isDatatype (ce))
3603 if (fileloc_isUser (fwhere))
3605 hasError = optgenerror
3607 message ("Type %q declared but not used",
3608 uentry_getName (ce)),
3612 else if (!uentry_isRefParam (ce) && !uentry_isExpandedMacro (ce))
3613 { /* errors for ref params will be reported in the next scope */
3614 llassertprint (uentry_isVar (ce),
3615 ("ce: %s", uentry_unparseFull (ce)));
3617 if (ctype_isFunction (uentry_getType (ce)))
3619 if (fileloc_isUser (fwhere))
3621 hasError = optgenerror
3623 message ("%q %q declared but not used",
3625 (isFileStatic ? "File static function"
3627 uentry_getName (ce)),
3633 if (fileloc_isUser (fwhere))
3637 hasError = optgenerror
3639 message ("%q %q declared but not used",
3641 (isFileStatic ? "File static variable"
3643 uentry_getName (ce)),
3653 else if ((uentry_isDatatype (ce) || uentry_isAnyTag (ce)))
3654 { /* check all fields */
3655 ctype ct = uentry_getRealType (ce);
3658 while (ctype_isAP (ct))
3660 ct = ctype_getBaseType (ct);
3663 if (ctype_isSU (ct))
3665 uentryList fields = ctype_getFields (ct);
3667 uentryList_elements (fields, field)
3669 if (!uentry_isUsed (field))
3671 if (uentry_hasName (ce))
3673 hasError |= optgenerror
3675 message ("Field %q of %s %q declared but not used",
3676 uentry_getName (field),
3677 cstring_makeLiteralTemp
3678 (ctype_isStruct (ct) ? "structure" : "union"),
3679 uentry_getName (ce)),
3680 uentry_whereEarliest (field));
3686 ** Can't report these errors for unnamed structs.
3687 ** No way to tell when there are multiple consistent
3688 ** unnamed structure types. (Could go through table
3689 ** and mark them all unused...)
3691 hasError |= optgenerror
3693 message ("Field %q of unnamed %s declared but not used",
3694 uentry_getName (field),
3695 cstring_makeLiteralTemp
3696 (ctype_isStruct (ct) ? "structure" : "union")),
3697 uentry_whereEarliest (field));
3702 uentry_setUsed (field, fileloc_undefined);
3704 } end_uentryList_elements;
3714 if (uentry_isParam (ce) && context_inMacro ())
3716 if (fileloc_isDefined (uentry_whereSpecified (ce)))
3718 uentry_showWhereSpecified (ce);
3723 uentry_showDefSpecInfo (ce, fwhere);
3726 uentry_setUsed (ce, fileloc_undefined);
3732 checkGlobalReturn (uentry glob, sRef orig)
3734 sRef sr = uentry_getSref (glob);
3736 DPRINTF (("Check global return: %s / orig: %s / sr: %s",
3737 uentry_unparseFull (glob),
3738 sRef_unparseFull (orig),
3739 sRef_unparseFull (sr)));
3741 DPRINTF (("Is killed: %s", bool_unparse (sRef_isKilledGlob (orig))));
3743 if (context_getFlag (FLG_GLOBSTATE))
3745 DPRINTF (("Is killed: %s", sRef_unparseFull (orig)));
3747 if (sRef_isKilledGlob (orig))
3749 if (sRef_isStateUndefined (sr)
3750 || sRef_isUnuseable (sr)
3751 || sRef_isStateUnknown (sr)
3752 || sRef_isDead (sr))
3758 ctype ct = ctype_realType (uentry_getType (glob));
3760 DPRINTF (("Check global destroyed: %s", uentry_unparseFull (glob)));
3762 if (ctype_isVisiblySharable (ct))
3767 ("Killed global %q (type %s) not released before return",
3768 uentry_getName (glob),
3769 ctype_unparse (ct)),
3772 sRef_showStateInfo (sr);
3777 sRef_protectDerivs ();
3778 (void) transferChecks_globalDestroyed (sr, g_currentloc);
3779 sRef_clearProtectDerivs ();
3785 if (sRef_isStateUndefined (sr))
3787 if (optgenerror (FLG_GLOBSTATE,
3789 ("Function returns with global %q undefined",
3790 uentry_getName (glob)),
3793 sRef_showStateInfo (sr);
3798 if (sRef_isDead (sr) || sRef_isKept (sr))
3802 message ("Function returns with global %q "
3803 "referencing %s storage",
3804 uentry_getName (glob),
3805 cstring_makeLiteralTemp (sRef_isDead (sr) ? "released" : "kept")),
3808 if (sRef_isKept (sr))
3810 sRef_showAliasInfo (sr);
3814 sRef_showStateInfo (sr);
3817 sRef_setDefState (sr, SS_UNKNOWN, fileloc_undefined);
3821 DPRINTF (("Here: %s / %s",
3822 uentry_unparseFull (glob),
3823 sRef_unparseFull (sr)));
3825 if (ctype_isRealPointer (uentry_getType (glob))
3826 && sRef_possiblyNull (sr)
3827 && !uentry_possiblyNull (glob))
3831 message ("Function returns with non-null global %q "
3832 "referencing null storage",
3833 uentry_getName (glob)),
3836 sRef_showNullInfo (sr);
3841 DPRINTF (("Check transfer: %s", uentry_unparseFull (glob)));
3842 transferChecks_globalReturn (glob);
3850 ** remember: check alias globals
3853 void usymtab_checkFinalScope (bool isReturn)
3856 bool mustDefine = context_getFlag (FLG_MUSTDEFINE);
3857 sRefSet checked = sRefSet_new ();
3858 usymtab stab = utab;
3862 ** need to check all scopes out to function parameters.
3867 for (i = 0; i < stab->nentries; i++)
3869 uentry ce = stab->entries[i];
3870 sRef sr = uentry_getSref (ce);
3871 sRef rb = sRef_getRootBase (sr);
3875 ** Shouldn't check if shadow checked in deeper scope:
3880 uentry oue = usymtab_lookupQuietNoAlt (utab, uentry_observeRealName (ce));
3882 if (!uentry_sameObject (ce, oue))
3884 /* what if it is one an alternate branch? */
3885 /*@innercontinue@*/ continue;
3889 DPRINTF (("Here check final scope: %s", uentry_unparseFull (ce)));
3891 if (ctype_isFunction (uentry_getType (ce)))
3893 /*@innercontinue@*/ continue;
3896 if (uentry_isAnyParam (ce)
3897 || uentry_isRefParam (ce)
3898 || sRef_isFileOrGlobalScope (rb))
3900 /* Don't do the loseref check...but should check state! */
3901 DPRINTF (("Skipping check 1"));
3903 else if (sRef_isDefinitelyNull (sr)
3904 || usymtab_isDefinitelyNull (sr))
3907 ** No state reference errors for definitely null references.
3910 DPRINTF (("Skipping check 2"));
3914 DPRINTF (("Lose ref: %s / %s", uentry_unparse (ce),
3915 sRef_unparseFull (sr)));
3917 tvalues = sRef_getValueTable (sr);
3919 valueTable_elements (tvalues, fkey, fval) {
3920 metaStateInfo minfo;
3921 cstring msg = cstring_undefined;
3924 minfo = context_lookupMetaStateInfo (fkey);
3925 llassert (metaStateInfo_isDefined (minfo));
3927 if (stateValue_isError (fval)
3928 || sRef_isStateUndefined (sr)) /* No errors for undefined state */
3930 DPRINTF (("Skipping check 3"));
3934 DPRINTF (("Check: %s / %s / %s", fkey,
3935 metaStateInfo_unparse (minfo),
3936 stateValue_unparse (fval)));
3938 minfo = context_lookupMetaStateInfo (fkey);
3940 nval = stateCombinationTable_lookupLoseReference
3941 (metaStateInfo_getTransferTable (minfo),
3942 stateValue_getValue (fval), &msg);
3944 if (cstring_isDefined (msg))
3949 ("%s loses reference %q in invalid state %q (%s)",
3950 cstring_makeLiteralTemp (isReturn ? "Return" : "Scope exit"),
3951 uentry_getName (ce),
3952 stateValue_unparseValue (fval, minfo),
3956 stateValue_show (fval, minfo);
3960 DPRINTF (("Suppressed transfer error: %s", msg));
3964 } end_valueTable_elements;
3967 DPRINTF (("Check mustfree entry: %s", uentry_unparseFull (ce)));
3969 if (!sRefSet_member (checked, sr) && !sRef_isFileOrGlobalScope (rb))
3971 if (ctype_isRealSU (uentry_getType (ce))
3972 && !uentry_isAnyParam (ce)
3973 && !uentry_isRefParam (ce)
3974 && !uentry_isStatic (ce)
3975 && !sRef_isDependent (sr)
3976 && !sRef_isOwned (sr))
3978 sRefSet als = usymtab_allAliases (sr);
3980 if (sRefSet_isEmpty (als))
3982 transferChecks_localDestroyed (sr, g_currentloc);
3986 /* aliased, no problem */ ;
3992 (!uentry_isStatic (ce)
3993 && ((sRef_isNewRef (sr))
3994 || (((sRef_isOnly (sr) || sRef_isFresh (sr)
3995 || sRef_isKeep (sr) || sRef_isOwned (sr))
3996 && !sRef_isDead (sr))
3997 && (!sRef_definitelyNull (sr))
3998 && (!usymtab_isDefinitelyNull (sr)))))
4000 bool hasError = TRUE;
4002 DPRINTF (("Checking: %s", sRef_unparseFull (sr)));
4005 ** If its a scope exit, check if there is an alias.
4006 ** If so, make it only. If not, there is an error.
4011 if (transferChecks_canLoseReference (sr, g_currentloc))
4013 DPRINTF (("Can lose!"));
4020 if (sRef_hasLastReference (sr))
4022 sRef ar = sRef_getAliasInfoRef (sr);
4025 (sRef_isFresh (ar) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4027 ("Last reference %q to %s storage %qnot %q before %q",
4029 alkind_unparse (sRef_getAliasKind (sr)),
4030 sRef_unparseOpt (ar),
4031 cstring_makeLiteral (sRef_isKeep (sr)
4032 ? "transferred" : "released"),
4033 cstring_makeLiteral (isReturn
4034 ? "return" : "scope exit")),
4037 sRef_showRefLost (sr);
4040 else if (sRef_isNewRef (sr))
4043 (sRef_isFresh (sr) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4045 ("%q %q not released before %q",
4047 (alkind_isKillRef (sRef_getOrigAliasKind (sr))
4048 ? "Kill reference parameter" : "New reference"),
4049 uentry_getName (ce),
4050 cstring_makeLiteral (isReturn
4051 ? "return" : "scope exit")),
4054 sRef_showAliasInfo (sr);
4059 if (ctype_isRealSU (sRef_getType (sr)))
4061 transferChecks_structDestroyed (sr, g_currentloc);
4066 (sRef_isFresh (sr) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4068 ("%s storage %q not %q before %q",
4069 alkind_capName (sRef_getAliasKind (sr)),
4070 uentry_getName (ce),
4071 cstring_makeLiteral (sRef_isKeep (sr)
4072 ? "transferred" : "released"),
4073 cstring_makeLiteral (isReturn
4074 ? "return" : "scope exit")),
4077 sRef_showAliasInfo (sr);
4078 DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
4090 if (mustDefine && uentry_isOut (ce))
4092 /* No error if its dead (either only or error already reported */
4093 if (!sRef_isReallyDefined (sr) && !sRef_isDead (sr))
4097 message ("Out storage %q not defined before %q",
4098 uentry_getName (ce),
4100 (isReturn ? "return" : "scope exit")),
4103 DPRINTF (("sr: %s", sRef_unparseFull (sr)));
4108 ** also check state is okay
4111 if (usymtab_lexicalLevel () > functionScope
4112 && uentry_isVariable (ce)
4113 && (sRef_isLocalVar (sr)
4114 && (sRef_isDependent (sr) || sRef_isLocalState (sr))))
4116 sRefSet ab = usymtab_aliasedBy (sr);
4118 /* should do something more efficient here */
4120 if (sRefSet_isEmpty (ab))
4122 /* and no local ref */
4123 DPRINTF (("Check lose ref: %s", uentry_unparseFull (ce)));
4124 transferChecks_loseReference (ce);
4138 checked = sRefSet_insert (checked, sr);
4141 llassert (usymtab_isDefined (stab->env));
4143 if (usymtab_isBranch (stab))
4145 stab = usymtab_dropEnv (stab);
4152 llassert (stab != usymtab_undefined);
4153 } while (isReturn && (stab->lexlevel >= paramsScope));
4155 sRefSet_free (checked);
4159 ** all globals are appropriately defined
4160 ** all parameters are appropriately defined
4161 ** special clauses are followed
4164 if (isReturn || (utab->lexlevel == paramsScope))
4166 uentry fcn = context_getHeader ();
4167 uentryList params = context_getParams ();
4168 globSet uglobs = context_getUsedGlobs ();
4169 globSet sglobs = context_getGlobs ();
4171 if (isReturn && context_maybeSet (FLG_GLOBALIAS))
4173 aliasTable_checkGlobs (utab->aliases);
4177 ** state clauses (ensures, defines, sets, allocates, releases)
4180 if (uentry_hasStateClauseList (fcn))
4182 stateClauseList clauses = uentry_getStateClauseList (fcn);
4184 stateClauseList_elements (clauses, cl)
4186 if (stateClause_isAfter (cl) && !stateClause_isGlobal (cl))
4188 if (stateClause_setsMetaState (cl))
4190 sRefSet rfs = stateClause_getRefs (cl);
4191 qual q = stateClause_getMetaQual (cl);
4192 annotationInfo ainfo = qual_getAnnotationInfo (q);
4193 metaStateInfo minfo = annotationInfo_getState (ainfo);
4194 cstring key = metaStateInfo_getName (minfo);
4195 int mvalue = annotationInfo_getValue (ainfo);
4197 DPRINTF (("Post meta state clause: %s", stateClause_unparse (cl)));
4199 sRefSet_elements (rfs, el)
4201 sRef base = sRef_getRootBase (el);
4203 if (sRef_isResult (base))
4206 ** This is checked for return transfers.
4210 else if (sRef_isParam (base) || sRef_isGlobalMarker (base))
4212 sRef sr = sRef_updateSref (base);
4213 sr = sRef_fixBase (el, sr);
4215 if (!sRef_checkMetaStateValue (sr, key, mvalue))
4220 ("Ensures clause not satisfied%q (state is %q): %q",
4221 sRef_isGlobalMarker (sr)
4223 : message (" by %q", sRef_unparse (sr)),
4224 stateValue_unparseValue (sRef_getMetaStateValue (sr, key),
4226 stateClause_unparse (cl)),
4229 sRef_showMetaStateInfo (sr, key);
4235 if (sRef_isMeaningful (el))
4240 } end_sRefSet_elements ;
4244 /* evs - 2000 07 10 - added this */
4245 sRefTest tst = stateClause_getPostTestFunction (cl);
4246 sRefSet rfs = stateClause_getRefs (cl);
4248 sRefSet_elements (rfs, el)
4250 sRef base = sRef_getRootBase (el);
4252 if (sRef_isResult (base))
4255 ** This is checked for return transfers.
4260 else if (sRef_isParam (base))
4262 sRef sr = sRef_updateSref (base);
4263 sr = sRef_fixBase (el, sr);
4265 if (tst != NULL && !tst (sr))
4268 (stateClause_postErrorCode (cl),
4269 message ("%s storage %qcorresponds to "
4270 "storage listed in %q clause",
4271 stateClause_postErrorString (cl, sr),
4272 sRef_unparseOpt (sr),
4273 stateClause_unparseKind (cl)),
4276 sRefShower ss = stateClause_getPostTestShower (cl);
4283 DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
4289 if (sRef_isMeaningful (el))
4294 } end_sRefSet_elements ;
4297 } end_stateClauseList_elements ;
4301 ** check parameters on return
4304 uentryList_elements (params, arg)
4306 if (!uentry_isElipsisMarker (arg))
4308 ctype rt = ctype_realType (uentry_getType (arg));
4310 if (ctype_isMutable (rt) || ctype_isSU (rt))
4312 uentry param = usymtab_lookupQuiet (utab, uentry_rawName (arg));
4313 DPRINTF (("Check param return: %s", uentry_unparseFull (param)));
4314 transferChecks_paramReturn (param);
4317 } end_uentryList_elements;
4319 DPRINTF (("Check global return: %s",
4320 globSet_unparse (sglobs)));
4322 globSet_allElements (sglobs, el)
4324 sRef orig = el; /*! sRef_updateSref (el); */ /*!!!*/
4325 uentry current = sRef_getUentry (el);
4327 DPRINTF (("Check global return: %s / %s", sRef_unparseFull (el),
4328 uentry_unparseFull (current)));
4330 if (uentry_isVariable (current) && !uentry_isRealFunction (current))
4332 checkGlobalReturn (current, orig);
4334 } end_globSet_allElements;
4336 globSet_allElements (uglobs, el)
4338 if (!globSet_member (sglobs, el))
4340 uentry current = sRef_getUentry (el);
4342 if (uentry_isVariable (current)
4343 && !uentry_isRealFunction (current))
4345 checkGlobalReturn (current, sRef_undefined);
4348 } end_globSet_allElements;
4353 usymtab_quietExitScope (fileloc loc)
4354 /*@globals utab, globtab, filetab; @*/
4357 usymtab t = utab->env;
4359 DPRINTF (("Quiet exit scope [%p]", utab));
4361 if (utab->reftable != NULL)
4365 for (i = 0; i < utab->nentries; i++)
4367 uentry current = utab->entries[i];
4368 uentry old = usymtab_lookupAux (t, uentry_rawName (current));
4370 uentry_mergeState (old, current, loc, FALSE, FALSE, FALSE, NOCLAUSE);
4374 llassert (t != NULL);
4376 if (t->lexlevel > paramsScope)
4378 t->guards = guardSet_levelUnion (t->guards, utab->guards, t->lexlevel);
4379 t->aliases = aliasTable_levelUnionSeq (t->aliases, utab->aliases,
4381 utab->aliases = aliasTable_undefined;
4384 t->mustBreak = utab->mustBreak;
4385 t->exitCode = utab->exitCode;
4387 DPRINTF (("Free level [%p]", utab));
4388 usymtab_freeLevel (utab);
4393 usymtab_checkAllValid ();
4398 ** Exit a scope with no checking, lose alias states.
4399 ** (When should this be used?)
4402 void usymtab_quietPlainExitScope (void)
4403 /*@globals utab, globtab, filetab@*/
4406 usymtab t = utab->env;
4408 llassert (t != NULL);
4409 llassert (NOALIAS (utab->aliases, t->aliases));
4410 usymtab_freeLevel (utab);
4414 void usymtab_exitScope (exprNode expr)
4415 /*@globals utab, filetab, globtab@*/
4416 /*@modifies utab, globtab@*/
4418 usymtab ctab = usymtab_undefined;
4419 usymtab lctab = usymtab_undefined;
4420 bool mustReturn = exprNode_mustEscape (expr);
4422 DPRINTF (("Exit scope [%p]", utab));
4424 if (utab->kind == US_CBRANCH)
4427 ** save the case branches, remove the first non-cbranch
4432 while (utab->kind == US_CBRANCH)
4436 llassert (utab != GLOBAL_ENV);
4440 if (utab->kind == US_TBRANCH || utab->kind == US_FBRANCH
4441 || utab->kind == US_CBRANCH || utab->kind == US_SWITCH)
4443 if (context_inMacro ())
4445 /* evs 2000-07-25 */
4446 /* Unparseable macro may end inside nested scope. Deal with it. */
4448 llerror (FLG_SYNTAX,
4449 message ("Problem parsing macro body of %s (unbalanced scopes). "
4450 "Attempting to recover, recommend /*@notfunction@*/ before "
4451 "macro definition.",
4452 context_inFunctionName ()));
4454 while (utab->kind == US_TBRANCH
4455 || utab->kind == US_FBRANCH
4456 || utab->kind == US_CBRANCH
4457 || utab->kind == US_SWITCH)
4460 llassert (utab != GLOBAL_ENV);
4464 llcontbug (message ("exitScope: in branch: %q", usymtab_unparseStack ()));
4466 } /*@=branchstate@*/
4470 ** check all variables in scope were used
4474 ** bogus errors if this is the normal inside a switch,
4475 ** since cases have not been merged yet. Should probably
4476 ** still check this, but I'm too lazy at the moment...
4479 llassertfatal (utab->env != GLOBAL_ENV);
4481 if (utab->env->kind != US_SWITCH)
4487 ** check aliasing: all only params are released (dead)
4488 ** definition: all out params are defined, all modified params
4489 ** are completely defined
4491 ** NOTE: note for exiting paramsScope, since checkReturn should be
4495 if (!mustReturn && (usymtab_lexicalLevel () > functionScope))
4498 ** should only call this is end of scope is reachable...
4501 usymtab_checkFinalScope (FALSE);
4504 if (usymtab_lexicalLevel () == paramsScope && context_inFunctionLike ())
4507 ** leaving a function, need to fix up globals
4510 uentryList params = context_getParams ();
4511 globSet globs = context_getUsedGlobs ();
4513 uentryList_elements (params, ue)
4515 uentry_fixupSref (ue);
4516 } end_uentryList_elements;
4518 clearFunctionTypes ();
4520 DPRINTF (("Fixing up globals: %s", globSet_unparse (globs)));
4522 globSet_allElements (globs, el)
4524 DPRINTF (("Fix: %s", sRef_unparseDebug (el)));
4526 if (sRef_isCvar (el))
4529 usymId index = sRef_getScopeIndex (el);
4531 if (sRef_isFileStatic (el))
4533 llassert (usymtab_isDefined (filetab));
4534 current = usymtab_fetchIndex (filetab, index);
4538 current = usymtab_fetchIndex (globtab, index);
4541 if (uentry_isVariable (current))
4543 DPRINTF (("Fixup: %s", uentry_unparse (current)));
4544 uentry_fixupSref (current);
4548 DPRINTF (("Clear: %s", uentry_getSref (current)));
4549 sRef_clearDerived (uentry_getSref (current));
4553 sRef_clearDerived (el); /* evans 2002-03-14 - this is the likely source of many crashes! */
4554 } end_globSet_allElements;
4557 usymtab_quietExitScope (exprNode_loc (expr));
4559 if (lctab != usymtab_undefined)
4561 /*@i@*/ lctab->env = utab;
4562 /*@i@*/ utab = ctab;
4563 /*@-branchstate@*/ } /*@=branchstate@*/
4568 usymtab_checkAllValid ();
4574 ** yikes! don't let the '170 kids see this one...
4578 usymtab_directParamNo (uentry ue)
4580 if (uentry_isVar (ue))
4582 sRef sr = uentry_getSref (ue);
4584 if (sRef_lexLevel (sr) == functionScope)
4586 usymId index = sRef_getScopeIndex (sr);
4588 if (index < usymId_fromInt (uentryList_size (context_getParams ())))
4594 return usymId_invalid;
4597 /*@dependent@*/ /*@exposed@*/ uentry
4598 usymtab_getParam (int paramno)
4602 ** requires in a function context (checked)
4604 ** depends on no nested functions --- the function
4605 ** parameters are ALWAYS one scope inside the global scope
4606 ** and entered in order!
4610 if (!context_inFunctionLike ())
4611 llfatalbug (message ("usymtab_getParam: not in function context: %q",
4612 context_unparse ()));
4614 while (s->lexlevel > paramsScope)
4619 llassert (usymtab_isDefined (s));
4621 if (paramno >= s->nentries)
4624 ** Parse errors lead to this.
4627 uentry err = uentry_makeVariableLoc (cstring_makeLiteralTemp ("<error>"),
4630 uentry_markOwned (err);
4634 return (s->entries[paramno]);
4637 static /*@dependent@*/ /*@exposed@*/ uentry
4638 usymtab_getRefTab (/*@notnull@*/ usymtab u, int level, usymId index)
4642 ue = usymtab_getRefNoisy (u, level, index);
4644 if (uentry_isUndefined (ue))
4646 llbug (message ("usymtab_getRef: out of range: %d. level = %d",
4653 static /*@dependent@*/ /*@exposed@*/ usymtab
4654 usymtab_dropEnv (/*@notnull@*/ usymtab s)
4656 if (s->kind == US_CBRANCH)
4664 llassert (s != GLOBAL_ENV);
4665 } while (s->kind == US_CBRANCH);
4666 /* drop all cases (except in nested scopes */
4669 llassert (s != GLOBAL_ENV);
4672 if (s->kind == US_FBRANCH)
4674 s = s->env; /* skip the true branch */
4675 llassert (usymtab_isDefined (s));
4676 llassert (s->kind == US_TBRANCH);
4679 llassert (s != GLOBAL_ENV);
4685 /*@dependent@*/ /*@exposed@*/ uentry
4686 usymtab_getRefQuiet (int level, usymId index)
4692 llassert (s != NULL);
4693 llassert (index >= 0);
4695 if (level > s->lexlevel)
4697 return uentry_undefined;
4700 llassertprint (level <= s->lexlevel, ("level: %d / lexlevel: %d",
4701 level, s->lexlevel));
4703 while (s->lexlevel > level)
4705 if (usymtab_isBranch (s))
4707 int eindex = refTable_lookup (s, level, index);
4709 if (eindex != NOT_FOUND)
4711 return (s->entries[eindex]);
4715 s = usymtab_dropEnv (s);
4718 while (usymtab_isBranch (s) && s->lexlevel == level)
4720 int eindex = refTable_lookup (s, level, index);
4722 if (eindex != NOT_FOUND)
4724 return (s->entries[eindex]);
4727 s = usymtab_dropEnv (s);
4730 if (index >= usymId_fromInt (s->nentries))
4732 return uentry_undefined;
4735 llassert (!uentry_isUndefined (s->entries[index]));
4737 return s->entries[index];
4740 static /*@dependent@*/ /*@exposed@*/ uentry
4741 usymtab_getRefNoisy (/*@notnull@*/ usymtab s, int level, usymId index)
4744 uentry ue = uentry_undefined;
4746 llassert (index >= 0);
4748 while (s->lexlevel > level)
4750 if (usymtab_isBranch (s))
4752 int eindex = refTable_lookup (s, level, index);
4754 if (eindex != NOT_FOUND)
4756 ue = s->entries[eindex];
4760 while (!usymtab_isBranch (otab))
4762 otab = usymtab_dropEnv (otab);
4763 llassert (otab != GLOBAL_ENV);
4766 if (refTable_lookup (otab, level, index) == NOT_FOUND)
4768 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4780 s = usymtab_dropEnv (s);
4783 llassert (usymtab_isDefined (s));
4785 while (usymtab_isBranch (s) && s->lexlevel == level)
4787 int eindex = refTable_lookup (s, level, index);
4789 if (eindex != NOT_FOUND)
4791 ue = s->entries[eindex];
4795 while (!usymtab_isBranch (otab))
4797 otab = usymtab_dropEnv (otab);
4798 llassert (otab != GLOBAL_ENV);
4801 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4811 s = usymtab_dropEnv (s);
4814 if (s->lexlevel == level && (index < usymId_fromInt (s->nentries)))
4816 ue = s->entries[index];
4818 if (uentry_isValid (ue))
4822 while (!usymtab_isBranch (otab))
4824 otab = usymtab_dropEnv (otab);
4826 if (otab == GLOBAL_ENV)
4832 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4843 if (index >= usymId_fromInt (s->nentries))
4845 return uentry_undefined;
4848 llassert (!uentry_isUndefined (s->entries[index]));
4850 return s->entries[index];
4854 ** looking up entries
4856 ** If entry is inside a branch, then copy it, and put it into
4857 ** the branch table.
4861 int refTable_lookup (/*@notnull@*/ usymtab ut, int level, usymId index)
4863 refTable rt = ut->reftable;
4866 llassert (rt != NULL);
4868 for (i = 0; i < ut->nentries; i++)
4870 if (rt[i]->level == level && rt[i]->index == usymId_toInt (index))
4880 /*@only@*/ refentry refentry_create (int level, int index)
4882 refentry r = (refentry) dmalloc (sizeof (*r));
4890 static /*@dependent@*/ /*@exposed@*/ uentry
4891 usymtab_addRefEntry (/*@notnull@*/ usymtab s, cstring k)
4895 if (ut->reftable == NULL)
4897 DPRINTF (("Adding ref entry without reftable: %s", k));
4898 return uentry_undefined;
4901 llassert (ut->reftable != NULL);
4903 while (s != GLOBAL_ENV)
4905 usymId eindex = usymtab_getIndex (s, k);
4907 if (usymtab_indexFound (eindex))
4909 uentry current = s->entries[eindex];
4911 if (uentry_isVar (current) && !ctype_isFunction (uentry_getType (current)))
4915 DPRINTF (("Here: copying %s", uentry_unparse (current)));
4916 if (uentry_isNonLocal (current))
4918 ue = uentry_copy (current);
4922 ue = uentry_copyNoSave (current);
4925 DPRINTF (("Here: copying %s", uentry_unparse (ue)));
4926 usymtab_addEntryQuiet (ut, ue);
4927 DPRINTF (("Okay..."));
4929 if (s->reftable != NULL)
4931 refentry ref = s->reftable[eindex];
4933 ut->reftable[ut->nentries - 1]
4934 = refentry_create (ref->level, ref->index);
4938 ut->reftable[ut->nentries - 1]
4939 = refentry_create (s->lexlevel, usymId_toInt (eindex));
4950 s = usymtab_dropEnv (s);
4953 return uentry_undefined;
4956 static uentry usymtab_lookupAux (usymtab s, cstring k)
4958 DPRINTF (("Lookup: %s", k));
4960 while (s != GLOBAL_ENV)
4962 usymId eindex = usymtab_getIndex (s, k);
4964 if (usymtab_indexFound (eindex))
4966 uentry ret = s->entries[eindex];
4970 if (s->kind == US_TBRANCH
4971 || s->kind == US_FBRANCH
4972 || s->kind == US_CBRANCH)
4973 /* uentry_isGlobalVariable (ret) && os->lexlevel > fileScope) */
4976 DPRINTF (("Adding global ref entry: %s", k));
4977 ret = usymtab_addRefEntry (os, k);
4978 DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
4983 DPRINTF (("Found: %s", uentry_unparseFull (ret)));
4987 if (s->kind == US_TBRANCH || s->kind == US_FBRANCH
4988 || s->kind == US_CBRANCH)
4990 /* why isn't this os??? */
4991 uentry ret = usymtab_addRefEntry (s, k);
4992 DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
4999 return uentry_undefined;
5002 static /*@dependent@*/ /*@exposed@*/ uentry
5003 usymtab_lookupQuietAux (usymtab s, cstring k, bool noalt)
5005 while (s != GLOBAL_ENV)
5007 usymId eindex = usymtab_getIndex (s, k);
5009 if (usymtab_indexFound (eindex))
5011 uentry ret = s->entries[eindex];
5015 if (noalt && usymtab_isBranch (s))
5017 s = usymtab_dropEnv (s);
5021 llassert (s != NULL);
5026 return uentry_undefined;
5029 static /*@exposed@*/ /*@dependent@*/ uentry
5030 usymtab_lookupQuiet (usymtab s, cstring k)
5032 return usymtab_lookupQuietAux (s, k, FALSE);
5035 static /*@exposed@*/ /*@dependent@*/ uentry
5036 usymtab_lookupQuietNoAlt (usymtab s, cstring k)
5038 return usymtab_lookupQuietAux (s, k, TRUE);
5041 /*@dependent@*/ /*@observer@*/ uentry
5042 usymtab_lookupSafe (cstring k)
5045 DPRINTF (("Lookup safe: %s", k));
5046 return (usymtab_lookupAux (utab, k));
5049 /*@dependent@*/ /*@observer@*/ uentry
5050 usymtab_lookupSafeScope (cstring k, int lexlevel)
5054 ** This is necessary to deal with shadowed variables that are referenced
5055 ** through aliases inside the shadowed scope. It would be better if
5056 ** lookup could take an sRef as a parameter.
5061 while (tab != GLOBAL_ENV && tab->lexlevel > lexlevel) {
5062 uentry ret = usymtab_lookupAux (tab, k);
5064 if (uentry_isValid (ret)) {
5065 sRef sr = uentry_getSref (ret);
5067 if (sRef_isCvar (sr) && sRef_lexLevel (sr) > lexlevel) {
5068 tab = usymtab_dropEnv (tab);
5075 return uentry_undefined;
5079 usymtab_lookupExpose (cstring k)
5082 uentry ce = usymtab_lookupAux (utab, k);
5084 if (uentry_isUndefined (ce))
5086 llfatalbug (message ("usymtab_lookup: not found: *%s*", k));
5089 if (uentry_isPriv (ce))
5091 llfatalbug (message ("usymtab_lookup: private: *%s*", k));
5097 uentry usymtab_lookupExposeGlob (cstring k)
5099 return (usymtab_lookupGlobSafe (k));
5102 uentry usymtab_lookupGlob (cstring k)
5103 /*@globals globtab@*/
5105 uentry ce = usymtab_lookupAux (globtab, k);
5107 if (uentry_isUndefined (ce))
5108 llfatalbug (message ("usymtab_lookup: not found: %s", k));
5110 if (uentry_isPriv (ce))
5111 llfatalbug (message ("usymtab_lookup: private: %s", k));
5113 DPRINTF (("Lookup global: %s", uentry_unparseFull (ce)));
5117 /*@observer@*/ uentry
5118 usymtab_lookupGlobSafe (cstring k)
5119 /*@globals globtab@*/
5121 uentry ce = usymtab_lookupAux (globtab, k);
5122 DPRINTF (("Lookup global: %s", uentry_unparseFull (ce)));
5126 uentry usymtab_lookupEither (cstring k)
5129 uentry ce = usymtab_lookupSafe (k);
5131 if (uentry_isUndefined (ce))
5132 llfatalerror (message ("usymtab_lookup: not found: %s", k));
5134 DPRINTF (("Lookup either: %s", uentry_unparseFull (ce)));
5139 usymtab_lookupType (cstring k)
5140 /*@globals globtab@*/
5142 typeId uid = usymtab_getTypeId (k);
5144 if (typeId_isInvalid (uid))
5146 llcontbug (message ("usymtab_lookupType: not found: %s", k));
5147 return ctype_unknown;
5150 return (uentry_getRealType (usymtab_getTypeEntry (uid)));
5154 usymtab_lookupAbstractType (cstring k) /*@globals globtab@*/
5156 typeId uid = usymtab_getTypeId (k);
5158 if (typeId_isInvalid (uid))
5160 llcontbug (message ("usymtab_lookupType: not found: %s", k));
5161 return ctype_unknown;
5164 return (uentry_getAbstractType (usymtab_getTypeEntry (uid)));
5168 ** if there is an unnamed lcl-specified struct tag matching
5169 ** the uentryList, return its datatype. Otherwise, returns
5174 usymtab_structFieldsType (uentryList f)
5175 /*@globals globtab@*/
5177 return (usymtab_suFieldsType (f, TRUE));
5181 usymtab_unionFieldsType (uentryList f)
5182 /*@globals globtab@*/
5184 return (usymtab_suFieldsType (f, FALSE));
5188 usymtab_suFieldsType (uentryList f, bool isStruct)
5189 /*@globals globtab@*/
5193 DPRINTF (("Fields: %s", uentryList_unparse (f)));
5195 if (fileloc_isSpec (g_currentloc))
5197 return (ctype_undefined);
5200 for (i = 0; i < globtab->nentries; i++)
5202 uentry current = globtab->entries[i];
5205 ? uentry_isStructTag (current) : uentry_isUnionTag (current)))
5207 if (isFakeTag (uentry_rawName (current)))
5209 ctype ct = uentry_getType (current);
5211 DPRINTF (("Check: %s", ctype_unparse (ct)));
5213 if ((isStruct ? ctype_isStruct (ct) : ctype_isUnion (ct))
5215 (uentry_isSpecified (current)
5216 && uentryList_equivFields (f, ctype_getFields (ct))))
5218 return uentry_getAbstractType (current);
5228 return ctype_undefined;
5232 usymtab_enumEnumNameListType (enumNameList f)
5233 /*@globals globtab@*/
5237 for (i = 0; i < globtab->nentries; i++)
5239 uentry current = globtab->entries[i];
5241 if (uentry_isEnumTag (current))
5243 if (isFakeTag (uentry_rawName (current)))
5245 ctype ct = uentry_getType (current);
5247 if (ctype_isEnum (ct) && (enumNameList_match (f, ctype_elist (ct))))
5249 return uentry_getType (current);
5255 return ctype_undefined;
5259 usymtab_exists (cstring k)
5262 uentry ce = usymtab_lookupSafe (k);
5263 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5267 usymtab_existsReal (cstring k)
5270 uentry ce = usymtab_lookupSafe (k);
5272 return (!(uentry_isUndefined (ce))
5273 && !(uentry_isPriv (ce))
5274 && !(uentry_isExpandedMacro (ce)));
5278 usymtab_existsGlob (cstring k)
5279 /*@globals globtab@*/
5281 uentry ce = usymtab_lookupAux (globtab, k);
5283 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5287 usymtab_existsEither (cstring k)
5290 uentry ce = usymtab_lookupAux (utab, k);
5292 return (uentry_isValid (ce));
5296 usymtab_existsGlobEither (cstring k)
5297 /*@globals globtab@*/
5299 uentry ce = usymtab_lookupAux (globtab, k);
5301 return (uentry_isValid (ce));
5305 usymtab_existsType (cstring k)
5306 /*@globals globtab@*/
5308 uentry ce = usymtab_lookupAux (globtab, k);
5310 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && uentry_isDatatype (ce));
5314 usymtab_existsTypeEither (cstring k)
5315 /*@globals globtab@*/
5318 ce = usymtab_lookupAux (globtab, k);
5319 return (uentry_isValid (ce) && uentry_isDatatype (ce));
5323 usymtab_existsStructTag (cstring k) /*@globals globtab@*/
5325 cstring sname = makeStruct (k);
5326 uentry ce = usymtab_lookupAux (globtab, sname);
5327 cstring_free (sname);
5328 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5332 usymtab_existsUnionTag (cstring k) /*@globals globtab@*/
5334 cstring uname = makeUnion (k);
5335 uentry ce = usymtab_lookupAux (globtab, uname);
5337 cstring_free (uname);
5339 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5343 usymtab_existsEnumTag (cstring k) /*@globals globtab@*/
5345 cstring ename = makeEnum (k);
5346 uentry ce = usymtab_lookupAux (globtab, ename);
5348 cstring_free (ename);
5349 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5352 bool usymtab_existsVar (cstring k)
5355 uentry ce = usymtab_lookupSafe (k);
5357 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && (uentry_isVar (ce)));
5365 refTable_free (/*@only@*/ /*@null@*/ refTable x, int nentries)
5371 for (i = 0; i < nentries; i++)
5381 usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab u)
5382 /*@globals globtab, utab, filetab@*/
5386 DPRINTF (("Free level [%p]", u));
5387 aliasTable_free (u->aliases);
5389 refTable_free (u->reftable, u->nentries);
5391 if (u == filetab || u == globtab)
5393 for (i = 0; i < u->nentries; i++)
5395 DPRINTF (("Free complete: %d", i));
5396 DPRINTF (("Uentry: %s", uentry_unparse (u->entries[i])));
5397 uentry_freeComplete (u->entries[i]);
5398 u->entries[i] = uentry_undefined;
5403 for (i = 0; i < u->nentries; i++)
5405 uentry_free (u->entries[i]);
5406 u->entries[i] = uentry_undefined;
5410 guardSet_free (u->guards);
5417 llassert (!cstringTable_isDefined (u->htable));
5420 sfree (u); /* evans 2002-07-12: was inside if */
5424 usymtab_freeAux (/*@only@*/ usymtab u)
5425 /*@globals globtab, utab, filetab@*/
5428 while (u != GLOBAL_ENV)
5431 usymtab_freeLevel (u);
5438 void usymtab_free ()
5439 /*@globals killed utab, globtab, filetab@*/
5443 usymtab_freeAux (utab);
5444 utab = usymtab_undefined;
5446 } /*@=globstate@*/ /* Splint cannot tell that utab is killed */
5448 static int usymtab_lexicalLevel (void) /*@globals utab@*/
5450 return (utab->lexlevel);
5453 bool usymtab_inGlobalScope () /*@globals utab, globtab@*/
5455 return (utab == globtab);
5458 bool usymtab_inFileScope () /*@globals utab@*/
5460 return (utab->lexlevel == fileScope);
5463 bool usymtab_inFunctionScope () /*@globals utab@*/
5465 return (utab->lexlevel == functionScope);
5469 usymtab_replaceEntry (uentry s)
5470 /*@globals utab, globtab@*/
5471 /*@modifies utab, s@*/
5473 usymtab_replaceEntryAux (utab, s);
5477 usymtab_matchForwardStruct (typeId u1, typeId u2)
5478 /*@globals globtab@*/
5480 uentry ue1 = usymtab_getTypeEntry (u1);
5481 uentry ue2 = usymtab_getTypeEntry (u2);
5483 if (uentry_isAnyTag (ue2))
5485 ctype reptype = uentry_getType (ue1);
5487 if (ctype_isPointer (reptype))
5489 ctype repbase = ctype_getBaseType (reptype);
5491 if (ctype_isUA (repbase))
5493 typeId rtuid = ctype_typeId (repbase);
5495 if (u2 == rtuid) return TRUE;
5497 if (typeId_isValid (rtuid))
5499 reptype = uentry_getType (usymtab_getTypeEntry (rtuid));
5500 return (ctype_isUA (reptype) && (u2 == (ctype_typeId (reptype))));
5509 void usymtab_addGuards (guardSet guards)
5512 utab->guards = guardSet_union (utab->guards, guards);
5515 static bool usymtab_isGuardedAux (sRef s)
5519 sRef base = sRef_getRootBase (s);
5520 int lowlevel = paramsScope;
5521 int baselevel = sRef_lexLevel (base);
5523 if (sRef_isCvar (base))
5525 lowlevel = baselevel;
5526 if (lowlevel < paramsScope) lowlevel = paramsScope;
5529 while (tab->lexlevel >= lowlevel)
5531 DPRINTF (("Is guarded? [%s] %s",
5532 guardSet_unparse (tab->guards),
5533 sRef_unparseFull (s)));
5535 if (guardSet_isGuarded (tab->guards, s))
5538 if (!sRef_definitelyNull (s))
5540 sRef_setNotNull (s, fileloc_undefined);
5546 tab = usymtab_dropEnv (tab);
5552 void usymtab_unguard (sRef s) /*@modifies utab@*/
5555 sRef base = sRef_getRootBase (s);
5556 int lowlevel = paramsScope;
5557 int baselevel = sRef_lexLevel (base);
5559 if (sRef_isCvar (base))
5561 lowlevel = baselevel;
5562 if (lowlevel < paramsScope) lowlevel = paramsScope;
5565 while (tab->lexlevel >= lowlevel)
5567 if (guardSet_isGuarded (tab->guards, s))
5569 guardSet_delete (tab->guards, s);
5572 tab = usymtab_dropEnv (tab);
5576 bool usymtab_isGuarded (sRef s)
5578 DPRINTF (("Is guarded? %s", sRef_unparseFull (s)));
5579 return (sRef_aliasCompleteSimplePred (usymtab_isGuardedAux, s));
5582 bool usymtab_isDefinitelyNull (sRef s)
5584 return (sRef_aliasCheckSimplePred (usymtab_isDefinitelyNullAux, s));
5587 bool usymtab_isDefinitelyNullDeep (sRef s)
5589 return (sRef_deepPred (usymtab_isDefinitelyNull, s));
5592 static bool usymtab_isDefinitelyNullAux (sRef s)
5596 sRef base = sRef_getRootBase (s);
5597 int lowlevel = paramsScope;
5599 if (sRef_isCvar (base))
5601 lowlevel = sRef_lexLevel (base);
5602 if (lowlevel < paramsScope) lowlevel = paramsScope;
5605 while (tab->lexlevel >= lowlevel)
5607 if (guardSet_mustBeNull (tab->guards, s))
5612 while (tab->kind == US_CBRANCH)
5617 llassert (usymtab_isDefined (tab));
5619 if (tab->kind == US_FBRANCH)
5622 llassert (tab->kind == US_TBRANCH);
5632 usymtab_printGuards ()
5633 /*@globals utab, globtab@*/
5635 usymtab ttab = utab;
5637 while (ttab != globtab)
5639 llmsg (message ("Guards [%d]: %q", ttab->lexlevel,
5640 guardSet_unparse (ttab->guards)));
5646 usymtab_displayAllUses ()
5647 /*@globals utab, globtab@*/
5651 /* only in top scope */
5652 llassert (utab == globtab);
5654 /* need a copy, so order is not messed up by sort! */
5655 copy = usymtab_shallowCopy (globtab);
5657 qsort (copy->entries, (size_t)copy->nentries,
5658 sizeof (*copy->entries), (int (*)(const void *, const void *)) uentry_xcompareuses);
5660 usymtab_entries (copy, ue)
5662 if (uentry_isValid (ue) && !uentry_isGlobalMarker (ue))
5664 filelocList uses = uentry_getUses (ue);
5665 int size = filelocList_realSize (uses);
5667 if (fileloc_isDefined (uentry_whereDefined (ue))
5668 && !fileloc_isLib (uentry_whereDefined (ue))
5671 llmsg (message ("%q (%q), %d use%&:\n %q",
5672 uentry_getName (ue),
5673 fileloc_unparse (uentry_whereDefined (ue)),
5674 size, filelocList_unparseUses (uses)));
5677 } end_usymtab_entries;
5679 usymtab_shallowFree (copy);
5682 static /*@dependent@*/ /*@exposed@*/ usymtab
5683 usymtab_getFileTab ()
5684 /*@globals filetab@*/
5686 llassert (filetab != NULL);
5692 usymtab_unparseStack ()
5695 return (usymtab_unparseStackTab (utab));
5698 static /*@only@*/ cstring
5699 usymtab_unparseStackTab (usymtab t)
5701 bool firstOne = TRUE;
5702 cstring ret = cstring_makeLiteral ("[");
5704 while (t != GLOBAL_ENV)
5708 ret = message ("%q %q", ret, usymtab_typeName (t));
5713 ret = message ("%q, %q", ret, usymtab_typeName (t));
5718 ret = message ("%q ]", ret);
5722 static /*@only@*/ cstring
5723 usymtab_typeName (/*@notnull@*/ usymtab t)
5727 case US_GLOBAL: return cstring_makeLiteral ("global");
5728 case US_NORMAL: return cstring_makeLiteral ("normal");
5729 case US_TBRANCH: return cstring_makeLiteral ("true");
5730 case US_FBRANCH: return cstring_makeLiteral ("false");
5731 case US_CBRANCH: return cstring_makeLiteral ("case");
5732 case US_SWITCH: return cstring_makeLiteral ("switch");
5738 void usymtab_addMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5741 if (!sRef_similar (s, al))
5743 usymtab_addForceMustAlias (s, al);
5748 ** Same as usymtab_addMustAlias, except does not check sRef_isSimilar.
5751 void usymtab_addForceMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5754 /* evans 2002-03-3: was sRef_isMeaningful -- but we need to keep aliases for new storage also! */
5755 if (sRef_isMeaningful (s)
5756 && sRef_isMeaningful (al)
5757 && !(sRef_isConst (s) || sRef_isConst (al))
5758 && !(sRef_isAddress (al) && sRef_isDirectParam (sRef_getBase (al))))
5760 utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
5761 DPRINTF (("Must alias: %s", aliasTable_unparse (utab->aliases)));
5764 ** for local variable, aliasing is symmetric
5767 if (sRef_isLocalVar (s) && sRef_isLocalVar (al))
5769 utab->aliases = aliasTable_addMustAlias (utab->aliases, al, s);
5774 DPRINTF (("Not aliasing! %s / %s", sRef_unparseFull (s), sRef_unparseFull (al)));
5775 DPRINTF (("meaningful: %d %d", sRef_isMeaningful (s), sRef_isMeaningful (al)));
5779 void usymtab_addReallyForceMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5782 utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
5785 void usymtab_clearAlias (sRef s)
5786 /*@modifies utab, s@*/
5789 aliasTable_clearAliases (utab->aliases, s);
5792 sRefSet usymtab_allAliases (sRef s)
5795 if (sRef_isSomewhatMeaningful (s))
5799 ret = sRefSet_unionFree (aliasTable_aliasedBy (utab->aliases, s),
5800 aliasTable_canAlias (utab->aliases, s));
5805 DPRINTF (("NOT A MEANINGFUL SREF!"));
5806 return sRefSet_undefined;
5810 /*@only@*/ sRefSet usymtab_canAlias (sRef s)
5813 if (sRef_isSomewhatMeaningful (s))
5815 sRefSet res = aliasTable_canAlias (utab->aliases, s);
5819 return sRefSet_undefined;
5822 /*@only@*/ sRefSet usymtab_aliasedBy (sRef s)
5825 return (aliasTable_aliasedBy (utab->aliases, s));
5828 /*@only@*/ cstring usymtab_unparseAliases ()
5831 return (aliasTable_unparse (utab->aliases));
5835 ** Debugging routines:
5836 ** okay to leak storage here, only for debugging
5842 usymtab_printOut (void)
5848 char *ind = mstring_copy (" ");
5850 fprintf (g_warningstream, "<<< [symbol table] >>>\n");
5852 while (s != GLOBAL_ENV && s->env != GLOBAL_ENV)
5854 cstring tname = usymtab_typeName (s);
5858 ind[depth * 3 + 1] = '\0';
5861 fprintf (g_warningstream, "level: %d (%s)\n", s->lexlevel,
5862 cstring_toCharsSafe (tname));
5864 cstring_free (tname);
5866 for (i = 0; i < s->nentries; i++)
5868 cstring us = uentry_unparseFull (s->entries[i]);
5869 fprintf (g_warningstream, "%s\n", cstring_toCharsSafe (us));
5873 if (s->reftable != NULL && s->nentries > 0)
5875 fprintf (g_warningstream, "\t<< Ref table >>\n");
5877 for (i = 0; i < s->nentries; i++)
5879 fprintf (g_warningstream, "\t%s %3d: %d, %d\n", ind, i,
5880 s->reftable[i]->level,
5881 s->reftable[i]->index);
5885 ind[depth * 3 + 1] = ' ';
5889 fprintf (g_warningstream, "<<< end usymtab >>>\n");
5895 usymtab_printTypes ()
5896 /*@globals globtab@*/
5898 usymtab_printAllAux (globtab);
5902 usymtab_printAll (void)
5905 usymtab_printAllAux (utab);
5909 usymtab_printAllAux (usymtab s)
5910 /*@modifies g_warningstream@*/
5914 char *ind = mstring_copy (" ");
5916 printf ("[[[ usymtab ]]]");
5918 while (s != GLOBAL_ENV)
5921 ind[depth * 3 + 1] = '\0';
5923 if (s->env == GLOBAL_ENV)
5927 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5928 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5929 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5933 for (i = looplow; i < s->nentries; i++)
5935 printf ("%s%3d. %s\n", ind, i,
5936 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5941 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5942 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5943 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5945 for (i = 0; i < s->nentries; i++)
5947 printf ("%s%3d %s\n", ind, i,
5948 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5952 ind[depth * 3 + 1] = ' ';
5956 printf ("----------\n");
5960 usymtab_printComplete ()
5965 char *ind = mstring_copy (" ");
5968 while (s != GLOBAL_ENV)
5972 ind[depth * 3 + 1] = '\0';
5975 if (s->env == GLOBAL_ENV)
5979 printf ("level: %d\n", s->lexlevel);
5983 for (i = looplow; i < s->nentries; i++)
5985 printf ("%s%3d %s\n", ind, i,
5986 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5991 printf ("level: %d\n", s->lexlevel);
5992 for (i = 0; i < s->nentries; i++)
5994 printf ("%s%3d %s\n", ind, i,
5995 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5999 ind[depth * 3 + 1] = ' ';
6004 printf ("----------\n");
6009 static /*@only@*/ cstring /*@unused@*/
6010 usymtab_unparseLocalAux (/*@notnull@*/ usymtab s)
6012 cstring c = message ("lexlevel: %d\n", s->lexlevel);
6015 for (i = 0; i < s->nentries; i++)
6017 c = message ("%q\n%q", c, uentry_unparseFull (s->entries[i]));
6020 c = message ("%q\n=========", c);
6024 static cstring /*@unused@*/ /*@only@*/
6025 usymtab_unparseLocalList (/*@notnull@*/ usymtab s)
6027 cstring c = message ("[%d/%s/%s] ", s->lexlevel,
6028 bool_unparse (s->mustBreak),
6029 exitkind_unparse (s->exitCode));
6032 for (i = 0; i < s->nentries; i++)
6034 sRef sr = uentry_getSref (s->entries[i]);
6038 c = message ("%q: %q [%b]", c, uentry_getName (s->entries[i]),
6039 sRef_isStateDefined (sr));
6043 c = message ("%q, %q [%b]", c, uentry_getName (s->entries[i]),
6044 sRef_isStateDefined (sr));
6054 usymtab_printLocal (void)
6060 printf ("lexlevel: %d\n", s->lexlevel);
6062 for (i = 0; i < s->nentries; i++)
6064 printf ("%s\n", cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
6067 while (s->lexlevel > 1)
6072 llassert (usymtab_isDefined (s));
6074 printf ("Params:\n");
6076 for (i = 0; i < s->nentries; i++)
6078 printf ("%d: %s\n", i,
6079 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
6084 static bool checkDistinctExternalName (uentry e)
6085 /*@globals globtab@*/
6086 /*@modifies *g_warningstream@*/
6088 size_t checklen = size_fromInt (context_getValue (FLG_EXTERNALNAMELEN));
6089 bool ignorecase = context_getFlag (FLG_EXTERNALNAMECASEINSENSITIVE);
6090 bool gotone = FALSE;
6091 bool extras = FALSE;
6092 bool hasError = FALSE;
6093 cstring name = uentry_rawName (e);
6094 usymtab st = globtab;
6102 if (uentry_isAnyTag (e))
6104 checklen++; /* the tag marker doesn't count */
6108 usymtab_entries (st, oe)
6110 if (uentry_sameObject (oe, e))
6117 if (cstring_equalCaseInsensitive (uentry_rawName (oe), name))
6126 (FLG_DISTINCTEXTERNALNAMES,
6128 ("External identifier %q is not distinguishable from %q "
6129 "because alphabetical case is ignored",
6131 uentry_getName (oe)),
6132 uentry_whereLast (e)))
6134 uentry_showWhereAny (oe);
6135 uentry_setHasNameError (oe);
6144 if (cstring_equalLenCaseInsensitive (uentry_rawName (oe),
6153 if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6156 (FLG_DISTINCTEXTERNALNAMES,
6159 ("External identifier %q is not distinguishable from %q "
6160 "in the first %d characters (%q)",
6162 uentry_getName (oe),
6163 size_toInt (checklen),
6164 cstring_clip (uentry_getName (e), checklen)),
6166 uentry_whereLast (e)))
6168 uentry_showWhereAny (oe);
6169 uentry_setHasNameError (oe);
6182 (FLG_DISTINCTEXTERNALNAMES,
6184 ("External identifier %q is not distinguishable from %q "
6185 "in the first %d characters because alphabetical case "
6188 uentry_getName (oe),
6189 size_toInt (checklen)),
6190 uentry_whereLast (e)))
6192 uentry_showWhereAny (oe);
6193 uentry_setHasNameError (oe);
6199 else if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6208 (FLG_DISTINCTEXTERNALNAMES,
6211 ("External identifier %q is not distinguishable from %q "
6212 "in the first %d characters (%q)",
6214 uentry_getName (oe),
6215 size_toInt (checklen),
6216 cstring_clip (uentry_getName (e), checklen)),
6218 uentry_whereLast (e)))
6220 uentry_showWhereAny (oe);
6221 uentry_setHasNameError (oe);
6230 } end_usymtab_entries ;
6237 (cstring_makeLiteral ("One or more additional "
6238 "indistinguishable external "
6239 "names not reported"));
6245 static bool checkDistinctInternalName (uentry e)
6247 /*@modifies *g_warningstream@*/
6249 usymtab ttab = utab;
6250 cstring name = uentry_rawName (e);
6251 size_t numchars = size_fromInt (context_getValue (FLG_INTERNALNAMELEN));
6252 bool caseinsensitive = context_getFlag (FLG_INTERNALNAMECASEINSENSITIVE);
6253 bool lookalike = context_getFlag (FLG_INTERNALNAMELOOKALIKE);
6255 if (uentry_isAnyTag (e) && (numchars != 0))
6257 numchars++; /* the tag marker doesn't count */
6260 while (usymtab_isDefined (ttab))
6262 usymtab_entries (ttab, oe)
6264 if (uentry_sameObject (oe, e))
6266 /*@innercontinue@*/ continue;
6269 switch (cstring_genericEqual
6270 (name, uentry_rawName (oe),
6271 numchars, caseinsensitive, lookalike))
6273 case CGE_DISTINCT: /* okay */
6277 if (cstring_equal (name, uentry_rawName (oe)))
6279 ; /* got a shadow error */
6284 (FLG_DISTINCTINTERNALNAMES,
6287 ("Internal identifier %q is not distinguishable from %q "
6288 "in the first %d characters (%q)",
6290 uentry_getName (oe),
6291 size_toInt (numchars),
6292 cstring_clip (uentry_getName (e), numchars)),
6294 uentry_whereLast (e)))
6296 uentry_showWhereAny (oe);
6297 uentry_setHasNameError (oe);
6304 if (numchars == 0 || (cstring_length (name) <= numchars))
6307 (FLG_DISTINCTINTERNALNAMES,
6309 ("Internal identifier %q is not distinguishable from %q "
6310 "without case sensitivity",
6312 uentry_getName (oe)),
6313 uentry_whereLast (e)))
6315 uentry_showWhereAny (oe);
6316 uentry_setHasNameError (oe);
6323 (FLG_DISTINCTINTERNALNAMES,
6325 ("Internal identifier %q is not distinguishable from %q "
6326 "in the first %d characters without case sensitivity",
6328 uentry_getName (oe),
6329 size_toInt (numchars)),
6330 uentry_whereLast (e)))
6332 uentry_showWhereAny (oe);
6333 uentry_setHasNameError (oe);
6341 || (cstring_length (name) <= numchars))
6344 (FLG_DISTINCTINTERNALNAMES,
6346 ("Internal identifier %q is not distinguishable from %q "
6347 "except by lookalike characters",
6349 uentry_getName (oe)),
6350 uentry_whereLast (e)))
6352 uentry_showWhereAny (oe);
6353 uentry_setHasNameError (oe);
6360 (FLG_DISTINCTINTERNALNAMES,
6362 ("Internal identifier %q is not distinguishable from %q "
6363 "in the first %d characters except by lookalike characters",
6365 uentry_getName (oe),
6366 size_toInt (numchars)),
6367 uentry_whereLast (e)))
6369 uentry_showWhereAny (oe);
6370 uentry_setHasNameError (oe);
6375 } end_usymtab_entries ;
6383 void usymtab_checkDistinctName (uentry e, int scope)
6384 /*@globals utab, globtab@*/
6386 bool hasError = FALSE;
6387 fileloc where = uentry_whereLast (e);
6389 if (!fileloc_isPreproc (where) && !fileloc_isBuiltin (where))
6391 if (scope == globScope)
6393 if (context_getFlag (FLG_DISTINCTEXTERNALNAMES))
6395 hasError = checkDistinctExternalName (e);
6399 if (!hasError && context_getFlag (FLG_DISTINCTINTERNALNAMES))
6401 hasError = checkDistinctInternalName (e);
6407 uentry_setHasNameError (e);
6411 /*@exposed@*/ sRef usymtab_lookupGlobalMarker (void) /*@globals utab@*/
6415 ue = usymtab_lookupAux (utab, GLOBAL_MARKER_NAME);
6416 llassert (uentry_isValid (ue));
6418 return uentry_getSref (ue);
6424 ** For debugging only
6428 usymtab_checkAllValid () /*@globals utab@*/
6432 while (tab != GLOBAL_ENV)
6436 for (i = 0; i < utab->nentries; i++)
6438 uentry e = utab->entries[i];
6440 uentry_checkValid (e);
6443 aliasTable_checkValid (tab->aliases);