2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 University of Virginia,
4 ** Massachusetts Institute of Technology
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ** General Public License for more details.
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
20 ** For information on splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
27 ** Lexically scoped symbol table.
29 ** Unlike a normal symbol table, this table splits to reflect branches.
31 ** This is necessary since symbol table entries also reflect
32 ** some state information, like initialization, that may be
33 ** different on different branches.
35 ** For each control structure we split:
37 ** { } - a normal scope (no control) US_NORMAL
39 ** if <pred> { } - US_TBRANCH true branch
40 ** while <pred> { } US_FBRANCH else branch
42 ** switch <pred> { } - US_SWITCH
44 ** case x: - case scope US_CBRANCH
45 ** Should be kept in a separate table, because of
49 # include "splintMacros.nf"
51 # include "structNames.h"
52 # include "exprChecks.h"
53 # include "transferChecks.h"
55 /* Needed to install macros when loading libraries */
58 # include "cpperror.h"
62 ** Keep track of type definitions inside a function.
65 static uentryList functypes = uentryList_undefined;
67 static bool dbgfree = FALSE;
68 static bool dbgload = TRUE;
73 ** Hack to prevent shadow errors from appearing when function parameters
74 ** are entered into a new scope.
77 static bool noshadowerror = FALSE;
80 ** Constraint: static variables can live in 1 or > 2.
82 ** except for tags. All tags must be at the global level.
83 ** Static tags are handled in a kludgey way.
87 ** utab is the universal symbol table
88 ** globtab is the global environment of utab
89 ** oldtab is needed for conversions in dumping (after sorting the table)
91 ** there can be only one usymtab!
94 static /*@checkedstrict@*/ /*@owned@*/ /*@notnull@*/ usymtab utab;
96 /* Reachable environments from from utab */
97 static /*@checkedstrict@*/ /*@notnull@*/ /*@dependent@*/ usymtab globtab;
98 static /*@checkedstrict@*/ /*@dependent@*/ usymtab filetab;
100 /* Used for sorting for dumpage. */
101 static /*@checkedstrict@*/ /*@owned@*/ usymtab oldtab;
103 static int usymtab_lexicalLevel (void) /*@globals utab@*/ ;
104 static bool usymtab_isAltDefinitelyNull (sRef p_s) /*@globals utab@*/ ;
105 static void refTable_free (/*@only@*/ /*@null@*/ refTable p_x, int p_nentries);
106 static ctype usymtab_suFieldsType (uentryList p_f, bool p_isStruct) /*@globals globtab@*/ ;
108 static void usymtab_freeAux (/*@only@*/ usymtab p_u)
109 /*@globals globtab, utab, filetab@*/
112 extern int usymtab_getCurrentDepth (void) /*@globals utab@*/
114 return utab->lexlevel;
118 usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab p_u)
119 /*@globals globtab, utab, filetab@*/ /*@modifies p_u@*/ ;
121 static bool usymtab_isDefinitelyNullAux (sRef p_s) /*@globals utab@*/ ;
122 static /*@only@*/ cstring usymtab_unparseStackTab (usymtab p_t);
123 static /*@exposed@*/ /*@dependent@*/ uentry
124 usymtab_getRefTab (/*@notnull@*/ usymtab p_u, int p_level, usymId p_index);
127 /* These are not used anymore... */
128 static /*@unused@*/ /*@only@*/ cstring
129 usymtab_unparseLocalAux (/*@notnull@*/ usymtab p_s);
130 static /*@unused@*/ /*@only@*/ cstring
131 usymtab_unparseLocalList (/*@notnull@*/ usymtab p_s);
134 static /*@only@*/ cstring usymtab_typeName (/*@notnull@*/ usymtab p_t);
135 static void usymtab_handleParams (void)
136 /*@globals utab, globtab, filetab@*/
137 /*@modifies utab@*/ ;
139 static /*@exposed@*/ /*@dependent@*/ uentry
140 usymtab_addRefEntry (/*@notnull@*/ usymtab p_s, cstring p_k);
141 static /*@exposed@*/ /*@dependent@*/ usymtab
142 usymtab_dropEnv (/*@notnull@*/ usymtab p_s);
143 static /*@exposed@*/ /*@dependent@*/ uentry
144 usymtab_getRefNoisy (/*@notnull@*/ usymtab p_s, int p_level, usymId p_index);
146 static /*@exposed@*/ /*@dependent@*/ uentry
147 usymtab_lookupQuietAux (usymtab p_s, cstring p_k, bool p_noalt);
149 static /*@exposed@*/ /*@dependent@*/ uentry
150 usymtab_lookupQuiet (usymtab p_s, cstring p_k);
152 static /*@exposed@*/ /*@dependent@*/ uentry
153 usymtab_lookupQuietNoAlt (usymtab p_s, cstring p_k);
155 static void usymtab_printAllAux (usymtab p_s) /*@modifies g_warningstream@*/ ;
157 /*@function bool usymtab_indexFound (usymId) @*/
158 # define usymtab_indexFound(u) ((u) != usymId_notfound)
160 static usymId usymtab_getIndex (/*@notnull@*/ usymtab p_s, cstring p_k);
161 static /*@exposed@*/ uentry usymtab_fetchIndex (/*@notnull@*/ usymtab p_s, usymId p_ui);
162 static /*@exposed@*/ uentry usymtab_lookupAux (usymtab p_s, cstring p_k);
164 static /*@exposed@*/ /*@dependent@*/ /*@notnull@*/
165 usymtab usymtab_getFileTab (void) /*@globals filetab@*/ ;
167 static int refTable_lookup (/*@notnull@*/ usymtab p_ut, int p_level, usymId p_index);
168 static bool usymtab_mustBreak (usymtab p_s);
169 static bool usymtab_mustEscape (usymtab p_s);
171 static void recordFunctionType (uentry ue)
173 llassert (uentry_isDatatype (ue) || uentry_isAnyTag (ue)
174 || uentry_isEnumConstant (ue));
175 DPRINTF (("Function type: %s", uentry_unparseFull (ue)));
177 functypes = uentryList_add (functypes, ue);
181 static void clearFunctionTypes (void)
182 /*@modifies globtab@*/
184 uentryList_elements (functypes, el)
186 if (cstring_isDefined (uentry_rawName (el)))
188 if (cstringTable_isDefined (globtab->htable))
190 cstringTable_remove (globtab->htable, uentry_rawName (el));
193 uentry_setName (el, cstring_undefined);
197 llassert (uentry_isValid (el));
198 el->sref = sRef_undefined;
199 /*@noaccess uentry@*/
200 } end_uentryList_elements ;
202 uentryList_clear (functypes);
205 static /*@falsewhennull@*/ bool usymtab_isBranch (usymtab u)
207 return (usymtab_isDefined (u) &&
208 (u->kind == US_TBRANCH || u->kind == US_FBRANCH
209 || u->kind == US_CBRANCH || u->kind == US_SWITCH));
212 static bool usymtab_mustBreak (usymtab s)
214 llassert (s != GLOBAL_ENV);
215 return (s->mustBreak);
218 static bool usymtab_mustEscape (usymtab s)
220 llassert (s != GLOBAL_ENV);
221 return (exitkind_mustEscape (s->exitCode));
224 void usymtab_setMustBreak ()
227 llassert (utab != GLOBAL_ENV);
228 utab->mustBreak = TRUE;
231 void usymtab_setExitCode (exitkind ex)
234 llassert (utab != GLOBAL_ENV);
238 if (exitkind_mustEscape (ex))
240 utab->mustBreak = TRUE;
244 bool usymtab_isAltDefinitelyNullDeep (sRef s)
246 return (sRef_deepPred (usymtab_isAltDefinitelyNull, s));
249 static bool usymtab_isAltDefinitelyNull (sRef s)
257 llassert (utab->env != NULL);
259 /*@-mods@*/ /* These modifications are cancelled. */
260 utab->guards = utab->env->guards;
261 utab->env->guards = t;
264 llassert (usymtab_isDefined (utab));
265 res = usymtab_isDefinitelyNull (s);
268 ** This reports a spurious error. It is okay, because of
269 ** the nesting relationship of usymtab environments.
272 /*@-mods@*/ /* Cancelling modifications. */
273 /*@i1@*/ utab->env->guards = utab->guards;
274 /*@i1@*/ utab->guards = t;
280 static /*@notnull@*/ /*@special@*/ usymtab
281 usymtab_create (uskind kind, /*@keep@*/ usymtab env, bool nextlevel)
283 /*@post:isnull result->htable, result->guards, result->aliases@*/
285 usymtab t = (usymtab) dmalloc (sizeof (*t));
288 t->nspace = CBASESIZE;
289 t->entries = (uentry *) dmalloc (sizeof (*t->entries) * CBASESIZE);
291 /* We only use a reftable for branch-level symbol tables.
294 t->reftable = (nextlevel
296 : (refentry *) dmalloc (sizeof (*t->reftable) * CBASESIZE));
299 t->lexlevel = (env == GLOBAL_ENV ? 0 : env->lexlevel) + (nextlevel ? 1 : 0);
304 t->guards = guardSet_undefined;
305 t->aliases = aliasTable_undefined;
307 t->mustBreak = FALSE;
308 t->exitCode = XK_NEVERESCAPE;
310 DPRINTF (("Create usymtab [%p]", t));
318 static /*@only@*/ /*@notnull@*/ usymtab
319 usymtab_createRoot (void) /*@modifies nothing@*/
321 usymtab u = (usymtab) dmalloc (sizeof (*u));
324 u->nspace = CGLOBBASESIZE;
325 u->entries = (uentry *) dmalloc (sizeof (*u->entries) * CGLOBBASESIZE);
328 u->htable = cstringTable_create (CGLOBHASHSIZE);
331 u->guards = guardSet_new ();
332 u->aliases = aliasTable_new ();
334 u->mustBreak = FALSE;
335 u->exitCode = XK_NEVERESCAPE;
342 usymtab_initMod (void)
343 /*@globals undef utab, undef oldtab, undef globtab, undef filetab @*/
344 /*@modifies utab, globtab, filetab, oldtab @*/
346 utab = usymtab_createRoot ();
348 filetab = usymtab_undefined;
349 oldtab = usymtab_undefined;
353 usymtab_destroyMod (void) /*@modifies utab, globtab, filetab@*/ /*@globals killed utab@*/
355 DPRINTF (("Destroy usymtab [%p]: %d", utab, utab->nentries));
356 usymtab_freeAux (utab);
357 utab = usymtab_undefined;
362 usymtab_initGlobalMarker () /*@globals globtab@*/
364 if (uentry_isValid (usymtab_lookupAux (globtab, GLOBAL_MARKER_NAME)))
366 ; /* Already entered from load table. */
370 usymtab_addGlobalEntry (uentry_makeGlobalMarker ());
375 ** utab should be empty? (requires?)
377 ** Adds bool types to symbol table (these are built in for now)
378 ** Only do this is there is no library!
384 DPRINTF (("Init bool!"));
386 if (context_getFlag (FLG_NOLIB))
388 ctype boolt = ctype_bool;
389 /* evs 2000-07-24: bool is now treated as abstract (always) */
391 uentry boolentry = uentry_makeBoolDatatype (qual_createAbstract ());
392 usymtab_supGlobalEntry (boolentry);
393 context_addBoolAccess ();
396 ** We supply values 0 and 1 for the constants, so things like
397 ** while (TRUE) can be interpreted correctly.
400 usymtab_supGlobalEntry
401 (uentry_makeConstantValue (context_getFalseName (), boolt,
402 fileloc_getBuiltin (), FALSE,
403 multiVal_makeInt (0)));
405 usymtab_supGlobalEntry
406 (uentry_makeConstantValue (context_getTrueName (), boolt,
407 fileloc_getBuiltin (), FALSE,
408 multiVal_makeInt (1)));
417 usymtab_grow (/*@notnull@*/ usymtab s)
420 o_uentry *oldsyms = s->entries;
422 s->nspace = CBASESIZE;
423 s->entries = (uentry *) dmalloc (sizeof (*s->entries)
424 * (s->nentries + s->nspace));
426 for (i = 0; i < s->nentries; i++)
428 s->entries[i] = oldsyms[i];
433 if (s->reftable != NULL)
435 refTable oldRefs = s->reftable;
437 s->reftable = (refentry *) dmalloc (sizeof (*s->reftable)
438 * (s->nentries + CBASESIZE + 1));
440 for (i = 0; i < s->nentries; i++)
442 s->reftable[i] = oldRefs[i];
453 usymtab_addEntryQuiet (/*@notnull@*/ usymtab s, /*@keep@*/ uentry e)
455 if (!(s->lexlevel > fileScope || !sRef_modInFunction ()))
457 if (uentry_isDatatype (e)
458 || uentry_isFunction (e)
459 || uentry_isAnyTag (e)
460 || uentry_isEnumConstant (e)
461 || context_inMacro ())
464 ** Not a bug. Code like,
465 ** int f (void) { typedef int tint; ... }
469 /* was nothing here! */
470 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
475 (cstring_makeLiteral ("Declaration outside function scope"));
477 llcontbug (message ("usymtab_addEntryQuiet: inconsistent state "
478 "(lexlevel = %d, modFunction = %s) adding: %q",
479 s->lexlevel, bool_unparse (sRef_modInFunction ()),
480 uentry_unparse (e)));
481 sRef_setGlobalScope ();
482 /* make sure the sRef is not bashed! */
483 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
493 s->entries[s->nentries] = e;
496 if (s == globtab || s == filetab)
498 if (!fileloc_isLib (g_currentloc))
500 uentry_tallyAnnots (e, AN_UNKNOWN);
505 if (cstringTable_isDefined (s->htable))
507 cstringTable_insert (s->htable, cstring_copy (uentry_rawName (e)), s->nentries);
513 static /*@observer@*/ uentry /*@alt void@*/
514 usymtab_addEntryBase (/*@notnull@*/ usymtab s, /*@only@*/ uentry e)
517 ** In theory, we shouldn't need this test because it this is
518 ** only called when a library is being read, and it shouldn't
519 ** ever have a duplicate entry. In practice, its safer to
520 ** leave it in, though.
525 if (uentry_isValid (old = usymtab_lookupQuiet (s, uentry_rawName (e))))
527 DPRINTF (("Duplicate entry: %s", uentry_unparse (e)));
528 uentry_free (e); /* duplicate */
533 usymId thisentry = usymId_fromInt (s->nentries);
535 if (uentry_isVar (e))
538 (e, sRef_makeCvar (globScope, thisentry,
540 stateInfo_makeLoc (uentry_whereLast (e), SA_DECLARED)));
543 usymtab_addEntryQuiet (s, e);
549 static /*@observer@*/ uentry /*@alt void@*/
550 usymtab_addEntryAlways (/*@notnull@*/ usymtab s, /*@only@*/ uentry e)
553 ** In theory, we shouldn't need this test because it this is
554 ** only called when a library is being read, and it shouldn't
555 ** ever have a duplicate entry. In practice, its safer to
556 ** leave it in, though.
560 usymId thisentry = usymId_fromInt (s->nentries);
562 if (uentry_isValid (old = usymtab_lookupQuiet (s, uentry_rawName (e))))
565 (message ("Duplicate entry in load library: %s. "
566 "Old entry: %q. New entry: %q",
568 uentry_unparseFull (old),
569 uentry_unparseFull (e)));
571 uentry_setName (e, message ("__x_%s", uentry_rawName (e)));
572 /* This shouldn't happen...unless the library is bad! */
576 if (uentry_isVar (e) && !uentry_isGlobalMarker (e))
579 (e, sRef_makeCvar (globScope, thisentry,
581 stateInfo_makeLoc (uentry_whereLast (e), SA_DECLARED)));
584 usymtab_addEntryQuiet (s, e);
589 usymtab_addEntryAux (/*@notnull@*/ usymtab st, /*@keep@*/ uentry e, bool isSref)
590 /*@globals globtab@*/
593 usymId thisentry = usymId_fromInt (st->nentries);
595 llassert (!uentry_isElipsisMarker (e));
599 ** llassert (usymtab_lookupSafe (uentry_rawName (e)) == uentry_undefined);
602 llassertprint (uentry_isAnyTag (e) ? st == globtab : TRUE,
603 ("non-global tag: %s / %d", uentry_unparseFull (e), st->lexlevel));
605 if (st->lexlevel == fileScope
606 && (!(uentry_isStatic (e)) || uentry_isAnyTag (e)))
613 ctype ct = uentry_getType (e);
615 if (uentry_isFunction (e) && ctype_isFunction (ct))
617 ct = ctype_getReturnType (ct);
620 if (uentry_isStatic (e))
622 sRef sr = sRef_makeCvar (st->lexlevel, thisentry, ct,
623 stateInfo_makeLoc (uentry_whereLast (e), SA_DECLARED));
625 if (sRef_isStack (sr) || sRef_isLocalState (sr))
627 sRef_setAliasKind (sr, AK_STATIC, uentry_whereLast (e));
628 sRef_setDefined (sr, uentry_whereLast (e));
631 uentry_setSref (e, sr);
636 (e, sRef_makeCvar (st->lexlevel, thisentry, ct,
637 stateInfo_makeLoc (uentry_whereLast (e), SA_DECLARED)));
641 if (uentry_isDatatype (e))
643 uentry_setDatatype (e, typeId_fromUsymId (thisentry));
646 if (uentry_isFunction (e))
648 ctype ct = uentry_getType (e);
650 if (ctype_isFunction (ct)
651 && uentryList_isMissingParams (ctype_argsFunction (ct)))
653 if (uentry_isDeclared (e))
657 message ("Function %q declared without parameter list",
659 uentry_whereDeclared (e));
665 message ("Function %q specified without parameter list",
667 uentry_whereSpecified (e));
672 if (st == globtab && !uentry_isSpecified (e))
674 exprChecks_checkExport (e);
677 uentry_checkName (e);
679 usymtab_addEntryQuiet (st, e);
680 DPRINTF (("Adding entry: [%p] %s", e, uentry_unparseFull (e)));
685 usymtab_addEntry (uentry e)
686 /*@globals utab, globtab@*/
687 /*@modifies utab, e@*/
689 llassertprint (!usymtab_exists (uentry_rawName (e)),
690 ("Entry already exists: %s", uentry_unparse (e)));
692 return usymtab_addEntryAux (utab, e, FALSE);
696 usymtab_addGlobalEntry (uentry e)
697 /*@modifies globtab, e@*/
699 DPRINTF (("Add global: %s / %s", uentry_unparse (e), bool_unparse (uentry_isForward (e))));
701 (void) usymtab_addEntryAux (globtab, e, FALSE);
705 ** supercede and replace entry use elements of entries array, and
706 ** assign an element to a new value, and then free the old value.
707 ** Need -deparrays to avoid errors for this.
713 usymtab_supEntryAux (/*@notnull@*/ usymtab st,
714 /*@only@*/ uentry e, bool isSref)
715 /*@globals globtab, filetab@*/
716 /*@modifies st, globtab, e@*/
718 cstring ename = uentry_rawName (e);
719 bool staticEntry = FALSE;
722 DPRINTF (("Sup entry aux: %s", uentry_unparseFull (e)));
724 /* static tags in global scope */
725 if (st->lexlevel == fileScope
726 && (!(uentry_isStatic (e)) || uentry_isAnyTag (e)))
728 eindex = usymtab_getIndex (st, ename);
730 if (usymtab_indexFound (eindex))
732 uentry ce = st->entries[eindex];
736 message ("%s %q shadows static declaration",
737 ekind_capName (uentry_getKind (e)),
739 uentry_whereDeclared (e)))
741 uentry_showWhereLast (ce);
744 if (eindex == usymId_fromInt (st->nentries - 1))
750 st->entries[eindex] = st->entries[st->nentries - 1];
753 if (cstringTable_isDefined (st->htable))
755 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
756 cstring_copy (uentry_rawName (e)));
766 if (uentry_isStatic (e)) {
767 if (uentry_isFunction (e)) {
769 ** Static function declarations are at the file level,
770 ** even if they are in a deeper scope.
773 st = usymtab_getFileTab ();
776 if (!uentry_isAnyTag (e) && st == globtab)
778 st = usymtab_getFileTab ();
780 DPRINTF (("Static entry!"));
785 eindex = usymtab_getIndex (st, ename);
787 if (usymtab_indexFound (eindex))
789 uentry ce = st->entries[eindex];
791 DPRINTF (("Found entry: %s", uentry_unparse (ce)));
793 if (uentry_isPriv (ce)
794 /* || (fileloc_isImport (uentry_whereSpecified (ce))) */
795 || (uentry_isStatic (ce)
796 && uentry_isAnyTag (ce)
797 && (uentry_isDeclared (ce)
798 && !fileloc_sameFile (uentry_whereDefined (ce),
799 uentry_whereDefined (e)))))
803 ** if overloading import should do some checks!
806 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
808 DPRINTF (("Overloading!"));
810 st->entries[eindex] = e;
812 if (uentry_isDatatype (e))
814 uentry_setDatatype (e, typeId_fromUsymId (eindex));
817 if (st == globtab && !uentry_isSpecified (e))
819 exprChecks_checkExport (e);
822 if (cstringTable_isDefined (st->htable))
824 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
825 cstring_copy (uentry_rawName (e)));
831 else if (uentry_isSpecified (ce))
833 if (uentry_isSpecified (e))
835 DPRINTF (("Here we are: %s", uentry_unparseFull (e)));
837 if (fileloc_isImport (uentry_whereSpecified (ce)))
839 if (cstringTable_isDefined (st->htable))
841 cstringTable_replaceKey (st->htable,
843 cstring_copy (uentry_rawName (e)));
847 st->entries[eindex] = e;
850 if (uentry_isDatatype (e)) uentry_setDatatype (e, typeId_fromUsymId (eindex));
854 if (fileloc_isImport (uentry_whereSpecified (e)))
860 /* Respecification errors already reported */
861 DPRINTF (("Respecification: %s / %s",
862 fileloc_unparse (uentry_whereSpecified (e)),
863 bool_unparse (fileloc_isSpec (uentry_whereSpecified (e)))));
865 if (uentry_isDatatype (e))
867 uentry_setDatatype (e, typeId_fromUsymId (eindex));
870 if (cstringTable_isDefined (st->htable))
872 cstringTable_replaceKey (st->htable,
874 cstring_copy (uentry_rawName (e)));
877 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
879 st->entries[eindex] = e;
884 else /* e not specified */
886 DPRINTF (("Merging..."));
888 if (uentry_isDeclared (ce))
891 No - this can happen for internal typedefs
892 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
895 DPRINTF (("Merge defn"));
896 uentry_mergeDefinition (ce, e);
901 No - this can happen for internal typedefs
902 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
905 DPRINTF (("Merge entries..."));
906 uentry_mergeEntries (ce, e);
907 DPRINTF (("After: %s", uentry_unparseFull (ce)));
911 else /* ce not specified */
913 if (!(st->lexlevel > fileScope || !sRef_modInFunction ()))
915 if (uentry_isDatatype (e) || uentry_isAnyTag (e)
916 || uentry_isEnumConstant (e)
917 || uentry_isStatic (e)) /* bug fix from Brian St. Pierre */
920 ** Not a bug. Code like,
921 ** int f (void) { typedef int tint; ... }
927 llcontbug (message ("usymtab_supEntryAux: inconsistent state "
928 "(lexlevel = %d, modFunction = %s) adding: %q",
929 st->lexlevel, bool_unparse (sRef_modInFunction ()),
930 uentry_unparse (e)));
932 if (sRef_modInFunction ())
934 /* make sure the sRef is not bashed! */
935 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
940 DPRINTF (("Merge.."));
941 uentry_mergeDefinition (ce, e);
946 ctype ct = uentry_getType (ce);
948 if (uentry_isFunction (ce) && ctype_isFunction (ct))
950 ct = ctype_getReturnType (ct);
954 (ce, sRef_makeCvar (st->lexlevel, eindex, ct,
955 stateInfo_makeLoc (uentry_whereLast (ce), SA_DECLARED)));
958 else /* no previous entry */
962 if (st->lexlevel == globScope
963 && !uentry_isStatic (e)
964 && !uentry_isExtern (e)
965 && usymtab_isDefined (filetab))
968 ** check if there is a static entry: (i.e.,
975 eindex = usymtab_getIndex (filetab, ename);
977 if (usymtab_indexFound (eindex))
979 uentry ce = filetab->entries[eindex];
981 uentry_setStatic (e);
982 uentry_mergeDefinition (ce, e);
988 outer = usymtab_lookupQuiet (st->env, ename);
990 DPRINTF (("New : [%p] %s", e, uentry_unparseFull (e)));
991 DPRINTF (("Outer: [%p] %s", outer, uentry_unparseFull (outer)));
994 ** no previous definition, add the new one
998 && uentry_isValid (outer)
999 && !(uentry_isYield (e) || uentry_isYield (outer))
1000 && fileloc_isDefined (uentry_whereLast (e))
1001 && !fileloc_isXHFile (uentry_whereLast (e))
1002 && fileloc_isDefined (uentry_whereLast (outer))
1003 && !fileloc_isXHFile (uentry_whereLast (outer)))
1005 if (!uentry_sameKind (outer, e))
1011 if (ctype_isUnknown (uentry_getType (outer))
1012 || uentry_isForward (outer))
1020 message ("%s %q shadows outer declaration",
1021 ekind_capName (uentry_getKind (e)),
1022 uentry_getName (e)),
1023 uentry_whereLast (e)))
1025 uentry_showWhereLast (outer);
1031 if (st == globtab && context_getFlag (FLG_NEWDECL))
1035 message ("New declaration: %q", uentry_getName (e)),
1036 uentry_whereLast (e));
1039 eindex = usymtab_addEntryAux (st, e, isSref);
1043 return (staticEntry ? usymId_invalid : eindex);
1047 usymtab_replaceEntryAux (/*@notnull@*/ usymtab st, /*@only@*/ uentry e)
1048 /*@globals globtab@*/ /*@modifies st, e@*/
1050 cstring ename = uentry_rawName (e);
1053 /* static tags in global scope */
1054 eindex = usymtab_getIndex (st, ename);
1056 if (usymtab_indexFound (eindex))
1058 uentry ce = st->entries[eindex];
1060 if (cstringTable_isDefined (st->htable))
1062 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
1063 cstring_copy (uentry_rawName (e)));
1067 st->entries[eindex] = e;
1071 eindex = usymtab_addEntryAux (st, e, FALSE);
1077 void usymtab_supEntry (uentry e)
1078 /*@globals utab, filetab, globtab@*/
1079 /*@modifies utab, globtab, e@*/
1081 (void) usymtab_supEntryAux (utab, e, FALSE);
1085 ** this should be lots more efficient!
1088 static /*@exposed@*/ uentry
1089 usymtab_supEntryReturnAux (/*@notnull@*/ usymtab tab,
1090 /*@only@*/ uentry e, bool isref)
1091 /*@globals globtab, filetab@*/
1092 /*@modifies tab, globtab, e@*/
1094 cstring rawName = cstring_copy (uentry_rawName (e));
1095 bool stat = (tab == globtab) && uentry_isStatic (e);
1098 (void) usymtab_supEntryAux (tab, e, isref);
1102 ret = usymtab_lookupAux (filetab, rawName);
1106 ret = usymtab_lookupAux (tab, rawName);
1108 if (uentry_isInvalid (ret) && usymtab_isDefined (filetab))
1110 ret = usymtab_lookupAux (filetab, rawName);
1114 cstring_free (rawName);
1118 /*@dependent@*/ /*@exposed@*/ uentry
1119 usymtab_supEntryReturn (/*@only@*/ uentry e)
1120 /*@globals utab, filetab, globtab@*/
1121 /*@modifies utab, globtab, e@*/
1123 return (usymtab_supEntryReturnAux (utab, e, FALSE));
1126 /*@dependent@*/ /*@exposed@*/ uentry
1127 usymtab_supEntrySrefReturn (/*@only@*/ uentry e)
1128 /*@globals utab, globtab, filetab@*/
1129 /*@modifies utab, globtab, e@*/
1131 return (usymtab_supEntryReturnAux (utab, e, TRUE));
1134 /*@dependent@*/ /*@exposed@*/ uentry
1135 usymtab_supGlobalEntryReturn (uentry e)
1136 /*@globals globtab, filetab@*/
1137 /*@modifies globtab, e@*/
1141 ret = usymtab_supEntryReturnAux (globtab, e, FALSE);
1144 ** We need to keep track of internal function declarations, so
1145 ** we can remove them from the symbol table after exiting this
1146 ** function. This is a bit bogus, of course.
1149 if (sRef_modInFunction ())
1151 recordFunctionType (ret);
1158 usymtab_supTypeEntry (/*@only@*/ uentry e)
1159 /*@globals globtab, filetab@*/
1160 /*@modifies globtab, e@*/
1165 if (uentry_isAbstractDatatype (e))
1167 typeId tid = usymtab_supAbstractTypeEntry (e, FALSE);
1168 ret = ctype_createAbstract (tid);
1169 uid = typeId_toUsymId (tid);
1173 uid = usymtab_supEntryAux (globtab, e, FALSE);
1174 ret = ctype_createUser (typeId_fromUsymId (uid));
1177 if (sRef_modInFunction ())
1179 recordFunctionType (globtab->entries[uid]);
1186 usymtab_supReturnTypeEntry (/*@only@*/ uentry e)
1187 /*@globals globtab, filetab@*/
1188 /*@modifies globtab@*/
1192 DPRINTF (("Abstract? %s", uentry_unparseFull (e)));
1194 if (uentry_isAbstractDatatype (e))
1196 uid = typeId_toUsymId (usymtab_supAbstractTypeEntry (e, FALSE));
1198 else if (uentry_isMaybeAbstract (e) && context_getFlag (FLG_IMPABSTRACT))
1200 bool maybeabs = TRUE;
1201 cstring sname = uentry_getName (e);
1202 uentry ue = usymtab_lookupGlobSafe (sname);
1203 cstring_free (sname);
1205 if (uentry_isValid (ue))
1207 DPRINTF (("Lookup: %s", uentry_unparseFull (ue)));
1209 if (uentry_isDatatype (ue))
1211 if (uentry_isMaybeAbstract (ue))
1222 DPRINTF (("Not datatype!"));
1229 typeId tid = usymtab_supAbstractTypeEntry (e, FALSE);
1230 ux = usymtab_getTypeEntry (tid);
1231 uentry_setAbstract (ux);
1232 uid = typeId_toUsymId (tid);
1236 uid = usymtab_supEntryAux (globtab, e, FALSE);
1237 e = usymtab_getTypeEntry (typeId_fromUsymId (uid));
1239 if (uentry_isMaybeAbstract (e))
1241 uentry_setConcrete (e);
1247 uid = usymtab_supEntryAux (globtab, e, FALSE);
1248 e = usymtab_getTypeEntry (typeId_fromUsymId (uid));
1250 /*? evans 2002-12-16 removed this? it doesn't make sense
1251 if (uentry_isMaybeAbstract (e))
1253 uentry_setConcrete (e);
1258 if (sRef_modInFunction ())
1260 recordFunctionType (globtab->entries[uid]);
1263 return (globtab->entries[uid]);
1267 usymtab_supAbstractTypeEntry (/*@only@*/ uentry e, bool dodef)
1268 /*@globals globtab, filetab@*/
1269 /*@modifies globtab, e@*/
1274 uid = typeId_fromUsymId (usymtab_supEntryAux (globtab, e, FALSE));
1275 ue = usymtab_getTypeEntry (uid);
1279 uentry_setDatatype (ue, uid);
1282 if (context_getFlag (FLG_ACCESSMODULE)) /* was accessfile */
1284 context_addFileAccessType (uid);
1287 if (sRef_modInFunction ())
1289 recordFunctionType (globtab->entries[uid]);
1296 usymtab_supExposedTypeEntry (/*@only@*/ uentry e, bool dodef)
1297 /*@globals globtab, filetab@*/
1298 /*@modifies globtab, e@*/
1302 uid = typeId_fromUsymId (usymtab_supEntryAux (globtab, e, FALSE));
1306 uentry ue = usymtab_getTypeEntry (uid);
1308 uentry_setDatatype (ue, uid);
1311 if (sRef_modInFunction ())
1313 recordFunctionType (globtab->entries[uid]);
1320 usymtab_supForwardTypeEntry (/*@only@*/ uentry e)
1321 /*@globals globtab, filetab@*/
1322 /*@modifies globtab, e@*/
1324 typeId uid = typeId_fromUsymId (usymtab_supEntryAux (globtab, e, FALSE));
1325 uentry ue = usymtab_getTypeEntry (uid);
1327 uentry_setDatatype (ue, uid);
1329 if (sRef_modInFunction ())
1331 recordFunctionType (globtab->entries[uid]);
1334 return (uentry_getAbstractType (ue));
1338 usymtab_supEntrySref (uentry e)
1339 /*@globals utab, globtab, filetab@*/
1340 /*@modifies utab, globtab, e@*/
1342 sRef old = uentry_getSref (e);
1344 if (sRef_isType (old))
1346 uentry ue = usymtab_supEntryReturnAux (utab, e, TRUE);
1349 if (uentry_isValid (ue))
1351 sRef uref = uentry_getSref (ue);
1353 sRef_mergeStateQuiet (uref, old);
1354 sRef_clearDerived (uref);
1356 /*@noaccess uentry@*/
1358 else if (sRef_isKnown (old))
1360 usymtab_supEntry (e);
1364 (void) usymtab_supEntryAux (utab, e, TRUE);
1368 void usymtab_supGlobalEntry (/*@only@*/ uentry e)
1369 /*@globals globtab, filetab@*/
1370 /*@modifies globtab, filetab, e@*/
1374 DPRINTF (("Sup global entry: %s", uentry_unparse (e)));
1376 uid = usymtab_supEntryAux (globtab, e, FALSE);
1378 if (sRef_modInFunction ())
1380 recordFunctionType (globtab->entries[uid]);
1385 usymtab_supReturnFileEntry (/*@only@*/ uentry e)
1386 /*@globals filetab, globtab@*/
1387 /*@modifies filetab, globtab, e@*/
1389 llassert (filetab != usymtab_undefined);
1390 DPRINTF (("File entry: %s", uentry_unparse (e)));
1391 return (usymtab_supEntryReturnAux (filetab, e, FALSE));
1399 usymtab_inDeepScope () /*@globals utab@*/
1401 return (utab->lexlevel > paramsScope);
1405 usymtab_getIndex (/*@notnull@*/ usymtab s, cstring k)
1409 DPRINTF (("Lookup %s", k));
1411 if (cstringTable_isDefined (s->htable))
1413 i = cstringTable_lookup (s->htable, k);
1414 return usymId_fromInt (i);
1418 for (i = 0; i < s->nentries; i++)
1420 uentry current = s->entries[i];
1422 DPRINTF (("Check %d: %s", i, uentry_rawName (current)));
1424 if (!uentry_isUndefined (current)
1425 && cstring_equal (uentry_rawName (current), k))
1427 return usymId_fromInt (i);
1431 return usymId_notfound;
1436 usymtab_fetchIndex (/*@notnull@*/ usymtab s, usymId ui)
1438 int i = usymId_toInt (ui);
1439 llassert (i >= 0 && i < s->nentries);
1440 return (s->entries[i]);
1444 usymtab_getTypeId (cstring k) /*@globals globtab@*/
1446 usymId uid = usymtab_getIndex (globtab, k);
1448 if (!usymtab_indexFound (uid)
1449 || !(uentry_isDatatype (usymtab_getTypeEntry (typeId_fromUsymId (uid)))))
1452 return typeId_invalid;
1456 return typeId_fromUsymId (uid);
1460 /*@dependent@*/ uentry
1461 usymtab_lookupStructTag (cstring k)
1463 cstring sname = makeStruct (k);
1464 uentry ue = usymtab_lookupGlob (sname);
1466 cstring_free (sname);
1470 /*@dependent@*/ uentry
1471 usymtab_lookupUnionTag (cstring k)
1473 cstring uname = makeUnion (k);
1474 uentry res = usymtab_lookupGlob (uname);
1476 cstring_free (uname);
1480 /*@dependent@*/ uentry
1481 usymtab_lookupEnumTag (cstring k)
1483 cstring ename = makeEnum (k);
1484 uentry res = usymtab_lookupGlob (ename);
1486 cstring_free (ename);
1491 usymtab_getId (cstring k) /*@globals globtab@*/
1493 usymId uid = usymtab_getIndex (globtab, k);
1496 if (!usymtab_indexFound (uid))
1498 return usymId_invalid;
1501 ue = usymtab_getGlobalEntry (uid);
1503 if (uentry_isPriv (ue))
1505 return usymId_invalid;
1511 static /*@exposed@*/ uentry
1512 usymtab_getEntryAux (/*@notnull@*/ usymtab s, usymId uid)
1514 llassert (uid != usymId_invalid);
1516 if (uid < 0 || uid >= usymId_fromInt (s->nentries))
1518 llcontbug (message ("usymtab_getEntry: out of range: level = %d [%d]",
1520 return uentry_undefined;
1523 llassertprint (uentry_isValid (s->entries[uid]),
1524 ("entry undefined: %d", uid));
1526 return s->entries[uid];
1529 /*@dependent@*/ /*@observer@*/ uentry
1530 usymtab_getGlobalEntry (usymId uid)
1531 /*@globals utab, globtab@*/
1533 if (dbgfree) return (uentry_undefined);
1535 if (utab->lexlevel > paramsScope)
1537 /* need to do this the awkward way, since it could be in conditional scope */
1538 return (usymtab_lookupSafe (uentry_rawName (globtab->entries[uid])));
1542 return (globtab->entries[uid]);
1546 /*@dependent@*/ /*@exposed@*/ uentry usymtab_getTypeEntry (typeId uid)
1547 /*@globals globtab@*/
1551 if (uid >= 0 && uid < typeId_fromInt (globtab->nentries))
1553 return (globtab->entries[uid]);
1557 return (uentry_undefined);
1562 llassert (uid >= 0 && uid < typeId_fromInt (globtab->nentries));
1563 return (globtab->entries[uid]);
1571 /*@dependent@*/ /*@exposed@*/ uentry usymtab_getTypeEntrySafe (typeId uid)
1572 /*@globals globtab@*/
1574 if (uid < 0 || uid >= typeId_fromInt (globtab->nentries))
1576 return uentry_undefined;
1579 return (globtab->entries[uid]);
1582 bool usymtab_isBoolType (typeId uid)
1583 /*@globals globtab@*/
1585 llassert (uid >= 0 && uid < typeId_fromInt (globtab->nentries));
1587 return (cstring_equal (uentry_rawName (globtab->entries[uid]),
1588 context_getBoolName ()));
1591 cstring usymtab_getTypeEntryName (typeId uid)
1592 /*@globals globtab@*/
1598 return (cstring_makeLiteral ("<freetype>"));
1601 ue = usymtab_getTypeEntry (uid);
1603 if (dbgload && !uentry_isValid (ue))
1605 return (message ("<missing type: %d>", uid));
1608 llassertprint (uentry_isValid (ue), ("type undefined: %d", uid));
1610 return (uentry_getName (ue));
1614 /*@unused@*/ static void
1615 usymtab_rehash (/*@notnull@*/ usymtab s)
1619 if (cstringTable_isDefined (s->htable))
1621 cstringTable_free (s->htable);
1624 s->htable = cstringTable_create (LLAHSHSIZE);
1626 for (i = 0; i < s->nentries; i++)
1628 cstringTable_insert (s->htable, cstring_copy (uentry_rawName (s->entries[i])), i);
1634 ** superficial copy of usymtab
1636 ** DO copy spec entries
1639 static /*@only@*/ /*@notnull@*/ usymtab
1640 usymtab_shallowCopy (/*@notnull@*/ usymtab s) /*@*/
1642 usymtab copytab = usymtab_createRoot ();
1645 for (i = 0; i < s->nentries; i++)
1647 usymtab_addEntryBase (copytab, s->entries[i]);
1654 usymtab_shallowFree (/*@only@*/ /*@notnull@*/ usymtab s)
1656 aliasTable_free (s->aliases);
1657 refTable_free (s->reftable, s->nentries);
1659 /*@-compdestroy@*/ sfree (s); /*@=compdestroy@*/
1662 usymId usymtab_convertTypeId (typeId uid)
1664 return usymtab_convertId (typeId_toUsymId (uid));
1668 ** usymtab_convertId: converts usymId from old table to sorted one
1671 usymId usymtab_convertId (usymId uid)
1672 /*@globals oldtab, utab@*/
1678 llassert (usymtab_isDefined (oldtab));
1680 ue = usymtab_getEntryAux (oldtab, uid);
1682 llassertprint (uentry_isValid (ue), ("convertId: undefined: %d", uid));
1684 name = uentry_rawName (ue);
1686 ret = usymtab_getIndex (utab, name);
1687 llassert (ret == uid); /*! for now, no rehash! */
1688 DPRINTF (("Convert: %s [%d] -> %s [%d]",
1689 uentry_unparse (ue), uid,
1690 uentry_unparse (utab->entries[ret]), ret));
1692 llassertprint (ret != usymId_invalid, ("convertId: return is invalid"));
1698 usymtab_prepareDump (void)
1699 /*@globals oldtab, utab@*/
1700 /*@modifies oldtab, utab@*/
1702 llassert (usymtab_inGlobalScope ());
1703 llassert (oldtab == usymtab_undefined);
1706 DPRINTF (("Preparing to dump:"));
1707 usymtab_printAll ();
1710 oldtab = usymtab_shallowCopy (utab);
1713 ** alpha compare - make sure order is same on different platforms
1714 ** error messages appear in same order
1718 qsort (utab->entries, (size_t)utab->nentries,
1719 sizeof (*utab->entries),
1720 (int (*)(const void *, const void *)) uentry_xcomparealpha);
1722 usymtab_rehash (utab);
1726 DPRINTF (("After rehash:"));
1727 usymtab_printAll ();
1731 void usymtab_dump (FILE *fout)
1732 /*@globals utab, oldtab@*/
1735 bool neednl = FALSE;
1736 uentry lastentry = uentry_undefined;
1737 ekind lastekind = KINVALID;
1741 ** must call prepareDump first
1744 llassert (oldtab != usymtab_undefined);
1746 for (i = 0; i < utab->nentries; i++)
1748 uentry thisentry = utab->entries[i];
1749 ekind thisekind = uentry_getKind (thisentry);
1751 if (!uentry_hasRealName (thisentry))
1753 llassert (uentry_isGlobalMarker (thisentry));
1757 check (fputc ('\n', fout) == (int) '\n');
1760 fprintf (fout, "*%d (GlobalMarker)\n", KGLOBALMARKER);
1761 lastekind = KINVALID;
1767 if (thisekind != lastekind)
1771 check (fputc ('\n', fout) == (int) '\n');
1775 lastentry = uentry_undefined;
1776 fprintf (fout, "*%d (%s)\n", ekind_toInt (thisekind),
1777 cstring_toCharsSafe (ekind_capName (thisekind)));
1778 lastekind = thisekind;
1783 ** evans - 2001-02-18 - added the - 48 fudge factor...
1784 ** extra characters dumped, but I haven't counded them carefully...
1787 if (uentry_isInvalid (lastentry) || !uentry_equiv (lastentry, thisentry)
1788 || (linelen > (MAX_DUMP_LINE_LENGTH - (2 * MAX_NAME_LENGTH) - 48)))
1792 DPRINTF (("Dumping entry: %d", i));
1793 cdump = message ("^%d %q", i, uentry_dump (thisentry));
1794 /* was: cdump = uentry_dump (thisentry)); */
1796 lastentry = thisentry;
1799 check (fputc ('\n', fout) == (int) '\n');
1803 linelen += cstring_length (cdump);
1805 /* no new line here! */
1806 if (cstring_length (cdump) > 0)
1808 check (fputs (cstring_toCharsSafe (cdump), fout) != EOF);
1811 cstring_free (cdump);
1816 cstring cdump = uentry_rawName (thisentry);
1817 DPRINTF (("Raw name: %s", cdump));
1818 linelen += (cstring_length (cdump) + 1);
1819 fprintf (fout, "#%s", cstring_toCharsSafe (cdump));
1826 check (fputc ('\n', fout) == (int) '\n');
1829 lastekind = KINVALID;
1831 fprintf(fout, ";; Library constraints\n");
1833 /*drl July 27 added this so that libraries without
1834 buffer constraints would be handled correctly.
1835 I'm trying to do this without breaking older libraries.
1837 Splint should still be able to handle libraries without this message.
1841 fprintf(fout, "start_Buffer_Constraints\n");
1843 for (i = 0; i < utab->nentries; i++)
1845 uentry thisentry = utab->entries[i];
1847 if (uentry_isFunction (thisentry) )
1849 constraintList preconditions;
1850 constraintList postconditions;
1852 preconditions = uentry_getFcnPreconditions (thisentry);
1853 postconditions = uentry_getFcnPostconditions (thisentry);
1855 if ( constraintList_isDefined(preconditions) ||
1856 constraintList_isDefined(postconditions) )
1858 fprintf(fout,"%s\n", cstring_toCharsSafe (uentry_rawName(thisentry) ) );
1859 if (constraintList_isDefined(preconditions) )
1861 fprintf(fout,"pre:\n");
1862 constraintList_dump(preconditions, fout);
1863 fprintf (fout, ";; end precondition constraints\n" );
1864 constraintList_free(preconditions);
1868 fprintf(fout,"pre:EMPTY\n");
1870 if (constraintList_isDefined(postconditions) )
1872 fprintf(fout,"post:\n");
1873 constraintList_dump(postconditions, fout);
1874 fprintf (fout, ";; end precondition constraints\n" );
1875 constraintList_free(postconditions);
1879 fprintf(fout,"post:EMPTY\n");
1888 void usymtab_load (FILE *f)
1889 /*@globals utab, globtab@*/
1890 /*@modifies utab, *f@*/
1892 char *s = mstring_create (MAX_DUMP_LINE_LENGTH);
1894 ekind kind = KINVALID;
1895 fileloc loc = g_currentloc;
1901 llassert (utab == globtab);
1902 llassert (utab->nentries == 0);
1904 while (((s = reader_readLine (f, s, MAX_DUMP_LINE_LENGTH)) != NULL)
1907 /* ignore ; comments */ ;
1910 while (s != NULL && *s != ';')
1918 ek = reader_getInt (&s);
1920 if (ek == KGLOBALMARKER)
1922 uentry lue = uentry_makeGlobalMarker ();
1923 DPRINTF (("Adding global marker: %s", uentry_unparseFull (lue)));
1924 usymtab_addEntryAlways (utab, lue);
1930 kind = ekind_fromInt (ek);
1938 (cstring_makeLiteral
1939 ("Library is in obsolete format. Use splint +whichlib "
1940 "to see which library is being loaded."));
1943 if (reader_optCheckChar (&s, '^'))
1945 index = reader_getInt (&s);
1952 llassert (kind != KINVALID);
1953 ue = uentry_undump (kind, loc, &s);
1955 llassert (utab->nentries == index || index == -1);
1957 if (uentry_isValid (ue))
1959 int lastindex = utab->nentries;
1960 ue = usymtab_addEntryAlways (utab, ue);
1964 if (uentry_isConstant (ue)) /*@i23! isPreProcessorMacro */
1966 cstring uname = uentry_getName (ue);
1968 /* Also check its a macro... */
1969 DPRINTF (("Installing: %s", uname));
1971 cpphash_installMacro
1972 (mstring_copy (cstring_toCharsSafe (uname)),
1973 cstring_length (uname),
1974 cpplib_createDefinition (message ("%s 255", uname),
1977 cpphash_hashCode (cstring_toCharsSafe (uname),
1978 cstring_length (uname),
1981 DPRINTF (("After install: %s", uname));
1985 if (utab->nentries != lastindex + 1)
1987 DPRINTF (("No add: %s", uentry_unparseFull (ue)));
1995 ** now, any other names are the same uentry
1998 while (*(s++) == '#')
2000 cstring name = cstring_fromCharsO (reader_getWord (&s));
2001 uentry nue = uentry_nameCopy (name, ue);
2003 DPRINTF (("Name copy: %s", uentry_unparseFull (nue)));
2007 usymtab_addEntryAlways (utab, nue);
2010 while ((c = *s) != '\0' && (c !='\n'))
2012 if (c != ' ' || c != '\t')
2014 llbuglit ("Junk in load file");
2022 s = reader_readLine (f, os, MAX_DUMP_LINE_LENGTH);
2027 to handle reading of buffer overflow related constraints
2029 while (fgets (s, MAX_DUMP_LINE_LENGTH, f) != NULL
2032 ; /* ignore ;-comments */
2035 /*drl July 27 added this so that libraries without
2036 buffer constraints would be handled correctly.
2037 I'm trying to do this without breaking older libraries*/
2039 /*check for "optional" start buffer constraints message*/
2041 if (mstring_equalPrefix (s, "start_Buffer_Constraints"))
2043 (void) fgets (s, MAX_DUMP_LINE_LENGTH, f);
2046 while (s != NULL && *s != ';')
2048 constraintList preconditions;
2049 constraintList postconditions;
2051 cstring name = cstring_fromChars(reader_getWord(&s) );
2053 ue = usymtab_lookup ( name );
2057 preconditions = constraintList_undefined;
2058 postconditions = constraintList_undefined;
2060 if (!uentry_isValid(ue) )
2062 llfatalbug ((message("Invalid uentry for %s library file may be corrupted", cstring_fromChars(s) ) ));
2064 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2066 temp = cstring_fromChars (reader_getWord(&s) );
2068 if (cstring_compareLit (temp,"pre:") == 0 )
2070 preconditions = constraintList_undump (f);
2074 if (cstring_compareLit (temp,"pre:EMPTY") != 0 )
2075 llfatalbug ((message("Error reading library file pre:EMPTY expected but got %s", temp ) ));
2080 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2082 temp = cstring_fromChars(reader_getWord(&s) );
2083 if (cstring_compareLit (temp, "post:") == 0 )
2085 postconditions = constraintList_undump (f);
2089 if (cstring_compareLit (temp, "post:EMPTY") != 0 )
2090 llfatalbug ((message("Error reading library file post:EMPTY expected but got %s", temp ) ));
2093 cstring_free (temp);
2095 uentry_setPreconditions (ue, functionConstraint_createBufferConstraint (preconditions));
2096 uentry_setPostconditions (ue, functionConstraint_createBufferConstraint (postconditions));
2098 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2106 ** file scope for static variables
2110 usymtab_enterFile ()
2111 /*@globals utab, globtab, filetab@*/
2112 /*@modifies filetab@*/
2114 llassert (utab == globtab);
2119 usymtab_entries (globtab, ue)
2121 if (sRef_hasDerived (uentry_getSref (ue)))
2123 fprintf (g_warningstream, "Derived Global: %s\n", uentry_unparse (ue));
2124 fprintf (g_warningstream, "sRef: %s\n", sRef_unparseFull (ue->sref));
2126 } end_usymtab_entries ;
2130 usymtab_enterScope ();
2136 /*@globals utab, filetab@*/
2137 /*@modifies filetab, utab@*/
2140 llassert (utab->lexlevel == 1);
2142 usymtab_exitScope (exprNode_undefined);
2147 usymtab_enterScope ()
2148 /*@globals utab, globtab, filetab@*/
2151 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
2153 /* unconditional scope: optimize to avoid copy */
2154 t->aliases = aliasTable_copy (utab->aliases);
2157 llassert (usymtab_isDefined (t->env));
2159 if (t->env->lexlevel == paramsScope && context_inFunctionLike ())
2161 noshadowerror = TRUE;
2162 usymtab_handleParams ();
2163 noshadowerror = FALSE;
2168 ** setup external references:
2169 ** o only, unique params alias external args
2170 ** o other params may alias anything of their type
2174 usymtab_handleParams (void)
2175 /*@globals utab, globtab, filetab@*/
2176 /*@modifies utab, globtab@*/
2178 usymtab ptab = utab->env;
2179 uentry fcn = context_getHeader ();
2181 usymtab_entries (ptab, param)
2185 if (!uentry_isYield (param))
2188 sRef pref = uentry_getSref (param);
2190 /* Could be a global. */
2192 if (uentry_isAnyParam (param))
2194 ue = uentry_makeVariable (fixParamName (uentry_rawName (param)),
2195 uentry_getType (param),
2196 fileloc_copy (uentry_whereDeclared (param)),
2199 uentry_copyState (ue, param);
2200 uentry_setRefParam (ue);
2202 ue = usymtab_supEntrySrefReturn (ue);
2204 /* must be after supercede! */
2206 if (!sRef_stateKnown (pref))
2208 uentry_setDefState (ue, SS_DEFINED);
2209 uentry_setDefState (param, SS_DEFINED);
2213 if (sRef_isStateSpecial (pref))
2215 uentry_setDefState (ue, SS_SPECIAL); /* ALLOCATED); */
2216 /* evans 2002-01-01: should be unnecessary, the pre clauses
2217 ** set the state if necessary.
2222 uentry_setDefState (ue, sRef_getDefState (pref));
2226 uref = uentry_getSref (ue);
2228 if (sRef_isStack (uref))
2230 alkind pkind = sRef_getAliasKind (pref);
2232 if (alkind_isKnown (pkind) && !alkind_isLocal (pkind)
2233 && !alkind_isStack (pkind))
2235 sRef_setAliasKind (uref, pkind, fileloc_undefined);
2236 sRef_setOrigAliasKind (uref, pkind);
2240 sRef_setAliasKind (uref, AK_IMPTEMP, fileloc_undefined);
2241 sRef_setOrigAliasKind (uref, AK_IMPTEMP);
2243 if (uentry_isOut (param))
2249 sRef_setDefined (uref, fileloc_undefined);
2255 usymtab_addMustAlias (uref, pref);
2257 if (!(uentry_isOnly (param) || uentry_isUnique (param)))
2260 ** This is needed for detecting possibly aliased parameters.
2263 sRef s = sRef_makeExternal (uref);
2264 usymtab_addMustAlias (uref, s);
2267 if (sRef_isKillRef (pref))
2269 sRef_setAliasKind (uref, AK_NEWREF, fileloc_undefined);
2270 sRef_setOrigAliasKind (uref, AK_KILLREF);
2272 else if (sRef_isRefCounted (uref))
2274 sRef_setOrigAliasKind (uref, AK_REFCOUNTED);
2279 sRef_setOrigAliasKind (uref, AK_LOCAL);
2286 } end_usymtab_entries;
2289 if (uentry_hasStateClauseList (fcn))
2291 stateClauseList clauses = uentry_getStateClauseList (fcn);
2293 stateClauseList_preElements (clauses, cl)
2295 fileloc loc = stateClause_loc (cl);
2296 sRefSet osrs = sRefSet_undefined;
2299 if (stateClause_isGlobal (cl))
2301 DPRINTF (("Global Marker: %s",
2302 sRef_unparseFull (usymtab_lookupGlobalMarker ())));
2303 llassert (sRef_isGlobalMarker (usymtab_lookupGlobalMarker ()));
2304 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
2309 srs = stateClause_getRefs (cl);
2312 sRefSet_elements (srs, el)
2314 sRef base = sRef_getRootBase (el);
2315 sRef sb = sRef_updateSref (el);
2317 if (sRef_isResult (base))
2319 ; /* nothing to do before */
2321 else if (sRef_isParam (base) || sRef_isGlobalMarker (base))
2323 if (stateClause_setsMetaState (cl))
2325 /* copied from exprNode.c:3040 */
2326 qual ql = stateClause_getMetaQual (cl);
2327 annotationInfo ainfo = qual_getAnnotationInfo (ql);
2328 metaStateInfo minfo = annotationInfo_getState (ainfo);
2329 cstring key = metaStateInfo_getName (minfo);
2330 int mvalue = annotationInfo_getValue (ainfo);
2332 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
2334 if (sRef_isResult (base))
2340 sRef_setMetaStateValueComplete (sb, key, mvalue, loc);
2345 sRefMod modf = stateClause_getEntryFunction (cl);
2349 sRefSet aliases = usymtab_allAliases (sb);
2353 sRefSet_elements (aliases, sr)
2356 } end_sRefSet_elements ;
2358 sRefSet_free (aliases);
2364 if (sRef_isValid (base))
2366 DPRINTF (("Base: %s", sRef_unparseFull (base)));
2370 } end_sRefSet_elements ;
2371 } end_stateClauseList_preElements ;
2376 usymtab_enterFunctionScope (uentry fcn)
2377 /*@globals utab, filetab, globtab@*/
2380 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
2382 DPRINTF (("Enter function: %s", uentry_unparse (fcn)));
2384 if (utab->lexlevel != fileScope)
2386 if (utab->lexlevel > fileScope)
2388 llparseerror (cstring_makeLiteral ("New function scope inside function"));
2390 while (utab->lexlevel > fileScope)
2392 /*@i@*/ utab = usymtab_dropEnv (utab);
2399 llfatalbug (cstring_makeLiteral ("New function not inside file."));
2401 /*@-branchstate@*/ } /*@=branchstate@*/
2405 DPRINTF (("Globs: %s", globSet_unparse (uentry_getGlobs (fcn))));
2407 globSet_allElements (uentry_getGlobs (fcn), el)
2409 DPRINTF (("Here we go: %s", sRef_unparseFull (el)));
2411 if (sRef_isUndefGlob (el))
2413 usymId index = sRef_getScopeIndex (el);
2414 sRef sr = sRef_updateSref (el);
2415 fileloc loc = uentry_whereEarliest (fcn);
2417 DPRINTF (("update: %s", sRef_unparseFull (sr)));
2418 DPRINTF (("Undef!"));
2419 if (sRef_isFileStatic (el))
2421 ctype ct = sRef_getType (el);
2424 llassert (usymtab_isDefined (filetab));
2426 ue = usymtab_fetchIndex (filetab, index);
2428 if (ctype_isRealArray (ct) || ctype_isRealSU (ct))
2430 sRef_setAllocated (sr, loc);
2434 sRef_setUndefined (sr, loc);
2439 uentry ue = globtab->entries[index];
2440 ctype ct = uentry_getType (ue);
2442 if (ctype_isArray (ct) || ctype_isSU (ct))
2444 sRef_setAllocated (sr, loc);
2448 sRef_setUndefined (sr, loc);
2452 else if (sRef_isAllocated (el))
2454 sRef sr = sRef_updateSref (el);
2455 fileloc loc = uentry_whereEarliest (fcn);
2457 sRef_setAllocated (sr, loc);
2459 else if (sRef_isPartial (el))
2461 sRef sr = sRef_updateSref (el);
2462 fileloc loc = uentry_whereEarliest (fcn);
2464 sRef_setPartial (sr, loc);
2469 sRef sr = sRef_updateSref (el);
2470 fileloc loc = uentry_whereEarliest (fcn);
2472 sRef_setDefined (sr, loc);
2476 /* shouldn't need to do anything! */
2478 } end_globSet_allElements;
2480 DPRINTF (("Globs after: %s", globSet_unparse (uentry_getGlobs (fcn))));
2482 usymtab_checkAllValid ();
2487 usymtab_caseBranch (void)
2490 usymtab t = usymtab_create (US_CBRANCH, utab, FALSE);
2495 usymtab_switchBranch (/*@unused@*/ exprNode s)
2498 usymtab t = usymtab_create (US_SWITCH, utab, FALSE);
2500 t->aliases = aliasTable_copy (utab->aliases);
2505 usymtab_trueBranch (/*@only@*/ guardSet guards)
2508 usymtab t = usymtab_create (US_TBRANCH, utab, FALSE);
2511 ** not true! (could be in a macro)
2513 ** llassertprint (utab->lexlevel > paramsScope,
2514 ** ("not in scope: %s", usymtab_unparseLocal ()));
2518 guardSet_free (t->guards);
2521 aliasTable_free (t->aliases);
2522 t->aliases = aliasTable_copy (utab->aliases);
2530 ** { int a; if (...) a = 3; < a may be undefined here!
2535 usymtab_popTrueBranch (exprNode pred, exprNode expr, clause cl) /*@modifies utab@*/
2538 ** add a false branch
2539 ** (could be done more efficiently as a special case, but
2540 ** it is better to only maintain one version of the code)
2543 if (utab->kind != US_TBRANCH
2544 && context_inIterDef ())
2546 usymtab_exitScope (expr);
2550 DPRINTF (("pop true branch.."));
2551 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2552 usymtab_popBranches (pred, expr, exprNode_undefined, TRUE, cl);
2557 usymtab_popCaseBranch () /*@modifies utab@*/
2559 llassert (utab->kind == US_CBRANCH);
2560 usymtab_quietPlainExitScope ();
2564 usymtab_popTrueExecBranch (exprNode pred, exprNode expr, clause cl)
2567 ** add a false branch that must return --- that is,
2568 ** the true branch is always executed!
2571 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2572 usymtab_popBranches (pred, expr, exprNode_makeMustExit (), FALSE, cl);
2576 usymtab_popOrBranch (exprNode pred, exprNode expr)
2580 usymtab env = utab->env;
2581 usymtab otab = utab;
2584 llassert (env != NULL);
2586 if (exprNode_isError (expr))
2592 mustReturn = exprNode_mustEscape (expr);
2596 llassert (utab->kind == US_TBRANCH);
2599 ** merge each entry in table with its original
2600 ** unless execution cannot continue after this branch
2603 for (i = 0; i < utab->nentries; i++)
2605 uentry current = utab->entries[i];
2606 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2608 uentry_mergeState (old, current, exprNode_loc (expr),
2609 mustReturn, FALSE, TRUE, ORCLAUSE);
2615 env->guards = guardSet_levelUnionFree (env->guards,
2616 guardSet_invert (exprNode_getGuards (pred)),
2621 env->aliases = aliasTable_levelUnion (env->aliases, otab->aliases, env->lexlevel);
2624 /* env is now utab */
2625 usymtab_quietPlainExitScope ();
2629 ** case syntax in C is very unrestricted. This is unfortunate.
2631 ** A switch case is ended either by a new case or default, or
2632 ** a close } that may close the switch or some other control
2637 usymtab_newCase (/*@unused@*/ exprNode pred, exprNode last)
2640 bool mustBreak = usymtab_mustBreak (utab);
2641 bool mustReturn = usymtab_mustEscape (utab);
2642 usymtab stab = utab;
2644 DPRINTF (("New case!"));
2647 ** Find last case (or outer switch)
2650 while (stab->kind != US_CBRANCH && stab->kind != US_SWITCH)
2653 llassert (stab != GLOBAL_ENV);
2656 while (stab->kind == US_CBRANCH)
2659 llassert (stab != GLOBAL_ENV);
2663 ** if its a fall through case, merge in outside entries and last case.
2668 ** case 1: x = 3; <fall through>
2669 ** case 2: << x may not be defined
2673 if (!mustBreak && !mustReturn && utab->kind == US_CBRANCH)
2675 llassert (stab->kind == US_SWITCH || stab->kind == US_NORMAL);
2677 usymtab_entries (utab, ue) /* but, keep track of used variables */
2679 uentry old = usymtab_lookupAux (stab, uentry_rawName (ue));
2681 llassert (uentry_isValid (old));
2683 /* modifies ue, not old */
2685 uentry_mergeState (ue, old, exprNode_loc (last),
2686 FALSE, FALSE, TRUE, CASECLAUSE);
2687 } end_usymtab_entries;
2689 utab->aliases = aliasTable_levelUnion (utab->aliases,
2690 stab->aliases, utab->lexlevel);
2693 ** No need for a new branch.
2700 usymtab_caseBranch ();
2701 /*@-mustfree@*/ /*< utab->aliases >*/
2702 utab->aliases = aliasTable_copy (stab->aliases);
2710 ** for && (both pred and expr are executed)
2714 usymtab_popAndBranch (exprNode pred, /*@unused@*/ exprNode expr)
2717 usymtab env = utab->env;
2721 llassert (utab->kind == US_TBRANCH);
2724 ** merge each entry in table with its original
2725 ** unless execution cannot continue after this branch
2728 for (i = 0; i < utab->nentries; i++)
2730 uentry current = utab->entries[i];
2731 sRef tref = uentry_getSref (current);
2732 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2733 sRef oref = uentry_getSref (old);
2735 /* note that is current is in a nested branch,
2736 it may create a "new" old entry. */
2738 llassert (uentry_isValid (old));
2739 uentry_mergeState (old, current, exprNode_loc (expr),
2740 FALSE, FALSE, TRUE, ANDCLAUSE);
2743 ** if is it defined by the second clause, then it should be defined.
2746 if (sRef_isAnyDefined (tref)
2747 && (sRef_isAllocated (oref) || sRef_isStateUndefined (oref)))
2749 sRef_setDefined (oref, g_currentloc);
2753 utab->guards = guardSet_levelUnionFree (utab->guards,
2754 guardSet_invert (exprNode_getGuards (pred)),
2756 utab->aliases = aliasTable_levelUnion (utab->aliases, otab->aliases, utab->lexlevel);
2758 usymtab_quietPlainExitScope ();
2763 ** Stack should be [ US_CBRANCH+ US_SWITCH ]
2764 ** Only branches which do not return (except possibly the last branch) are included.
2766 ** Conditionally merge state from all CBRANCHes.
2768 ** If allpaths is TRUE, then all possible executions go through some switch
2769 ** case, and the original scope is not merged.
2773 usymtab_exitSwitch (/*@unused@*/ exprNode sw, bool allpaths)
2776 usymtab ttab = utab;
2777 usymtab stab = ttab;
2778 usymtab ltab = ttab;
2779 bool lastMustReturn = usymtab_mustEscape (utab);
2783 while (stab->kind == US_CBRANCH)
2786 llassert (stab != GLOBAL_ENV);
2789 while (stab->kind == US_NORMAL)
2792 llassert (stab != GLOBAL_ENV);
2795 llassert (stab->kind == US_SWITCH);
2797 /* go to the scope outside the switch (US_SWITCH is just a marker! */
2799 llassert (stab != GLOBAL_ENV);
2803 llassert (usymtab_isDefined (ttab));
2805 if (ttab->kind == US_CBRANCH)
2807 /* was quietPlainExitScope --- but, can't free it yet! */
2809 llassert (utab != GLOBAL_ENV);
2811 while (ttab->kind == US_CBRANCH)
2814 ** (from popTrueBranch)
2817 bool mustReturn = usymtab_mustEscape (ttab);
2818 bool mustBreak = usymtab_mustBreak (ttab);
2820 usymtab_entries (ttab, current)
2822 uentry old = /*@-compmempass@*/ usymtab_lookupAux (ltab, uentry_rawName (current));
2826 ** note that is this is in a nested branch,
2827 ** it may create a "new" old entry.
2830 if (uentry_isValid (old))
2834 uentry_mergeUses (current, old);
2835 uentry_setState (old, current);
2839 uentry_mergeState (old, current, exprNode_loc (sw),
2840 mustReturn, FALSE, TRUE, SWITCHCLAUSE);
2847 } end_usymtab_entries;
2850 ** if entry is not in symbol table for this case, merge with pre-switch
2854 if (!mustReturn && !mustBreak)
2856 usymtab_entries (stab, current)
2858 if (!usymtab_indexFound (usymtab_getIndex (ttab, uentry_rawName (current))))
2860 uentry old = /*@-compmempass@*/
2861 usymtab_lookupAux (ltab, uentry_rawName (current));
2864 llassert (uentry_isValid (old));
2865 uentry_mergeState (old, current, exprNode_loc (sw),
2866 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2868 } end_usymtab_entries;
2871 ltab->env = ttab->env;
2875 ** Suprious error, becuase of environments.
2878 /*@i1@*/ utab = ltab;
2880 lastMustReturn = FALSE;
2887 ** now, there is one US_CBRANCH. Merge this with the stab.
2891 for (i = 0; i < ltab->nentries; i++)
2893 uentry current = ltab->entries[i];
2894 uentry old = usymtab_lookupAux (stab, uentry_rawName (current));
2896 /* note that is this is in a nested branch,
2897 it may create a "new" old entry. */
2900 if (uentry_isValid (old))
2904 uentry_mergeUses (current, old);
2905 uentry_setState (old, current);
2909 uentry_mergeState (old, current, exprNode_loc (sw),
2910 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2924 ** switch may or may not be followed by a new scope
2927 if (utab->kind == US_SWITCH)
2929 usymtab_quietPlainExitScope ();
2933 usymtab_quietPlainExitScope ();
2934 llassert (utab->kind == US_SWITCH);
2935 usymtab_quietPlainExitScope ();
2941 updateNullState (sRef el, /*@notnull@*/ usymtab ttab,
2942 /*@notnull@*/ usymtab ftab, bool trueGuard)
2944 sRef base = sRef_getRootBase (el);
2945 int level = sRef_lexLevel (base);
2947 if (sRef_isCvar (base))
2949 usymId index = sRef_getScopeIndex (base);
2950 uentry ue = usymtab_getRefTab (ttab, level, index);
2952 if (!uentry_isLset (ue))
2954 sRef sr = uentry_getSref (ue);
2958 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2962 if (!guardSet_isGuarded (ttab->guards, el)
2963 && !sRef_isNotNull (sr))
2965 DPRINTF (("Here! %s / %s",
2966 sRef_unparseFull (sr),
2967 sRef_unparseFull (el)));
2968 sRef_setDerivNullState (sr, el, NS_DEFNULL);
2977 ue = usymtab_getRefTab (ftab, level, index);
2979 if (!uentry_isLset (ue))
2981 sRef sr = uentry_getSref (ue);
2983 if (!trueGuard) /* yikes! forgot the ! */
2985 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2990 if (!guardSet_isGuarded (ftab->guards, el)
2991 && !sRef_isNotNull (sr))
2993 sRef_setDerivNullState (sr, el, NS_DEFNULL);
3005 usymtab_popBranches (exprNode pred, exprNode tbranch, exprNode fbranch,
3006 bool isOpt, clause cl)
3010 usymtab ftab = utab;
3011 usymtab ttab = utab->env;
3015 guardSet guards = exprNode_getGuards (pred);
3016 sRefSet tguards = guardSet_getTrueGuards (guards);
3017 sRefSet fguards = guardSet_getFalseGuards (guards);
3018 bool mustReturnT = exprNode_mustEscape (tbranch);
3019 bool mustReturnF = exprNode_mustEscape (fbranch);
3021 DPRINTF (("Pop branches: %s [mustreturn: %s/%s]", exprNode_unparse (pred),
3022 bool_unparse (mustReturnT),
3023 bool_unparse (mustReturnF)));
3025 if (exprNode_isDefined (fbranch))
3027 loc = exprNode_loc (fbranch);
3031 loc = exprNode_loc (tbranch);
3034 llassert (usymtab_isDefined (ttab));
3038 llassert (usymtab_isDefined (env));
3039 llassert (ftab->kind == US_FBRANCH);
3040 llassert (ttab->kind == US_TBRANCH);
3043 ** For each element that is true guarded (i.e., if (x != NULL))
3044 ** make x = null in false branch,
3045 ** and x = notnull in true branch.
3046 ** unless x was set locally in that branch.
3047 ** For each element that is false guarded (x == NULL)
3048 ** make x = null in true, notnull in false.
3050 ** For each element that is either guarded (pred(x))
3054 sRefSet_allElements (tguards, el)
3056 updateNullState (el, ttab, ftab, TRUE);
3057 } end_sRefSet_allElements;
3059 sRefSet_allElements (fguards, el)
3061 updateNullState (el, ttab, ftab, FALSE);
3062 } end_sRefSet_allElements;
3066 ** if an entry is in both true and false, merge the entries,
3067 ** then replace original with new state.
3069 ** if an entry is in one table, merge it with the original.
3072 DPRINTF (("ftab: %d", ftab->nentries));
3074 for (i = 0; i < ftab->nentries; i++)
3076 uentry fthis = ftab->entries[i];
3077 uentry old = usymtab_lookupAux (env, uentry_rawName (fthis));
3078 usymId tindex = usymtab_getIndex (ttab, uentry_rawName (fthis));
3080 DPRINTF (("Entry: %s / %s", uentry_unparseFull (fthis), uentry_unparseFull (old)));
3082 if (uentry_isUndefined (old))
3084 /* possible entry was added as an undefined id */
3085 DPRINTF (("Undefined! %s", uentry_rawName (fthis)));
3089 if (usymtab_indexFound (tindex))
3091 uentry tthis = ttab->entries[tindex];
3093 /* note that is this is in a nested branch,
3094 it may create a "new" old entry. */
3100 uentry_mergeState (fthis, tthis, loc,
3101 mustReturnT, FALSE, FALSE, cl);
3105 uentry_mergeUses (fthis, tthis);
3108 uentry_setState (old, fthis);
3115 uentry_setState (old, tthis);
3116 uentry_mergeState (old, fthis, loc, mustReturnF,
3120 ttab->entries[tindex] = uentry_undefined;
3121 uentry_free (tthis);
3125 uentry_mergeState (old, fthis, loc, mustReturnF, TRUE, FALSE, cl);
3129 for (i = 0; i < ttab->nentries; i++)
3131 uentry current = ttab->entries[i];
3133 DPRINTF (("ttab: %s", uentry_unparseFull (current)));
3135 if (!uentry_isUndefined (current))
3137 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
3139 DPRINTF (("Old: %s", uentry_unparseFull (old)));
3141 if (uentry_isUndefined (old))
3143 llcontbug (message ("Undefined entry: %s", uentry_rawName (current)));
3149 uentry_mergeUses (current, old);
3150 uentry_setState (old, current);
3155 ** Assumes false branch is a fall-through if
3156 ** fbranch is not defined. This is true, unless
3157 ** where was some greivous error in processing
3158 ** the else branch of an if-then, in which case
3159 ** this is probably the right thing to do anyway.
3162 uentry_mergeState (old, current, loc, mustReturnT,
3166 DPRINTF (("==> %s", uentry_unparseFull (old)));
3171 ** Plain levelUnion doesn't work, since we need to use the sRef's in env->aliases
3172 ** if they are present.
3175 llassert (NOALIAS (env->aliases, ttab->aliases));
3176 llassert (NOALIAS (env->aliases, ftab->aliases));
3178 aliasTable_free (env->aliases);
3180 env->aliases = aliasTable_levelUnionNew (ttab->aliases,
3181 ftab->aliases, env->lexlevel);
3183 aliasTable_fixSrefs (env->aliases);
3185 DPRINTF (("Aliases: %s", aliasTable_unparse (env->aliases)));
3187 /* exit true and false scopes */
3188 usymtab_quietPlainExitScope ();
3189 usymtab_quietPlainExitScope ();
3193 utab->guards = guardSet_levelUnionFree
3195 guardSet_invert (exprNode_getGuards (pred)),
3201 utab->guards = guardSet_levelUnion (utab->guards,
3202 exprNode_getGuards (pred),
3206 DPRINTF (("Here."));
3209 static void usymtab_fixCases (void) /*@modifies utab@*/ {
3210 while (utab->kind == US_CBRANCH)
3212 usymtab_quietPlainExitScope ();
3215 llassert (utab->kind != US_CBRANCH);
3219 usymtab_altBranch (/*@only@*/ guardSet guards)
3223 usymtab parent = utab->env;
3225 t = usymtab_create (US_FBRANCH, utab, FALSE);
3228 ** If we are in a case, need to close it. The C syntax
3229 ** is very liberal, so this kludge is necessary.
3232 usymtab_fixCases ();
3234 DPRINTF (("Current kind: %s", usymtab_unparseStack ()));
3236 llassert (utab->kind == US_TBRANCH);
3237 llassert (parent != GLOBAL_ENV);
3239 guardSet_free (t->guards);
3242 aliasTable_free (t->aliases);
3243 t->aliases = aliasTable_copy (parent->aliases);
3249 usymtab_allDefined (void)
3250 /*@globals utab, globtab@*/
3254 llassert (utab == globtab);
3256 for (i = 0; i < utab->nentries; i++)
3258 uentry e = utab->entries[i];
3260 if (uentry_isPriv (e))
3262 ; /* no need to define it */
3266 if (context_getFlag (FLG_SPECUNDECL))
3268 fileloc sloc = uentry_whereSpecified (e);
3269 fileloc dloc = uentry_whereDeclared (e);
3271 if (fileloc_isDefined (sloc)
3272 && !uentry_isFakeTag (e)
3273 && !fileloc_isDefined (dloc))
3277 message ("%s %q specified but not declared",
3278 ekind_capName (uentry_getKind (e)),
3279 uentry_getName (e)),
3284 if (!uentry_isCodeDefined (e))
3286 fileloc dloc = uentry_whereDeclared (e);
3288 if (fileloc_isLib (dloc) || fileloc_isXHFile (dloc))
3292 else if (fileloc_isDefined (dloc))
3294 if (!uentry_isAnyTag (e))
3296 if (fileloc_isUser (dloc))
3300 message ("%s %q declared but not defined",
3301 ekind_capName (uentry_getKind (e)),
3302 uentry_getName (e)),
3304 DPRINTF (("decl: %s", uentry_unparseFull (e)));
3310 fileloc sloc = uentry_whereSpecified (e);
3312 if (fileloc_isDefined (sloc)
3313 && !fileloc_isImport (sloc)
3314 && !fileloc_isLib (sloc)
3315 && !fileloc_isPreproc (sloc)
3316 && !uentry_isFakeTag (e))
3318 if (uentry_isVariable (e) || uentry_isFunction (e))
3322 message ("%s %q specified but not declared or defined",
3323 ekind_capName (uentry_getKind (e)),
3324 uentry_getName (e)),
3331 message ("%s %q specified but not defined",
3332 ekind_capName (uentry_getKind (e)),
3333 uentry_getName (e)),
3343 void usymtab_exportHeader (void)
3348 for (i = 0; i < utab->nentries; i++)
3350 uentry ce = utab->entries[i];
3352 if (!uentry_isDatatype (ce)
3353 && !uentry_isAnyTag (ce)
3354 && !uentry_isEitherConstant (ce) && !uentry_isStatic (ce)
3355 && !uentry_isExternal (ce)
3356 && !uentry_isForward (ce))
3358 fileloc fwhere = uentry_whereDeclared (ce);
3360 if (fileloc_isUndefined (fwhere)
3361 && uentry_isFunction (ce))
3363 fwhere = uentry_whereDefined (ce);
3366 if (fileloc_isDefined (fwhere)
3367 && !fileloc_isHeader (fwhere)
3368 && !fileloc_isXHFile (fwhere)
3369 && !(fileloc_isSpecialFile (fwhere)
3370 && !context_getFlag (FLG_UNUSEDSPECIAL)))
3372 if (uentry_isVariable (ce))
3375 (FLG_EXPORTHEADERVAR,
3376 message ("%s %q exported but not declared in header file",
3377 ekind_capName (uentry_getKind (ce)),
3378 uentry_getName (ce)),
3381 uentry_showDefSpecInfo (ce, fwhere);
3386 if (!uentry_isIter (ce)
3387 && !uentry_isEndIter (ce)
3388 && !uentry_isExpandedMacro (ce))
3390 if (uentry_isFunction (ce)
3391 && cstring_equalLit (uentry_rawName (ce), "main"))
3393 ; /* no error for main */
3399 message ("%s %q exported but not declared "
3401 ekind_capName (uentry_getKind (ce)),
3402 uentry_getName (ce)),
3405 uentry_showDefSpecInfo (ce, fwhere);
3415 void usymtab_exportLocal (void)
3420 for (i = 0; i < utab->nentries; i++)
3422 uentry ce = utab->entries[i];
3424 if (!uentry_isDatatype (ce) && !uentry_isAnyTag (ce)
3425 && !uentry_isEitherConstant (ce)
3426 && !uentry_isIter (ce)
3427 && !uentry_isEndIter (ce)
3428 && !uentry_isExpandedMacro (ce)
3429 && uentry_isUsed (ce))
3431 /* check static uses */
3432 filelocList fuses = uentry_getUses (ce);
3433 fileloc mod = uentry_whereDefined (ce);
3434 bool ok = filelocList_isEmpty (fuses);
3435 fileloc fwhere = uentry_whereDeclared (ce);
3437 if (fileloc_isSpecialFile (fwhere)
3438 && !context_getFlag (FLG_UNUSEDSPECIAL))
3440 ok = TRUE; /* no errors for special files */
3444 filelocList_elements (fuses, uloc)
3446 if (fileloc_isUndefined (uloc) || !fileloc_sameModule (uloc, mod))
3449 /*@innerbreak@*/ break;
3451 } end_filelocList_elements;
3458 message ("%s exported but not used outside %s: %q",
3459 ekind_capName (uentry_getKind (ce)),
3460 fileloc_getBase (mod),
3461 uentry_getName (ce)),
3464 uentry_showDefSpecInfo (ce, fwhere);
3472 usymtab_allUsed (void)
3476 bool isFileStatic = usymtab_inFileScope ();
3477 cstring last_file = cstring_undefined;
3479 for (i = 0; i < utab->nentries; i++)
3481 bool hasError = FALSE;
3482 uentry ce = utab->entries[i];
3483 fileloc fwhere = uentry_whereDeclared (ce);
3485 if (fileloc_isUndefined (fwhere))
3487 fwhere = uentry_whereDefined (ce);
3490 if (fileloc_isInvalid (fwhere)
3491 || fileloc_isLib (fwhere)
3492 || fileloc_isBuiltin (fwhere)
3493 || ((fileloc_isSpecialFile (fwhere)
3494 || fileloc_isSpecialFile (uentry_whereDefined (ce)))
3495 && !context_getFlag (FLG_UNUSEDSPECIAL)))
3499 else if (!uentry_wasUsed (ce) && !uentry_isAnyTag (ce))
3501 cstring fname = fileloc_filename (fwhere);
3503 if (cstring_isUndefined (last_file))
3507 else if (cstring_equal (fname, last_file))
3516 if (uentry_isParam (ce))
3518 if (context_inMacro ())
3520 sRef cref = uentry_getSref (ce);
3522 if (uentry_isYield (ce))
3524 ; /* no checks (for now) */
3526 else if (sRef_isSafe (cref))
3532 if (uentry_hasRealName (ce))
3535 optgenerror (FLG_MACROPARAMS,
3536 message ("Macro parameter %q not used",
3537 uentry_getName (ce)),
3544 if (cstring_equalFree (uentry_getName (ce),
3545 cstring_makeLiteral ("...")))
3551 hasError = optgenerror (FLG_PARAMUNUSED,
3552 message ("Parameter %q not used",
3553 uentry_getName (ce)),
3558 else if (uentry_isFunction (ce) || uentry_isIter (ce))
3560 if (fileloc_isUser (fwhere))
3562 hasError = optgenerror
3564 message ("%q %q declared but not used",
3566 (uentry_isIter (ce) ? "Iterator"
3567 : (isFileStatic ? "File static function" : "Function")),
3568 uentry_getName (ce)),
3572 else if (uentry_isEndIter (ce))
3574 ; /* no error (already reported for iter */
3576 else if (uentry_isEnumConstant (ce))
3578 if (fileloc_isUser (fwhere))
3580 hasError = optgenerror
3582 message ("Enum member %q not used",
3583 uentry_getName (ce)),
3587 else if (uentry_isConstant (ce))
3589 if (fileloc_isUser (fwhere))
3591 hasError = optgenerror
3593 message ("Constant %q declared but not used",
3594 uentry_getName (ce)),
3598 else if (uentry_isDatatype (ce))
3600 if (fileloc_isUser (fwhere))
3602 hasError = optgenerror
3604 message ("Type %q declared but not used",
3605 uentry_getName (ce)),
3609 else if (!uentry_isRefParam (ce) && !uentry_isExpandedMacro (ce))
3610 { /* errors for ref params will be reported in the next scope */
3611 llassertprint (uentry_isVar (ce),
3612 ("ce: %s", uentry_unparseFull (ce)));
3614 if (ctype_isFunction (uentry_getType (ce)))
3616 if (fileloc_isUser (fwhere))
3618 hasError = optgenerror
3620 message ("%q %q declared but not used",
3622 (isFileStatic ? "File static function"
3624 uentry_getName (ce)),
3630 if (fileloc_isUser (fwhere))
3634 hasError = optgenerror
3636 message ("%q %q declared but not used",
3638 (isFileStatic ? "File static variable"
3640 uentry_getName (ce)),
3650 else if ((uentry_isDatatype (ce) || uentry_isAnyTag (ce)))
3651 { /* check all fields */
3652 ctype ct = uentry_getRealType (ce);
3655 while (ctype_isAP (ct))
3657 ct = ctype_getBaseType (ct);
3660 if (ctype_isSU (ct))
3662 uentryList fields = ctype_getFields (ct);
3664 uentryList_elements (fields, field)
3666 if (!uentry_isUsed (field))
3668 if (uentry_hasName (ce))
3670 hasError |= optgenerror
3672 message ("Field %q of %s %q declared but not used",
3673 uentry_getName (field),
3674 cstring_makeLiteralTemp
3675 (ctype_isStruct (ct) ? "structure" : "union"),
3676 uentry_getName (ce)),
3677 uentry_whereEarliest (field));
3683 ** Can't report these errors for unnamed structs.
3684 ** No way to tell when there are multiple consistent
3685 ** unnamed structure types. (Could go through table
3686 ** and mark them all unused...)
3688 hasError |= optgenerror
3690 message ("Field %q of unnamed %s declared but not used",
3691 uentry_getName (field),
3692 cstring_makeLiteralTemp
3693 (ctype_isStruct (ct) ? "structure" : "union")),
3694 uentry_whereEarliest (field));
3699 uentry_setUsed (field, fileloc_undefined);
3701 } end_uentryList_elements;
3711 if (uentry_isParam (ce) && context_inMacro ())
3713 if (fileloc_isDefined (uentry_whereSpecified (ce)))
3715 uentry_showWhereSpecified (ce);
3720 uentry_showDefSpecInfo (ce, fwhere);
3723 uentry_setUsed (ce, fileloc_undefined);
3729 checkGlobalReturn (uentry glob, sRef orig)
3731 sRef sr = uentry_getSref (glob);
3733 DPRINTF (("Check global return: %s / orig: %s / sr: %s",
3734 uentry_unparseFull (glob),
3735 sRef_unparseFull (orig),
3736 sRef_unparseFull (sr)));
3738 DPRINTF (("Is killed: %s", bool_unparse (sRef_isKilledGlob (orig))));
3740 if (context_getFlag (FLG_GLOBSTATE))
3742 DPRINTF (("Is killed: %s", sRef_unparseFull (orig)));
3744 if (sRef_isKilledGlob (orig))
3746 if (sRef_isStateUndefined (sr)
3747 || sRef_isUnuseable (sr)
3748 || sRef_isStateUnknown (sr)
3749 || sRef_isDead (sr))
3755 ctype ct = ctype_realType (uentry_getType (glob));
3757 DPRINTF (("Check global destroyed: %s", uentry_unparseFull (glob)));
3759 if (ctype_isVisiblySharable (ct))
3764 ("Killed global %q (type %s) not released before return",
3765 uentry_getName (glob),
3766 ctype_unparse (ct)),
3769 sRef_showStateInfo (sr);
3774 sRef_protectDerivs ();
3775 (void) transferChecks_globalDestroyed (sr, g_currentloc);
3776 sRef_clearProtectDerivs ();
3782 if (sRef_isStateUndefined (sr))
3784 if (optgenerror (FLG_GLOBSTATE,
3786 ("Function returns with global %q undefined",
3787 uentry_getName (glob)),
3790 sRef_showStateInfo (sr);
3795 if (sRef_isDead (sr) || sRef_isKept (sr))
3799 message ("Function returns with global %q "
3800 "referencing %s storage",
3801 uentry_getName (glob),
3802 cstring_makeLiteralTemp (sRef_isDead (sr) ? "released" : "kept")),
3805 if (sRef_isKept (sr))
3807 sRef_showAliasInfo (sr);
3811 sRef_showStateInfo (sr);
3814 sRef_setDefState (sr, SS_UNKNOWN, fileloc_undefined);
3818 if (ctype_isRealPointer (uentry_getType (glob))
3819 && sRef_possiblyNull (sr)
3820 && !uentry_possiblyNull (glob))
3824 message ("Function returns with non-null global %q "
3825 "referencing null storage",
3826 uentry_getName (glob)),
3829 sRef_showNullInfo (sr);
3834 DPRINTF (("Check transfer: %s", uentry_unparseFull (glob)));
3835 transferChecks_globalReturn (glob);
3843 ** remember: check alias globals
3846 void usymtab_checkFinalScope (bool isReturn)
3849 bool mustDefine = context_getFlag (FLG_MUSTDEFINE);
3850 sRefSet checked = sRefSet_new ();
3851 usymtab stab = utab;
3855 ** need to check all scopes out to function parameters.
3860 for (i = 0; i < stab->nentries; i++)
3862 uentry ce = stab->entries[i];
3863 sRef sr = uentry_getSref (ce);
3864 sRef rb = sRef_getRootBase (sr);
3868 ** Shouldn't check if shadow checked in deeper scope:
3873 uentry oue = usymtab_lookupQuietNoAlt (utab, uentry_observeRealName (ce));
3875 if (!uentry_sameObject (ce, oue))
3877 /* what if it is one an alternate branch? */
3878 /*@innercontinue@*/ continue;
3882 DPRINTF (("Here check final scope: %s", uentry_unparseFull (ce)));
3884 if (ctype_isFunction (uentry_getType (ce)))
3886 /*@innercontinue@*/ continue;
3889 if (uentry_isAnyParam (ce)
3890 || uentry_isRefParam (ce)
3891 || sRef_isFileOrGlobalScope (rb))
3893 /* Don't do the loseref check...but should check state! */
3894 DPRINTF (("Skipping check 1"));
3896 else if (sRef_isDefinitelyNull (sr)
3897 || usymtab_isDefinitelyNull (sr))
3900 ** No state reference errors for definitely null references.
3903 DPRINTF (("Skipping check 2"));
3907 DPRINTF (("Lose ref: %s / %s", uentry_unparse (ce),
3908 sRef_unparseFull (sr)));
3910 tvalues = sRef_getValueTable (sr);
3912 valueTable_elements (tvalues, fkey, fval) {
3913 metaStateInfo minfo;
3914 cstring msg = cstring_undefined;
3917 minfo = context_lookupMetaStateInfo (fkey);
3918 llassert (metaStateInfo_isDefined (minfo));
3920 if (stateValue_isError (fval)
3921 || sRef_isStateUndefined (sr)) /* No errors for undefined state */
3923 DPRINTF (("Skipping check 3"));
3927 DPRINTF (("Check: %s / %s / %s", fkey,
3928 metaStateInfo_unparse (minfo),
3929 stateValue_unparse (fval)));
3931 minfo = context_lookupMetaStateInfo (fkey);
3933 nval = stateCombinationTable_lookupLoseReference
3934 (metaStateInfo_getTransferTable (minfo),
3935 stateValue_getValue (fval), &msg);
3937 if (cstring_isDefined (msg))
3942 ("%s loses reference %q in invalid state %q (%s)",
3943 cstring_makeLiteralTemp (isReturn ? "Return" : "Scope exit"),
3944 uentry_getName (ce),
3945 stateValue_unparseValue (fval, minfo),
3949 stateValue_show (fval, minfo);
3953 DPRINTF (("Suppressed transfer error: %s", msg));
3957 } end_valueTable_elements;
3960 DPRINTF (("Check mustfree entry: %s", uentry_unparseFull (ce)));
3962 if (!sRefSet_member (checked, sr) && !sRef_isFileOrGlobalScope (rb))
3964 if (ctype_isRealSU (uentry_getType (ce))
3965 && !uentry_isAnyParam (ce)
3966 && !uentry_isRefParam (ce)
3967 && !uentry_isStatic (ce)
3968 && !sRef_isDependent (sr)
3969 && !sRef_isOwned (sr))
3971 sRefSet als = usymtab_allAliases (sr);
3973 if (sRefSet_isEmpty (als))
3975 transferChecks_localDestroyed (sr, g_currentloc);
3979 /* aliased, no problem */ ;
3985 (!uentry_isStatic (ce)
3986 && ((sRef_isNewRef (sr))
3987 || (((sRef_isOnly (sr) || sRef_isFresh (sr)
3988 || sRef_isKeep (sr) || sRef_isOwned (sr))
3989 && !sRef_isDead (sr))
3990 && (!sRef_definitelyNull (sr))
3991 && (!usymtab_isDefinitelyNull (sr)))))
3993 bool hasError = TRUE;
3995 DPRINTF (("Checking: %s", sRef_unparseFull (sr)));
3998 ** If its a scope exit, check if there is an alias.
3999 ** If so, make it only. If not, there is an error.
4004 if (transferChecks_canLoseReference (sr, g_currentloc))
4006 DPRINTF (("Can lose!"));
4013 if (sRef_hasLastReference (sr))
4015 sRef ar = sRef_getAliasInfoRef (sr);
4018 (sRef_isFresh (ar) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4020 ("Last reference %q to %s storage %qnot %q before %q",
4022 alkind_unparse (sRef_getAliasKind (sr)),
4023 sRef_unparseOpt (ar),
4024 cstring_makeLiteral (sRef_isKeep (sr)
4025 ? "transferred" : "released"),
4026 cstring_makeLiteral (isReturn
4027 ? "return" : "scope exit")),
4030 sRef_showRefLost (sr);
4033 else if (sRef_isNewRef (sr))
4036 (sRef_isFresh (sr) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4038 ("%q %q not released before %q",
4040 (alkind_isKillRef (sRef_getOrigAliasKind (sr))
4041 ? "Kill reference parameter" : "New reference"),
4042 uentry_getName (ce),
4043 cstring_makeLiteral (isReturn
4044 ? "return" : "scope exit")),
4047 sRef_showAliasInfo (sr);
4052 if (ctype_isRealSU (sRef_getType (sr)))
4054 transferChecks_structDestroyed (sr, g_currentloc);
4059 (sRef_isFresh (sr) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4061 ("%s storage %q not %q before %q",
4062 alkind_capName (sRef_getAliasKind (sr)),
4063 uentry_getName (ce),
4064 cstring_makeLiteral (sRef_isKeep (sr)
4065 ? "transferred" : "released"),
4066 cstring_makeLiteral (isReturn
4067 ? "return" : "scope exit")),
4070 sRef_showAliasInfo (sr);
4071 DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
4083 if (mustDefine && uentry_isOut (ce))
4085 /* No error if its dead (either only or error already reported */
4086 if (!sRef_isReallyDefined (sr) && !sRef_isDead (sr))
4090 message ("Out storage %q not defined before %q",
4091 uentry_getName (ce),
4093 (isReturn ? "return" : "scope exit")),
4096 DPRINTF (("sr: %s", sRef_unparseFull (sr)));
4101 ** also check state is okay
4104 if (usymtab_lexicalLevel () > functionScope
4105 && uentry_isVariable (ce)
4106 && (sRef_isLocalVar (sr)
4107 && (sRef_isDependent (sr) || sRef_isLocalState (sr))))
4109 sRefSet ab = usymtab_aliasedBy (sr);
4111 /* should do something more efficient here */
4113 if (sRefSet_isEmpty (ab))
4115 /* and no local ref */
4116 DPRINTF (("Check lose ref: %s", uentry_unparseFull (ce)));
4117 transferChecks_loseReference (ce);
4131 checked = sRefSet_insert (checked, sr);
4134 llassert (usymtab_isDefined (stab->env));
4136 if (usymtab_isBranch (stab))
4138 stab = usymtab_dropEnv (stab);
4145 llassert (stab != usymtab_undefined);
4146 } while (isReturn && (stab->lexlevel >= paramsScope));
4148 sRefSet_free (checked);
4152 ** all globals are appropriately defined
4153 ** all parameters are appropriately defined
4154 ** special clauses are followed
4157 if (isReturn || (utab->lexlevel == paramsScope))
4159 uentry fcn = context_getHeader ();
4160 uentryList params = context_getParams ();
4161 globSet uglobs = context_getUsedGlobs ();
4162 globSet sglobs = context_getGlobs ();
4164 if (isReturn && context_maybeSet (FLG_GLOBALIAS))
4166 aliasTable_checkGlobs (utab->aliases);
4170 ** state clauses (ensures, defines, sets, allocates, releases)
4173 if (uentry_hasStateClauseList (fcn))
4175 stateClauseList clauses = uentry_getStateClauseList (fcn);
4177 stateClauseList_elements (clauses, cl)
4179 if (stateClause_isAfter (cl) && !stateClause_isGlobal (cl))
4181 if (stateClause_setsMetaState (cl))
4183 sRefSet rfs = stateClause_getRefs (cl);
4184 qual q = stateClause_getMetaQual (cl);
4185 annotationInfo ainfo = qual_getAnnotationInfo (q);
4186 metaStateInfo minfo = annotationInfo_getState (ainfo);
4187 cstring key = metaStateInfo_getName (minfo);
4188 int mvalue = annotationInfo_getValue (ainfo);
4190 DPRINTF (("Post meta state clause: %s", stateClause_unparse (cl)));
4192 sRefSet_elements (rfs, el)
4194 sRef base = sRef_getRootBase (el);
4196 if (sRef_isResult (base))
4199 ** This is checked for return transfers.
4203 else if (sRef_isParam (base) || sRef_isGlobalMarker (base))
4205 sRef sr = sRef_updateSref (base);
4206 sr = sRef_fixBase (el, sr);
4208 if (!sRef_checkMetaStateValue (sr, key, mvalue))
4213 ("Ensures clause not satisfied%q (state is %q): %q",
4214 sRef_isGlobalMarker (sr)
4216 : message (" by %q", sRef_unparse (sr)),
4217 stateValue_unparseValue (sRef_getMetaStateValue (sr, key),
4219 stateClause_unparse (cl)),
4222 sRef_showMetaStateInfo (sr, key);
4228 if (sRef_isMeaningful (el))
4233 } end_sRefSet_elements ;
4237 /* evs - 2000 07 10 - added this */
4238 sRefTest tst = stateClause_getPostTestFunction (cl);
4239 sRefSet rfs = stateClause_getRefs (cl);
4241 sRefSet_elements (rfs, el)
4243 sRef base = sRef_getRootBase (el);
4245 if (sRef_isResult (base))
4248 ** This is checked for return transfers.
4253 else if (sRef_isParam (base))
4255 sRef sr = sRef_updateSref (base);
4256 sr = sRef_fixBase (el, sr);
4258 if (tst != NULL && !tst (sr))
4261 (stateClause_postErrorCode (cl),
4262 message ("%s storage %qcorresponds to "
4263 "storage listed in %q clause",
4264 stateClause_postErrorString (cl, sr),
4265 sRef_unparseOpt (sr),
4266 stateClause_unparseKind (cl)),
4269 sRefShower ss = stateClause_getPostTestShower (cl);
4276 DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
4282 if (sRef_isMeaningful (el))
4287 } end_sRefSet_elements ;
4290 } end_stateClauseList_elements ;
4294 ** check parameters on return
4297 uentryList_elements (params, arg)
4299 if (!uentry_isElipsisMarker (arg))
4301 ctype rt = ctype_realType (uentry_getType (arg));
4303 if (ctype_isMutable (rt) || ctype_isSU (rt))
4305 uentry param = usymtab_lookupQuiet (utab, uentry_rawName (arg));
4306 DPRINTF (("Check param return: %s", uentry_unparseFull (param)));
4307 transferChecks_paramReturn (param);
4310 } end_uentryList_elements;
4312 DPRINTF (("Check global return: %s",
4313 globSet_unparse (sglobs)));
4315 globSet_allElements (sglobs, el)
4317 sRef orig = el; /*! sRef_updateSref (el); */ /*!!!*/
4318 uentry current = sRef_getUentry (el);
4320 DPRINTF (("Check global return: %s / %s", sRef_unparseFull (el),
4321 uentry_unparseFull (current)));
4323 if (uentry_isVariable (current) && !uentry_isRealFunction (current))
4325 checkGlobalReturn (current, orig);
4327 } end_globSet_allElements;
4329 globSet_allElements (uglobs, el)
4331 if (!globSet_member (sglobs, el))
4333 uentry current = sRef_getUentry (el);
4335 if (uentry_isVariable (current)
4336 && !uentry_isRealFunction (current))
4338 checkGlobalReturn (current, sRef_undefined);
4341 } end_globSet_allElements;
4346 usymtab_quietExitScope (fileloc loc)
4347 /*@globals utab, globtab, filetab; @*/
4350 usymtab t = utab->env;
4352 DPRINTF (("Quiet exit scope [%p]", utab));
4354 if (utab->reftable != NULL)
4358 for (i = 0; i < utab->nentries; i++)
4360 uentry current = utab->entries[i];
4361 uentry old = usymtab_lookupAux (t, uentry_rawName (current));
4363 uentry_mergeState (old, current, loc, FALSE, FALSE, FALSE, NOCLAUSE);
4367 llassert (t != NULL);
4369 if (t->lexlevel > paramsScope)
4371 t->guards = guardSet_levelUnion (t->guards, utab->guards, t->lexlevel);
4372 t->aliases = aliasTable_levelUnionSeq (t->aliases, utab->aliases,
4374 utab->aliases = aliasTable_undefined;
4377 t->mustBreak = utab->mustBreak;
4378 t->exitCode = utab->exitCode;
4380 DPRINTF (("Free level [%p]", utab));
4381 usymtab_freeLevel (utab);
4386 usymtab_checkAllValid ();
4391 ** Exit a scope with no checking, lose alias states.
4392 ** (When should this be used?)
4395 void usymtab_quietPlainExitScope (void)
4396 /*@globals utab, globtab, filetab@*/
4399 usymtab t = utab->env;
4401 llassert (t != NULL);
4402 llassert (NOALIAS (utab->aliases, t->aliases));
4403 usymtab_freeLevel (utab);
4407 void usymtab_exitScope (exprNode expr)
4408 /*@globals utab, filetab, globtab@*/
4409 /*@modifies utab, globtab@*/
4411 usymtab ctab = usymtab_undefined;
4412 usymtab lctab = usymtab_undefined;
4413 bool mustReturn = exprNode_mustEscape (expr);
4415 DPRINTF (("Exit scope [%p]", utab));
4417 if (utab->kind == US_CBRANCH)
4420 ** save the case branches, remove the first non-cbranch
4425 while (utab->kind == US_CBRANCH)
4429 llassert (utab != GLOBAL_ENV);
4433 if (utab->kind == US_TBRANCH || utab->kind == US_FBRANCH
4434 || utab->kind == US_CBRANCH || utab->kind == US_SWITCH)
4436 if (context_inMacro ())
4438 /* evs 2000-07-25 */
4439 /* Unparseable macro may end inside nested scope. Deal with it. */
4441 llerror (FLG_SYNTAX,
4442 message ("Problem parsing macro body of %s (unbalanced scopes). "
4443 "Attempting to recover, recommend /*@notfunction@*/ before "
4444 "macro definition.",
4445 context_inFunctionName ()));
4447 while (utab->kind == US_TBRANCH
4448 || utab->kind == US_FBRANCH
4449 || utab->kind == US_CBRANCH
4450 || utab->kind == US_SWITCH)
4453 llassert (utab != GLOBAL_ENV);
4457 llcontbug (message ("exitScope: in branch: %q", usymtab_unparseStack ()));
4459 } /*@=branchstate@*/
4463 ** check all variables in scope were used
4467 ** bogus errors if this is the normal inside a switch,
4468 ** since cases have not been merged yet. Should probably
4469 ** still check this, but I'm too lazy at the moment...
4472 llassertfatal (utab->env != GLOBAL_ENV);
4474 if (utab->env->kind != US_SWITCH)
4480 ** check aliasing: all only params are released (dead)
4481 ** definition: all out params are defined, all modified params
4482 ** are completely defined
4484 ** NOTE: note for exiting paramsScope, since checkReturn should be
4488 if (!mustReturn && (usymtab_lexicalLevel () > functionScope))
4491 ** should only call this is end of scope is reachable...
4494 usymtab_checkFinalScope (FALSE);
4497 if (usymtab_lexicalLevel () == paramsScope && context_inFunctionLike ())
4500 ** leaving a function, need to fix up globals
4503 uentryList params = context_getParams ();
4504 globSet globs = context_getUsedGlobs ();
4506 uentryList_elements (params, ue)
4508 uentry_fixupSref (ue);
4509 } end_uentryList_elements;
4511 clearFunctionTypes ();
4513 DPRINTF (("Fixing up globals: %s", globSet_unparse (globs)));
4515 globSet_allElements (globs, el)
4517 DPRINTF (("Fix: %s", sRef_unparseDebug (el)));
4519 if (sRef_isCvar (el))
4522 usymId index = sRef_getScopeIndex (el);
4524 if (sRef_isFileStatic (el))
4526 llassert (usymtab_isDefined (filetab));
4527 current = usymtab_fetchIndex (filetab, index);
4531 current = usymtab_fetchIndex (globtab, index);
4534 if (uentry_isVariable (current))
4536 DPRINTF (("Fixup: %s", uentry_unparse (current)));
4537 uentry_fixupSref (current);
4541 DPRINTF (("Clear: %s", uentry_getSref (current)));
4542 sRef_clearDerived (uentry_getSref (current));
4546 sRef_clearDerived (el); /* evans 2002-03-14 - this is the likely source of many crashes! */
4547 } end_globSet_allElements;
4550 usymtab_quietExitScope (exprNode_loc (expr));
4552 if (lctab != usymtab_undefined)
4554 /*@i@*/ lctab->env = utab;
4555 /*@i@*/ utab = ctab;
4556 /*@-branchstate@*/ } /*@=branchstate@*/
4561 usymtab_checkAllValid ();
4567 ** yikes! don't let the '170 kids see this one...
4571 usymtab_directParamNo (uentry ue)
4573 if (uentry_isVar (ue))
4575 sRef sr = uentry_getSref (ue);
4577 if (sRef_lexLevel (sr) == functionScope)
4579 usymId index = sRef_getScopeIndex (sr);
4581 if (index < usymId_fromInt (uentryList_size (context_getParams ())))
4587 return usymId_invalid;
4590 /*@dependent@*/ /*@exposed@*/ uentry
4591 usymtab_getParam (int paramno)
4595 ** requires in a function context (checked)
4597 ** depends on no nested functions --- the function
4598 ** parameters are ALWAYS one scope inside the global scope
4599 ** and entered in order!
4603 if (!context_inFunctionLike ())
4604 llfatalbug (message ("usymtab_getParam: not in function context: %q",
4605 context_unparse ()));
4607 while (s->lexlevel > paramsScope)
4612 llassert (usymtab_isDefined (s));
4614 if (paramno >= s->nentries)
4617 ** Parse errors lead to this.
4620 uentry err = uentry_makeVariableLoc (cstring_makeLiteralTemp ("<error>"),
4623 uentry_markOwned (err);
4627 return (s->entries[paramno]);
4630 static /*@dependent@*/ /*@exposed@*/ uentry
4631 usymtab_getRefTab (/*@notnull@*/ usymtab u, int level, usymId index)
4635 ue = usymtab_getRefNoisy (u, level, index);
4637 if (uentry_isUndefined (ue))
4639 llbug (message ("usymtab_getRef: out of range: %d. level = %d",
4646 static /*@dependent@*/ /*@exposed@*/ usymtab
4647 usymtab_dropEnv (/*@notnull@*/ usymtab s)
4649 if (s->kind == US_CBRANCH)
4657 llassert (s != GLOBAL_ENV);
4658 } while (s->kind == US_CBRANCH);
4659 /* drop all cases (except in nested scopes */
4662 llassert (s != GLOBAL_ENV);
4665 if (s->kind == US_FBRANCH)
4667 s = s->env; /* skip the true branch */
4668 llassert (usymtab_isDefined (s));
4669 llassert (s->kind == US_TBRANCH);
4672 llassert (s != GLOBAL_ENV);
4678 /*@dependent@*/ /*@exposed@*/ uentry
4679 usymtab_getRefQuiet (int level, usymId index)
4685 llassert (s != NULL);
4686 llassert (index >= 0);
4688 if (level > s->lexlevel)
4690 return uentry_undefined;
4693 llassertprint (level <= s->lexlevel, ("level: %d / lexlevel: %d",
4694 level, s->lexlevel));
4696 while (s->lexlevel > level)
4698 if (usymtab_isBranch (s))
4700 int eindex = refTable_lookup (s, level, index);
4702 if (eindex != NOT_FOUND)
4704 return (s->entries[eindex]);
4708 s = usymtab_dropEnv (s);
4711 while (usymtab_isBranch (s) && s->lexlevel == level)
4713 int eindex = refTable_lookup (s, level, index);
4715 if (eindex != NOT_FOUND)
4717 return (s->entries[eindex]);
4720 s = usymtab_dropEnv (s);
4723 if (index >= usymId_fromInt (s->nentries))
4725 return uentry_undefined;
4728 llassert (!uentry_isUndefined (s->entries[index]));
4730 return s->entries[index];
4733 static /*@dependent@*/ /*@exposed@*/ uentry
4734 usymtab_getRefNoisy (/*@notnull@*/ usymtab s, int level, usymId index)
4737 uentry ue = uentry_undefined;
4739 llassert (index >= 0);
4741 while (s->lexlevel > level)
4743 if (usymtab_isBranch (s))
4745 int eindex = refTable_lookup (s, level, index);
4747 if (eindex != NOT_FOUND)
4749 ue = s->entries[eindex];
4753 while (!usymtab_isBranch (otab))
4755 otab = usymtab_dropEnv (otab);
4756 llassert (otab != GLOBAL_ENV);
4759 if (refTable_lookup (otab, level, index) == NOT_FOUND)
4761 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4773 s = usymtab_dropEnv (s);
4776 llassert (usymtab_isDefined (s));
4778 while (usymtab_isBranch (s) && s->lexlevel == level)
4780 int eindex = refTable_lookup (s, level, index);
4782 if (eindex != NOT_FOUND)
4784 ue = s->entries[eindex];
4788 while (!usymtab_isBranch (otab))
4790 otab = usymtab_dropEnv (otab);
4791 llassert (otab != GLOBAL_ENV);
4794 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4804 s = usymtab_dropEnv (s);
4807 if (s->lexlevel == level && (index < usymId_fromInt (s->nentries)))
4809 ue = s->entries[index];
4811 if (uentry_isValid (ue))
4815 while (!usymtab_isBranch (otab))
4817 otab = usymtab_dropEnv (otab);
4819 if (otab == GLOBAL_ENV)
4825 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4836 if (index >= usymId_fromInt (s->nentries))
4838 return uentry_undefined;
4841 llassert (!uentry_isUndefined (s->entries[index]));
4843 return s->entries[index];
4847 ** looking up entries
4849 ** If entry is inside a branch, then copy it, and put it into
4850 ** the branch table.
4854 int refTable_lookup (/*@notnull@*/ usymtab ut, int level, usymId index)
4856 refTable rt = ut->reftable;
4859 llassert (rt != NULL);
4861 for (i = 0; i < ut->nentries; i++)
4863 if (rt[i]->level == level && rt[i]->index == usymId_toInt (index))
4873 /*@only@*/ refentry refentry_create (int level, int index)
4875 refentry r = (refentry) dmalloc (sizeof (*r));
4883 static /*@dependent@*/ /*@exposed@*/ uentry
4884 usymtab_addRefEntry (/*@notnull@*/ usymtab s, cstring k)
4888 if (ut->reftable == NULL)
4890 DPRINTF (("Adding ref entry without reftable: %s", k));
4891 return uentry_undefined;
4894 llassert (ut->reftable != NULL);
4896 while (s != GLOBAL_ENV)
4898 usymId eindex = usymtab_getIndex (s, k);
4900 if (usymtab_indexFound (eindex))
4902 uentry current = s->entries[eindex];
4904 if (uentry_isVar (current) && !ctype_isFunction (uentry_getType (current)))
4908 DPRINTF (("Here: copying %s", uentry_unparse (current)));
4909 if (uentry_isNonLocal (current))
4911 ue = uentry_copy (current);
4915 ue = uentry_copyNoSave (current);
4918 DPRINTF (("Here: copying %s", uentry_unparse (ue)));
4919 usymtab_addEntryQuiet (ut, ue);
4920 DPRINTF (("Okay..."));
4922 if (s->reftable != NULL)
4924 refentry ref = s->reftable[eindex];
4926 ut->reftable[ut->nentries - 1]
4927 = refentry_create (ref->level, ref->index);
4931 ut->reftable[ut->nentries - 1]
4932 = refentry_create (s->lexlevel, usymId_toInt (eindex));
4943 s = usymtab_dropEnv (s);
4946 return uentry_undefined;
4949 static uentry usymtab_lookupAux (usymtab s, cstring k)
4951 DPRINTF (("Lookup: %s", k));
4953 while (s != GLOBAL_ENV)
4955 usymId eindex = usymtab_getIndex (s, k);
4957 if (usymtab_indexFound (eindex))
4959 uentry ret = s->entries[eindex];
4963 if (s->kind == US_TBRANCH
4964 || s->kind == US_FBRANCH
4965 || s->kind == US_CBRANCH)
4966 /* uentry_isGlobalVariable (ret) && os->lexlevel > fileScope) */
4969 DPRINTF (("Adding global ref entry: %s", k));
4970 ret = usymtab_addRefEntry (os, k);
4971 DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
4976 DPRINTF (("Found: %s", uentry_unparseFull (ret)));
4980 if (s->kind == US_TBRANCH || s->kind == US_FBRANCH
4981 || s->kind == US_CBRANCH)
4983 /* why isn't this os??? */
4984 uentry ret = usymtab_addRefEntry (s, k);
4985 DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
4992 return uentry_undefined;
4995 static /*@dependent@*/ /*@exposed@*/ uentry
4996 usymtab_lookupQuietAux (usymtab s, cstring k, bool noalt)
4998 while (s != GLOBAL_ENV)
5000 usymId eindex = usymtab_getIndex (s, k);
5002 if (usymtab_indexFound (eindex))
5004 uentry ret = s->entries[eindex];
5008 if (noalt && usymtab_isBranch (s))
5010 s = usymtab_dropEnv (s);
5014 llassert (s != NULL);
5019 return uentry_undefined;
5022 static /*@exposed@*/ /*@dependent@*/ uentry
5023 usymtab_lookupQuiet (usymtab s, cstring k)
5025 return usymtab_lookupQuietAux (s, k, FALSE);
5028 static /*@exposed@*/ /*@dependent@*/ uentry
5029 usymtab_lookupQuietNoAlt (usymtab s, cstring k)
5031 return usymtab_lookupQuietAux (s, k, TRUE);
5034 /*@dependent@*/ /*@observer@*/ uentry
5035 usymtab_lookupSafe (cstring k)
5038 DPRINTF (("Lookup safe: %s", k));
5039 return (usymtab_lookupAux (utab, k));
5043 usymtab_lookupExpose (cstring k)
5046 uentry ce = usymtab_lookupAux (utab, k);
5048 if (uentry_isUndefined (ce))
5050 llfatalbug (message ("usymtab_lookup: not found: *%s*", k));
5053 if (uentry_isPriv (ce))
5055 llfatalbug (message ("usymtab_lookup: private: *%s*", k));
5061 uentry usymtab_lookupExposeGlob (cstring k)
5063 return (usymtab_lookupGlobSafe (k));
5066 uentry usymtab_lookupGlob (cstring k)
5067 /*@globals globtab@*/
5069 uentry ce = usymtab_lookupAux (globtab, k);
5071 if (uentry_isUndefined (ce))
5072 llfatalbug (message ("usymtab_lookup: not found: %s", k));
5074 if (uentry_isPriv (ce))
5075 llfatalbug (message ("usymtab_lookup: private: %s", k));
5077 DPRINTF (("Lookup global: %s", uentry_unparseFull (ce)));
5081 /*@observer@*/ uentry
5082 usymtab_lookupGlobSafe (cstring k)
5083 /*@globals globtab@*/
5085 uentry ce = usymtab_lookupAux (globtab, k);
5086 DPRINTF (("Lookup global: %s", uentry_unparseFull (ce)));
5090 uentry usymtab_lookupEither (cstring k)
5093 uentry ce = usymtab_lookupSafe (k);
5095 if (uentry_isUndefined (ce))
5096 llfatalerror (message ("usymtab_lookup: not found: %s", k));
5098 DPRINTF (("Lookup either: %s", uentry_unparseFull (ce)));
5103 usymtab_lookupType (cstring k)
5104 /*@globals globtab@*/
5106 typeId uid = usymtab_getTypeId (k);
5108 if (typeId_isInvalid (uid))
5110 llcontbug (message ("usymtab_lookupType: not found: %s", k));
5111 return ctype_unknown;
5114 return (uentry_getRealType (usymtab_getTypeEntry (uid)));
5118 usymtab_lookupAbstractType (cstring k) /*@globals globtab@*/
5120 typeId uid = usymtab_getTypeId (k);
5122 if (typeId_isInvalid (uid))
5124 llcontbug (message ("usymtab_lookupType: not found: %s", k));
5125 return ctype_unknown;
5128 return (uentry_getAbstractType (usymtab_getTypeEntry (uid)));
5132 ** if there is an unnamed lcl-specified struct tag matching
5133 ** the uentryList, return its datatype. Otherwise, returns
5138 usymtab_structFieldsType (uentryList f)
5139 /*@globals globtab@*/
5141 return (usymtab_suFieldsType (f, TRUE));
5145 usymtab_unionFieldsType (uentryList f)
5146 /*@globals globtab@*/
5148 return (usymtab_suFieldsType (f, FALSE));
5152 usymtab_suFieldsType (uentryList f, bool isStruct)
5153 /*@globals globtab@*/
5157 DPRINTF (("Fields: %s", uentryList_unparse (f)));
5159 if (fileloc_isSpec (g_currentloc))
5161 return (ctype_undefined);
5164 for (i = 0; i < globtab->nentries; i++)
5166 uentry current = globtab->entries[i];
5169 ? uentry_isStructTag (current) : uentry_isUnionTag (current)))
5171 if (isFakeTag (uentry_rawName (current)))
5173 ctype ct = uentry_getType (current);
5175 DPRINTF (("Check: %s", ctype_unparse (ct)));
5177 if ((isStruct ? ctype_isStruct (ct) : ctype_isUnion (ct))
5179 (uentry_isSpecified (current)
5180 && uentryList_equivFields (f, ctype_getFields (ct))))
5182 return uentry_getAbstractType (current);
5192 return ctype_undefined;
5196 usymtab_enumEnumNameListType (enumNameList f)
5197 /*@globals globtab@*/
5201 for (i = 0; i < globtab->nentries; i++)
5203 uentry current = globtab->entries[i];
5205 if (uentry_isEnumTag (current))
5207 if (isFakeTag (uentry_rawName (current)))
5209 ctype ct = uentry_getType (current);
5211 if (ctype_isEnum (ct) && (enumNameList_match (f, ctype_elist (ct))))
5213 return uentry_getType (current);
5219 return ctype_undefined;
5223 usymtab_exists (cstring k)
5226 uentry ce = usymtab_lookupSafe (k);
5227 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5231 usymtab_existsReal (cstring k)
5234 uentry ce = usymtab_lookupSafe (k);
5236 return (!(uentry_isUndefined (ce))
5237 && !(uentry_isPriv (ce))
5238 && !(uentry_isExpandedMacro (ce)));
5242 usymtab_existsGlob (cstring k)
5243 /*@globals globtab@*/
5245 uentry ce = usymtab_lookupAux (globtab, k);
5247 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5251 usymtab_existsEither (cstring k)
5254 uentry ce = usymtab_lookupAux (utab, k);
5256 return (uentry_isValid (ce));
5260 usymtab_existsGlobEither (cstring k)
5261 /*@globals globtab@*/
5263 uentry ce = usymtab_lookupAux (globtab, k);
5265 return (uentry_isValid (ce));
5269 usymtab_existsType (cstring k)
5270 /*@globals globtab@*/
5272 uentry ce = usymtab_lookupAux (globtab, k);
5274 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && uentry_isDatatype (ce));
5278 usymtab_existsTypeEither (cstring k)
5279 /*@globals globtab@*/
5282 ce = usymtab_lookupAux (globtab, k);
5283 return (uentry_isValid (ce) && uentry_isDatatype (ce));
5287 usymtab_existsStructTag (cstring k) /*@globals globtab@*/
5289 cstring sname = makeStruct (k);
5290 uentry ce = usymtab_lookupAux (globtab, sname);
5291 cstring_free (sname);
5292 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5296 usymtab_existsUnionTag (cstring k) /*@globals globtab@*/
5298 cstring uname = makeUnion (k);
5299 uentry ce = usymtab_lookupAux (globtab, uname);
5301 cstring_free (uname);
5303 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5307 usymtab_existsEnumTag (cstring k) /*@globals globtab@*/
5309 cstring ename = makeEnum (k);
5310 uentry ce = usymtab_lookupAux (globtab, ename);
5312 cstring_free (ename);
5313 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5316 bool usymtab_existsVar (cstring k)
5319 uentry ce = usymtab_lookupSafe (k);
5321 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && (uentry_isVar (ce)));
5329 refTable_free (/*@only@*/ /*@null@*/ refTable x, int nentries)
5335 for (i = 0; i < nentries; i++)
5345 usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab u)
5346 /*@globals globtab, utab, filetab@*/
5350 DPRINTF (("Free level [%p]", u));
5351 aliasTable_free (u->aliases);
5353 refTable_free (u->reftable, u->nentries);
5355 if (u == filetab || u == globtab)
5357 for (i = 0; i < u->nentries; i++)
5359 DPRINTF (("Free complete: %d", i));
5360 DPRINTF (("Uentry: %s", uentry_unparse (u->entries[i])));
5361 uentry_freeComplete (u->entries[i]);
5362 u->entries[i] = uentry_undefined;
5367 for (i = 0; i < u->nentries; i++)
5369 uentry_free (u->entries[i]);
5370 u->entries[i] = uentry_undefined;
5374 guardSet_free (u->guards);
5381 llassert (!cstringTable_isDefined (u->htable));
5384 sfree (u); /* evans 2002-07-12: was inside if */
5388 usymtab_freeAux (/*@only@*/ usymtab u)
5389 /*@globals globtab, utab, filetab@*/
5392 while (u != GLOBAL_ENV)
5395 usymtab_freeLevel (u);
5402 void usymtab_free ()
5403 /*@globals killed utab, globtab, filetab@*/
5407 usymtab_freeAux (utab);
5408 utab = usymtab_undefined;
5410 } /*@=globstate@*/ /* Splint cannot tell that utab is killed */
5412 static int usymtab_lexicalLevel (void) /*@globals utab@*/
5414 return (utab->lexlevel);
5417 bool usymtab_inGlobalScope () /*@globals utab, globtab@*/
5419 return (utab == globtab);
5422 bool usymtab_inFileScope () /*@globals utab@*/
5424 return (utab->lexlevel == fileScope);
5427 bool usymtab_inFunctionScope () /*@globals utab@*/
5429 return (utab->lexlevel == functionScope);
5433 usymtab_replaceEntry (uentry s)
5434 /*@globals utab, globtab@*/
5435 /*@modifies utab, s@*/
5437 usymtab_replaceEntryAux (utab, s);
5441 usymtab_matchForwardStruct (typeId u1, typeId u2)
5442 /*@globals globtab@*/
5444 uentry ue1 = usymtab_getTypeEntry (u1);
5445 uentry ue2 = usymtab_getTypeEntry (u2);
5447 if (uentry_isAnyTag (ue2))
5449 ctype reptype = uentry_getType (ue1);
5451 if (ctype_isPointer (reptype))
5453 ctype repbase = ctype_getBaseType (reptype);
5455 if (ctype_isUA (repbase))
5457 typeId rtuid = ctype_typeId (repbase);
5459 if (u2 == rtuid) return TRUE;
5461 if (typeId_isValid (rtuid))
5463 reptype = uentry_getType (usymtab_getTypeEntry (rtuid));
5464 return (ctype_isUA (reptype) && (u2 == (ctype_typeId (reptype))));
5473 void usymtab_addGuards (guardSet guards)
5476 utab->guards = guardSet_union (utab->guards, guards);
5479 static bool usymtab_isGuardedAux (sRef s)
5483 sRef base = sRef_getRootBase (s);
5484 int lowlevel = paramsScope;
5485 int baselevel = sRef_lexLevel (base);
5487 if (sRef_isCvar (base))
5489 lowlevel = baselevel;
5490 if (lowlevel < paramsScope) lowlevel = paramsScope;
5493 while (tab->lexlevel >= lowlevel)
5495 DPRINTF (("Is guarded? [%s] %s",
5496 guardSet_unparse (tab->guards),
5497 sRef_unparseFull (s)));
5499 if (guardSet_isGuarded (tab->guards, s))
5502 if (!sRef_definitelyNull (s))
5504 sRef_setNotNull (s, fileloc_undefined);
5510 tab = usymtab_dropEnv (tab);
5516 void usymtab_unguard (sRef s) /*@modifies utab@*/
5519 sRef base = sRef_getRootBase (s);
5520 int lowlevel = paramsScope;
5521 int baselevel = sRef_lexLevel (base);
5523 if (sRef_isCvar (base))
5525 lowlevel = baselevel;
5526 if (lowlevel < paramsScope) lowlevel = paramsScope;
5529 while (tab->lexlevel >= lowlevel)
5531 if (guardSet_isGuarded (tab->guards, s))
5533 guardSet_delete (tab->guards, s);
5536 tab = usymtab_dropEnv (tab);
5540 bool usymtab_isGuarded (sRef s)
5542 DPRINTF (("Is guarded? %s", sRef_unparseFull (s)));
5543 return (sRef_aliasCompleteSimplePred (usymtab_isGuardedAux, s));
5546 bool usymtab_isDefinitelyNull (sRef s)
5548 return (sRef_aliasCheckSimplePred (usymtab_isDefinitelyNullAux, s));
5551 bool usymtab_isDefinitelyNullDeep (sRef s)
5553 return (sRef_deepPred (usymtab_isDefinitelyNull, s));
5556 static bool usymtab_isDefinitelyNullAux (sRef s)
5560 sRef base = sRef_getRootBase (s);
5561 int lowlevel = paramsScope;
5563 if (sRef_isCvar (base))
5565 lowlevel = sRef_lexLevel (base);
5566 if (lowlevel < paramsScope) lowlevel = paramsScope;
5569 while (tab->lexlevel >= lowlevel)
5571 if (guardSet_mustBeNull (tab->guards, s))
5576 while (tab->kind == US_CBRANCH)
5581 llassert (usymtab_isDefined (tab));
5583 if (tab->kind == US_FBRANCH)
5586 llassert (tab->kind == US_TBRANCH);
5596 usymtab_printGuards ()
5597 /*@globals utab, globtab@*/
5599 usymtab ttab = utab;
5601 while (ttab != globtab)
5603 llmsg (message ("Guards [%d]: %q", ttab->lexlevel,
5604 guardSet_unparse (ttab->guards)));
5610 usymtab_displayAllUses ()
5611 /*@globals utab, globtab@*/
5615 /* only in top scope */
5616 llassert (utab == globtab);
5618 /* need a copy, so order is not messed up by sort! */
5619 copy = usymtab_shallowCopy (globtab);
5621 qsort (copy->entries, (size_t)copy->nentries,
5622 sizeof (*copy->entries), (int (*)(const void *, const void *)) uentry_xcompareuses);
5624 usymtab_entries (copy, ue)
5626 if (uentry_isValid (ue) && !uentry_isGlobalMarker (ue))
5628 filelocList uses = uentry_getUses (ue);
5629 int size = filelocList_realSize (uses);
5631 if (fileloc_isDefined (uentry_whereDefined (ue))
5632 && !fileloc_isLib (uentry_whereDefined (ue))
5635 llmsg (message ("%q (%q), %d use%&:\n %q",
5636 uentry_getName (ue),
5637 fileloc_unparse (uentry_whereDefined (ue)),
5638 size, filelocList_unparseUses (uses)));
5641 } end_usymtab_entries;
5643 usymtab_shallowFree (copy);
5646 static /*@dependent@*/ /*@exposed@*/ usymtab
5647 usymtab_getFileTab ()
5648 /*@globals filetab@*/
5650 llassert (filetab != NULL);
5656 usymtab_unparseStack ()
5659 return (usymtab_unparseStackTab (utab));
5662 static /*@only@*/ cstring
5663 usymtab_unparseStackTab (usymtab t)
5665 bool firstOne = TRUE;
5666 cstring ret = cstring_makeLiteral ("[");
5668 while (t != GLOBAL_ENV)
5672 ret = message ("%q %q", ret, usymtab_typeName (t));
5677 ret = message ("%q, %q", ret, usymtab_typeName (t));
5682 ret = message ("%q ]", ret);
5686 static /*@only@*/ cstring
5687 usymtab_typeName (/*@notnull@*/ usymtab t)
5691 case US_GLOBAL: return cstring_makeLiteral ("global");
5692 case US_NORMAL: return cstring_makeLiteral ("normal");
5693 case US_TBRANCH: return cstring_makeLiteral ("true");
5694 case US_FBRANCH: return cstring_makeLiteral ("false");
5695 case US_CBRANCH: return cstring_makeLiteral ("case");
5696 case US_SWITCH: return cstring_makeLiteral ("switch");
5702 void usymtab_addMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5705 if (!sRef_similar (s, al))
5707 usymtab_addForceMustAlias (s, al);
5712 ** Same as usymtab_addMustAlias, except does not check sRef_isSimilar.
5715 void usymtab_addForceMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5718 /* evans 2002-03-3: was sRef_isMeaningful -- but we need to keep aliases for new storage also! */
5719 if (sRef_isMeaningful (s)
5720 && sRef_isMeaningful (al)
5721 && !(sRef_isConst (s) || sRef_isConst (al))
5722 && !(sRef_isAddress (al) && sRef_isDirectParam (sRef_getBase (al))))
5724 utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
5725 DPRINTF (("Must alias: %s", aliasTable_unparse (utab->aliases)));
5728 ** for local variable, aliasing is symmetric
5731 if (sRef_isLocalVar (s) && sRef_isLocalVar (al))
5733 utab->aliases = aliasTable_addMustAlias (utab->aliases, al, s);
5738 DPRINTF (("Not aliasing! %s / %s", sRef_unparseFull (s), sRef_unparseFull (al)));
5739 DPRINTF (("meaningful: %d %d", sRef_isMeaningful (s), sRef_isMeaningful (al)));
5743 void usymtab_addReallyForceMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5746 utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
5749 void usymtab_clearAlias (sRef s)
5750 /*@modifies utab, s@*/
5753 aliasTable_clearAliases (utab->aliases, s);
5756 sRefSet usymtab_allAliases (sRef s)
5759 if (sRef_isSomewhatMeaningful (s))
5763 ret = sRefSet_unionFree (aliasTable_aliasedBy (utab->aliases, s),
5764 aliasTable_canAlias (utab->aliases, s));
5769 DPRINTF (("NOT A MEANINGFUL SREF!"));
5770 return sRefSet_undefined;
5774 /*@only@*/ sRefSet usymtab_canAlias (sRef s)
5777 if (sRef_isSomewhatMeaningful (s))
5779 sRefSet res = aliasTable_canAlias (utab->aliases, s);
5783 return sRefSet_undefined;
5786 /*@only@*/ sRefSet usymtab_aliasedBy (sRef s)
5789 return (aliasTable_aliasedBy (utab->aliases, s));
5792 /*@only@*/ cstring usymtab_unparseAliases ()
5795 return (aliasTable_unparse (utab->aliases));
5799 ** Debugging routines:
5800 ** okay to leak storage here, only for debugging
5806 usymtab_printOut (void)
5812 char *ind = mstring_copy (" ");
5814 fprintf (g_warningstream, "<<< [symbol table] >>>\n");
5816 while (s != GLOBAL_ENV && s->env != GLOBAL_ENV)
5818 cstring tname = usymtab_typeName (s);
5822 ind[depth * 3 + 1] = '\0';
5825 fprintf (g_warningstream, "level: %d (%s)\n", s->lexlevel,
5826 cstring_toCharsSafe (tname));
5828 cstring_free (tname);
5830 for (i = 0; i < s->nentries; i++)
5832 cstring us = uentry_unparseFull (s->entries[i]);
5833 fprintf (g_warningstream, "%s\n", cstring_toCharsSafe (us));
5837 if (s->reftable != NULL && s->nentries > 0)
5839 fprintf (g_warningstream, "\t<< Ref table >>\n");
5841 for (i = 0; i < s->nentries; i++)
5843 fprintf (g_warningstream, "\t%s %3d: %d, %d\n", ind, i,
5844 s->reftable[i]->level,
5845 s->reftable[i]->index);
5849 ind[depth * 3 + 1] = ' ';
5853 fprintf (g_warningstream, "<<< end usymtab >>>\n");
5859 usymtab_printTypes ()
5860 /*@globals globtab@*/
5862 usymtab_printAllAux (globtab);
5866 usymtab_printAll (void)
5869 usymtab_printAllAux (utab);
5873 usymtab_printAllAux (usymtab s)
5874 /*@modifies g_warningstream@*/
5878 char *ind = mstring_copy (" ");
5880 printf ("[[[ usymtab ]]]");
5882 while (s != GLOBAL_ENV)
5885 ind[depth * 3 + 1] = '\0';
5887 if (s->env == GLOBAL_ENV)
5891 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5892 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5893 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5897 for (i = looplow; i < s->nentries; i++)
5899 printf ("%s%3d. %s\n", ind, i,
5900 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5905 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5906 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5907 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5909 for (i = 0; i < s->nentries; i++)
5911 printf ("%s%3d %s\n", ind, i,
5912 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5916 ind[depth * 3 + 1] = ' ';
5920 printf ("----------\n");
5924 usymtab_printComplete ()
5929 char *ind = mstring_copy (" ");
5932 while (s != GLOBAL_ENV)
5936 ind[depth * 3 + 1] = '\0';
5939 if (s->env == GLOBAL_ENV)
5943 printf ("level: %d\n", s->lexlevel);
5947 for (i = looplow; i < s->nentries; i++)
5949 printf ("%s%3d %s\n", ind, i,
5950 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5955 printf ("level: %d\n", s->lexlevel);
5956 for (i = 0; i < s->nentries; i++)
5958 printf ("%s%3d %s\n", ind, i,
5959 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5963 ind[depth * 3 + 1] = ' ';
5968 printf ("----------\n");
5973 static /*@only@*/ cstring /*@unused@*/
5974 usymtab_unparseLocalAux (/*@notnull@*/ usymtab s)
5976 cstring c = message ("lexlevel: %d\n", s->lexlevel);
5979 for (i = 0; i < s->nentries; i++)
5981 c = message ("%q\n%q", c, uentry_unparseFull (s->entries[i]));
5984 c = message ("%q\n=========", c);
5988 static cstring /*@unused@*/ /*@only@*/
5989 usymtab_unparseLocalList (/*@notnull@*/ usymtab s)
5991 cstring c = message ("[%d/%s/%s] ", s->lexlevel,
5992 bool_unparse (s->mustBreak),
5993 exitkind_unparse (s->exitCode));
5996 for (i = 0; i < s->nentries; i++)
5998 sRef sr = uentry_getSref (s->entries[i]);
6002 c = message ("%q: %q [%b]", c, uentry_getName (s->entries[i]),
6003 sRef_isStateDefined (sr));
6007 c = message ("%q, %q [%b]", c, uentry_getName (s->entries[i]),
6008 sRef_isStateDefined (sr));
6018 usymtab_printLocal (void)
6024 printf ("lexlevel: %d\n", s->lexlevel);
6026 for (i = 0; i < s->nentries; i++)
6028 printf ("%s\n", cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
6031 while (s->lexlevel > 1)
6036 llassert (usymtab_isDefined (s));
6038 printf ("Params:\n");
6040 for (i = 0; i < s->nentries; i++)
6042 printf ("%d: %s\n", i,
6043 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
6048 static bool checkDistinctExternalName (uentry e)
6049 /*@globals globtab@*/
6050 /*@modifies *g_warningstream@*/
6052 size_t checklen = size_fromInt (context_getValue (FLG_EXTERNALNAMELEN));
6053 bool ignorecase = context_getFlag (FLG_EXTERNALNAMECASEINSENSITIVE);
6054 bool gotone = FALSE;
6055 bool extras = FALSE;
6056 bool hasError = FALSE;
6057 cstring name = uentry_rawName (e);
6058 usymtab st = globtab;
6066 if (uentry_isAnyTag (e))
6068 checklen++; /* the tag marker doesn't count */
6072 usymtab_entries (st, oe)
6074 if (uentry_sameObject (oe, e))
6081 if (cstring_equalCaseInsensitive (uentry_rawName (oe), name))
6090 (FLG_DISTINCTEXTERNALNAMES,
6092 ("External identifier %q is not distinguishable from %q "
6093 "because alphabetical case is ignored",
6095 uentry_getName (oe)),
6096 uentry_whereLast (e)))
6098 uentry_showWhereAny (oe);
6099 uentry_setHasNameError (oe);
6108 if (cstring_equalLenCaseInsensitive (uentry_rawName (oe),
6117 if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6120 (FLG_DISTINCTEXTERNALNAMES,
6123 ("External identifier %q is not distinguishable from %q "
6124 "in the first %d characters (%q)",
6126 uentry_getName (oe),
6127 size_toInt (checklen),
6128 cstring_clip (uentry_getName (e), checklen)),
6130 uentry_whereLast (e)))
6132 uentry_showWhereAny (oe);
6133 uentry_setHasNameError (oe);
6146 (FLG_DISTINCTEXTERNALNAMES,
6148 ("External identifier %q is not distinguishable from %q "
6149 "in the first %d characters because alphabetical case "
6152 uentry_getName (oe),
6153 size_toInt (checklen)),
6154 uentry_whereLast (e)))
6156 uentry_showWhereAny (oe);
6157 uentry_setHasNameError (oe);
6163 else if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6172 (FLG_DISTINCTEXTERNALNAMES,
6175 ("External identifier %q is not distinguishable from %q "
6176 "in the first %d characters (%q)",
6178 uentry_getName (oe),
6179 size_toInt (checklen),
6180 cstring_clip (uentry_getName (e), checklen)),
6182 uentry_whereLast (e)))
6184 uentry_showWhereAny (oe);
6185 uentry_setHasNameError (oe);
6194 } end_usymtab_entries ;
6201 (cstring_makeLiteral ("One or more additional "
6202 "indistinguishable external "
6203 "names not reported"));
6209 static bool checkDistinctInternalName (uentry e)
6211 /*@modifies *g_warningstream@*/
6213 usymtab ttab = utab;
6214 cstring name = uentry_rawName (e);
6215 size_t numchars = size_fromInt (context_getValue (FLG_INTERNALNAMELEN));
6216 bool caseinsensitive = context_getFlag (FLG_INTERNALNAMECASEINSENSITIVE);
6217 bool lookalike = context_getFlag (FLG_INTERNALNAMELOOKALIKE);
6219 if (uentry_isAnyTag (e) && (numchars != 0))
6221 numchars++; /* the tag marker doesn't count */
6224 while (usymtab_isDefined (ttab))
6226 usymtab_entries (ttab, oe)
6228 if (uentry_sameObject (oe, e))
6230 /*@innercontinue@*/ continue;
6233 switch (cstring_genericEqual
6234 (name, uentry_rawName (oe),
6235 numchars, caseinsensitive, lookalike))
6237 case CGE_DISTINCT: /* okay */
6241 if (cstring_equal (name, uentry_rawName (oe)))
6243 ; /* got a shadow error */
6248 (FLG_DISTINCTINTERNALNAMES,
6251 ("Internal identifier %q is not distinguishable from %q "
6252 "in the first %d characters (%q)",
6254 uentry_getName (oe),
6255 size_toInt (numchars),
6256 cstring_clip (uentry_getName (e), numchars)),
6258 uentry_whereLast (e)))
6260 uentry_showWhereAny (oe);
6261 uentry_setHasNameError (oe);
6268 if (numchars == 0 || (cstring_length (name) <= numchars))
6271 (FLG_DISTINCTINTERNALNAMES,
6273 ("Internal identifier %q is not distinguishable from %q "
6274 "without case sensitivity",
6276 uentry_getName (oe)),
6277 uentry_whereLast (e)))
6279 uentry_showWhereAny (oe);
6280 uentry_setHasNameError (oe);
6287 (FLG_DISTINCTINTERNALNAMES,
6289 ("Internal identifier %q is not distinguishable from %q "
6290 "in the first %d characters without case sensitivity",
6292 uentry_getName (oe),
6293 size_toInt (numchars)),
6294 uentry_whereLast (e)))
6296 uentry_showWhereAny (oe);
6297 uentry_setHasNameError (oe);
6305 || (cstring_length (name) <= numchars))
6308 (FLG_DISTINCTINTERNALNAMES,
6310 ("Internal identifier %q is not distinguishable from %q "
6311 "except by lookalike characters",
6313 uentry_getName (oe)),
6314 uentry_whereLast (e)))
6316 uentry_showWhereAny (oe);
6317 uentry_setHasNameError (oe);
6324 (FLG_DISTINCTINTERNALNAMES,
6326 ("Internal identifier %q is not distinguishable from %q "
6327 "in the first %d characters except by lookalike characters",
6329 uentry_getName (oe),
6330 size_toInt (numchars)),
6331 uentry_whereLast (e)))
6333 uentry_showWhereAny (oe);
6334 uentry_setHasNameError (oe);
6339 } end_usymtab_entries ;
6347 void usymtab_checkDistinctName (uentry e, int scope)
6348 /*@globals utab, globtab@*/
6350 bool hasError = FALSE;
6351 fileloc where = uentry_whereLast (e);
6353 if (!fileloc_isPreproc (where) && !fileloc_isBuiltin (where))
6355 if (scope == globScope)
6357 if (context_getFlag (FLG_DISTINCTEXTERNALNAMES))
6359 hasError = checkDistinctExternalName (e);
6363 if (!hasError && context_getFlag (FLG_DISTINCTINTERNALNAMES))
6365 hasError = checkDistinctInternalName (e);
6371 uentry_setHasNameError (e);
6375 /*@exposed@*/ sRef usymtab_lookupGlobalMarker (void) /*@globals utab@*/
6379 ue = usymtab_lookupAux (utab, GLOBAL_MARKER_NAME);
6380 llassert (uentry_isValid (ue));
6382 return uentry_getSref (ue);
6388 ** For debugging only
6392 usymtab_checkAllValid () /*@globals utab@*/
6396 while (tab != GLOBAL_ENV)
6400 for (i = 0; i < utab->nentries; i++)
6402 uentry e = utab->entries[i];
6404 uentry_checkValid (e);
6407 aliasTable_checkValid (tab->aliases);