2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2001 University of Virginia,
4 ** Massachusetts Institute of Technology
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ** General Public License for more details.
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
20 ** For information on lclint: lclint-request@cs.virginia.edu
21 ** To report a bug: lclint-bug@cs.virginia.edu
22 ** For more information: http://lclint.cs.virginia.edu
27 ** Lexically scoped symbol table.
29 ** Unlike a normal symbol table, this table splits to reflect branches.
31 ** This is necessary since symbol table entries also reflect
32 ** some state information, like initialization, that may be
33 ** different on different branches.
35 ** For each control structure we split:
37 ** { } - a normal scope (no control) US_NORMAL
39 ** if <pred> { } - US_TBRANCH true branch
40 ** while <pred> { } US_FBRANCH else branch
42 ** switch <pred> { } - US_SWITCH
44 ** case x: - case scope US_CBRANCH
45 ** Should be kept in a separate table, because of
49 # include "lclintMacros.nf"
51 # include "structNames.h"
52 # include "exprChecks.h"
53 # include "transferChecks.h"
56 ** Keep track of type definitions inside a function.
59 static uentryList functypes = uentryList_undefined;
61 static bool dbgfree = FALSE;
62 static bool dbgload = TRUE;
67 ** Hack to prevent shadow errors from appearing when function parameters
68 ** are entered into a new scope.
71 static bool noshadowerror = FALSE;
74 ** Constraint: static variables can live in 1 or > 2.
76 ** except for tags. All tags must be at the global level.
77 ** Static tags are handled in a kludgey way.
81 ** utab is the universal symbol table
82 ** globtab is the global environment of utab
83 ** oldtab is needed for conversions in dumping (after sorting the table)
85 ** there can be only one usymtab!
88 static /*@checkedstrict@*/ /*@owned@*/ /*@notnull@*/ usymtab utab;
90 /* Reachable environments from from utab */
91 static /*@checkedstrict@*/ /*@notnull@*/ /*@dependent@*/ usymtab globtab;
92 static /*@checkedstrict@*/ /*@dependent@*/ usymtab filetab;
94 /* Used for sorting for dumpage. */
95 static /*@checkedstrict@*/ /*@owned@*/ usymtab oldtab;
97 static int usymtab_lexicalLevel (void) /*@globals utab@*/ ;
98 static bool usymtab_isAltDefinitelyNull (sRef p_s) /*@globals utab@*/ ;
99 static void refTable_free (/*@only@*/ /*@null@*/ refTable p_x, int p_nentries);
100 static ctype usymtab_suFieldsType (uentryList p_f, bool p_isStruct) /*@globals globtab@*/ ;
102 extern int usymtab_getCurrentDepth (void) /*@globals utab@*/
104 return utab->lexlevel;
108 usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab p_u)
109 /*@globals globtab, utab, filetab@*/ /*@modifies p_u@*/ ;
111 static bool usymtab_isDefinitelyNullAux (sRef p_s) /*@globals utab@*/ ;
112 static /*@only@*/ cstring usymtab_unparseStackTab (usymtab p_t);
113 static /*@exposed@*/ /*@dependent@*/ uentry
114 usymtab_getRefTab (/*@notnull@*/ usymtab p_u, int p_level, usymId p_index);
115 static /*@unused@*/ /*@only@*/ cstring
116 usymtab_unparseLocalAux (/*@notnull@*/ usymtab p_s);
117 static /*@unused@*/ /*@only@*/ cstring
118 usymtab_unparseLocalList (/*@notnull@*/ usymtab p_s);
119 static /*@only@*/ cstring usymtab_typeName (/*@notnull@*/ usymtab p_t);
120 static void usymtab_handleParams (void)
121 /*@globals utab, globtab, filetab@*/
122 /*@modifies utab@*/ ;
124 static /*@exposed@*/ /*@dependent@*/ uentry
125 usymtab_addRefEntry (/*@notnull@*/ usymtab p_s, cstring p_k);
126 static /*@exposed@*/ /*@dependent@*/ usymtab
127 usymtab_dropEnv (/*@notnull@*/ usymtab p_s);
128 static /*@exposed@*/ /*@dependent@*/ uentry
129 usymtab_getRefNoisy (/*@notnull@*/ usymtab p_s, int p_level, usymId p_index);
131 static /*@exposed@*/ /*@dependent@*/ uentry
132 usymtab_lookupQuietAux (usymtab p_s, cstring p_k, bool p_noalt);
134 static /*@exposed@*/ /*@dependent@*/ uentry
135 usymtab_lookupQuiet (usymtab p_s, cstring p_k);
137 static /*@exposed@*/ /*@dependent@*/ uentry
138 usymtab_lookupQuietNoAlt (usymtab p_s, cstring p_k);
140 static void usymtab_printAllAux (usymtab p_s) /*@modifies g_msgstream@*/ ;
141 static int usymtab_getIndex (/*@notnull@*/ usymtab p_s, cstring p_k);
142 static /*@exposed@*/ uentry usymtab_fetchIndex (/*@notnull@*/ usymtab p_s, int p_i);
143 static /*@exposed@*/ uentry
144 usymtab_lookupAux (usymtab p_s, cstring p_k);
145 static /*@exposed@*/ /*@dependent@*/ /*@notnull@*/ usymtab
146 usymtab_getFileTab (void) /*@globals filetab@*/ ;
147 static int refTable_lookup (/*@notnull@*/ usymtab p_ut, int p_level, int p_index);
148 static bool usymtab_mustBreak (usymtab p_s);
149 static bool usymtab_mustEscape (usymtab p_s);
151 static void recordFunctionType (uentry ue)
153 llassert (uentry_isDatatype (ue) || uentry_isAnyTag (ue)
154 || uentry_isEnumConstant (ue));
155 DPRINTF (("Function type: %s", uentry_unparseFull (ue)));
157 functypes = uentryList_add (functypes, ue);
161 static void clearFunctionTypes (void)
162 /*@modifies globtab@*/
164 uentryList_elements (functypes, el)
166 if (cstring_isDefined (uentry_rawName (el)))
168 if (cstringTable_isDefined (globtab->htable))
170 cstringTable_remove (globtab->htable, uentry_rawName (el));
173 uentry_setName (el, cstring_undefined);
177 llassert (uentry_isValid (el));
178 el->sref = sRef_undefined;
179 /*@noaccess uentry@*/
180 } end_uentryList_elements ;
182 uentryList_clear (functypes);
185 static /*@falsenull@*/ bool usymtab_isBranch (usymtab u)
187 return (usymtab_isDefined (u) &&
188 (u->kind == US_TBRANCH || u->kind == US_FBRANCH
189 || u->kind == US_CBRANCH || u->kind == US_SWITCH));
192 static bool usymtab_mustBreak (usymtab s)
194 llassert (s != GLOBAL_ENV);
195 return (s->mustBreak);
198 static bool usymtab_mustEscape (usymtab s)
200 llassert (s != GLOBAL_ENV);
201 return (exitkind_mustEscape (s->exitCode));
204 void usymtab_setMustBreak ()
207 llassert (utab != GLOBAL_ENV);
208 utab->mustBreak = TRUE;
211 void usymtab_setExitCode (exitkind ex)
214 llassert (utab != GLOBAL_ENV);
218 if (exitkind_mustEscape (ex))
220 utab->mustBreak = TRUE;
224 bool usymtab_isAltDefinitelyNullDeep (sRef s)
226 return (sRef_deepPred (usymtab_isAltDefinitelyNull, s));
229 static bool usymtab_isAltDefinitelyNull (sRef s)
237 llassert (utab->env != NULL);
239 /*@-mods@*/ /* These modifications are cancelled. */
240 utab->guards = utab->env->guards;
241 utab->env->guards = t;
244 llassert (usymtab_isDefined (utab));
245 res = usymtab_isDefinitelyNull (s);
248 ** This reports a spurious error. It is okay, because of
249 ** the nesting relationship of usymtab environments.
252 /*@-mods@*/ /* Cancelling modifications. */
253 /*@i1@*/ utab->env->guards = utab->guards;
254 /*@i1@*/ utab->guards = t;
260 static /*@notnull@*/ /*@special@*/ usymtab
261 usymtab_create (uskind kind, /*@keep@*/ usymtab env, bool nextlevel)
263 /*@post:isnull result->htable, result->guards, result->aliases@*/
265 usymtab t = (usymtab) dmalloc (sizeof (*t));
268 t->nspace = CBASESIZE;
269 t->entries = (uentry *) dmalloc (sizeof (*t->entries) * CBASESIZE);
271 /* We only use a reftable for branch-level symbol tables.
274 t->reftable = (nextlevel
276 : (refentry *) dmalloc (sizeof (*t->reftable) * CBASESIZE));
279 t->lexlevel = (env == GLOBAL_ENV ? 0 : env->lexlevel) + (nextlevel ? 1 : 0);
284 t->guards = guardSet_undefined;
285 t->aliases = aliasTable_undefined;
287 t->mustBreak = FALSE;
288 t->exitCode = XK_NEVERESCAPE;
297 static /*@only@*/ /*@notnull@*/ usymtab
298 usymtab_createRoot (void) /*@modifies nothing@*/
300 usymtab u = (usymtab) dmalloc (sizeof (*u));
303 u->nspace = CGLOBBASESIZE;
304 u->entries = (uentry *) dmalloc (sizeof (*u->entries) * CGLOBBASESIZE);
307 u->htable = cstringTable_create (CGLOBHASHSIZE);
310 u->guards = guardSet_new ();
311 u->aliases = aliasTable_new ();
313 u->mustBreak = FALSE;
314 u->exitCode = XK_NEVERESCAPE;
321 usymtab_initMod (void)
322 /*@globals undef utab, undef oldtab, undef globtab, undef filetab @*/
323 /*@modifies utab, globtab, filetab, oldtab @*/
325 utab = usymtab_createRoot ();
327 filetab = usymtab_undefined;
328 oldtab = usymtab_undefined;
333 usymtab_initGlobalMarker () /*@globals globtab@*/
335 if (uentry_isValid (usymtab_lookupAux (globtab, GLOBAL_MARKER_NAME)))
337 ; /* Already entered from load table. */
341 usymtab_addGlobalEntry (uentry_makeGlobalMarker ());
346 ** utab should be empty? (requires?)
348 ** Adds bool types to symbol table (these are built in for now)
349 ** Only do this is there is no library!
355 if (context_getFlag (FLG_NOLIB))
357 ctype boolt = ctype_bool;
358 /* evs 2000-07-24: bool is now treated as abstract (always) */
360 uentry boolentry = uentry_makeBoolDatatype (YES);
361 usymtab_supGlobalEntry (boolentry);
362 context_addBoolAccess ();
365 ** We supply values 0 and 1 for the constants, so things like
366 ** while (TRUE) can be interpreted correctly.
369 usymtab_supGlobalEntry
370 (uentry_makeConstantAux (context_getFalseName (), boolt,
371 fileloc_getBuiltin (), FALSE,
372 multiVal_makeInt (0)));
373 usymtab_supGlobalEntry
374 (uentry_makeConstantAux (context_getTrueName (), boolt,
375 fileloc_getBuiltin (), FALSE,
376 multiVal_makeInt (1)));
385 usymtab_grow (/*@notnull@*/ usymtab s)
388 o_uentry *oldsyms = s->entries;
390 s->nspace = CBASESIZE;
391 s->entries = (uentry *) dmalloc (sizeof (*s->entries)
392 * (s->nentries + s->nspace));
394 for (i = 0; i < s->nentries; i++)
396 s->entries[i] = oldsyms[i];
401 if (s->reftable != NULL)
403 refTable oldRefs = s->reftable;
405 s->reftable = (refentry *) dmalloc (sizeof (*s->reftable)
406 * (s->nentries + CBASESIZE + 1));
408 for (i = 0; i < s->nentries; i++)
410 s->reftable[i] = oldRefs[i];
421 usymtab_addEntryQuiet (/*@notnull@*/ usymtab s, /*@keep@*/ uentry e)
423 if (!(s->lexlevel > fileScope || !sRef_modInFunction ()))
425 if (uentry_isDatatype (e)
426 || uentry_isFunction (e)
427 || uentry_isAnyTag (e)
428 || uentry_isEnumConstant (e)
429 || context_inMacro ())
432 ** Not a bug. Code like,
433 ** int f (void) { typedef int tint; ... }
437 /* was nothing here! */
438 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
443 (cstring_makeLiteral ("Declaration outside function scope"));
445 llcontbug (message ("usymtab_addEntryQuiet: inconsistent state "
446 "(lexlevel = %d, modFunction = %s) adding: %q",
447 s->lexlevel, bool_unparse (sRef_modInFunction ()),
448 uentry_unparse (e)));
449 sRef_setGlobalScope ();
450 /* make sure the sRef is not bashed! */
451 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
461 s->entries[s->nentries] = e;
464 if (s == globtab || s == filetab)
466 if (!fileloc_isLib (g_currentloc))
468 uentry_tallyAnnots (e, AN_UNKNOWN);
473 if (cstringTable_isDefined (s->htable))
475 cstringTable_insert (s->htable, cstring_copy (uentry_rawName (e)), s->nentries);
481 static /*@observer@*/ uentry /*@alt void@*/
482 usymtab_addEntryBase (/*@notnull@*/ usymtab s, /*@only@*/ uentry e)
485 ** In theory, we shouldn't need this test because it this is
486 ** only called when a library is being read, and it shouldn't
487 ** ever have a duplicate entry. In practice, its safer to
488 ** leave it in, though.
493 if (uentry_isValid (old = usymtab_lookupQuiet (s, uentry_rawName (e))))
495 DPRINTF (("Duplicate entry: %s", uentry_unparse (e)));
496 uentry_free (e); /* duplicate */
501 int thisentry = s->nentries;
503 if (uentry_isVar (e))
505 uentry_setSref (e, sRef_makeCvar (globScope, thisentry,
507 stateInfo_makeLoc (uentry_whereLast (e))));
510 usymtab_addEntryQuiet (s, e);
516 static /*@observer@*/ uentry /*@alt void@*/
517 usymtab_addEntryAlways (/*@notnull@*/ usymtab s, /*@only@*/ uentry e)
520 ** In theory, we shouldn't need this test because it this is
521 ** only called when a library is being read, and it shouldn't
522 ** ever have a duplicate entry. In practice, its safer to
523 ** leave it in, though.
527 int thisentry = s->nentries;
529 if (uentry_isValid (old = usymtab_lookupQuiet (s, uentry_rawName (e))))
532 (message ("Duplicate entry in load library: %s. "
533 "Old entry: %q. New entry: %q",
535 uentry_unparseFull (old),
536 uentry_unparseFull (e)));
538 uentry_setName (e, message ("__x_%s", uentry_rawName (e)));
539 /* This shouldn't happen...unless the library is bad! */
543 if (uentry_isVar (e) && !uentry_isGlobalMarker (e))
545 uentry_setSref (e, sRef_makeCvar (globScope, thisentry,
547 stateInfo_makeLoc (uentry_whereLast (e))));
550 usymtab_addEntryQuiet (s, e);
555 usymtab_addEntryAux (/*@notnull@*/ usymtab st, /*@keep@*/ uentry e, bool isSref)
556 /*@globals globtab@*/
559 usymId thisentry = st->nentries;
561 llassert (!uentry_isElipsisMarker (e));
565 ** llassert (usymtab_lookupSafe (uentry_rawName (e)) == uentry_undefined);
568 llassertprint (uentry_isAnyTag (e) ? st == globtab : TRUE,
569 ("non-global tag: %s / %d", uentry_unparseFull (e), st->lexlevel));
571 if (st->lexlevel == fileScope
572 && (!(uentry_isStatic (e)) || uentry_isAnyTag (e)))
579 ctype ct = uentry_getType (e);
581 if (uentry_isFunction (e) && ctype_isFunction (ct))
583 ct = ctype_getReturnType (ct);
586 if (uentry_isStatic (e))
588 sRef sr = sRef_makeCvar (st->lexlevel, thisentry, ct, stateInfo_makeLoc (uentry_whereLast (e)));
590 if (sRef_isStack (sr) || sRef_isLocalState (sr))
592 sRef_setAliasKind (sr, AK_STATIC, uentry_whereLast (e));
593 sRef_setDefined (sr, uentry_whereLast (e));
596 uentry_setSref (e, sr);
600 uentry_setSref (e, sRef_makeCvar (st->lexlevel, thisentry, ct, stateInfo_makeLoc (uentry_whereLast (e))));
604 if (uentry_isDatatype (e))
607 uentry_setDatatype (e, thisentry);
610 if (uentry_isFunction (e))
612 ctype ct = uentry_getType (e);
614 if (ctype_isFunction (ct)
615 && uentryList_isMissingParams (ctype_argsFunction (ct)))
617 if (uentry_isDeclared (e))
621 message ("Function %q declared without parameter list",
623 uentry_whereDeclared (e));
629 message ("Function %q specified without parameter list",
631 uentry_whereSpecified (e));
636 if (st == globtab && !uentry_isSpecified (e))
638 exprChecks_checkExport (e);
641 uentry_checkName (e);
643 usymtab_addEntryQuiet (st, e);
644 DPRINTF (("Adding entry: [%p] %s", e, uentry_unparseFull (e)));
649 usymtab_addEntry (uentry e)
650 /*@globals utab, globtab@*/
651 /*@modifies utab, e@*/
653 llassertprint (!usymtab_exists (uentry_rawName (e)),
654 ("Entry already exists: %s", uentry_unparse (e)));
656 return usymtab_addEntryAux (utab, e, FALSE);
660 usymtab_addGlobalEntry (uentry e)
661 /*@modifies globtab, e@*/
663 DPRINTF (("Add global: %s / %s", uentry_unparse (e), bool_unparse (uentry_isForward (e))));
665 (void) usymtab_addEntryAux (globtab, e, FALSE);
669 ** supercede and replace entry use elements of entries array, and
670 ** assign an element to a new value, and then free the old value.
671 ** Need -deparrays to avoid errors for this.
677 usymtab_supEntryAux (/*@notnull@*/ usymtab st,
678 /*@only@*/ uentry e, bool isSref)
679 /*@globals globtab, filetab@*/
680 /*@modifies st, globtab, e@*/
682 cstring ename = uentry_rawName (e);
683 bool staticEntry = FALSE;
686 DPRINTF (("Sup entry aux: %s", uentry_unparseFull (e)));
688 /* static tags in global scope */
689 if (st->lexlevel == fileScope
690 && (!(uentry_isStatic (e)) || uentry_isAnyTag (e)))
692 eindex = usymtab_getIndex (st, ename);
694 if (eindex != NOT_FOUND)
696 uentry ce = st->entries[eindex];
700 message ("%s %q shadows static declaration",
701 ekind_capName (uentry_getKind (e)),
703 uentry_whereDeclared (e)))
705 uentry_showWhereLast (ce);
708 if (eindex == st->nentries - 1)
714 st->entries[eindex] = st->entries[st->nentries - 1];
717 if (cstringTable_isDefined (st->htable))
719 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
720 cstring_copy (uentry_rawName (e)));
730 if (uentry_isStatic (e)) {
731 if (uentry_isFunction (e)) {
733 ** Static function declarations are at the file level,
734 ** even if they are in a deeper scope.
737 st = usymtab_getFileTab ();
740 if (!uentry_isAnyTag (e) && st == globtab)
742 st = usymtab_getFileTab ();
744 DPRINTF (("Static entry!"));
749 DPRINTF (("Using symtab: %s", usymtab_unparseLocalAux (st)));
751 eindex = usymtab_getIndex (st, ename);
753 if (eindex != NOT_FOUND)
755 uentry ce = st->entries[eindex];
757 DPRINTF (("Found entry: %s", uentry_unparse (ce)));
759 if (uentry_isPriv (ce)
760 /* || (fileloc_isImport (uentry_whereSpecified (ce))) */
761 || (uentry_isStatic (ce)
762 && uentry_isAnyTag (ce)
763 && (uentry_isDeclared (ce)
764 && !fileloc_sameFile (uentry_whereDefined (ce),
765 uentry_whereDefined (e)))))
769 ** if overloading import should do some checks!
772 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
774 DPRINTF (("Overloading!"));
776 st->entries[eindex] = e;
778 if (uentry_isDatatype (e))
780 uentry_setDatatype (e, eindex);
783 if (st == globtab && !uentry_isSpecified (e))
785 exprChecks_checkExport (e);
788 if (cstringTable_isDefined (st->htable))
790 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
791 cstring_copy (uentry_rawName (e)));
797 else if (uentry_isSpecified (ce))
799 if (uentry_isSpecified (e))
801 DPRINTF (("Here we are: %s", uentry_unparseFull (e)));
803 if (fileloc_isImport (uentry_whereSpecified (ce)))
805 if (cstringTable_isDefined (st->htable))
807 cstringTable_replaceKey (st->htable,
809 cstring_copy (uentry_rawName (e)));
813 st->entries[eindex] = e;
816 if (uentry_isDatatype (e)) uentry_setDatatype (e, eindex);
820 if (fileloc_isImport (uentry_whereSpecified (e)))
826 /* Respecification errors already reported */
827 DPRINTF (("Respecification: %s / %s",
828 fileloc_unparse (uentry_whereSpecified (e)),
829 bool_unparse (fileloc_isSpec (uentry_whereSpecified (e)))));
831 if (uentry_isDatatype (e))
833 uentry_setDatatype (e, eindex);
836 if (cstringTable_isDefined (st->htable))
838 cstringTable_replaceKey (st->htable,
840 cstring_copy (uentry_rawName (e)));
843 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
845 st->entries[eindex] = e;
850 else /* e not specified */
852 DPRINTF (("Merging..."));
854 if (uentry_isDeclared (ce))
857 No - this can happen for internal typedefs
858 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
861 DPRINTF (("Merge defn"));
862 uentry_mergeDefinition (ce, e);
867 No - this can happen for internal typedefs
868 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
871 DPRINTF (("Merge entries..."));
872 uentry_mergeEntries (ce, e);
873 DPRINTF (("After: %s", uentry_unparseFull (ce)));
877 else /* ce not specified */
879 if (!(st->lexlevel > fileScope || !sRef_modInFunction ()))
881 if (uentry_isDatatype (e) || uentry_isAnyTag (e)
882 || uentry_isEnumConstant (e))
885 ** Not a bug. Code like,
886 ** int f (void) { typedef int tint; ... }
892 llcontbug (message ("usymtab_supEntryAux: inconsistent state "
893 "(lexlevel = %d, modFunction = %s) adding: %q",
894 st->lexlevel, bool_unparse (sRef_modInFunction ()),
895 uentry_unparse (e)));
897 if (sRef_modInFunction ())
899 /* make sure the sRef is not bashed! */
900 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
905 DPRINTF (("Merge.."));
906 uentry_mergeDefinition (ce, e);
911 ctype ct = uentry_getType (ce);
913 if (uentry_isFunction (ce) && ctype_isFunction (ct))
915 ct = ctype_getReturnType (ct);
918 uentry_setSref (ce, sRef_makeCvar (st->lexlevel, eindex, ct, stateInfo_makeLoc (uentry_whereLast (ce))));
921 else /* no previous entry */
925 if (st->lexlevel == globScope
926 && !uentry_isStatic (e)
927 && !uentry_isExtern (e)
928 && usymtab_isDefined (filetab))
931 ** check if there is a static entry: (i.e.,
938 eindex = usymtab_getIndex (filetab, ename);
940 if (eindex != NOT_FOUND)
942 uentry ce = filetab->entries[eindex];
944 uentry_setStatic (e);
945 uentry_mergeDefinition (ce, e);
951 outer = usymtab_lookupQuiet (st->env, ename);
953 DPRINTF (("New : [%p] %s", e, uentry_unparseFull (e)));
954 DPRINTF (("Outer: [%p] %s", outer, uentry_unparseFull (outer)));
957 ** no previous definition, add the new one
961 && uentry_isValid (outer)
962 && !(uentry_isYield (e) || uentry_isYield (outer))
963 && fileloc_isDefined (uentry_whereLast (e))
964 && !fileloc_isXHFile (uentry_whereLast (e))
965 && fileloc_isDefined (uentry_whereLast (outer))
966 && !fileloc_isXHFile (uentry_whereLast (outer)))
968 if (!uentry_sameKind (outer, e))
974 if (ctype_isUnknown (uentry_getType (outer))
975 || uentry_isForward (outer))
983 message ("%s %q shadows outer declaration",
984 ekind_capName (uentry_getKind (e)),
986 uentry_whereLast (e)))
988 uentry_showWhereLast (outer);
994 if (st == globtab && context_getFlag (FLG_NEWDECL))
998 message ("New declaration: %q", uentry_getName (e)),
999 uentry_whereLast (e));
1002 eindex = usymtab_addEntryAux (st, e, isSref);
1006 return (staticEntry ? USYMIDINVALID : eindex);
1011 usymtab_replaceEntryAux (/*@notnull@*/ usymtab st, /*@only@*/ uentry e)
1012 /*@globals globtab@*/ /*@modifies st, e@*/
1014 cstring ename = uentry_rawName (e);
1017 /* static tags in global scope */
1018 eindex = usymtab_getIndex (st, ename);
1020 if (eindex != NOT_FOUND)
1022 uentry ce = st->entries[eindex];
1024 if (cstringTable_isDefined (st->htable))
1026 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
1027 cstring_copy (uentry_rawName (e)));
1031 st->entries[eindex] = e;
1035 eindex = usymtab_addEntryAux (st, e, FALSE);
1042 void usymtab_supEntry (uentry e)
1043 /*@globals utab, filetab, globtab@*/
1044 /*@modifies utab, globtab, e@*/
1046 (void) usymtab_supEntryAux (utab, e, FALSE);
1050 ** this should be lots more efficient!
1053 static /*@exposed@*/ uentry
1054 usymtab_supEntryReturnAux (/*@notnull@*/ usymtab tab,
1055 /*@only@*/ uentry e, bool isref)
1056 /*@globals globtab, filetab@*/
1057 /*@modifies tab, globtab, e@*/
1059 cstring rawName = cstring_copy (uentry_rawName (e));
1060 bool stat = (tab == globtab) && uentry_isStatic (e);
1063 (void) usymtab_supEntryAux (tab, e, isref);
1067 ret = usymtab_lookupAux (filetab, rawName);
1071 ret = usymtab_lookupAux (tab, rawName);
1073 if (uentry_isInvalid (ret) && usymtab_isDefined (filetab))
1075 ret = usymtab_lookupAux (filetab, rawName);
1079 cstring_free (rawName);
1083 /*@dependent@*/ /*@exposed@*/ uentry
1084 usymtab_supEntryReturn (/*@only@*/ uentry e)
1085 /*@globals utab, filetab, globtab@*/
1086 /*@modifies utab, globtab, e@*/
1088 return (usymtab_supEntryReturnAux (utab, e, FALSE));
1091 /*@dependent@*/ /*@exposed@*/ uentry
1092 usymtab_supEntrySrefReturn (/*@only@*/ uentry e)
1093 /*@globals utab, globtab, filetab@*/
1094 /*@modifies utab, globtab, e@*/
1096 return (usymtab_supEntryReturnAux (utab, e, TRUE));
1099 /*@dependent@*/ /*@exposed@*/ uentry
1100 usymtab_supGlobalEntryReturn (uentry e)
1101 /*@globals globtab, filetab@*/
1102 /*@modifies globtab, e@*/
1106 ret = usymtab_supEntryReturnAux (globtab, e, FALSE);
1109 ** We need to keep track of internal function declarations, so
1110 ** we can remove them from the symbol table after exiting this
1111 ** function. This is a bit bogus, of course.
1114 if (sRef_modInFunction ())
1116 recordFunctionType (ret);
1123 usymtab_supTypeEntry (/*@only@*/ uentry e)
1124 /*@globals globtab, filetab@*/
1125 /*@modifies globtab, e@*/
1130 if (uentry_isAbstractDatatype (e))
1132 uid = usymtab_supAbstractTypeEntry (e, FALSE);
1133 ret = ctype_createAbstract (uid);
1137 uid = usymtab_supEntryAux (globtab, e, FALSE);
1138 ret = ctype_createUser (uid);
1141 if (sRef_modInFunction ())
1143 recordFunctionType (globtab->entries[uid]);
1150 usymtab_supReturnTypeEntry (/*@only@*/ uentry e)
1151 /*@globals globtab, filetab@*/
1152 /*@modifies globtab@*/
1156 DPRINTF (("Abstract? %s", uentry_unparseFull (e)));
1158 if (uentry_isAbstractDatatype (e))
1160 uid = usymtab_supAbstractTypeEntry (e, FALSE);
1162 else if (uentry_isMaybeAbstract (e) && context_getFlag (FLG_IMPABSTRACT))
1164 bool maybeabs = TRUE;
1165 cstring sname = uentry_getName (e);
1166 uentry ue = usymtab_lookupGlobSafe (sname);
1167 cstring_free (sname);
1169 if (uentry_isValid (ue))
1171 DPRINTF (("Lookup: %s", uentry_unparseFull (ue)));
1173 if (uentry_isDatatype (ue))
1175 if (uentry_isMaybeAbstract (ue))
1186 DPRINTF (("Not datatype!"));
1193 uid = usymtab_supAbstractTypeEntry (e, FALSE);
1194 ux = usymtab_getTypeEntry (uid);
1195 uentry_setAbstract (ux);
1199 uid = usymtab_supEntryAux (globtab, e, FALSE);
1200 e = usymtab_getTypeEntry (uid);
1202 if (uentry_isMaybeAbstract (e))
1204 uentry_setConcrete (e);
1210 uid = usymtab_supEntryAux (globtab, e, FALSE);
1211 e = usymtab_getTypeEntry (uid);
1213 if (uentry_isMaybeAbstract (e))
1215 uentry_setConcrete (e);
1219 if (sRef_modInFunction ())
1221 recordFunctionType (globtab->entries[uid]);
1224 return (globtab->entries[uid]);
1228 usymtab_supAbstractTypeEntry (/*@only@*/ uentry e, bool dodef)
1229 /*@globals globtab, filetab@*/
1230 /*@modifies globtab, e@*/
1235 uid = usymtab_supEntryAux (globtab, e, FALSE);
1236 ue = usymtab_getTypeEntry (uid);
1240 uentry_setDatatype (ue, uid);
1243 if (context_getFlag (FLG_ACCESSMODULE)) /* was accessfile */
1245 context_addFileAccessType (uid);
1248 if (sRef_modInFunction ())
1250 recordFunctionType (globtab->entries[uid]);
1258 usymtab_supExposedTypeEntry (/*@only@*/ uentry e, bool dodef)
1259 /*@globals globtab, filetab@*/
1260 /*@modifies globtab, e@*/
1264 uid = usymtab_supEntryAux (globtab, e, FALSE);
1268 uentry ue = usymtab_getTypeEntry (uid);
1270 uentry_setDatatype (ue, uid);
1273 if (sRef_modInFunction ())
1275 recordFunctionType (globtab->entries[uid]);
1283 usymtab_supForwardTypeEntry (/*@only@*/ uentry e)
1284 /*@globals globtab, filetab@*/
1285 /*@modifies globtab, e@*/
1287 usymId uid = usymtab_supEntryAux (globtab, e, FALSE);
1288 uentry ue = usymtab_getTypeEntry (uid);
1290 uentry_setDatatype (ue, uid);
1292 if (sRef_modInFunction ())
1294 recordFunctionType (globtab->entries[uid]);
1297 return (uentry_getAbstractType (ue));
1301 usymtab_supEntrySref (uentry e)
1302 /*@globals utab, globtab, filetab@*/
1303 /*@modifies utab, globtab, e@*/
1305 sRef old = uentry_getSref (e);
1308 if (sRef_isType (old))
1310 uentry ue = usymtab_supEntryReturnAux (utab, e, TRUE);
1313 if (uentry_isValid (ue))
1315 sRef uref = uentry_getSref (ue);
1317 sRef_mergeStateQuiet (uref, old);
1318 sRef_clearDerived (uref);
1320 /*@noaccess uentry@*/
1322 else if (sRef_isKnown (old))
1324 usymtab_supEntry (e);
1328 (void) usymtab_supEntryAux (utab, e, TRUE);
1332 void usymtab_supGlobalEntry (/*@only@*/ uentry e)
1333 /*@globals globtab, filetab@*/
1334 /*@modifies globtab, filetab, e@*/
1338 DPRINTF (("Sup global entry: %s", uentry_unparse (e)));
1340 uid = usymtab_supEntryAux (globtab, e, FALSE);
1342 if (sRef_modInFunction ())
1344 recordFunctionType (globtab->entries[uid]);
1349 usymtab_supReturnFileEntry (/*@only@*/ uentry e)
1350 /*@globals filetab, globtab@*/
1351 /*@modifies filetab, globtab, e@*/
1353 llassert (filetab != usymtab_undefined);
1354 DPRINTF (("File entry: %s", uentry_unparse (e)));
1355 return (usymtab_supEntryReturnAux (filetab, e, FALSE));
1363 usymtab_inDeepScope () /*@globals utab@*/
1365 return (utab->lexlevel > paramsScope);
1369 usymtab_getIndex (/*@notnull@*/ usymtab s, cstring k)
1373 DPRINTF (("Lookup %s", k));
1375 if (cstringTable_isDefined (s->htable))
1377 i = cstringTable_lookup (s->htable, k);
1382 for (i = 0; i < s->nentries; i++)
1384 uentry current = s->entries[i];
1386 DPRINTF (("Check %d: %s", i, uentry_rawName (current)));
1388 if (!uentry_isUndefined (current)
1389 && cstring_equal (uentry_rawName (current), k))
1400 usymtab_fetchIndex (/*@notnull@*/ usymtab s, int i)
1402 llassert (i >= 0 && i < s->nentries);
1403 return (s->entries[i]);
1407 usymtab_getTypeId (cstring k) /*@globals globtab@*/
1409 usymId uid = usymtab_getIndex (globtab, k);
1411 if (uid == NOT_FOUND) return USYMIDINVALID;
1413 if (!(uentry_isDatatype (usymtab_getTypeEntry (uid)))) {
1414 return USYMIDINVALID;
1420 /*@dependent@*/ uentry
1421 usymtab_lookupStructTag (cstring k)
1423 cstring sname = makeStruct (k);
1424 uentry ue = usymtab_lookupGlob (sname);
1426 cstring_free (sname);
1430 /*@dependent@*/ uentry
1431 usymtab_lookupUnionTag (cstring k)
1433 cstring uname = makeUnion (k);
1434 uentry res = usymtab_lookupGlob (uname);
1436 cstring_free (uname);
1440 /*@dependent@*/ uentry
1441 usymtab_lookupEnumTag (cstring k)
1443 cstring ename = makeEnum (k);
1444 uentry res = usymtab_lookupGlob (ename);
1446 cstring_free (ename);
1451 usymtab_getId (cstring k) /*@globals globtab@*/
1453 usymId uid = usymtab_getIndex (globtab, k);
1456 if (uid == NOT_FOUND)
1458 return USYMIDINVALID;
1461 ue = usymtab_getGlobalEntry (uid);
1463 if (uentry_isPriv (ue))
1465 return USYMIDINVALID;
1471 static /*@exposed@*/ uentry
1472 usymtab_getEntryAux (/*@notnull@*/ usymtab s, usymId uid)
1474 llassert (uid != USYMIDINVALID);
1476 if (uid < 0 || uid >= s->nentries)
1478 llcontbug (message ("usymtab_getEntry: out of range: level = %d [%d]",
1480 return uentry_undefined;
1483 llassertprint (uentry_isValid (s->entries[uid]),
1484 ("entry undefined: %d", uid));
1486 return s->entries[uid];
1489 /*@dependent@*/ /*@observer@*/ uentry
1490 usymtab_getGlobalEntry (usymId uid)
1491 /*@globals utab, globtab@*/
1493 if (dbgfree) return (uentry_undefined);
1495 if (utab->lexlevel > paramsScope)
1497 /* need to do this the awkward way, since it could be in conditional scope */
1498 return (usymtab_lookupSafe (uentry_rawName (globtab->entries[uid])));
1502 return (globtab->entries[uid]);
1506 /*@dependent@*/ /*@exposed@*/ uentry
1507 usymtab_getTypeEntry (usymId uid)
1508 /*@globals globtab@*/
1512 if (uid >= 0 && uid < globtab->nentries)
1514 return (globtab->entries[uid]);
1518 return (uentry_undefined);
1523 llassert (uid >= 0 && uid < globtab->nentries);
1524 return (globtab->entries[uid]);
1532 /*@dependent@*/ /*@exposed@*/ uentry
1533 usymtab_getTypeEntrySafe (usymId uid)
1534 /*@globals globtab@*/
1536 if (uid < 0 || uid >= globtab->nentries)
1538 return uentry_undefined;
1541 return (globtab->entries[uid]);
1545 usymtab_isBoolType (usymId uid)
1546 /*@globals globtab@*/
1548 llassert (uid >= 0 && uid < globtab->nentries);
1550 return (cstring_equal (uentry_rawName (globtab->entries[uid]),
1551 context_getBoolName ()));
1555 usymtab_getTypeEntryName (usymId uid)
1556 /*@globals globtab@*/
1562 return (cstring_makeLiteral ("<freetype>"));
1565 ue = usymtab_getTypeEntry (uid);
1567 if (dbgload && !uentry_isValid (ue))
1569 return (message ("<missing type: %d>", uid));
1572 llassertprint (uentry_isValid (ue), ("type undefined: %d", uid));
1574 return (uentry_getName (ue));
1577 /*@unused@*/ static void
1578 usymtab_rehash (/*@notnull@*/ usymtab s)
1582 if (cstringTable_isDefined (s->htable))
1584 cstringTable_free (s->htable);
1587 s->htable = cstringTable_create (LLHASHSIZE);
1589 for (i = 0; i < s->nentries; i++)
1591 cstringTable_insert (s->htable, cstring_copy (uentry_rawName (s->entries[i])), i);
1596 ** superficial copy of usymtab
1598 ** DO copy spec entries
1601 static /*@only@*/ /*@notnull@*/ usymtab
1602 usymtab_shallowCopy (/*@notnull@*/ usymtab s) /*@*/
1604 usymtab copytab = usymtab_createRoot ();
1607 for (i = 0; i < s->nentries; i++)
1609 usymtab_addEntryBase (copytab, s->entries[i]);
1616 usymtab_shallowFree (/*@only@*/ /*@notnull@*/ usymtab s)
1618 aliasTable_free (s->aliases);
1619 refTable_free (s->reftable, s->nentries);
1621 /*@-compdestroy@*/ sfree (s); /*@=compdestroy@*/
1625 ** converts usymId from old table to sorted one
1629 usymtab_convertId (usymId uid)
1630 /*@globals oldtab, utab@*/
1636 llassert (usymtab_isDefined (oldtab));
1638 ue = usymtab_getEntryAux (oldtab, uid);
1640 llassertprint (uentry_isValid (ue), ("convertId: undefined: %d", uid));
1642 name = uentry_rawName (ue);
1644 ret = usymtab_getIndex (utab, name);
1645 llassert (ret == uid); /*! for now, no rehash! */
1646 DPRINTF (("Convert: %s [%d] -> %s [%d]",
1647 uentry_unparse (ue), uid,
1648 uentry_unparse (utab->entries[ret]), ret));
1650 llassertprint (ret != USYMIDINVALID, ("convertId: return is invalid"));
1656 usymtab_prepareDump (void)
1657 /*@globals oldtab, utab@*/
1658 /*@modifies oldtab, utab@*/
1660 llassert (usymtab_inGlobalScope ());
1661 llassert (oldtab == usymtab_undefined);
1664 DPRINTF (("Preparing to dump:"));
1665 usymtab_printAll ();
1668 oldtab = usymtab_shallowCopy (utab);
1671 ** alpha compare - make sure order is same on different platforms
1672 ** error messages appear in same order
1676 qsort (utab->entries, (size_t)utab->nentries,
1677 sizeof (*utab->entries),
1678 (int (*)(const void *, const void *)) uentry_xcomparealpha);
1680 usymtab_rehash (utab);
1684 DPRINTF (("After rehash:"));
1685 usymtab_printAll ();
1689 void usymtab_dump (FILE *fout)
1690 /*@globals utab, oldtab@*/
1693 bool neednl = FALSE;
1694 uentry lastentry = uentry_undefined;
1695 ekind lastekind = KINVALID;
1699 ** must call prepareDump first
1702 llassert (oldtab != usymtab_undefined);
1704 for (i = 0; i < utab->nentries; i++)
1706 uentry thisentry = utab->entries[i];
1707 ekind thisekind = uentry_getKind (thisentry);
1709 if (!uentry_hasRealName (thisentry))
1711 llassert (uentry_isGlobalMarker (thisentry));
1715 check (fputc ('\n', fout) == (int) '\n');
1718 fprintf (fout, "*%d (GlobalMarker)\n", KGLOBALMARKER);
1719 lastekind = KINVALID;
1725 if (thisekind != lastekind)
1729 check (fputc ('\n', fout) == (int) '\n');
1733 lastentry = uentry_undefined;
1734 fprintf (fout, "*%d (%s)\n", ekind_toInt (thisekind),
1735 cstring_toCharsSafe (ekind_capName (thisekind)));
1736 lastekind = thisekind;
1741 ** evans - 2001-02-18 - added the - 48 fudge factor...
1742 ** extra characters dumped, but I haven't counded them carefully...
1745 if (uentry_isInvalid (lastentry) || !uentry_equiv (lastentry, thisentry)
1746 || (linelen > (MAX_DUMP_LINE_LENGTH - (2 * MAX_NAME_LENGTH) - 48)))
1750 DPRINTF (("Dumping entry: %d", i));
1751 cdump = message ("^%d %q", i, uentry_dump (thisentry));
1752 /* was: cdump = uentry_dump (thisentry)); */
1754 lastentry = thisentry;
1757 check (fputc ('\n', fout) == (int) '\n');
1761 linelen += cstring_length (cdump);
1763 /* no new line here! */
1764 if (cstring_length (cdump) > 0)
1766 check (fputs (cstring_toCharsSafe (cdump), fout) != EOF);
1769 cstring_free (cdump);
1774 cstring cdump = uentry_rawName (thisentry);
1775 DPRINTF (("Raw name: %s", cdump));
1776 linelen += (cstring_length (cdump) + 1);
1777 fprintf (fout, "#%s", cstring_toCharsSafe (cdump));
1784 check (fputc ('\n', fout) == (int) '\n');
1787 lastekind = KINVALID;
1789 fprintf(fout, ";; Library constraints\n");
1790 for (i = 0; i < utab->nentries; i++)
1792 uentry thisentry = utab->entries[i];
1794 if (uentry_isFunction (thisentry) )
1796 constraintList preconditions;
1797 constraintList postconditions;
1799 preconditions = uentry_getFcnPreconditions (thisentry);
1800 postconditions = uentry_getFcnPostconditions (thisentry);
1802 if ( constraintList_isDefined(preconditions) ||
1803 constraintList_isDefined(postconditions) )
1805 fprintf(fout,"%s\n", cstring_toCharsSafe (uentry_rawName(thisentry) ) );
1806 if (constraintList_isDefined(preconditions) )
1808 fprintf(fout,"pre:\n");
1809 constraintList_dump(preconditions, fout);
1810 fprintf (fout, ";; end precondition constraints\n" );
1811 constraintList_free(preconditions);
1815 fprintf(fout,"pre:EMPTY\n");
1817 if (constraintList_isDefined(postconditions) )
1819 fprintf(fout,"post:\n");
1820 constraintList_dump(postconditions, fout);
1821 fprintf (fout, ";; end precondition constraints\n" );
1822 constraintList_free(postconditions);
1826 fprintf(fout,"post:EMPTY\n");
1837 void usymtab_load (FILE *f)
1838 /*@globals utab, globtab@*/
1839 /*@modifies utab, *f@*/
1841 char *s = mstring_create (MAX_DUMP_LINE_LENGTH);
1843 ekind kind = KINVALID;
1844 fileloc loc = g_currentloc;
1850 llassert (utab == globtab);
1851 llassert (utab->nentries == 0);
1853 while (((s = reader_readLine (f, s, MAX_DUMP_LINE_LENGTH)) != NULL)
1856 /* ignore ; comments */ ;
1859 while (s != NULL && *s != ';')
1867 ek = reader_getInt (&s);
1869 if (ek == KGLOBALMARKER)
1871 uentry lue = uentry_makeGlobalMarker ();
1872 DPRINTF (("Adding global marker: %s", uentry_unparseFull (lue)));
1873 usymtab_addEntryAlways (utab, lue);
1879 kind = ekind_fromInt (ek);
1887 (cstring_makeLiteral
1888 ("Library is in obsolete format. Use lclint +whichlib "
1889 "to see which library is being loaded."));
1892 if (reader_optCheckChar (&s, '^'))
1894 index = reader_getInt (&s);
1901 llassert (kind != KINVALID);
1902 ue = uentry_undump (kind, loc, &s);
1904 llassert (utab->nentries == index || index == -1);
1906 if (uentry_isValid (ue))
1908 int lastindex = utab->nentries;
1909 ue = usymtab_addEntryAlways (utab, ue);
1910 if (utab->nentries != lastindex + 1)
1912 DPRINTF (("No add: %s", uentry_unparseFull (ue)));
1920 ** now, any other names are the same uentry
1923 while (*(s++) == '#')
1925 cstring name = cstring_fromCharsO (reader_getWord (&s));
1926 uentry nue = uentry_nameCopy (name, ue);
1928 DPRINTF (("Name copy: %s", uentry_unparseFull (nue)));
1932 usymtab_addEntryAlways (utab, nue);
1935 while ((c = *s) != '\0' && (c !='\n'))
1937 if (c != ' ' || c != '\t')
1939 llbuglit ("Junk in load file");
1947 s = reader_readLine (f, os, MAX_DUMP_LINE_LENGTH);
1952 to handle reading of buffer overflow related constraints
1954 while (fgets (s, MAX_DUMP_LINE_LENGTH, f) != NULL
1957 ; /* ignore ;-comments */
1960 while (s != NULL && *s != ';')
1962 constraintList preconditions;
1963 constraintList postconditions;
1965 cstring name = cstring_fromChars(reader_getWord(&s) );
1967 ue = usymtab_lookup ( name );
1971 preconditions = constraintList_undefined;
1972 postconditions = constraintList_undefined;
1974 if (!uentry_isValid(ue) )
1976 llfatalbug ((message("Invalid uentry for %s library file may be corrupted", cstring_fromChars(s) ) ));
1978 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
1980 temp = cstring_fromChars (reader_getWord(&s) );
1982 if (cstring_compareLit (temp,"pre:") == 0 )
1984 preconditions = constraintList_undump (f);
1988 if (cstring_compareLit (temp,"pre:EMPTY") != 0 )
1989 llfatalbug ((message("Error reading library file pre:EMPTY expected but got %s", temp ) ));
1994 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
1996 temp = cstring_fromChars(reader_getWord(&s) );
1997 if (cstring_compareLit (temp, "post:") == 0 )
1999 postconditions = constraintList_undump (f);
2003 if (cstring_compareLit (temp, "post:EMPTY") != 0 )
2004 llfatalbug ((message("Error reading library file post:EMPTY expected but got %s", temp ) ));
2007 cstring_free (temp);
2009 uentry_setPreconditions (ue, functionConstraint_createBufferConstraint (preconditions));
2010 uentry_setPostconditions (ue, functionConstraint_createBufferConstraint (postconditions));
2012 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2020 ** file scope for static variables
2024 usymtab_enterFile ()
2025 /*@globals utab, globtab, filetab@*/
2026 /*@modifies filetab@*/
2028 llassert (utab == globtab);
2033 usymtab_entries (globtab, ue)
2035 if (sRef_hasDerived (uentry_getSref (ue)))
2037 fprintf (g_msgstream, "Derived Global: %s\n", uentry_unparse (ue));
2038 fprintf (g_msgstream, "sRef: %s\n", sRef_unparseFull (ue->sref));
2040 } end_usymtab_entries ;
2044 usymtab_enterScope ();
2050 /*@globals utab, filetab@*/
2051 /*@modifies filetab, utab@*/
2054 llassert (utab->lexlevel == 1);
2056 usymtab_exitScope (exprNode_undefined);
2061 usymtab_enterScope ()
2062 /*@globals utab, globtab, filetab@*/
2065 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
2067 /* unconditional scope: optimize to avoid copy */
2068 t->aliases = aliasTable_copy (utab->aliases);
2071 llassert (usymtab_isDefined (t->env));
2073 if (t->env->lexlevel == paramsScope && context_inFunctionLike ())
2075 noshadowerror = TRUE;
2076 usymtab_handleParams ();
2077 noshadowerror = FALSE;
2082 ** setup external references:
2083 ** o only, unique params alias external args
2084 ** o other params may alias anything of their type
2088 usymtab_handleParams (void)
2089 /*@globals utab, globtab, filetab@*/
2090 /*@modifies utab, globtab@*/
2092 usymtab ptab = utab->env;
2093 uentry fcn = context_getHeader ();
2095 usymtab_entries (ptab, param)
2099 if (!uentry_isYield (param))
2102 sRef pref = uentry_getSref (param);
2104 /* Could be a global. */
2106 if (uentry_isAnyParam (param))
2108 ue = uentry_makeVariable (fixParamName (uentry_rawName (param)),
2109 uentry_getType (param),
2110 fileloc_copy (uentry_whereDeclared (param)),
2113 uentry_copyState (ue, param);
2114 uentry_setRefParam (ue);
2116 ue = usymtab_supEntrySrefReturn (ue);
2118 /* must be after supercede! */
2120 if (!sRef_stateKnown (pref))
2122 uentry_setDefState (ue, SS_DEFINED);
2123 uentry_setDefState (param, SS_DEFINED);
2127 if (sRef_isStateSpecial (pref))
2129 uentry_setDefState (ue, SS_ALLOCATED);
2133 uentry_setDefState (ue, sRef_getDefState (pref));
2137 uref = uentry_getSref (ue);
2139 if (sRef_isStack (uref))
2141 alkind pkind = sRef_getAliasKind (pref);
2143 if (alkind_isKnown (pkind) && !alkind_isLocal (pkind)
2144 && !alkind_isStack (pkind))
2146 sRef_setAliasKind (uref, pkind, fileloc_undefined);
2147 sRef_setOrigAliasKind (uref, pkind);
2151 sRef_setAliasKind (uref, AK_IMPTEMP, fileloc_undefined);
2152 sRef_setOrigAliasKind (uref, AK_IMPTEMP);
2154 if (uentry_isOut (param))
2160 sRef_setDefined (uref, fileloc_undefined);
2166 usymtab_addMustAlias (uref, pref);
2168 if (!(uentry_isOnly (param) || uentry_isUnique (param)))
2171 ** This is needed for detecting possibly aliased parameters.
2174 sRef s = sRef_makeExternal (uref);
2175 usymtab_addMustAlias (uref, s);
2178 if (sRef_isKillRef (pref))
2180 sRef_setAliasKind (uref, AK_NEWREF, fileloc_undefined);
2181 sRef_setOrigAliasKind (uref, AK_KILLREF);
2183 else if (sRef_isRefCounted (uref))
2185 sRef_setOrigAliasKind (uref, AK_REFCOUNTED);
2190 sRef_setOrigAliasKind (uref, AK_LOCAL);
2197 } end_usymtab_entries;
2200 if (uentry_hasStateClauseList (fcn))
2202 stateClauseList clauses = uentry_getStateClauseList (fcn);
2204 stateClauseList_preElements (clauses, cl)
2206 fileloc loc = stateClause_loc (cl);
2207 sRefSet osrs = sRefSet_undefined;
2210 if (stateClause_isGlobal (cl))
2212 DPRINTF (("Global Marker: %s",
2213 sRef_unparseFull (usymtab_lookupGlobalMarker ())));
2214 llassert (sRef_isGlobalMarker (usymtab_lookupGlobalMarker ()));
2215 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
2220 srs = stateClause_getRefs (cl);
2223 sRefSet_elements (srs, el)
2225 sRef base = sRef_getRootBase (el);
2226 sRef sb = sRef_updateSref (el);
2228 if (sRef_isResult (base))
2230 ; /* nothing to do before */
2232 else if (sRef_isParam (base) || sRef_isGlobalMarker (base))
2234 if (stateClause_setsMetaState (cl))
2236 /* copied from exprNode.c:3040 */
2237 qual ql = stateClause_getMetaQual (cl);
2238 annotationInfo ainfo = qual_getAnnotationInfo (ql);
2239 metaStateInfo minfo = annotationInfo_getState (ainfo);
2240 cstring key = metaStateInfo_getName (minfo);
2241 int mvalue = annotationInfo_getValue (ainfo);
2243 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
2245 if (sRef_isResult (base))
2251 sRef_setMetaStateValueComplete (sb, key, mvalue, loc);
2256 sRefMod modf = stateClause_getEntryFunction (cl);
2260 sRefSet aliases = usymtab_allAliases (sb);
2264 sRefSet_elements (aliases, sr)
2267 } end_sRefSet_elements ;
2269 sRefSet_free (aliases);
2275 if (sRef_isValid (base))
2277 DPRINTF (("Base: %s", sRef_unparseFull (base)));
2281 } end_sRefSet_elements ;
2282 } end_stateClauseList_preElements ;
2287 usymtab_enterFunctionScope (uentry fcn)
2288 /*@globals utab, filetab, globtab@*/
2291 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
2293 if (utab->lexlevel != fileScope)
2295 if (utab->lexlevel > fileScope)
2297 llparseerror (cstring_makeLiteral ("New function scope inside function"));
2299 while (utab->lexlevel > fileScope)
2301 /*@i@*/ utab = usymtab_dropEnv (utab);
2308 llfatalbug (cstring_makeLiteral ("New function not inside file."));
2310 /*@-branchstate@*/ } /*@=branchstate@*/
2314 DPRINTF (("Globs: %s", globSet_unparse (uentry_getGlobs (fcn))));
2316 globSet_allElements (uentry_getGlobs (fcn), el)
2318 DPRINTF (("Here we go: %s", sRef_unparseFull (el)));
2320 if (sRef_isUndefGlob (el))
2322 int index = sRef_getScopeIndex (el);
2323 sRef sr = sRef_updateSref (el);
2324 fileloc loc = uentry_whereEarliest (fcn);
2326 DPRINTF (("update: %s", sRef_unparseFull (sr)));
2327 DPRINTF (("Undef!"));
2328 if (sRef_isFileStatic (el))
2330 ctype ct = sRef_getType (el);
2333 llassert (usymtab_isDefined (filetab));
2335 ue = usymtab_fetchIndex (filetab, index);
2337 if (ctype_isRealArray (ct) || ctype_isRealSU (ct))
2339 sRef_setAllocated (sr, loc);
2343 sRef_setUndefined (sr, loc);
2348 uentry ue = globtab->entries[index];
2349 ctype ct = uentry_getType (ue);
2351 if (ctype_isArray (ct) || ctype_isSU (ct))
2353 sRef_setAllocated (sr, loc);
2357 sRef_setUndefined (sr, loc);
2361 else if (sRef_isAllocated (el))
2363 sRef sr = sRef_updateSref (el);
2364 fileloc loc = uentry_whereEarliest (fcn);
2366 sRef_setAllocated (sr, loc);
2368 else if (sRef_isPartial (el))
2370 sRef sr = sRef_updateSref (el);
2371 fileloc loc = uentry_whereEarliest (fcn);
2373 sRef_setPartial (sr, loc);
2378 sRef sr = sRef_updateSref (el);
2379 fileloc loc = uentry_whereEarliest (fcn);
2381 sRef_setDefined (sr, loc);
2385 /* shouldn't need to do anything! */
2387 } end_globSet_allElements;
2389 DPRINTF (("Globs after: %s", globSet_unparse (uentry_getGlobs (fcn))));
2393 usymtab_caseBranch (void)
2396 usymtab t = usymtab_create (US_CBRANCH, utab, FALSE);
2401 usymtab_switchBranch (/*@unused@*/ exprNode s)
2404 usymtab t = usymtab_create (US_SWITCH, utab, FALSE);
2406 t->aliases = aliasTable_copy (utab->aliases);
2411 usymtab_trueBranch (/*@only@*/ guardSet guards)
2414 usymtab t = usymtab_create (US_TBRANCH, utab, FALSE);
2417 ** not true! (could be in a macro)
2419 ** llassertprint (utab->lexlevel > paramsScope,
2420 ** ("not in scope: %s", usymtab_unparseLocal ()));
2424 guardSet_free (t->guards);
2427 aliasTable_free (t->aliases);
2428 t->aliases = aliasTable_copy (utab->aliases);
2436 ** { int a; if (...) a = 3; < a may be undefined here!
2441 usymtab_popTrueBranch (exprNode pred, exprNode expr, clause cl) /*@modifies utab@*/
2444 ** add a false branch
2445 ** (could be done more efficiently as a special case, but
2446 ** it is better to only maintain one version of the code)
2449 if (utab->kind != US_TBRANCH
2450 && context_inIterDef ())
2452 usymtab_exitScope (expr);
2456 DPRINTF (("pop true branch.."));
2457 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2458 usymtab_popBranches (pred, expr, exprNode_undefined, TRUE, cl);
2463 usymtab_popCaseBranch () /*@modifies utab@*/
2465 llassert (utab->kind == US_CBRANCH);
2466 usymtab_quietPlainExitScope ();
2470 usymtab_popTrueExecBranch (exprNode pred, exprNode expr, clause cl)
2473 ** add a false branch that must return --- that is,
2474 ** the true branch is always executed!
2477 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2478 usymtab_popBranches (pred, expr, exprNode_makeMustExit (), FALSE, cl);
2482 usymtab_popOrBranch (exprNode pred, exprNode expr)
2486 usymtab env = utab->env;
2487 usymtab otab = utab;
2490 llassert (env != NULL);
2492 if (exprNode_isError (expr))
2498 mustReturn = exprNode_mustEscape (expr);
2502 llassert (utab->kind == US_TBRANCH);
2505 ** merge each entry in table with its original
2506 ** unless execution cannot continue after this branch
2509 for (i = 0; i < utab->nentries; i++)
2511 uentry current = utab->entries[i];
2512 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2514 uentry_mergeState (old, current, exprNode_loc (expr),
2515 mustReturn, FALSE, TRUE, ORCLAUSE);
2521 env->guards = guardSet_levelUnionFree (env->guards,
2522 guardSet_invert (exprNode_getGuards (pred)),
2527 env->aliases = aliasTable_levelUnion (env->aliases, otab->aliases, env->lexlevel);
2530 /* env is now utab */
2531 usymtab_quietPlainExitScope ();
2535 ** case syntax in C is very unrestricted. This is unfortunate.
2537 ** A switch case is ended either by a new case or default, or
2538 ** a close } that may close the switch or some other control
2543 usymtab_newCase (/*@unused@*/ exprNode pred, exprNode last)
2546 bool mustBreak = usymtab_mustBreak (utab);
2547 bool mustReturn = usymtab_mustEscape (utab);
2548 usymtab stab = utab;
2551 ** Find last case (or outer switch)
2554 while (stab->kind != US_CBRANCH && stab->kind != US_SWITCH)
2557 llassert (stab != GLOBAL_ENV);
2562 while (stab->kind == US_CBRANCH)
2565 llassert (stab != GLOBAL_ENV);
2569 ** if its a fall through case, merge in outside entries and last case.
2574 ** case 1: x = 3; <fall through>
2575 ** case 2: << x may not be defined
2579 if (!mustBreak && !mustReturn && utab->kind == US_CBRANCH)
2581 llassert (stab->kind == US_SWITCH || stab->kind == US_NORMAL);
2583 usymtab_entries (utab, ue) /* but, keep track of used variables */
2585 uentry old = usymtab_lookupAux (stab, uentry_rawName (ue));
2587 llassert (uentry_isValid (old));
2589 /* modifies ue, not old */
2591 uentry_mergeState (ue, old, exprNode_loc (last),
2592 FALSE, FALSE, TRUE, CASECLAUSE);
2593 } end_usymtab_entries;
2595 utab->aliases = aliasTable_levelUnion (utab->aliases,
2596 stab->aliases, utab->lexlevel);
2599 ** No need for a new branch.
2606 usymtab_caseBranch ();
2607 /*@-mustfree@*/ /*< utab->aliases >*/
2608 utab->aliases = aliasTable_copy (stab->aliases);
2616 ** for && (both pred and expr are executed)
2620 usymtab_popAndBranch (exprNode pred, /*@unused@*/ exprNode expr)
2623 usymtab env = utab->env;
2627 llassert (utab->kind == US_TBRANCH);
2630 ** merge each entry in table with its original
2631 ** unless execution cannot continue after this branch
2634 for (i = 0; i < utab->nentries; i++)
2636 uentry current = utab->entries[i];
2637 sRef tref = uentry_getSref (current);
2638 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2639 sRef oref = uentry_getSref (old);
2641 /* note that is current is in a nested branch,
2642 it may create a "new" old entry. */
2644 llassert (uentry_isValid (old));
2645 uentry_mergeState (old, current, exprNode_loc (expr),
2646 FALSE, FALSE, TRUE, ANDCLAUSE);
2649 ** if is it defined by the second clause, then it should be defined.
2652 if (sRef_isAnyDefined (tref)
2653 && (sRef_isAllocated (oref) || sRef_isStateUndefined (oref)))
2655 sRef_setDefined (oref, g_currentloc);
2659 utab->guards = guardSet_levelUnionFree (utab->guards,
2660 guardSet_invert (exprNode_getGuards (pred)),
2662 utab->aliases = aliasTable_levelUnion (utab->aliases, otab->aliases, utab->lexlevel);
2664 usymtab_quietPlainExitScope ();
2669 ** Stack should be [ US_CBRANCH+ US_SWITCH ]
2670 ** Only branches which do not return (except possibly the last branch) are included.
2672 ** Conditionally merge state from all CBRANCHes.
2674 ** If allpaths is TRUE, then all possible executions go through some switch
2675 ** case, and the original scope is not merged.
2679 usymtab_exitSwitch (/*@unused@*/ exprNode sw, bool allpaths)
2682 usymtab ttab = utab;
2683 usymtab stab = ttab;
2684 usymtab ltab = ttab;
2685 bool lastMustReturn = usymtab_mustEscape (utab);
2689 while (stab->kind == US_CBRANCH)
2692 llassert (stab != GLOBAL_ENV);
2695 while (stab->kind == US_NORMAL)
2698 llassert (stab != GLOBAL_ENV);
2701 llassert (stab->kind == US_SWITCH);
2703 /* go to the scope outside the switch (US_SWITCH is just a marker! */
2705 llassert (stab != GLOBAL_ENV);
2709 llassert (usymtab_isDefined (ttab));
2711 if (ttab->kind == US_CBRANCH)
2713 /* was quietPlainExitScope --- but, can't free it yet! */
2715 llassert (utab != GLOBAL_ENV);
2717 while (ttab->kind == US_CBRANCH)
2720 ** (from popTrueBranch)
2723 bool mustReturn = usymtab_mustEscape (ttab);
2724 bool mustBreak = usymtab_mustBreak (ttab);
2726 usymtab_entries (ttab, current)
2728 uentry old = /*@-compmempass@*/ usymtab_lookupAux (ltab, uentry_rawName (current));
2732 ** note that is this is in a nested branch,
2733 ** it may create a "new" old entry.
2736 if (uentry_isValid (old))
2740 uentry_mergeUses (current, old);
2741 uentry_setState (old, current);
2745 uentry_mergeState (old, current, exprNode_loc (sw),
2746 mustReturn, FALSE, TRUE, SWITCHCLAUSE);
2753 } end_usymtab_entries;
2756 ** if entry is not in symbol table for this case, merge with pre-switch
2760 if (!mustReturn && !mustBreak)
2762 usymtab_entries (stab, current)
2764 if (usymtab_getIndex (ttab, uentry_rawName (current)) == NOT_FOUND)
2766 uentry old = /*@-compmempass@*/
2767 usymtab_lookupAux (ltab, uentry_rawName (current));
2770 llassert (uentry_isValid (old));
2771 uentry_mergeState (old, current, exprNode_loc (sw),
2772 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2774 } end_usymtab_entries;
2777 ltab->env = ttab->env;
2781 ** Suprious error, becuase of environments.
2784 /*@i1@*/ utab = ltab;
2786 lastMustReturn = FALSE;
2793 ** now, there is one US_CBRANCH. Merge this with the stab.
2797 for (i = 0; i < ltab->nentries; i++)
2799 uentry current = ltab->entries[i];
2800 uentry old = usymtab_lookupAux (stab, uentry_rawName (current));
2802 /* note that is this is in a nested branch,
2803 it may create a "new" old entry. */
2806 if (uentry_isValid (old))
2810 uentry_mergeUses (current, old);
2811 uentry_setState (old, current);
2815 uentry_mergeState (old, current, exprNode_loc (sw),
2816 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2830 ** switch may or may not be followed by a new scope
2833 if (utab->kind == US_SWITCH)
2835 usymtab_quietPlainExitScope ();
2839 usymtab_quietPlainExitScope ();
2840 llassert (utab->kind == US_SWITCH);
2841 usymtab_quietPlainExitScope ();
2847 updateNullState (sRef el, /*@notnull@*/ usymtab ttab,
2848 /*@notnull@*/ usymtab ftab, bool trueGuard)
2850 sRef base = sRef_getRootBase (el);
2851 int level = sRef_lexLevel (base);
2853 if (sRef_isCvar (base))
2855 usymId index = sRef_getScopeIndex (base);
2856 uentry ue = usymtab_getRefTab (ttab, level, index);
2858 if (!uentry_isLset (ue))
2860 sRef sr = uentry_getSref (ue);
2864 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2868 if (!guardSet_isGuarded (ttab->guards, el)
2869 && !sRef_isNotNull (sr))
2871 sRef_setDerivNullState (sr, el, NS_DEFNULL);
2879 ue = usymtab_getRefTab (ftab, level, index);
2881 if (!uentry_isLset (ue))
2883 sRef sr = uentry_getSref (ue);
2886 if (!trueGuard) /* yikes! forgot the ! */
2888 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2893 if (!guardSet_isGuarded (ftab->guards, el)
2894 && !sRef_isNotNull (sr))
2896 sRef_setDerivNullState (sr, el, NS_DEFNULL);
2908 usymtab_popBranches (exprNode pred, exprNode tbranch, exprNode fbranch,
2909 bool isOpt, clause cl)
2913 usymtab ftab = utab;
2914 usymtab ttab = utab->env;
2918 guardSet guards = exprNode_getGuards (pred);
2919 sRefSet tguards = guardSet_getTrueGuards (guards);
2920 sRefSet fguards = guardSet_getFalseGuards (guards);
2921 bool mustReturnT = exprNode_mustEscape (tbranch);
2922 bool mustReturnF = exprNode_mustEscape (fbranch);
2924 DPRINTF (("Pop branches: %s [mustreturn: %s/%s]", exprNode_unparse (pred),
2925 bool_unparse (mustReturnT),
2926 bool_unparse (mustReturnF)));
2928 if (exprNode_isDefined (fbranch))
2930 loc = exprNode_loc (fbranch);
2934 loc = exprNode_loc (tbranch);
2937 llassert (usymtab_isDefined (ttab));
2941 llassert (usymtab_isDefined (env));
2942 llassert (ftab->kind == US_FBRANCH);
2943 llassert (ttab->kind == US_TBRANCH);
2946 ** For each element that is true guarded (i.e., if (x != NULL))
2947 ** make x = null in false branch,
2948 ** and x = notnull in true branch.
2949 ** unless x was set locally in that branch.
2950 ** For each element that is false guarded (x == NULL)
2951 ** make x = null in true, notnull in false.
2953 ** For each element that is either guarded (pred(x))
2957 sRefSet_allElements (tguards, el)
2959 updateNullState (el, ttab, ftab, TRUE);
2960 } end_sRefSet_allElements;
2962 sRefSet_allElements (fguards, el)
2964 updateNullState (el, ttab, ftab, FALSE);
2965 } end_sRefSet_allElements;
2969 ** if an entry is in both true and false, merge the entries,
2970 ** then replace original with new state.
2972 ** if an entry is in one table, merge it with the original.
2975 DPRINTF (("ftab: %d", ftab->nentries));
2977 for (i = 0; i < ftab->nentries; i++)
2979 uentry fthis = ftab->entries[i];
2980 uentry old = usymtab_lookupAux (env, uentry_rawName (fthis));
2981 int tindex = usymtab_getIndex (ttab, uentry_rawName (fthis));
2983 DPRINTF (("Entry: %s / %s", uentry_unparseFull (fthis), uentry_unparseFull (old)));
2985 if (uentry_isUndefined (old))
2987 /* possible entry was added as an undefined id */
2988 DPRINTF (("Undefined! %s", uentry_rawName (fthis)));
2992 if (tindex != NOT_FOUND)
2994 uentry tthis = ttab->entries[tindex];
2996 /* note that is this is in a nested branch,
2997 it may create a "new" old entry. */
3003 uentry_mergeState (fthis, tthis, loc,
3004 mustReturnT, FALSE, FALSE, cl);
3008 uentry_mergeUses (fthis, tthis);
3011 uentry_setState (old, fthis);
3018 uentry_setState (old, tthis);
3019 uentry_mergeState (old, fthis, loc, mustReturnF,
3023 ttab->entries[tindex] = uentry_undefined;
3024 uentry_free (tthis);
3028 uentry_mergeState (old, fthis, loc, mustReturnF, TRUE, FALSE, cl);
3032 for (i = 0; i < ttab->nentries; i++)
3034 uentry current = ttab->entries[i];
3036 DPRINTF (("ttab: %s", uentry_unparseFull (current)));
3038 if (!uentry_isUndefined (current))
3040 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
3042 DPRINTF (("Old: %s", uentry_unparseFull (old)));
3044 if (uentry_isUndefined (old))
3046 llcontbug (message ("Undefined entry: %s", uentry_rawName (current)));
3052 uentry_mergeUses (current, old);
3053 uentry_setState (old, current);
3058 ** Assumes false branch is a fall-through if
3059 ** fbranch is not defined. This is true, unless
3060 ** where was some greivous error in processing
3061 ** the else branch of an if-then, in which case
3062 ** this is probably the right thing to do anyway.
3065 uentry_mergeState (old, current, loc, mustReturnT,
3069 DPRINTF (("==> %s", uentry_unparseFull (old)));
3074 ** Plain levelUnion doesn't work, since we need to use the sRef's in env->aliases
3075 ** if they are present.
3078 llassert (NOALIAS (env->aliases, ttab->aliases));
3079 llassert (NOALIAS (env->aliases, ftab->aliases));
3081 aliasTable_free (env->aliases);
3083 env->aliases = aliasTable_levelUnionNew (ttab->aliases,
3084 ftab->aliases, env->lexlevel);
3086 aliasTable_fixSrefs (env->aliases);
3088 DPRINTF (("Aliases: %s", aliasTable_unparse (env->aliases)));
3090 /* exit true and false scopes */
3091 usymtab_quietPlainExitScope ();
3092 usymtab_quietPlainExitScope ();
3096 utab->guards = guardSet_levelUnionFree
3098 guardSet_invert (exprNode_getGuards (pred)),
3104 utab->guards = guardSet_levelUnion (utab->guards,
3105 exprNode_getGuards (pred),
3109 DPRINTF (("Here."));
3112 static void usymtab_fixCases (void) /*@modifies utab@*/ {
3113 while (utab->kind == US_CBRANCH)
3115 usymtab_quietPlainExitScope ();
3118 llassert (utab->kind != US_CBRANCH);
3122 usymtab_altBranch (/*@only@*/ guardSet guards)
3126 usymtab parent = utab->env;
3128 t = usymtab_create (US_FBRANCH, utab, FALSE);
3131 ** If we are in a case, need to close it. The C syntax
3132 ** is very liberal, so this kludge is necessary.
3135 usymtab_fixCases ();
3137 DPRINTF (("Current kind: %s", usymtab_unparseStack ()));
3139 llassert (utab->kind == US_TBRANCH);
3140 llassert (parent != GLOBAL_ENV);
3142 guardSet_free (t->guards);
3145 aliasTable_free (t->aliases);
3146 t->aliases = aliasTable_copy (parent->aliases);
3152 usymtab_allDefined (void)
3153 /*@globals utab, globtab@*/
3157 llassert (utab == globtab);
3159 for (i = 0; i < utab->nentries; i++)
3161 uentry e = utab->entries[i];
3163 if (uentry_isPriv (e))
3165 ; /* no need to define it */
3169 if (context_getFlag (FLG_SPECUNDECL))
3171 fileloc sloc = uentry_whereSpecified (e);
3172 fileloc dloc = uentry_whereDeclared (e);
3174 if (fileloc_isDefined (sloc)
3175 && !uentry_isFakeTag (e)
3176 && !fileloc_isDefined (dloc))
3180 message ("%s %q specified but not declared",
3181 ekind_capName (uentry_getKind (e)),
3182 uentry_getName (e)),
3187 if (!uentry_isCodeDefined (e))
3189 fileloc dloc = uentry_whereDeclared (e);
3191 if (fileloc_isLib (dloc) || fileloc_isXHFile (dloc))
3195 else if (fileloc_isDefined (dloc))
3197 if (!uentry_isAnyTag (e))
3199 if (fileloc_isUser (dloc))
3203 message ("%s %q declared but not defined",
3204 ekind_capName (uentry_getKind (e)),
3205 uentry_getName (e)),
3207 DPRINTF (("decl: %s", uentry_unparseFull (e)));
3213 fileloc sloc = uentry_whereSpecified (e);
3215 if (fileloc_isDefined (sloc)
3216 && !fileloc_isImport (sloc)
3217 && !fileloc_isLib (sloc)
3218 && !fileloc_isPreproc (sloc)
3219 && !uentry_isFakeTag (e))
3221 if (uentry_isVariable (e) || uentry_isFunction (e))
3225 message ("%s %q specified but not declared or defined",
3226 ekind_capName (uentry_getKind (e)),
3227 uentry_getName (e)),
3234 message ("%s %q specified but not defined",
3235 ekind_capName (uentry_getKind (e)),
3236 uentry_getName (e)),
3246 void usymtab_exportHeader (void)
3251 for (i = 0; i < utab->nentries; i++)
3253 uentry ce = utab->entries[i];
3255 if (!uentry_isDatatype (ce)
3256 && !uentry_isAnyTag (ce)
3257 && !uentry_isEitherConstant (ce) && !uentry_isStatic (ce)
3258 && !uentry_isExternal (ce)
3259 && !uentry_isForward (ce))
3261 fileloc fwhere = uentry_whereDeclared (ce);
3263 if (fileloc_isUndefined (fwhere)
3264 && uentry_isFunction (ce))
3266 fwhere = uentry_whereDefined (ce);
3269 if (fileloc_isDefined (fwhere)
3270 && !fileloc_isHeader (fwhere)
3271 && !fileloc_isXHFile (fwhere)
3272 && !(fileloc_isSpecialFile (fwhere)
3273 && !context_getFlag (FLG_UNUSEDSPECIAL)))
3275 if (uentry_isVariable (ce))
3278 (FLG_EXPORTHEADERVAR,
3279 message ("%s %q exported but not declared in header file",
3280 ekind_capName (uentry_getKind (ce)),
3281 uentry_getName (ce)),
3284 uentry_showDefSpecInfo (ce, fwhere);
3289 if (!uentry_isIter (ce)
3290 && !uentry_isEndIter (ce)
3291 && !uentry_isExpandedMacro (ce))
3293 if (uentry_isFunction (ce)
3294 && cstring_equalLit (uentry_rawName (ce), "main"))
3296 ; /* no error for main */
3302 message ("%s %q exported but not declared "
3304 ekind_capName (uentry_getKind (ce)),
3305 uentry_getName (ce)),
3308 uentry_showDefSpecInfo (ce, fwhere);
3318 void usymtab_exportLocal (void)
3323 for (i = 0; i < utab->nentries; i++)
3325 uentry ce = utab->entries[i];
3327 if (!uentry_isDatatype (ce) && !uentry_isAnyTag (ce)
3328 && !uentry_isEitherConstant (ce)
3329 && !uentry_isIter (ce)
3330 && !uentry_isEndIter (ce)
3331 && !uentry_isExpandedMacro (ce)
3332 && uentry_isUsed (ce))
3334 /* check static uses */
3335 filelocList fuses = uentry_getUses (ce);
3336 fileloc mod = uentry_whereDefined (ce);
3337 bool ok = filelocList_isEmpty (fuses);
3338 fileloc fwhere = uentry_whereDeclared (ce);
3340 if (fileloc_isSpecialFile (fwhere)
3341 && !context_getFlag (FLG_UNUSEDSPECIAL))
3343 ok = TRUE; /* no errors for special files */
3347 filelocList_elements (fuses, uloc)
3349 if (fileloc_isUndefined (uloc) || !fileloc_sameModule (uloc, mod))
3352 /*@innerbreak@*/ break;
3354 } end_filelocList_elements;
3361 message ("%s exported but not used outside %s: %q",
3362 ekind_capName (uentry_getKind (ce)),
3363 fileloc_getBase (mod),
3364 uentry_getName (ce)),
3367 uentry_showDefSpecInfo (ce, fwhere);
3375 usymtab_allUsed (void)
3379 bool isFileStatic = usymtab_inFileScope ();
3380 cstring last_file = cstring_undefined;
3382 for (i = 0; i < utab->nentries; i++)
3384 bool hasError = FALSE;
3385 uentry ce = utab->entries[i];
3386 fileloc fwhere = uentry_whereDeclared (ce);
3388 if (fileloc_isUndefined (fwhere))
3390 fwhere = uentry_whereDefined (ce);
3393 if (fileloc_isInvalid (fwhere)
3394 || fileloc_isLib (fwhere)
3395 || fileloc_isBuiltin (fwhere)
3396 || ((fileloc_isSpecialFile (fwhere)
3397 || fileloc_isSpecialFile (uentry_whereDefined (ce)))
3398 && !context_getFlag (FLG_UNUSEDSPECIAL)))
3402 else if (!uentry_wasUsed (ce) && !uentry_isAnyTag (ce))
3404 cstring fname = fileloc_filename (fwhere);
3406 if (cstring_isUndefined (last_file))
3410 else if (cstring_equal (fname, last_file))
3419 if (uentry_isParam (ce))
3421 if (context_inMacro ())
3423 sRef cref = uentry_getSref (ce);
3425 if (uentry_isYield (ce))
3427 ; /* no checks (for now) */
3429 else if (sRef_isSafe (cref))
3435 if (uentry_hasRealName (ce))
3438 optgenerror (FLG_MACROPARAMS,
3439 message ("Macro parameter %q not used",
3440 uentry_getName (ce)),
3447 if (cstring_equalFree (uentry_getName (ce),
3448 cstring_makeLiteral ("...")))
3454 hasError = optgenerror (FLG_PARAMUNUSED,
3455 message ("Parameter %q not used",
3456 uentry_getName (ce)),
3461 else if (uentry_isFunction (ce) || uentry_isIter (ce))
3463 if (fileloc_isUser (fwhere))
3465 hasError = optgenerror
3467 message ("%q %q declared but not used",
3469 (uentry_isIter (ce) ? "Iterator"
3470 : (isFileStatic ? "File static function" : "Function")),
3471 uentry_getName (ce)),
3475 else if (uentry_isEndIter (ce))
3477 ; /* no error (already reported for iter */
3479 else if (uentry_isEnumConstant (ce))
3481 if (fileloc_isUser (fwhere))
3483 hasError = optgenerror
3485 message ("Enum member %q not used",
3486 uentry_getName (ce)),
3490 else if (uentry_isConstant (ce))
3492 if (fileloc_isUser (fwhere))
3494 hasError = optgenerror
3496 message ("Constant %q declared but not used",
3497 uentry_getName (ce)),
3501 else if (uentry_isDatatype (ce))
3503 if (fileloc_isUser (fwhere))
3505 hasError = optgenerror
3507 message ("Type %q declared but not used",
3508 uentry_getName (ce)),
3512 else if (!uentry_isRefParam (ce) && !uentry_isExpandedMacro (ce))
3513 { /* errors for ref params will be reported in the next scope */
3514 llassertprint (uentry_isVar (ce),
3515 ("ce: %s", uentry_unparseFull (ce)));
3517 if (ctype_isFunction (uentry_getType (ce)))
3519 if (fileloc_isUser (fwhere))
3521 hasError = optgenerror
3523 message ("%q %q declared but not used",
3525 (isFileStatic ? "File static function"
3527 uentry_getName (ce)),
3533 if (fileloc_isUser (fwhere))
3537 hasError = optgenerror
3539 message ("%q %q declared but not used",
3541 (isFileStatic ? "File static variable"
3543 uentry_getName (ce)),
3553 else if ((uentry_isDatatype (ce) || uentry_isAnyTag (ce)))
3554 { /* check all fields */
3555 ctype ct = uentry_getRealType (ce);
3558 while (ctype_isAP (ct))
3560 ct = ctype_getBaseType (ct);
3563 if (ctype_isSU (ct))
3565 uentryList fields = ctype_getFields (ct);
3567 uentryList_elements (fields, field)
3569 if (!uentry_isUsed (field))
3571 if (uentry_hasName (ce))
3573 hasError |= optgenerror
3575 message ("Field %q of %s %q declared but not used",
3576 uentry_getName (field),
3577 cstring_makeLiteralTemp
3578 (ctype_isStruct (ct) ? "structure" : "union"),
3579 uentry_getName (ce)),
3580 uentry_whereEarliest (field));
3586 ** Can't report these errors for unnamed structs.
3587 ** No way to tell when there are multiple consistent
3588 ** unnamed structure types. (Could go through table
3589 ** and mark them all unused...)
3591 hasError |= optgenerror
3593 message ("Field %q of unnamed %s declared but not used",
3594 uentry_getName (field),
3595 cstring_makeLiteralTemp
3596 (ctype_isStruct (ct) ? "structure" : "union")),
3597 uentry_whereEarliest (field));
3602 uentry_setUsed (field, fileloc_undefined);
3604 } end_uentryList_elements;
3614 if (uentry_isParam (ce) && context_inMacro ())
3616 if (fileloc_isDefined (uentry_whereSpecified (ce)))
3618 uentry_showWhereSpecified (ce);
3623 uentry_showDefSpecInfo (ce, fwhere);
3626 uentry_setUsed (ce, fileloc_undefined);
3632 checkGlobalReturn (uentry glob, sRef orig)
3634 sRef sr = uentry_getSref (glob);
3636 DPRINTF (("Check global return: %s / orig: %s / sr: %s",
3637 uentry_unparseFull (glob),
3638 sRef_unparseFull (orig),
3639 sRef_unparseFull (sr)));
3641 DPRINTF (("Is killed: %s", bool_unparse (sRef_isKilledGlob (orig))));
3643 if (context_getFlag (FLG_GLOBSTATE))
3645 DPRINTF (("Is killed: %s", sRef_unparseFull (orig)));
3647 if (sRef_isKilledGlob (orig))
3649 if (sRef_isStateUndefined (sr)
3650 || sRef_isUnuseable (sr)
3651 || sRef_isStateUnknown (sr)
3652 || sRef_isDead (sr))
3658 ctype ct = ctype_realType (uentry_getType (glob));
3660 if (ctype_isVisiblySharable (ct))
3665 ("Killed global %q (type %s) not released before return",
3666 uentry_getName (glob),
3667 ctype_unparse (ct)),
3670 sRef_showStateInfo (sr);
3675 sRef_protectDerivs ();
3676 (void) checkGlobalDestroyed (sr, g_currentloc);
3677 sRef_clearProtectDerivs ();
3683 if (sRef_isStateUndefined (sr))
3685 if (optgenerror (FLG_GLOBSTATE,
3687 ("Function returns with global %q undefined",
3688 uentry_getName (glob)),
3691 sRef_showStateInfo (sr);
3696 if (sRef_isDead (sr) || sRef_isKept (sr))
3700 message ("Function returns with global %q "
3701 "referencing %s storage",
3702 uentry_getName (glob),
3703 cstring_makeLiteralTemp (sRef_isDead (sr) ? "released" : "kept")),
3706 if (sRef_isKept (sr))
3708 sRef_showAliasInfo (sr);
3712 sRef_showStateInfo (sr);
3715 sRef_setDefState (sr, SS_UNKNOWN, fileloc_undefined);
3719 if (ctype_isRealPointer (uentry_getType (glob))
3720 && sRef_possiblyNull (sr)
3721 && !uentry_possiblyNull (glob))
3725 message ("Function returns with non-null global %q "
3726 "referencing null storage",
3727 uentry_getName (glob)),
3730 sRef_showNullInfo (sr);
3735 checkGlobReturn (glob);
3743 ** remember: check alias globals
3746 void usymtab_checkFinalScope (bool isReturn)
3749 bool mustFree = context_getFlag (FLG_MUSTFREE);
3750 bool mustDefine = context_getFlag (FLG_MUSTDEFINE);
3751 /* bool mustNotAlias = context_getFlag (FLG_MUSTNOTALIAS); */
3752 sRefSet checked = sRefSet_new ();
3753 usymtab stab = utab;
3757 ** need to check all scopes out to function parameters.
3762 for (i = 0; i < stab->nentries; i++)
3764 uentry ce = stab->entries[i];
3765 sRef sr = uentry_getSref (ce);
3766 sRef rb = sRef_getRootBase (sr);
3770 ** Shouldn't check if shadow checked in deeper scope:
3775 uentry oue = usymtab_lookupQuietNoAlt (utab, uentry_observeRealName (ce));
3777 if (!uentry_sameObject (ce, oue))
3779 DPRINTF (("Skipping outer entry: %s / %s", uentry_unparseFull (ce),
3780 uentry_unparseFull (oue)));
3781 /*@i32 what if it is one an alternate branch? */
3782 /*@innercontinue@*/ continue;
3786 DPRINTF (("Here check final scope: %s", uentry_unparseFull (ce)));
3788 if (ctype_isFunction (uentry_getType (ce)))
3790 /*@innercontinue@*/ continue;
3793 if (uentry_isAnyParam (ce)
3794 || uentry_isRefParam (ce)
3795 || sRef_isFileOrGlobalScope (rb))
3797 /* Don't do the loseref check...but should check state! */
3799 else if (sRef_isDefinitelyNull (sr)
3800 || usymtab_isDefinitelyNull (sr))
3803 ** No state reference errors for definitely null references.
3808 DPRINTF (("Lose ref: %s / %s", uentry_unparse (ce),
3809 sRef_unparseFull (sr)));
3811 tvalues = sRef_getValueTable (sr);
3813 valueTable_elements (tvalues, fkey, fval) {
3814 metaStateInfo minfo;
3815 cstring msg = cstring_undefined;
3818 minfo = context_lookupMetaStateInfo (fkey);
3819 llassert (metaStateInfo_isDefined (minfo));
3821 if (stateValue_isError (fval)
3822 || sRef_isStateUndefined (sr)) /* No errors for undefined state */
3828 DPRINTF (("Check: %s / %s / %s", fkey,
3829 metaStateInfo_unparse (minfo),
3830 stateValue_unparse (fval)));
3832 minfo = context_lookupMetaStateInfo (fkey);
3834 nval = stateCombinationTable_lookupLoseReference
3835 (metaStateInfo_getTransferTable (minfo),
3836 stateValue_getValue (fval), &msg);
3838 if (cstring_isDefined (msg))
3840 /*@i32 print extra info for assignments@*/
3841 DPRINTF (("From: %s", sRef_unparseFull (sr)));
3842 DPRINTF (("Null? %s / %s",
3843 bool_unparse (sRef_isDefinitelyNull (sr)),
3844 bool_unparse (usymtab_isGuarded (sr))));
3849 ("%s loses reference %q in invalid state %q (%s)",
3850 cstring_makeLiteralTemp (isReturn ? "Return" : "Scope exit"),
3851 uentry_getName (ce),
3852 stateValue_unparseValue (fval, minfo),
3856 stateValue_show (fval, minfo);
3860 DPRINTF (("Suppressed transfer error: %s", msg));
3864 } end_valueTable_elements;
3869 DPRINTF (("Check entry: %s", uentry_unparseFull (ce)));
3871 if (!sRefSet_member (checked, sr) && !sRef_isFileOrGlobalScope (rb))
3873 if (ctype_isRealSU (uentry_getType (ce))
3874 && !uentry_isAnyParam (ce)
3875 && !uentry_isRefParam (ce)
3876 && !uentry_isStatic (ce)
3877 && !sRef_isDependent (sr)
3878 && !sRef_isOwned (sr))
3880 sRefSet als = usymtab_allAliases (sr);
3882 if (sRefSet_isEmpty (als))
3884 checkLocalDestroyed (sr, g_currentloc);
3888 /* aliased, no problem */ ;
3894 (!uentry_isStatic (ce)
3895 && ((sRef_isNewRef (sr))
3896 || (((sRef_isOnly (sr) || sRef_isFresh (sr)
3897 || sRef_isKeep (sr) || sRef_isOwned (sr))
3898 && !sRef_isDead (sr))
3899 && (!sRef_definitelyNull (sr))
3900 && (!usymtab_isDefinitelyNull (sr)))))
3902 bool hasError = TRUE;
3904 DPRINTF (("Checking: %s", sRef_unparseFull (sr)));
3907 ** If its a scope exit, check if there is an alias.
3908 ** If so, make it only. If not, there is an error.
3913 if (canLoseReference (sr, g_currentloc))
3915 DPRINTF (("Can lose!"));
3922 if (sRef_hasLastReference (sr))
3924 sRef ar = sRef_getAliasInfoRef (sr);
3929 ("Last reference %q to %s storage %qnot %q before %q",
3931 alkind_unparse (sRef_getAliasKind (sr)),
3932 sRef_unparseOpt (ar),
3933 cstring_makeLiteral (sRef_isKeep (sr)
3934 ? "transferred" : "released"),
3935 cstring_makeLiteral (isReturn
3936 ? "return" : "scope exit")),
3939 sRef_showRefLost (sr);
3942 else if (sRef_isNewRef (sr))
3947 ("%q %q not released before %q",
3949 (alkind_isKillRef (sRef_getOrigAliasKind (sr))
3950 ? "Kill reference parameter" : "New reference"),
3951 uentry_getName (ce),
3952 cstring_makeLiteral (isReturn
3953 ? "return" : "scope exit")),
3956 sRef_showAliasInfo (sr);
3961 if (ctype_isRealSU (sRef_getType (sr)))
3963 checkStructDestroyed (sr, g_currentloc);
3967 DPRINTF (("Here we are: %s", sRef_unparseFull (sr)));
3972 ("%s storage %q not %q before %q",
3973 alkind_capName (sRef_getAliasKind (sr)),
3974 uentry_getName (ce),
3975 cstring_makeLiteral (sRef_isKeep (sr)
3976 ? "transferred" : "released"),
3977 cstring_makeLiteral (isReturn
3978 ? "return" : "scope exit")),
3981 sRef_showAliasInfo (sr);
3982 DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
3993 else if (mustDefine && uentry_isOut (ce))
3995 if (!ynm_toBoolStrict (sRef_isReadable (sr)))
3999 message ("Out storage %q not defined before %q",
4000 uentry_getName (ce),
4002 (isReturn ? "return" : "scope exit")),
4005 /* uentry_showWhereDeclared (ce); */
4014 ** also check state is okay
4017 if (usymtab_lexicalLevel () > functionScope
4018 && uentry_isVariable (ce)
4019 && (sRef_isLocalVar (sr)
4020 && (sRef_isDependent (sr) || sRef_isLocalState (sr))))
4022 sRefSet ab = usymtab_aliasedBy (sr);
4024 /* should do something more efficient here */
4026 if (sRefSet_isEmpty (ab))
4028 /* and no local ref */
4029 DPRINTF (("Check lose ref: %s", uentry_unparseFull (ce)));
4044 checked = sRefSet_insert (checked, sr);
4048 llassert (usymtab_isDefined (stab->env));
4050 if (usymtab_isBranch (stab))
4052 stab = usymtab_dropEnv (stab);
4059 llassert (stab != usymtab_undefined);
4060 } while (isReturn && (stab->lexlevel >= paramsScope));
4062 sRefSet_free (checked);
4066 ** all globals are appropriately defined
4067 ** all parameters are appropriately defined
4068 ** special clauses are followed
4071 if (isReturn || (utab->lexlevel == paramsScope))
4073 uentry fcn = context_getHeader ();
4074 uentryList params = context_getParams ();
4075 globSet uglobs = context_getUsedGlobs ();
4076 globSet sglobs = context_getGlobs ();
4078 if (isReturn && context_maybeSet (FLG_GLOBALIAS))
4080 aliasTable_checkGlobs (utab->aliases);
4084 ** state clauses (ensures, defines, sets, allocates, releases)
4087 if (uentry_hasStateClauseList (fcn))
4089 stateClauseList clauses = uentry_getStateClauseList (fcn);
4091 stateClauseList_elements (clauses, cl)
4093 if (stateClause_isAfter (cl) && !stateClause_isGlobal (cl))
4095 if (stateClause_setsMetaState (cl))
4097 sRefSet rfs = stateClause_getRefs (cl);
4098 qual q = stateClause_getMetaQual (cl);
4099 annotationInfo ainfo = qual_getAnnotationInfo (q);
4100 metaStateInfo minfo = annotationInfo_getState (ainfo);
4101 cstring key = metaStateInfo_getName (minfo);
4102 int mvalue = annotationInfo_getValue (ainfo);
4104 DPRINTF (("Post meta state clause: %s", stateClause_unparse (cl)));
4106 sRefSet_elements (rfs, el)
4108 sRef base = sRef_getRootBase (el);
4110 if (sRef_isResult (base))
4113 ** This is checked for return transfers.
4117 else if (sRef_isParam (base) || sRef_isGlobalMarker (base))
4119 sRef sr = sRef_updateSref (base);
4120 sr = sRef_fixBase (el, sr);
4122 if (!sRef_checkMetaStateValue (sr, key, mvalue))
4127 ("Ensures clause not satisfied%q (state is %q): %q",
4128 sRef_isGlobalMarker (sr)
4130 : message (" by %q", sRef_unparse (sr)),
4131 stateValue_unparseValue (sRef_getMetaStateValue (sr, key),
4133 stateClause_unparse (cl)),
4136 sRef_showMetaStateInfo (sr, key);
4142 if (sRef_isMeaningful (el))
4147 } end_sRefSet_elements ;
4151 /* evs - 2000 07 10 - added this */
4152 sRefTest tst = stateClause_getPostTestFunction (cl);
4153 sRefSet rfs = stateClause_getRefs (cl);
4155 sRefSet_elements (rfs, el)
4157 sRef base = sRef_getRootBase (el);
4159 if (sRef_isResult (base))
4162 ** This is checked for return transfers.
4167 else if (sRef_isParam (base))
4169 sRef sr = sRef_updateSref (base);
4170 sr = sRef_fixBase (el, sr);
4172 if (tst != NULL && !tst (sr))
4175 (stateClause_postErrorCode (cl),
4176 message ("%s storage %qcorresponds to "
4177 "storage listed in %q clause",
4178 stateClause_postErrorString (cl, sr),
4179 sRef_unparseOpt (sr),
4180 stateClause_unparseKind (cl)),
4183 sRefShower ss = stateClause_getPostTestShower (cl);
4190 DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
4196 if (sRef_isMeaningful (el))
4201 } end_sRefSet_elements ;
4204 } end_stateClauseList_elements ;
4208 ** check parameters on return
4211 uentryList_elements (params, arg)
4213 if (!uentry_isElipsisMarker (arg))
4215 ctype rt = ctype_realType (uentry_getType (arg));
4217 if (ctype_isMutable (rt) || ctype_isSU (rt))
4219 uentry param = usymtab_lookupQuiet (utab, uentry_rawName (arg));
4220 DPRINTF (("Check param return: %s", uentry_unparseFull (param)));
4221 checkParamReturn (param);
4224 } end_uentryList_elements;
4226 DPRINTF (("Check global return: %s",
4227 globSet_unparse (sglobs)));
4229 globSet_allElements (sglobs, el)
4231 sRef orig = el; /*! sRef_updateSref (el); */ /*!!!*/
4232 uentry current = sRef_getUentry (el);
4234 DPRINTF (("Check global return: %s / %s", sRef_unparseFull (el),
4235 uentry_unparseFull (current)));
4237 if (uentry_isVariable (current) && !uentry_isRealFunction (current))
4239 checkGlobalReturn (current, orig);
4241 } end_globSet_allElements;
4243 globSet_allElements (uglobs, el)
4245 if (!globSet_member (sglobs, el))
4247 uentry current = sRef_getUentry (el);
4249 if (uentry_isVariable (current)
4250 && !uentry_isRealFunction (current))
4252 checkGlobalReturn (current, sRef_undefined);
4255 } end_globSet_allElements;
4260 usymtab_quietExitScope (fileloc loc)
4261 /*@globals utab, globtab, filetab; @*/
4264 usymtab t = utab->env;
4266 if (utab->reftable != NULL)
4270 for (i = 0; i < utab->nentries; i++)
4272 uentry current = utab->entries[i];
4273 uentry old = usymtab_lookupAux (t, uentry_rawName (current));
4275 uentry_mergeState (old, current, loc, FALSE, FALSE, FALSE, NOCLAUSE);
4279 llassert (t != NULL);
4281 if (t->lexlevel > paramsScope)
4283 t->guards = guardSet_levelUnion (t->guards, utab->guards, t->lexlevel);
4284 t->aliases = aliasTable_levelUnionSeq (t->aliases, utab->aliases,
4286 utab->aliases = aliasTable_undefined;
4289 t->mustBreak = utab->mustBreak;
4290 t->exitCode = utab->exitCode;
4292 usymtab_freeLevel (utab);
4298 ** Exit a scope with no checking, lose alias states.
4299 ** (When should this be used?)
4302 void usymtab_quietPlainExitScope (void)
4303 /*@globals utab, globtab, filetab@*/
4306 usymtab t = utab->env;
4308 llassert (t != NULL);
4309 llassert (NOALIAS (utab->aliases, t->aliases));
4310 usymtab_freeLevel (utab);
4314 void usymtab_exitScope (exprNode expr)
4315 /*@globals utab, filetab, globtab@*/
4316 /*@modifies utab, globtab@*/
4318 usymtab ctab = usymtab_undefined;
4319 usymtab lctab = usymtab_undefined;
4320 bool mustReturn = exprNode_mustEscape (expr);
4322 DPRINTF (("Exit scope"));
4324 if (utab->kind == US_CBRANCH)
4327 ** save the case branches, remove the first non-cbranch
4332 while (utab->kind == US_CBRANCH)
4336 llassert (utab != GLOBAL_ENV);
4340 if (utab->kind == US_TBRANCH || utab->kind == US_FBRANCH
4341 || utab->kind == US_CBRANCH || utab->kind == US_SWITCH) {
4343 if (context_inMacro ()) {
4344 /* evs 2000-07-25 */
4345 /* Unparseable macro may end inside nested scope. Deal with it. */
4347 llerror (FLG_SYNTAX,
4348 message ("Problem parsing macro body of %s (unbalanced scopes). "
4349 "Attempting to recover, recommend /*@notfunction@*/ before "
4350 "macro definition.",
4351 context_inFunctionName ()));
4353 while (utab->kind == US_TBRANCH
4354 || utab->kind == US_FBRANCH
4355 || utab->kind == US_CBRANCH
4356 || utab->kind == US_SWITCH)
4359 llassert (utab != GLOBAL_ENV);
4362 llcontbug (message ("exitScope: in branch: %q", usymtab_unparseStack ()));
4364 } /*@=branchstate@*/
4368 ** check all variables in scope were used
4372 ** bogus errors if this is the normal inside a switch,
4373 ** since cases have not been merged yet. Should probably
4374 ** still check this, but I'm too lazy at the moment...
4377 llassertfatal (utab->env != GLOBAL_ENV);
4379 if (utab->env->kind != US_SWITCH)
4385 ** check aliasing: all only params are released (dead)
4386 ** definition: all out params are defined, all modified params
4387 ** are completely defined
4389 ** NOTE: note for exiting paramsScope, since checkReturn should be
4393 if (!mustReturn && (usymtab_lexicalLevel () > functionScope))
4396 ** should only call this is end of scope is reachable...
4399 usymtab_checkFinalScope (FALSE);
4402 if (usymtab_lexicalLevel () == paramsScope && context_inFunctionLike ())
4405 ** leaving a function, need to fix up globals
4408 uentryList params = context_getParams ();
4409 globSet globs = context_getUsedGlobs ();
4412 uentryList_elements (params, ue)
4414 uentry_fixupSref (ue);
4415 } end_uentryList_elements;
4417 clearFunctionTypes ();
4420 globSet_allElements (globs, el)
4422 if (sRef_isCvar (el))
4425 int index = sRef_getScopeIndex (el);
4427 if (sRef_isFileStatic (el))
4429 llassert (usymtab_isDefined (filetab));
4430 current = usymtab_fetchIndex (filetab, index);
4434 current = usymtab_fetchIndex (globtab, index);
4437 if (uentry_isVariable (current))
4439 uentry_fixupSref (current);
4443 sRef_clearDerived (uentry_getSref (current));
4446 } end_globSet_allElements;
4449 usymtab_quietExitScope (exprNode_loc (expr));
4451 if (lctab != usymtab_undefined)
4453 /*@i@*/ lctab->env = utab;
4454 /*@i@*/ utab = ctab;
4455 /*@-branchstate@*/ } /*@=branchstate@*/
4461 ** yikes! don't let the '170 kids see this one...
4465 uentry_directParamNo (uentry ue)
4467 if (uentry_isVar (ue))
4469 sRef sr = uentry_getSref (ue);
4471 if (sRef_lexLevel (sr) == functionScope)
4476 llassert (sr->info != NULL);
4477 llassert (sr->info->cvar != NULL);
4478 index = sr->info->cvar->index;
4481 if (index < uentryList_size (context_getParams ()))
4490 /*@dependent@*/ /*@exposed@*/ uentry
4491 usymtab_getParam (int paramno)
4495 ** requires in a function context (checked)
4497 ** depends on no nested functions --- the function
4498 ** parameters are ALWAYS one scope inside the global scope
4499 ** and entered in order!
4503 if (!context_inFunctionLike ())
4504 llfatalbug (message ("usymtab_getParam: not in function context: %q",
4505 context_unparse ()));
4507 while (s->lexlevel > paramsScope)
4512 llassert (usymtab_isDefined (s));
4514 if (paramno >= s->nentries)
4517 ** Parse errors lead to this.
4520 uentry err = uentry_makeVariableLoc (cstring_makeLiteralTemp ("<error>"),
4523 uentry_markOwned (err);
4527 return (s->entries[paramno]);
4530 static /*@dependent@*/ /*@exposed@*/ uentry
4531 usymtab_getRefTab (/*@notnull@*/ usymtab u, int level, usymId index)
4535 ue = usymtab_getRefNoisy (u, level, index);
4537 if (uentry_isUndefined (ue))
4539 llbug (message ("usymtab_getRef: out of range: %d. level = %d",
4546 static /*@dependent@*/ /*@exposed@*/ usymtab
4547 usymtab_dropEnv (/*@notnull@*/ usymtab s)
4549 if (s->kind == US_CBRANCH)
4557 llassert (s != GLOBAL_ENV);
4558 } while (s->kind == US_CBRANCH);
4559 /* drop all cases (except in nested scopes */
4562 llassert (s != GLOBAL_ENV);
4565 if (s->kind == US_FBRANCH)
4567 s = s->env; /* skip the true branch */
4568 llassert (usymtab_isDefined (s));
4569 llassert (s->kind == US_TBRANCH);
4572 llassert (s != GLOBAL_ENV);
4578 /*@dependent@*/ /*@exposed@*/ uentry
4579 usymtab_getRefQuiet (int level, usymId index)
4585 llassert (s != NULL);
4586 llassert (index >= 0);
4588 if (level > s->lexlevel)
4590 return uentry_undefined;
4593 llassertprint (level <= s->lexlevel, ("level: %d / lexlevel: %d",
4594 level, s->lexlevel));
4596 while (s->lexlevel > level)
4598 if (usymtab_isBranch (s))
4600 int eindex = refTable_lookup (s, level, index);
4602 if (eindex != NOT_FOUND)
4604 return (s->entries[eindex]);
4608 s = usymtab_dropEnv (s);
4611 while (usymtab_isBranch (s) && s->lexlevel == level)
4613 int eindex = refTable_lookup (s, level, index);
4615 if (eindex != NOT_FOUND)
4617 return (s->entries[eindex]);
4620 s = usymtab_dropEnv (s);
4623 if (index >= s->nentries)
4625 return uentry_undefined;
4628 llassert (!uentry_isUndefined (s->entries[index]));
4630 return s->entries[index];
4633 static /*@dependent@*/ /*@exposed@*/ uentry
4634 usymtab_getRefNoisy (/*@notnull@*/ usymtab s, int level, usymId index)
4637 uentry ue = uentry_undefined;
4639 llassert (index >= 0);
4641 while (s->lexlevel > level)
4643 if (usymtab_isBranch (s))
4645 int eindex = refTable_lookup (s, level, index);
4647 if (eindex != NOT_FOUND)
4649 ue = s->entries[eindex];
4653 while (!usymtab_isBranch (otab))
4655 otab = usymtab_dropEnv (otab);
4656 llassert (otab != GLOBAL_ENV);
4659 if (refTable_lookup (otab, level, index) == NOT_FOUND)
4661 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4673 s = usymtab_dropEnv (s);
4676 llassert (usymtab_isDefined (s));
4678 while (usymtab_isBranch (s) && s->lexlevel == level)
4680 int eindex = refTable_lookup (s, level, index);
4683 if (eindex != NOT_FOUND)
4685 ue = s->entries[eindex];
4689 while (!usymtab_isBranch (otab))
4691 otab = usymtab_dropEnv (otab);
4692 llassert (otab != GLOBAL_ENV);
4695 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4705 s = usymtab_dropEnv (s);
4708 if (s->lexlevel == level && (index < s->nentries))
4710 ue = s->entries[index];
4712 if (uentry_isValid (ue))
4716 while (!usymtab_isBranch (otab))
4718 otab = usymtab_dropEnv (otab);
4720 if (otab == GLOBAL_ENV)
4726 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4737 if (index >= s->nentries)
4739 return uentry_undefined;
4742 llassert (!uentry_isUndefined (s->entries[index]));
4744 return s->entries[index];
4748 ** looking up entries
4750 ** If entry is inside a branch, then copy it, and put it into
4751 ** the branch table.
4755 int refTable_lookup (/*@notnull@*/ usymtab ut, int level, int index)
4757 refTable rt = ut->reftable;
4760 llassert (rt != NULL);
4762 for (i = 0; i < ut->nentries; i++)
4764 if (rt[i]->level == level && rt[i]->index == index)
4774 /*@only@*/ refentry refentry_create (int level, int index)
4776 refentry r = (refentry) dmalloc (sizeof (*r));
4784 static /*@dependent@*/ /*@exposed@*/ uentry
4785 usymtab_addRefEntry (/*@notnull@*/ usymtab s, cstring k)
4790 if (ut->reftable == NULL)
4792 DPRINTF (("Adding ref entry without reftable: %s", k));
4793 return uentry_undefined;
4796 llassert (ut->reftable != NULL);
4798 while (s != GLOBAL_ENV)
4800 eindex = usymtab_getIndex (s, k);
4802 if (eindex != NOT_FOUND)
4804 uentry current = s->entries[eindex];
4806 if (uentry_isVar (current) && !ctype_isFunction (uentry_getType (current)))
4810 DPRINTF (("Here: copying %s", uentry_unparse (current)));
4811 ue = uentry_copy (current);
4812 DPRINTF (("Here: copying %s", uentry_unparse (ue)));
4813 usymtab_addEntryQuiet (ut, ue);
4814 DPRINTF (("Okay..."));
4816 if (s->reftable != NULL)
4818 refentry ref = s->reftable[eindex];
4820 ut->reftable[ut->nentries - 1]
4821 = refentry_create (ref->level, ref->index);
4825 ut->reftable[ut->nentries - 1]
4826 = refentry_create (s->lexlevel, eindex);
4837 s = usymtab_dropEnv (s);
4840 return uentry_undefined;
4843 static uentry usymtab_lookupAux (usymtab s, cstring k)
4845 DPRINTF (("Lookup: %s", k));
4847 while (s != GLOBAL_ENV)
4849 int eindex = usymtab_getIndex (s, k);
4851 if (eindex != NOT_FOUND)
4853 uentry ret = s->entries[eindex];
4857 if (s->kind == US_TBRANCH
4858 || s->kind == US_FBRANCH
4859 || s->kind == US_CBRANCH)
4860 /* uentry_isGlobalVariable (ret) && os->lexlevel > fileScope) */
4863 DPRINTF (("Adding global ref entry: %s", k));
4864 ret = usymtab_addRefEntry (os, k);
4865 DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
4870 DPRINTF (("Found: %s", uentry_unparseFull (ret)));
4874 if (s->kind == US_TBRANCH || s->kind == US_FBRANCH
4875 || s->kind == US_CBRANCH)
4877 /* why isn't this os??? */
4878 uentry ret = usymtab_addRefEntry (s, k);
4879 DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
4886 return uentry_undefined;
4889 static /*@dependent@*/ /*@exposed@*/ uentry
4890 usymtab_lookupQuietAux (usymtab s, cstring k, bool noalt)
4894 while (s != GLOBAL_ENV)
4896 eindex = usymtab_getIndex (s, k);
4898 if (eindex != NOT_FOUND)
4900 uentry ret = s->entries[eindex];
4904 if (noalt && usymtab_isBranch (s))
4906 s = usymtab_dropEnv (s);
4914 return uentry_undefined;
4917 static /*@exposed@*/ /*@dependent@*/ uentry
4918 usymtab_lookupQuiet (usymtab s, cstring k)
4920 return usymtab_lookupQuietAux (s, k, FALSE);
4923 static /*@exposed@*/ /*@dependent@*/ uentry
4924 usymtab_lookupQuietNoAlt (usymtab s, cstring k)
4926 return usymtab_lookupQuietAux (s, k, TRUE);
4929 /*@dependent@*/ /*@observer@*/ uentry
4930 usymtab_lookupSafe (cstring k)
4933 DPRINTF (("Lookup safe: %s", k));
4934 return (usymtab_lookupAux (utab, k));
4938 usymtab_lookupExpose (cstring k)
4941 uentry ce = usymtab_lookupAux (utab, k);
4943 if (uentry_isUndefined (ce))
4945 llfatalbug (message ("usymtab_lookup: not found: *%s*", k));
4948 if (uentry_isPriv (ce))
4950 llfatalbug (message ("usymtab_lookup: private: *%s*", k));
4956 uentry usymtab_lookupExposeGlob (cstring k)
4958 return (usymtab_lookupGlobSafe (k));
4961 uentry usymtab_lookupGlob (cstring k)
4962 /*@globals globtab@*/
4964 uentry ce = usymtab_lookupAux (globtab, k);
4966 if (uentry_isUndefined (ce))
4967 llfatalbug (message ("usymtab_lookup: not found: %s", k));
4969 if (uentry_isPriv (ce))
4970 llfatalbug (message ("usymtab_lookup: private: %s", k));
4975 /*@observer@*/ uentry
4976 usymtab_lookupGlobSafe (cstring k)
4977 /*@globals globtab@*/
4979 uentry ce = usymtab_lookupAux (globtab, k);
4984 uentry usymtab_lookupEither (cstring k)
4987 uentry ce = usymtab_lookupSafe (k);
4989 if (uentry_isUndefined (ce))
4990 llfatalerror (message ("usymtab_lookup: not found: %s", k));
4997 usymtab_lookupType (cstring k)
4998 /*@globals globtab@*/
5000 usymId uid = usymtab_getTypeId (k);
5002 if (uid == USYMIDINVALID)
5004 llcontbug (message ("usymtab_lookupType: not found: %s", k));
5005 return ctype_unknown;
5008 return (uentry_getRealType (usymtab_getTypeEntry (uid)));
5013 usymtab_lookupAbstractType (cstring k) /*@globals globtab@*/
5015 usymId uid = usymtab_getTypeId (k);
5017 if (uid == USYMIDINVALID)
5019 llcontbug (message ("usymtab_lookupType: not found: %s", k));
5020 return ctype_unknown;
5023 return (uentry_getAbstractType (usymtab_getTypeEntry (uid)));
5027 ** if there is an unnamed lcl-specified struct tag matching
5028 ** the uentryList, return its datatype. Otherwise, returns
5033 usymtab_structFieldsType (uentryList f)
5034 /*@globals globtab@*/
5036 return (usymtab_suFieldsType (f, TRUE));
5040 usymtab_unionFieldsType (uentryList f)
5041 /*@globals globtab@*/
5043 return (usymtab_suFieldsType (f, FALSE));
5047 usymtab_suFieldsType (uentryList f, bool isStruct)
5048 /*@globals globtab@*/
5052 DPRINTF (("Fields: %s", uentryList_unparse (f)));
5054 if (fileloc_isSpec (g_currentloc))
5056 return (ctype_undefined);
5059 for (i = 0; i < globtab->nentries; i++)
5061 uentry current = globtab->entries[i];
5064 ? uentry_isStructTag (current) : uentry_isUnionTag (current)))
5066 if (isFakeTag (uentry_rawName (current)))
5068 ctype ct = uentry_getType (current);
5070 DPRINTF (("Check: %s", ctype_unparse (ct)));
5072 if ((isStruct ? ctype_isStruct (ct) : ctype_isUnion (ct))
5074 (uentry_isSpecified (current)
5075 && uentryList_equivFields (f, ctype_getFields (ct))))
5077 return uentry_getAbstractType (current);
5087 return ctype_undefined;
5091 usymtab_enumEnumNameListType (enumNameList f)
5092 /*@globals globtab@*/
5096 for (i = 0; i < globtab->nentries; i++)
5098 uentry current = globtab->entries[i];
5100 if (uentry_isEnumTag (current))
5102 if (isFakeTag (uentry_rawName (current)))
5104 ctype ct = uentry_getType (current);
5106 if (ctype_isEnum (ct) && (enumNameList_match (f, ctype_elist (ct))))
5108 return uentry_getType (current);
5114 return ctype_undefined;
5118 usymtab_exists (cstring k)
5121 uentry ce = usymtab_lookupSafe (k);
5122 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5126 usymtab_existsReal (cstring k)
5129 uentry ce = usymtab_lookupSafe (k);
5131 return (!(uentry_isUndefined (ce))
5132 && !(uentry_isPriv (ce))
5133 && !(uentry_isExpandedMacro (ce)));
5137 usymtab_existsGlob (cstring k)
5138 /*@globals globtab@*/
5140 uentry ce = usymtab_lookupAux (globtab, k);
5142 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5147 usymtab_existsEither (cstring k)
5150 uentry ce = usymtab_lookupAux (utab, k);
5152 return (uentry_isValid (ce));
5156 usymtab_existsGlobEither (cstring k)
5157 /*@globals globtab@*/
5159 uentry ce = usymtab_lookupAux (globtab, k);
5161 return (uentry_isValid (ce));
5166 usymtab_existsType (cstring k)
5167 /*@globals globtab@*/
5169 uentry ce = usymtab_lookupAux (globtab, k);
5171 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && uentry_isDatatype (ce));
5175 usymtab_existsTypeEither (cstring k)
5176 /*@globals globtab@*/
5179 ce = usymtab_lookupAux (globtab, k);
5180 return (uentry_isValid (ce) && uentry_isDatatype (ce));
5184 usymtab_existsStructTag (cstring k) /*@globals globtab@*/
5186 cstring sname = makeStruct (k);
5187 uentry ce = usymtab_lookupAux (globtab, sname);
5188 cstring_free (sname);
5189 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5193 usymtab_existsUnionTag (cstring k) /*@globals globtab@*/
5195 cstring uname = makeUnion (k);
5196 uentry ce = usymtab_lookupAux (globtab, uname);
5198 cstring_free (uname);
5200 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5204 usymtab_existsEnumTag (cstring k) /*@globals globtab@*/
5206 cstring ename = makeEnum (k);
5207 uentry ce = usymtab_lookupAux (globtab, ename);
5209 cstring_free (ename);
5210 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5214 bool usymtab_existsVar (cstring k)
5217 uentry ce = usymtab_lookupSafe (k);
5219 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && (uentry_isVar (ce)));
5228 refTable_free (/*@only@*/ /*@null@*/ refTable x, int nentries)
5234 for (i = 0; i < nentries; i++)
5244 usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab u)
5245 /*@globals globtab, utab, filetab@*/
5249 aliasTable_free (u->aliases);
5251 refTable_free (u->reftable, u->nentries);
5253 if (u == filetab || u == globtab)
5255 for (i = 0; i < u->nentries; i++)
5257 uentry_freeComplete (u->entries[i]);
5262 for (i = 0; i < u->nentries; i++)
5264 uentry_free (u->entries[i]);
5268 guardSet_free (u->guards);
5275 llassert (!cstringTable_isDefined (u->htable));
5283 usymtab_freeAux (/*@only@*/ usymtab u)
5284 /*@globals globtab, utab, filetab@*/
5287 while (u != GLOBAL_ENV)
5290 usymtab_freeLevel (u);
5297 void usymtab_free ()
5298 /*@globals killed utab, globtab, filetab@*/
5302 usymtab_freeAux (utab);
5305 static int usymtab_lexicalLevel (void) /*@globals utab@*/
5307 return (utab->lexlevel);
5310 bool usymtab_inGlobalScope () /*@globals utab, globtab@*/
5312 return (utab == globtab);
5315 bool usymtab_inFileScope () /*@globals utab@*/
5317 return (utab->lexlevel == fileScope);
5320 bool usymtab_inFunctionScope () /*@globals utab@*/
5322 return (utab->lexlevel == functionScope);
5327 usymtab_replaceEntry (uentry s)
5328 /*@globals utab, globtab@*/
5329 /*@modifies utab, s@*/
5331 usymtab_replaceEntryAux (utab, s);
5336 usymtab_matchForwardStruct (usymId u1, usymId u2)
5337 /*@globals globtab@*/
5339 uentry ue1 = usymtab_getTypeEntry (u1);
5340 uentry ue2 = usymtab_getTypeEntry (u2);
5342 if (uentry_isAnyTag (ue2))
5344 ctype reptype = uentry_getType (ue1);
5346 if (ctype_isPointer (reptype))
5348 ctype repbase = ctype_getBaseType (reptype);
5350 if (ctype_isUA (repbase))
5352 typeId rtuid = ctype_typeId (repbase);
5354 if (u2 == rtuid) return TRUE;
5356 if (usymId_isValid (rtuid))
5358 reptype = uentry_getType (usymtab_getTypeEntry (rtuid));
5360 return (ctype_isUA (reptype) && (u2 == (ctype_typeId (reptype))));
5369 void usymtab_addGuards (guardSet guards)
5372 utab->guards = guardSet_union (utab->guards, guards);
5375 static bool usymtab_isGuardedAux (sRef s)
5379 sRef base = sRef_getRootBase (s);
5380 int lowlevel = paramsScope;
5381 int baselevel = sRef_lexLevel (base);
5383 if (sRef_isCvar (base))
5385 lowlevel = baselevel;
5386 if (lowlevel < paramsScope) lowlevel = paramsScope;
5389 while (tab->lexlevel >= lowlevel)
5391 DPRINTF (("Is guarded? [%s] %s",
5392 guardSet_unparse (tab->guards),
5393 sRef_unparseFull (s)));
5395 if (guardSet_isGuarded (tab->guards, s))
5398 if (!sRef_definitelyNull (s))
5400 sRef_setNotNull (s, fileloc_undefined);
5406 tab = usymtab_dropEnv (tab);
5412 void usymtab_unguard (sRef s) /*@modifies utab@*/
5415 sRef base = sRef_getRootBase (s);
5416 int lowlevel = paramsScope;
5417 int baselevel = sRef_lexLevel (base);
5419 if (sRef_isCvar (base))
5421 lowlevel = baselevel;
5422 if (lowlevel < paramsScope) lowlevel = paramsScope;
5425 while (tab->lexlevel >= lowlevel)
5427 if (guardSet_isGuarded (tab->guards, s))
5429 guardSet_delete (tab->guards, s);
5432 tab = usymtab_dropEnv (tab);
5436 bool usymtab_isGuarded (sRef s)
5438 DPRINTF (("Is guarded? %s", sRef_unparseFull (s)));
5439 return (sRef_aliasCompleteSimplePred (usymtab_isGuardedAux, s));
5442 bool usymtab_isDefinitelyNull (sRef s)
5444 return (sRef_aliasCheckSimplePred (usymtab_isDefinitelyNullAux, s));
5447 bool usymtab_isDefinitelyNullDeep (sRef s)
5449 return (sRef_deepPred (usymtab_isDefinitelyNull, s));
5452 static bool usymtab_isDefinitelyNullAux (sRef s)
5456 sRef base = sRef_getRootBase (s);
5457 int lowlevel = paramsScope;
5459 if (sRef_isCvar (base))
5461 lowlevel = sRef_lexLevel (base);
5462 if (lowlevel < paramsScope) lowlevel = paramsScope;
5465 while (tab->lexlevel >= lowlevel)
5467 if (guardSet_mustBeNull (tab->guards, s))
5472 while (tab->kind == US_CBRANCH)
5477 llassert (usymtab_isDefined (tab));
5479 if (tab->kind == US_FBRANCH)
5482 llassert (tab->kind == US_TBRANCH);
5492 usymtab_printGuards ()
5493 /*@globals utab, globtab@*/
5495 usymtab ttab = utab;
5497 while (ttab != globtab)
5499 llmsg (message ("Guards [%d]: %q", ttab->lexlevel,
5500 guardSet_unparse (ttab->guards)));
5506 usymtab_displayAllUses ()
5507 /*@globals utab, globtab@*/
5511 /* only in top scope */
5512 llassert (utab == globtab);
5514 /* need a copy, so order is not messed up by sort! */
5515 copy = usymtab_shallowCopy (globtab);
5517 qsort (copy->entries, (size_t)copy->nentries,
5518 sizeof (*copy->entries), (int (*)(const void *, const void *)) uentry_xcompareuses);
5520 usymtab_entries (copy, ue)
5522 if (uentry_isValid (ue))
5524 filelocList uses = uentry_getUses (ue);
5525 int size = filelocList_realSize (uses);
5527 if (fileloc_isDefined (uentry_whereDefined (ue))
5528 && !fileloc_isLib (uentry_whereDefined (ue))
5531 llmsg (message ("%q (%q), %d use%&:\n %q",
5532 uentry_getName (ue),
5533 fileloc_unparse (uentry_whereDefined (ue)),
5534 size, filelocList_unparseUses (uses)));
5537 } end_usymtab_entries;
5539 usymtab_shallowFree (copy);
5542 static /*@dependent@*/ /*@exposed@*/ usymtab
5543 usymtab_getFileTab ()
5544 /*@globals filetab@*/
5546 llassert (filetab != NULL);
5552 usymtab_unparseStack ()
5555 return (usymtab_unparseStackTab (utab));
5558 static /*@only@*/ cstring
5559 usymtab_unparseStackTab (usymtab t)
5561 bool firstOne = TRUE;
5562 cstring ret = cstring_makeLiteral ("[");
5564 while (t != GLOBAL_ENV)
5568 ret = message ("%q %q", ret, usymtab_typeName (t));
5573 ret = message ("%q, %q", ret, usymtab_typeName (t));
5578 ret = message ("%q ]", ret);
5582 static /*@only@*/ cstring
5583 usymtab_typeName (/*@notnull@*/ usymtab t)
5587 case US_GLOBAL: return cstring_makeLiteral ("global");
5588 case US_NORMAL: return cstring_makeLiteral ("normal");
5589 case US_TBRANCH: return cstring_makeLiteral ("true");
5590 case US_FBRANCH: return cstring_makeLiteral ("false");
5591 case US_CBRANCH: return cstring_makeLiteral ("case");
5592 case US_SWITCH: return cstring_makeLiteral ("switch");
5598 void usymtab_addMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5601 if (!sRef_similar (s, al))
5603 usymtab_addForceMustAlias (s, al);
5608 ** Same as usymtab_addMustAlias, except does not check sRef_isSimilar.
5611 void usymtab_addForceMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5614 if (sRef_isMeaningful (s)
5615 && sRef_isMeaningful (al)
5616 && !(sRef_isConst (s) || sRef_isConst (al))
5617 && !(sRef_isAddress (al) && sRef_isDirectParam (sRef_getBase (al))))
5619 utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
5620 DPRINTF (("Must alias: %s", aliasTable_unparse (utab->aliases)));
5623 ** for local variable, aliasing is symmetric
5626 if (sRef_isLocalVar (s) && sRef_isLocalVar (al))
5628 utab->aliases = aliasTable_addMustAlias (utab->aliases, al, s);
5637 void usymtab_clearAlias (sRef s)
5638 /*@modifies utab, s@*/
5641 aliasTable_clearAliases (utab->aliases, s);
5644 sRefSet usymtab_allAliases (sRef s)
5647 if (sRef_isMeaningful (s))
5651 ret = sRefSet_unionFree (aliasTable_aliasedBy (utab->aliases, s),
5652 aliasTable_canAlias (utab->aliases, s));
5657 DPRINTF (("NOT A MEANINGFUL SREF!"));
5658 return sRefSet_undefined;
5662 /*@only@*/ sRefSet usymtab_canAlias (sRef s)
5665 if (sRef_isMeaningful (s))
5667 sRefSet res = aliasTable_canAlias (utab->aliases, s);
5671 return sRefSet_undefined;
5674 /*@only@*/ sRefSet usymtab_aliasedBy (sRef s)
5677 return (aliasTable_aliasedBy (utab->aliases, s));
5680 /*@only@*/ cstring usymtab_unparseAliases ()
5683 return (aliasTable_unparse (utab->aliases));
5687 ** Debugging routines:
5688 ** okay to leak storage here, only for debugging
5694 usymtab_printOut (void)
5700 char *ind = mstring_copy (" ");
5702 fprintf (g_msgstream, "<<< [symbol table] >>>\n");
5704 while (s != GLOBAL_ENV && s->env != GLOBAL_ENV)
5706 cstring tname = usymtab_typeName (s);
5710 ind[depth * 3 + 1] = '\0';
5713 fprintf (g_msgstream, "level: %d (%s)\n", s->lexlevel,
5714 cstring_toCharsSafe (tname));
5716 cstring_free (tname);
5718 for (i = 0; i < s->nentries; i++)
5720 cstring us = uentry_unparseFull (s->entries[i]);
5721 fprintf (g_msgstream, "%s\n", cstring_toCharsSafe (us));
5725 if (s->reftable != NULL && s->nentries > 0)
5727 fprintf (g_msgstream, "\t<< Ref table >>\n");
5729 for (i = 0; i < s->nentries; i++)
5731 fprintf (g_msgstream, "\t%s %3d: %d, %d\n", ind, i,
5732 s->reftable[i]->level,
5733 s->reftable[i]->index);
5737 ind[depth * 3 + 1] = ' ';
5741 fprintf (g_msgstream, "<<< end usymtab >>>\n");
5747 usymtab_printTypes ()
5748 /*@globals globtab@*/
5750 usymtab_printAllAux (globtab);
5754 usymtab_printAll (void)
5757 usymtab_printAllAux (utab);
5761 usymtab_printAllAux (usymtab s)
5762 /*@modifies g_msgstream@*/
5766 char *ind = mstring_copy (" ");
5768 printf ("[[[ usymtab ]]]");
5770 while (s != GLOBAL_ENV)
5773 ind[depth * 3 + 1] = '\0';
5775 if (s->env == GLOBAL_ENV)
5779 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5780 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5781 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5785 for (i = looplow; i < s->nentries; i++)
5787 printf ("%s%3d. %s\n", ind, i,
5788 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5793 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5794 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5795 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5797 for (i = 0; i < s->nentries; i++)
5799 printf ("%s%3d %s\n", ind, i,
5800 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5804 ind[depth * 3 + 1] = ' ';
5808 printf ("----------\n");
5812 usymtab_printComplete ()
5817 char *ind = mstring_copy (" ");
5820 while (s != GLOBAL_ENV)
5824 ind[depth * 3 + 1] = '\0';
5827 if (s->env == GLOBAL_ENV)
5831 printf ("level: %d\n", s->lexlevel);
5835 for (i = looplow; i < s->nentries; i++)
5837 printf ("%s%3d %s\n", ind, i,
5838 cstring_toCharsSafe (uentry_unparse (s->entries[i])));
5843 printf ("level: %d\n", s->lexlevel);
5844 for (i = 0; i < s->nentries; i++)
5846 printf ("%s%3d %s\n", ind, i,
5847 cstring_toCharsSafe (uentry_unparse (s->entries[i])));
5851 ind[depth * 3 + 1] = ' ';
5856 printf ("----------\n");
5860 static /*@only@*/ cstring /*@unused@*/
5861 usymtab_unparseLocalAux (/*@notnull@*/ usymtab s)
5863 cstring c = message ("lexlevel: %d\n", s->lexlevel);
5866 for (i = 0; i < s->nentries; i++)
5868 c = message ("%q\n%q", c, uentry_unparseFull (s->entries[i]));
5871 c = message ("%q\n=========", c);
5875 static cstring /*@unused@*/ /*@only@*/
5876 usymtab_unparseLocalList (/*@notnull@*/ usymtab s)
5878 cstring c = message ("[%d/%s/%s] ", s->lexlevel,
5879 bool_unparse (s->mustBreak),
5880 exitkind_unparse (s->exitCode));
5883 for (i = 0; i < s->nentries; i++)
5885 sRef sr = uentry_getSref (s->entries[i]);
5889 c = message ("%q: %q [%b]", c, uentry_getName (s->entries[i]),
5890 sRef_isStateDefined (sr));
5894 c = message ("%q, %q [%b]", c, uentry_getName (s->entries[i]),
5895 sRef_isStateDefined (sr));
5904 usymtab_printLocal (void)
5910 printf ("lexlevel: %d\n", s->lexlevel);
5912 for (i = 0; i < s->nentries; i++)
5914 printf ("%s\n", cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5917 while (s->lexlevel > 1)
5922 llassert (usymtab_isDefined (s));
5924 printf ("Params:\n");
5926 for (i = 0; i < s->nentries; i++)
5928 printf ("%d: %s\n", i,
5929 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5934 static bool checkDistinctExternalName (uentry e)
5935 /*@globals globtab@*/
5936 /*@modifies *g_msgstream@*/
5938 int checklen = context_getValue (FLG_EXTERNALNAMELEN);
5939 bool ignorecase = context_getFlag (FLG_EXTERNALNAMECASEINSENSITIVE);
5940 bool gotone = FALSE;
5941 bool extras = FALSE;
5942 bool hasError = FALSE;
5943 cstring name = uentry_rawName (e);
5944 usymtab st = globtab;
5952 if (uentry_isAnyTag (e))
5954 checklen++; /* the tag marker doesn't count */
5958 usymtab_entries (st, oe)
5960 if (uentry_sameObject (oe, e))
5967 if (cstring_equalCaseInsensitive (uentry_rawName (oe), name))
5976 (FLG_DISTINCTEXTERNALNAMES,
5978 ("External identifier %q is not distinguishable from %q "
5979 "because alphabetical case is ignored",
5981 uentry_getName (oe)),
5982 uentry_whereLast (e)))
5984 uentry_showWhereAny (oe);
5985 uentry_setHasNameError (oe);
5994 if (cstring_equalLenCaseInsensitive (uentry_rawName (oe),
6003 if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6006 (FLG_DISTINCTEXTERNALNAMES,
6009 ("External identifier %q is not distinguishable from %q "
6010 "in the first %d characters (%q)",
6012 uentry_getName (oe),
6014 cstring_clip (uentry_getName (e), checklen)),
6016 uentry_whereLast (e)))
6018 uentry_showWhereAny (oe);
6019 uentry_setHasNameError (oe);
6032 (FLG_DISTINCTEXTERNALNAMES,
6034 ("External identifier %q is not distinguishable from %q "
6035 "in the first %d characters because alphabetical case "
6038 uentry_getName (oe),
6040 uentry_whereLast (e)))
6042 uentry_showWhereAny (oe);
6043 uentry_setHasNameError (oe);
6049 else if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6058 (FLG_DISTINCTEXTERNALNAMES,
6061 ("External identifier %q is not distinguishable from %q "
6062 "in the first %d characters (%q)",
6064 uentry_getName (oe),
6066 cstring_clip (uentry_getName (e), checklen)),
6068 uentry_whereLast (e)))
6070 uentry_showWhereAny (oe);
6071 uentry_setHasNameError (oe);
6080 } end_usymtab_entries ;
6087 (cstring_makeLiteral ("One or more additional "
6088 "indistinguishable external "
6089 "names not reported"));
6095 static bool checkDistinctInternalName (uentry e)
6097 /*@modifies *g_msgstream@*/
6099 usymtab ttab = utab;
6100 cstring name = uentry_rawName (e);
6101 int numchars = context_getValue (FLG_INTERNALNAMELEN);
6102 bool caseinsensitive = context_getFlag (FLG_INTERNALNAMECASEINSENSITIVE);
6103 bool lookalike = context_getFlag (FLG_INTERNALNAMELOOKALIKE);
6105 if (uentry_isAnyTag (e) && (numchars != 0))
6107 numchars++; /* the tag marker doesn't count */
6110 while (usymtab_isDefined (ttab))
6112 usymtab_entries (ttab, oe)
6114 if (uentry_sameObject (oe, e))
6116 /*@innercontinue@*/ continue;
6119 switch (cstring_genericEqual
6120 (name, uentry_rawName (oe),
6121 numchars, caseinsensitive, lookalike))
6123 case CGE_DISTINCT: /* okay */
6127 if (cstring_equal (name, uentry_rawName (oe)))
6129 ; /* got a shadow error */
6134 (FLG_DISTINCTINTERNALNAMES,
6137 ("Internal identifier %q is not distinguishable from %q "
6138 "in the first %d characters (%q)",
6140 uentry_getName (oe),
6142 cstring_clip (uentry_getName (e), numchars)),
6144 uentry_whereLast (e)))
6146 uentry_showWhereAny (oe);
6147 uentry_setHasNameError (oe);
6155 || (cstring_length (name) <= numchars))
6158 (FLG_DISTINCTINTERNALNAMES,
6160 ("Internal identifier %q is not distinguishable from %q "
6161 "without case sensitivity",
6163 uentry_getName (oe)),
6164 uentry_whereLast (e)))
6166 uentry_showWhereAny (oe);
6167 uentry_setHasNameError (oe);
6174 (FLG_DISTINCTINTERNALNAMES,
6176 ("Internal identifier %q is not distinguishable from %q "
6177 "in the first %d characters without case sensitivity",
6179 uentry_getName (oe),
6181 uentry_whereLast (e)))
6183 uentry_showWhereAny (oe);
6184 uentry_setHasNameError (oe);
6192 || (cstring_length (name) <= numchars))
6195 (FLG_DISTINCTINTERNALNAMES,
6197 ("Internal identifier %q is not distinguishable from %q "
6198 "except by lookalike characters",
6200 uentry_getName (oe)),
6201 uentry_whereLast (e)))
6203 uentry_showWhereAny (oe);
6204 uentry_setHasNameError (oe);
6211 (FLG_DISTINCTINTERNALNAMES,
6213 ("Internal identifier %q is not distinguishable from %q "
6214 "in the first %d characters except by lookalike characters",
6216 uentry_getName (oe),
6218 uentry_whereLast (e)))
6220 uentry_showWhereAny (oe);
6221 uentry_setHasNameError (oe);
6226 } end_usymtab_entries ;
6234 void usymtab_checkDistinctName (uentry e, int scope)
6235 /*@globals utab, globtab@*/
6237 bool hasError = FALSE;
6238 fileloc where = uentry_whereLast (e);
6240 if (!fileloc_isPreproc (where) && !fileloc_isBuiltin (where))
6242 if (scope == globScope)
6244 if (context_getFlag (FLG_DISTINCTEXTERNALNAMES))
6246 hasError = checkDistinctExternalName (e);
6250 if (!hasError && context_getFlag (FLG_DISTINCTINTERNALNAMES))
6252 hasError = checkDistinctInternalName (e);
6258 uentry_setHasNameError (e);
6262 /*@exposed@*/ sRef usymtab_lookupGlobalMarker (void) /*@globals utab@*/
6266 ue = usymtab_lookupAux (utab, GLOBAL_MARKER_NAME);
6267 llassert (uentry_isValid (ue));
6269 return uentry_getSref (ue);