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 llbuglit ("Junk in load file");
2018 s = reader_readLine (f, os, MAX_DUMP_LINE_LENGTH);
2023 to handle reading of buffer overflow related constraints
2025 while (fgets (s, MAX_DUMP_LINE_LENGTH, f) != NULL
2028 ; /* ignore ;-comments */
2031 /*drl July 27 added this so that libraries without
2032 buffer constraints would be handled correctly.
2033 I'm trying to do this without breaking older libraries*/
2035 /*check for "optional" start buffer constraints message*/
2037 if (mstring_equalPrefix (s, "start_Buffer_Constraints"))
2039 (void) fgets (s, MAX_DUMP_LINE_LENGTH, f);
2042 while (s != NULL && *s != ';')
2044 constraintList preconditions;
2045 constraintList postconditions;
2046 cstring name = cstring_fromChars (reader_getWord (&s));
2049 ue = usymtab_lookup (name);
2050 cstring_free (name);
2052 preconditions = constraintList_undefined;
2053 postconditions = constraintList_undefined;
2055 if (!uentry_isValid(ue) )
2057 llfatalbug ((message("Invalid uentry for %s library file may be corrupted", cstring_fromChars(s) ) ));
2059 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2061 temp = cstring_fromChars (reader_getWord(&s) );
2063 if (cstring_compareLit (temp,"pre:") == 0 )
2065 preconditions = constraintList_undump (f);
2069 if (cstring_compareLit (temp,"pre:EMPTY") != 0 )
2070 llfatalbug ((message("Error reading library file pre:EMPTY expected but got %s", temp ) ));
2075 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2077 temp = cstring_fromChars(reader_getWord(&s) );
2078 if (cstring_compareLit (temp, "post:") == 0 )
2080 postconditions = constraintList_undump (f);
2084 if (cstring_compareLit (temp, "post:EMPTY") != 0 )
2085 llfatalbug ((message("Error reading library file post:EMPTY expected but got %s", temp ) ));
2088 cstring_free (temp);
2090 uentry_setPreconditions (ue, functionConstraint_createBufferConstraint (preconditions));
2091 uentry_setPostconditions (ue, functionConstraint_createBufferConstraint (postconditions));
2093 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2101 ** file scope for static variables
2105 usymtab_enterFile ()
2106 /*@globals utab, globtab, filetab@*/
2107 /*@modifies filetab@*/
2109 llassert (utab == globtab);
2114 usymtab_entries (globtab, ue)
2116 if (sRef_hasDerived (uentry_getSref (ue)))
2118 fprintf (g_warningstream, "Derived Global: %s\n", uentry_unparse (ue));
2119 fprintf (g_warningstream, "sRef: %s\n", sRef_unparseFull (ue->sref));
2121 } end_usymtab_entries ;
2125 usymtab_enterScope ();
2131 /*@globals utab, filetab@*/
2132 /*@modifies filetab, utab@*/
2135 llassert (utab->lexlevel == 1);
2137 usymtab_exitScope (exprNode_undefined);
2142 usymtab_enterScope ()
2143 /*@globals utab, globtab, filetab@*/
2146 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
2148 /* unconditional scope: optimize to avoid copy */
2149 t->aliases = aliasTable_copy (utab->aliases);
2152 llassert (usymtab_isDefined (t->env));
2154 if (t->env->lexlevel == paramsScope && context_inFunctionLike ())
2156 noshadowerror = TRUE;
2157 usymtab_handleParams ();
2158 noshadowerror = FALSE;
2163 ** setup external references:
2164 ** o only, unique params alias external args
2165 ** o other params may alias anything of their type
2169 usymtab_handleParams (void)
2170 /*@globals utab, globtab, filetab@*/
2171 /*@modifies utab, globtab@*/
2173 usymtab ptab = utab->env;
2174 uentry fcn = context_getHeader ();
2176 usymtab_entries (ptab, param)
2180 if (!uentry_isYield (param))
2183 sRef pref = uentry_getSref (param);
2185 /* Could be a global. */
2187 if (uentry_isAnyParam (param))
2189 ue = uentry_makeVariable (fixParamName (uentry_rawName (param)),
2190 uentry_getType (param),
2191 fileloc_copy (uentry_whereDeclared (param)),
2194 uentry_copyState (ue, param);
2195 uentry_setRefParam (ue);
2197 ue = usymtab_supEntrySrefReturn (ue);
2199 /* must be after supercede! */
2201 if (!sRef_stateKnown (pref))
2203 uentry_setDefState (ue, SS_DEFINED);
2204 uentry_setDefState (param, SS_DEFINED);
2208 if (sRef_isStateSpecial (pref))
2210 uentry_setDefState (ue, SS_SPECIAL); /* ALLOCATED); */
2211 /* evans 2002-01-01: should be unnecessary, the pre clauses
2212 ** set the state if necessary.
2217 uentry_setDefState (ue, sRef_getDefState (pref));
2221 uref = uentry_getSref (ue);
2223 if (sRef_isStack (uref))
2225 alkind pkind = sRef_getAliasKind (pref);
2227 if (alkind_isKnown (pkind) && !alkind_isLocal (pkind)
2228 && !alkind_isStack (pkind))
2230 sRef_setAliasKind (uref, pkind, fileloc_undefined);
2231 sRef_setOrigAliasKind (uref, pkind);
2235 sRef_setAliasKind (uref, AK_IMPTEMP, fileloc_undefined);
2236 sRef_setOrigAliasKind (uref, AK_IMPTEMP);
2238 if (uentry_isOut (param))
2244 sRef_setDefined (uref, fileloc_undefined);
2250 usymtab_addMustAlias (uref, pref);
2252 if (!(uentry_isOnly (param) || uentry_isUnique (param)))
2255 ** This is needed for detecting possibly aliased parameters.
2258 sRef s = sRef_makeExternal (uref);
2259 usymtab_addMustAlias (uref, s);
2262 if (sRef_isKillRef (pref))
2264 sRef_setAliasKind (uref, AK_NEWREF, fileloc_undefined);
2265 sRef_setOrigAliasKind (uref, AK_KILLREF);
2267 else if (sRef_isRefCounted (uref))
2269 sRef_setOrigAliasKind (uref, AK_REFCOUNTED);
2274 sRef_setOrigAliasKind (uref, AK_LOCAL);
2281 } end_usymtab_entries;
2284 if (uentry_hasStateClauseList (fcn))
2286 stateClauseList clauses = uentry_getStateClauseList (fcn);
2288 stateClauseList_preElements (clauses, cl)
2290 fileloc loc = stateClause_loc (cl);
2291 sRefSet osrs = sRefSet_undefined;
2294 if (stateClause_isGlobal (cl))
2296 DPRINTF (("Global Marker: %s",
2297 sRef_unparseFull (usymtab_lookupGlobalMarker ())));
2298 llassert (sRef_isGlobalMarker (usymtab_lookupGlobalMarker ()));
2299 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
2304 srs = stateClause_getRefs (cl);
2307 sRefSet_elements (srs, el)
2309 sRef base = sRef_getRootBase (el);
2310 sRef sb = sRef_updateSref (el);
2312 if (sRef_isResult (base))
2314 ; /* nothing to do before */
2316 else if (sRef_isParam (base) || sRef_isGlobalMarker (base))
2318 if (stateClause_setsMetaState (cl))
2320 /* copied from exprNode.c:3040 */
2321 qual ql = stateClause_getMetaQual (cl);
2322 annotationInfo ainfo = qual_getAnnotationInfo (ql);
2323 metaStateInfo minfo = annotationInfo_getState (ainfo);
2324 cstring key = metaStateInfo_getName (minfo);
2325 int mvalue = annotationInfo_getValue (ainfo);
2327 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
2329 if (sRef_isResult (base))
2335 sRef_setMetaStateValueComplete (sb, key, mvalue, loc);
2340 sRefMod modf = stateClause_getEntryFunction (cl);
2344 sRefSet aliases = usymtab_allAliases (sb);
2348 sRefSet_elements (aliases, sr)
2351 } end_sRefSet_elements ;
2353 sRefSet_free (aliases);
2359 if (sRef_isValid (base))
2361 DPRINTF (("Base: %s", sRef_unparseFull (base)));
2365 } end_sRefSet_elements ;
2366 } end_stateClauseList_preElements ;
2371 usymtab_enterFunctionScope (uentry fcn)
2372 /*@globals utab, filetab, globtab@*/
2375 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
2377 DPRINTF (("Enter function: %s", uentry_unparse (fcn)));
2379 if (utab->lexlevel != fileScope)
2381 if (utab->lexlevel > fileScope)
2383 llparseerror (cstring_makeLiteral ("New function scope inside function"));
2385 while (utab->lexlevel > fileScope)
2387 /*@i@*/ utab = usymtab_dropEnv (utab);
2394 llfatalbug (cstring_makeLiteral ("New function not inside file."));
2396 /*@-branchstate@*/ } /*@=branchstate@*/
2400 DPRINTF (("Globs: %s", globSet_unparse (uentry_getGlobs (fcn))));
2402 globSet_allElements (uentry_getGlobs (fcn), el)
2404 DPRINTF (("Here we go: %s", sRef_unparseFull (el)));
2406 if (sRef_isUndefGlob (el))
2408 usymId index = sRef_getScopeIndex (el);
2409 sRef sr = sRef_updateSref (el);
2410 fileloc loc = uentry_whereEarliest (fcn);
2412 DPRINTF (("update: %s", sRef_unparseFull (sr)));
2413 DPRINTF (("Undef!"));
2414 if (sRef_isFileStatic (el))
2416 ctype ct = sRef_getType (el);
2419 llassert (usymtab_isDefined (filetab));
2421 ue = usymtab_fetchIndex (filetab, index);
2423 if (ctype_isRealArray (ct) || ctype_isRealSU (ct))
2425 sRef_setAllocated (sr, loc);
2429 sRef_setUndefined (sr, loc);
2434 uentry ue = globtab->entries[index];
2435 ctype ct = uentry_getType (ue);
2437 if (ctype_isArray (ct) || ctype_isSU (ct))
2439 sRef_setAllocated (sr, loc);
2443 sRef_setUndefined (sr, loc);
2447 else if (sRef_isAllocated (el))
2449 sRef sr = sRef_updateSref (el);
2450 fileloc loc = uentry_whereEarliest (fcn);
2452 sRef_setAllocated (sr, loc);
2454 else if (sRef_isPartial (el))
2456 sRef sr = sRef_updateSref (el);
2457 fileloc loc = uentry_whereEarliest (fcn);
2459 sRef_setPartial (sr, loc);
2464 sRef sr = sRef_updateSref (el);
2465 fileloc loc = uentry_whereEarliest (fcn);
2467 sRef_setDefined (sr, loc);
2471 /* shouldn't need to do anything! */
2473 } end_globSet_allElements;
2475 DPRINTF (("Globs after: %s", globSet_unparse (uentry_getGlobs (fcn))));
2477 usymtab_checkAllValid ();
2482 usymtab_caseBranch (void)
2485 usymtab t = usymtab_create (US_CBRANCH, utab, FALSE);
2490 usymtab_switchBranch (/*@unused@*/ exprNode s)
2493 usymtab t = usymtab_create (US_SWITCH, utab, FALSE);
2495 t->aliases = aliasTable_copy (utab->aliases);
2500 usymtab_trueBranch (/*@only@*/ guardSet guards)
2503 usymtab t = usymtab_create (US_TBRANCH, utab, FALSE);
2506 ** not true! (could be in a macro)
2508 ** llassertprint (utab->lexlevel > paramsScope,
2509 ** ("not in scope: %s", usymtab_unparseLocal ()));
2513 guardSet_free (t->guards);
2516 aliasTable_free (t->aliases);
2517 t->aliases = aliasTable_copy (utab->aliases);
2525 ** { int a; if (...) a = 3; < a may be undefined here!
2530 usymtab_popTrueBranch (exprNode pred, exprNode expr, clause cl) /*@modifies utab@*/
2533 ** add a false branch
2534 ** (could be done more efficiently as a special case, but
2535 ** it is better to only maintain one version of the code)
2538 if (utab->kind != US_TBRANCH
2539 && context_inIterDef ())
2541 usymtab_exitScope (expr);
2545 DPRINTF (("pop true branch.."));
2546 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2547 usymtab_popBranches (pred, expr, exprNode_undefined, TRUE, cl);
2552 usymtab_popCaseBranch () /*@modifies utab@*/
2554 llassert (utab->kind == US_CBRANCH);
2555 usymtab_quietPlainExitScope ();
2559 usymtab_popTrueExecBranch (exprNode pred, exprNode expr, clause cl)
2562 ** add a false branch that must return --- that is,
2563 ** the true branch is always executed!
2566 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2567 usymtab_popBranches (pred, expr, exprNode_makeMustExit (), FALSE, cl);
2571 usymtab_popOrBranch (exprNode pred, exprNode expr)
2575 usymtab env = utab->env;
2576 usymtab otab = utab;
2579 llassert (env != NULL);
2581 if (exprNode_isError (expr))
2587 mustReturn = exprNode_mustEscape (expr);
2591 llassert (utab->kind == US_TBRANCH);
2594 ** merge each entry in table with its original
2595 ** unless execution cannot continue after this branch
2598 for (i = 0; i < utab->nentries; i++)
2600 uentry current = utab->entries[i];
2601 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2603 uentry_mergeState (old, current, exprNode_loc (expr),
2604 mustReturn, FALSE, TRUE, ORCLAUSE);
2610 env->guards = guardSet_levelUnionFree (env->guards,
2611 guardSet_invert (exprNode_getGuards (pred)),
2616 env->aliases = aliasTable_levelUnion (env->aliases, otab->aliases, env->lexlevel);
2619 /* env is now utab */
2620 usymtab_quietPlainExitScope ();
2624 ** case syntax in C is very unrestricted. This is unfortunate.
2626 ** A switch case is ended either by a new case or default, or
2627 ** a close } that may close the switch or some other control
2632 usymtab_newCase (/*@unused@*/ exprNode pred, exprNode last)
2635 bool mustBreak = usymtab_mustBreak (utab);
2636 bool mustReturn = usymtab_mustEscape (utab);
2637 usymtab stab = utab;
2639 DPRINTF (("New case!"));
2642 ** Find last case (or outer switch)
2645 while (stab->kind != US_CBRANCH && stab->kind != US_SWITCH)
2648 llassert (stab != GLOBAL_ENV);
2651 while (stab->kind == US_CBRANCH)
2654 llassert (stab != GLOBAL_ENV);
2658 ** if its a fall through case, merge in outside entries and last case.
2663 ** case 1: x = 3; <fall through>
2664 ** case 2: << x may not be defined
2668 if (!mustBreak && !mustReturn && utab->kind == US_CBRANCH)
2670 llassert (stab->kind == US_SWITCH || stab->kind == US_NORMAL);
2672 usymtab_entries (utab, ue) /* but, keep track of used variables */
2674 uentry old = usymtab_lookupAux (stab, uentry_rawName (ue));
2676 llassert (uentry_isValid (old));
2678 /* modifies ue, not old */
2680 uentry_mergeState (ue, old, exprNode_loc (last),
2681 FALSE, FALSE, TRUE, CASECLAUSE);
2682 } end_usymtab_entries;
2684 utab->aliases = aliasTable_levelUnion (utab->aliases,
2685 stab->aliases, utab->lexlevel);
2688 ** No need for a new branch.
2695 usymtab_caseBranch ();
2696 /*@-mustfree@*/ /*< utab->aliases >*/
2697 utab->aliases = aliasTable_copy (stab->aliases);
2705 ** for && (both pred and expr are executed)
2709 usymtab_popAndBranch (exprNode pred, /*@unused@*/ exprNode expr)
2712 usymtab env = utab->env;
2716 llassert (utab->kind == US_TBRANCH);
2719 ** merge each entry in table with its original
2720 ** unless execution cannot continue after this branch
2723 for (i = 0; i < utab->nentries; i++)
2725 uentry current = utab->entries[i];
2726 sRef tref = uentry_getSref (current);
2727 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2728 sRef oref = uentry_getSref (old);
2730 /* note that is current is in a nested branch,
2731 it may create a "new" old entry. */
2733 llassert (uentry_isValid (old));
2734 uentry_mergeState (old, current, exprNode_loc (expr),
2735 FALSE, FALSE, TRUE, ANDCLAUSE);
2738 ** if is it defined by the second clause, then it should be defined.
2741 if (sRef_isAnyDefined (tref)
2742 && (sRef_isAllocated (oref) || sRef_isStateUndefined (oref)))
2744 sRef_setDefined (oref, g_currentloc);
2748 DPRINTF (("Popping and: %s / %s",
2749 guardSet_unparse (utab->guards),
2750 guardSet_unparse (exprNode_getGuards (pred))));
2752 utab->guards = guardSet_levelUnionFree (utab->guards,
2753 guardSet_invert (exprNode_getGuards (pred)),
2755 utab->aliases = aliasTable_levelUnion (utab->aliases, otab->aliases, utab->lexlevel);
2757 usymtab_quietPlainExitScope ();
2762 ** Stack should be [ US_CBRANCH+ US_SWITCH ]
2763 ** Only branches which do not return (except possibly the last branch) are included.
2765 ** Conditionally merge state from all CBRANCHes.
2767 ** If allpaths is TRUE, then all possible executions go through some switch
2768 ** case, and the original scope is not merged.
2772 usymtab_exitSwitch (/*@unused@*/ exprNode sw, bool allpaths)
2775 usymtab ttab = utab;
2776 usymtab stab = ttab;
2777 usymtab ltab = ttab;
2778 bool lastMustReturn = usymtab_mustEscape (utab);
2782 while (stab->kind == US_CBRANCH)
2785 llassert (stab != GLOBAL_ENV);
2788 while (stab->kind == US_NORMAL)
2791 llassert (stab != GLOBAL_ENV);
2794 llassert (stab->kind == US_SWITCH);
2796 /* go to the scope outside the switch (US_SWITCH is just a marker! */
2798 llassert (stab != GLOBAL_ENV);
2802 llassert (usymtab_isDefined (ttab));
2804 if (ttab->kind == US_CBRANCH)
2806 /* was quietPlainExitScope --- but, can't free it yet! */
2808 llassert (utab != GLOBAL_ENV);
2810 while (ttab->kind == US_CBRANCH)
2813 ** (from popTrueBranch)
2816 bool mustReturn = usymtab_mustEscape (ttab);
2817 bool mustBreak = usymtab_mustBreak (ttab);
2819 usymtab_entries (ttab, current)
2821 uentry old = /*@-compmempass@*/ usymtab_lookupAux (ltab, uentry_rawName (current));
2825 ** note that is this is in a nested branch,
2826 ** it may create a "new" old entry.
2829 if (uentry_isValid (old))
2833 uentry_mergeUses (current, old);
2834 uentry_setState (old, current);
2838 uentry_mergeState (old, current, exprNode_loc (sw),
2839 mustReturn, FALSE, TRUE, SWITCHCLAUSE);
2846 } end_usymtab_entries;
2849 ** if entry is not in symbol table for this case, merge with pre-switch
2853 if (!mustReturn && !mustBreak)
2855 usymtab_entries (stab, current)
2857 if (!usymtab_indexFound (usymtab_getIndex (ttab, uentry_rawName (current))))
2859 uentry old = /*@-compmempass@*/
2860 usymtab_lookupAux (ltab, uentry_rawName (current));
2863 llassert (uentry_isValid (old));
2864 uentry_mergeState (old, current, exprNode_loc (sw),
2865 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2867 } end_usymtab_entries;
2870 ltab->env = ttab->env;
2874 ** Suprious error, becuase of environments.
2877 /*@i1@*/ utab = ltab;
2879 lastMustReturn = FALSE;
2886 ** now, there is one US_CBRANCH. Merge this with the stab.
2890 for (i = 0; i < ltab->nentries; i++)
2892 uentry current = ltab->entries[i];
2893 uentry old = usymtab_lookupAux (stab, uentry_rawName (current));
2895 /* note that is this is in a nested branch,
2896 it may create a "new" old entry. */
2899 if (uentry_isValid (old))
2903 uentry_mergeUses (current, old);
2904 uentry_setState (old, current);
2908 uentry_mergeState (old, current, exprNode_loc (sw),
2909 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2923 ** switch may or may not be followed by a new scope
2926 if (utab->kind == US_SWITCH)
2928 usymtab_quietPlainExitScope ();
2932 usymtab_quietPlainExitScope ();
2933 llassert (utab->kind == US_SWITCH);
2934 usymtab_quietPlainExitScope ();
2940 updateNullState (sRef el, /*@notnull@*/ usymtab ttab,
2941 /*@notnull@*/ usymtab ftab, bool trueGuard)
2943 sRef base = sRef_getRootBase (el);
2944 int level = sRef_lexLevel (base);
2946 if (sRef_isCvar (base))
2948 usymId index = sRef_getScopeIndex (base);
2949 uentry ue = usymtab_getRefTab (ttab, level, index);
2951 if (!uentry_isLset (ue))
2953 sRef sr = uentry_getSref (ue);
2957 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2961 if (!guardSet_isGuarded (ttab->guards, el)
2962 && !sRef_isNotNull (sr))
2964 DPRINTF (("Here! %s / %s",
2965 sRef_unparseFull (sr),
2966 sRef_unparseFull (el)));
2967 sRef_setDerivNullState (sr, el, NS_DEFNULL);
2976 ue = usymtab_getRefTab (ftab, level, index);
2978 if (!uentry_isLset (ue))
2980 sRef sr = uentry_getSref (ue);
2982 if (!trueGuard) /* yikes! forgot the ! */
2984 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2989 if (!guardSet_isGuarded (ftab->guards, el)
2990 && !sRef_isNotNull (sr))
2992 sRef_setDerivNullState (sr, el, NS_DEFNULL);
3004 usymtab_popBranches (exprNode pred, exprNode tbranch, exprNode fbranch,
3005 bool isOpt, clause cl)
3009 usymtab ftab = utab;
3010 usymtab ttab = utab->env;
3014 guardSet guards = exprNode_getGuards (pred);
3015 sRefSet tguards = guardSet_getTrueGuards (guards);
3016 sRefSet fguards = guardSet_getFalseGuards (guards);
3017 bool mustReturnT = exprNode_mustEscape (tbranch);
3018 bool mustReturnF = exprNode_mustEscape (fbranch);
3020 DPRINTF (("Pop branches: %s [mustreturn: %s/%s]", exprNode_unparse (pred),
3021 bool_unparse (mustReturnT),
3022 bool_unparse (mustReturnF)));
3024 if (exprNode_isDefined (fbranch))
3026 loc = exprNode_loc (fbranch);
3030 loc = exprNode_loc (tbranch);
3033 llassert (usymtab_isDefined (ttab));
3037 llassert (usymtab_isDefined (env));
3038 llassert (ftab->kind == US_FBRANCH);
3039 llassert (ttab->kind == US_TBRANCH);
3042 ** For each element that is true guarded (i.e., if (x != NULL))
3043 ** make x = null in false branch,
3044 ** and x = notnull in true branch.
3045 ** unless x was set locally in that branch.
3046 ** For each element that is false guarded (x == NULL)
3047 ** make x = null in true, notnull in false.
3049 ** For each element that is either guarded (pred(x))
3053 sRefSet_allElements (tguards, el)
3055 updateNullState (el, ttab, ftab, TRUE);
3056 } end_sRefSet_allElements;
3058 sRefSet_allElements (fguards, el)
3060 updateNullState (el, ttab, ftab, FALSE);
3061 } end_sRefSet_allElements;
3065 ** if an entry is in both true and false, merge the entries,
3066 ** then replace original with new state.
3068 ** if an entry is in one table, merge it with the original.
3071 DPRINTF (("ftab: %d", ftab->nentries));
3073 for (i = 0; i < ftab->nentries; i++)
3075 uentry fthis = ftab->entries[i];
3076 uentry old = usymtab_lookupAux (env, uentry_rawName (fthis));
3077 usymId tindex = usymtab_getIndex (ttab, uentry_rawName (fthis));
3079 DPRINTF (("Entry: %s / %s", uentry_unparseFull (fthis), uentry_unparseFull (old)));
3081 if (uentry_isUndefined (old))
3083 /* possible entry was added as an undefined id */
3084 DPRINTF (("Undefined! %s", uentry_rawName (fthis)));
3088 if (usymtab_indexFound (tindex))
3090 uentry tthis = ttab->entries[tindex];
3092 /* note that is this is in a nested branch,
3093 it may create a "new" old entry. */
3099 uentry_mergeState (fthis, tthis, loc,
3100 mustReturnT, FALSE, FALSE, cl);
3104 uentry_mergeUses (fthis, tthis);
3107 uentry_setState (old, fthis);
3114 uentry_setState (old, tthis);
3115 uentry_mergeState (old, fthis, loc, mustReturnF,
3119 ttab->entries[tindex] = uentry_undefined;
3120 uentry_free (tthis);
3124 uentry_mergeState (old, fthis, loc, mustReturnF, TRUE, FALSE, cl);
3128 for (i = 0; i < ttab->nentries; i++)
3130 uentry current = ttab->entries[i];
3132 DPRINTF (("ttab: %s", uentry_unparseFull (current)));
3134 if (!uentry_isUndefined (current))
3136 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
3138 DPRINTF (("Old: %s", uentry_unparseFull (old)));
3140 if (uentry_isUndefined (old))
3142 llcontbug (message ("Undefined entry: %s", uentry_rawName (current)));
3148 uentry_mergeUses (current, old);
3149 uentry_setState (old, current);
3154 ** Assumes false branch is a fall-through if
3155 ** fbranch is not defined. This is true, unless
3156 ** where was some greivous error in processing
3157 ** the else branch of an if-then, in which case
3158 ** this is probably the right thing to do anyway.
3161 uentry_mergeState (old, current, loc, mustReturnT,
3165 DPRINTF (("==> %s", uentry_unparseFull (old)));
3170 ** Plain levelUnion doesn't work, since we need to use the sRef's in env->aliases
3171 ** if they are present.
3174 llassert (NOALIAS (env->aliases, ttab->aliases));
3175 llassert (NOALIAS (env->aliases, ftab->aliases));
3177 aliasTable_free (env->aliases);
3179 env->aliases = aliasTable_levelUnionNew (ttab->aliases,
3180 ftab->aliases, env->lexlevel);
3182 aliasTable_fixSrefs (env->aliases);
3184 DPRINTF (("Aliases: %s", aliasTable_unparse (env->aliases)));
3186 /* exit true and false scopes */
3187 usymtab_quietPlainExitScope ();
3188 usymtab_quietPlainExitScope ();
3192 utab->guards = guardSet_levelUnionFree
3194 guardSet_invert (exprNode_getGuards (pred)),
3200 utab->guards = guardSet_levelUnion (utab->guards,
3201 exprNode_getGuards (pred),
3205 DPRINTF (("Here."));
3208 static void usymtab_fixCases (void) /*@modifies utab@*/ {
3209 while (utab->kind == US_CBRANCH)
3211 usymtab_quietPlainExitScope ();
3214 llassert (utab->kind != US_CBRANCH);
3218 usymtab_altBranch (/*@only@*/ guardSet guards)
3222 usymtab parent = utab->env;
3224 t = usymtab_create (US_FBRANCH, utab, FALSE);
3227 ** If we are in a case, need to close it. The C syntax
3228 ** is very liberal, so this kludge is necessary.
3231 usymtab_fixCases ();
3233 DPRINTF (("Current kind: %s", usymtab_unparseStack ()));
3235 llassert (utab->kind == US_TBRANCH);
3236 llassert (parent != GLOBAL_ENV);
3238 guardSet_free (t->guards);
3241 aliasTable_free (t->aliases);
3242 t->aliases = aliasTable_copy (parent->aliases);
3248 usymtab_allDefined (void)
3249 /*@globals utab, globtab@*/
3253 llassert (utab == globtab);
3255 for (i = 0; i < utab->nentries; i++)
3257 uentry e = utab->entries[i];
3259 if (uentry_isPriv (e))
3261 ; /* no need to define it */
3265 if (context_getFlag (FLG_SPECUNDECL))
3267 fileloc sloc = uentry_whereSpecified (e);
3268 fileloc dloc = uentry_whereDeclared (e);
3270 if (fileloc_isDefined (sloc)
3271 && !uentry_isFakeTag (e)
3272 && !fileloc_isDefined (dloc))
3276 message ("%s %q specified but not declared",
3277 ekind_capName (uentry_getKind (e)),
3278 uentry_getName (e)),
3283 if (!uentry_isCodeDefined (e))
3285 fileloc dloc = uentry_whereDeclared (e);
3287 if (fileloc_isLib (dloc) || fileloc_isXHFile (dloc))
3291 else if (fileloc_isDefined (dloc))
3293 if (!uentry_isAnyTag (e))
3295 if (fileloc_isUser (dloc))
3299 message ("%s %q declared but not defined",
3300 ekind_capName (uentry_getKind (e)),
3301 uentry_getName (e)),
3303 DPRINTF (("decl: %s", uentry_unparseFull (e)));
3309 fileloc sloc = uentry_whereSpecified (e);
3311 if (fileloc_isDefined (sloc)
3312 && !fileloc_isImport (sloc)
3313 && !fileloc_isLib (sloc)
3314 && !fileloc_isPreproc (sloc)
3315 && !uentry_isFakeTag (e))
3317 if (uentry_isVariable (e) || uentry_isFunction (e))
3321 message ("%s %q specified but not declared or defined",
3322 ekind_capName (uentry_getKind (e)),
3323 uentry_getName (e)),
3330 message ("%s %q specified but not defined",
3331 ekind_capName (uentry_getKind (e)),
3332 uentry_getName (e)),
3342 void usymtab_exportHeader (void)
3347 for (i = 0; i < utab->nentries; i++)
3349 uentry ce = utab->entries[i];
3351 if (!uentry_isDatatype (ce)
3352 && !uentry_isAnyTag (ce)
3353 && !uentry_isEitherConstant (ce) && !uentry_isStatic (ce)
3354 && !uentry_isExternal (ce)
3355 && !uentry_isForward (ce))
3357 fileloc fwhere = uentry_whereDeclared (ce);
3359 if (fileloc_isUndefined (fwhere)
3360 && uentry_isFunction (ce))
3362 fwhere = uentry_whereDefined (ce);
3365 if (fileloc_isDefined (fwhere)
3366 && !fileloc_isHeader (fwhere)
3367 && !fileloc_isXHFile (fwhere)
3368 && !(fileloc_isSpecialFile (fwhere)
3369 && !context_getFlag (FLG_UNUSEDSPECIAL)))
3371 if (uentry_isVariable (ce))
3374 (FLG_EXPORTHEADERVAR,
3375 message ("%s %q exported but not declared in header file",
3376 ekind_capName (uentry_getKind (ce)),
3377 uentry_getName (ce)),
3380 uentry_showDefSpecInfo (ce, fwhere);
3385 if (!uentry_isIter (ce)
3386 && !uentry_isEndIter (ce)
3387 && !uentry_isExpandedMacro (ce))
3389 if (uentry_isFunction (ce)
3390 && cstring_equalLit (uentry_rawName (ce), "main"))
3392 ; /* no error for main */
3398 message ("%s %q exported but not declared "
3400 ekind_capName (uentry_getKind (ce)),
3401 uentry_getName (ce)),
3404 uentry_showDefSpecInfo (ce, fwhere);
3414 void usymtab_exportLocal (void)
3419 for (i = 0; i < utab->nentries; i++)
3421 uentry ce = utab->entries[i];
3423 if (!uentry_isDatatype (ce) && !uentry_isAnyTag (ce)
3424 && !uentry_isEitherConstant (ce)
3425 && !uentry_isIter (ce)
3426 && !uentry_isEndIter (ce)
3427 && !uentry_isExpandedMacro (ce)
3428 && uentry_isUsed (ce))
3430 /* check static uses */
3431 filelocList fuses = uentry_getUses (ce);
3432 fileloc mod = uentry_whereDefined (ce);
3433 bool ok = filelocList_isEmpty (fuses);
3434 fileloc fwhere = uentry_whereDeclared (ce);
3436 if (fileloc_isSpecialFile (fwhere)
3437 && !context_getFlag (FLG_UNUSEDSPECIAL))
3439 ok = TRUE; /* no errors for special files */
3443 filelocList_elements (fuses, uloc)
3445 if (fileloc_isUndefined (uloc) || !fileloc_sameModule (uloc, mod))
3448 /*@innerbreak@*/ break;
3450 } end_filelocList_elements;
3457 message ("%s exported but not used outside %s: %q",
3458 ekind_capName (uentry_getKind (ce)),
3459 fileloc_getBase (mod),
3460 uentry_getName (ce)),
3463 uentry_showDefSpecInfo (ce, fwhere);
3471 usymtab_allUsed (void)
3475 bool isFileStatic = usymtab_inFileScope ();
3476 cstring last_file = cstring_undefined;
3478 for (i = 0; i < utab->nentries; i++)
3480 bool hasError = FALSE;
3481 uentry ce = utab->entries[i];
3482 fileloc fwhere = uentry_whereDeclared (ce);
3484 if (fileloc_isUndefined (fwhere))
3486 fwhere = uentry_whereDefined (ce);
3489 if (fileloc_isInvalid (fwhere)
3490 || fileloc_isLib (fwhere)
3491 || fileloc_isBuiltin (fwhere)
3492 || ((fileloc_isSpecialFile (fwhere)
3493 || fileloc_isSpecialFile (uentry_whereDefined (ce)))
3494 && !context_getFlag (FLG_UNUSEDSPECIAL)))
3498 else if (!uentry_wasUsed (ce) && !uentry_isAnyTag (ce))
3500 cstring fname = fileloc_filename (fwhere);
3502 if (cstring_isUndefined (last_file))
3506 else if (cstring_equal (fname, last_file))
3515 if (uentry_isParam (ce))
3517 if (context_inMacro ())
3519 sRef cref = uentry_getSref (ce);
3521 if (uentry_isYield (ce))
3523 ; /* no checks (for now) */
3525 else if (sRef_isSafe (cref))
3531 if (uentry_hasRealName (ce))
3534 optgenerror (FLG_MACROPARAMS,
3535 message ("Macro parameter %q not used",
3536 uentry_getName (ce)),
3543 if (cstring_equalFree (uentry_getName (ce),
3544 cstring_makeLiteral ("...")))
3550 hasError = optgenerror (FLG_PARAMUNUSED,
3551 message ("Parameter %q not used",
3552 uentry_getName (ce)),
3557 else if (uentry_isFunction (ce) || uentry_isIter (ce))
3559 if (fileloc_isUser (fwhere))
3561 hasError = optgenerror
3563 message ("%q %q declared but not used",
3565 (uentry_isIter (ce) ? "Iterator"
3566 : (isFileStatic ? "File static function" : "Function")),
3567 uentry_getName (ce)),
3571 else if (uentry_isEndIter (ce))
3573 ; /* no error (already reported for iter */
3575 else if (uentry_isEnumConstant (ce))
3577 if (fileloc_isUser (fwhere))
3579 hasError = optgenerror
3581 message ("Enum member %q not used",
3582 uentry_getName (ce)),
3586 else if (uentry_isConstant (ce))
3588 if (fileloc_isUser (fwhere))
3590 hasError = optgenerror
3592 message ("Constant %q declared but not used",
3593 uentry_getName (ce)),
3597 else if (uentry_isDatatype (ce))
3599 if (fileloc_isUser (fwhere))
3601 hasError = optgenerror
3603 message ("Type %q declared but not used",
3604 uentry_getName (ce)),
3608 else if (!uentry_isRefParam (ce) && !uentry_isExpandedMacro (ce))
3609 { /* errors for ref params will be reported in the next scope */
3610 llassertprint (uentry_isVar (ce),
3611 ("ce: %s", uentry_unparseFull (ce)));
3613 if (ctype_isFunction (uentry_getType (ce)))
3615 if (fileloc_isUser (fwhere))
3617 hasError = optgenerror
3619 message ("%q %q declared but not used",
3621 (isFileStatic ? "File static function"
3623 uentry_getName (ce)),
3629 if (fileloc_isUser (fwhere))
3633 hasError = optgenerror
3635 message ("%q %q declared but not used",
3637 (isFileStatic ? "File static variable"
3639 uentry_getName (ce)),
3649 else if ((uentry_isDatatype (ce) || uentry_isAnyTag (ce)))
3650 { /* check all fields */
3651 ctype ct = uentry_getRealType (ce);
3654 while (ctype_isAP (ct))
3656 ct = ctype_getBaseType (ct);
3659 if (ctype_isSU (ct))
3661 uentryList fields = ctype_getFields (ct);
3663 uentryList_elements (fields, field)
3665 if (!uentry_isUsed (field))
3667 if (uentry_hasName (ce))
3669 hasError |= optgenerror
3671 message ("Field %q of %s %q declared but not used",
3672 uentry_getName (field),
3673 cstring_makeLiteralTemp
3674 (ctype_isStruct (ct) ? "structure" : "union"),
3675 uentry_getName (ce)),
3676 uentry_whereEarliest (field));
3682 ** Can't report these errors for unnamed structs.
3683 ** No way to tell when there are multiple consistent
3684 ** unnamed structure types. (Could go through table
3685 ** and mark them all unused...)
3687 hasError |= optgenerror
3689 message ("Field %q of unnamed %s declared but not used",
3690 uentry_getName (field),
3691 cstring_makeLiteralTemp
3692 (ctype_isStruct (ct) ? "structure" : "union")),
3693 uentry_whereEarliest (field));
3698 uentry_setUsed (field, fileloc_undefined);
3700 } end_uentryList_elements;
3710 if (uentry_isParam (ce) && context_inMacro ())
3712 if (fileloc_isDefined (uentry_whereSpecified (ce)))
3714 uentry_showWhereSpecified (ce);
3719 uentry_showDefSpecInfo (ce, fwhere);
3722 uentry_setUsed (ce, fileloc_undefined);
3728 checkGlobalReturn (uentry glob, sRef orig)
3730 sRef sr = uentry_getSref (glob);
3732 DPRINTF (("Check global return: %s / orig: %s / sr: %s",
3733 uentry_unparseFull (glob),
3734 sRef_unparseFull (orig),
3735 sRef_unparseFull (sr)));
3737 DPRINTF (("Is killed: %s", bool_unparse (sRef_isKilledGlob (orig))));
3739 if (context_getFlag (FLG_GLOBSTATE))
3741 DPRINTF (("Is killed: %s", sRef_unparseFull (orig)));
3743 if (sRef_isKilledGlob (orig))
3745 if (sRef_isStateUndefined (sr)
3746 || sRef_isUnuseable (sr)
3747 || sRef_isStateUnknown (sr)
3748 || sRef_isDead (sr))
3754 ctype ct = ctype_realType (uentry_getType (glob));
3756 DPRINTF (("Check global destroyed: %s", uentry_unparseFull (glob)));
3758 if (ctype_isVisiblySharable (ct))
3763 ("Killed global %q (type %s) not released before return",
3764 uentry_getName (glob),
3765 ctype_unparse (ct)),
3768 sRef_showStateInfo (sr);
3773 sRef_protectDerivs ();
3774 (void) transferChecks_globalDestroyed (sr, g_currentloc);
3775 sRef_clearProtectDerivs ();
3781 if (sRef_isStateUndefined (sr))
3783 if (optgenerror (FLG_GLOBSTATE,
3785 ("Function returns with global %q undefined",
3786 uentry_getName (glob)),
3789 sRef_showStateInfo (sr);
3794 if (sRef_isDead (sr) || sRef_isKept (sr))
3798 message ("Function returns with global %q "
3799 "referencing %s storage",
3800 uentry_getName (glob),
3801 cstring_makeLiteralTemp (sRef_isDead (sr) ? "released" : "kept")),
3804 if (sRef_isKept (sr))
3806 sRef_showAliasInfo (sr);
3810 sRef_showStateInfo (sr);
3813 sRef_setDefState (sr, SS_UNKNOWN, fileloc_undefined);
3817 DPRINTF (("Here: %s / %s",
3818 uentry_unparseFull (glob),
3819 sRef_unparseFull (sr)));
3821 if (ctype_isRealPointer (uentry_getType (glob))
3822 && sRef_possiblyNull (sr)
3823 && !uentry_possiblyNull (glob))
3827 message ("Function returns with non-null global %q "
3828 "referencing null storage",
3829 uentry_getName (glob)),
3832 sRef_showNullInfo (sr);
3837 DPRINTF (("Check transfer: %s", uentry_unparseFull (glob)));
3838 transferChecks_globalReturn (glob);
3846 ** remember: check alias globals
3849 void usymtab_checkFinalScope (bool isReturn)
3852 bool mustDefine = context_getFlag (FLG_MUSTDEFINE);
3853 sRefSet checked = sRefSet_new ();
3854 usymtab stab = utab;
3858 ** need to check all scopes out to function parameters.
3863 for (i = 0; i < stab->nentries; i++)
3865 uentry ce = stab->entries[i];
3866 sRef sr = uentry_getSref (ce);
3867 sRef rb = sRef_getRootBase (sr);
3871 ** Shouldn't check if shadow checked in deeper scope:
3876 uentry oue = usymtab_lookupQuietNoAlt (utab, uentry_observeRealName (ce));
3878 if (!uentry_sameObject (ce, oue))
3880 /* what if it is one an alternate branch? */
3881 /*@innercontinue@*/ continue;
3885 DPRINTF (("Here check final scope: %s", uentry_unparseFull (ce)));
3887 if (ctype_isFunction (uentry_getType (ce)))
3889 /*@innercontinue@*/ continue;
3892 if (uentry_isAnyParam (ce)
3893 || uentry_isRefParam (ce)
3894 || sRef_isFileOrGlobalScope (rb))
3896 /* Don't do the loseref check...but should check state! */
3897 DPRINTF (("Skipping check 1"));
3899 else if (sRef_isDefinitelyNull (sr)
3900 || usymtab_isDefinitelyNull (sr))
3903 ** No state reference errors for definitely null references.
3906 DPRINTF (("Skipping check 2"));
3910 DPRINTF (("Lose ref: %s / %s", uentry_unparse (ce),
3911 sRef_unparseFull (sr)));
3913 tvalues = sRef_getValueTable (sr);
3915 valueTable_elements (tvalues, fkey, fval) {
3916 metaStateInfo minfo;
3917 cstring msg = cstring_undefined;
3920 minfo = context_lookupMetaStateInfo (fkey);
3921 llassert (metaStateInfo_isDefined (minfo));
3923 if (stateValue_isError (fval)
3924 || sRef_isStateUndefined (sr)) /* No errors for undefined state */
3926 DPRINTF (("Skipping check 3"));
3930 DPRINTF (("Check: %s / %s / %s", fkey,
3931 metaStateInfo_unparse (minfo),
3932 stateValue_unparse (fval)));
3934 minfo = context_lookupMetaStateInfo (fkey);
3936 nval = stateCombinationTable_lookupLoseReference
3937 (metaStateInfo_getTransferTable (minfo),
3938 stateValue_getValue (fval), &msg);
3940 if (cstring_isDefined (msg))
3945 ("%s loses reference %q in invalid state %q (%s)",
3946 cstring_makeLiteralTemp (isReturn ? "Return" : "Scope exit"),
3947 uentry_getName (ce),
3948 stateValue_unparseValue (fval, minfo),
3952 stateValue_show (fval, minfo);
3956 DPRINTF (("Suppressed transfer error: %s", msg));
3960 } end_valueTable_elements;
3963 DPRINTF (("Check mustfree entry: %s", uentry_unparseFull (ce)));
3965 if (!sRefSet_member (checked, sr) && !sRef_isFileOrGlobalScope (rb))
3967 if (ctype_isRealSU (uentry_getType (ce))
3968 && !uentry_isAnyParam (ce)
3969 && !uentry_isRefParam (ce)
3970 && !uentry_isStatic (ce)
3971 && !sRef_isDependent (sr)
3972 && !sRef_isOwned (sr))
3974 sRefSet als = usymtab_allAliases (sr);
3976 if (sRefSet_isEmpty (als))
3978 transferChecks_localDestroyed (sr, g_currentloc);
3982 /* aliased, no problem */ ;
3988 (!uentry_isStatic (ce)
3989 && ((sRef_isNewRef (sr))
3990 || (((sRef_isOnly (sr) || sRef_isFresh (sr)
3991 || sRef_isKeep (sr) || sRef_isOwned (sr))
3992 && !sRef_isDead (sr))
3993 && (!sRef_definitelyNull (sr))
3994 && (!usymtab_isDefinitelyNull (sr)))))
3996 bool hasError = TRUE;
3998 DPRINTF (("Checking: %s", sRef_unparseFull (sr)));
4001 ** If its a scope exit, check if there is an alias.
4002 ** If so, make it only. If not, there is an error.
4007 if (transferChecks_canLoseReference (sr, g_currentloc))
4009 DPRINTF (("Can lose!"));
4016 if (sRef_hasLastReference (sr))
4018 sRef ar = sRef_getAliasInfoRef (sr);
4021 (sRef_isFresh (ar) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4023 ("Last reference %q to %s storage %qnot %q before %q",
4025 alkind_unparse (sRef_getAliasKind (sr)),
4026 sRef_unparseOpt (ar),
4027 cstring_makeLiteral (sRef_isKeep (sr)
4028 ? "transferred" : "released"),
4029 cstring_makeLiteral (isReturn
4030 ? "return" : "scope exit")),
4033 sRef_showRefLost (sr);
4036 else if (sRef_isNewRef (sr))
4039 (sRef_isFresh (sr) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4041 ("%q %q not released before %q",
4043 (alkind_isKillRef (sRef_getOrigAliasKind (sr))
4044 ? "Kill reference parameter" : "New reference"),
4045 uentry_getName (ce),
4046 cstring_makeLiteral (isReturn
4047 ? "return" : "scope exit")),
4050 sRef_showAliasInfo (sr);
4055 if (ctype_isRealSU (sRef_getType (sr)))
4057 transferChecks_structDestroyed (sr, g_currentloc);
4062 (sRef_isFresh (sr) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4064 ("%s storage %q not %q before %q",
4065 alkind_capName (sRef_getAliasKind (sr)),
4066 uentry_getName (ce),
4067 cstring_makeLiteral (sRef_isKeep (sr)
4068 ? "transferred" : "released"),
4069 cstring_makeLiteral (isReturn
4070 ? "return" : "scope exit")),
4073 sRef_showAliasInfo (sr);
4074 DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
4086 if (mustDefine && uentry_isOut (ce))
4088 /* No error if its dead (either only or error already reported */
4089 if (!sRef_isReallyDefined (sr) && !sRef_isDead (sr))
4093 message ("Out storage %q not defined before %q",
4094 uentry_getName (ce),
4096 (isReturn ? "return" : "scope exit")),
4099 DPRINTF (("sr: %s", sRef_unparseFull (sr)));
4104 ** also check state is okay
4107 if (usymtab_lexicalLevel () > functionScope
4108 && uentry_isVariable (ce)
4109 && (sRef_isLocalVar (sr)
4110 && (sRef_isDependent (sr) || sRef_isLocalState (sr))))
4112 sRefSet ab = usymtab_aliasedBy (sr);
4114 /* should do something more efficient here */
4116 if (sRefSet_isEmpty (ab))
4118 /* and no local ref */
4119 DPRINTF (("Check lose ref: %s", uentry_unparseFull (ce)));
4120 transferChecks_loseReference (ce);
4134 checked = sRefSet_insert (checked, sr);
4137 llassert (usymtab_isDefined (stab->env));
4139 if (usymtab_isBranch (stab))
4141 stab = usymtab_dropEnv (stab);
4148 llassert (stab != usymtab_undefined);
4149 } while (isReturn && (stab->lexlevel >= paramsScope));
4151 sRefSet_free (checked);
4155 ** all globals are appropriately defined
4156 ** all parameters are appropriately defined
4157 ** special clauses are followed
4160 if (isReturn || (utab->lexlevel == paramsScope))
4162 uentry fcn = context_getHeader ();
4163 uentryList params = context_getParams ();
4164 globSet uglobs = context_getUsedGlobs ();
4165 globSet sglobs = context_getGlobs ();
4167 if (isReturn && context_maybeSet (FLG_GLOBALIAS))
4169 aliasTable_checkGlobs (utab->aliases);
4173 ** state clauses (ensures, defines, sets, allocates, releases)
4176 if (uentry_hasStateClauseList (fcn))
4178 stateClauseList clauses = uentry_getStateClauseList (fcn);
4180 stateClauseList_elements (clauses, cl)
4182 if (stateClause_isAfter (cl) && !stateClause_isGlobal (cl))
4184 if (stateClause_setsMetaState (cl))
4186 sRefSet rfs = stateClause_getRefs (cl);
4187 qual q = stateClause_getMetaQual (cl);
4188 annotationInfo ainfo = qual_getAnnotationInfo (q);
4189 metaStateInfo minfo = annotationInfo_getState (ainfo);
4190 cstring key = metaStateInfo_getName (minfo);
4191 int mvalue = annotationInfo_getValue (ainfo);
4193 DPRINTF (("Post meta state clause: %s", stateClause_unparse (cl)));
4195 sRefSet_elements (rfs, el)
4197 sRef base = sRef_getRootBase (el);
4199 if (sRef_isResult (base))
4202 ** This is checked for return transfers.
4206 else if (sRef_isParam (base) || sRef_isGlobalMarker (base))
4208 sRef sr = sRef_updateSref (base);
4209 sr = sRef_fixBase (el, sr);
4211 if (!sRef_checkMetaStateValue (sr, key, mvalue))
4216 ("Ensures clause not satisfied%q (state is %q): %q",
4217 sRef_isGlobalMarker (sr)
4219 : message (" by %q", sRef_unparse (sr)),
4220 stateValue_unparseValue (sRef_getMetaStateValue (sr, key),
4222 stateClause_unparse (cl)),
4225 sRef_showMetaStateInfo (sr, key);
4231 if (sRef_isMeaningful (el))
4236 } end_sRefSet_elements ;
4240 /* evs - 2000 07 10 - added this */
4241 sRefTest tst = stateClause_getPostTestFunction (cl);
4242 sRefSet rfs = stateClause_getRefs (cl);
4244 sRefSet_elements (rfs, el)
4246 sRef base = sRef_getRootBase (el);
4248 if (sRef_isResult (base))
4251 ** This is checked for return transfers.
4256 else if (sRef_isParam (base))
4258 sRef sr = sRef_updateSref (base);
4259 sr = sRef_fixBase (el, sr);
4261 if (tst != NULL && !tst (sr))
4264 (stateClause_postErrorCode (cl),
4265 message ("%s storage %qcorresponds to "
4266 "storage listed in %q clause",
4267 stateClause_postErrorString (cl, sr),
4268 sRef_unparseOpt (sr),
4269 stateClause_unparseKind (cl)),
4272 sRefShower ss = stateClause_getPostTestShower (cl);
4279 DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
4285 if (sRef_isMeaningful (el))
4290 } end_sRefSet_elements ;
4293 } end_stateClauseList_elements ;
4297 ** check parameters on return
4300 uentryList_elements (params, arg)
4302 if (!uentry_isElipsisMarker (arg))
4304 ctype rt = ctype_realType (uentry_getType (arg));
4306 if (ctype_isMutable (rt) || ctype_isSU (rt))
4308 uentry param = usymtab_lookupQuiet (utab, uentry_rawName (arg));
4309 DPRINTF (("Check param return: %s", uentry_unparseFull (param)));
4310 transferChecks_paramReturn (param);
4313 } end_uentryList_elements;
4315 DPRINTF (("Check global return: %s",
4316 globSet_unparse (sglobs)));
4318 globSet_allElements (sglobs, el)
4320 sRef orig = el; /*! sRef_updateSref (el); */ /*!!!*/
4321 uentry current = sRef_getUentry (el);
4323 DPRINTF (("Check global return: %s / %s", sRef_unparseFull (el),
4324 uentry_unparseFull (current)));
4326 if (uentry_isVariable (current) && !uentry_isRealFunction (current))
4328 checkGlobalReturn (current, orig);
4330 } end_globSet_allElements;
4332 globSet_allElements (uglobs, el)
4334 if (!globSet_member (sglobs, el))
4336 uentry current = sRef_getUentry (el);
4338 if (uentry_isVariable (current)
4339 && !uentry_isRealFunction (current))
4341 checkGlobalReturn (current, sRef_undefined);
4344 } end_globSet_allElements;
4349 usymtab_quietExitScope (fileloc loc)
4350 /*@globals utab, globtab, filetab; @*/
4353 usymtab t = utab->env;
4355 DPRINTF (("Quiet exit scope [%p]", utab));
4357 if (utab->reftable != NULL)
4361 for (i = 0; i < utab->nentries; i++)
4363 uentry current = utab->entries[i];
4364 uentry old = usymtab_lookupAux (t, uentry_rawName (current));
4366 uentry_mergeState (old, current, loc, FALSE, FALSE, FALSE, NOCLAUSE);
4370 llassert (t != NULL);
4372 if (t->lexlevel > paramsScope)
4374 t->guards = guardSet_levelUnion (t->guards, utab->guards, t->lexlevel);
4375 t->aliases = aliasTable_levelUnionSeq (t->aliases, utab->aliases,
4377 utab->aliases = aliasTable_undefined;
4380 t->mustBreak = utab->mustBreak;
4381 t->exitCode = utab->exitCode;
4383 DPRINTF (("Free level [%p]", utab));
4384 usymtab_freeLevel (utab);
4389 usymtab_checkAllValid ();
4394 ** Exit a scope with no checking, lose alias states.
4395 ** (When should this be used?)
4398 void usymtab_quietPlainExitScope (void)
4399 /*@globals utab, globtab, filetab@*/
4402 usymtab t = utab->env;
4404 llassert (t != NULL);
4405 llassert (NOALIAS (utab->aliases, t->aliases));
4406 usymtab_freeLevel (utab);
4410 void usymtab_exitScope (exprNode expr)
4411 /*@globals utab, filetab, globtab@*/
4412 /*@modifies utab, globtab@*/
4414 usymtab ctab = usymtab_undefined;
4415 usymtab lctab = usymtab_undefined;
4416 bool mustReturn = exprNode_mustEscape (expr);
4418 DPRINTF (("Exit scope [%p]", utab));
4420 if (utab->kind == US_CBRANCH)
4423 ** save the case branches, remove the first non-cbranch
4428 while (utab->kind == US_CBRANCH)
4432 llassert (utab != GLOBAL_ENV);
4436 if (utab->kind == US_TBRANCH || utab->kind == US_FBRANCH
4437 || utab->kind == US_CBRANCH || utab->kind == US_SWITCH)
4439 if (context_inMacro ())
4441 /* evs 2000-07-25 */
4442 /* Unparseable macro may end inside nested scope. Deal with it. */
4444 llerror (FLG_SYNTAX,
4445 message ("Problem parsing macro body of %s (unbalanced scopes). "
4446 "Attempting to recover, recommend /*@notfunction@*/ before "
4447 "macro definition.",
4448 context_inFunctionName ()));
4450 while (utab->kind == US_TBRANCH
4451 || utab->kind == US_FBRANCH
4452 || utab->kind == US_CBRANCH
4453 || utab->kind == US_SWITCH)
4456 llassert (utab != GLOBAL_ENV);
4460 llcontbug (message ("exitScope: in branch: %q", usymtab_unparseStack ()));
4462 } /*@=branchstate@*/
4466 ** check all variables in scope were used
4470 ** bogus errors if this is the normal inside a switch,
4471 ** since cases have not been merged yet. Should probably
4472 ** still check this, but I'm too lazy at the moment...
4475 llassertfatal (utab->env != GLOBAL_ENV);
4477 if (utab->env->kind != US_SWITCH)
4483 ** check aliasing: all only params are released (dead)
4484 ** definition: all out params are defined, all modified params
4485 ** are completely defined
4487 ** NOTE: note for exiting paramsScope, since checkReturn should be
4491 if (!mustReturn && (usymtab_lexicalLevel () > functionScope))
4494 ** should only call this is end of scope is reachable...
4497 usymtab_checkFinalScope (FALSE);
4500 if (usymtab_lexicalLevel () == paramsScope && context_inFunctionLike ())
4503 ** leaving a function, need to fix up globals
4506 uentryList params = context_getParams ();
4507 globSet globs = context_getUsedGlobs ();
4509 uentryList_elements (params, ue)
4511 uentry_fixupSref (ue);
4512 } end_uentryList_elements;
4514 clearFunctionTypes ();
4516 DPRINTF (("Fixing up globals: %s", globSet_unparse (globs)));
4518 globSet_allElements (globs, el)
4520 DPRINTF (("Fix: %s", sRef_unparseDebug (el)));
4522 if (sRef_isCvar (el))
4525 usymId index = sRef_getScopeIndex (el);
4527 if (sRef_isFileStatic (el))
4529 llassert (usymtab_isDefined (filetab));
4530 current = usymtab_fetchIndex (filetab, index);
4534 current = usymtab_fetchIndex (globtab, index);
4537 if (uentry_isVariable (current))
4539 DPRINTF (("Fixup: %s", uentry_unparse (current)));
4540 uentry_fixupSref (current);
4544 DPRINTF (("Clear: %s", uentry_getSref (current)));
4545 sRef_clearDerived (uentry_getSref (current));
4549 sRef_clearDerived (el); /* evans 2002-03-14 - this is the likely source of many crashes! */
4550 } end_globSet_allElements;
4553 usymtab_quietExitScope (exprNode_loc (expr));
4555 if (lctab != usymtab_undefined)
4557 /*@i@*/ lctab->env = utab;
4558 /*@i@*/ utab = ctab;
4559 /*@-branchstate@*/ } /*@=branchstate@*/
4564 usymtab_checkAllValid ();
4570 ** yikes! don't let the '170 kids see this one...
4574 usymtab_directParamNo (uentry ue)
4576 if (uentry_isVar (ue))
4578 sRef sr = uentry_getSref (ue);
4580 if (sRef_lexLevel (sr) == functionScope)
4582 usymId index = sRef_getScopeIndex (sr);
4584 if (index < usymId_fromInt (uentryList_size (context_getParams ())))
4590 return usymId_invalid;
4593 /*@dependent@*/ /*@exposed@*/ uentry
4594 usymtab_getParam (int paramno)
4598 ** requires in a function context (checked)
4600 ** depends on no nested functions --- the function
4601 ** parameters are ALWAYS one scope inside the global scope
4602 ** and entered in order!
4606 if (!context_inFunctionLike ())
4607 llfatalbug (message ("usymtab_getParam: not in function context: %q",
4608 context_unparse ()));
4610 while (s->lexlevel > paramsScope)
4615 llassert (usymtab_isDefined (s));
4617 if (paramno >= s->nentries)
4620 ** Parse errors lead to this.
4623 uentry err = uentry_makeVariableLoc (cstring_makeLiteralTemp ("<error>"),
4626 uentry_markOwned (err);
4630 return (s->entries[paramno]);
4633 static /*@dependent@*/ /*@exposed@*/ uentry
4634 usymtab_getRefTab (/*@notnull@*/ usymtab u, int level, usymId index)
4638 ue = usymtab_getRefNoisy (u, level, index);
4640 if (uentry_isUndefined (ue))
4642 llbug (message ("usymtab_getRef: out of range: %d. level = %d",
4649 static /*@dependent@*/ /*@exposed@*/ usymtab
4650 usymtab_dropEnv (/*@notnull@*/ usymtab s)
4652 if (s->kind == US_CBRANCH)
4660 llassert (s != GLOBAL_ENV);
4661 } while (s->kind == US_CBRANCH);
4662 /* drop all cases (except in nested scopes */
4665 llassert (s != GLOBAL_ENV);
4668 if (s->kind == US_FBRANCH)
4670 s = s->env; /* skip the true branch */
4671 llassert (usymtab_isDefined (s));
4672 llassert (s->kind == US_TBRANCH);
4675 llassert (s != GLOBAL_ENV);
4681 /*@dependent@*/ /*@exposed@*/ uentry
4682 usymtab_getRefQuiet (int level, usymId index)
4688 llassert (s != NULL);
4689 llassert (index >= 0);
4691 if (level > s->lexlevel)
4693 return uentry_undefined;
4696 llassertprint (level <= s->lexlevel, ("level: %d / lexlevel: %d",
4697 level, s->lexlevel));
4699 while (s->lexlevel > level)
4701 if (usymtab_isBranch (s))
4703 int eindex = refTable_lookup (s, level, index);
4705 if (eindex != NOT_FOUND)
4707 return (s->entries[eindex]);
4711 s = usymtab_dropEnv (s);
4714 while (usymtab_isBranch (s) && s->lexlevel == level)
4716 int eindex = refTable_lookup (s, level, index);
4718 if (eindex != NOT_FOUND)
4720 return (s->entries[eindex]);
4723 s = usymtab_dropEnv (s);
4726 if (index >= usymId_fromInt (s->nentries))
4728 return uentry_undefined;
4731 llassert (!uentry_isUndefined (s->entries[index]));
4733 return s->entries[index];
4736 static /*@dependent@*/ /*@exposed@*/ uentry
4737 usymtab_getRefNoisy (/*@notnull@*/ usymtab s, int level, usymId index)
4740 uentry ue = uentry_undefined;
4742 llassert (index >= 0);
4744 while (s->lexlevel > level)
4746 if (usymtab_isBranch (s))
4748 int eindex = refTable_lookup (s, level, index);
4750 if (eindex != NOT_FOUND)
4752 ue = s->entries[eindex];
4756 while (!usymtab_isBranch (otab))
4758 otab = usymtab_dropEnv (otab);
4759 llassert (otab != GLOBAL_ENV);
4762 if (refTable_lookup (otab, level, index) == NOT_FOUND)
4764 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4776 s = usymtab_dropEnv (s);
4779 llassert (usymtab_isDefined (s));
4781 while (usymtab_isBranch (s) && s->lexlevel == level)
4783 int eindex = refTable_lookup (s, level, index);
4785 if (eindex != NOT_FOUND)
4787 ue = s->entries[eindex];
4791 while (!usymtab_isBranch (otab))
4793 otab = usymtab_dropEnv (otab);
4794 llassert (otab != GLOBAL_ENV);
4797 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4807 s = usymtab_dropEnv (s);
4810 if (s->lexlevel == level && (index < usymId_fromInt (s->nentries)))
4812 ue = s->entries[index];
4814 if (uentry_isValid (ue))
4818 while (!usymtab_isBranch (otab))
4820 otab = usymtab_dropEnv (otab);
4822 if (otab == GLOBAL_ENV)
4828 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4839 if (index >= usymId_fromInt (s->nentries))
4841 return uentry_undefined;
4844 llassert (!uentry_isUndefined (s->entries[index]));
4846 return s->entries[index];
4850 ** looking up entries
4852 ** If entry is inside a branch, then copy it, and put it into
4853 ** the branch table.
4857 int refTable_lookup (/*@notnull@*/ usymtab ut, int level, usymId index)
4859 refTable rt = ut->reftable;
4862 llassert (rt != NULL);
4864 for (i = 0; i < ut->nentries; i++)
4866 if (rt[i]->level == level && rt[i]->index == usymId_toInt (index))
4876 /*@only@*/ refentry refentry_create (int level, int index)
4878 refentry r = (refentry) dmalloc (sizeof (*r));
4886 static /*@dependent@*/ /*@exposed@*/ uentry
4887 usymtab_addRefEntry (/*@notnull@*/ usymtab s, cstring k)
4891 if (ut->reftable == NULL)
4893 DPRINTF (("Adding ref entry without reftable: %s", k));
4894 return uentry_undefined;
4897 llassert (ut->reftable != NULL);
4899 while (s != GLOBAL_ENV)
4901 usymId eindex = usymtab_getIndex (s, k);
4903 if (usymtab_indexFound (eindex))
4905 uentry current = s->entries[eindex];
4907 if (uentry_isVar (current) && !ctype_isFunction (uentry_getType (current)))
4911 DPRINTF (("Here: copying %s", uentry_unparse (current)));
4912 if (uentry_isNonLocal (current))
4914 ue = uentry_copy (current);
4918 ue = uentry_copyNoSave (current);
4921 DPRINTF (("Here: copying %s", uentry_unparse (ue)));
4922 usymtab_addEntryQuiet (ut, ue);
4923 DPRINTF (("Okay..."));
4925 if (s->reftable != NULL)
4927 refentry ref = s->reftable[eindex];
4929 ut->reftable[ut->nentries - 1]
4930 = refentry_create (ref->level, ref->index);
4934 ut->reftable[ut->nentries - 1]
4935 = refentry_create (s->lexlevel, usymId_toInt (eindex));
4946 s = usymtab_dropEnv (s);
4949 return uentry_undefined;
4952 static uentry usymtab_lookupAux (usymtab s, cstring k)
4954 DPRINTF (("Lookup: %s", k));
4956 while (s != GLOBAL_ENV)
4958 usymId eindex = usymtab_getIndex (s, k);
4960 if (usymtab_indexFound (eindex))
4962 uentry ret = s->entries[eindex];
4966 if (s->kind == US_TBRANCH
4967 || s->kind == US_FBRANCH
4968 || s->kind == US_CBRANCH)
4969 /* uentry_isGlobalVariable (ret) && os->lexlevel > fileScope) */
4972 DPRINTF (("Adding global ref entry: %s", k));
4973 ret = usymtab_addRefEntry (os, k);
4974 DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
4979 DPRINTF (("Found: %s", uentry_unparseFull (ret)));
4983 if (s->kind == US_TBRANCH || s->kind == US_FBRANCH
4984 || s->kind == US_CBRANCH)
4986 /* why isn't this os??? */
4987 uentry ret = usymtab_addRefEntry (s, k);
4988 DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
4995 return uentry_undefined;
4998 static /*@dependent@*/ /*@exposed@*/ uentry
4999 usymtab_lookupQuietAux (usymtab s, cstring k, bool noalt)
5001 while (s != GLOBAL_ENV)
5003 usymId eindex = usymtab_getIndex (s, k);
5005 if (usymtab_indexFound (eindex))
5007 uentry ret = s->entries[eindex];
5011 if (noalt && usymtab_isBranch (s))
5013 s = usymtab_dropEnv (s);
5017 llassert (s != NULL);
5022 return uentry_undefined;
5025 static /*@exposed@*/ /*@dependent@*/ uentry
5026 usymtab_lookupQuiet (usymtab s, cstring k)
5028 return usymtab_lookupQuietAux (s, k, FALSE);
5031 static /*@exposed@*/ /*@dependent@*/ uentry
5032 usymtab_lookupQuietNoAlt (usymtab s, cstring k)
5034 return usymtab_lookupQuietAux (s, k, TRUE);
5037 /*@dependent@*/ /*@observer@*/ uentry
5038 usymtab_lookupSafe (cstring k)
5041 DPRINTF (("Lookup safe: %s", k));
5042 return (usymtab_lookupAux (utab, k));
5045 /*@dependent@*/ /*@observer@*/ uentry
5046 usymtab_lookupSafeScope (cstring k, int lexlevel)
5050 ** This is necessary to deal with shadowed variables that are referenced
5051 ** through aliases inside the shadowed scope. It would be better if
5052 ** lookup could take an sRef as a parameter.
5057 while (tab != GLOBAL_ENV && tab->lexlevel > lexlevel) {
5058 uentry ret = usymtab_lookupAux (tab, k);
5060 if (uentry_isValid (ret)) {
5061 sRef sr = uentry_getSref (ret);
5063 if (sRef_isCvar (sr) && sRef_lexLevel (sr) > lexlevel) {
5064 tab = usymtab_dropEnv (tab);
5071 return uentry_undefined;
5075 usymtab_lookupExpose (cstring k)
5078 uentry ce = usymtab_lookupAux (utab, k);
5080 if (uentry_isUndefined (ce))
5082 llfatalbug (message ("usymtab_lookup: not found: *%s*", k));
5085 if (uentry_isPriv (ce))
5087 llfatalbug (message ("usymtab_lookup: private: *%s*", k));
5093 uentry usymtab_lookupExposeGlob (cstring k)
5095 return (usymtab_lookupGlobSafe (k));
5098 uentry usymtab_lookupGlob (cstring k)
5099 /*@globals globtab@*/
5101 uentry ce = usymtab_lookupAux (globtab, k);
5103 if (uentry_isUndefined (ce))
5104 llfatalbug (message ("usymtab_lookup: not found: %s", k));
5106 if (uentry_isPriv (ce))
5107 llfatalbug (message ("usymtab_lookup: private: %s", k));
5109 DPRINTF (("Lookup global: %s", uentry_unparseFull (ce)));
5113 /*@observer@*/ uentry
5114 usymtab_lookupGlobSafe (cstring k)
5115 /*@globals globtab@*/
5117 uentry ce = usymtab_lookupAux (globtab, k);
5118 DPRINTF (("Lookup global: %s", uentry_unparseFull (ce)));
5122 uentry usymtab_lookupEither (cstring k)
5125 uentry ce = usymtab_lookupSafe (k);
5127 if (uentry_isUndefined (ce))
5128 llfatalerror (message ("usymtab_lookup: not found: %s", k));
5130 DPRINTF (("Lookup either: %s", uentry_unparseFull (ce)));
5135 usymtab_lookupType (cstring k)
5136 /*@globals globtab@*/
5138 typeId uid = usymtab_getTypeId (k);
5140 if (typeId_isInvalid (uid))
5142 llcontbug (message ("usymtab_lookupType: not found: %s", k));
5143 return ctype_unknown;
5146 return (uentry_getRealType (usymtab_getTypeEntry (uid)));
5150 usymtab_lookupAbstractType (cstring k) /*@globals globtab@*/
5152 typeId uid = usymtab_getTypeId (k);
5154 if (typeId_isInvalid (uid))
5156 llcontbug (message ("usymtab_lookupType: not found: %s", k));
5157 return ctype_unknown;
5160 return (uentry_getAbstractType (usymtab_getTypeEntry (uid)));
5164 ** if there is an unnamed lcl-specified struct tag matching
5165 ** the uentryList, return its datatype. Otherwise, returns
5170 usymtab_structFieldsType (uentryList f)
5171 /*@globals globtab@*/
5173 return (usymtab_suFieldsType (f, TRUE));
5177 usymtab_unionFieldsType (uentryList f)
5178 /*@globals globtab@*/
5180 return (usymtab_suFieldsType (f, FALSE));
5184 usymtab_suFieldsType (uentryList f, bool isStruct)
5185 /*@globals globtab@*/
5189 DPRINTF (("Fields: %s", uentryList_unparse (f)));
5191 if (fileloc_isSpec (g_currentloc))
5193 return (ctype_undefined);
5196 for (i = 0; i < globtab->nentries; i++)
5198 uentry current = globtab->entries[i];
5201 ? uentry_isStructTag (current) : uentry_isUnionTag (current)))
5203 if (isFakeTag (uentry_rawName (current)))
5205 ctype ct = uentry_getType (current);
5207 DPRINTF (("Check: %s", ctype_unparse (ct)));
5209 if ((isStruct ? ctype_isStruct (ct) : ctype_isUnion (ct))
5211 (uentry_isSpecified (current)
5212 && uentryList_equivFields (f, ctype_getFields (ct))))
5214 return uentry_getAbstractType (current);
5224 return ctype_undefined;
5228 usymtab_enumEnumNameListType (enumNameList f)
5229 /*@globals globtab@*/
5233 for (i = 0; i < globtab->nentries; i++)
5235 uentry current = globtab->entries[i];
5237 if (uentry_isEnumTag (current))
5239 if (isFakeTag (uentry_rawName (current)))
5241 ctype ct = uentry_getType (current);
5243 if (ctype_isEnum (ct) && (enumNameList_match (f, ctype_elist (ct))))
5245 return uentry_getType (current);
5251 return ctype_undefined;
5255 usymtab_exists (cstring k)
5258 uentry ce = usymtab_lookupSafe (k);
5259 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5263 usymtab_existsReal (cstring k)
5266 uentry ce = usymtab_lookupSafe (k);
5268 return (!(uentry_isUndefined (ce))
5269 && !(uentry_isPriv (ce))
5270 && !(uentry_isExpandedMacro (ce)));
5274 usymtab_existsGlob (cstring k)
5275 /*@globals globtab@*/
5277 uentry ce = usymtab_lookupAux (globtab, k);
5279 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5283 usymtab_existsEither (cstring k)
5286 uentry ce = usymtab_lookupAux (utab, k);
5288 return (uentry_isValid (ce));
5292 usymtab_existsGlobEither (cstring k)
5293 /*@globals globtab@*/
5295 uentry ce = usymtab_lookupAux (globtab, k);
5297 return (uentry_isValid (ce));
5301 usymtab_existsType (cstring k)
5302 /*@globals globtab@*/
5304 uentry ce = usymtab_lookupAux (globtab, k);
5306 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && uentry_isDatatype (ce));
5310 usymtab_existsTypeEither (cstring k)
5311 /*@globals globtab@*/
5314 ce = usymtab_lookupAux (globtab, k);
5315 return (uentry_isValid (ce) && uentry_isDatatype (ce));
5319 usymtab_existsStructTag (cstring k) /*@globals globtab@*/
5321 cstring sname = makeStruct (k);
5322 uentry ce = usymtab_lookupAux (globtab, sname);
5323 cstring_free (sname);
5324 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5328 usymtab_existsUnionTag (cstring k) /*@globals globtab@*/
5330 cstring uname = makeUnion (k);
5331 uentry ce = usymtab_lookupAux (globtab, uname);
5333 cstring_free (uname);
5335 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5339 usymtab_existsEnumTag (cstring k) /*@globals globtab@*/
5341 cstring ename = makeEnum (k);
5342 uentry ce = usymtab_lookupAux (globtab, ename);
5344 cstring_free (ename);
5345 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5348 bool usymtab_existsVar (cstring k)
5351 uentry ce = usymtab_lookupSafe (k);
5353 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && (uentry_isVar (ce)));
5361 refTable_free (/*@only@*/ /*@null@*/ refTable x, int nentries)
5367 for (i = 0; i < nentries; i++)
5377 usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab u)
5378 /*@globals globtab, utab, filetab@*/
5382 DPRINTF (("Free level [%p]", u));
5383 aliasTable_free (u->aliases);
5385 refTable_free (u->reftable, u->nentries);
5387 if (u == filetab || u == globtab)
5389 for (i = 0; i < u->nentries; i++)
5391 DPRINTF (("Free complete: %d", i));
5392 DPRINTF (("Uentry: %s", uentry_unparse (u->entries[i])));
5393 uentry_freeComplete (u->entries[i]);
5394 u->entries[i] = uentry_undefined;
5399 for (i = 0; i < u->nentries; i++)
5401 uentry_free (u->entries[i]);
5402 u->entries[i] = uentry_undefined;
5406 guardSet_free (u->guards);
5413 llassert (!cstringTable_isDefined (u->htable));
5416 sfree (u); /* evans 2002-07-12: was inside if */
5420 usymtab_freeAux (/*@only@*/ usymtab u)
5421 /*@globals globtab, utab, filetab@*/
5424 while (u != GLOBAL_ENV)
5427 usymtab_freeLevel (u);
5434 void usymtab_free ()
5435 /*@globals killed utab, globtab, filetab@*/
5439 usymtab_freeAux (utab);
5440 utab = usymtab_undefined;
5442 } /*@=globstate@*/ /* Splint cannot tell that utab is killed */
5444 static int usymtab_lexicalLevel (void) /*@globals utab@*/
5446 return (utab->lexlevel);
5449 bool usymtab_inGlobalScope () /*@globals utab, globtab@*/
5451 return (utab == globtab);
5454 bool usymtab_inFileScope () /*@globals utab@*/
5456 return (utab->lexlevel == fileScope);
5459 bool usymtab_inFunctionScope () /*@globals utab@*/
5461 return (utab->lexlevel == functionScope);
5465 usymtab_replaceEntry (uentry s)
5466 /*@globals utab, globtab@*/
5467 /*@modifies utab, s@*/
5469 usymtab_replaceEntryAux (utab, s);
5473 usymtab_matchForwardStruct (typeId u1, typeId u2)
5474 /*@globals globtab@*/
5476 uentry ue1 = usymtab_getTypeEntry (u1);
5477 uentry ue2 = usymtab_getTypeEntry (u2);
5479 if (uentry_isAnyTag (ue2))
5481 ctype reptype = uentry_getType (ue1);
5483 if (ctype_isPointer (reptype))
5485 ctype repbase = ctype_getBaseType (reptype);
5487 if (ctype_isUA (repbase))
5489 typeId rtuid = ctype_typeId (repbase);
5491 if (u2 == rtuid) return TRUE;
5493 if (typeId_isValid (rtuid))
5495 reptype = uentry_getType (usymtab_getTypeEntry (rtuid));
5496 return (ctype_isUA (reptype) && (u2 == (ctype_typeId (reptype))));
5505 void usymtab_addGuards (guardSet guards)
5508 utab->guards = guardSet_union (utab->guards, guards);
5511 static bool usymtab_isGuardedAux (sRef s)
5515 sRef base = sRef_getRootBase (s);
5516 int lowlevel = paramsScope;
5517 int baselevel = sRef_lexLevel (base);
5519 if (sRef_isCvar (base))
5521 lowlevel = baselevel;
5522 if (lowlevel < paramsScope) lowlevel = paramsScope;
5525 while (tab->lexlevel >= lowlevel)
5527 DPRINTF (("Is guarded? [%s] %s",
5528 guardSet_unparse (tab->guards),
5529 sRef_unparseFull (s)));
5531 if (guardSet_isGuarded (tab->guards, s))
5534 if (!sRef_definitelyNull (s))
5536 sRef_setNotNull (s, fileloc_undefined);
5542 tab = usymtab_dropEnv (tab);
5548 void usymtab_unguard (sRef s) /*@modifies utab@*/
5551 sRef base = sRef_getRootBase (s);
5552 int lowlevel = paramsScope;
5553 int baselevel = sRef_lexLevel (base);
5555 if (sRef_isCvar (base))
5557 lowlevel = baselevel;
5558 if (lowlevel < paramsScope) lowlevel = paramsScope;
5561 while (tab->lexlevel >= lowlevel)
5563 if (guardSet_isGuarded (tab->guards, s))
5565 guardSet_delete (tab->guards, s);
5568 tab = usymtab_dropEnv (tab);
5572 bool usymtab_isGuarded (sRef s)
5574 DPRINTF (("Is guarded? %s", sRef_unparseFull (s)));
5575 return (sRef_aliasCompleteSimplePred (usymtab_isGuardedAux, s));
5578 bool usymtab_isDefinitelyNull (sRef s)
5580 return (sRef_aliasCheckSimplePred (usymtab_isDefinitelyNullAux, s));
5583 bool usymtab_isDefinitelyNullDeep (sRef s)
5585 return (sRef_deepPred (usymtab_isDefinitelyNull, s));
5588 static bool usymtab_isDefinitelyNullAux (sRef s)
5592 sRef base = sRef_getRootBase (s);
5593 int lowlevel = paramsScope;
5595 if (sRef_isCvar (base))
5597 lowlevel = sRef_lexLevel (base);
5598 if (lowlevel < paramsScope) lowlevel = paramsScope;
5601 while (tab->lexlevel >= lowlevel)
5603 if (guardSet_mustBeNull (tab->guards, s))
5608 while (tab->kind == US_CBRANCH)
5613 llassert (usymtab_isDefined (tab));
5615 if (tab->kind == US_FBRANCH)
5618 llassert (tab->kind == US_TBRANCH);
5628 usymtab_printGuards ()
5629 /*@globals utab, globtab@*/
5631 usymtab ttab = utab;
5633 while (ttab != globtab)
5635 llmsg (message ("Guards [%d]: %q", ttab->lexlevel,
5636 guardSet_unparse (ttab->guards)));
5642 usymtab_displayAllUses ()
5643 /*@globals utab, globtab@*/
5647 /* only in top scope */
5648 llassert (utab == globtab);
5650 /* need a copy, so order is not messed up by sort! */
5651 copy = usymtab_shallowCopy (globtab);
5653 qsort (copy->entries, (size_t)copy->nentries,
5654 sizeof (*copy->entries), (int (*)(const void *, const void *)) uentry_xcompareuses);
5656 usymtab_entries (copy, ue)
5658 if (uentry_isValid (ue) && !uentry_isGlobalMarker (ue))
5660 filelocList uses = uentry_getUses (ue);
5661 int size = filelocList_realSize (uses);
5663 if (fileloc_isDefined (uentry_whereDefined (ue))
5664 && !fileloc_isLib (uentry_whereDefined (ue))
5667 llmsg (message ("%q (%q), %d use%&:\n %q",
5668 uentry_getName (ue),
5669 fileloc_unparse (uentry_whereDefined (ue)),
5670 size, filelocList_unparseUses (uses)));
5673 } end_usymtab_entries;
5675 usymtab_shallowFree (copy);
5678 static /*@dependent@*/ /*@exposed@*/ usymtab
5679 usymtab_getFileTab ()
5680 /*@globals filetab@*/
5682 llassert (filetab != NULL);
5688 usymtab_unparseStack ()
5691 return (usymtab_unparseStackTab (utab));
5694 static /*@only@*/ cstring
5695 usymtab_unparseStackTab (usymtab t)
5697 bool firstOne = TRUE;
5698 cstring ret = cstring_makeLiteral ("[");
5700 while (t != GLOBAL_ENV)
5704 ret = message ("%q %q", ret, usymtab_typeName (t));
5709 ret = message ("%q, %q", ret, usymtab_typeName (t));
5714 ret = message ("%q ]", ret);
5718 static /*@only@*/ cstring
5719 usymtab_typeName (/*@notnull@*/ usymtab t)
5723 case US_GLOBAL: return cstring_makeLiteral ("global");
5724 case US_NORMAL: return cstring_makeLiteral ("normal");
5725 case US_TBRANCH: return cstring_makeLiteral ("true");
5726 case US_FBRANCH: return cstring_makeLiteral ("false");
5727 case US_CBRANCH: return cstring_makeLiteral ("case");
5728 case US_SWITCH: return cstring_makeLiteral ("switch");
5734 void usymtab_addMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5737 if (!sRef_similar (s, al))
5739 usymtab_addForceMustAlias (s, al);
5744 ** Same as usymtab_addMustAlias, except does not check sRef_isSimilar.
5747 void usymtab_addForceMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5750 /* evans 2002-03-3: was sRef_isMeaningful -- but we need to keep aliases for new storage also! */
5751 if (sRef_isMeaningful (s)
5752 && sRef_isMeaningful (al)
5753 && !(sRef_isConst (s) || sRef_isConst (al))
5754 && !(sRef_isAddress (al) && sRef_isDirectParam (sRef_getBase (al))))
5756 utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
5757 DPRINTF (("Must alias: %s", aliasTable_unparse (utab->aliases)));
5760 ** for local variable, aliasing is symmetric
5763 if (sRef_isLocalVar (s) && sRef_isLocalVar (al))
5765 utab->aliases = aliasTable_addMustAlias (utab->aliases, al, s);
5770 DPRINTF (("Not aliasing! %s / %s", sRef_unparseFull (s), sRef_unparseFull (al)));
5771 DPRINTF (("meaningful: %d %d", sRef_isMeaningful (s), sRef_isMeaningful (al)));
5775 void usymtab_addReallyForceMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5778 utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
5781 void usymtab_clearAlias (sRef s)
5782 /*@modifies utab, s@*/
5785 aliasTable_clearAliases (utab->aliases, s);
5788 sRefSet usymtab_allAliases (sRef s)
5791 if (sRef_isSomewhatMeaningful (s))
5795 ret = sRefSet_unionFree (aliasTable_aliasedBy (utab->aliases, s),
5796 aliasTable_canAlias (utab->aliases, s));
5801 DPRINTF (("NOT A MEANINGFUL SREF!"));
5802 return sRefSet_undefined;
5806 /*@only@*/ sRefSet usymtab_canAlias (sRef s)
5809 if (sRef_isSomewhatMeaningful (s))
5811 sRefSet res = aliasTable_canAlias (utab->aliases, s);
5815 return sRefSet_undefined;
5818 /*@only@*/ sRefSet usymtab_aliasedBy (sRef s)
5821 return (aliasTable_aliasedBy (utab->aliases, s));
5824 /*@only@*/ cstring usymtab_unparseAliases ()
5827 return (aliasTable_unparse (utab->aliases));
5831 ** Debugging routines:
5832 ** okay to leak storage here, only for debugging
5838 usymtab_printOut (void)
5844 char *ind = mstring_copy (" ");
5846 fprintf (g_warningstream, "<<< [symbol table] >>>\n");
5848 while (s != GLOBAL_ENV && s->env != GLOBAL_ENV)
5850 cstring tname = usymtab_typeName (s);
5854 ind[depth * 3 + 1] = '\0';
5857 fprintf (g_warningstream, "level: %d (%s)\n", s->lexlevel,
5858 cstring_toCharsSafe (tname));
5860 cstring_free (tname);
5862 for (i = 0; i < s->nentries; i++)
5864 cstring us = uentry_unparseFull (s->entries[i]);
5865 fprintf (g_warningstream, "%s\n", cstring_toCharsSafe (us));
5869 if (s->reftable != NULL && s->nentries > 0)
5871 fprintf (g_warningstream, "\t<< Ref table >>\n");
5873 for (i = 0; i < s->nentries; i++)
5875 fprintf (g_warningstream, "\t%s %3d: %d, %d\n", ind, i,
5876 s->reftable[i]->level,
5877 s->reftable[i]->index);
5881 ind[depth * 3 + 1] = ' ';
5885 fprintf (g_warningstream, "<<< end usymtab >>>\n");
5891 usymtab_printTypes ()
5892 /*@globals globtab@*/
5894 usymtab_printAllAux (globtab);
5898 usymtab_printAll (void)
5901 usymtab_printAllAux (utab);
5905 usymtab_printAllAux (usymtab s)
5906 /*@modifies g_warningstream@*/
5910 char *ind = mstring_copy (" ");
5912 printf ("[[[ usymtab ]]]");
5914 while (s != GLOBAL_ENV)
5917 ind[depth * 3 + 1] = '\0';
5919 if (s->env == GLOBAL_ENV)
5923 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5924 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5925 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5929 for (i = looplow; i < s->nentries; i++)
5931 printf ("%s%3d. %s\n", ind, i,
5932 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5937 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5938 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5939 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5941 for (i = 0; i < s->nentries; i++)
5943 printf ("%s%3d %s\n", ind, i,
5944 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5948 ind[depth * 3 + 1] = ' ';
5952 printf ("----------\n");
5956 usymtab_printComplete ()
5961 char *ind = mstring_copy (" ");
5964 while (s != GLOBAL_ENV)
5968 ind[depth * 3 + 1] = '\0';
5971 if (s->env == GLOBAL_ENV)
5975 printf ("level: %d\n", s->lexlevel);
5979 for (i = looplow; i < s->nentries; i++)
5981 printf ("%s%3d %s\n", ind, i,
5982 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5987 printf ("level: %d\n", s->lexlevel);
5988 for (i = 0; i < s->nentries; i++)
5990 printf ("%s%3d %s\n", ind, i,
5991 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5995 ind[depth * 3 + 1] = ' ';
6000 printf ("----------\n");
6005 static /*@only@*/ cstring /*@unused@*/
6006 usymtab_unparseLocalAux (/*@notnull@*/ usymtab s)
6008 cstring c = message ("lexlevel: %d\n", s->lexlevel);
6011 for (i = 0; i < s->nentries; i++)
6013 c = message ("%q\n%q", c, uentry_unparseFull (s->entries[i]));
6016 c = message ("%q\n=========", c);
6020 static cstring /*@unused@*/ /*@only@*/
6021 usymtab_unparseLocalList (/*@notnull@*/ usymtab s)
6023 cstring c = message ("[%d/%s/%s] ", s->lexlevel,
6024 bool_unparse (s->mustBreak),
6025 exitkind_unparse (s->exitCode));
6028 for (i = 0; i < s->nentries; i++)
6030 sRef sr = uentry_getSref (s->entries[i]);
6034 c = message ("%q: %q [%b]", c, uentry_getName (s->entries[i]),
6035 sRef_isStateDefined (sr));
6039 c = message ("%q, %q [%b]", c, uentry_getName (s->entries[i]),
6040 sRef_isStateDefined (sr));
6050 usymtab_printLocal (void)
6056 printf ("lexlevel: %d\n", s->lexlevel);
6058 for (i = 0; i < s->nentries; i++)
6060 printf ("%s\n", cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
6063 while (s->lexlevel > 1)
6068 llassert (usymtab_isDefined (s));
6070 printf ("Params:\n");
6072 for (i = 0; i < s->nentries; i++)
6074 printf ("%d: %s\n", i,
6075 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
6080 static bool checkDistinctExternalName (uentry e)
6081 /*@globals globtab@*/
6082 /*@modifies *g_warningstream@*/
6084 size_t checklen = size_fromInt (context_getValue (FLG_EXTERNALNAMELEN));
6085 bool ignorecase = context_getFlag (FLG_EXTERNALNAMECASEINSENSITIVE);
6086 bool gotone = FALSE;
6087 bool extras = FALSE;
6088 bool hasError = FALSE;
6089 cstring name = uentry_rawName (e);
6090 usymtab st = globtab;
6098 if (uentry_isAnyTag (e))
6100 checklen++; /* the tag marker doesn't count */
6104 usymtab_entries (st, oe)
6106 if (uentry_sameObject (oe, e))
6113 if (cstring_equalCaseInsensitive (uentry_rawName (oe), name))
6122 (FLG_DISTINCTEXTERNALNAMES,
6124 ("External identifier %q is not distinguishable from %q "
6125 "because alphabetical case is ignored",
6127 uentry_getName (oe)),
6128 uentry_whereLast (e)))
6130 uentry_showWhereAny (oe);
6131 uentry_setHasNameError (oe);
6140 if (cstring_equalLenCaseInsensitive (uentry_rawName (oe),
6149 if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6152 (FLG_DISTINCTEXTERNALNAMES,
6155 ("External identifier %q is not distinguishable from %q "
6156 "in the first %d characters (%q)",
6158 uentry_getName (oe),
6159 size_toInt (checklen),
6160 cstring_clip (uentry_getName (e), checklen)),
6162 uentry_whereLast (e)))
6164 uentry_showWhereAny (oe);
6165 uentry_setHasNameError (oe);
6178 (FLG_DISTINCTEXTERNALNAMES,
6180 ("External identifier %q is not distinguishable from %q "
6181 "in the first %d characters because alphabetical case "
6184 uentry_getName (oe),
6185 size_toInt (checklen)),
6186 uentry_whereLast (e)))
6188 uentry_showWhereAny (oe);
6189 uentry_setHasNameError (oe);
6195 else if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6204 (FLG_DISTINCTEXTERNALNAMES,
6207 ("External identifier %q is not distinguishable from %q "
6208 "in the first %d characters (%q)",
6210 uentry_getName (oe),
6211 size_toInt (checklen),
6212 cstring_clip (uentry_getName (e), checklen)),
6214 uentry_whereLast (e)))
6216 uentry_showWhereAny (oe);
6217 uentry_setHasNameError (oe);
6226 } end_usymtab_entries ;
6233 (cstring_makeLiteral ("One or more additional "
6234 "indistinguishable external "
6235 "names not reported"));
6241 static bool checkDistinctInternalName (uentry e)
6243 /*@modifies *g_warningstream@*/
6245 usymtab ttab = utab;
6246 cstring name = uentry_rawName (e);
6247 size_t numchars = size_fromInt (context_getValue (FLG_INTERNALNAMELEN));
6248 bool caseinsensitive = context_getFlag (FLG_INTERNALNAMECASEINSENSITIVE);
6249 bool lookalike = context_getFlag (FLG_INTERNALNAMELOOKALIKE);
6251 if (uentry_isAnyTag (e) && (numchars != 0))
6253 numchars++; /* the tag marker doesn't count */
6256 while (usymtab_isDefined (ttab))
6258 usymtab_entries (ttab, oe)
6260 if (uentry_sameObject (oe, e))
6262 /*@innercontinue@*/ continue;
6265 switch (cstring_genericEqual
6266 (name, uentry_rawName (oe),
6267 numchars, caseinsensitive, lookalike))
6269 case CGE_DISTINCT: /* okay */
6273 if (cstring_equal (name, uentry_rawName (oe)))
6275 ; /* got a shadow error */
6280 (FLG_DISTINCTINTERNALNAMES,
6283 ("Internal identifier %q is not distinguishable from %q "
6284 "in the first %d characters (%q)",
6286 uentry_getName (oe),
6287 size_toInt (numchars),
6288 cstring_clip (uentry_getName (e), numchars)),
6290 uentry_whereLast (e)))
6292 uentry_showWhereAny (oe);
6293 uentry_setHasNameError (oe);
6300 if (numchars == 0 || (cstring_length (name) <= numchars))
6303 (FLG_DISTINCTINTERNALNAMES,
6305 ("Internal identifier %q is not distinguishable from %q "
6306 "without case sensitivity",
6308 uentry_getName (oe)),
6309 uentry_whereLast (e)))
6311 uentry_showWhereAny (oe);
6312 uentry_setHasNameError (oe);
6319 (FLG_DISTINCTINTERNALNAMES,
6321 ("Internal identifier %q is not distinguishable from %q "
6322 "in the first %d characters without case sensitivity",
6324 uentry_getName (oe),
6325 size_toInt (numchars)),
6326 uentry_whereLast (e)))
6328 uentry_showWhereAny (oe);
6329 uentry_setHasNameError (oe);
6337 || (cstring_length (name) <= numchars))
6340 (FLG_DISTINCTINTERNALNAMES,
6342 ("Internal identifier %q is not distinguishable from %q "
6343 "except by lookalike characters",
6345 uentry_getName (oe)),
6346 uentry_whereLast (e)))
6348 uentry_showWhereAny (oe);
6349 uentry_setHasNameError (oe);
6356 (FLG_DISTINCTINTERNALNAMES,
6358 ("Internal identifier %q is not distinguishable from %q "
6359 "in the first %d characters except by lookalike characters",
6361 uentry_getName (oe),
6362 size_toInt (numchars)),
6363 uentry_whereLast (e)))
6365 uentry_showWhereAny (oe);
6366 uentry_setHasNameError (oe);
6371 } end_usymtab_entries ;
6379 void usymtab_checkDistinctName (uentry e, int scope)
6380 /*@globals utab, globtab@*/
6382 bool hasError = FALSE;
6383 fileloc where = uentry_whereLast (e);
6385 if (!fileloc_isPreproc (where) && !fileloc_isBuiltin (where))
6387 if (scope == globScope)
6389 if (context_getFlag (FLG_DISTINCTEXTERNALNAMES))
6391 hasError = checkDistinctExternalName (e);
6395 if (!hasError && context_getFlag (FLG_DISTINCTINTERNALNAMES))
6397 hasError = checkDistinctInternalName (e);
6403 uentry_setHasNameError (e);
6407 /*@exposed@*/ sRef usymtab_lookupGlobalMarker (void) /*@globals utab@*/
6411 ue = usymtab_lookupAux (utab, GLOBAL_MARKER_NAME);
6412 llassert (uentry_isValid (ue));
6414 return uentry_getSref (ue);
6420 ** For debugging only
6424 usymtab_checkAllValid () /*@globals utab@*/
6428 while (tab != GLOBAL_ENV)
6432 for (i = 0; i < utab->nentries; i++)
6434 uentry e = utab->entries[i];
6436 uentry_checkValid (e);
6439 aliasTable_checkValid (tab->aliases);