2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2002 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 extern int usymtab_getCurrentDepth (void) /*@globals utab@*/
110 return utab->lexlevel;
114 usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab p_u)
115 /*@globals globtab, utab, filetab@*/ /*@modifies p_u@*/ ;
117 static bool usymtab_isDefinitelyNullAux (sRef p_s) /*@globals utab@*/ ;
118 static /*@only@*/ cstring usymtab_unparseStackTab (usymtab p_t);
119 static /*@exposed@*/ /*@dependent@*/ uentry
120 usymtab_getRefTab (/*@notnull@*/ usymtab p_u, int p_level, usymId p_index);
123 /* These are not used anymore... */
124 static /*@unused@*/ /*@only@*/ cstring
125 usymtab_unparseLocalAux (/*@notnull@*/ usymtab p_s);
126 static /*@unused@*/ /*@only@*/ cstring
127 usymtab_unparseLocalList (/*@notnull@*/ usymtab p_s);
130 static /*@only@*/ cstring usymtab_typeName (/*@notnull@*/ usymtab p_t);
131 static void usymtab_handleParams (void)
132 /*@globals utab, globtab, filetab@*/
133 /*@modifies utab@*/ ;
135 static /*@exposed@*/ /*@dependent@*/ uentry
136 usymtab_addRefEntry (/*@notnull@*/ usymtab p_s, cstring p_k);
137 static /*@exposed@*/ /*@dependent@*/ usymtab
138 usymtab_dropEnv (/*@notnull@*/ usymtab p_s);
139 static /*@exposed@*/ /*@dependent@*/ uentry
140 usymtab_getRefNoisy (/*@notnull@*/ usymtab p_s, int p_level, usymId p_index);
142 static /*@exposed@*/ /*@dependent@*/ uentry
143 usymtab_lookupQuietAux (usymtab p_s, cstring p_k, bool p_noalt);
145 static /*@exposed@*/ /*@dependent@*/ uentry
146 usymtab_lookupQuiet (usymtab p_s, cstring p_k);
148 static /*@exposed@*/ /*@dependent@*/ uentry
149 usymtab_lookupQuietNoAlt (usymtab p_s, cstring p_k);
151 static void usymtab_printAllAux (usymtab p_s) /*@modifies g_warningstream@*/ ;
152 static int usymtab_getIndex (/*@notnull@*/ usymtab p_s, cstring p_k);
153 static /*@exposed@*/ uentry usymtab_fetchIndex (/*@notnull@*/ usymtab p_s, int p_i);
154 static /*@exposed@*/ uentry
155 usymtab_lookupAux (usymtab p_s, cstring p_k);
156 static /*@exposed@*/ /*@dependent@*/ /*@notnull@*/ usymtab
157 usymtab_getFileTab (void) /*@globals filetab@*/ ;
158 static int refTable_lookup (/*@notnull@*/ usymtab p_ut, int p_level, int p_index);
159 static bool usymtab_mustBreak (usymtab p_s);
160 static bool usymtab_mustEscape (usymtab p_s);
162 static void recordFunctionType (uentry ue)
164 llassert (uentry_isDatatype (ue) || uentry_isAnyTag (ue)
165 || uentry_isEnumConstant (ue));
166 DPRINTF (("Function type: %s", uentry_unparseFull (ue)));
168 functypes = uentryList_add (functypes, ue);
172 static void clearFunctionTypes (void)
173 /*@modifies globtab@*/
175 uentryList_elements (functypes, el)
177 if (cstring_isDefined (uentry_rawName (el)))
179 if (cstringTable_isDefined (globtab->htable))
181 cstringTable_remove (globtab->htable, uentry_rawName (el));
184 uentry_setName (el, cstring_undefined);
188 llassert (uentry_isValid (el));
189 el->sref = sRef_undefined;
190 /*@noaccess uentry@*/
191 } end_uentryList_elements ;
193 uentryList_clear (functypes);
196 static /*@falsewhennull@*/ bool usymtab_isBranch (usymtab u)
198 return (usymtab_isDefined (u) &&
199 (u->kind == US_TBRANCH || u->kind == US_FBRANCH
200 || u->kind == US_CBRANCH || u->kind == US_SWITCH));
203 static bool usymtab_mustBreak (usymtab s)
205 llassert (s != GLOBAL_ENV);
206 return (s->mustBreak);
209 static bool usymtab_mustEscape (usymtab s)
211 llassert (s != GLOBAL_ENV);
212 return (exitkind_mustEscape (s->exitCode));
215 void usymtab_setMustBreak ()
218 llassert (utab != GLOBAL_ENV);
219 utab->mustBreak = TRUE;
222 void usymtab_setExitCode (exitkind ex)
225 llassert (utab != GLOBAL_ENV);
229 if (exitkind_mustEscape (ex))
231 utab->mustBreak = TRUE;
235 bool usymtab_isAltDefinitelyNullDeep (sRef s)
237 return (sRef_deepPred (usymtab_isAltDefinitelyNull, s));
240 static bool usymtab_isAltDefinitelyNull (sRef s)
248 llassert (utab->env != NULL);
250 /*@-mods@*/ /* These modifications are cancelled. */
251 utab->guards = utab->env->guards;
252 utab->env->guards = t;
255 llassert (usymtab_isDefined (utab));
256 res = usymtab_isDefinitelyNull (s);
259 ** This reports a spurious error. It is okay, because of
260 ** the nesting relationship of usymtab environments.
263 /*@-mods@*/ /* Cancelling modifications. */
264 /*@i1@*/ utab->env->guards = utab->guards;
265 /*@i1@*/ utab->guards = t;
271 static /*@notnull@*/ /*@special@*/ usymtab
272 usymtab_create (uskind kind, /*@keep@*/ usymtab env, bool nextlevel)
274 /*@post:isnull result->htable, result->guards, result->aliases@*/
276 usymtab t = (usymtab) dmalloc (sizeof (*t));
279 t->nspace = CBASESIZE;
280 t->entries = (uentry *) dmalloc (sizeof (*t->entries) * CBASESIZE);
282 /* We only use a reftable for branch-level symbol tables.
285 t->reftable = (nextlevel
287 : (refentry *) dmalloc (sizeof (*t->reftable) * CBASESIZE));
290 t->lexlevel = (env == GLOBAL_ENV ? 0 : env->lexlevel) + (nextlevel ? 1 : 0);
295 t->guards = guardSet_undefined;
296 t->aliases = aliasTable_undefined;
298 t->mustBreak = FALSE;
299 t->exitCode = XK_NEVERESCAPE;
308 static /*@only@*/ /*@notnull@*/ usymtab
309 usymtab_createRoot (void) /*@modifies nothing@*/
311 usymtab u = (usymtab) dmalloc (sizeof (*u));
314 u->nspace = CGLOBBASESIZE;
315 u->entries = (uentry *) dmalloc (sizeof (*u->entries) * CGLOBBASESIZE);
318 u->htable = cstringTable_create (CGLOBHASHSIZE);
321 u->guards = guardSet_new ();
322 u->aliases = aliasTable_new ();
324 u->mustBreak = FALSE;
325 u->exitCode = XK_NEVERESCAPE;
332 usymtab_initMod (void)
333 /*@globals undef utab, undef oldtab, undef globtab, undef filetab @*/
334 /*@modifies utab, globtab, filetab, oldtab @*/
336 utab = usymtab_createRoot ();
338 filetab = usymtab_undefined;
339 oldtab = usymtab_undefined;
344 usymtab_initGlobalMarker () /*@globals globtab@*/
346 if (uentry_isValid (usymtab_lookupAux (globtab, GLOBAL_MARKER_NAME)))
348 ; /* Already entered from load table. */
352 usymtab_addGlobalEntry (uentry_makeGlobalMarker ());
357 ** utab should be empty? (requires?)
359 ** Adds bool types to symbol table (these are built in for now)
360 ** Only do this is there is no library!
366 if (context_getFlag (FLG_NOLIB))
368 ctype boolt = ctype_bool;
369 /* evs 2000-07-24: bool is now treated as abstract (always) */
371 uentry boolentry = uentry_makeBoolDatatype (YES);
372 usymtab_supGlobalEntry (boolentry);
373 context_addBoolAccess ();
376 ** We supply values 0 and 1 for the constants, so things like
377 ** while (TRUE) can be interpreted correctly.
380 usymtab_supGlobalEntry
381 (uentry_makeConstantValue (context_getFalseName (), boolt,
382 fileloc_getBuiltin (), FALSE,
383 multiVal_makeInt (0)));
385 usymtab_supGlobalEntry
386 (uentry_makeConstantValue (context_getTrueName (), boolt,
387 fileloc_getBuiltin (), FALSE,
388 multiVal_makeInt (1)));
397 usymtab_grow (/*@notnull@*/ usymtab s)
400 o_uentry *oldsyms = s->entries;
402 s->nspace = CBASESIZE;
403 s->entries = (uentry *) dmalloc (sizeof (*s->entries)
404 * (s->nentries + s->nspace));
406 for (i = 0; i < s->nentries; i++)
408 s->entries[i] = oldsyms[i];
413 if (s->reftable != NULL)
415 refTable oldRefs = s->reftable;
417 s->reftable = (refentry *) dmalloc (sizeof (*s->reftable)
418 * (s->nentries + CBASESIZE + 1));
420 for (i = 0; i < s->nentries; i++)
422 s->reftable[i] = oldRefs[i];
433 usymtab_addEntryQuiet (/*@notnull@*/ usymtab s, /*@keep@*/ uentry e)
435 if (!(s->lexlevel > fileScope || !sRef_modInFunction ()))
437 if (uentry_isDatatype (e)
438 || uentry_isFunction (e)
439 || uentry_isAnyTag (e)
440 || uentry_isEnumConstant (e)
441 || context_inMacro ())
444 ** Not a bug. Code like,
445 ** int f (void) { typedef int tint; ... }
449 /* was nothing here! */
450 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
455 (cstring_makeLiteral ("Declaration outside function scope"));
457 llcontbug (message ("usymtab_addEntryQuiet: inconsistent state "
458 "(lexlevel = %d, modFunction = %s) adding: %q",
459 s->lexlevel, bool_unparse (sRef_modInFunction ()),
460 uentry_unparse (e)));
461 sRef_setGlobalScope ();
462 /* make sure the sRef is not bashed! */
463 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
473 s->entries[s->nentries] = e;
476 if (s == globtab || s == filetab)
478 if (!fileloc_isLib (g_currentloc))
480 uentry_tallyAnnots (e, AN_UNKNOWN);
485 if (cstringTable_isDefined (s->htable))
487 cstringTable_insert (s->htable, cstring_copy (uentry_rawName (e)), s->nentries);
493 static /*@observer@*/ uentry /*@alt void@*/
494 usymtab_addEntryBase (/*@notnull@*/ usymtab s, /*@only@*/ uentry e)
497 ** In theory, we shouldn't need this test because it this is
498 ** only called when a library is being read, and it shouldn't
499 ** ever have a duplicate entry. In practice, its safer to
500 ** leave it in, though.
505 if (uentry_isValid (old = usymtab_lookupQuiet (s, uentry_rawName (e))))
507 DPRINTF (("Duplicate entry: %s", uentry_unparse (e)));
508 uentry_free (e); /* duplicate */
513 int thisentry = s->nentries;
515 if (uentry_isVar (e))
517 uentry_setSref (e, sRef_makeCvar (globScope, thisentry,
519 stateInfo_makeLoc (uentry_whereLast (e))));
522 usymtab_addEntryQuiet (s, e);
528 static /*@observer@*/ uentry /*@alt void@*/
529 usymtab_addEntryAlways (/*@notnull@*/ usymtab s, /*@only@*/ uentry e)
532 ** In theory, we shouldn't need this test because it this is
533 ** only called when a library is being read, and it shouldn't
534 ** ever have a duplicate entry. In practice, its safer to
535 ** leave it in, though.
539 int thisentry = s->nentries;
541 if (uentry_isValid (old = usymtab_lookupQuiet (s, uentry_rawName (e))))
544 (message ("Duplicate entry in load library: %s. "
545 "Old entry: %q. New entry: %q",
547 uentry_unparseFull (old),
548 uentry_unparseFull (e)));
550 uentry_setName (e, message ("__x_%s", uentry_rawName (e)));
551 /* This shouldn't happen...unless the library is bad! */
555 if (uentry_isVar (e) && !uentry_isGlobalMarker (e))
557 uentry_setSref (e, sRef_makeCvar (globScope, thisentry,
559 stateInfo_makeLoc (uentry_whereLast (e))));
562 usymtab_addEntryQuiet (s, e);
567 usymtab_addEntryAux (/*@notnull@*/ usymtab st, /*@keep@*/ uentry e, bool isSref)
568 /*@globals globtab@*/
571 usymId thisentry = st->nentries;
573 llassert (!uentry_isElipsisMarker (e));
577 ** llassert (usymtab_lookupSafe (uentry_rawName (e)) == uentry_undefined);
580 llassertprint (uentry_isAnyTag (e) ? st == globtab : TRUE,
581 ("non-global tag: %s / %d", uentry_unparseFull (e), st->lexlevel));
583 if (st->lexlevel == fileScope
584 && (!(uentry_isStatic (e)) || uentry_isAnyTag (e)))
591 ctype ct = uentry_getType (e);
593 if (uentry_isFunction (e) && ctype_isFunction (ct))
595 ct = ctype_getReturnType (ct);
598 if (uentry_isStatic (e))
600 sRef sr = sRef_makeCvar (st->lexlevel, thisentry, ct, stateInfo_makeLoc (uentry_whereLast (e)));
602 if (sRef_isStack (sr) || sRef_isLocalState (sr))
604 sRef_setAliasKind (sr, AK_STATIC, uentry_whereLast (e));
605 sRef_setDefined (sr, uentry_whereLast (e));
608 uentry_setSref (e, sr);
612 uentry_setSref (e, sRef_makeCvar (st->lexlevel, thisentry, ct, stateInfo_makeLoc (uentry_whereLast (e))));
616 if (uentry_isDatatype (e))
619 uentry_setDatatype (e, thisentry);
622 if (uentry_isFunction (e))
624 ctype ct = uentry_getType (e);
626 if (ctype_isFunction (ct)
627 && uentryList_isMissingParams (ctype_argsFunction (ct)))
629 if (uentry_isDeclared (e))
633 message ("Function %q declared without parameter list",
635 uentry_whereDeclared (e));
641 message ("Function %q specified without parameter list",
643 uentry_whereSpecified (e));
648 if (st == globtab && !uentry_isSpecified (e))
650 exprChecks_checkExport (e);
653 uentry_checkName (e);
655 usymtab_addEntryQuiet (st, e);
656 DPRINTF (("Adding entry: [%p] %s", e, uentry_unparseFull (e)));
661 usymtab_addEntry (uentry e)
662 /*@globals utab, globtab@*/
663 /*@modifies utab, e@*/
665 llassertprint (!usymtab_exists (uentry_rawName (e)),
666 ("Entry already exists: %s", uentry_unparse (e)));
668 return usymtab_addEntryAux (utab, e, FALSE);
672 usymtab_addGlobalEntry (uentry e)
673 /*@modifies globtab, e@*/
675 DPRINTF (("Add global: %s / %s", uentry_unparse (e), bool_unparse (uentry_isForward (e))));
677 (void) usymtab_addEntryAux (globtab, e, FALSE);
681 ** supercede and replace entry use elements of entries array, and
682 ** assign an element to a new value, and then free the old value.
683 ** Need -deparrays to avoid errors for this.
689 usymtab_supEntryAux (/*@notnull@*/ usymtab st,
690 /*@only@*/ uentry e, bool isSref)
691 /*@globals globtab, filetab@*/
692 /*@modifies st, globtab, e@*/
694 cstring ename = uentry_rawName (e);
695 bool staticEntry = FALSE;
698 DPRINTF (("Sup entry aux: %s", uentry_unparseFull (e)));
700 /* static tags in global scope */
701 if (st->lexlevel == fileScope
702 && (!(uentry_isStatic (e)) || uentry_isAnyTag (e)))
704 eindex = usymtab_getIndex (st, ename);
706 if (eindex != NOT_FOUND)
708 uentry ce = st->entries[eindex];
712 message ("%s %q shadows static declaration",
713 ekind_capName (uentry_getKind (e)),
715 uentry_whereDeclared (e)))
717 uentry_showWhereLast (ce);
720 if (eindex == st->nentries - 1)
726 st->entries[eindex] = st->entries[st->nentries - 1];
729 if (cstringTable_isDefined (st->htable))
731 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
732 cstring_copy (uentry_rawName (e)));
742 if (uentry_isStatic (e)) {
743 if (uentry_isFunction (e)) {
745 ** Static function declarations are at the file level,
746 ** even if they are in a deeper scope.
749 st = usymtab_getFileTab ();
752 if (!uentry_isAnyTag (e) && st == globtab)
754 st = usymtab_getFileTab ();
756 DPRINTF (("Static entry!"));
761 eindex = usymtab_getIndex (st, ename);
763 if (eindex != NOT_FOUND)
765 uentry ce = st->entries[eindex];
767 DPRINTF (("Found entry: %s", uentry_unparse (ce)));
769 if (uentry_isPriv (ce)
770 /* || (fileloc_isImport (uentry_whereSpecified (ce))) */
771 || (uentry_isStatic (ce)
772 && uentry_isAnyTag (ce)
773 && (uentry_isDeclared (ce)
774 && !fileloc_sameFile (uentry_whereDefined (ce),
775 uentry_whereDefined (e)))))
779 ** if overloading import should do some checks!
782 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
784 DPRINTF (("Overloading!"));
786 st->entries[eindex] = e;
788 if (uentry_isDatatype (e))
790 uentry_setDatatype (e, eindex);
793 if (st == globtab && !uentry_isSpecified (e))
795 exprChecks_checkExport (e);
798 if (cstringTable_isDefined (st->htable))
800 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
801 cstring_copy (uentry_rawName (e)));
807 else if (uentry_isSpecified (ce))
809 if (uentry_isSpecified (e))
811 DPRINTF (("Here we are: %s", uentry_unparseFull (e)));
813 if (fileloc_isImport (uentry_whereSpecified (ce)))
815 if (cstringTable_isDefined (st->htable))
817 cstringTable_replaceKey (st->htable,
819 cstring_copy (uentry_rawName (e)));
823 st->entries[eindex] = e;
826 if (uentry_isDatatype (e)) uentry_setDatatype (e, eindex);
830 if (fileloc_isImport (uentry_whereSpecified (e)))
836 /* Respecification errors already reported */
837 DPRINTF (("Respecification: %s / %s",
838 fileloc_unparse (uentry_whereSpecified (e)),
839 bool_unparse (fileloc_isSpec (uentry_whereSpecified (e)))));
841 if (uentry_isDatatype (e))
843 uentry_setDatatype (e, eindex);
846 if (cstringTable_isDefined (st->htable))
848 cstringTable_replaceKey (st->htable,
850 cstring_copy (uentry_rawName (e)));
853 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
855 st->entries[eindex] = e;
860 else /* e not specified */
862 DPRINTF (("Merging..."));
864 if (uentry_isDeclared (ce))
867 No - this can happen for internal typedefs
868 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
871 DPRINTF (("Merge defn"));
872 uentry_mergeDefinition (ce, e);
877 No - this can happen for internal typedefs
878 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
881 DPRINTF (("Merge entries..."));
882 uentry_mergeEntries (ce, e);
883 DPRINTF (("After: %s", uentry_unparseFull (ce)));
887 else /* ce not specified */
889 if (!(st->lexlevel > fileScope || !sRef_modInFunction ()))
891 if (uentry_isDatatype (e) || uentry_isAnyTag (e)
892 || uentry_isEnumConstant (e))
895 ** Not a bug. Code like,
896 ** int f (void) { typedef int tint; ... }
902 llcontbug (message ("usymtab_supEntryAux: inconsistent state "
903 "(lexlevel = %d, modFunction = %s) adding: %q",
904 st->lexlevel, bool_unparse (sRef_modInFunction ()),
905 uentry_unparse (e)));
907 if (sRef_modInFunction ())
909 /* make sure the sRef is not bashed! */
910 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
915 DPRINTF (("Merge.."));
916 uentry_mergeDefinition (ce, e);
921 ctype ct = uentry_getType (ce);
923 if (uentry_isFunction (ce) && ctype_isFunction (ct))
925 ct = ctype_getReturnType (ct);
928 uentry_setSref (ce, sRef_makeCvar (st->lexlevel, eindex, ct, stateInfo_makeLoc (uentry_whereLast (ce))));
931 else /* no previous entry */
935 if (st->lexlevel == globScope
936 && !uentry_isStatic (e)
937 && !uentry_isExtern (e)
938 && usymtab_isDefined (filetab))
941 ** check if there is a static entry: (i.e.,
948 eindex = usymtab_getIndex (filetab, ename);
950 if (eindex != NOT_FOUND)
952 uentry ce = filetab->entries[eindex];
954 uentry_setStatic (e);
955 uentry_mergeDefinition (ce, e);
961 outer = usymtab_lookupQuiet (st->env, ename);
963 DPRINTF (("New : [%p] %s", e, uentry_unparseFull (e)));
964 DPRINTF (("Outer: [%p] %s", outer, uentry_unparseFull (outer)));
967 ** no previous definition, add the new one
971 && uentry_isValid (outer)
972 && !(uentry_isYield (e) || uentry_isYield (outer))
973 && fileloc_isDefined (uentry_whereLast (e))
974 && !fileloc_isXHFile (uentry_whereLast (e))
975 && fileloc_isDefined (uentry_whereLast (outer))
976 && !fileloc_isXHFile (uentry_whereLast (outer)))
978 if (!uentry_sameKind (outer, e))
984 if (ctype_isUnknown (uentry_getType (outer))
985 || uentry_isForward (outer))
993 message ("%s %q shadows outer declaration",
994 ekind_capName (uentry_getKind (e)),
996 uentry_whereLast (e)))
998 uentry_showWhereLast (outer);
1004 if (st == globtab && context_getFlag (FLG_NEWDECL))
1008 message ("New declaration: %q", uentry_getName (e)),
1009 uentry_whereLast (e));
1012 eindex = usymtab_addEntryAux (st, e, isSref);
1016 return (staticEntry ? USYMIDINVALID : eindex);
1021 usymtab_replaceEntryAux (/*@notnull@*/ usymtab st, /*@only@*/ uentry e)
1022 /*@globals globtab@*/ /*@modifies st, e@*/
1024 cstring ename = uentry_rawName (e);
1027 /* static tags in global scope */
1028 eindex = usymtab_getIndex (st, ename);
1030 if (eindex != NOT_FOUND)
1032 uentry ce = st->entries[eindex];
1034 if (cstringTable_isDefined (st->htable))
1036 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
1037 cstring_copy (uentry_rawName (e)));
1041 st->entries[eindex] = e;
1045 eindex = usymtab_addEntryAux (st, e, FALSE);
1052 void usymtab_supEntry (uentry e)
1053 /*@globals utab, filetab, globtab@*/
1054 /*@modifies utab, globtab, e@*/
1056 (void) usymtab_supEntryAux (utab, e, FALSE);
1060 ** this should be lots more efficient!
1063 static /*@exposed@*/ uentry
1064 usymtab_supEntryReturnAux (/*@notnull@*/ usymtab tab,
1065 /*@only@*/ uentry e, bool isref)
1066 /*@globals globtab, filetab@*/
1067 /*@modifies tab, globtab, e@*/
1069 cstring rawName = cstring_copy (uentry_rawName (e));
1070 bool stat = (tab == globtab) && uentry_isStatic (e);
1073 (void) usymtab_supEntryAux (tab, e, isref);
1077 ret = usymtab_lookupAux (filetab, rawName);
1081 ret = usymtab_lookupAux (tab, rawName);
1083 if (uentry_isInvalid (ret) && usymtab_isDefined (filetab))
1085 ret = usymtab_lookupAux (filetab, rawName);
1089 cstring_free (rawName);
1093 /*@dependent@*/ /*@exposed@*/ uentry
1094 usymtab_supEntryReturn (/*@only@*/ uentry e)
1095 /*@globals utab, filetab, globtab@*/
1096 /*@modifies utab, globtab, e@*/
1098 return (usymtab_supEntryReturnAux (utab, e, FALSE));
1101 /*@dependent@*/ /*@exposed@*/ uentry
1102 usymtab_supEntrySrefReturn (/*@only@*/ uentry e)
1103 /*@globals utab, globtab, filetab@*/
1104 /*@modifies utab, globtab, e@*/
1106 return (usymtab_supEntryReturnAux (utab, e, TRUE));
1109 /*@dependent@*/ /*@exposed@*/ uentry
1110 usymtab_supGlobalEntryReturn (uentry e)
1111 /*@globals globtab, filetab@*/
1112 /*@modifies globtab, e@*/
1116 ret = usymtab_supEntryReturnAux (globtab, e, FALSE);
1119 ** We need to keep track of internal function declarations, so
1120 ** we can remove them from the symbol table after exiting this
1121 ** function. This is a bit bogus, of course.
1124 if (sRef_modInFunction ())
1126 recordFunctionType (ret);
1133 usymtab_supTypeEntry (/*@only@*/ uentry e)
1134 /*@globals globtab, filetab@*/
1135 /*@modifies globtab, e@*/
1140 if (uentry_isAbstractDatatype (e))
1142 uid = usymtab_supAbstractTypeEntry (e, FALSE);
1143 ret = ctype_createAbstract (uid);
1147 uid = usymtab_supEntryAux (globtab, e, FALSE);
1148 ret = ctype_createUser (uid);
1151 if (sRef_modInFunction ())
1153 recordFunctionType (globtab->entries[uid]);
1160 usymtab_supReturnTypeEntry (/*@only@*/ uentry e)
1161 /*@globals globtab, filetab@*/
1162 /*@modifies globtab@*/
1166 DPRINTF (("Abstract? %s", uentry_unparseFull (e)));
1168 if (uentry_isAbstractDatatype (e))
1170 uid = usymtab_supAbstractTypeEntry (e, FALSE);
1172 else if (uentry_isMaybeAbstract (e) && context_getFlag (FLG_IMPABSTRACT))
1174 bool maybeabs = TRUE;
1175 cstring sname = uentry_getName (e);
1176 uentry ue = usymtab_lookupGlobSafe (sname);
1177 cstring_free (sname);
1179 if (uentry_isValid (ue))
1181 DPRINTF (("Lookup: %s", uentry_unparseFull (ue)));
1183 if (uentry_isDatatype (ue))
1185 if (uentry_isMaybeAbstract (ue))
1196 DPRINTF (("Not datatype!"));
1203 uid = usymtab_supAbstractTypeEntry (e, FALSE);
1204 ux = usymtab_getTypeEntry (uid);
1205 uentry_setAbstract (ux);
1209 uid = usymtab_supEntryAux (globtab, e, FALSE);
1210 e = usymtab_getTypeEntry (uid);
1212 if (uentry_isMaybeAbstract (e))
1214 uentry_setConcrete (e);
1220 uid = usymtab_supEntryAux (globtab, e, FALSE);
1221 e = usymtab_getTypeEntry (uid);
1223 if (uentry_isMaybeAbstract (e))
1225 uentry_setConcrete (e);
1229 if (sRef_modInFunction ())
1231 recordFunctionType (globtab->entries[uid]);
1234 return (globtab->entries[uid]);
1238 usymtab_supAbstractTypeEntry (/*@only@*/ uentry e, bool dodef)
1239 /*@globals globtab, filetab@*/
1240 /*@modifies globtab, e@*/
1245 uid = usymtab_supEntryAux (globtab, e, FALSE);
1246 ue = usymtab_getTypeEntry (uid);
1250 uentry_setDatatype (ue, uid);
1253 if (context_getFlag (FLG_ACCESSMODULE)) /* was accessfile */
1255 context_addFileAccessType (uid);
1258 if (sRef_modInFunction ())
1260 recordFunctionType (globtab->entries[uid]);
1268 usymtab_supExposedTypeEntry (/*@only@*/ uentry e, bool dodef)
1269 /*@globals globtab, filetab@*/
1270 /*@modifies globtab, e@*/
1274 uid = usymtab_supEntryAux (globtab, e, FALSE);
1278 uentry ue = usymtab_getTypeEntry (uid);
1280 uentry_setDatatype (ue, uid);
1283 if (sRef_modInFunction ())
1285 recordFunctionType (globtab->entries[uid]);
1293 usymtab_supForwardTypeEntry (/*@only@*/ uentry e)
1294 /*@globals globtab, filetab@*/
1295 /*@modifies globtab, e@*/
1297 usymId uid = usymtab_supEntryAux (globtab, e, FALSE);
1298 uentry ue = usymtab_getTypeEntry (uid);
1300 uentry_setDatatype (ue, uid);
1302 if (sRef_modInFunction ())
1304 recordFunctionType (globtab->entries[uid]);
1307 return (uentry_getAbstractType (ue));
1311 usymtab_supEntrySref (uentry e)
1312 /*@globals utab, globtab, filetab@*/
1313 /*@modifies utab, globtab, e@*/
1315 sRef old = uentry_getSref (e);
1317 if (sRef_isType (old))
1319 uentry ue = usymtab_supEntryReturnAux (utab, e, TRUE);
1322 if (uentry_isValid (ue))
1324 sRef uref = uentry_getSref (ue);
1326 sRef_mergeStateQuiet (uref, old);
1327 sRef_clearDerived (uref);
1329 /*@noaccess uentry@*/
1331 else if (sRef_isKnown (old))
1333 usymtab_supEntry (e);
1337 (void) usymtab_supEntryAux (utab, e, TRUE);
1341 void usymtab_supGlobalEntry (/*@only@*/ uentry e)
1342 /*@globals globtab, filetab@*/
1343 /*@modifies globtab, filetab, e@*/
1347 DPRINTF (("Sup global entry: %s", uentry_unparse (e)));
1349 uid = usymtab_supEntryAux (globtab, e, FALSE);
1351 if (sRef_modInFunction ())
1353 recordFunctionType (globtab->entries[uid]);
1358 usymtab_supReturnFileEntry (/*@only@*/ uentry e)
1359 /*@globals filetab, globtab@*/
1360 /*@modifies filetab, globtab, e@*/
1362 llassert (filetab != usymtab_undefined);
1363 DPRINTF (("File entry: %s", uentry_unparse (e)));
1364 return (usymtab_supEntryReturnAux (filetab, e, FALSE));
1372 usymtab_inDeepScope () /*@globals utab@*/
1374 return (utab->lexlevel > paramsScope);
1378 usymtab_getIndex (/*@notnull@*/ usymtab s, cstring k)
1382 DPRINTF (("Lookup %s", k));
1384 if (cstringTable_isDefined (s->htable))
1386 i = cstringTable_lookup (s->htable, k);
1391 for (i = 0; i < s->nentries; i++)
1393 uentry current = s->entries[i];
1395 DPRINTF (("Check %d: %s", i, uentry_rawName (current)));
1397 if (!uentry_isUndefined (current)
1398 && cstring_equal (uentry_rawName (current), k))
1409 usymtab_fetchIndex (/*@notnull@*/ usymtab s, int i)
1411 llassert (i >= 0 && i < s->nentries);
1412 return (s->entries[i]);
1416 usymtab_getTypeId (cstring k) /*@globals globtab@*/
1418 usymId uid = usymtab_getIndex (globtab, k);
1420 if (uid == NOT_FOUND) return USYMIDINVALID;
1422 if (!(uentry_isDatatype (usymtab_getTypeEntry (uid)))) {
1423 return USYMIDINVALID;
1429 /*@dependent@*/ uentry
1430 usymtab_lookupStructTag (cstring k)
1432 cstring sname = makeStruct (k);
1433 uentry ue = usymtab_lookupGlob (sname);
1435 cstring_free (sname);
1439 /*@dependent@*/ uentry
1440 usymtab_lookupUnionTag (cstring k)
1442 cstring uname = makeUnion (k);
1443 uentry res = usymtab_lookupGlob (uname);
1445 cstring_free (uname);
1449 /*@dependent@*/ uentry
1450 usymtab_lookupEnumTag (cstring k)
1452 cstring ename = makeEnum (k);
1453 uentry res = usymtab_lookupGlob (ename);
1455 cstring_free (ename);
1460 usymtab_getId (cstring k) /*@globals globtab@*/
1462 usymId uid = usymtab_getIndex (globtab, k);
1465 if (uid == NOT_FOUND)
1467 return USYMIDINVALID;
1470 ue = usymtab_getGlobalEntry (uid);
1472 if (uentry_isPriv (ue))
1474 return USYMIDINVALID;
1480 static /*@exposed@*/ uentry
1481 usymtab_getEntryAux (/*@notnull@*/ usymtab s, usymId uid)
1483 llassert (uid != USYMIDINVALID);
1485 if (uid < 0 || uid >= s->nentries)
1487 llcontbug (message ("usymtab_getEntry: out of range: level = %d [%d]",
1489 return uentry_undefined;
1492 llassertprint (uentry_isValid (s->entries[uid]),
1493 ("entry undefined: %d", uid));
1495 return s->entries[uid];
1498 /*@dependent@*/ /*@observer@*/ uentry
1499 usymtab_getGlobalEntry (usymId uid)
1500 /*@globals utab, globtab@*/
1502 if (dbgfree) return (uentry_undefined);
1504 if (utab->lexlevel > paramsScope)
1506 /* need to do this the awkward way, since it could be in conditional scope */
1507 return (usymtab_lookupSafe (uentry_rawName (globtab->entries[uid])));
1511 return (globtab->entries[uid]);
1515 /*@dependent@*/ /*@exposed@*/ uentry
1516 usymtab_getTypeEntry (usymId uid)
1517 /*@globals globtab@*/
1521 if (uid >= 0 && uid < globtab->nentries)
1523 return (globtab->entries[uid]);
1527 return (uentry_undefined);
1532 llassert (uid >= 0 && uid < globtab->nentries);
1533 return (globtab->entries[uid]);
1541 /*@dependent@*/ /*@exposed@*/ uentry
1542 usymtab_getTypeEntrySafe (usymId uid)
1543 /*@globals globtab@*/
1545 if (uid < 0 || uid >= globtab->nentries)
1547 return uentry_undefined;
1550 return (globtab->entries[uid]);
1554 usymtab_isBoolType (usymId uid)
1555 /*@globals globtab@*/
1557 llassert (uid >= 0 && uid < globtab->nentries);
1559 return (cstring_equal (uentry_rawName (globtab->entries[uid]),
1560 context_getBoolName ()));
1564 usymtab_getTypeEntryName (usymId uid)
1565 /*@globals globtab@*/
1571 return (cstring_makeLiteral ("<freetype>"));
1574 ue = usymtab_getTypeEntry (uid);
1576 if (dbgload && !uentry_isValid (ue))
1578 return (message ("<missing type: %d>", uid));
1581 llassertprint (uentry_isValid (ue), ("type undefined: %d", uid));
1583 return (uentry_getName (ue));
1587 /*@unused@*/ static void
1588 usymtab_rehash (/*@notnull@*/ usymtab s)
1592 if (cstringTable_isDefined (s->htable))
1594 cstringTable_free (s->htable);
1597 s->htable = cstringTable_create (LLHASHSIZE);
1599 for (i = 0; i < s->nentries; i++)
1601 cstringTable_insert (s->htable, cstring_copy (uentry_rawName (s->entries[i])), i);
1607 ** superficial copy of usymtab
1609 ** DO copy spec entries
1612 static /*@only@*/ /*@notnull@*/ usymtab
1613 usymtab_shallowCopy (/*@notnull@*/ usymtab s) /*@*/
1615 usymtab copytab = usymtab_createRoot ();
1618 for (i = 0; i < s->nentries; i++)
1620 usymtab_addEntryBase (copytab, s->entries[i]);
1627 usymtab_shallowFree (/*@only@*/ /*@notnull@*/ usymtab s)
1629 aliasTable_free (s->aliases);
1630 refTable_free (s->reftable, s->nentries);
1632 /*@-compdestroy@*/ sfree (s); /*@=compdestroy@*/
1636 ** converts usymId from old table to sorted one
1640 usymtab_convertId (usymId uid)
1641 /*@globals oldtab, utab@*/
1647 llassert (usymtab_isDefined (oldtab));
1649 ue = usymtab_getEntryAux (oldtab, uid);
1651 llassertprint (uentry_isValid (ue), ("convertId: undefined: %d", uid));
1653 name = uentry_rawName (ue);
1655 ret = usymtab_getIndex (utab, name);
1656 llassert (ret == uid); /*! for now, no rehash! */
1657 DPRINTF (("Convert: %s [%d] -> %s [%d]",
1658 uentry_unparse (ue), uid,
1659 uentry_unparse (utab->entries[ret]), ret));
1661 llassertprint (ret != USYMIDINVALID, ("convertId: return is invalid"));
1667 usymtab_prepareDump (void)
1668 /*@globals oldtab, utab@*/
1669 /*@modifies oldtab, utab@*/
1671 llassert (usymtab_inGlobalScope ());
1672 llassert (oldtab == usymtab_undefined);
1675 DPRINTF (("Preparing to dump:"));
1676 usymtab_printAll ();
1679 oldtab = usymtab_shallowCopy (utab);
1682 ** alpha compare - make sure order is same on different platforms
1683 ** error messages appear in same order
1687 qsort (utab->entries, (size_t)utab->nentries,
1688 sizeof (*utab->entries),
1689 (int (*)(const void *, const void *)) uentry_xcomparealpha);
1691 usymtab_rehash (utab);
1695 DPRINTF (("After rehash:"));
1696 usymtab_printAll ();
1700 void usymtab_dump (FILE *fout)
1701 /*@globals utab, oldtab@*/
1704 bool neednl = FALSE;
1705 uentry lastentry = uentry_undefined;
1706 ekind lastekind = KINVALID;
1710 ** must call prepareDump first
1713 llassert (oldtab != usymtab_undefined);
1715 for (i = 0; i < utab->nentries; i++)
1717 uentry thisentry = utab->entries[i];
1718 ekind thisekind = uentry_getKind (thisentry);
1720 if (!uentry_hasRealName (thisentry))
1722 llassert (uentry_isGlobalMarker (thisentry));
1726 check (fputc ('\n', fout) == (int) '\n');
1729 fprintf (fout, "*%d (GlobalMarker)\n", KGLOBALMARKER);
1730 lastekind = KINVALID;
1736 if (thisekind != lastekind)
1740 check (fputc ('\n', fout) == (int) '\n');
1744 lastentry = uentry_undefined;
1745 fprintf (fout, "*%d (%s)\n", ekind_toInt (thisekind),
1746 cstring_toCharsSafe (ekind_capName (thisekind)));
1747 lastekind = thisekind;
1752 ** evans - 2001-02-18 - added the - 48 fudge factor...
1753 ** extra characters dumped, but I haven't counded them carefully...
1756 if (uentry_isInvalid (lastentry) || !uentry_equiv (lastentry, thisentry)
1757 || (linelen > (MAX_DUMP_LINE_LENGTH - (2 * MAX_NAME_LENGTH) - 48)))
1761 DPRINTF (("Dumping entry: %d", i));
1762 cdump = message ("^%d %q", i, uentry_dump (thisentry));
1763 /* was: cdump = uentry_dump (thisentry)); */
1765 lastentry = thisentry;
1768 check (fputc ('\n', fout) == (int) '\n');
1772 linelen += cstring_length (cdump);
1774 /* no new line here! */
1775 if (cstring_length (cdump) > 0)
1777 check (fputs (cstring_toCharsSafe (cdump), fout) != EOF);
1780 cstring_free (cdump);
1785 cstring cdump = uentry_rawName (thisentry);
1786 DPRINTF (("Raw name: %s", cdump));
1787 linelen += (cstring_length (cdump) + 1);
1788 fprintf (fout, "#%s", cstring_toCharsSafe (cdump));
1795 check (fputc ('\n', fout) == (int) '\n');
1798 lastekind = KINVALID;
1800 fprintf(fout, ";; Library constraints\n");
1801 for (i = 0; i < utab->nentries; i++)
1803 uentry thisentry = utab->entries[i];
1805 if (uentry_isFunction (thisentry) )
1807 constraintList preconditions;
1808 constraintList postconditions;
1810 preconditions = uentry_getFcnPreconditions (thisentry);
1811 postconditions = uentry_getFcnPostconditions (thisentry);
1813 if ( constraintList_isDefined(preconditions) ||
1814 constraintList_isDefined(postconditions) )
1816 fprintf(fout,"%s\n", cstring_toCharsSafe (uentry_rawName(thisentry) ) );
1817 if (constraintList_isDefined(preconditions) )
1819 fprintf(fout,"pre:\n");
1820 constraintList_dump(preconditions, fout);
1821 fprintf (fout, ";; end precondition constraints\n" );
1822 constraintList_free(preconditions);
1826 fprintf(fout,"pre:EMPTY\n");
1828 if (constraintList_isDefined(postconditions) )
1830 fprintf(fout,"post:\n");
1831 constraintList_dump(postconditions, fout);
1832 fprintf (fout, ";; end precondition constraints\n" );
1833 constraintList_free(postconditions);
1837 fprintf(fout,"post:EMPTY\n");
1846 void usymtab_load (FILE *f)
1847 /*@globals utab, globtab@*/
1848 /*@modifies utab, *f@*/
1850 char *s = mstring_create (MAX_DUMP_LINE_LENGTH);
1852 ekind kind = KINVALID;
1853 fileloc loc = g_currentloc;
1859 llassert (utab == globtab);
1860 llassert (utab->nentries == 0);
1862 while (((s = reader_readLine (f, s, MAX_DUMP_LINE_LENGTH)) != NULL)
1865 /* ignore ; comments */ ;
1868 while (s != NULL && *s != ';')
1876 ek = reader_getInt (&s);
1878 if (ek == KGLOBALMARKER)
1880 uentry lue = uentry_makeGlobalMarker ();
1881 DPRINTF (("Adding global marker: %s", uentry_unparseFull (lue)));
1882 usymtab_addEntryAlways (utab, lue);
1888 kind = ekind_fromInt (ek);
1896 (cstring_makeLiteral
1897 ("Library is in obsolete format. Use splint +whichlib "
1898 "to see which library is being loaded."));
1901 if (reader_optCheckChar (&s, '^'))
1903 index = reader_getInt (&s);
1910 llassert (kind != KINVALID);
1911 ue = uentry_undump (kind, loc, &s);
1913 llassert (utab->nentries == index || index == -1);
1915 if (uentry_isValid (ue))
1917 int lastindex = utab->nentries;
1918 ue = usymtab_addEntryAlways (utab, ue);
1922 if (uentry_isConstant (ue)) /*@i23! isPreProcessorMacro */
1924 cstring uname = uentry_getName (ue);
1926 /* Also check its a macro... */
1927 DPRINTF (("Installing: %s", uname));
1929 cpphash_installMacro
1930 (mstring_copy (cstring_toCharsSafe (uname)),
1931 cstring_length (uname),
1932 cpplib_createDefinition (message ("%s 255", uname),
1935 cpphash_hashCode (cstring_toCharsSafe (uname),
1936 cstring_length (uname),
1939 DPRINTF (("After install: %s", uname));
1943 if (utab->nentries != lastindex + 1)
1945 DPRINTF (("No add: %s", uentry_unparseFull (ue)));
1953 ** now, any other names are the same uentry
1956 while (*(s++) == '#')
1958 cstring name = cstring_fromCharsO (reader_getWord (&s));
1959 uentry nue = uentry_nameCopy (name, ue);
1961 DPRINTF (("Name copy: %s", uentry_unparseFull (nue)));
1965 usymtab_addEntryAlways (utab, nue);
1968 while ((c = *s) != '\0' && (c !='\n'))
1970 if (c != ' ' || c != '\t')
1972 llbuglit ("Junk in load file");
1980 s = reader_readLine (f, os, MAX_DUMP_LINE_LENGTH);
1985 to handle reading of buffer overflow related constraints
1987 while (fgets (s, MAX_DUMP_LINE_LENGTH, f) != NULL
1990 ; /* ignore ;-comments */
1993 while (s != NULL && *s != ';')
1995 constraintList preconditions;
1996 constraintList postconditions;
1998 cstring name = cstring_fromChars(reader_getWord(&s) );
2000 ue = usymtab_lookup ( name );
2004 preconditions = constraintList_undefined;
2005 postconditions = constraintList_undefined;
2007 if (!uentry_isValid(ue) )
2009 llfatalbug ((message("Invalid uentry for %s library file may be corrupted", cstring_fromChars(s) ) ));
2011 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2013 temp = cstring_fromChars (reader_getWord(&s) );
2015 if (cstring_compareLit (temp,"pre:") == 0 )
2017 preconditions = constraintList_undump (f);
2021 if (cstring_compareLit (temp,"pre:EMPTY") != 0 )
2022 llfatalbug ((message("Error reading library file pre:EMPTY expected but got %s", temp ) ));
2027 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2029 temp = cstring_fromChars(reader_getWord(&s) );
2030 if (cstring_compareLit (temp, "post:") == 0 )
2032 postconditions = constraintList_undump (f);
2036 if (cstring_compareLit (temp, "post:EMPTY") != 0 )
2037 llfatalbug ((message("Error reading library file post:EMPTY expected but got %s", temp ) ));
2040 cstring_free (temp);
2042 uentry_setPreconditions (ue, functionConstraint_createBufferConstraint (preconditions));
2043 uentry_setPostconditions (ue, functionConstraint_createBufferConstraint (postconditions));
2045 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2053 ** file scope for static variables
2057 usymtab_enterFile ()
2058 /*@globals utab, globtab, filetab@*/
2059 /*@modifies filetab@*/
2061 llassert (utab == globtab);
2066 usymtab_entries (globtab, ue)
2068 if (sRef_hasDerived (uentry_getSref (ue)))
2070 fprintf (g_warningstream, "Derived Global: %s\n", uentry_unparse (ue));
2071 fprintf (g_warningstream, "sRef: %s\n", sRef_unparseFull (ue->sref));
2073 } end_usymtab_entries ;
2077 usymtab_enterScope ();
2083 /*@globals utab, filetab@*/
2084 /*@modifies filetab, utab@*/
2087 llassert (utab->lexlevel == 1);
2089 usymtab_exitScope (exprNode_undefined);
2094 usymtab_enterScope ()
2095 /*@globals utab, globtab, filetab@*/
2098 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
2100 /* unconditional scope: optimize to avoid copy */
2101 t->aliases = aliasTable_copy (utab->aliases);
2104 llassert (usymtab_isDefined (t->env));
2106 if (t->env->lexlevel == paramsScope && context_inFunctionLike ())
2108 noshadowerror = TRUE;
2109 usymtab_handleParams ();
2110 noshadowerror = FALSE;
2115 ** setup external references:
2116 ** o only, unique params alias external args
2117 ** o other params may alias anything of their type
2121 usymtab_handleParams (void)
2122 /*@globals utab, globtab, filetab@*/
2123 /*@modifies utab, globtab@*/
2125 usymtab ptab = utab->env;
2126 uentry fcn = context_getHeader ();
2128 usymtab_entries (ptab, param)
2132 if (!uentry_isYield (param))
2135 sRef pref = uentry_getSref (param);
2137 /* Could be a global. */
2139 if (uentry_isAnyParam (param))
2141 ue = uentry_makeVariable (fixParamName (uentry_rawName (param)),
2142 uentry_getType (param),
2143 fileloc_copy (uentry_whereDeclared (param)),
2146 uentry_copyState (ue, param);
2147 uentry_setRefParam (ue);
2149 ue = usymtab_supEntrySrefReturn (ue);
2151 /* must be after supercede! */
2153 if (!sRef_stateKnown (pref))
2155 uentry_setDefState (ue, SS_DEFINED);
2156 uentry_setDefState (param, SS_DEFINED);
2160 if (sRef_isStateSpecial (pref))
2162 uentry_setDefState (ue, SS_SPECIAL); /* ALLOCATED); */
2163 /* evans 2002-01-01: should be unnecessary, the pre clauses
2164 ** set the state if necessary.
2169 uentry_setDefState (ue, sRef_getDefState (pref));
2173 uref = uentry_getSref (ue);
2175 if (sRef_isStack (uref))
2177 alkind pkind = sRef_getAliasKind (pref);
2179 if (alkind_isKnown (pkind) && !alkind_isLocal (pkind)
2180 && !alkind_isStack (pkind))
2182 sRef_setAliasKind (uref, pkind, fileloc_undefined);
2183 sRef_setOrigAliasKind (uref, pkind);
2187 sRef_setAliasKind (uref, AK_IMPTEMP, fileloc_undefined);
2188 sRef_setOrigAliasKind (uref, AK_IMPTEMP);
2190 if (uentry_isOut (param))
2196 sRef_setDefined (uref, fileloc_undefined);
2202 usymtab_addMustAlias (uref, pref);
2204 if (!(uentry_isOnly (param) || uentry_isUnique (param)))
2207 ** This is needed for detecting possibly aliased parameters.
2210 sRef s = sRef_makeExternal (uref);
2211 usymtab_addMustAlias (uref, s);
2214 if (sRef_isKillRef (pref))
2216 sRef_setAliasKind (uref, AK_NEWREF, fileloc_undefined);
2217 sRef_setOrigAliasKind (uref, AK_KILLREF);
2219 else if (sRef_isRefCounted (uref))
2221 sRef_setOrigAliasKind (uref, AK_REFCOUNTED);
2226 sRef_setOrigAliasKind (uref, AK_LOCAL);
2233 } end_usymtab_entries;
2236 if (uentry_hasStateClauseList (fcn))
2238 stateClauseList clauses = uentry_getStateClauseList (fcn);
2240 stateClauseList_preElements (clauses, cl)
2242 fileloc loc = stateClause_loc (cl);
2243 sRefSet osrs = sRefSet_undefined;
2246 if (stateClause_isGlobal (cl))
2248 DPRINTF (("Global Marker: %s",
2249 sRef_unparseFull (usymtab_lookupGlobalMarker ())));
2250 llassert (sRef_isGlobalMarker (usymtab_lookupGlobalMarker ()));
2251 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
2256 srs = stateClause_getRefs (cl);
2259 sRefSet_elements (srs, el)
2261 sRef base = sRef_getRootBase (el);
2262 sRef sb = sRef_updateSref (el);
2264 if (sRef_isResult (base))
2266 ; /* nothing to do before */
2268 else if (sRef_isParam (base) || sRef_isGlobalMarker (base))
2270 if (stateClause_setsMetaState (cl))
2272 /* copied from exprNode.c:3040 */
2273 qual ql = stateClause_getMetaQual (cl);
2274 annotationInfo ainfo = qual_getAnnotationInfo (ql);
2275 metaStateInfo minfo = annotationInfo_getState (ainfo);
2276 cstring key = metaStateInfo_getName (minfo);
2277 int mvalue = annotationInfo_getValue (ainfo);
2279 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
2281 if (sRef_isResult (base))
2287 sRef_setMetaStateValueComplete (sb, key, mvalue, loc);
2292 sRefMod modf = stateClause_getEntryFunction (cl);
2296 sRefSet aliases = usymtab_allAliases (sb);
2300 sRefSet_elements (aliases, sr)
2303 } end_sRefSet_elements ;
2305 sRefSet_free (aliases);
2311 if (sRef_isValid (base))
2313 DPRINTF (("Base: %s", sRef_unparseFull (base)));
2317 } end_sRefSet_elements ;
2318 } end_stateClauseList_preElements ;
2323 usymtab_enterFunctionScope (uentry fcn)
2324 /*@globals utab, filetab, globtab@*/
2327 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
2329 DPRINTF (("Enter function: %s", uentry_unparse (fcn)));
2331 if (utab->lexlevel != fileScope)
2333 if (utab->lexlevel > fileScope)
2335 llparseerror (cstring_makeLiteral ("New function scope inside function"));
2337 while (utab->lexlevel > fileScope)
2339 /*@i@*/ utab = usymtab_dropEnv (utab);
2346 llfatalbug (cstring_makeLiteral ("New function not inside file."));
2348 /*@-branchstate@*/ } /*@=branchstate@*/
2352 DPRINTF (("Globs: %s", globSet_unparse (uentry_getGlobs (fcn))));
2354 globSet_allElements (uentry_getGlobs (fcn), el)
2356 DPRINTF (("Here we go: %s", sRef_unparseFull (el)));
2358 if (sRef_isUndefGlob (el))
2360 int index = sRef_getScopeIndex (el);
2361 sRef sr = sRef_updateSref (el);
2362 fileloc loc = uentry_whereEarliest (fcn);
2364 DPRINTF (("update: %s", sRef_unparseFull (sr)));
2365 DPRINTF (("Undef!"));
2366 if (sRef_isFileStatic (el))
2368 ctype ct = sRef_getType (el);
2371 llassert (usymtab_isDefined (filetab));
2373 ue = usymtab_fetchIndex (filetab, index);
2375 if (ctype_isRealArray (ct) || ctype_isRealSU (ct))
2377 sRef_setAllocated (sr, loc);
2381 sRef_setUndefined (sr, loc);
2386 uentry ue = globtab->entries[index];
2387 ctype ct = uentry_getType (ue);
2389 if (ctype_isArray (ct) || ctype_isSU (ct))
2391 sRef_setAllocated (sr, loc);
2395 sRef_setUndefined (sr, loc);
2399 else if (sRef_isAllocated (el))
2401 sRef sr = sRef_updateSref (el);
2402 fileloc loc = uentry_whereEarliest (fcn);
2404 sRef_setAllocated (sr, loc);
2406 else if (sRef_isPartial (el))
2408 sRef sr = sRef_updateSref (el);
2409 fileloc loc = uentry_whereEarliest (fcn);
2411 sRef_setPartial (sr, loc);
2416 sRef sr = sRef_updateSref (el);
2417 fileloc loc = uentry_whereEarliest (fcn);
2419 sRef_setDefined (sr, loc);
2423 /* shouldn't need to do anything! */
2425 } end_globSet_allElements;
2427 DPRINTF (("Globs after: %s", globSet_unparse (uentry_getGlobs (fcn))));
2429 usymtab_checkAllValid ();
2434 usymtab_caseBranch (void)
2437 usymtab t = usymtab_create (US_CBRANCH, utab, FALSE);
2442 usymtab_switchBranch (/*@unused@*/ exprNode s)
2445 usymtab t = usymtab_create (US_SWITCH, utab, FALSE);
2447 t->aliases = aliasTable_copy (utab->aliases);
2452 usymtab_trueBranch (/*@only@*/ guardSet guards)
2455 usymtab t = usymtab_create (US_TBRANCH, utab, FALSE);
2458 ** not true! (could be in a macro)
2460 ** llassertprint (utab->lexlevel > paramsScope,
2461 ** ("not in scope: %s", usymtab_unparseLocal ()));
2465 guardSet_free (t->guards);
2468 aliasTable_free (t->aliases);
2469 t->aliases = aliasTable_copy (utab->aliases);
2477 ** { int a; if (...) a = 3; < a may be undefined here!
2482 usymtab_popTrueBranch (exprNode pred, exprNode expr, clause cl) /*@modifies utab@*/
2485 ** add a false branch
2486 ** (could be done more efficiently as a special case, but
2487 ** it is better to only maintain one version of the code)
2490 if (utab->kind != US_TBRANCH
2491 && context_inIterDef ())
2493 usymtab_exitScope (expr);
2497 DPRINTF (("pop true branch.."));
2498 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2499 usymtab_popBranches (pred, expr, exprNode_undefined, TRUE, cl);
2504 usymtab_popCaseBranch () /*@modifies utab@*/
2506 llassert (utab->kind == US_CBRANCH);
2507 usymtab_quietPlainExitScope ();
2511 usymtab_popTrueExecBranch (exprNode pred, exprNode expr, clause cl)
2514 ** add a false branch that must return --- that is,
2515 ** the true branch is always executed!
2518 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2519 usymtab_popBranches (pred, expr, exprNode_makeMustExit (), FALSE, cl);
2523 usymtab_popOrBranch (exprNode pred, exprNode expr)
2527 usymtab env = utab->env;
2528 usymtab otab = utab;
2531 llassert (env != NULL);
2533 if (exprNode_isError (expr))
2539 mustReturn = exprNode_mustEscape (expr);
2543 llassert (utab->kind == US_TBRANCH);
2546 ** merge each entry in table with its original
2547 ** unless execution cannot continue after this branch
2550 for (i = 0; i < utab->nentries; i++)
2552 uentry current = utab->entries[i];
2553 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2555 uentry_mergeState (old, current, exprNode_loc (expr),
2556 mustReturn, FALSE, TRUE, ORCLAUSE);
2562 env->guards = guardSet_levelUnionFree (env->guards,
2563 guardSet_invert (exprNode_getGuards (pred)),
2568 env->aliases = aliasTable_levelUnion (env->aliases, otab->aliases, env->lexlevel);
2571 /* env is now utab */
2572 usymtab_quietPlainExitScope ();
2576 ** case syntax in C is very unrestricted. This is unfortunate.
2578 ** A switch case is ended either by a new case or default, or
2579 ** a close } that may close the switch or some other control
2584 usymtab_newCase (/*@unused@*/ exprNode pred, exprNode last)
2587 bool mustBreak = usymtab_mustBreak (utab);
2588 bool mustReturn = usymtab_mustEscape (utab);
2589 usymtab stab = utab;
2591 DPRINTF (("New case!"));
2594 ** Find last case (or outer switch)
2597 while (stab->kind != US_CBRANCH && stab->kind != US_SWITCH)
2600 llassert (stab != GLOBAL_ENV);
2603 while (stab->kind == US_CBRANCH)
2606 llassert (stab != GLOBAL_ENV);
2610 ** if its a fall through case, merge in outside entries and last case.
2615 ** case 1: x = 3; <fall through>
2616 ** case 2: << x may not be defined
2620 if (!mustBreak && !mustReturn && utab->kind == US_CBRANCH)
2622 llassert (stab->kind == US_SWITCH || stab->kind == US_NORMAL);
2624 usymtab_entries (utab, ue) /* but, keep track of used variables */
2626 uentry old = usymtab_lookupAux (stab, uentry_rawName (ue));
2628 llassert (uentry_isValid (old));
2630 /* modifies ue, not old */
2632 uentry_mergeState (ue, old, exprNode_loc (last),
2633 FALSE, FALSE, TRUE, CASECLAUSE);
2634 } end_usymtab_entries;
2636 utab->aliases = aliasTable_levelUnion (utab->aliases,
2637 stab->aliases, utab->lexlevel);
2640 ** No need for a new branch.
2647 usymtab_caseBranch ();
2648 /*@-mustfree@*/ /*< utab->aliases >*/
2649 utab->aliases = aliasTable_copy (stab->aliases);
2657 ** for && (both pred and expr are executed)
2661 usymtab_popAndBranch (exprNode pred, /*@unused@*/ exprNode expr)
2664 usymtab env = utab->env;
2668 llassert (utab->kind == US_TBRANCH);
2671 ** merge each entry in table with its original
2672 ** unless execution cannot continue after this branch
2675 for (i = 0; i < utab->nentries; i++)
2677 uentry current = utab->entries[i];
2678 sRef tref = uentry_getSref (current);
2679 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2680 sRef oref = uentry_getSref (old);
2682 /* note that is current is in a nested branch,
2683 it may create a "new" old entry. */
2685 llassert (uentry_isValid (old));
2686 uentry_mergeState (old, current, exprNode_loc (expr),
2687 FALSE, FALSE, TRUE, ANDCLAUSE);
2690 ** if is it defined by the second clause, then it should be defined.
2693 if (sRef_isAnyDefined (tref)
2694 && (sRef_isAllocated (oref) || sRef_isStateUndefined (oref)))
2696 sRef_setDefined (oref, g_currentloc);
2700 utab->guards = guardSet_levelUnionFree (utab->guards,
2701 guardSet_invert (exprNode_getGuards (pred)),
2703 utab->aliases = aliasTable_levelUnion (utab->aliases, otab->aliases, utab->lexlevel);
2705 usymtab_quietPlainExitScope ();
2710 ** Stack should be [ US_CBRANCH+ US_SWITCH ]
2711 ** Only branches which do not return (except possibly the last branch) are included.
2713 ** Conditionally merge state from all CBRANCHes.
2715 ** If allpaths is TRUE, then all possible executions go through some switch
2716 ** case, and the original scope is not merged.
2720 usymtab_exitSwitch (/*@unused@*/ exprNode sw, bool allpaths)
2723 usymtab ttab = utab;
2724 usymtab stab = ttab;
2725 usymtab ltab = ttab;
2726 bool lastMustReturn = usymtab_mustEscape (utab);
2730 while (stab->kind == US_CBRANCH)
2733 llassert (stab != GLOBAL_ENV);
2736 while (stab->kind == US_NORMAL)
2739 llassert (stab != GLOBAL_ENV);
2742 llassert (stab->kind == US_SWITCH);
2744 /* go to the scope outside the switch (US_SWITCH is just a marker! */
2746 llassert (stab != GLOBAL_ENV);
2750 llassert (usymtab_isDefined (ttab));
2752 if (ttab->kind == US_CBRANCH)
2754 /* was quietPlainExitScope --- but, can't free it yet! */
2756 llassert (utab != GLOBAL_ENV);
2758 while (ttab->kind == US_CBRANCH)
2761 ** (from popTrueBranch)
2764 bool mustReturn = usymtab_mustEscape (ttab);
2765 bool mustBreak = usymtab_mustBreak (ttab);
2767 usymtab_entries (ttab, current)
2769 uentry old = /*@-compmempass@*/ usymtab_lookupAux (ltab, uentry_rawName (current));
2773 ** note that is this is in a nested branch,
2774 ** it may create a "new" old entry.
2777 if (uentry_isValid (old))
2781 uentry_mergeUses (current, old);
2782 uentry_setState (old, current);
2786 uentry_mergeState (old, current, exprNode_loc (sw),
2787 mustReturn, FALSE, TRUE, SWITCHCLAUSE);
2794 } end_usymtab_entries;
2797 ** if entry is not in symbol table for this case, merge with pre-switch
2801 if (!mustReturn && !mustBreak)
2803 usymtab_entries (stab, current)
2805 if (usymtab_getIndex (ttab, uentry_rawName (current)) == NOT_FOUND)
2807 uentry old = /*@-compmempass@*/
2808 usymtab_lookupAux (ltab, uentry_rawName (current));
2811 llassert (uentry_isValid (old));
2812 uentry_mergeState (old, current, exprNode_loc (sw),
2813 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2815 } end_usymtab_entries;
2818 ltab->env = ttab->env;
2822 ** Suprious error, becuase of environments.
2825 /*@i1@*/ utab = ltab;
2827 lastMustReturn = FALSE;
2834 ** now, there is one US_CBRANCH. Merge this with the stab.
2838 for (i = 0; i < ltab->nentries; i++)
2840 uentry current = ltab->entries[i];
2841 uentry old = usymtab_lookupAux (stab, uentry_rawName (current));
2843 /* note that is this is in a nested branch,
2844 it may create a "new" old entry. */
2847 if (uentry_isValid (old))
2851 uentry_mergeUses (current, old);
2852 uentry_setState (old, current);
2856 uentry_mergeState (old, current, exprNode_loc (sw),
2857 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2871 ** switch may or may not be followed by a new scope
2874 if (utab->kind == US_SWITCH)
2876 usymtab_quietPlainExitScope ();
2880 usymtab_quietPlainExitScope ();
2881 llassert (utab->kind == US_SWITCH);
2882 usymtab_quietPlainExitScope ();
2888 updateNullState (sRef el, /*@notnull@*/ usymtab ttab,
2889 /*@notnull@*/ usymtab ftab, bool trueGuard)
2891 sRef base = sRef_getRootBase (el);
2892 int level = sRef_lexLevel (base);
2894 if (sRef_isCvar (base))
2896 usymId index = sRef_getScopeIndex (base);
2897 uentry ue = usymtab_getRefTab (ttab, level, index);
2899 if (!uentry_isLset (ue))
2901 sRef sr = uentry_getSref (ue);
2905 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2909 if (!guardSet_isGuarded (ttab->guards, el)
2910 && !sRef_isNotNull (sr))
2912 DPRINTF (("Here! %s / %s",
2913 sRef_unparseFull (sr),
2914 sRef_unparseFull (el)));
2915 sRef_setDerivNullState (sr, el, NS_DEFNULL);
2924 ue = usymtab_getRefTab (ftab, level, index);
2926 if (!uentry_isLset (ue))
2928 sRef sr = uentry_getSref (ue);
2930 if (!trueGuard) /* yikes! forgot the ! */
2932 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2937 if (!guardSet_isGuarded (ftab->guards, el)
2938 && !sRef_isNotNull (sr))
2940 sRef_setDerivNullState (sr, el, NS_DEFNULL);
2952 usymtab_popBranches (exprNode pred, exprNode tbranch, exprNode fbranch,
2953 bool isOpt, clause cl)
2957 usymtab ftab = utab;
2958 usymtab ttab = utab->env;
2962 guardSet guards = exprNode_getGuards (pred);
2963 sRefSet tguards = guardSet_getTrueGuards (guards);
2964 sRefSet fguards = guardSet_getFalseGuards (guards);
2965 bool mustReturnT = exprNode_mustEscape (tbranch);
2966 bool mustReturnF = exprNode_mustEscape (fbranch);
2968 DPRINTF (("Pop branches: %s [mustreturn: %s/%s]", exprNode_unparse (pred),
2969 bool_unparse (mustReturnT),
2970 bool_unparse (mustReturnF)));
2972 if (exprNode_isDefined (fbranch))
2974 loc = exprNode_loc (fbranch);
2978 loc = exprNode_loc (tbranch);
2981 llassert (usymtab_isDefined (ttab));
2985 llassert (usymtab_isDefined (env));
2986 llassert (ftab->kind == US_FBRANCH);
2987 llassert (ttab->kind == US_TBRANCH);
2990 ** For each element that is true guarded (i.e., if (x != NULL))
2991 ** make x = null in false branch,
2992 ** and x = notnull in true branch.
2993 ** unless x was set locally in that branch.
2994 ** For each element that is false guarded (x == NULL)
2995 ** make x = null in true, notnull in false.
2997 ** For each element that is either guarded (pred(x))
3001 sRefSet_allElements (tguards, el)
3003 updateNullState (el, ttab, ftab, TRUE);
3004 } end_sRefSet_allElements;
3006 sRefSet_allElements (fguards, el)
3008 updateNullState (el, ttab, ftab, FALSE);
3009 } end_sRefSet_allElements;
3013 ** if an entry is in both true and false, merge the entries,
3014 ** then replace original with new state.
3016 ** if an entry is in one table, merge it with the original.
3019 DPRINTF (("ftab: %d", ftab->nentries));
3021 for (i = 0; i < ftab->nentries; i++)
3023 uentry fthis = ftab->entries[i];
3024 uentry old = usymtab_lookupAux (env, uentry_rawName (fthis));
3025 int tindex = usymtab_getIndex (ttab, uentry_rawName (fthis));
3027 DPRINTF (("Entry: %s / %s", uentry_unparseFull (fthis), uentry_unparseFull (old)));
3029 if (uentry_isUndefined (old))
3031 /* possible entry was added as an undefined id */
3032 DPRINTF (("Undefined! %s", uentry_rawName (fthis)));
3036 if (tindex != NOT_FOUND)
3038 uentry tthis = ttab->entries[tindex];
3040 /* note that is this is in a nested branch,
3041 it may create a "new" old entry. */
3047 uentry_mergeState (fthis, tthis, loc,
3048 mustReturnT, FALSE, FALSE, cl);
3052 uentry_mergeUses (fthis, tthis);
3055 uentry_setState (old, fthis);
3062 uentry_setState (old, tthis);
3063 uentry_mergeState (old, fthis, loc, mustReturnF,
3067 ttab->entries[tindex] = uentry_undefined;
3068 uentry_free (tthis);
3072 uentry_mergeState (old, fthis, loc, mustReturnF, TRUE, FALSE, cl);
3076 for (i = 0; i < ttab->nentries; i++)
3078 uentry current = ttab->entries[i];
3080 DPRINTF (("ttab: %s", uentry_unparseFull (current)));
3082 if (!uentry_isUndefined (current))
3084 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
3086 DPRINTF (("Old: %s", uentry_unparseFull (old)));
3088 if (uentry_isUndefined (old))
3090 llcontbug (message ("Undefined entry: %s", uentry_rawName (current)));
3096 uentry_mergeUses (current, old);
3097 uentry_setState (old, current);
3102 ** Assumes false branch is a fall-through if
3103 ** fbranch is not defined. This is true, unless
3104 ** where was some greivous error in processing
3105 ** the else branch of an if-then, in which case
3106 ** this is probably the right thing to do anyway.
3109 uentry_mergeState (old, current, loc, mustReturnT,
3113 DPRINTF (("==> %s", uentry_unparseFull (old)));
3118 ** Plain levelUnion doesn't work, since we need to use the sRef's in env->aliases
3119 ** if they are present.
3122 llassert (NOALIAS (env->aliases, ttab->aliases));
3123 llassert (NOALIAS (env->aliases, ftab->aliases));
3125 aliasTable_free (env->aliases);
3127 env->aliases = aliasTable_levelUnionNew (ttab->aliases,
3128 ftab->aliases, env->lexlevel);
3130 aliasTable_fixSrefs (env->aliases);
3132 DPRINTF (("Aliases: %s", aliasTable_unparse (env->aliases)));
3134 /* exit true and false scopes */
3135 usymtab_quietPlainExitScope ();
3136 usymtab_quietPlainExitScope ();
3140 utab->guards = guardSet_levelUnionFree
3142 guardSet_invert (exprNode_getGuards (pred)),
3148 utab->guards = guardSet_levelUnion (utab->guards,
3149 exprNode_getGuards (pred),
3153 DPRINTF (("Here."));
3156 static void usymtab_fixCases (void) /*@modifies utab@*/ {
3157 while (utab->kind == US_CBRANCH)
3159 usymtab_quietPlainExitScope ();
3162 llassert (utab->kind != US_CBRANCH);
3166 usymtab_altBranch (/*@only@*/ guardSet guards)
3170 usymtab parent = utab->env;
3172 t = usymtab_create (US_FBRANCH, utab, FALSE);
3175 ** If we are in a case, need to close it. The C syntax
3176 ** is very liberal, so this kludge is necessary.
3179 usymtab_fixCases ();
3181 DPRINTF (("Current kind: %s", usymtab_unparseStack ()));
3183 llassert (utab->kind == US_TBRANCH);
3184 llassert (parent != GLOBAL_ENV);
3186 guardSet_free (t->guards);
3189 aliasTable_free (t->aliases);
3190 t->aliases = aliasTable_copy (parent->aliases);
3196 usymtab_allDefined (void)
3197 /*@globals utab, globtab@*/
3201 llassert (utab == globtab);
3203 for (i = 0; i < utab->nentries; i++)
3205 uentry e = utab->entries[i];
3207 if (uentry_isPriv (e))
3209 ; /* no need to define it */
3213 if (context_getFlag (FLG_SPECUNDECL))
3215 fileloc sloc = uentry_whereSpecified (e);
3216 fileloc dloc = uentry_whereDeclared (e);
3218 if (fileloc_isDefined (sloc)
3219 && !uentry_isFakeTag (e)
3220 && !fileloc_isDefined (dloc))
3224 message ("%s %q specified but not declared",
3225 ekind_capName (uentry_getKind (e)),
3226 uentry_getName (e)),
3231 if (!uentry_isCodeDefined (e))
3233 fileloc dloc = uentry_whereDeclared (e);
3235 if (fileloc_isLib (dloc) || fileloc_isXHFile (dloc))
3239 else if (fileloc_isDefined (dloc))
3241 if (!uentry_isAnyTag (e))
3243 if (fileloc_isUser (dloc))
3247 message ("%s %q declared but not defined",
3248 ekind_capName (uentry_getKind (e)),
3249 uentry_getName (e)),
3251 DPRINTF (("decl: %s", uentry_unparseFull (e)));
3257 fileloc sloc = uentry_whereSpecified (e);
3259 if (fileloc_isDefined (sloc)
3260 && !fileloc_isImport (sloc)
3261 && !fileloc_isLib (sloc)
3262 && !fileloc_isPreproc (sloc)
3263 && !uentry_isFakeTag (e))
3265 if (uentry_isVariable (e) || uentry_isFunction (e))
3269 message ("%s %q specified but not declared or defined",
3270 ekind_capName (uentry_getKind (e)),
3271 uentry_getName (e)),
3278 message ("%s %q specified but not defined",
3279 ekind_capName (uentry_getKind (e)),
3280 uentry_getName (e)),
3290 void usymtab_exportHeader (void)
3295 for (i = 0; i < utab->nentries; i++)
3297 uentry ce = utab->entries[i];
3299 if (!uentry_isDatatype (ce)
3300 && !uentry_isAnyTag (ce)
3301 && !uentry_isEitherConstant (ce) && !uentry_isStatic (ce)
3302 && !uentry_isExternal (ce)
3303 && !uentry_isForward (ce))
3305 fileloc fwhere = uentry_whereDeclared (ce);
3307 if (fileloc_isUndefined (fwhere)
3308 && uentry_isFunction (ce))
3310 fwhere = uentry_whereDefined (ce);
3313 if (fileloc_isDefined (fwhere)
3314 && !fileloc_isHeader (fwhere)
3315 && !fileloc_isXHFile (fwhere)
3316 && !(fileloc_isSpecialFile (fwhere)
3317 && !context_getFlag (FLG_UNUSEDSPECIAL)))
3319 if (uentry_isVariable (ce))
3322 (FLG_EXPORTHEADERVAR,
3323 message ("%s %q exported but not declared in header file",
3324 ekind_capName (uentry_getKind (ce)),
3325 uentry_getName (ce)),
3328 uentry_showDefSpecInfo (ce, fwhere);
3333 if (!uentry_isIter (ce)
3334 && !uentry_isEndIter (ce)
3335 && !uentry_isExpandedMacro (ce))
3337 if (uentry_isFunction (ce)
3338 && cstring_equalLit (uentry_rawName (ce), "main"))
3340 ; /* no error for main */
3346 message ("%s %q exported but not declared "
3348 ekind_capName (uentry_getKind (ce)),
3349 uentry_getName (ce)),
3352 uentry_showDefSpecInfo (ce, fwhere);
3362 void usymtab_exportLocal (void)
3367 for (i = 0; i < utab->nentries; i++)
3369 uentry ce = utab->entries[i];
3371 if (!uentry_isDatatype (ce) && !uentry_isAnyTag (ce)
3372 && !uentry_isEitherConstant (ce)
3373 && !uentry_isIter (ce)
3374 && !uentry_isEndIter (ce)
3375 && !uentry_isExpandedMacro (ce)
3376 && uentry_isUsed (ce))
3378 /* check static uses */
3379 filelocList fuses = uentry_getUses (ce);
3380 fileloc mod = uentry_whereDefined (ce);
3381 bool ok = filelocList_isEmpty (fuses);
3382 fileloc fwhere = uentry_whereDeclared (ce);
3384 if (fileloc_isSpecialFile (fwhere)
3385 && !context_getFlag (FLG_UNUSEDSPECIAL))
3387 ok = TRUE; /* no errors for special files */
3391 filelocList_elements (fuses, uloc)
3393 if (fileloc_isUndefined (uloc) || !fileloc_sameModule (uloc, mod))
3396 /*@innerbreak@*/ break;
3398 } end_filelocList_elements;
3405 message ("%s exported but not used outside %s: %q",
3406 ekind_capName (uentry_getKind (ce)),
3407 fileloc_getBase (mod),
3408 uentry_getName (ce)),
3411 uentry_showDefSpecInfo (ce, fwhere);
3419 usymtab_allUsed (void)
3423 bool isFileStatic = usymtab_inFileScope ();
3424 cstring last_file = cstring_undefined;
3426 for (i = 0; i < utab->nentries; i++)
3428 bool hasError = FALSE;
3429 uentry ce = utab->entries[i];
3430 fileloc fwhere = uentry_whereDeclared (ce);
3432 if (fileloc_isUndefined (fwhere))
3434 fwhere = uentry_whereDefined (ce);
3437 if (fileloc_isInvalid (fwhere)
3438 || fileloc_isLib (fwhere)
3439 || fileloc_isBuiltin (fwhere)
3440 || ((fileloc_isSpecialFile (fwhere)
3441 || fileloc_isSpecialFile (uentry_whereDefined (ce)))
3442 && !context_getFlag (FLG_UNUSEDSPECIAL)))
3446 else if (!uentry_wasUsed (ce) && !uentry_isAnyTag (ce))
3448 cstring fname = fileloc_filename (fwhere);
3450 if (cstring_isUndefined (last_file))
3454 else if (cstring_equal (fname, last_file))
3463 if (uentry_isParam (ce))
3465 if (context_inMacro ())
3467 sRef cref = uentry_getSref (ce);
3469 if (uentry_isYield (ce))
3471 ; /* no checks (for now) */
3473 else if (sRef_isSafe (cref))
3479 if (uentry_hasRealName (ce))
3482 optgenerror (FLG_MACROPARAMS,
3483 message ("Macro parameter %q not used",
3484 uentry_getName (ce)),
3491 if (cstring_equalFree (uentry_getName (ce),
3492 cstring_makeLiteral ("...")))
3498 hasError = optgenerror (FLG_PARAMUNUSED,
3499 message ("Parameter %q not used",
3500 uentry_getName (ce)),
3505 else if (uentry_isFunction (ce) || uentry_isIter (ce))
3507 if (fileloc_isUser (fwhere))
3509 hasError = optgenerror
3511 message ("%q %q declared but not used",
3513 (uentry_isIter (ce) ? "Iterator"
3514 : (isFileStatic ? "File static function" : "Function")),
3515 uentry_getName (ce)),
3519 else if (uentry_isEndIter (ce))
3521 ; /* no error (already reported for iter */
3523 else if (uentry_isEnumConstant (ce))
3525 if (fileloc_isUser (fwhere))
3527 hasError = optgenerror
3529 message ("Enum member %q not used",
3530 uentry_getName (ce)),
3534 else if (uentry_isConstant (ce))
3536 if (fileloc_isUser (fwhere))
3538 hasError = optgenerror
3540 message ("Constant %q declared but not used",
3541 uentry_getName (ce)),
3545 else if (uentry_isDatatype (ce))
3547 if (fileloc_isUser (fwhere))
3549 hasError = optgenerror
3551 message ("Type %q declared but not used",
3552 uentry_getName (ce)),
3556 else if (!uentry_isRefParam (ce) && !uentry_isExpandedMacro (ce))
3557 { /* errors for ref params will be reported in the next scope */
3558 llassertprint (uentry_isVar (ce),
3559 ("ce: %s", uentry_unparseFull (ce)));
3561 if (ctype_isFunction (uentry_getType (ce)))
3563 if (fileloc_isUser (fwhere))
3565 hasError = optgenerror
3567 message ("%q %q declared but not used",
3569 (isFileStatic ? "File static function"
3571 uentry_getName (ce)),
3577 if (fileloc_isUser (fwhere))
3581 hasError = optgenerror
3583 message ("%q %q declared but not used",
3585 (isFileStatic ? "File static variable"
3587 uentry_getName (ce)),
3597 else if ((uentry_isDatatype (ce) || uentry_isAnyTag (ce)))
3598 { /* check all fields */
3599 ctype ct = uentry_getRealType (ce);
3602 while (ctype_isAP (ct))
3604 ct = ctype_getBaseType (ct);
3607 if (ctype_isSU (ct))
3609 uentryList fields = ctype_getFields (ct);
3611 uentryList_elements (fields, field)
3613 if (!uentry_isUsed (field))
3615 if (uentry_hasName (ce))
3617 hasError |= optgenerror
3619 message ("Field %q of %s %q declared but not used",
3620 uentry_getName (field),
3621 cstring_makeLiteralTemp
3622 (ctype_isStruct (ct) ? "structure" : "union"),
3623 uentry_getName (ce)),
3624 uentry_whereEarliest (field));
3630 ** Can't report these errors for unnamed structs.
3631 ** No way to tell when there are multiple consistent
3632 ** unnamed structure types. (Could go through table
3633 ** and mark them all unused...)
3635 hasError |= optgenerror
3637 message ("Field %q of unnamed %s declared but not used",
3638 uentry_getName (field),
3639 cstring_makeLiteralTemp
3640 (ctype_isStruct (ct) ? "structure" : "union")),
3641 uentry_whereEarliest (field));
3646 uentry_setUsed (field, fileloc_undefined);
3648 } end_uentryList_elements;
3658 if (uentry_isParam (ce) && context_inMacro ())
3660 if (fileloc_isDefined (uentry_whereSpecified (ce)))
3662 uentry_showWhereSpecified (ce);
3667 uentry_showDefSpecInfo (ce, fwhere);
3670 uentry_setUsed (ce, fileloc_undefined);
3676 checkGlobalReturn (uentry glob, sRef orig)
3678 sRef sr = uentry_getSref (glob);
3680 DPRINTF (("Check global return: %s / orig: %s / sr: %s",
3681 uentry_unparseFull (glob),
3682 sRef_unparseFull (orig),
3683 sRef_unparseFull (sr)));
3685 DPRINTF (("Is killed: %s", bool_unparse (sRef_isKilledGlob (orig))));
3687 if (context_getFlag (FLG_GLOBSTATE))
3689 DPRINTF (("Is killed: %s", sRef_unparseFull (orig)));
3691 if (sRef_isKilledGlob (orig))
3693 if (sRef_isStateUndefined (sr)
3694 || sRef_isUnuseable (sr)
3695 || sRef_isStateUnknown (sr)
3696 || sRef_isDead (sr))
3702 ctype ct = ctype_realType (uentry_getType (glob));
3704 DPRINTF (("Check global destroyed: %s", uentry_unparseFull (glob)));
3706 if (ctype_isVisiblySharable (ct))
3711 ("Killed global %q (type %s) not released before return",
3712 uentry_getName (glob),
3713 ctype_unparse (ct)),
3716 sRef_showStateInfo (sr);
3721 sRef_protectDerivs ();
3722 (void) transferChecks_globalDestroyed (sr, g_currentloc);
3723 sRef_clearProtectDerivs ();
3729 if (sRef_isStateUndefined (sr))
3731 if (optgenerror (FLG_GLOBSTATE,
3733 ("Function returns with global %q undefined",
3734 uentry_getName (glob)),
3737 sRef_showStateInfo (sr);
3742 if (sRef_isDead (sr) || sRef_isKept (sr))
3746 message ("Function returns with global %q "
3747 "referencing %s storage",
3748 uentry_getName (glob),
3749 cstring_makeLiteralTemp (sRef_isDead (sr) ? "released" : "kept")),
3752 if (sRef_isKept (sr))
3754 sRef_showAliasInfo (sr);
3758 sRef_showStateInfo (sr);
3761 sRef_setDefState (sr, SS_UNKNOWN, fileloc_undefined);
3765 if (ctype_isRealPointer (uentry_getType (glob))
3766 && sRef_possiblyNull (sr)
3767 && !uentry_possiblyNull (glob))
3771 message ("Function returns with non-null global %q "
3772 "referencing null storage",
3773 uentry_getName (glob)),
3776 sRef_showNullInfo (sr);
3781 DPRINTF (("Check transfer: %s", uentry_unparseFull (glob)));
3782 transferChecks_globalReturn (glob);
3790 ** remember: check alias globals
3793 void usymtab_checkFinalScope (bool isReturn)
3796 bool mustFree = context_getFlag (FLG_MUSTFREEONLY) || context_getFlag (FLG_MUSTFREEFRESH); /*@i423 remove this mustFree */
3797 bool mustDefine = context_getFlag (FLG_MUSTDEFINE);
3798 /* bool mustNotAlias = context_getFlag (FLG_MUSTNOTALIAS); */
3799 sRefSet checked = sRefSet_new ();
3800 usymtab stab = utab;
3804 ** need to check all scopes out to function parameters.
3809 for (i = 0; i < stab->nentries; i++)
3811 uentry ce = stab->entries[i];
3812 sRef sr = uentry_getSref (ce);
3813 sRef rb = sRef_getRootBase (sr);
3817 ** Shouldn't check if shadow checked in deeper scope:
3822 uentry oue = usymtab_lookupQuietNoAlt (utab, uentry_observeRealName (ce));
3824 if (!uentry_sameObject (ce, oue))
3826 DPRINTF (("Skipping outer entry: %s / %s", uentry_unparseFull (ce),
3827 uentry_unparseFull (oue)));
3828 /*@i32 what if it is one an alternate branch? */
3829 /*@innercontinue@*/ continue;
3833 DPRINTF (("Here check final scope: %s", uentry_unparseFull (ce)));
3835 if (ctype_isFunction (uentry_getType (ce)))
3837 /*@innercontinue@*/ continue;
3840 if (uentry_isAnyParam (ce)
3841 || uentry_isRefParam (ce)
3842 || sRef_isFileOrGlobalScope (rb))
3844 /* Don't do the loseref check...but should check state! */
3845 DPRINTF (("Skipping check 1"));
3847 else if (sRef_isDefinitelyNull (sr)
3848 || usymtab_isDefinitelyNull (sr))
3851 ** No state reference errors for definitely null references.
3854 DPRINTF (("Skipping check 2"));
3858 DPRINTF (("Lose ref: %s / %s", uentry_unparse (ce),
3859 sRef_unparseFull (sr)));
3861 tvalues = sRef_getValueTable (sr);
3863 valueTable_elements (tvalues, fkey, fval) {
3864 metaStateInfo minfo;
3865 cstring msg = cstring_undefined;
3868 minfo = context_lookupMetaStateInfo (fkey);
3869 llassert (metaStateInfo_isDefined (minfo));
3871 if (stateValue_isError (fval)
3872 || sRef_isStateUndefined (sr)) /* No errors for undefined state */
3874 DPRINTF (("Skipping check 3"));
3878 DPRINTF (("Check: %s / %s / %s", fkey,
3879 metaStateInfo_unparse (minfo),
3880 stateValue_unparse (fval)));
3882 minfo = context_lookupMetaStateInfo (fkey);
3884 nval = stateCombinationTable_lookupLoseReference
3885 (metaStateInfo_getTransferTable (minfo),
3886 stateValue_getValue (fval), &msg);
3888 if (cstring_isDefined (msg))
3890 /*@i32 print extra info for assignments@*/
3891 DPRINTF (("From: %s", sRef_unparseFull (sr)));
3892 DPRINTF (("Null? %s / %s",
3893 bool_unparse (sRef_isDefinitelyNull (sr)),
3894 bool_unparse (usymtab_isGuarded (sr))));
3899 ("%s loses reference %q in invalid state %q (%s)",
3900 cstring_makeLiteralTemp (isReturn ? "Return" : "Scope exit"),
3901 uentry_getName (ce),
3902 stateValue_unparseValue (fval, minfo),
3906 stateValue_show (fval, minfo);
3910 DPRINTF (("Suppressed transfer error: %s", msg));
3914 } end_valueTable_elements;
3917 DPRINTF (("Here 1"));
3921 DPRINTF (("Check mustfree entry: %s", uentry_unparseFull (ce)));
3923 if (!sRefSet_member (checked, sr) && !sRef_isFileOrGlobalScope (rb))
3925 if (ctype_isRealSU (uentry_getType (ce))
3926 && !uentry_isAnyParam (ce)
3927 && !uentry_isRefParam (ce)
3928 && !uentry_isStatic (ce)
3929 && !sRef_isDependent (sr)
3930 && !sRef_isOwned (sr))
3932 sRefSet als = usymtab_allAliases (sr);
3934 if (sRefSet_isEmpty (als))
3936 transferChecks_localDestroyed (sr, g_currentloc);
3940 /* aliased, no problem */ ;
3946 (!uentry_isStatic (ce)
3947 && ((sRef_isNewRef (sr))
3948 || (((sRef_isOnly (sr) || sRef_isFresh (sr)
3949 || sRef_isKeep (sr) || sRef_isOwned (sr))
3950 && !sRef_isDead (sr))
3951 && (!sRef_definitelyNull (sr))
3952 && (!usymtab_isDefinitelyNull (sr)))))
3954 bool hasError = TRUE;
3956 DPRINTF (("Checking: %s", sRef_unparseFull (sr)));
3959 ** If its a scope exit, check if there is an alias.
3960 ** If so, make it only. If not, there is an error.
3965 if (transferChecks_canLoseReference (sr, g_currentloc))
3967 DPRINTF (("Can lose!"));
3974 if (sRef_hasLastReference (sr))
3976 sRef ar = sRef_getAliasInfoRef (sr);
3979 (sRef_isFresh (ar) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
3981 ("Last reference %q to %s storage %qnot %q before %q",
3983 alkind_unparse (sRef_getAliasKind (sr)),
3984 sRef_unparseOpt (ar),
3985 cstring_makeLiteral (sRef_isKeep (sr)
3986 ? "transferred" : "released"),
3987 cstring_makeLiteral (isReturn
3988 ? "return" : "scope exit")),
3991 sRef_showRefLost (sr);
3994 else if (sRef_isNewRef (sr))
3997 (sRef_isFresh (sr) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
3999 ("%q %q not released before %q",
4001 (alkind_isKillRef (sRef_getOrigAliasKind (sr))
4002 ? "Kill reference parameter" : "New reference"),
4003 uentry_getName (ce),
4004 cstring_makeLiteral (isReturn
4005 ? "return" : "scope exit")),
4008 sRef_showAliasInfo (sr);
4013 if (ctype_isRealSU (sRef_getType (sr)))
4015 transferChecks_structDestroyed (sr, g_currentloc);
4019 DPRINTF (("Here we are: %s", sRef_unparseFull (sr)));
4022 (sRef_isFresh (sr) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4024 ("%s storage %q not %q before %q",
4025 alkind_capName (sRef_getAliasKind (sr)),
4026 uentry_getName (ce),
4027 cstring_makeLiteral (sRef_isKeep (sr)
4028 ? "transferred" : "released"),
4029 cstring_makeLiteral (isReturn
4030 ? "return" : "scope exit")),
4033 sRef_showAliasInfo (sr);
4034 DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
4047 if (mustDefine && uentry_isOut (ce))
4049 /* No error if its dead (either only or error already reported */
4050 if (!sRef_isReallyDefined (sr) && !sRef_isDead (sr))
4054 message ("Out storage %q not defined before %q",
4055 uentry_getName (ce),
4057 (isReturn ? "return" : "scope exit")),
4060 DPRINTF (("sr: %s", sRef_unparseFull (sr)));
4065 ** also check state is okay
4068 if (usymtab_lexicalLevel () > functionScope
4069 && uentry_isVariable (ce)
4070 && (sRef_isLocalVar (sr)
4071 && (sRef_isDependent (sr) || sRef_isLocalState (sr))))
4073 sRefSet ab = usymtab_aliasedBy (sr);
4075 /* should do something more efficient here */
4077 if (sRefSet_isEmpty (ab))
4079 /* and no local ref */
4080 DPRINTF (("Check lose ref: %s", uentry_unparseFull (ce)));
4081 transferChecks_loseReference (ce);
4095 checked = sRefSet_insert (checked, sr);
4098 llassert (usymtab_isDefined (stab->env));
4100 if (usymtab_isBranch (stab))
4102 stab = usymtab_dropEnv (stab);
4109 llassert (stab != usymtab_undefined);
4110 } while (isReturn && (stab->lexlevel >= paramsScope));
4112 sRefSet_free (checked);
4116 ** all globals are appropriately defined
4117 ** all parameters are appropriately defined
4118 ** special clauses are followed
4121 if (isReturn || (utab->lexlevel == paramsScope))
4123 uentry fcn = context_getHeader ();
4124 uentryList params = context_getParams ();
4125 globSet uglobs = context_getUsedGlobs ();
4126 globSet sglobs = context_getGlobs ();
4128 if (isReturn && context_maybeSet (FLG_GLOBALIAS))
4130 aliasTable_checkGlobs (utab->aliases);
4134 ** state clauses (ensures, defines, sets, allocates, releases)
4137 if (uentry_hasStateClauseList (fcn))
4139 stateClauseList clauses = uentry_getStateClauseList (fcn);
4141 stateClauseList_elements (clauses, cl)
4143 if (stateClause_isAfter (cl) && !stateClause_isGlobal (cl))
4145 if (stateClause_setsMetaState (cl))
4147 sRefSet rfs = stateClause_getRefs (cl);
4148 qual q = stateClause_getMetaQual (cl);
4149 annotationInfo ainfo = qual_getAnnotationInfo (q);
4150 metaStateInfo minfo = annotationInfo_getState (ainfo);
4151 cstring key = metaStateInfo_getName (minfo);
4152 int mvalue = annotationInfo_getValue (ainfo);
4154 DPRINTF (("Post meta state clause: %s", stateClause_unparse (cl)));
4156 sRefSet_elements (rfs, el)
4158 sRef base = sRef_getRootBase (el);
4160 if (sRef_isResult (base))
4163 ** This is checked for return transfers.
4167 else if (sRef_isParam (base) || sRef_isGlobalMarker (base))
4169 sRef sr = sRef_updateSref (base);
4170 sr = sRef_fixBase (el, sr);
4172 if (!sRef_checkMetaStateValue (sr, key, mvalue))
4177 ("Ensures clause not satisfied%q (state is %q): %q",
4178 sRef_isGlobalMarker (sr)
4180 : message (" by %q", sRef_unparse (sr)),
4181 stateValue_unparseValue (sRef_getMetaStateValue (sr, key),
4183 stateClause_unparse (cl)),
4186 sRef_showMetaStateInfo (sr, key);
4192 if (sRef_isMeaningful (el))
4197 } end_sRefSet_elements ;
4201 /* evs - 2000 07 10 - added this */
4202 sRefTest tst = stateClause_getPostTestFunction (cl);
4203 sRefSet rfs = stateClause_getRefs (cl);
4205 sRefSet_elements (rfs, el)
4207 sRef base = sRef_getRootBase (el);
4209 if (sRef_isResult (base))
4212 ** This is checked for return transfers.
4217 else if (sRef_isParam (base))
4219 sRef sr = sRef_updateSref (base);
4220 sr = sRef_fixBase (el, sr);
4222 if (tst != NULL && !tst (sr))
4225 (stateClause_postErrorCode (cl),
4226 message ("%s storage %qcorresponds to "
4227 "storage listed in %q clause",
4228 stateClause_postErrorString (cl, sr),
4229 sRef_unparseOpt (sr),
4230 stateClause_unparseKind (cl)),
4233 sRefShower ss = stateClause_getPostTestShower (cl);
4240 DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
4246 if (sRef_isMeaningful (el))
4251 } end_sRefSet_elements ;
4254 } end_stateClauseList_elements ;
4258 ** check parameters on return
4261 uentryList_elements (params, arg)
4263 if (!uentry_isElipsisMarker (arg))
4265 ctype rt = ctype_realType (uentry_getType (arg));
4267 if (ctype_isMutable (rt) || ctype_isSU (rt))
4269 uentry param = usymtab_lookupQuiet (utab, uentry_rawName (arg));
4270 DPRINTF (("Check param return: %s", uentry_unparseFull (param)));
4271 transferChecks_paramReturn (param);
4274 } end_uentryList_elements;
4276 DPRINTF (("Check global return: %s",
4277 globSet_unparse (sglobs)));
4279 globSet_allElements (sglobs, el)
4281 sRef orig = el; /*! sRef_updateSref (el); */ /*!!!*/
4282 uentry current = sRef_getUentry (el);
4284 DPRINTF (("Check global return: %s / %s", sRef_unparseFull (el),
4285 uentry_unparseFull (current)));
4287 if (uentry_isVariable (current) && !uentry_isRealFunction (current))
4289 checkGlobalReturn (current, orig);
4291 } end_globSet_allElements;
4293 globSet_allElements (uglobs, el)
4295 if (!globSet_member (sglobs, el))
4297 uentry current = sRef_getUentry (el);
4299 if (uentry_isVariable (current)
4300 && !uentry_isRealFunction (current))
4302 checkGlobalReturn (current, sRef_undefined);
4305 } end_globSet_allElements;
4310 usymtab_quietExitScope (fileloc loc)
4311 /*@globals utab, globtab, filetab; @*/
4314 usymtab t = utab->env;
4316 if (utab->reftable != NULL)
4320 for (i = 0; i < utab->nentries; i++)
4322 uentry current = utab->entries[i];
4323 uentry old = usymtab_lookupAux (t, uentry_rawName (current));
4325 uentry_mergeState (old, current, loc, FALSE, FALSE, FALSE, NOCLAUSE);
4329 llassert (t != NULL);
4331 if (t->lexlevel > paramsScope)
4333 t->guards = guardSet_levelUnion (t->guards, utab->guards, t->lexlevel);
4334 t->aliases = aliasTable_levelUnionSeq (t->aliases, utab->aliases,
4336 utab->aliases = aliasTable_undefined;
4339 t->mustBreak = utab->mustBreak;
4340 t->exitCode = utab->exitCode;
4342 usymtab_freeLevel (utab);
4347 usymtab_checkAllValid ();
4352 ** Exit a scope with no checking, lose alias states.
4353 ** (When should this be used?)
4356 void usymtab_quietPlainExitScope (void)
4357 /*@globals utab, globtab, filetab@*/
4360 usymtab t = utab->env;
4362 llassert (t != NULL);
4363 llassert (NOALIAS (utab->aliases, t->aliases));
4364 usymtab_freeLevel (utab);
4368 void usymtab_exitScope (exprNode expr)
4369 /*@globals utab, filetab, globtab@*/
4370 /*@modifies utab, globtab@*/
4372 usymtab ctab = usymtab_undefined;
4373 usymtab lctab = usymtab_undefined;
4374 bool mustReturn = exprNode_mustEscape (expr);
4376 DPRINTF (("Exit scope"));
4378 if (utab->kind == US_CBRANCH)
4381 ** save the case branches, remove the first non-cbranch
4386 while (utab->kind == US_CBRANCH)
4390 llassert (utab != GLOBAL_ENV);
4394 if (utab->kind == US_TBRANCH || utab->kind == US_FBRANCH
4395 || utab->kind == US_CBRANCH || utab->kind == US_SWITCH)
4397 if (context_inMacro ())
4399 /* evs 2000-07-25 */
4400 /* Unparseable macro may end inside nested scope. Deal with it. */
4402 llerror (FLG_SYNTAX,
4403 message ("Problem parsing macro body of %s (unbalanced scopes). "
4404 "Attempting to recover, recommend /*@notfunction@*/ before "
4405 "macro definition.",
4406 context_inFunctionName ()));
4408 while (utab->kind == US_TBRANCH
4409 || utab->kind == US_FBRANCH
4410 || utab->kind == US_CBRANCH
4411 || utab->kind == US_SWITCH)
4414 llassert (utab != GLOBAL_ENV);
4418 llcontbug (message ("exitScope: in branch: %q", usymtab_unparseStack ()));
4420 } /*@=branchstate@*/
4424 ** check all variables in scope were used
4428 ** bogus errors if this is the normal inside a switch,
4429 ** since cases have not been merged yet. Should probably
4430 ** still check this, but I'm too lazy at the moment...
4433 llassertfatal (utab->env != GLOBAL_ENV);
4435 if (utab->env->kind != US_SWITCH)
4441 ** check aliasing: all only params are released (dead)
4442 ** definition: all out params are defined, all modified params
4443 ** are completely defined
4445 ** NOTE: note for exiting paramsScope, since checkReturn should be
4449 if (!mustReturn && (usymtab_lexicalLevel () > functionScope))
4452 ** should only call this is end of scope is reachable...
4455 usymtab_checkFinalScope (FALSE);
4458 if (usymtab_lexicalLevel () == paramsScope && context_inFunctionLike ())
4461 ** leaving a function, need to fix up globals
4464 uentryList params = context_getParams ();
4465 globSet globs = context_getUsedGlobs ();
4467 uentryList_elements (params, ue)
4469 uentry_fixupSref (ue);
4470 } end_uentryList_elements;
4472 clearFunctionTypes ();
4474 DPRINTF (("Fixing up globals: %s", globSet_unparse (globs)));
4476 globSet_allElements (globs, el)
4478 DPRINTF (("Fix: %s", sRef_unparseDebug (el)));
4480 if (sRef_isCvar (el))
4483 int index = sRef_getScopeIndex (el);
4485 if (sRef_isFileStatic (el))
4487 llassert (usymtab_isDefined (filetab));
4488 current = usymtab_fetchIndex (filetab, index);
4492 current = usymtab_fetchIndex (globtab, index);
4495 if (uentry_isVariable (current))
4497 DPRINTF (("Fixup: %s", uentry_unparse (current)));
4498 uentry_fixupSref (current);
4502 DPRINTF (("Clear: %s", uentry_getSref (current)));
4503 sRef_clearDerived (uentry_getSref (current));
4507 sRef_clearDerived (el); /* evans 2002-03-14 - this is the likely source of many crashes! */
4508 } end_globSet_allElements;
4511 usymtab_quietExitScope (exprNode_loc (expr));
4513 if (lctab != usymtab_undefined)
4515 /*@i@*/ lctab->env = utab;
4516 /*@i@*/ utab = ctab;
4517 /*@-branchstate@*/ } /*@=branchstate@*/
4522 usymtab_checkAllValid ();
4528 ** yikes! don't let the '170 kids see this one...
4532 uentry_directParamNo (uentry ue)
4534 if (uentry_isVar (ue))
4536 sRef sr = uentry_getSref (ue);
4538 if (sRef_lexLevel (sr) == functionScope)
4540 int index = sRef_getScopeIndex (sr);
4542 if (index < uentryList_size (context_getParams ()))
4551 /*@dependent@*/ /*@exposed@*/ uentry
4552 usymtab_getParam (int paramno)
4556 ** requires in a function context (checked)
4558 ** depends on no nested functions --- the function
4559 ** parameters are ALWAYS one scope inside the global scope
4560 ** and entered in order!
4564 if (!context_inFunctionLike ())
4565 llfatalbug (message ("usymtab_getParam: not in function context: %q",
4566 context_unparse ()));
4568 while (s->lexlevel > paramsScope)
4573 llassert (usymtab_isDefined (s));
4575 if (paramno >= s->nentries)
4578 ** Parse errors lead to this.
4581 uentry err = uentry_makeVariableLoc (cstring_makeLiteralTemp ("<error>"),
4584 uentry_markOwned (err);
4588 return (s->entries[paramno]);
4591 static /*@dependent@*/ /*@exposed@*/ uentry
4592 usymtab_getRefTab (/*@notnull@*/ usymtab u, int level, usymId index)
4596 ue = usymtab_getRefNoisy (u, level, index);
4598 if (uentry_isUndefined (ue))
4600 llbug (message ("usymtab_getRef: out of range: %d. level = %d",
4607 static /*@dependent@*/ /*@exposed@*/ usymtab
4608 usymtab_dropEnv (/*@notnull@*/ usymtab s)
4610 if (s->kind == US_CBRANCH)
4618 llassert (s != GLOBAL_ENV);
4619 } while (s->kind == US_CBRANCH);
4620 /* drop all cases (except in nested scopes */
4623 llassert (s != GLOBAL_ENV);
4626 if (s->kind == US_FBRANCH)
4628 s = s->env; /* skip the true branch */
4629 llassert (usymtab_isDefined (s));
4630 llassert (s->kind == US_TBRANCH);
4633 llassert (s != GLOBAL_ENV);
4639 /*@dependent@*/ /*@exposed@*/ uentry
4640 usymtab_getRefQuiet (int level, usymId index)
4646 llassert (s != NULL);
4647 llassert (index >= 0);
4649 if (level > s->lexlevel)
4651 return uentry_undefined;
4654 llassertprint (level <= s->lexlevel, ("level: %d / lexlevel: %d",
4655 level, s->lexlevel));
4657 while (s->lexlevel > level)
4659 if (usymtab_isBranch (s))
4661 int eindex = refTable_lookup (s, level, index);
4663 if (eindex != NOT_FOUND)
4665 return (s->entries[eindex]);
4669 s = usymtab_dropEnv (s);
4672 while (usymtab_isBranch (s) && s->lexlevel == level)
4674 int eindex = refTable_lookup (s, level, index);
4676 if (eindex != NOT_FOUND)
4678 return (s->entries[eindex]);
4681 s = usymtab_dropEnv (s);
4684 if (index >= s->nentries)
4686 return uentry_undefined;
4689 llassert (!uentry_isUndefined (s->entries[index]));
4691 return s->entries[index];
4694 static /*@dependent@*/ /*@exposed@*/ uentry
4695 usymtab_getRefNoisy (/*@notnull@*/ usymtab s, int level, usymId index)
4698 uentry ue = uentry_undefined;
4700 llassert (index >= 0);
4702 while (s->lexlevel > level)
4704 if (usymtab_isBranch (s))
4706 int eindex = refTable_lookup (s, level, index);
4708 if (eindex != NOT_FOUND)
4710 ue = s->entries[eindex];
4714 while (!usymtab_isBranch (otab))
4716 otab = usymtab_dropEnv (otab);
4717 llassert (otab != GLOBAL_ENV);
4720 if (refTable_lookup (otab, level, index) == NOT_FOUND)
4722 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4734 s = usymtab_dropEnv (s);
4737 llassert (usymtab_isDefined (s));
4739 while (usymtab_isBranch (s) && s->lexlevel == level)
4741 int eindex = refTable_lookup (s, level, index);
4744 if (eindex != NOT_FOUND)
4746 ue = s->entries[eindex];
4750 while (!usymtab_isBranch (otab))
4752 otab = usymtab_dropEnv (otab);
4753 llassert (otab != GLOBAL_ENV);
4756 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4766 s = usymtab_dropEnv (s);
4769 if (s->lexlevel == level && (index < s->nentries))
4771 ue = s->entries[index];
4773 if (uentry_isValid (ue))
4777 while (!usymtab_isBranch (otab))
4779 otab = usymtab_dropEnv (otab);
4781 if (otab == GLOBAL_ENV)
4787 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4798 if (index >= s->nentries)
4800 return uentry_undefined;
4803 llassert (!uentry_isUndefined (s->entries[index]));
4805 return s->entries[index];
4809 ** looking up entries
4811 ** If entry is inside a branch, then copy it, and put it into
4812 ** the branch table.
4816 int refTable_lookup (/*@notnull@*/ usymtab ut, int level, int index)
4818 refTable rt = ut->reftable;
4821 llassert (rt != NULL);
4823 for (i = 0; i < ut->nentries; i++)
4825 if (rt[i]->level == level && rt[i]->index == index)
4835 /*@only@*/ refentry refentry_create (int level, int index)
4837 refentry r = (refentry) dmalloc (sizeof (*r));
4845 static /*@dependent@*/ /*@exposed@*/ uentry
4846 usymtab_addRefEntry (/*@notnull@*/ usymtab s, cstring k)
4851 if (ut->reftable == NULL)
4853 DPRINTF (("Adding ref entry without reftable: %s", k));
4854 return uentry_undefined;
4857 llassert (ut->reftable != NULL);
4859 while (s != GLOBAL_ENV)
4861 eindex = usymtab_getIndex (s, k);
4863 if (eindex != NOT_FOUND)
4865 uentry current = s->entries[eindex];
4867 if (uentry_isVar (current) && !ctype_isFunction (uentry_getType (current)))
4871 DPRINTF (("Here: copying %s", uentry_unparse (current)));
4872 ue = uentry_copy (current);
4873 DPRINTF (("Here: copying %s", uentry_unparse (ue)));
4874 usymtab_addEntryQuiet (ut, ue);
4875 DPRINTF (("Okay..."));
4877 if (s->reftable != NULL)
4879 refentry ref = s->reftable[eindex];
4881 ut->reftable[ut->nentries - 1]
4882 = refentry_create (ref->level, ref->index);
4886 ut->reftable[ut->nentries - 1]
4887 = refentry_create (s->lexlevel, eindex);
4898 s = usymtab_dropEnv (s);
4901 return uentry_undefined;
4904 static uentry usymtab_lookupAux (usymtab s, cstring k)
4906 DPRINTF (("Lookup: %s", k));
4908 while (s != GLOBAL_ENV)
4910 int eindex = usymtab_getIndex (s, k);
4912 if (eindex != NOT_FOUND)
4914 uentry ret = s->entries[eindex];
4918 if (s->kind == US_TBRANCH
4919 || s->kind == US_FBRANCH
4920 || s->kind == US_CBRANCH)
4921 /* uentry_isGlobalVariable (ret) && os->lexlevel > fileScope) */
4924 DPRINTF (("Adding global ref entry: %s", k));
4925 ret = usymtab_addRefEntry (os, k);
4926 DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
4931 DPRINTF (("Found: %s", uentry_unparseFull (ret)));
4935 if (s->kind == US_TBRANCH || s->kind == US_FBRANCH
4936 || s->kind == US_CBRANCH)
4938 /* why isn't this os??? */
4939 uentry ret = usymtab_addRefEntry (s, k);
4940 DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
4947 return uentry_undefined;
4950 static /*@dependent@*/ /*@exposed@*/ uentry
4951 usymtab_lookupQuietAux (usymtab s, cstring k, bool noalt)
4955 while (s != GLOBAL_ENV)
4957 eindex = usymtab_getIndex (s, k);
4959 if (eindex != NOT_FOUND)
4961 uentry ret = s->entries[eindex];
4965 if (noalt && usymtab_isBranch (s))
4967 s = usymtab_dropEnv (s);
4971 llassert (s != NULL); /*@i523 should not need this? */
4976 return uentry_undefined;
4979 static /*@exposed@*/ /*@dependent@*/ uentry
4980 usymtab_lookupQuiet (usymtab s, cstring k)
4982 return usymtab_lookupQuietAux (s, k, FALSE);
4985 static /*@exposed@*/ /*@dependent@*/ uentry
4986 usymtab_lookupQuietNoAlt (usymtab s, cstring k)
4988 return usymtab_lookupQuietAux (s, k, TRUE);
4991 /*@dependent@*/ /*@observer@*/ uentry
4992 usymtab_lookupSafe (cstring k)
4995 DPRINTF (("Lookup safe: %s", k));
4996 return (usymtab_lookupAux (utab, k));
5000 usymtab_lookupExpose (cstring k)
5003 uentry ce = usymtab_lookupAux (utab, k);
5005 if (uentry_isUndefined (ce))
5007 llfatalbug (message ("usymtab_lookup: not found: *%s*", k));
5010 if (uentry_isPriv (ce))
5012 llfatalbug (message ("usymtab_lookup: private: *%s*", k));
5018 uentry usymtab_lookupExposeGlob (cstring k)
5020 return (usymtab_lookupGlobSafe (k));
5023 uentry usymtab_lookupGlob (cstring k)
5024 /*@globals globtab@*/
5026 uentry ce = usymtab_lookupAux (globtab, k);
5028 if (uentry_isUndefined (ce))
5029 llfatalbug (message ("usymtab_lookup: not found: %s", k));
5031 if (uentry_isPriv (ce))
5032 llfatalbug (message ("usymtab_lookup: private: %s", k));
5034 DPRINTF (("Lookup global: %s", uentry_unparseFull (ce)));
5038 /*@observer@*/ uentry
5039 usymtab_lookupGlobSafe (cstring k)
5040 /*@globals globtab@*/
5042 uentry ce = usymtab_lookupAux (globtab, k);
5043 DPRINTF (("Lookup global: %s", uentry_unparseFull (ce)));
5047 uentry usymtab_lookupEither (cstring k)
5050 uentry ce = usymtab_lookupSafe (k);
5052 if (uentry_isUndefined (ce))
5053 llfatalerror (message ("usymtab_lookup: not found: %s", k));
5055 DPRINTF (("Lookup either: %s", uentry_unparseFull (ce)));
5061 usymtab_lookupType (cstring k)
5062 /*@globals globtab@*/
5064 usymId uid = usymtab_getTypeId (k);
5066 if (uid == USYMIDINVALID)
5068 llcontbug (message ("usymtab_lookupType: not found: %s", k));
5069 return ctype_unknown;
5072 return (uentry_getRealType (usymtab_getTypeEntry (uid)));
5077 usymtab_lookupAbstractType (cstring k) /*@globals globtab@*/
5079 usymId uid = usymtab_getTypeId (k);
5081 if (uid == USYMIDINVALID)
5083 llcontbug (message ("usymtab_lookupType: not found: %s", k));
5084 return ctype_unknown;
5087 return (uentry_getAbstractType (usymtab_getTypeEntry (uid)));
5091 ** if there is an unnamed lcl-specified struct tag matching
5092 ** the uentryList, return its datatype. Otherwise, returns
5097 usymtab_structFieldsType (uentryList f)
5098 /*@globals globtab@*/
5100 return (usymtab_suFieldsType (f, TRUE));
5104 usymtab_unionFieldsType (uentryList f)
5105 /*@globals globtab@*/
5107 return (usymtab_suFieldsType (f, FALSE));
5111 usymtab_suFieldsType (uentryList f, bool isStruct)
5112 /*@globals globtab@*/
5116 DPRINTF (("Fields: %s", uentryList_unparse (f)));
5118 if (fileloc_isSpec (g_currentloc))
5120 return (ctype_undefined);
5123 for (i = 0; i < globtab->nentries; i++)
5125 uentry current = globtab->entries[i];
5128 ? uentry_isStructTag (current) : uentry_isUnionTag (current)))
5130 if (isFakeTag (uentry_rawName (current)))
5132 ctype ct = uentry_getType (current);
5134 DPRINTF (("Check: %s", ctype_unparse (ct)));
5136 if ((isStruct ? ctype_isStruct (ct) : ctype_isUnion (ct))
5138 (uentry_isSpecified (current)
5139 && uentryList_equivFields (f, ctype_getFields (ct))))
5141 return uentry_getAbstractType (current);
5151 return ctype_undefined;
5155 usymtab_enumEnumNameListType (enumNameList f)
5156 /*@globals globtab@*/
5160 for (i = 0; i < globtab->nentries; i++)
5162 uentry current = globtab->entries[i];
5164 if (uentry_isEnumTag (current))
5166 if (isFakeTag (uentry_rawName (current)))
5168 ctype ct = uentry_getType (current);
5170 if (ctype_isEnum (ct) && (enumNameList_match (f, ctype_elist (ct))))
5172 return uentry_getType (current);
5178 return ctype_undefined;
5182 usymtab_exists (cstring k)
5185 uentry ce = usymtab_lookupSafe (k);
5186 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5190 usymtab_existsReal (cstring k)
5193 uentry ce = usymtab_lookupSafe (k);
5195 return (!(uentry_isUndefined (ce))
5196 && !(uentry_isPriv (ce))
5197 && !(uentry_isExpandedMacro (ce)));
5201 usymtab_existsGlob (cstring k)
5202 /*@globals globtab@*/
5204 uentry ce = usymtab_lookupAux (globtab, k);
5206 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5211 usymtab_existsEither (cstring k)
5214 uentry ce = usymtab_lookupAux (utab, k);
5216 return (uentry_isValid (ce));
5220 usymtab_existsGlobEither (cstring k)
5221 /*@globals globtab@*/
5223 uentry ce = usymtab_lookupAux (globtab, k);
5225 return (uentry_isValid (ce));
5230 usymtab_existsType (cstring k)
5231 /*@globals globtab@*/
5233 uentry ce = usymtab_lookupAux (globtab, k);
5235 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && uentry_isDatatype (ce));
5239 usymtab_existsTypeEither (cstring k)
5240 /*@globals globtab@*/
5243 ce = usymtab_lookupAux (globtab, k);
5244 return (uentry_isValid (ce) && uentry_isDatatype (ce));
5248 usymtab_existsStructTag (cstring k) /*@globals globtab@*/
5250 cstring sname = makeStruct (k);
5251 uentry ce = usymtab_lookupAux (globtab, sname);
5252 cstring_free (sname);
5253 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5257 usymtab_existsUnionTag (cstring k) /*@globals globtab@*/
5259 cstring uname = makeUnion (k);
5260 uentry ce = usymtab_lookupAux (globtab, uname);
5262 cstring_free (uname);
5264 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5268 usymtab_existsEnumTag (cstring k) /*@globals globtab@*/
5270 cstring ename = makeEnum (k);
5271 uentry ce = usymtab_lookupAux (globtab, ename);
5273 cstring_free (ename);
5274 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5278 bool usymtab_existsVar (cstring k)
5281 uentry ce = usymtab_lookupSafe (k);
5283 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && (uentry_isVar (ce)));
5292 refTable_free (/*@only@*/ /*@null@*/ refTable x, int nentries)
5298 for (i = 0; i < nentries; i++)
5308 usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab u)
5309 /*@globals globtab, utab, filetab@*/
5313 aliasTable_free (u->aliases);
5315 refTable_free (u->reftable, u->nentries);
5317 if (u == filetab || u == globtab)
5319 for (i = 0; i < u->nentries; i++)
5321 uentry_freeComplete (u->entries[i]);
5326 for (i = 0; i < u->nentries; i++)
5328 uentry_free (u->entries[i]);
5332 guardSet_free (u->guards);
5339 llassert (!cstringTable_isDefined (u->htable));
5347 usymtab_freeAux (/*@only@*/ usymtab u)
5348 /*@globals globtab, utab, filetab@*/
5351 while (u != GLOBAL_ENV)
5354 usymtab_freeLevel (u);
5361 void usymtab_free ()
5362 /*@globals killed utab, globtab, filetab@*/
5366 usymtab_freeAux (utab);
5369 static int usymtab_lexicalLevel (void) /*@globals utab@*/
5371 return (utab->lexlevel);
5374 bool usymtab_inGlobalScope () /*@globals utab, globtab@*/
5376 return (utab == globtab);
5379 bool usymtab_inFileScope () /*@globals utab@*/
5381 return (utab->lexlevel == fileScope);
5384 bool usymtab_inFunctionScope () /*@globals utab@*/
5386 return (utab->lexlevel == functionScope);
5391 usymtab_replaceEntry (uentry s)
5392 /*@globals utab, globtab@*/
5393 /*@modifies utab, s@*/
5395 usymtab_replaceEntryAux (utab, s);
5400 usymtab_matchForwardStruct (usymId u1, usymId u2)
5401 /*@globals globtab@*/
5403 uentry ue1 = usymtab_getTypeEntry (u1);
5404 uentry ue2 = usymtab_getTypeEntry (u2);
5406 if (uentry_isAnyTag (ue2))
5408 ctype reptype = uentry_getType (ue1);
5410 if (ctype_isPointer (reptype))
5412 ctype repbase = ctype_getBaseType (reptype);
5414 if (ctype_isUA (repbase))
5416 typeId rtuid = ctype_typeId (repbase);
5418 if (u2 == rtuid) return TRUE;
5420 if (usymId_isValid (rtuid))
5422 reptype = uentry_getType (usymtab_getTypeEntry (rtuid));
5424 return (ctype_isUA (reptype) && (u2 == (ctype_typeId (reptype))));
5433 void usymtab_addGuards (guardSet guards)
5436 utab->guards = guardSet_union (utab->guards, guards);
5439 static bool usymtab_isGuardedAux (sRef s)
5443 sRef base = sRef_getRootBase (s);
5444 int lowlevel = paramsScope;
5445 int baselevel = sRef_lexLevel (base);
5447 if (sRef_isCvar (base))
5449 lowlevel = baselevel;
5450 if (lowlevel < paramsScope) lowlevel = paramsScope;
5453 while (tab->lexlevel >= lowlevel)
5455 DPRINTF (("Is guarded? [%s] %s",
5456 guardSet_unparse (tab->guards),
5457 sRef_unparseFull (s)));
5459 if (guardSet_isGuarded (tab->guards, s))
5462 if (!sRef_definitelyNull (s))
5464 sRef_setNotNull (s, fileloc_undefined);
5470 tab = usymtab_dropEnv (tab);
5476 void usymtab_unguard (sRef s) /*@modifies utab@*/
5479 sRef base = sRef_getRootBase (s);
5480 int lowlevel = paramsScope;
5481 int baselevel = sRef_lexLevel (base);
5483 if (sRef_isCvar (base))
5485 lowlevel = baselevel;
5486 if (lowlevel < paramsScope) lowlevel = paramsScope;
5489 while (tab->lexlevel >= lowlevel)
5491 if (guardSet_isGuarded (tab->guards, s))
5493 guardSet_delete (tab->guards, s);
5496 tab = usymtab_dropEnv (tab);
5500 bool usymtab_isGuarded (sRef s)
5502 DPRINTF (("Is guarded? %s", sRef_unparseFull (s)));
5503 return (sRef_aliasCompleteSimplePred (usymtab_isGuardedAux, s));
5506 bool usymtab_isDefinitelyNull (sRef s)
5508 return (sRef_aliasCheckSimplePred (usymtab_isDefinitelyNullAux, s));
5511 bool usymtab_isDefinitelyNullDeep (sRef s)
5513 return (sRef_deepPred (usymtab_isDefinitelyNull, s));
5516 static bool usymtab_isDefinitelyNullAux (sRef s)
5520 sRef base = sRef_getRootBase (s);
5521 int lowlevel = paramsScope;
5523 if (sRef_isCvar (base))
5525 lowlevel = sRef_lexLevel (base);
5526 if (lowlevel < paramsScope) lowlevel = paramsScope;
5529 while (tab->lexlevel >= lowlevel)
5531 if (guardSet_mustBeNull (tab->guards, s))
5536 while (tab->kind == US_CBRANCH)
5541 llassert (usymtab_isDefined (tab));
5543 if (tab->kind == US_FBRANCH)
5546 llassert (tab->kind == US_TBRANCH);
5556 usymtab_printGuards ()
5557 /*@globals utab, globtab@*/
5559 usymtab ttab = utab;
5561 while (ttab != globtab)
5563 llmsg (message ("Guards [%d]: %q", ttab->lexlevel,
5564 guardSet_unparse (ttab->guards)));
5570 usymtab_displayAllUses ()
5571 /*@globals utab, globtab@*/
5575 /* only in top scope */
5576 llassert (utab == globtab);
5578 /* need a copy, so order is not messed up by sort! */
5579 copy = usymtab_shallowCopy (globtab);
5581 qsort (copy->entries, (size_t)copy->nentries,
5582 sizeof (*copy->entries), (int (*)(const void *, const void *)) uentry_xcompareuses);
5584 usymtab_entries (copy, ue)
5586 if (uentry_isValid (ue) && !uentry_isGlobalMarker (ue))
5588 filelocList uses = uentry_getUses (ue);
5589 int size = filelocList_realSize (uses);
5591 if (fileloc_isDefined (uentry_whereDefined (ue))
5592 && !fileloc_isLib (uentry_whereDefined (ue))
5595 llmsg (message ("%q (%q), %d use%&:\n %q",
5596 uentry_getName (ue),
5597 fileloc_unparse (uentry_whereDefined (ue)),
5598 size, filelocList_unparseUses (uses)));
5601 } end_usymtab_entries;
5603 usymtab_shallowFree (copy);
5606 static /*@dependent@*/ /*@exposed@*/ usymtab
5607 usymtab_getFileTab ()
5608 /*@globals filetab@*/
5610 llassert (filetab != NULL);
5616 usymtab_unparseStack ()
5619 return (usymtab_unparseStackTab (utab));
5622 static /*@only@*/ cstring
5623 usymtab_unparseStackTab (usymtab t)
5625 bool firstOne = TRUE;
5626 cstring ret = cstring_makeLiteral ("[");
5628 while (t != GLOBAL_ENV)
5632 ret = message ("%q %q", ret, usymtab_typeName (t));
5637 ret = message ("%q, %q", ret, usymtab_typeName (t));
5642 ret = message ("%q ]", ret);
5646 static /*@only@*/ cstring
5647 usymtab_typeName (/*@notnull@*/ usymtab t)
5651 case US_GLOBAL: return cstring_makeLiteral ("global");
5652 case US_NORMAL: return cstring_makeLiteral ("normal");
5653 case US_TBRANCH: return cstring_makeLiteral ("true");
5654 case US_FBRANCH: return cstring_makeLiteral ("false");
5655 case US_CBRANCH: return cstring_makeLiteral ("case");
5656 case US_SWITCH: return cstring_makeLiteral ("switch");
5662 void usymtab_addMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5665 if (!sRef_similar (s, al))
5667 usymtab_addForceMustAlias (s, al);
5672 ** Same as usymtab_addMustAlias, except does not check sRef_isSimilar.
5675 void usymtab_addForceMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5678 /* evans 2002-03-3: was sRef_isMeaningful -- but we need to keep aliases for new storage also! */
5679 if (sRef_isMeaningful (s)
5680 && sRef_isMeaningful (al)
5681 && !(sRef_isConst (s) || sRef_isConst (al))
5682 && !(sRef_isAddress (al) && sRef_isDirectParam (sRef_getBase (al))))
5684 utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
5685 DPRINTF (("Must alias: %s", aliasTable_unparse (utab->aliases)));
5688 ** for local variable, aliasing is symmetric
5691 if (sRef_isLocalVar (s) && sRef_isLocalVar (al))
5693 utab->aliases = aliasTable_addMustAlias (utab->aliases, al, s);
5698 DPRINTF (("Not aliasing! %s / %s", sRef_unparseFull (s), sRef_unparseFull (al)));
5699 DPRINTF (("meaningful: %d %d", sRef_isMeaningful (s), sRef_isMeaningful (al)));
5703 void usymtab_addReallyForceMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5706 utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
5709 void usymtab_clearAlias (sRef s)
5710 /*@modifies utab, s@*/
5713 aliasTable_clearAliases (utab->aliases, s);
5716 sRefSet usymtab_allAliases (sRef s)
5719 if (sRef_isSomewhatMeaningful (s))
5723 ret = sRefSet_unionFree (aliasTable_aliasedBy (utab->aliases, s),
5724 aliasTable_canAlias (utab->aliases, s));
5729 DPRINTF (("NOT A MEANINGFUL SREF!"));
5730 return sRefSet_undefined;
5734 /*@only@*/ sRefSet usymtab_canAlias (sRef s)
5737 if (sRef_isSomewhatMeaningful (s))
5739 sRefSet res = aliasTable_canAlias (utab->aliases, s);
5743 return sRefSet_undefined;
5746 /*@only@*/ sRefSet usymtab_aliasedBy (sRef s)
5749 return (aliasTable_aliasedBy (utab->aliases, s));
5752 /*@only@*/ cstring usymtab_unparseAliases ()
5755 return (aliasTable_unparse (utab->aliases));
5759 ** Debugging routines:
5760 ** okay to leak storage here, only for debugging
5766 usymtab_printOut (void)
5772 char *ind = mstring_copy (" ");
5774 fprintf (g_warningstream, "<<< [symbol table] >>>\n");
5776 while (s != GLOBAL_ENV && s->env != GLOBAL_ENV)
5778 cstring tname = usymtab_typeName (s);
5782 ind[depth * 3 + 1] = '\0';
5785 fprintf (g_warningstream, "level: %d (%s)\n", s->lexlevel,
5786 cstring_toCharsSafe (tname));
5788 cstring_free (tname);
5790 for (i = 0; i < s->nentries; i++)
5792 cstring us = uentry_unparseFull (s->entries[i]);
5793 fprintf (g_warningstream, "%s\n", cstring_toCharsSafe (us));
5797 if (s->reftable != NULL && s->nentries > 0)
5799 fprintf (g_warningstream, "\t<< Ref table >>\n");
5801 for (i = 0; i < s->nentries; i++)
5803 fprintf (g_warningstream, "\t%s %3d: %d, %d\n", ind, i,
5804 s->reftable[i]->level,
5805 s->reftable[i]->index);
5809 ind[depth * 3 + 1] = ' ';
5813 fprintf (g_warningstream, "<<< end usymtab >>>\n");
5819 usymtab_printTypes ()
5820 /*@globals globtab@*/
5822 usymtab_printAllAux (globtab);
5826 usymtab_printAll (void)
5829 usymtab_printAllAux (utab);
5833 usymtab_printAllAux (usymtab s)
5834 /*@modifies g_warningstream@*/
5838 char *ind = mstring_copy (" ");
5840 printf ("[[[ usymtab ]]]");
5842 while (s != GLOBAL_ENV)
5845 ind[depth * 3 + 1] = '\0';
5847 if (s->env == GLOBAL_ENV)
5851 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5852 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5853 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5857 for (i = looplow; i < s->nentries; i++)
5859 printf ("%s%3d. %s\n", ind, i,
5860 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5865 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5866 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5867 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5869 for (i = 0; i < s->nentries; i++)
5871 printf ("%s%3d %s\n", ind, i,
5872 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5876 ind[depth * 3 + 1] = ' ';
5880 printf ("----------\n");
5884 usymtab_printComplete ()
5889 char *ind = mstring_copy (" ");
5892 while (s != GLOBAL_ENV)
5896 ind[depth * 3 + 1] = '\0';
5899 if (s->env == GLOBAL_ENV)
5903 printf ("level: %d\n", s->lexlevel);
5907 for (i = looplow; i < s->nentries; i++)
5909 printf ("%s%3d %s\n", ind, i,
5910 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5915 printf ("level: %d\n", s->lexlevel);
5916 for (i = 0; i < s->nentries; i++)
5918 printf ("%s%3d %s\n", ind, i,
5919 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5923 ind[depth * 3 + 1] = ' ';
5928 printf ("----------\n");
5933 static /*@only@*/ cstring /*@unused@*/
5934 usymtab_unparseLocalAux (/*@notnull@*/ usymtab s)
5936 cstring c = message ("lexlevel: %d\n", s->lexlevel);
5939 for (i = 0; i < s->nentries; i++)
5941 c = message ("%q\n%q", c, uentry_unparseFull (s->entries[i]));
5944 c = message ("%q\n=========", c);
5948 static cstring /*@unused@*/ /*@only@*/
5949 usymtab_unparseLocalList (/*@notnull@*/ usymtab s)
5951 cstring c = message ("[%d/%s/%s] ", s->lexlevel,
5952 bool_unparse (s->mustBreak),
5953 exitkind_unparse (s->exitCode));
5956 for (i = 0; i < s->nentries; i++)
5958 sRef sr = uentry_getSref (s->entries[i]);
5962 c = message ("%q: %q [%b]", c, uentry_getName (s->entries[i]),
5963 sRef_isStateDefined (sr));
5967 c = message ("%q, %q [%b]", c, uentry_getName (s->entries[i]),
5968 sRef_isStateDefined (sr));
5978 usymtab_printLocal (void)
5984 printf ("lexlevel: %d\n", s->lexlevel);
5986 for (i = 0; i < s->nentries; i++)
5988 printf ("%s\n", cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5991 while (s->lexlevel > 1)
5996 llassert (usymtab_isDefined (s));
5998 printf ("Params:\n");
6000 for (i = 0; i < s->nentries; i++)
6002 printf ("%d: %s\n", i,
6003 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
6008 static bool checkDistinctExternalName (uentry e)
6009 /*@globals globtab@*/
6010 /*@modifies *g_warningstream@*/
6012 size_t checklen = size_fromInt (context_getValue (FLG_EXTERNALNAMELEN));
6013 bool ignorecase = context_getFlag (FLG_EXTERNALNAMECASEINSENSITIVE);
6014 bool gotone = FALSE;
6015 bool extras = FALSE;
6016 bool hasError = FALSE;
6017 cstring name = uentry_rawName (e);
6018 usymtab st = globtab;
6026 if (uentry_isAnyTag (e))
6028 checklen++; /* the tag marker doesn't count */
6032 usymtab_entries (st, oe)
6034 if (uentry_sameObject (oe, e))
6041 if (cstring_equalCaseInsensitive (uentry_rawName (oe), name))
6050 (FLG_DISTINCTEXTERNALNAMES,
6052 ("External identifier %q is not distinguishable from %q "
6053 "because alphabetical case is ignored",
6055 uentry_getName (oe)),
6056 uentry_whereLast (e)))
6058 uentry_showWhereAny (oe);
6059 uentry_setHasNameError (oe);
6068 if (cstring_equalLenCaseInsensitive (uentry_rawName (oe),
6077 if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6080 (FLG_DISTINCTEXTERNALNAMES,
6083 ("External identifier %q is not distinguishable from %q "
6084 "in the first %d characters (%q)",
6086 uentry_getName (oe),
6087 size_toInt (checklen),
6088 cstring_clip (uentry_getName (e), checklen)),
6090 uentry_whereLast (e)))
6092 uentry_showWhereAny (oe);
6093 uentry_setHasNameError (oe);
6106 (FLG_DISTINCTEXTERNALNAMES,
6108 ("External identifier %q is not distinguishable from %q "
6109 "in the first %d characters because alphabetical case "
6112 uentry_getName (oe),
6113 size_toInt (checklen)),
6114 uentry_whereLast (e)))
6116 uentry_showWhereAny (oe);
6117 uentry_setHasNameError (oe);
6123 else if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6132 (FLG_DISTINCTEXTERNALNAMES,
6135 ("External identifier %q is not distinguishable from %q "
6136 "in the first %d characters (%q)",
6138 uentry_getName (oe),
6139 size_toInt (checklen),
6140 cstring_clip (uentry_getName (e), checklen)),
6142 uentry_whereLast (e)))
6144 uentry_showWhereAny (oe);
6145 uentry_setHasNameError (oe);
6154 } end_usymtab_entries ;
6161 (cstring_makeLiteral ("One or more additional "
6162 "indistinguishable external "
6163 "names not reported"));
6169 static bool checkDistinctInternalName (uentry e)
6171 /*@modifies *g_warningstream@*/
6173 usymtab ttab = utab;
6174 cstring name = uentry_rawName (e);
6175 size_t numchars = size_fromInt (context_getValue (FLG_INTERNALNAMELEN));
6176 bool caseinsensitive = context_getFlag (FLG_INTERNALNAMECASEINSENSITIVE);
6177 bool lookalike = context_getFlag (FLG_INTERNALNAMELOOKALIKE);
6179 if (uentry_isAnyTag (e) && (numchars != 0))
6181 numchars++; /* the tag marker doesn't count */
6184 while (usymtab_isDefined (ttab))
6186 usymtab_entries (ttab, oe)
6188 if (uentry_sameObject (oe, e))
6190 /*@innercontinue@*/ continue;
6193 switch (cstring_genericEqual
6194 (name, uentry_rawName (oe),
6195 numchars, caseinsensitive, lookalike))
6197 case CGE_DISTINCT: /* okay */
6201 if (cstring_equal (name, uentry_rawName (oe)))
6203 ; /* got a shadow error */
6208 (FLG_DISTINCTINTERNALNAMES,
6211 ("Internal identifier %q is not distinguishable from %q "
6212 "in the first %d characters (%q)",
6214 uentry_getName (oe),
6215 size_toInt (numchars),
6216 cstring_clip (uentry_getName (e), numchars)),
6218 uentry_whereLast (e)))
6220 uentry_showWhereAny (oe);
6221 uentry_setHasNameError (oe);
6228 if (numchars == 0 || (cstring_length (name) <= numchars))
6231 (FLG_DISTINCTINTERNALNAMES,
6233 ("Internal identifier %q is not distinguishable from %q "
6234 "without case sensitivity",
6236 uentry_getName (oe)),
6237 uentry_whereLast (e)))
6239 uentry_showWhereAny (oe);
6240 uentry_setHasNameError (oe);
6247 (FLG_DISTINCTINTERNALNAMES,
6249 ("Internal identifier %q is not distinguishable from %q "
6250 "in the first %d characters without case sensitivity",
6252 uentry_getName (oe),
6253 size_toInt (numchars)),
6254 uentry_whereLast (e)))
6256 uentry_showWhereAny (oe);
6257 uentry_setHasNameError (oe);
6265 || (cstring_length (name) <= numchars))
6268 (FLG_DISTINCTINTERNALNAMES,
6270 ("Internal identifier %q is not distinguishable from %q "
6271 "except by lookalike characters",
6273 uentry_getName (oe)),
6274 uentry_whereLast (e)))
6276 uentry_showWhereAny (oe);
6277 uentry_setHasNameError (oe);
6284 (FLG_DISTINCTINTERNALNAMES,
6286 ("Internal identifier %q is not distinguishable from %q "
6287 "in the first %d characters except by lookalike characters",
6289 uentry_getName (oe),
6290 size_toInt (numchars)),
6291 uentry_whereLast (e)))
6293 uentry_showWhereAny (oe);
6294 uentry_setHasNameError (oe);
6299 } end_usymtab_entries ;
6307 void usymtab_checkDistinctName (uentry e, int scope)
6308 /*@globals utab, globtab@*/
6310 bool hasError = FALSE;
6311 fileloc where = uentry_whereLast (e);
6313 if (!fileloc_isPreproc (where) && !fileloc_isBuiltin (where))
6315 if (scope == globScope)
6317 if (context_getFlag (FLG_DISTINCTEXTERNALNAMES))
6319 hasError = checkDistinctExternalName (e);
6323 if (!hasError && context_getFlag (FLG_DISTINCTINTERNALNAMES))
6325 hasError = checkDistinctInternalName (e);
6331 uentry_setHasNameError (e);
6335 /*@exposed@*/ sRef usymtab_lookupGlobalMarker (void) /*@globals utab@*/
6339 ue = usymtab_lookupAux (utab, GLOBAL_MARKER_NAME);
6340 llassert (uentry_isValid (ue));
6342 return uentry_getSref (ue);
6348 ** For debugging only
6352 usymtab_checkAllValid () /*@globals utab@*/
6356 while (tab != GLOBAL_ENV)
6360 for (i = 0; i < utab->nentries; i++)
6362 uentry e = utab->entries[i];
6364 uentry_checkValid (e);
6367 aliasTable_checkValid (tab->aliases);