2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 University of Virginia,
4 ** Massachusetts Institute of Technology
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ** General Public License for more details.
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
20 ** For information on splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
27 ** Lexically scoped symbol table.
29 ** Unlike a normal symbol table, this table splits to reflect branches.
31 ** This is necessary since symbol table entries also reflect
32 ** some state information, like initialization, that may be
33 ** different on different branches.
35 ** For each control structure we split:
37 ** { } - a normal scope (no control) US_NORMAL
39 ** if <pred> { } - US_TBRANCH true branch
40 ** while <pred> { } US_FBRANCH else branch
42 ** switch <pred> { } - US_SWITCH
44 ** case x: - case scope US_CBRANCH
45 ** Should be kept in a separate table, because of
49 # include "splintMacros.nf"
51 # include "structNames.h"
52 # include "exprChecks.h"
53 # include "transferChecks.h"
55 /* Needed to install macros when loading libraries */
58 # include "cpperror.h"
62 ** Keep track of type definitions inside a function.
65 static uentryList functypes = uentryList_undefined;
67 static bool dbgfree = FALSE;
68 static bool dbgload = TRUE;
73 ** Hack to prevent shadow errors from appearing when function parameters
74 ** are entered into a new scope.
77 static bool noshadowerror = FALSE;
80 ** Constraint: static variables can live in 1 or > 2.
82 ** except for tags. All tags must be at the global level.
83 ** Static tags are handled in a kludgey way.
87 ** utab is the universal symbol table
88 ** globtab is the global environment of utab
89 ** oldtab is needed for conversions in dumping (after sorting the table)
91 ** there can be only one usymtab!
94 static /*@checkedstrict@*/ /*@owned@*/ /*@notnull@*/ usymtab utab;
96 /* Reachable environments from from utab */
97 static /*@checkedstrict@*/ /*@notnull@*/ /*@dependent@*/ usymtab globtab;
98 static /*@checkedstrict@*/ /*@dependent@*/ usymtab filetab;
100 /* Used for sorting for dumpage. */
101 static /*@checkedstrict@*/ /*@owned@*/ usymtab oldtab;
103 static int usymtab_lexicalLevel (void) /*@globals utab@*/ ;
104 static bool usymtab_isAltDefinitelyNull (sRef p_s) /*@globals utab@*/ ;
105 static void refTable_free (/*@only@*/ /*@null@*/ refTable p_x, int p_nentries);
106 static ctype usymtab_suFieldsType (uentryList p_f, bool p_isStruct) /*@globals globtab@*/ ;
108 static void usymtab_freeAux (/*@only@*/ usymtab p_u)
109 /*@globals globtab, utab, filetab@*/
112 extern int usymtab_getCurrentDepth (void) /*@globals utab@*/
114 return utab->lexlevel;
118 usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab p_u)
119 /*@globals globtab, utab, filetab@*/ /*@modifies p_u@*/ ;
121 static bool usymtab_isDefinitelyNullAux (sRef p_s) /*@globals utab@*/ ;
122 static /*@only@*/ cstring usymtab_unparseStackTab (usymtab p_t);
123 static /*@exposed@*/ /*@dependent@*/ uentry
124 usymtab_getRefTab (/*@notnull@*/ usymtab p_u, int p_level, usymId p_index);
127 /* These are not used anymore... */
128 static /*@unused@*/ /*@only@*/ cstring
129 usymtab_unparseLocalAux (/*@notnull@*/ usymtab p_s);
130 static /*@unused@*/ /*@only@*/ cstring
131 usymtab_unparseLocalList (/*@notnull@*/ usymtab p_s);
134 static /*@only@*/ cstring usymtab_typeName (/*@notnull@*/ usymtab p_t);
135 static void usymtab_handleParams (void)
136 /*@globals utab, globtab, filetab@*/
137 /*@modifies utab@*/ ;
139 static /*@exposed@*/ /*@dependent@*/ uentry
140 usymtab_addRefEntry (/*@notnull@*/ usymtab p_s, cstring p_k);
141 static /*@exposed@*/ /*@dependent@*/ usymtab
142 usymtab_dropEnv (/*@notnull@*/ usymtab p_s);
143 static /*@exposed@*/ /*@dependent@*/ uentry
144 usymtab_getRefNoisy (/*@notnull@*/ usymtab p_s, int p_level, usymId p_index);
146 static /*@exposed@*/ /*@dependent@*/ uentry
147 usymtab_lookupQuietAux (usymtab p_s, cstring p_k, bool p_noalt);
149 static /*@exposed@*/ /*@dependent@*/ uentry
150 usymtab_lookupQuiet (usymtab p_s, cstring p_k);
152 static /*@exposed@*/ /*@dependent@*/ uentry
153 usymtab_lookupQuietNoAlt (usymtab p_s, cstring p_k);
155 static void usymtab_printAllAux (usymtab p_s) /*@modifies g_warningstream@*/ ;
156 static int usymtab_getIndex (/*@notnull@*/ usymtab p_s, cstring p_k);
157 static /*@exposed@*/ uentry usymtab_fetchIndex (/*@notnull@*/ usymtab p_s, int p_i);
158 static /*@exposed@*/ uentry
159 usymtab_lookupAux (usymtab p_s, cstring p_k);
160 static /*@exposed@*/ /*@dependent@*/ /*@notnull@*/ usymtab
161 usymtab_getFileTab (void) /*@globals filetab@*/ ;
162 static int refTable_lookup (/*@notnull@*/ usymtab p_ut, int p_level, int p_index);
163 static bool usymtab_mustBreak (usymtab p_s);
164 static bool usymtab_mustEscape (usymtab p_s);
166 static void recordFunctionType (uentry ue)
168 llassert (uentry_isDatatype (ue) || uentry_isAnyTag (ue)
169 || uentry_isEnumConstant (ue));
170 DPRINTF (("Function type: %s", uentry_unparseFull (ue)));
172 functypes = uentryList_add (functypes, ue);
176 static void clearFunctionTypes (void)
177 /*@modifies globtab@*/
179 uentryList_elements (functypes, el)
181 if (cstring_isDefined (uentry_rawName (el)))
183 if (cstringTable_isDefined (globtab->htable))
185 cstringTable_remove (globtab->htable, uentry_rawName (el));
188 uentry_setName (el, cstring_undefined);
192 llassert (uentry_isValid (el));
193 el->sref = sRef_undefined;
194 /*@noaccess uentry@*/
195 } end_uentryList_elements ;
197 uentryList_clear (functypes);
200 static /*@falsewhennull@*/ bool usymtab_isBranch (usymtab u)
202 return (usymtab_isDefined (u) &&
203 (u->kind == US_TBRANCH || u->kind == US_FBRANCH
204 || u->kind == US_CBRANCH || u->kind == US_SWITCH));
207 static bool usymtab_mustBreak (usymtab s)
209 llassert (s != GLOBAL_ENV);
210 return (s->mustBreak);
213 static bool usymtab_mustEscape (usymtab s)
215 llassert (s != GLOBAL_ENV);
216 return (exitkind_mustEscape (s->exitCode));
219 void usymtab_setMustBreak ()
222 llassert (utab != GLOBAL_ENV);
223 utab->mustBreak = TRUE;
226 void usymtab_setExitCode (exitkind ex)
229 llassert (utab != GLOBAL_ENV);
233 if (exitkind_mustEscape (ex))
235 utab->mustBreak = TRUE;
239 bool usymtab_isAltDefinitelyNullDeep (sRef s)
241 return (sRef_deepPred (usymtab_isAltDefinitelyNull, s));
244 static bool usymtab_isAltDefinitelyNull (sRef s)
252 llassert (utab->env != NULL);
254 /*@-mods@*/ /* These modifications are cancelled. */
255 utab->guards = utab->env->guards;
256 utab->env->guards = t;
259 llassert (usymtab_isDefined (utab));
260 res = usymtab_isDefinitelyNull (s);
263 ** This reports a spurious error. It is okay, because of
264 ** the nesting relationship of usymtab environments.
267 /*@-mods@*/ /* Cancelling modifications. */
268 /*@i1@*/ utab->env->guards = utab->guards;
269 /*@i1@*/ utab->guards = t;
275 static /*@notnull@*/ /*@special@*/ usymtab
276 usymtab_create (uskind kind, /*@keep@*/ usymtab env, bool nextlevel)
278 /*@post:isnull result->htable, result->guards, result->aliases@*/
280 usymtab t = (usymtab) dmalloc (sizeof (*t));
283 t->nspace = CBASESIZE;
284 t->entries = (uentry *) dmalloc (sizeof (*t->entries) * CBASESIZE);
286 /* We only use a reftable for branch-level symbol tables.
289 t->reftable = (nextlevel
291 : (refentry *) dmalloc (sizeof (*t->reftable) * CBASESIZE));
294 t->lexlevel = (env == GLOBAL_ENV ? 0 : env->lexlevel) + (nextlevel ? 1 : 0);
299 t->guards = guardSet_undefined;
300 t->aliases = aliasTable_undefined;
302 t->mustBreak = FALSE;
303 t->exitCode = XK_NEVERESCAPE;
305 DPRINTF (("Create usymtab [%p]", t));
313 static /*@only@*/ /*@notnull@*/ usymtab
314 usymtab_createRoot (void) /*@modifies nothing@*/
316 usymtab u = (usymtab) dmalloc (sizeof (*u));
319 u->nspace = CGLOBBASESIZE;
320 u->entries = (uentry *) dmalloc (sizeof (*u->entries) * CGLOBBASESIZE);
323 u->htable = cstringTable_create (CGLOBHASHSIZE);
326 u->guards = guardSet_new ();
327 u->aliases = aliasTable_new ();
329 u->mustBreak = FALSE;
330 u->exitCode = XK_NEVERESCAPE;
337 usymtab_initMod (void)
338 /*@globals undef utab, undef oldtab, undef globtab, undef filetab @*/
339 /*@modifies utab, globtab, filetab, oldtab @*/
341 utab = usymtab_createRoot ();
343 filetab = usymtab_undefined;
344 oldtab = usymtab_undefined;
348 usymtab_destroyMod (void) /*@modifies utab, globtab, filetab@*/ /*@globals killed utab@*/
350 DPRINTF (("Destroy usymtab [%p]: %d", utab, utab->nentries));
351 usymtab_freeAux (utab);
352 utab = usymtab_undefined;
357 usymtab_initGlobalMarker () /*@globals globtab@*/
359 if (uentry_isValid (usymtab_lookupAux (globtab, GLOBAL_MARKER_NAME)))
361 ; /* Already entered from load table. */
365 usymtab_addGlobalEntry (uentry_makeGlobalMarker ());
370 ** utab should be empty? (requires?)
372 ** Adds bool types to symbol table (these are built in for now)
373 ** Only do this is there is no library!
379 DPRINTF (("Init bool!"));
381 if (context_getFlag (FLG_NOLIB))
383 ctype boolt = ctype_bool;
384 /* evs 2000-07-24: bool is now treated as abstract (always) */
386 uentry boolentry = uentry_makeBoolDatatype (qual_createAbstract ());
387 usymtab_supGlobalEntry (boolentry);
388 context_addBoolAccess ();
391 ** We supply values 0 and 1 for the constants, so things like
392 ** while (TRUE) can be interpreted correctly.
395 usymtab_supGlobalEntry
396 (uentry_makeConstantValue (context_getFalseName (), boolt,
397 fileloc_getBuiltin (), FALSE,
398 multiVal_makeInt (0)));
400 usymtab_supGlobalEntry
401 (uentry_makeConstantValue (context_getTrueName (), boolt,
402 fileloc_getBuiltin (), FALSE,
403 multiVal_makeInt (1)));
412 usymtab_grow (/*@notnull@*/ usymtab s)
415 o_uentry *oldsyms = s->entries;
417 s->nspace = CBASESIZE;
418 s->entries = (uentry *) dmalloc (sizeof (*s->entries)
419 * (s->nentries + s->nspace));
421 for (i = 0; i < s->nentries; i++)
423 s->entries[i] = oldsyms[i];
428 if (s->reftable != NULL)
430 refTable oldRefs = s->reftable;
432 s->reftable = (refentry *) dmalloc (sizeof (*s->reftable)
433 * (s->nentries + CBASESIZE + 1));
435 for (i = 0; i < s->nentries; i++)
437 s->reftable[i] = oldRefs[i];
448 usymtab_addEntryQuiet (/*@notnull@*/ usymtab s, /*@keep@*/ uentry e)
450 if (!(s->lexlevel > fileScope || !sRef_modInFunction ()))
452 if (uentry_isDatatype (e)
453 || uentry_isFunction (e)
454 || uentry_isAnyTag (e)
455 || uentry_isEnumConstant (e)
456 || context_inMacro ())
459 ** Not a bug. Code like,
460 ** int f (void) { typedef int tint; ... }
464 /* was nothing here! */
465 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
470 (cstring_makeLiteral ("Declaration outside function scope"));
472 llcontbug (message ("usymtab_addEntryQuiet: inconsistent state "
473 "(lexlevel = %d, modFunction = %s) adding: %q",
474 s->lexlevel, bool_unparse (sRef_modInFunction ()),
475 uentry_unparse (e)));
476 sRef_setGlobalScope ();
477 /* make sure the sRef is not bashed! */
478 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
488 s->entries[s->nentries] = e;
491 if (s == globtab || s == filetab)
493 if (!fileloc_isLib (g_currentloc))
495 uentry_tallyAnnots (e, AN_UNKNOWN);
500 if (cstringTable_isDefined (s->htable))
502 cstringTable_insert (s->htable, cstring_copy (uentry_rawName (e)), s->nentries);
508 static /*@observer@*/ uentry /*@alt void@*/
509 usymtab_addEntryBase (/*@notnull@*/ usymtab s, /*@only@*/ uentry e)
512 ** In theory, we shouldn't need this test because it this is
513 ** only called when a library is being read, and it shouldn't
514 ** ever have a duplicate entry. In practice, its safer to
515 ** leave it in, though.
520 if (uentry_isValid (old = usymtab_lookupQuiet (s, uentry_rawName (e))))
522 DPRINTF (("Duplicate entry: %s", uentry_unparse (e)));
523 uentry_free (e); /* duplicate */
528 int thisentry = s->nentries;
530 if (uentry_isVar (e))
533 (e, sRef_makeCvar (globScope, thisentry,
535 stateInfo_makeLoc (uentry_whereLast (e), SA_DECLARED)));
538 usymtab_addEntryQuiet (s, e);
544 static /*@observer@*/ uentry /*@alt void@*/
545 usymtab_addEntryAlways (/*@notnull@*/ usymtab s, /*@only@*/ uentry e)
548 ** In theory, we shouldn't need this test because it this is
549 ** only called when a library is being read, and it shouldn't
550 ** ever have a duplicate entry. In practice, its safer to
551 ** leave it in, though.
555 int thisentry = s->nentries;
557 if (uentry_isValid (old = usymtab_lookupQuiet (s, uentry_rawName (e))))
560 (message ("Duplicate entry in load library: %s. "
561 "Old entry: %q. New entry: %q",
563 uentry_unparseFull (old),
564 uentry_unparseFull (e)));
566 uentry_setName (e, message ("__x_%s", uentry_rawName (e)));
567 /* This shouldn't happen...unless the library is bad! */
571 if (uentry_isVar (e) && !uentry_isGlobalMarker (e))
574 (e, sRef_makeCvar (globScope, thisentry,
576 stateInfo_makeLoc (uentry_whereLast (e), SA_DECLARED)));
579 usymtab_addEntryQuiet (s, e);
584 usymtab_addEntryAux (/*@notnull@*/ usymtab st, /*@keep@*/ uentry e, bool isSref)
585 /*@globals globtab@*/
588 usymId thisentry = st->nentries;
590 llassert (!uentry_isElipsisMarker (e));
594 ** llassert (usymtab_lookupSafe (uentry_rawName (e)) == uentry_undefined);
597 llassertprint (uentry_isAnyTag (e) ? st == globtab : TRUE,
598 ("non-global tag: %s / %d", uentry_unparseFull (e), st->lexlevel));
600 if (st->lexlevel == fileScope
601 && (!(uentry_isStatic (e)) || uentry_isAnyTag (e)))
608 ctype ct = uentry_getType (e);
610 if (uentry_isFunction (e) && ctype_isFunction (ct))
612 ct = ctype_getReturnType (ct);
615 if (uentry_isStatic (e))
617 sRef sr = sRef_makeCvar (st->lexlevel, thisentry, ct,
618 stateInfo_makeLoc (uentry_whereLast (e), SA_DECLARED));
620 if (sRef_isStack (sr) || sRef_isLocalState (sr))
622 sRef_setAliasKind (sr, AK_STATIC, uentry_whereLast (e));
623 sRef_setDefined (sr, uentry_whereLast (e));
626 uentry_setSref (e, sr);
631 (e, sRef_makeCvar (st->lexlevel, thisentry, ct,
632 stateInfo_makeLoc (uentry_whereLast (e), SA_DECLARED)));
636 if (uentry_isDatatype (e))
639 uentry_setDatatype (e, thisentry);
642 if (uentry_isFunction (e))
644 ctype ct = uentry_getType (e);
646 if (ctype_isFunction (ct)
647 && uentryList_isMissingParams (ctype_argsFunction (ct)))
649 if (uentry_isDeclared (e))
653 message ("Function %q declared without parameter list",
655 uentry_whereDeclared (e));
661 message ("Function %q specified without parameter list",
663 uentry_whereSpecified (e));
668 if (st == globtab && !uentry_isSpecified (e))
670 exprChecks_checkExport (e);
673 uentry_checkName (e);
675 usymtab_addEntryQuiet (st, e);
676 DPRINTF (("Adding entry: [%p] %s", e, uentry_unparseFull (e)));
681 usymtab_addEntry (uentry e)
682 /*@globals utab, globtab@*/
683 /*@modifies utab, e@*/
685 llassertprint (!usymtab_exists (uentry_rawName (e)),
686 ("Entry already exists: %s", uentry_unparse (e)));
688 return usymtab_addEntryAux (utab, e, FALSE);
692 usymtab_addGlobalEntry (uentry e)
693 /*@modifies globtab, e@*/
695 DPRINTF (("Add global: %s / %s", uentry_unparse (e), bool_unparse (uentry_isForward (e))));
697 (void) usymtab_addEntryAux (globtab, e, FALSE);
701 ** supercede and replace entry use elements of entries array, and
702 ** assign an element to a new value, and then free the old value.
703 ** Need -deparrays to avoid errors for this.
709 usymtab_supEntryAux (/*@notnull@*/ usymtab st,
710 /*@only@*/ uentry e, bool isSref)
711 /*@globals globtab, filetab@*/
712 /*@modifies st, globtab, e@*/
714 cstring ename = uentry_rawName (e);
715 bool staticEntry = FALSE;
718 DPRINTF (("Sup entry aux: %s", uentry_unparseFull (e)));
720 /* static tags in global scope */
721 if (st->lexlevel == fileScope
722 && (!(uentry_isStatic (e)) || uentry_isAnyTag (e)))
724 eindex = usymtab_getIndex (st, ename);
726 if (eindex != NOT_FOUND)
728 uentry ce = st->entries[eindex];
732 message ("%s %q shadows static declaration",
733 ekind_capName (uentry_getKind (e)),
735 uentry_whereDeclared (e)))
737 uentry_showWhereLast (ce);
740 if (eindex == st->nentries - 1)
746 st->entries[eindex] = st->entries[st->nentries - 1];
749 if (cstringTable_isDefined (st->htable))
751 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
752 cstring_copy (uentry_rawName (e)));
762 if (uentry_isStatic (e)) {
763 if (uentry_isFunction (e)) {
765 ** Static function declarations are at the file level,
766 ** even if they are in a deeper scope.
769 st = usymtab_getFileTab ();
772 if (!uentry_isAnyTag (e) && st == globtab)
774 st = usymtab_getFileTab ();
776 DPRINTF (("Static entry!"));
781 eindex = usymtab_getIndex (st, ename);
783 if (eindex != NOT_FOUND)
785 uentry ce = st->entries[eindex];
787 DPRINTF (("Found entry: %s", uentry_unparse (ce)));
789 if (uentry_isPriv (ce)
790 /* || (fileloc_isImport (uentry_whereSpecified (ce))) */
791 || (uentry_isStatic (ce)
792 && uentry_isAnyTag (ce)
793 && (uentry_isDeclared (ce)
794 && !fileloc_sameFile (uentry_whereDefined (ce),
795 uentry_whereDefined (e)))))
799 ** if overloading import should do some checks!
802 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
804 DPRINTF (("Overloading!"));
806 st->entries[eindex] = e;
808 if (uentry_isDatatype (e))
810 uentry_setDatatype (e, eindex);
813 if (st == globtab && !uentry_isSpecified (e))
815 exprChecks_checkExport (e);
818 if (cstringTable_isDefined (st->htable))
820 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
821 cstring_copy (uentry_rawName (e)));
827 else if (uentry_isSpecified (ce))
829 if (uentry_isSpecified (e))
831 DPRINTF (("Here we are: %s", uentry_unparseFull (e)));
833 if (fileloc_isImport (uentry_whereSpecified (ce)))
835 if (cstringTable_isDefined (st->htable))
837 cstringTable_replaceKey (st->htable,
839 cstring_copy (uentry_rawName (e)));
843 st->entries[eindex] = e;
846 if (uentry_isDatatype (e)) uentry_setDatatype (e, eindex);
850 if (fileloc_isImport (uentry_whereSpecified (e)))
856 /* Respecification errors already reported */
857 DPRINTF (("Respecification: %s / %s",
858 fileloc_unparse (uentry_whereSpecified (e)),
859 bool_unparse (fileloc_isSpec (uentry_whereSpecified (e)))));
861 if (uentry_isDatatype (e))
863 uentry_setDatatype (e, eindex);
866 if (cstringTable_isDefined (st->htable))
868 cstringTable_replaceKey (st->htable,
870 cstring_copy (uentry_rawName (e)));
873 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
875 st->entries[eindex] = e;
880 else /* e not specified */
882 DPRINTF (("Merging..."));
884 if (uentry_isDeclared (ce))
887 No - this can happen for internal typedefs
888 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
891 DPRINTF (("Merge defn"));
892 uentry_mergeDefinition (ce, e);
897 No - this can happen for internal typedefs
898 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
901 DPRINTF (("Merge entries..."));
902 uentry_mergeEntries (ce, e);
903 DPRINTF (("After: %s", uentry_unparseFull (ce)));
907 else /* ce not specified */
909 if (!(st->lexlevel > fileScope || !sRef_modInFunction ()))
911 if (uentry_isDatatype (e) || uentry_isAnyTag (e)
912 || uentry_isEnumConstant (e)
913 || uentry_isStatic (e)) /* bug fix from Brian St. Pierre */
916 ** Not a bug. Code like,
917 ** int f (void) { typedef int tint; ... }
923 llcontbug (message ("usymtab_supEntryAux: inconsistent state "
924 "(lexlevel = %d, modFunction = %s) adding: %q",
925 st->lexlevel, bool_unparse (sRef_modInFunction ()),
926 uentry_unparse (e)));
928 if (sRef_modInFunction ())
930 /* make sure the sRef is not bashed! */
931 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
936 DPRINTF (("Merge.."));
937 uentry_mergeDefinition (ce, e);
942 ctype ct = uentry_getType (ce);
944 if (uentry_isFunction (ce) && ctype_isFunction (ct))
946 ct = ctype_getReturnType (ct);
950 (ce, sRef_makeCvar (st->lexlevel, eindex, ct,
951 stateInfo_makeLoc (uentry_whereLast (ce), SA_DECLARED)));
954 else /* no previous entry */
958 if (st->lexlevel == globScope
959 && !uentry_isStatic (e)
960 && !uentry_isExtern (e)
961 && usymtab_isDefined (filetab))
964 ** check if there is a static entry: (i.e.,
971 eindex = usymtab_getIndex (filetab, ename);
973 if (eindex != NOT_FOUND)
975 uentry ce = filetab->entries[eindex];
977 uentry_setStatic (e);
978 uentry_mergeDefinition (ce, e);
984 outer = usymtab_lookupQuiet (st->env, ename);
986 DPRINTF (("New : [%p] %s", e, uentry_unparseFull (e)));
987 DPRINTF (("Outer: [%p] %s", outer, uentry_unparseFull (outer)));
990 ** no previous definition, add the new one
994 && uentry_isValid (outer)
995 && !(uentry_isYield (e) || uentry_isYield (outer))
996 && fileloc_isDefined (uentry_whereLast (e))
997 && !fileloc_isXHFile (uentry_whereLast (e))
998 && fileloc_isDefined (uentry_whereLast (outer))
999 && !fileloc_isXHFile (uentry_whereLast (outer)))
1001 if (!uentry_sameKind (outer, e))
1007 if (ctype_isUnknown (uentry_getType (outer))
1008 || uentry_isForward (outer))
1016 message ("%s %q shadows outer declaration",
1017 ekind_capName (uentry_getKind (e)),
1018 uentry_getName (e)),
1019 uentry_whereLast (e)))
1021 uentry_showWhereLast (outer);
1027 if (st == globtab && context_getFlag (FLG_NEWDECL))
1031 message ("New declaration: %q", uentry_getName (e)),
1032 uentry_whereLast (e));
1035 eindex = usymtab_addEntryAux (st, e, isSref);
1039 return (staticEntry ? USYMIDINVALID : eindex);
1043 usymtab_replaceEntryAux (/*@notnull@*/ usymtab st, /*@only@*/ uentry e)
1044 /*@globals globtab@*/ /*@modifies st, e@*/
1046 cstring ename = uentry_rawName (e);
1049 /* static tags in global scope */
1050 eindex = usymtab_getIndex (st, ename);
1052 if (eindex != NOT_FOUND)
1054 uentry ce = st->entries[eindex];
1056 if (cstringTable_isDefined (st->htable))
1058 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
1059 cstring_copy (uentry_rawName (e)));
1063 st->entries[eindex] = e;
1067 eindex = usymtab_addEntryAux (st, e, FALSE);
1073 void usymtab_supEntry (uentry e)
1074 /*@globals utab, filetab, globtab@*/
1075 /*@modifies utab, globtab, e@*/
1077 (void) usymtab_supEntryAux (utab, e, FALSE);
1081 ** this should be lots more efficient!
1084 static /*@exposed@*/ uentry
1085 usymtab_supEntryReturnAux (/*@notnull@*/ usymtab tab,
1086 /*@only@*/ uentry e, bool isref)
1087 /*@globals globtab, filetab@*/
1088 /*@modifies tab, globtab, e@*/
1090 cstring rawName = cstring_copy (uentry_rawName (e));
1091 bool stat = (tab == globtab) && uentry_isStatic (e);
1094 (void) usymtab_supEntryAux (tab, e, isref);
1098 ret = usymtab_lookupAux (filetab, rawName);
1102 ret = usymtab_lookupAux (tab, rawName);
1104 if (uentry_isInvalid (ret) && usymtab_isDefined (filetab))
1106 ret = usymtab_lookupAux (filetab, rawName);
1110 cstring_free (rawName);
1114 /*@dependent@*/ /*@exposed@*/ uentry
1115 usymtab_supEntryReturn (/*@only@*/ uentry e)
1116 /*@globals utab, filetab, globtab@*/
1117 /*@modifies utab, globtab, e@*/
1119 return (usymtab_supEntryReturnAux (utab, e, FALSE));
1122 /*@dependent@*/ /*@exposed@*/ uentry
1123 usymtab_supEntrySrefReturn (/*@only@*/ uentry e)
1124 /*@globals utab, globtab, filetab@*/
1125 /*@modifies utab, globtab, e@*/
1127 return (usymtab_supEntryReturnAux (utab, e, TRUE));
1130 /*@dependent@*/ /*@exposed@*/ uentry
1131 usymtab_supGlobalEntryReturn (uentry e)
1132 /*@globals globtab, filetab@*/
1133 /*@modifies globtab, e@*/
1137 ret = usymtab_supEntryReturnAux (globtab, e, FALSE);
1140 ** We need to keep track of internal function declarations, so
1141 ** we can remove them from the symbol table after exiting this
1142 ** function. This is a bit bogus, of course.
1145 if (sRef_modInFunction ())
1147 recordFunctionType (ret);
1154 usymtab_supTypeEntry (/*@only@*/ uentry e)
1155 /*@globals globtab, filetab@*/
1156 /*@modifies globtab, e@*/
1161 if (uentry_isAbstractDatatype (e))
1163 uid = usymtab_supAbstractTypeEntry (e, FALSE);
1164 ret = ctype_createAbstract (uid);
1168 uid = usymtab_supEntryAux (globtab, e, FALSE);
1169 ret = ctype_createUser (uid);
1172 if (sRef_modInFunction ())
1174 recordFunctionType (globtab->entries[uid]);
1181 usymtab_supReturnTypeEntry (/*@only@*/ uentry e)
1182 /*@globals globtab, filetab@*/
1183 /*@modifies globtab@*/
1187 DPRINTF (("Abstract? %s", uentry_unparseFull (e)));
1189 if (uentry_isAbstractDatatype (e))
1191 uid = usymtab_supAbstractTypeEntry (e, FALSE);
1193 else if (uentry_isMaybeAbstract (e) && context_getFlag (FLG_IMPABSTRACT))
1195 bool maybeabs = TRUE;
1196 cstring sname = uentry_getName (e);
1197 uentry ue = usymtab_lookupGlobSafe (sname);
1198 cstring_free (sname);
1200 if (uentry_isValid (ue))
1202 DPRINTF (("Lookup: %s", uentry_unparseFull (ue)));
1204 if (uentry_isDatatype (ue))
1206 if (uentry_isMaybeAbstract (ue))
1217 DPRINTF (("Not datatype!"));
1224 uid = usymtab_supAbstractTypeEntry (e, FALSE);
1225 ux = usymtab_getTypeEntry (uid);
1226 uentry_setAbstract (ux);
1230 uid = usymtab_supEntryAux (globtab, e, FALSE);
1231 e = usymtab_getTypeEntry (uid);
1233 if (uentry_isMaybeAbstract (e))
1235 uentry_setConcrete (e);
1241 uid = usymtab_supEntryAux (globtab, e, FALSE);
1242 e = usymtab_getTypeEntry (uid);
1244 /*? evans 2002-12-16 removed this? it doesn't make sense
1245 if (uentry_isMaybeAbstract (e))
1247 uentry_setConcrete (e);
1252 if (sRef_modInFunction ())
1254 recordFunctionType (globtab->entries[uid]);
1257 return (globtab->entries[uid]);
1261 usymtab_supAbstractTypeEntry (/*@only@*/ uentry e, bool dodef)
1262 /*@globals globtab, filetab@*/
1263 /*@modifies globtab, e@*/
1268 uid = usymtab_supEntryAux (globtab, e, FALSE);
1269 ue = usymtab_getTypeEntry (uid);
1273 uentry_setDatatype (ue, uid);
1276 if (context_getFlag (FLG_ACCESSMODULE)) /* was accessfile */
1278 context_addFileAccessType (uid);
1281 if (sRef_modInFunction ())
1283 recordFunctionType (globtab->entries[uid]);
1290 usymtab_supExposedTypeEntry (/*@only@*/ uentry e, bool dodef)
1291 /*@globals globtab, filetab@*/
1292 /*@modifies globtab, e@*/
1296 uid = usymtab_supEntryAux (globtab, e, FALSE);
1300 uentry ue = usymtab_getTypeEntry (uid);
1302 uentry_setDatatype (ue, uid);
1305 if (sRef_modInFunction ())
1307 recordFunctionType (globtab->entries[uid]);
1314 usymtab_supForwardTypeEntry (/*@only@*/ uentry e)
1315 /*@globals globtab, filetab@*/
1316 /*@modifies globtab, e@*/
1318 usymId uid = usymtab_supEntryAux (globtab, e, FALSE);
1319 uentry ue = usymtab_getTypeEntry (uid);
1321 uentry_setDatatype (ue, uid);
1323 if (sRef_modInFunction ())
1325 recordFunctionType (globtab->entries[uid]);
1328 return (uentry_getAbstractType (ue));
1332 usymtab_supEntrySref (uentry e)
1333 /*@globals utab, globtab, filetab@*/
1334 /*@modifies utab, globtab, e@*/
1336 sRef old = uentry_getSref (e);
1338 if (sRef_isType (old))
1340 uentry ue = usymtab_supEntryReturnAux (utab, e, TRUE);
1343 if (uentry_isValid (ue))
1345 sRef uref = uentry_getSref (ue);
1347 sRef_mergeStateQuiet (uref, old);
1348 sRef_clearDerived (uref);
1350 /*@noaccess uentry@*/
1352 else if (sRef_isKnown (old))
1354 usymtab_supEntry (e);
1358 (void) usymtab_supEntryAux (utab, e, TRUE);
1362 void usymtab_supGlobalEntry (/*@only@*/ uentry e)
1363 /*@globals globtab, filetab@*/
1364 /*@modifies globtab, filetab, e@*/
1368 DPRINTF (("Sup global entry: %s", uentry_unparse (e)));
1370 uid = usymtab_supEntryAux (globtab, e, FALSE);
1372 if (sRef_modInFunction ())
1374 recordFunctionType (globtab->entries[uid]);
1379 usymtab_supReturnFileEntry (/*@only@*/ uentry e)
1380 /*@globals filetab, globtab@*/
1381 /*@modifies filetab, globtab, e@*/
1383 llassert (filetab != usymtab_undefined);
1384 DPRINTF (("File entry: %s", uentry_unparse (e)));
1385 return (usymtab_supEntryReturnAux (filetab, e, FALSE));
1393 usymtab_inDeepScope () /*@globals utab@*/
1395 return (utab->lexlevel > paramsScope);
1399 usymtab_getIndex (/*@notnull@*/ usymtab s, cstring k)
1403 DPRINTF (("Lookup %s", k));
1405 if (cstringTable_isDefined (s->htable))
1407 i = cstringTable_lookup (s->htable, k);
1412 for (i = 0; i < s->nentries; i++)
1414 uentry current = s->entries[i];
1416 DPRINTF (("Check %d: %s", i, uentry_rawName (current)));
1418 if (!uentry_isUndefined (current)
1419 && cstring_equal (uentry_rawName (current), k))
1430 usymtab_fetchIndex (/*@notnull@*/ usymtab s, int i)
1432 llassert (i >= 0 && i < s->nentries);
1433 return (s->entries[i]);
1437 usymtab_getTypeId (cstring k) /*@globals globtab@*/
1439 usymId uid = usymtab_getIndex (globtab, k);
1441 if (uid == NOT_FOUND) return USYMIDINVALID;
1443 if (!(uentry_isDatatype (usymtab_getTypeEntry (uid)))) {
1444 return USYMIDINVALID;
1450 /*@dependent@*/ uentry
1451 usymtab_lookupStructTag (cstring k)
1453 cstring sname = makeStruct (k);
1454 uentry ue = usymtab_lookupGlob (sname);
1456 cstring_free (sname);
1460 /*@dependent@*/ uentry
1461 usymtab_lookupUnionTag (cstring k)
1463 cstring uname = makeUnion (k);
1464 uentry res = usymtab_lookupGlob (uname);
1466 cstring_free (uname);
1470 /*@dependent@*/ uentry
1471 usymtab_lookupEnumTag (cstring k)
1473 cstring ename = makeEnum (k);
1474 uentry res = usymtab_lookupGlob (ename);
1476 cstring_free (ename);
1481 usymtab_getId (cstring k) /*@globals globtab@*/
1483 usymId uid = usymtab_getIndex (globtab, k);
1486 if (uid == NOT_FOUND)
1488 return USYMIDINVALID;
1491 ue = usymtab_getGlobalEntry (uid);
1493 if (uentry_isPriv (ue))
1495 return USYMIDINVALID;
1501 static /*@exposed@*/ uentry
1502 usymtab_getEntryAux (/*@notnull@*/ usymtab s, usymId uid)
1504 llassert (uid != USYMIDINVALID);
1506 if (uid < 0 || uid >= s->nentries)
1508 llcontbug (message ("usymtab_getEntry: out of range: level = %d [%d]",
1510 return uentry_undefined;
1513 llassertprint (uentry_isValid (s->entries[uid]),
1514 ("entry undefined: %d", uid));
1516 return s->entries[uid];
1519 /*@dependent@*/ /*@observer@*/ uentry
1520 usymtab_getGlobalEntry (usymId uid)
1521 /*@globals utab, globtab@*/
1523 if (dbgfree) return (uentry_undefined);
1525 if (utab->lexlevel > paramsScope)
1527 /* need to do this the awkward way, since it could be in conditional scope */
1528 return (usymtab_lookupSafe (uentry_rawName (globtab->entries[uid])));
1532 return (globtab->entries[uid]);
1536 /*@dependent@*/ /*@exposed@*/ uentry
1537 usymtab_getTypeEntry (usymId uid)
1538 /*@globals globtab@*/
1542 if (uid >= 0 && uid < globtab->nentries)
1544 return (globtab->entries[uid]);
1548 return (uentry_undefined);
1553 llassert (uid >= 0 && uid < globtab->nentries);
1554 return (globtab->entries[uid]);
1562 /*@dependent@*/ /*@exposed@*/ uentry
1563 usymtab_getTypeEntrySafe (usymId uid)
1564 /*@globals globtab@*/
1566 if (uid < 0 || uid >= globtab->nentries)
1568 return uentry_undefined;
1571 return (globtab->entries[uid]);
1575 usymtab_isBoolType (usymId uid)
1576 /*@globals globtab@*/
1578 llassert (uid >= 0 && uid < globtab->nentries);
1580 return (cstring_equal (uentry_rawName (globtab->entries[uid]),
1581 context_getBoolName ()));
1585 usymtab_getTypeEntryName (usymId uid)
1586 /*@globals globtab@*/
1592 return (cstring_makeLiteral ("<freetype>"));
1595 ue = usymtab_getTypeEntry (uid);
1597 if (dbgload && !uentry_isValid (ue))
1599 return (message ("<missing type: %d>", uid));
1602 llassertprint (uentry_isValid (ue), ("type undefined: %d", uid));
1604 return (uentry_getName (ue));
1608 /*@unused@*/ static void
1609 usymtab_rehash (/*@notnull@*/ usymtab s)
1613 if (cstringTable_isDefined (s->htable))
1615 cstringTable_free (s->htable);
1618 s->htable = cstringTable_create (LLAHSHSIZE);
1620 for (i = 0; i < s->nentries; i++)
1622 cstringTable_insert (s->htable, cstring_copy (uentry_rawName (s->entries[i])), i);
1628 ** superficial copy of usymtab
1630 ** DO copy spec entries
1633 static /*@only@*/ /*@notnull@*/ usymtab
1634 usymtab_shallowCopy (/*@notnull@*/ usymtab s) /*@*/
1636 usymtab copytab = usymtab_createRoot ();
1639 for (i = 0; i < s->nentries; i++)
1641 usymtab_addEntryBase (copytab, s->entries[i]);
1648 usymtab_shallowFree (/*@only@*/ /*@notnull@*/ usymtab s)
1650 aliasTable_free (s->aliases);
1651 refTable_free (s->reftable, s->nentries);
1653 /*@-compdestroy@*/ sfree (s); /*@=compdestroy@*/
1657 ** converts usymId from old table to sorted one
1661 usymtab_convertId (usymId uid)
1662 /*@globals oldtab, utab@*/
1668 llassert (usymtab_isDefined (oldtab));
1670 ue = usymtab_getEntryAux (oldtab, uid);
1672 llassertprint (uentry_isValid (ue), ("convertId: undefined: %d", uid));
1674 name = uentry_rawName (ue);
1676 ret = usymtab_getIndex (utab, name);
1677 llassert (ret == uid); /*! for now, no rehash! */
1678 DPRINTF (("Convert: %s [%d] -> %s [%d]",
1679 uentry_unparse (ue), uid,
1680 uentry_unparse (utab->entries[ret]), ret));
1682 llassertprint (ret != USYMIDINVALID, ("convertId: return is invalid"));
1688 usymtab_prepareDump (void)
1689 /*@globals oldtab, utab@*/
1690 /*@modifies oldtab, utab@*/
1692 llassert (usymtab_inGlobalScope ());
1693 llassert (oldtab == usymtab_undefined);
1696 DPRINTF (("Preparing to dump:"));
1697 usymtab_printAll ();
1700 oldtab = usymtab_shallowCopy (utab);
1703 ** alpha compare - make sure order is same on different platforms
1704 ** error messages appear in same order
1708 qsort (utab->entries, (size_t)utab->nentries,
1709 sizeof (*utab->entries),
1710 (int (*)(const void *, const void *)) uentry_xcomparealpha);
1712 usymtab_rehash (utab);
1716 DPRINTF (("After rehash:"));
1717 usymtab_printAll ();
1721 void usymtab_dump (FILE *fout)
1722 /*@globals utab, oldtab@*/
1725 bool neednl = FALSE;
1726 uentry lastentry = uentry_undefined;
1727 ekind lastekind = KINVALID;
1731 ** must call prepareDump first
1734 llassert (oldtab != usymtab_undefined);
1736 for (i = 0; i < utab->nentries; i++)
1738 uentry thisentry = utab->entries[i];
1739 ekind thisekind = uentry_getKind (thisentry);
1741 if (!uentry_hasRealName (thisentry))
1743 llassert (uentry_isGlobalMarker (thisentry));
1747 check (fputc ('\n', fout) == (int) '\n');
1750 fprintf (fout, "*%d (GlobalMarker)\n", KGLOBALMARKER);
1751 lastekind = KINVALID;
1757 if (thisekind != lastekind)
1761 check (fputc ('\n', fout) == (int) '\n');
1765 lastentry = uentry_undefined;
1766 fprintf (fout, "*%d (%s)\n", ekind_toInt (thisekind),
1767 cstring_toCharsSafe (ekind_capName (thisekind)));
1768 lastekind = thisekind;
1773 ** evans - 2001-02-18 - added the - 48 fudge factor...
1774 ** extra characters dumped, but I haven't counded them carefully...
1777 if (uentry_isInvalid (lastentry) || !uentry_equiv (lastentry, thisentry)
1778 || (linelen > (MAX_DUMP_LINE_LENGTH - (2 * MAX_NAME_LENGTH) - 48)))
1782 DPRINTF (("Dumping entry: %d", i));
1783 cdump = message ("^%d %q", i, uentry_dump (thisentry));
1784 /* was: cdump = uentry_dump (thisentry)); */
1786 lastentry = thisentry;
1789 check (fputc ('\n', fout) == (int) '\n');
1793 linelen += cstring_length (cdump);
1795 /* no new line here! */
1796 if (cstring_length (cdump) > 0)
1798 check (fputs (cstring_toCharsSafe (cdump), fout) != EOF);
1801 cstring_free (cdump);
1806 cstring cdump = uentry_rawName (thisentry);
1807 DPRINTF (("Raw name: %s", cdump));
1808 linelen += (cstring_length (cdump) + 1);
1809 fprintf (fout, "#%s", cstring_toCharsSafe (cdump));
1816 check (fputc ('\n', fout) == (int) '\n');
1819 lastekind = KINVALID;
1821 fprintf(fout, ";; Library constraints\n");
1823 /*drl July 27 added this so that libraries without
1824 buffer constraints would be handled correctly.
1825 I'm trying to do this without breaking older libraries.
1827 Splint should still be able to handle libraries without this message.
1831 fprintf(fout, "start_Buffer_Constraints\n");
1833 for (i = 0; i < utab->nentries; i++)
1835 uentry thisentry = utab->entries[i];
1837 if (uentry_isFunction (thisentry) )
1839 constraintList preconditions;
1840 constraintList postconditions;
1842 preconditions = uentry_getFcnPreconditions (thisentry);
1843 postconditions = uentry_getFcnPostconditions (thisentry);
1845 if ( constraintList_isDefined(preconditions) ||
1846 constraintList_isDefined(postconditions) )
1848 fprintf(fout,"%s\n", cstring_toCharsSafe (uentry_rawName(thisentry) ) );
1849 if (constraintList_isDefined(preconditions) )
1851 fprintf(fout,"pre:\n");
1852 constraintList_dump(preconditions, fout);
1853 fprintf (fout, ";; end precondition constraints\n" );
1854 constraintList_free(preconditions);
1858 fprintf(fout,"pre:EMPTY\n");
1860 if (constraintList_isDefined(postconditions) )
1862 fprintf(fout,"post:\n");
1863 constraintList_dump(postconditions, fout);
1864 fprintf (fout, ";; end precondition constraints\n" );
1865 constraintList_free(postconditions);
1869 fprintf(fout,"post:EMPTY\n");
1878 void usymtab_load (FILE *f)
1879 /*@globals utab, globtab@*/
1880 /*@modifies utab, *f@*/
1882 char *s = mstring_create (MAX_DUMP_LINE_LENGTH);
1884 ekind kind = KINVALID;
1885 fileloc loc = g_currentloc;
1891 llassert (utab == globtab);
1892 llassert (utab->nentries == 0);
1894 while (((s = reader_readLine (f, s, MAX_DUMP_LINE_LENGTH)) != NULL)
1897 /* ignore ; comments */ ;
1900 while (s != NULL && *s != ';')
1908 ek = reader_getInt (&s);
1910 if (ek == KGLOBALMARKER)
1912 uentry lue = uentry_makeGlobalMarker ();
1913 DPRINTF (("Adding global marker: %s", uentry_unparseFull (lue)));
1914 usymtab_addEntryAlways (utab, lue);
1920 kind = ekind_fromInt (ek);
1928 (cstring_makeLiteral
1929 ("Library is in obsolete format. Use splint +whichlib "
1930 "to see which library is being loaded."));
1933 if (reader_optCheckChar (&s, '^'))
1935 index = reader_getInt (&s);
1942 llassert (kind != KINVALID);
1943 ue = uentry_undump (kind, loc, &s);
1945 llassert (utab->nentries == index || index == -1);
1947 if (uentry_isValid (ue))
1949 int lastindex = utab->nentries;
1950 ue = usymtab_addEntryAlways (utab, ue);
1954 if (uentry_isConstant (ue)) /*@i23! isPreProcessorMacro */
1956 cstring uname = uentry_getName (ue);
1958 /* Also check its a macro... */
1959 DPRINTF (("Installing: %s", uname));
1961 cpphash_installMacro
1962 (mstring_copy (cstring_toCharsSafe (uname)),
1963 cstring_length (uname),
1964 cpplib_createDefinition (message ("%s 255", uname),
1967 cpphash_hashCode (cstring_toCharsSafe (uname),
1968 cstring_length (uname),
1971 DPRINTF (("After install: %s", uname));
1975 if (utab->nentries != lastindex + 1)
1977 DPRINTF (("No add: %s", uentry_unparseFull (ue)));
1985 ** now, any other names are the same uentry
1988 while (*(s++) == '#')
1990 cstring name = cstring_fromCharsO (reader_getWord (&s));
1991 uentry nue = uentry_nameCopy (name, ue);
1993 DPRINTF (("Name copy: %s", uentry_unparseFull (nue)));
1997 usymtab_addEntryAlways (utab, nue);
2000 while ((c = *s) != '\0' && (c !='\n'))
2002 if (c != ' ' || c != '\t')
2004 llbuglit ("Junk in load file");
2012 s = reader_readLine (f, os, MAX_DUMP_LINE_LENGTH);
2017 to handle reading of buffer overflow related constraints
2019 while (fgets (s, MAX_DUMP_LINE_LENGTH, f) != NULL
2022 ; /* ignore ;-comments */
2025 /*drl July 27 added this so that libraries without
2026 buffer constraints would be handled correctly.
2027 I'm trying to do this without breaking older libraries*/
2029 /*check for "optional" start buffer constraints message*/
2031 if (mstring_equalPrefix (s, "start_Buffer_Constraints"))
2033 (void) fgets (s, MAX_DUMP_LINE_LENGTH, f);
2036 while (s != NULL && *s != ';')
2038 constraintList preconditions;
2039 constraintList postconditions;
2041 cstring name = cstring_fromChars(reader_getWord(&s) );
2043 ue = usymtab_lookup ( name );
2047 preconditions = constraintList_undefined;
2048 postconditions = constraintList_undefined;
2050 if (!uentry_isValid(ue) )
2052 llfatalbug ((message("Invalid uentry for %s library file may be corrupted", cstring_fromChars(s) ) ));
2054 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2056 temp = cstring_fromChars (reader_getWord(&s) );
2058 if (cstring_compareLit (temp,"pre:") == 0 )
2060 preconditions = constraintList_undump (f);
2064 if (cstring_compareLit (temp,"pre:EMPTY") != 0 )
2065 llfatalbug ((message("Error reading library file pre:EMPTY expected but got %s", temp ) ));
2070 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2072 temp = cstring_fromChars(reader_getWord(&s) );
2073 if (cstring_compareLit (temp, "post:") == 0 )
2075 postconditions = constraintList_undump (f);
2079 if (cstring_compareLit (temp, "post:EMPTY") != 0 )
2080 llfatalbug ((message("Error reading library file post:EMPTY expected but got %s", temp ) ));
2083 cstring_free (temp);
2085 uentry_setPreconditions (ue, functionConstraint_createBufferConstraint (preconditions));
2086 uentry_setPostconditions (ue, functionConstraint_createBufferConstraint (postconditions));
2088 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2096 ** file scope for static variables
2100 usymtab_enterFile ()
2101 /*@globals utab, globtab, filetab@*/
2102 /*@modifies filetab@*/
2104 llassert (utab == globtab);
2109 usymtab_entries (globtab, ue)
2111 if (sRef_hasDerived (uentry_getSref (ue)))
2113 fprintf (g_warningstream, "Derived Global: %s\n", uentry_unparse (ue));
2114 fprintf (g_warningstream, "sRef: %s\n", sRef_unparseFull (ue->sref));
2116 } end_usymtab_entries ;
2120 usymtab_enterScope ();
2126 /*@globals utab, filetab@*/
2127 /*@modifies filetab, utab@*/
2130 llassert (utab->lexlevel == 1);
2132 usymtab_exitScope (exprNode_undefined);
2137 usymtab_enterScope ()
2138 /*@globals utab, globtab, filetab@*/
2141 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
2143 /* unconditional scope: optimize to avoid copy */
2144 t->aliases = aliasTable_copy (utab->aliases);
2147 llassert (usymtab_isDefined (t->env));
2149 if (t->env->lexlevel == paramsScope && context_inFunctionLike ())
2151 noshadowerror = TRUE;
2152 usymtab_handleParams ();
2153 noshadowerror = FALSE;
2158 ** setup external references:
2159 ** o only, unique params alias external args
2160 ** o other params may alias anything of their type
2164 usymtab_handleParams (void)
2165 /*@globals utab, globtab, filetab@*/
2166 /*@modifies utab, globtab@*/
2168 usymtab ptab = utab->env;
2169 uentry fcn = context_getHeader ();
2171 usymtab_entries (ptab, param)
2175 if (!uentry_isYield (param))
2178 sRef pref = uentry_getSref (param);
2180 /* Could be a global. */
2182 if (uentry_isAnyParam (param))
2184 ue = uentry_makeVariable (fixParamName (uentry_rawName (param)),
2185 uentry_getType (param),
2186 fileloc_copy (uentry_whereDeclared (param)),
2189 uentry_copyState (ue, param);
2190 uentry_setRefParam (ue);
2192 ue = usymtab_supEntrySrefReturn (ue);
2194 /* must be after supercede! */
2196 if (!sRef_stateKnown (pref))
2198 uentry_setDefState (ue, SS_DEFINED);
2199 uentry_setDefState (param, SS_DEFINED);
2203 if (sRef_isStateSpecial (pref))
2205 uentry_setDefState (ue, SS_SPECIAL); /* ALLOCATED); */
2206 /* evans 2002-01-01: should be unnecessary, the pre clauses
2207 ** set the state if necessary.
2212 uentry_setDefState (ue, sRef_getDefState (pref));
2216 uref = uentry_getSref (ue);
2218 if (sRef_isStack (uref))
2220 alkind pkind = sRef_getAliasKind (pref);
2222 if (alkind_isKnown (pkind) && !alkind_isLocal (pkind)
2223 && !alkind_isStack (pkind))
2225 sRef_setAliasKind (uref, pkind, fileloc_undefined);
2226 sRef_setOrigAliasKind (uref, pkind);
2230 sRef_setAliasKind (uref, AK_IMPTEMP, fileloc_undefined);
2231 sRef_setOrigAliasKind (uref, AK_IMPTEMP);
2233 if (uentry_isOut (param))
2239 sRef_setDefined (uref, fileloc_undefined);
2245 usymtab_addMustAlias (uref, pref);
2247 if (!(uentry_isOnly (param) || uentry_isUnique (param)))
2250 ** This is needed for detecting possibly aliased parameters.
2253 sRef s = sRef_makeExternal (uref);
2254 usymtab_addMustAlias (uref, s);
2257 if (sRef_isKillRef (pref))
2259 sRef_setAliasKind (uref, AK_NEWREF, fileloc_undefined);
2260 sRef_setOrigAliasKind (uref, AK_KILLREF);
2262 else if (sRef_isRefCounted (uref))
2264 sRef_setOrigAliasKind (uref, AK_REFCOUNTED);
2269 sRef_setOrigAliasKind (uref, AK_LOCAL);
2276 } end_usymtab_entries;
2279 if (uentry_hasStateClauseList (fcn))
2281 stateClauseList clauses = uentry_getStateClauseList (fcn);
2283 stateClauseList_preElements (clauses, cl)
2285 fileloc loc = stateClause_loc (cl);
2286 sRefSet osrs = sRefSet_undefined;
2289 if (stateClause_isGlobal (cl))
2291 DPRINTF (("Global Marker: %s",
2292 sRef_unparseFull (usymtab_lookupGlobalMarker ())));
2293 llassert (sRef_isGlobalMarker (usymtab_lookupGlobalMarker ()));
2294 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
2299 srs = stateClause_getRefs (cl);
2302 sRefSet_elements (srs, el)
2304 sRef base = sRef_getRootBase (el);
2305 sRef sb = sRef_updateSref (el);
2307 if (sRef_isResult (base))
2309 ; /* nothing to do before */
2311 else if (sRef_isParam (base) || sRef_isGlobalMarker (base))
2313 if (stateClause_setsMetaState (cl))
2315 /* copied from exprNode.c:3040 */
2316 qual ql = stateClause_getMetaQual (cl);
2317 annotationInfo ainfo = qual_getAnnotationInfo (ql);
2318 metaStateInfo minfo = annotationInfo_getState (ainfo);
2319 cstring key = metaStateInfo_getName (minfo);
2320 int mvalue = annotationInfo_getValue (ainfo);
2322 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
2324 if (sRef_isResult (base))
2330 sRef_setMetaStateValueComplete (sb, key, mvalue, loc);
2335 sRefMod modf = stateClause_getEntryFunction (cl);
2339 sRefSet aliases = usymtab_allAliases (sb);
2343 sRefSet_elements (aliases, sr)
2346 } end_sRefSet_elements ;
2348 sRefSet_free (aliases);
2354 if (sRef_isValid (base))
2356 DPRINTF (("Base: %s", sRef_unparseFull (base)));
2360 } end_sRefSet_elements ;
2361 } end_stateClauseList_preElements ;
2366 usymtab_enterFunctionScope (uentry fcn)
2367 /*@globals utab, filetab, globtab@*/
2370 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
2372 DPRINTF (("Enter function: %s", uentry_unparse (fcn)));
2374 if (utab->lexlevel != fileScope)
2376 if (utab->lexlevel > fileScope)
2378 llparseerror (cstring_makeLiteral ("New function scope inside function"));
2380 while (utab->lexlevel > fileScope)
2382 /*@i@*/ utab = usymtab_dropEnv (utab);
2389 llfatalbug (cstring_makeLiteral ("New function not inside file."));
2391 /*@-branchstate@*/ } /*@=branchstate@*/
2395 DPRINTF (("Globs: %s", globSet_unparse (uentry_getGlobs (fcn))));
2397 globSet_allElements (uentry_getGlobs (fcn), el)
2399 DPRINTF (("Here we go: %s", sRef_unparseFull (el)));
2401 if (sRef_isUndefGlob (el))
2403 int index = sRef_getScopeIndex (el);
2404 sRef sr = sRef_updateSref (el);
2405 fileloc loc = uentry_whereEarliest (fcn);
2407 DPRINTF (("update: %s", sRef_unparseFull (sr)));
2408 DPRINTF (("Undef!"));
2409 if (sRef_isFileStatic (el))
2411 ctype ct = sRef_getType (el);
2414 llassert (usymtab_isDefined (filetab));
2416 ue = usymtab_fetchIndex (filetab, index);
2418 if (ctype_isRealArray (ct) || ctype_isRealSU (ct))
2420 sRef_setAllocated (sr, loc);
2424 sRef_setUndefined (sr, loc);
2429 uentry ue = globtab->entries[index];
2430 ctype ct = uentry_getType (ue);
2432 if (ctype_isArray (ct) || ctype_isSU (ct))
2434 sRef_setAllocated (sr, loc);
2438 sRef_setUndefined (sr, loc);
2442 else if (sRef_isAllocated (el))
2444 sRef sr = sRef_updateSref (el);
2445 fileloc loc = uentry_whereEarliest (fcn);
2447 sRef_setAllocated (sr, loc);
2449 else if (sRef_isPartial (el))
2451 sRef sr = sRef_updateSref (el);
2452 fileloc loc = uentry_whereEarliest (fcn);
2454 sRef_setPartial (sr, loc);
2459 sRef sr = sRef_updateSref (el);
2460 fileloc loc = uentry_whereEarliest (fcn);
2462 sRef_setDefined (sr, loc);
2466 /* shouldn't need to do anything! */
2468 } end_globSet_allElements;
2470 DPRINTF (("Globs after: %s", globSet_unparse (uentry_getGlobs (fcn))));
2472 usymtab_checkAllValid ();
2477 usymtab_caseBranch (void)
2480 usymtab t = usymtab_create (US_CBRANCH, utab, FALSE);
2485 usymtab_switchBranch (/*@unused@*/ exprNode s)
2488 usymtab t = usymtab_create (US_SWITCH, utab, FALSE);
2490 t->aliases = aliasTable_copy (utab->aliases);
2495 usymtab_trueBranch (/*@only@*/ guardSet guards)
2498 usymtab t = usymtab_create (US_TBRANCH, utab, FALSE);
2501 ** not true! (could be in a macro)
2503 ** llassertprint (utab->lexlevel > paramsScope,
2504 ** ("not in scope: %s", usymtab_unparseLocal ()));
2508 guardSet_free (t->guards);
2511 aliasTable_free (t->aliases);
2512 t->aliases = aliasTable_copy (utab->aliases);
2520 ** { int a; if (...) a = 3; < a may be undefined here!
2525 usymtab_popTrueBranch (exprNode pred, exprNode expr, clause cl) /*@modifies utab@*/
2528 ** add a false branch
2529 ** (could be done more efficiently as a special case, but
2530 ** it is better to only maintain one version of the code)
2533 if (utab->kind != US_TBRANCH
2534 && context_inIterDef ())
2536 usymtab_exitScope (expr);
2540 DPRINTF (("pop true branch.."));
2541 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2542 usymtab_popBranches (pred, expr, exprNode_undefined, TRUE, cl);
2547 usymtab_popCaseBranch () /*@modifies utab@*/
2549 llassert (utab->kind == US_CBRANCH);
2550 usymtab_quietPlainExitScope ();
2554 usymtab_popTrueExecBranch (exprNode pred, exprNode expr, clause cl)
2557 ** add a false branch that must return --- that is,
2558 ** the true branch is always executed!
2561 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2562 usymtab_popBranches (pred, expr, exprNode_makeMustExit (), FALSE, cl);
2566 usymtab_popOrBranch (exprNode pred, exprNode expr)
2570 usymtab env = utab->env;
2571 usymtab otab = utab;
2574 llassert (env != NULL);
2576 if (exprNode_isError (expr))
2582 mustReturn = exprNode_mustEscape (expr);
2586 llassert (utab->kind == US_TBRANCH);
2589 ** merge each entry in table with its original
2590 ** unless execution cannot continue after this branch
2593 for (i = 0; i < utab->nentries; i++)
2595 uentry current = utab->entries[i];
2596 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2598 uentry_mergeState (old, current, exprNode_loc (expr),
2599 mustReturn, FALSE, TRUE, ORCLAUSE);
2605 env->guards = guardSet_levelUnionFree (env->guards,
2606 guardSet_invert (exprNode_getGuards (pred)),
2611 env->aliases = aliasTable_levelUnion (env->aliases, otab->aliases, env->lexlevel);
2614 /* env is now utab */
2615 usymtab_quietPlainExitScope ();
2619 ** case syntax in C is very unrestricted. This is unfortunate.
2621 ** A switch case is ended either by a new case or default, or
2622 ** a close } that may close the switch or some other control
2627 usymtab_newCase (/*@unused@*/ exprNode pred, exprNode last)
2630 bool mustBreak = usymtab_mustBreak (utab);
2631 bool mustReturn = usymtab_mustEscape (utab);
2632 usymtab stab = utab;
2634 DPRINTF (("New case!"));
2637 ** Find last case (or outer switch)
2640 while (stab->kind != US_CBRANCH && stab->kind != US_SWITCH)
2643 llassert (stab != GLOBAL_ENV);
2646 while (stab->kind == US_CBRANCH)
2649 llassert (stab != GLOBAL_ENV);
2653 ** if its a fall through case, merge in outside entries and last case.
2658 ** case 1: x = 3; <fall through>
2659 ** case 2: << x may not be defined
2663 if (!mustBreak && !mustReturn && utab->kind == US_CBRANCH)
2665 llassert (stab->kind == US_SWITCH || stab->kind == US_NORMAL);
2667 usymtab_entries (utab, ue) /* but, keep track of used variables */
2669 uentry old = usymtab_lookupAux (stab, uentry_rawName (ue));
2671 llassert (uentry_isValid (old));
2673 /* modifies ue, not old */
2675 uentry_mergeState (ue, old, exprNode_loc (last),
2676 FALSE, FALSE, TRUE, CASECLAUSE);
2677 } end_usymtab_entries;
2679 utab->aliases = aliasTable_levelUnion (utab->aliases,
2680 stab->aliases, utab->lexlevel);
2683 ** No need for a new branch.
2690 usymtab_caseBranch ();
2691 /*@-mustfree@*/ /*< utab->aliases >*/
2692 utab->aliases = aliasTable_copy (stab->aliases);
2700 ** for && (both pred and expr are executed)
2704 usymtab_popAndBranch (exprNode pred, /*@unused@*/ exprNode expr)
2707 usymtab env = utab->env;
2711 llassert (utab->kind == US_TBRANCH);
2714 ** merge each entry in table with its original
2715 ** unless execution cannot continue after this branch
2718 for (i = 0; i < utab->nentries; i++)
2720 uentry current = utab->entries[i];
2721 sRef tref = uentry_getSref (current);
2722 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2723 sRef oref = uentry_getSref (old);
2725 /* note that is current is in a nested branch,
2726 it may create a "new" old entry. */
2728 llassert (uentry_isValid (old));
2729 uentry_mergeState (old, current, exprNode_loc (expr),
2730 FALSE, FALSE, TRUE, ANDCLAUSE);
2733 ** if is it defined by the second clause, then it should be defined.
2736 if (sRef_isAnyDefined (tref)
2737 && (sRef_isAllocated (oref) || sRef_isStateUndefined (oref)))
2739 sRef_setDefined (oref, g_currentloc);
2743 utab->guards = guardSet_levelUnionFree (utab->guards,
2744 guardSet_invert (exprNode_getGuards (pred)),
2746 utab->aliases = aliasTable_levelUnion (utab->aliases, otab->aliases, utab->lexlevel);
2748 usymtab_quietPlainExitScope ();
2753 ** Stack should be [ US_CBRANCH+ US_SWITCH ]
2754 ** Only branches which do not return (except possibly the last branch) are included.
2756 ** Conditionally merge state from all CBRANCHes.
2758 ** If allpaths is TRUE, then all possible executions go through some switch
2759 ** case, and the original scope is not merged.
2763 usymtab_exitSwitch (/*@unused@*/ exprNode sw, bool allpaths)
2766 usymtab ttab = utab;
2767 usymtab stab = ttab;
2768 usymtab ltab = ttab;
2769 bool lastMustReturn = usymtab_mustEscape (utab);
2773 while (stab->kind == US_CBRANCH)
2776 llassert (stab != GLOBAL_ENV);
2779 while (stab->kind == US_NORMAL)
2782 llassert (stab != GLOBAL_ENV);
2785 llassert (stab->kind == US_SWITCH);
2787 /* go to the scope outside the switch (US_SWITCH is just a marker! */
2789 llassert (stab != GLOBAL_ENV);
2793 llassert (usymtab_isDefined (ttab));
2795 if (ttab->kind == US_CBRANCH)
2797 /* was quietPlainExitScope --- but, can't free it yet! */
2799 llassert (utab != GLOBAL_ENV);
2801 while (ttab->kind == US_CBRANCH)
2804 ** (from popTrueBranch)
2807 bool mustReturn = usymtab_mustEscape (ttab);
2808 bool mustBreak = usymtab_mustBreak (ttab);
2810 usymtab_entries (ttab, current)
2812 uentry old = /*@-compmempass@*/ usymtab_lookupAux (ltab, uentry_rawName (current));
2816 ** note that is this is in a nested branch,
2817 ** it may create a "new" old entry.
2820 if (uentry_isValid (old))
2824 uentry_mergeUses (current, old);
2825 uentry_setState (old, current);
2829 uentry_mergeState (old, current, exprNode_loc (sw),
2830 mustReturn, FALSE, TRUE, SWITCHCLAUSE);
2837 } end_usymtab_entries;
2840 ** if entry is not in symbol table for this case, merge with pre-switch
2844 if (!mustReturn && !mustBreak)
2846 usymtab_entries (stab, current)
2848 if (usymtab_getIndex (ttab, uentry_rawName (current)) == NOT_FOUND)
2850 uentry old = /*@-compmempass@*/
2851 usymtab_lookupAux (ltab, uentry_rawName (current));
2854 llassert (uentry_isValid (old));
2855 uentry_mergeState (old, current, exprNode_loc (sw),
2856 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2858 } end_usymtab_entries;
2861 ltab->env = ttab->env;
2865 ** Suprious error, becuase of environments.
2868 /*@i1@*/ utab = ltab;
2870 lastMustReturn = FALSE;
2877 ** now, there is one US_CBRANCH. Merge this with the stab.
2881 for (i = 0; i < ltab->nentries; i++)
2883 uentry current = ltab->entries[i];
2884 uentry old = usymtab_lookupAux (stab, uentry_rawName (current));
2886 /* note that is this is in a nested branch,
2887 it may create a "new" old entry. */
2890 if (uentry_isValid (old))
2894 uentry_mergeUses (current, old);
2895 uentry_setState (old, current);
2899 uentry_mergeState (old, current, exprNode_loc (sw),
2900 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2914 ** switch may or may not be followed by a new scope
2917 if (utab->kind == US_SWITCH)
2919 usymtab_quietPlainExitScope ();
2923 usymtab_quietPlainExitScope ();
2924 llassert (utab->kind == US_SWITCH);
2925 usymtab_quietPlainExitScope ();
2931 updateNullState (sRef el, /*@notnull@*/ usymtab ttab,
2932 /*@notnull@*/ usymtab ftab, bool trueGuard)
2934 sRef base = sRef_getRootBase (el);
2935 int level = sRef_lexLevel (base);
2937 if (sRef_isCvar (base))
2939 usymId index = sRef_getScopeIndex (base);
2940 uentry ue = usymtab_getRefTab (ttab, level, index);
2942 if (!uentry_isLset (ue))
2944 sRef sr = uentry_getSref (ue);
2948 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2952 if (!guardSet_isGuarded (ttab->guards, el)
2953 && !sRef_isNotNull (sr))
2955 DPRINTF (("Here! %s / %s",
2956 sRef_unparseFull (sr),
2957 sRef_unparseFull (el)));
2958 sRef_setDerivNullState (sr, el, NS_DEFNULL);
2967 ue = usymtab_getRefTab (ftab, level, index);
2969 if (!uentry_isLset (ue))
2971 sRef sr = uentry_getSref (ue);
2973 if (!trueGuard) /* yikes! forgot the ! */
2975 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2980 if (!guardSet_isGuarded (ftab->guards, el)
2981 && !sRef_isNotNull (sr))
2983 sRef_setDerivNullState (sr, el, NS_DEFNULL);
2995 usymtab_popBranches (exprNode pred, exprNode tbranch, exprNode fbranch,
2996 bool isOpt, clause cl)
3000 usymtab ftab = utab;
3001 usymtab ttab = utab->env;
3005 guardSet guards = exprNode_getGuards (pred);
3006 sRefSet tguards = guardSet_getTrueGuards (guards);
3007 sRefSet fguards = guardSet_getFalseGuards (guards);
3008 bool mustReturnT = exprNode_mustEscape (tbranch);
3009 bool mustReturnF = exprNode_mustEscape (fbranch);
3011 DPRINTF (("Pop branches: %s [mustreturn: %s/%s]", exprNode_unparse (pred),
3012 bool_unparse (mustReturnT),
3013 bool_unparse (mustReturnF)));
3015 if (exprNode_isDefined (fbranch))
3017 loc = exprNode_loc (fbranch);
3021 loc = exprNode_loc (tbranch);
3024 llassert (usymtab_isDefined (ttab));
3028 llassert (usymtab_isDefined (env));
3029 llassert (ftab->kind == US_FBRANCH);
3030 llassert (ttab->kind == US_TBRANCH);
3033 ** For each element that is true guarded (i.e., if (x != NULL))
3034 ** make x = null in false branch,
3035 ** and x = notnull in true branch.
3036 ** unless x was set locally in that branch.
3037 ** For each element that is false guarded (x == NULL)
3038 ** make x = null in true, notnull in false.
3040 ** For each element that is either guarded (pred(x))
3044 sRefSet_allElements (tguards, el)
3046 updateNullState (el, ttab, ftab, TRUE);
3047 } end_sRefSet_allElements;
3049 sRefSet_allElements (fguards, el)
3051 updateNullState (el, ttab, ftab, FALSE);
3052 } end_sRefSet_allElements;
3056 ** if an entry is in both true and false, merge the entries,
3057 ** then replace original with new state.
3059 ** if an entry is in one table, merge it with the original.
3062 DPRINTF (("ftab: %d", ftab->nentries));
3064 for (i = 0; i < ftab->nentries; i++)
3066 uentry fthis = ftab->entries[i];
3067 uentry old = usymtab_lookupAux (env, uentry_rawName (fthis));
3068 int tindex = usymtab_getIndex (ttab, uentry_rawName (fthis));
3070 DPRINTF (("Entry: %s / %s", uentry_unparseFull (fthis), uentry_unparseFull (old)));
3072 if (uentry_isUndefined (old))
3074 /* possible entry was added as an undefined id */
3075 DPRINTF (("Undefined! %s", uentry_rawName (fthis)));
3079 if (tindex != NOT_FOUND)
3081 uentry tthis = ttab->entries[tindex];
3083 /* note that is this is in a nested branch,
3084 it may create a "new" old entry. */
3090 uentry_mergeState (fthis, tthis, loc,
3091 mustReturnT, FALSE, FALSE, cl);
3095 uentry_mergeUses (fthis, tthis);
3098 uentry_setState (old, fthis);
3105 uentry_setState (old, tthis);
3106 uentry_mergeState (old, fthis, loc, mustReturnF,
3110 ttab->entries[tindex] = uentry_undefined;
3111 uentry_free (tthis);
3115 uentry_mergeState (old, fthis, loc, mustReturnF, TRUE, FALSE, cl);
3119 for (i = 0; i < ttab->nentries; i++)
3121 uentry current = ttab->entries[i];
3123 DPRINTF (("ttab: %s", uentry_unparseFull (current)));
3125 if (!uentry_isUndefined (current))
3127 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
3129 DPRINTF (("Old: %s", uentry_unparseFull (old)));
3131 if (uentry_isUndefined (old))
3133 llcontbug (message ("Undefined entry: %s", uentry_rawName (current)));
3139 uentry_mergeUses (current, old);
3140 uentry_setState (old, current);
3145 ** Assumes false branch is a fall-through if
3146 ** fbranch is not defined. This is true, unless
3147 ** where was some greivous error in processing
3148 ** the else branch of an if-then, in which case
3149 ** this is probably the right thing to do anyway.
3152 uentry_mergeState (old, current, loc, mustReturnT,
3156 DPRINTF (("==> %s", uentry_unparseFull (old)));
3161 ** Plain levelUnion doesn't work, since we need to use the sRef's in env->aliases
3162 ** if they are present.
3165 llassert (NOALIAS (env->aliases, ttab->aliases));
3166 llassert (NOALIAS (env->aliases, ftab->aliases));
3168 aliasTable_free (env->aliases);
3170 env->aliases = aliasTable_levelUnionNew (ttab->aliases,
3171 ftab->aliases, env->lexlevel);
3173 aliasTable_fixSrefs (env->aliases);
3175 DPRINTF (("Aliases: %s", aliasTable_unparse (env->aliases)));
3177 /* exit true and false scopes */
3178 usymtab_quietPlainExitScope ();
3179 usymtab_quietPlainExitScope ();
3183 utab->guards = guardSet_levelUnionFree
3185 guardSet_invert (exprNode_getGuards (pred)),
3191 utab->guards = guardSet_levelUnion (utab->guards,
3192 exprNode_getGuards (pred),
3196 DPRINTF (("Here."));
3199 static void usymtab_fixCases (void) /*@modifies utab@*/ {
3200 while (utab->kind == US_CBRANCH)
3202 usymtab_quietPlainExitScope ();
3205 llassert (utab->kind != US_CBRANCH);
3209 usymtab_altBranch (/*@only@*/ guardSet guards)
3213 usymtab parent = utab->env;
3215 t = usymtab_create (US_FBRANCH, utab, FALSE);
3218 ** If we are in a case, need to close it. The C syntax
3219 ** is very liberal, so this kludge is necessary.
3222 usymtab_fixCases ();
3224 DPRINTF (("Current kind: %s", usymtab_unparseStack ()));
3226 llassert (utab->kind == US_TBRANCH);
3227 llassert (parent != GLOBAL_ENV);
3229 guardSet_free (t->guards);
3232 aliasTable_free (t->aliases);
3233 t->aliases = aliasTable_copy (parent->aliases);
3239 usymtab_allDefined (void)
3240 /*@globals utab, globtab@*/
3244 llassert (utab == globtab);
3246 for (i = 0; i < utab->nentries; i++)
3248 uentry e = utab->entries[i];
3250 if (uentry_isPriv (e))
3252 ; /* no need to define it */
3256 if (context_getFlag (FLG_SPECUNDECL))
3258 fileloc sloc = uentry_whereSpecified (e);
3259 fileloc dloc = uentry_whereDeclared (e);
3261 if (fileloc_isDefined (sloc)
3262 && !uentry_isFakeTag (e)
3263 && !fileloc_isDefined (dloc))
3267 message ("%s %q specified but not declared",
3268 ekind_capName (uentry_getKind (e)),
3269 uentry_getName (e)),
3274 if (!uentry_isCodeDefined (e))
3276 fileloc dloc = uentry_whereDeclared (e);
3278 if (fileloc_isLib (dloc) || fileloc_isXHFile (dloc))
3282 else if (fileloc_isDefined (dloc))
3284 if (!uentry_isAnyTag (e))
3286 if (fileloc_isUser (dloc))
3290 message ("%s %q declared but not defined",
3291 ekind_capName (uentry_getKind (e)),
3292 uentry_getName (e)),
3294 DPRINTF (("decl: %s", uentry_unparseFull (e)));
3300 fileloc sloc = uentry_whereSpecified (e);
3302 if (fileloc_isDefined (sloc)
3303 && !fileloc_isImport (sloc)
3304 && !fileloc_isLib (sloc)
3305 && !fileloc_isPreproc (sloc)
3306 && !uentry_isFakeTag (e))
3308 if (uentry_isVariable (e) || uentry_isFunction (e))
3312 message ("%s %q specified but not declared or defined",
3313 ekind_capName (uentry_getKind (e)),
3314 uentry_getName (e)),
3321 message ("%s %q specified but not defined",
3322 ekind_capName (uentry_getKind (e)),
3323 uentry_getName (e)),
3333 void usymtab_exportHeader (void)
3338 for (i = 0; i < utab->nentries; i++)
3340 uentry ce = utab->entries[i];
3342 if (!uentry_isDatatype (ce)
3343 && !uentry_isAnyTag (ce)
3344 && !uentry_isEitherConstant (ce) && !uentry_isStatic (ce)
3345 && !uentry_isExternal (ce)
3346 && !uentry_isForward (ce))
3348 fileloc fwhere = uentry_whereDeclared (ce);
3350 if (fileloc_isUndefined (fwhere)
3351 && uentry_isFunction (ce))
3353 fwhere = uentry_whereDefined (ce);
3356 if (fileloc_isDefined (fwhere)
3357 && !fileloc_isHeader (fwhere)
3358 && !fileloc_isXHFile (fwhere)
3359 && !(fileloc_isSpecialFile (fwhere)
3360 && !context_getFlag (FLG_UNUSEDSPECIAL)))
3362 if (uentry_isVariable (ce))
3365 (FLG_EXPORTHEADERVAR,
3366 message ("%s %q exported but not declared in header file",
3367 ekind_capName (uentry_getKind (ce)),
3368 uentry_getName (ce)),
3371 uentry_showDefSpecInfo (ce, fwhere);
3376 if (!uentry_isIter (ce)
3377 && !uentry_isEndIter (ce)
3378 && !uentry_isExpandedMacro (ce))
3380 if (uentry_isFunction (ce)
3381 && cstring_equalLit (uentry_rawName (ce), "main"))
3383 ; /* no error for main */
3389 message ("%s %q exported but not declared "
3391 ekind_capName (uentry_getKind (ce)),
3392 uentry_getName (ce)),
3395 uentry_showDefSpecInfo (ce, fwhere);
3405 void usymtab_exportLocal (void)
3410 for (i = 0; i < utab->nentries; i++)
3412 uentry ce = utab->entries[i];
3414 if (!uentry_isDatatype (ce) && !uentry_isAnyTag (ce)
3415 && !uentry_isEitherConstant (ce)
3416 && !uentry_isIter (ce)
3417 && !uentry_isEndIter (ce)
3418 && !uentry_isExpandedMacro (ce)
3419 && uentry_isUsed (ce))
3421 /* check static uses */
3422 filelocList fuses = uentry_getUses (ce);
3423 fileloc mod = uentry_whereDefined (ce);
3424 bool ok = filelocList_isEmpty (fuses);
3425 fileloc fwhere = uentry_whereDeclared (ce);
3427 if (fileloc_isSpecialFile (fwhere)
3428 && !context_getFlag (FLG_UNUSEDSPECIAL))
3430 ok = TRUE; /* no errors for special files */
3434 filelocList_elements (fuses, uloc)
3436 if (fileloc_isUndefined (uloc) || !fileloc_sameModule (uloc, mod))
3439 /*@innerbreak@*/ break;
3441 } end_filelocList_elements;
3448 message ("%s exported but not used outside %s: %q",
3449 ekind_capName (uentry_getKind (ce)),
3450 fileloc_getBase (mod),
3451 uentry_getName (ce)),
3454 uentry_showDefSpecInfo (ce, fwhere);
3462 usymtab_allUsed (void)
3466 bool isFileStatic = usymtab_inFileScope ();
3467 cstring last_file = cstring_undefined;
3469 for (i = 0; i < utab->nentries; i++)
3471 bool hasError = FALSE;
3472 uentry ce = utab->entries[i];
3473 fileloc fwhere = uentry_whereDeclared (ce);
3475 if (fileloc_isUndefined (fwhere))
3477 fwhere = uentry_whereDefined (ce);
3480 if (fileloc_isInvalid (fwhere)
3481 || fileloc_isLib (fwhere)
3482 || fileloc_isBuiltin (fwhere)
3483 || ((fileloc_isSpecialFile (fwhere)
3484 || fileloc_isSpecialFile (uentry_whereDefined (ce)))
3485 && !context_getFlag (FLG_UNUSEDSPECIAL)))
3489 else if (!uentry_wasUsed (ce) && !uentry_isAnyTag (ce))
3491 cstring fname = fileloc_filename (fwhere);
3493 if (cstring_isUndefined (last_file))
3497 else if (cstring_equal (fname, last_file))
3506 if (uentry_isParam (ce))
3508 if (context_inMacro ())
3510 sRef cref = uentry_getSref (ce);
3512 if (uentry_isYield (ce))
3514 ; /* no checks (for now) */
3516 else if (sRef_isSafe (cref))
3522 if (uentry_hasRealName (ce))
3525 optgenerror (FLG_MACROPARAMS,
3526 message ("Macro parameter %q not used",
3527 uentry_getName (ce)),
3534 if (cstring_equalFree (uentry_getName (ce),
3535 cstring_makeLiteral ("...")))
3541 hasError = optgenerror (FLG_PARAMUNUSED,
3542 message ("Parameter %q not used",
3543 uentry_getName (ce)),
3548 else if (uentry_isFunction (ce) || uentry_isIter (ce))
3550 if (fileloc_isUser (fwhere))
3552 hasError = optgenerror
3554 message ("%q %q declared but not used",
3556 (uentry_isIter (ce) ? "Iterator"
3557 : (isFileStatic ? "File static function" : "Function")),
3558 uentry_getName (ce)),
3562 else if (uentry_isEndIter (ce))
3564 ; /* no error (already reported for iter */
3566 else if (uentry_isEnumConstant (ce))
3568 if (fileloc_isUser (fwhere))
3570 hasError = optgenerror
3572 message ("Enum member %q not used",
3573 uentry_getName (ce)),
3577 else if (uentry_isConstant (ce))
3579 if (fileloc_isUser (fwhere))
3581 hasError = optgenerror
3583 message ("Constant %q declared but not used",
3584 uentry_getName (ce)),
3588 else if (uentry_isDatatype (ce))
3590 if (fileloc_isUser (fwhere))
3592 hasError = optgenerror
3594 message ("Type %q declared but not used",
3595 uentry_getName (ce)),
3599 else if (!uentry_isRefParam (ce) && !uentry_isExpandedMacro (ce))
3600 { /* errors for ref params will be reported in the next scope */
3601 llassertprint (uentry_isVar (ce),
3602 ("ce: %s", uentry_unparseFull (ce)));
3604 if (ctype_isFunction (uentry_getType (ce)))
3606 if (fileloc_isUser (fwhere))
3608 hasError = optgenerror
3610 message ("%q %q declared but not used",
3612 (isFileStatic ? "File static function"
3614 uentry_getName (ce)),
3620 if (fileloc_isUser (fwhere))
3624 hasError = optgenerror
3626 message ("%q %q declared but not used",
3628 (isFileStatic ? "File static variable"
3630 uentry_getName (ce)),
3640 else if ((uentry_isDatatype (ce) || uentry_isAnyTag (ce)))
3641 { /* check all fields */
3642 ctype ct = uentry_getRealType (ce);
3645 while (ctype_isAP (ct))
3647 ct = ctype_getBaseType (ct);
3650 if (ctype_isSU (ct))
3652 uentryList fields = ctype_getFields (ct);
3654 uentryList_elements (fields, field)
3656 if (!uentry_isUsed (field))
3658 if (uentry_hasName (ce))
3660 hasError |= optgenerror
3662 message ("Field %q of %s %q declared but not used",
3663 uentry_getName (field),
3664 cstring_makeLiteralTemp
3665 (ctype_isStruct (ct) ? "structure" : "union"),
3666 uentry_getName (ce)),
3667 uentry_whereEarliest (field));
3673 ** Can't report these errors for unnamed structs.
3674 ** No way to tell when there are multiple consistent
3675 ** unnamed structure types. (Could go through table
3676 ** and mark them all unused...)
3678 hasError |= optgenerror
3680 message ("Field %q of unnamed %s declared but not used",
3681 uentry_getName (field),
3682 cstring_makeLiteralTemp
3683 (ctype_isStruct (ct) ? "structure" : "union")),
3684 uentry_whereEarliest (field));
3689 uentry_setUsed (field, fileloc_undefined);
3691 } end_uentryList_elements;
3701 if (uentry_isParam (ce) && context_inMacro ())
3703 if (fileloc_isDefined (uentry_whereSpecified (ce)))
3705 uentry_showWhereSpecified (ce);
3710 uentry_showDefSpecInfo (ce, fwhere);
3713 uentry_setUsed (ce, fileloc_undefined);
3719 checkGlobalReturn (uentry glob, sRef orig)
3721 sRef sr = uentry_getSref (glob);
3723 DPRINTF (("Check global return: %s / orig: %s / sr: %s",
3724 uentry_unparseFull (glob),
3725 sRef_unparseFull (orig),
3726 sRef_unparseFull (sr)));
3728 DPRINTF (("Is killed: %s", bool_unparse (sRef_isKilledGlob (orig))));
3730 if (context_getFlag (FLG_GLOBSTATE))
3732 DPRINTF (("Is killed: %s", sRef_unparseFull (orig)));
3734 if (sRef_isKilledGlob (orig))
3736 if (sRef_isStateUndefined (sr)
3737 || sRef_isUnuseable (sr)
3738 || sRef_isStateUnknown (sr)
3739 || sRef_isDead (sr))
3745 ctype ct = ctype_realType (uentry_getType (glob));
3747 DPRINTF (("Check global destroyed: %s", uentry_unparseFull (glob)));
3749 if (ctype_isVisiblySharable (ct))
3754 ("Killed global %q (type %s) not released before return",
3755 uentry_getName (glob),
3756 ctype_unparse (ct)),
3759 sRef_showStateInfo (sr);
3764 sRef_protectDerivs ();
3765 (void) transferChecks_globalDestroyed (sr, g_currentloc);
3766 sRef_clearProtectDerivs ();
3772 if (sRef_isStateUndefined (sr))
3774 if (optgenerror (FLG_GLOBSTATE,
3776 ("Function returns with global %q undefined",
3777 uentry_getName (glob)),
3780 sRef_showStateInfo (sr);
3785 if (sRef_isDead (sr) || sRef_isKept (sr))
3789 message ("Function returns with global %q "
3790 "referencing %s storage",
3791 uentry_getName (glob),
3792 cstring_makeLiteralTemp (sRef_isDead (sr) ? "released" : "kept")),
3795 if (sRef_isKept (sr))
3797 sRef_showAliasInfo (sr);
3801 sRef_showStateInfo (sr);
3804 sRef_setDefState (sr, SS_UNKNOWN, fileloc_undefined);
3808 if (ctype_isRealPointer (uentry_getType (glob))
3809 && sRef_possiblyNull (sr)
3810 && !uentry_possiblyNull (glob))
3814 message ("Function returns with non-null global %q "
3815 "referencing null storage",
3816 uentry_getName (glob)),
3819 sRef_showNullInfo (sr);
3824 DPRINTF (("Check transfer: %s", uentry_unparseFull (glob)));
3825 transferChecks_globalReturn (glob);
3833 ** remember: check alias globals
3836 void usymtab_checkFinalScope (bool isReturn)
3839 bool mustFree = context_getFlag (FLG_MUSTFREEONLY) || context_getFlag (FLG_MUSTFREEFRESH); /*@i423 remove this mustFree */
3840 bool mustDefine = context_getFlag (FLG_MUSTDEFINE);
3841 /* bool mustNotAlias = context_getFlag (FLG_MUSTNOTALIAS); */
3842 sRefSet checked = sRefSet_new ();
3843 usymtab stab = utab;
3847 ** need to check all scopes out to function parameters.
3852 for (i = 0; i < stab->nentries; i++)
3854 uentry ce = stab->entries[i];
3855 sRef sr = uentry_getSref (ce);
3856 sRef rb = sRef_getRootBase (sr);
3860 ** Shouldn't check if shadow checked in deeper scope:
3865 uentry oue = usymtab_lookupQuietNoAlt (utab, uentry_observeRealName (ce));
3867 if (!uentry_sameObject (ce, oue))
3869 DPRINTF (("Skipping outer entry: %s / %s", uentry_unparseFull (ce),
3870 uentry_unparseFull (oue)));
3871 /*@i32 what if it is one an alternate branch? */
3872 /*@innercontinue@*/ continue;
3876 DPRINTF (("Here check final scope: %s", uentry_unparseFull (ce)));
3878 if (ctype_isFunction (uentry_getType (ce)))
3880 /*@innercontinue@*/ continue;
3883 if (uentry_isAnyParam (ce)
3884 || uentry_isRefParam (ce)
3885 || sRef_isFileOrGlobalScope (rb))
3887 /* Don't do the loseref check...but should check state! */
3888 DPRINTF (("Skipping check 1"));
3890 else if (sRef_isDefinitelyNull (sr)
3891 || usymtab_isDefinitelyNull (sr))
3894 ** No state reference errors for definitely null references.
3897 DPRINTF (("Skipping check 2"));
3901 DPRINTF (("Lose ref: %s / %s", uentry_unparse (ce),
3902 sRef_unparseFull (sr)));
3904 tvalues = sRef_getValueTable (sr);
3906 valueTable_elements (tvalues, fkey, fval) {
3907 metaStateInfo minfo;
3908 cstring msg = cstring_undefined;
3911 minfo = context_lookupMetaStateInfo (fkey);
3912 llassert (metaStateInfo_isDefined (minfo));
3914 if (stateValue_isError (fval)
3915 || sRef_isStateUndefined (sr)) /* No errors for undefined state */
3917 DPRINTF (("Skipping check 3"));
3921 DPRINTF (("Check: %s / %s / %s", fkey,
3922 metaStateInfo_unparse (minfo),
3923 stateValue_unparse (fval)));
3925 minfo = context_lookupMetaStateInfo (fkey);
3927 nval = stateCombinationTable_lookupLoseReference
3928 (metaStateInfo_getTransferTable (minfo),
3929 stateValue_getValue (fval), &msg);
3931 if (cstring_isDefined (msg))
3933 /*@i32 print extra info for assignments@*/
3934 DPRINTF (("From: %s", sRef_unparseFull (sr)));
3935 DPRINTF (("Null? %s / %s",
3936 bool_unparse (sRef_isDefinitelyNull (sr)),
3937 bool_unparse (usymtab_isGuarded (sr))));
3942 ("%s loses reference %q in invalid state %q (%s)",
3943 cstring_makeLiteralTemp (isReturn ? "Return" : "Scope exit"),
3944 uentry_getName (ce),
3945 stateValue_unparseValue (fval, minfo),
3949 stateValue_show (fval, minfo);
3953 DPRINTF (("Suppressed transfer error: %s", msg));
3957 } end_valueTable_elements;
3960 DPRINTF (("Here 1"));
3964 DPRINTF (("Check mustfree entry: %s", uentry_unparseFull (ce)));
3966 if (!sRefSet_member (checked, sr) && !sRef_isFileOrGlobalScope (rb))
3968 if (ctype_isRealSU (uentry_getType (ce))
3969 && !uentry_isAnyParam (ce)
3970 && !uentry_isRefParam (ce)
3971 && !uentry_isStatic (ce)
3972 && !sRef_isDependent (sr)
3973 && !sRef_isOwned (sr))
3975 sRefSet als = usymtab_allAliases (sr);
3977 if (sRefSet_isEmpty (als))
3979 transferChecks_localDestroyed (sr, g_currentloc);
3983 /* aliased, no problem */ ;
3989 (!uentry_isStatic (ce)
3990 && ((sRef_isNewRef (sr))
3991 || (((sRef_isOnly (sr) || sRef_isFresh (sr)
3992 || sRef_isKeep (sr) || sRef_isOwned (sr))
3993 && !sRef_isDead (sr))
3994 && (!sRef_definitelyNull (sr))
3995 && (!usymtab_isDefinitelyNull (sr)))))
3997 bool hasError = TRUE;
3999 DPRINTF (("Checking: %s", sRef_unparseFull (sr)));
4002 ** If its a scope exit, check if there is an alias.
4003 ** If so, make it only. If not, there is an error.
4008 if (transferChecks_canLoseReference (sr, g_currentloc))
4010 DPRINTF (("Can lose!"));
4017 if (sRef_hasLastReference (sr))
4019 sRef ar = sRef_getAliasInfoRef (sr);
4022 (sRef_isFresh (ar) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4024 ("Last reference %q to %s storage %qnot %q before %q",
4026 alkind_unparse (sRef_getAliasKind (sr)),
4027 sRef_unparseOpt (ar),
4028 cstring_makeLiteral (sRef_isKeep (sr)
4029 ? "transferred" : "released"),
4030 cstring_makeLiteral (isReturn
4031 ? "return" : "scope exit")),
4034 sRef_showRefLost (sr);
4037 else if (sRef_isNewRef (sr))
4040 (sRef_isFresh (sr) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4042 ("%q %q not released before %q",
4044 (alkind_isKillRef (sRef_getOrigAliasKind (sr))
4045 ? "Kill reference parameter" : "New reference"),
4046 uentry_getName (ce),
4047 cstring_makeLiteral (isReturn
4048 ? "return" : "scope exit")),
4051 sRef_showAliasInfo (sr);
4056 if (ctype_isRealSU (sRef_getType (sr)))
4058 transferChecks_structDestroyed (sr, g_currentloc);
4062 DPRINTF (("Here we are: %s", sRef_unparseFull (sr)));
4065 (sRef_isFresh (sr) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4067 ("%s storage %q not %q before %q",
4068 alkind_capName (sRef_getAliasKind (sr)),
4069 uentry_getName (ce),
4070 cstring_makeLiteral (sRef_isKeep (sr)
4071 ? "transferred" : "released"),
4072 cstring_makeLiteral (isReturn
4073 ? "return" : "scope exit")),
4076 sRef_showAliasInfo (sr);
4077 DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
4090 if (mustDefine && uentry_isOut (ce))
4092 /* No error if its dead (either only or error already reported */
4093 if (!sRef_isReallyDefined (sr) && !sRef_isDead (sr))
4097 message ("Out storage %q not defined before %q",
4098 uentry_getName (ce),
4100 (isReturn ? "return" : "scope exit")),
4103 DPRINTF (("sr: %s", sRef_unparseFull (sr)));
4108 ** also check state is okay
4111 if (usymtab_lexicalLevel () > functionScope
4112 && uentry_isVariable (ce)
4113 && (sRef_isLocalVar (sr)
4114 && (sRef_isDependent (sr) || sRef_isLocalState (sr))))
4116 sRefSet ab = usymtab_aliasedBy (sr);
4118 /* should do something more efficient here */
4120 if (sRefSet_isEmpty (ab))
4122 /* and no local ref */
4123 DPRINTF (("Check lose ref: %s", uentry_unparseFull (ce)));
4124 transferChecks_loseReference (ce);
4138 checked = sRefSet_insert (checked, sr);
4141 llassert (usymtab_isDefined (stab->env));
4143 if (usymtab_isBranch (stab))
4145 stab = usymtab_dropEnv (stab);
4152 llassert (stab != usymtab_undefined);
4153 } while (isReturn && (stab->lexlevel >= paramsScope));
4155 sRefSet_free (checked);
4159 ** all globals are appropriately defined
4160 ** all parameters are appropriately defined
4161 ** special clauses are followed
4164 if (isReturn || (utab->lexlevel == paramsScope))
4166 uentry fcn = context_getHeader ();
4167 uentryList params = context_getParams ();
4168 globSet uglobs = context_getUsedGlobs ();
4169 globSet sglobs = context_getGlobs ();
4171 if (isReturn && context_maybeSet (FLG_GLOBALIAS))
4173 aliasTable_checkGlobs (utab->aliases);
4177 ** state clauses (ensures, defines, sets, allocates, releases)
4180 if (uentry_hasStateClauseList (fcn))
4182 stateClauseList clauses = uentry_getStateClauseList (fcn);
4184 stateClauseList_elements (clauses, cl)
4186 if (stateClause_isAfter (cl) && !stateClause_isGlobal (cl))
4188 if (stateClause_setsMetaState (cl))
4190 sRefSet rfs = stateClause_getRefs (cl);
4191 qual q = stateClause_getMetaQual (cl);
4192 annotationInfo ainfo = qual_getAnnotationInfo (q);
4193 metaStateInfo minfo = annotationInfo_getState (ainfo);
4194 cstring key = metaStateInfo_getName (minfo);
4195 int mvalue = annotationInfo_getValue (ainfo);
4197 DPRINTF (("Post meta state clause: %s", stateClause_unparse (cl)));
4199 sRefSet_elements (rfs, el)
4201 sRef base = sRef_getRootBase (el);
4203 if (sRef_isResult (base))
4206 ** This is checked for return transfers.
4210 else if (sRef_isParam (base) || sRef_isGlobalMarker (base))
4212 sRef sr = sRef_updateSref (base);
4213 sr = sRef_fixBase (el, sr);
4215 if (!sRef_checkMetaStateValue (sr, key, mvalue))
4220 ("Ensures clause not satisfied%q (state is %q): %q",
4221 sRef_isGlobalMarker (sr)
4223 : message (" by %q", sRef_unparse (sr)),
4224 stateValue_unparseValue (sRef_getMetaStateValue (sr, key),
4226 stateClause_unparse (cl)),
4229 sRef_showMetaStateInfo (sr, key);
4235 if (sRef_isMeaningful (el))
4240 } end_sRefSet_elements ;
4244 /* evs - 2000 07 10 - added this */
4245 sRefTest tst = stateClause_getPostTestFunction (cl);
4246 sRefSet rfs = stateClause_getRefs (cl);
4248 sRefSet_elements (rfs, el)
4250 sRef base = sRef_getRootBase (el);
4252 if (sRef_isResult (base))
4255 ** This is checked for return transfers.
4260 else if (sRef_isParam (base))
4262 sRef sr = sRef_updateSref (base);
4263 sr = sRef_fixBase (el, sr);
4265 if (tst != NULL && !tst (sr))
4268 (stateClause_postErrorCode (cl),
4269 message ("%s storage %qcorresponds to "
4270 "storage listed in %q clause",
4271 stateClause_postErrorString (cl, sr),
4272 sRef_unparseOpt (sr),
4273 stateClause_unparseKind (cl)),
4276 sRefShower ss = stateClause_getPostTestShower (cl);
4283 DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
4289 if (sRef_isMeaningful (el))
4294 } end_sRefSet_elements ;
4297 } end_stateClauseList_elements ;
4301 ** check parameters on return
4304 uentryList_elements (params, arg)
4306 if (!uentry_isElipsisMarker (arg))
4308 ctype rt = ctype_realType (uentry_getType (arg));
4310 if (ctype_isMutable (rt) || ctype_isSU (rt))
4312 uentry param = usymtab_lookupQuiet (utab, uentry_rawName (arg));
4313 DPRINTF (("Check param return: %s", uentry_unparseFull (param)));
4314 transferChecks_paramReturn (param);
4317 } end_uentryList_elements;
4319 DPRINTF (("Check global return: %s",
4320 globSet_unparse (sglobs)));
4322 globSet_allElements (sglobs, el)
4324 sRef orig = el; /*! sRef_updateSref (el); */ /*!!!*/
4325 uentry current = sRef_getUentry (el);
4327 DPRINTF (("Check global return: %s / %s", sRef_unparseFull (el),
4328 uentry_unparseFull (current)));
4330 if (uentry_isVariable (current) && !uentry_isRealFunction (current))
4332 checkGlobalReturn (current, orig);
4334 } end_globSet_allElements;
4336 globSet_allElements (uglobs, el)
4338 if (!globSet_member (sglobs, el))
4340 uentry current = sRef_getUentry (el);
4342 if (uentry_isVariable (current)
4343 && !uentry_isRealFunction (current))
4345 checkGlobalReturn (current, sRef_undefined);
4348 } end_globSet_allElements;
4353 usymtab_quietExitScope (fileloc loc)
4354 /*@globals utab, globtab, filetab; @*/
4357 usymtab t = utab->env;
4359 DPRINTF (("Quiet exit scope [%p]", utab));
4361 if (utab->reftable != NULL)
4365 for (i = 0; i < utab->nentries; i++)
4367 uentry current = utab->entries[i];
4368 uentry old = usymtab_lookupAux (t, uentry_rawName (current));
4370 uentry_mergeState (old, current, loc, FALSE, FALSE, FALSE, NOCLAUSE);
4374 llassert (t != NULL);
4376 if (t->lexlevel > paramsScope)
4378 t->guards = guardSet_levelUnion (t->guards, utab->guards, t->lexlevel);
4379 t->aliases = aliasTable_levelUnionSeq (t->aliases, utab->aliases,
4381 utab->aliases = aliasTable_undefined;
4384 t->mustBreak = utab->mustBreak;
4385 t->exitCode = utab->exitCode;
4387 DPRINTF (("Free level [%p]", utab));
4388 usymtab_freeLevel (utab);
4393 usymtab_checkAllValid ();
4398 ** Exit a scope with no checking, lose alias states.
4399 ** (When should this be used?)
4402 void usymtab_quietPlainExitScope (void)
4403 /*@globals utab, globtab, filetab@*/
4406 usymtab t = utab->env;
4408 llassert (t != NULL);
4409 llassert (NOALIAS (utab->aliases, t->aliases));
4410 usymtab_freeLevel (utab);
4414 void usymtab_exitScope (exprNode expr)
4415 /*@globals utab, filetab, globtab@*/
4416 /*@modifies utab, globtab@*/
4418 usymtab ctab = usymtab_undefined;
4419 usymtab lctab = usymtab_undefined;
4420 bool mustReturn = exprNode_mustEscape (expr);
4422 DPRINTF (("Exit scope [%p]", utab));
4424 if (utab->kind == US_CBRANCH)
4427 ** save the case branches, remove the first non-cbranch
4432 while (utab->kind == US_CBRANCH)
4436 llassert (utab != GLOBAL_ENV);
4440 if (utab->kind == US_TBRANCH || utab->kind == US_FBRANCH
4441 || utab->kind == US_CBRANCH || utab->kind == US_SWITCH)
4443 if (context_inMacro ())
4445 /* evs 2000-07-25 */
4446 /* Unparseable macro may end inside nested scope. Deal with it. */
4448 llerror (FLG_SYNTAX,
4449 message ("Problem parsing macro body of %s (unbalanced scopes). "
4450 "Attempting to recover, recommend /*@notfunction@*/ before "
4451 "macro definition.",
4452 context_inFunctionName ()));
4454 while (utab->kind == US_TBRANCH
4455 || utab->kind == US_FBRANCH
4456 || utab->kind == US_CBRANCH
4457 || utab->kind == US_SWITCH)
4460 llassert (utab != GLOBAL_ENV);
4464 llcontbug (message ("exitScope: in branch: %q", usymtab_unparseStack ()));
4466 } /*@=branchstate@*/
4470 ** check all variables in scope were used
4474 ** bogus errors if this is the normal inside a switch,
4475 ** since cases have not been merged yet. Should probably
4476 ** still check this, but I'm too lazy at the moment...
4479 llassertfatal (utab->env != GLOBAL_ENV);
4481 if (utab->env->kind != US_SWITCH)
4487 ** check aliasing: all only params are released (dead)
4488 ** definition: all out params are defined, all modified params
4489 ** are completely defined
4491 ** NOTE: note for exiting paramsScope, since checkReturn should be
4495 if (!mustReturn && (usymtab_lexicalLevel () > functionScope))
4498 ** should only call this is end of scope is reachable...
4501 usymtab_checkFinalScope (FALSE);
4504 if (usymtab_lexicalLevel () == paramsScope && context_inFunctionLike ())
4507 ** leaving a function, need to fix up globals
4510 uentryList params = context_getParams ();
4511 globSet globs = context_getUsedGlobs ();
4513 uentryList_elements (params, ue)
4515 uentry_fixupSref (ue);
4516 } end_uentryList_elements;
4518 clearFunctionTypes ();
4520 DPRINTF (("Fixing up globals: %s", globSet_unparse (globs)));
4522 globSet_allElements (globs, el)
4524 DPRINTF (("Fix: %s", sRef_unparseDebug (el)));
4526 if (sRef_isCvar (el))
4529 int index = sRef_getScopeIndex (el);
4531 if (sRef_isFileStatic (el))
4533 llassert (usymtab_isDefined (filetab));
4534 current = usymtab_fetchIndex (filetab, index);
4538 current = usymtab_fetchIndex (globtab, index);
4541 if (uentry_isVariable (current))
4543 DPRINTF (("Fixup: %s", uentry_unparse (current)));
4544 uentry_fixupSref (current);
4548 DPRINTF (("Clear: %s", uentry_getSref (current)));
4549 sRef_clearDerived (uentry_getSref (current));
4553 sRef_clearDerived (el); /* evans 2002-03-14 - this is the likely source of many crashes! */
4554 } end_globSet_allElements;
4557 usymtab_quietExitScope (exprNode_loc (expr));
4559 if (lctab != usymtab_undefined)
4561 /*@i@*/ lctab->env = utab;
4562 /*@i@*/ utab = ctab;
4563 /*@-branchstate@*/ } /*@=branchstate@*/
4568 usymtab_checkAllValid ();
4574 ** yikes! don't let the '170 kids see this one...
4578 uentry_directParamNo (uentry ue)
4580 if (uentry_isVar (ue))
4582 sRef sr = uentry_getSref (ue);
4584 if (sRef_lexLevel (sr) == functionScope)
4586 int index = sRef_getScopeIndex (sr);
4588 if (index < uentryList_size (context_getParams ()))
4597 /*@dependent@*/ /*@exposed@*/ uentry
4598 usymtab_getParam (int paramno)
4602 ** requires in a function context (checked)
4604 ** depends on no nested functions --- the function
4605 ** parameters are ALWAYS one scope inside the global scope
4606 ** and entered in order!
4610 if (!context_inFunctionLike ())
4611 llfatalbug (message ("usymtab_getParam: not in function context: %q",
4612 context_unparse ()));
4614 while (s->lexlevel > paramsScope)
4619 llassert (usymtab_isDefined (s));
4621 if (paramno >= s->nentries)
4624 ** Parse errors lead to this.
4627 uentry err = uentry_makeVariableLoc (cstring_makeLiteralTemp ("<error>"),
4630 uentry_markOwned (err);
4634 return (s->entries[paramno]);
4637 static /*@dependent@*/ /*@exposed@*/ uentry
4638 usymtab_getRefTab (/*@notnull@*/ usymtab u, int level, usymId index)
4642 ue = usymtab_getRefNoisy (u, level, index);
4644 if (uentry_isUndefined (ue))
4646 llbug (message ("usymtab_getRef: out of range: %d. level = %d",
4653 static /*@dependent@*/ /*@exposed@*/ usymtab
4654 usymtab_dropEnv (/*@notnull@*/ usymtab s)
4656 if (s->kind == US_CBRANCH)
4664 llassert (s != GLOBAL_ENV);
4665 } while (s->kind == US_CBRANCH);
4666 /* drop all cases (except in nested scopes */
4669 llassert (s != GLOBAL_ENV);
4672 if (s->kind == US_FBRANCH)
4674 s = s->env; /* skip the true branch */
4675 llassert (usymtab_isDefined (s));
4676 llassert (s->kind == US_TBRANCH);
4679 llassert (s != GLOBAL_ENV);
4685 /*@dependent@*/ /*@exposed@*/ uentry
4686 usymtab_getRefQuiet (int level, usymId index)
4692 llassert (s != NULL);
4693 llassert (index >= 0);
4695 if (level > s->lexlevel)
4697 return uentry_undefined;
4700 llassertprint (level <= s->lexlevel, ("level: %d / lexlevel: %d",
4701 level, s->lexlevel));
4703 while (s->lexlevel > level)
4705 if (usymtab_isBranch (s))
4707 int eindex = refTable_lookup (s, level, index);
4709 if (eindex != NOT_FOUND)
4711 return (s->entries[eindex]);
4715 s = usymtab_dropEnv (s);
4718 while (usymtab_isBranch (s) && s->lexlevel == level)
4720 int eindex = refTable_lookup (s, level, index);
4722 if (eindex != NOT_FOUND)
4724 return (s->entries[eindex]);
4727 s = usymtab_dropEnv (s);
4730 if (index >= s->nentries)
4732 return uentry_undefined;
4735 llassert (!uentry_isUndefined (s->entries[index]));
4737 return s->entries[index];
4740 static /*@dependent@*/ /*@exposed@*/ uentry
4741 usymtab_getRefNoisy (/*@notnull@*/ usymtab s, int level, usymId index)
4744 uentry ue = uentry_undefined;
4746 llassert (index >= 0);
4748 while (s->lexlevel > level)
4750 if (usymtab_isBranch (s))
4752 int eindex = refTable_lookup (s, level, index);
4754 if (eindex != NOT_FOUND)
4756 ue = s->entries[eindex];
4760 while (!usymtab_isBranch (otab))
4762 otab = usymtab_dropEnv (otab);
4763 llassert (otab != GLOBAL_ENV);
4766 if (refTable_lookup (otab, level, index) == NOT_FOUND)
4768 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4780 s = usymtab_dropEnv (s);
4783 llassert (usymtab_isDefined (s));
4785 while (usymtab_isBranch (s) && s->lexlevel == level)
4787 int eindex = refTable_lookup (s, level, index);
4790 if (eindex != NOT_FOUND)
4792 ue = s->entries[eindex];
4796 while (!usymtab_isBranch (otab))
4798 otab = usymtab_dropEnv (otab);
4799 llassert (otab != GLOBAL_ENV);
4802 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4812 s = usymtab_dropEnv (s);
4815 if (s->lexlevel == level && (index < s->nentries))
4817 ue = s->entries[index];
4819 if (uentry_isValid (ue))
4823 while (!usymtab_isBranch (otab))
4825 otab = usymtab_dropEnv (otab);
4827 if (otab == GLOBAL_ENV)
4833 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4844 if (index >= s->nentries)
4846 return uentry_undefined;
4849 llassert (!uentry_isUndefined (s->entries[index]));
4851 return s->entries[index];
4855 ** looking up entries
4857 ** If entry is inside a branch, then copy it, and put it into
4858 ** the branch table.
4862 int refTable_lookup (/*@notnull@*/ usymtab ut, int level, int index)
4864 refTable rt = ut->reftable;
4867 llassert (rt != NULL);
4869 for (i = 0; i < ut->nentries; i++)
4871 if (rt[i]->level == level && rt[i]->index == index)
4881 /*@only@*/ refentry refentry_create (int level, int index)
4883 refentry r = (refentry) dmalloc (sizeof (*r));
4891 static /*@dependent@*/ /*@exposed@*/ uentry
4892 usymtab_addRefEntry (/*@notnull@*/ usymtab s, cstring k)
4897 if (ut->reftable == NULL)
4899 DPRINTF (("Adding ref entry without reftable: %s", k));
4900 return uentry_undefined;
4903 llassert (ut->reftable != NULL);
4905 while (s != GLOBAL_ENV)
4907 eindex = usymtab_getIndex (s, k);
4909 if (eindex != NOT_FOUND)
4911 uentry current = s->entries[eindex];
4913 if (uentry_isVar (current) && !ctype_isFunction (uentry_getType (current)))
4917 DPRINTF (("Here: copying %s", uentry_unparse (current)));
4918 if (uentry_isNonLocal (current))
4920 ue = uentry_copy (current);
4924 ue = uentry_copyNoSave (current);
4927 DPRINTF (("Here: copying %s", uentry_unparse (ue)));
4928 usymtab_addEntryQuiet (ut, ue);
4929 DPRINTF (("Okay..."));
4931 if (s->reftable != NULL)
4933 refentry ref = s->reftable[eindex];
4935 ut->reftable[ut->nentries - 1]
4936 = refentry_create (ref->level, ref->index);
4940 ut->reftable[ut->nentries - 1]
4941 = refentry_create (s->lexlevel, eindex);
4952 s = usymtab_dropEnv (s);
4955 return uentry_undefined;
4958 static uentry usymtab_lookupAux (usymtab s, cstring k)
4960 DPRINTF (("Lookup: %s", k));
4962 while (s != GLOBAL_ENV)
4964 int eindex = usymtab_getIndex (s, k);
4966 if (eindex != NOT_FOUND)
4968 uentry ret = s->entries[eindex];
4972 if (s->kind == US_TBRANCH
4973 || s->kind == US_FBRANCH
4974 || s->kind == US_CBRANCH)
4975 /* uentry_isGlobalVariable (ret) && os->lexlevel > fileScope) */
4978 DPRINTF (("Adding global ref entry: %s", k));
4979 ret = usymtab_addRefEntry (os, k);
4980 DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
4985 DPRINTF (("Found: %s", uentry_unparseFull (ret)));
4989 if (s->kind == US_TBRANCH || s->kind == US_FBRANCH
4990 || s->kind == US_CBRANCH)
4992 /* why isn't this os??? */
4993 uentry ret = usymtab_addRefEntry (s, k);
4994 DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
5001 return uentry_undefined;
5004 static /*@dependent@*/ /*@exposed@*/ uentry
5005 usymtab_lookupQuietAux (usymtab s, cstring k, bool noalt)
5009 while (s != GLOBAL_ENV)
5011 eindex = usymtab_getIndex (s, k);
5013 if (eindex != NOT_FOUND)
5015 uentry ret = s->entries[eindex];
5019 if (noalt && usymtab_isBranch (s))
5021 s = usymtab_dropEnv (s);
5025 llassert (s != NULL); /*@i523 should not need this? */
5030 return uentry_undefined;
5033 static /*@exposed@*/ /*@dependent@*/ uentry
5034 usymtab_lookupQuiet (usymtab s, cstring k)
5036 return usymtab_lookupQuietAux (s, k, FALSE);
5039 static /*@exposed@*/ /*@dependent@*/ uentry
5040 usymtab_lookupQuietNoAlt (usymtab s, cstring k)
5042 return usymtab_lookupQuietAux (s, k, TRUE);
5045 /*@dependent@*/ /*@observer@*/ uentry
5046 usymtab_lookupSafe (cstring k)
5049 DPRINTF (("Lookup safe: %s", k));
5050 return (usymtab_lookupAux (utab, k));
5054 usymtab_lookupExpose (cstring k)
5057 uentry ce = usymtab_lookupAux (utab, k);
5059 if (uentry_isUndefined (ce))
5061 llfatalbug (message ("usymtab_lookup: not found: *%s*", k));
5064 if (uentry_isPriv (ce))
5066 llfatalbug (message ("usymtab_lookup: private: *%s*", k));
5072 uentry usymtab_lookupExposeGlob (cstring k)
5074 return (usymtab_lookupGlobSafe (k));
5077 uentry usymtab_lookupGlob (cstring k)
5078 /*@globals globtab@*/
5080 uentry ce = usymtab_lookupAux (globtab, k);
5082 if (uentry_isUndefined (ce))
5083 llfatalbug (message ("usymtab_lookup: not found: %s", k));
5085 if (uentry_isPriv (ce))
5086 llfatalbug (message ("usymtab_lookup: private: %s", k));
5088 DPRINTF (("Lookup global: %s", uentry_unparseFull (ce)));
5092 /*@observer@*/ uentry
5093 usymtab_lookupGlobSafe (cstring k)
5094 /*@globals globtab@*/
5096 uentry ce = usymtab_lookupAux (globtab, k);
5097 DPRINTF (("Lookup global: %s", uentry_unparseFull (ce)));
5101 uentry usymtab_lookupEither (cstring k)
5104 uentry ce = usymtab_lookupSafe (k);
5106 if (uentry_isUndefined (ce))
5107 llfatalerror (message ("usymtab_lookup: not found: %s", k));
5109 DPRINTF (("Lookup either: %s", uentry_unparseFull (ce)));
5114 usymtab_lookupType (cstring k)
5115 /*@globals globtab@*/
5117 usymId uid = usymtab_getTypeId (k);
5119 if (uid == USYMIDINVALID)
5121 llcontbug (message ("usymtab_lookupType: not found: %s", k));
5122 return ctype_unknown;
5125 return (uentry_getRealType (usymtab_getTypeEntry (uid)));
5129 usymtab_lookupAbstractType (cstring k) /*@globals globtab@*/
5131 usymId uid = usymtab_getTypeId (k);
5133 if (uid == USYMIDINVALID)
5135 llcontbug (message ("usymtab_lookupType: not found: %s", k));
5136 return ctype_unknown;
5139 return (uentry_getAbstractType (usymtab_getTypeEntry (uid)));
5143 ** if there is an unnamed lcl-specified struct tag matching
5144 ** the uentryList, return its datatype. Otherwise, returns
5149 usymtab_structFieldsType (uentryList f)
5150 /*@globals globtab@*/
5152 return (usymtab_suFieldsType (f, TRUE));
5156 usymtab_unionFieldsType (uentryList f)
5157 /*@globals globtab@*/
5159 return (usymtab_suFieldsType (f, FALSE));
5163 usymtab_suFieldsType (uentryList f, bool isStruct)
5164 /*@globals globtab@*/
5168 DPRINTF (("Fields: %s", uentryList_unparse (f)));
5170 if (fileloc_isSpec (g_currentloc))
5172 return (ctype_undefined);
5175 for (i = 0; i < globtab->nentries; i++)
5177 uentry current = globtab->entries[i];
5180 ? uentry_isStructTag (current) : uentry_isUnionTag (current)))
5182 if (isFakeTag (uentry_rawName (current)))
5184 ctype ct = uentry_getType (current);
5186 DPRINTF (("Check: %s", ctype_unparse (ct)));
5188 if ((isStruct ? ctype_isStruct (ct) : ctype_isUnion (ct))
5190 (uentry_isSpecified (current)
5191 && uentryList_equivFields (f, ctype_getFields (ct))))
5193 return uentry_getAbstractType (current);
5203 return ctype_undefined;
5207 usymtab_enumEnumNameListType (enumNameList f)
5208 /*@globals globtab@*/
5212 for (i = 0; i < globtab->nentries; i++)
5214 uentry current = globtab->entries[i];
5216 if (uentry_isEnumTag (current))
5218 if (isFakeTag (uentry_rawName (current)))
5220 ctype ct = uentry_getType (current);
5222 if (ctype_isEnum (ct) && (enumNameList_match (f, ctype_elist (ct))))
5224 return uentry_getType (current);
5230 return ctype_undefined;
5234 usymtab_exists (cstring k)
5237 uentry ce = usymtab_lookupSafe (k);
5238 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5242 usymtab_existsReal (cstring k)
5245 uentry ce = usymtab_lookupSafe (k);
5247 return (!(uentry_isUndefined (ce))
5248 && !(uentry_isPriv (ce))
5249 && !(uentry_isExpandedMacro (ce)));
5253 usymtab_existsGlob (cstring k)
5254 /*@globals globtab@*/
5256 uentry ce = usymtab_lookupAux (globtab, k);
5258 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5262 usymtab_existsEither (cstring k)
5265 uentry ce = usymtab_lookupAux (utab, k);
5267 return (uentry_isValid (ce));
5271 usymtab_existsGlobEither (cstring k)
5272 /*@globals globtab@*/
5274 uentry ce = usymtab_lookupAux (globtab, k);
5276 return (uentry_isValid (ce));
5280 usymtab_existsType (cstring k)
5281 /*@globals globtab@*/
5283 uentry ce = usymtab_lookupAux (globtab, k);
5285 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && uentry_isDatatype (ce));
5289 usymtab_existsTypeEither (cstring k)
5290 /*@globals globtab@*/
5293 ce = usymtab_lookupAux (globtab, k);
5294 return (uentry_isValid (ce) && uentry_isDatatype (ce));
5298 usymtab_existsStructTag (cstring k) /*@globals globtab@*/
5300 cstring sname = makeStruct (k);
5301 uentry ce = usymtab_lookupAux (globtab, sname);
5302 cstring_free (sname);
5303 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5307 usymtab_existsUnionTag (cstring k) /*@globals globtab@*/
5309 cstring uname = makeUnion (k);
5310 uentry ce = usymtab_lookupAux (globtab, uname);
5312 cstring_free (uname);
5314 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5318 usymtab_existsEnumTag (cstring k) /*@globals globtab@*/
5320 cstring ename = makeEnum (k);
5321 uentry ce = usymtab_lookupAux (globtab, ename);
5323 cstring_free (ename);
5324 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5327 bool usymtab_existsVar (cstring k)
5330 uentry ce = usymtab_lookupSafe (k);
5332 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && (uentry_isVar (ce)));
5340 refTable_free (/*@only@*/ /*@null@*/ refTable x, int nentries)
5346 for (i = 0; i < nentries; i++)
5356 usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab u)
5357 /*@globals globtab, utab, filetab@*/
5361 DPRINTF (("Free level [%p]", u));
5362 aliasTable_free (u->aliases);
5364 refTable_free (u->reftable, u->nentries);
5366 if (u == filetab || u == globtab)
5368 for (i = 0; i < u->nentries; i++)
5370 DPRINTF (("Free complete: %d", i));
5371 DPRINTF (("Uentry: %s", uentry_unparse (u->entries[i])));
5372 uentry_freeComplete (u->entries[i]);
5373 u->entries[i] = uentry_undefined;
5378 for (i = 0; i < u->nentries; i++)
5380 uentry_free (u->entries[i]);
5381 u->entries[i] = uentry_undefined;
5385 guardSet_free (u->guards);
5392 llassert (!cstringTable_isDefined (u->htable));
5395 sfree (u); /* evans 2002-07-12: was inside if */
5400 usymtab_freeAux (/*@only@*/ usymtab u)
5401 /*@globals globtab, utab, filetab@*/
5404 while (u != GLOBAL_ENV)
5407 usymtab_freeLevel (u);
5414 void usymtab_free ()
5415 /*@globals killed utab, globtab, filetab@*/
5419 usymtab_freeAux (utab);
5420 utab = usymtab_undefined;
5423 static int usymtab_lexicalLevel (void) /*@globals utab@*/
5425 return (utab->lexlevel);
5428 bool usymtab_inGlobalScope () /*@globals utab, globtab@*/
5430 return (utab == globtab);
5433 bool usymtab_inFileScope () /*@globals utab@*/
5435 return (utab->lexlevel == fileScope);
5438 bool usymtab_inFunctionScope () /*@globals utab@*/
5440 return (utab->lexlevel == functionScope);
5444 usymtab_replaceEntry (uentry s)
5445 /*@globals utab, globtab@*/
5446 /*@modifies utab, s@*/
5448 usymtab_replaceEntryAux (utab, s);
5452 usymtab_matchForwardStruct (usymId u1, usymId u2)
5453 /*@globals globtab@*/
5455 uentry ue1 = usymtab_getTypeEntry (u1);
5456 uentry ue2 = usymtab_getTypeEntry (u2);
5458 if (uentry_isAnyTag (ue2))
5460 ctype reptype = uentry_getType (ue1);
5462 if (ctype_isPointer (reptype))
5464 ctype repbase = ctype_getBaseType (reptype);
5466 if (ctype_isUA (repbase))
5468 typeId rtuid = ctype_typeId (repbase);
5470 if (u2 == rtuid) return TRUE;
5472 if (usymId_isValid (rtuid))
5474 reptype = uentry_getType (usymtab_getTypeEntry (rtuid));
5476 return (ctype_isUA (reptype) && (u2 == (ctype_typeId (reptype))));
5485 void usymtab_addGuards (guardSet guards)
5488 utab->guards = guardSet_union (utab->guards, guards);
5491 static bool usymtab_isGuardedAux (sRef s)
5495 sRef base = sRef_getRootBase (s);
5496 int lowlevel = paramsScope;
5497 int baselevel = sRef_lexLevel (base);
5499 if (sRef_isCvar (base))
5501 lowlevel = baselevel;
5502 if (lowlevel < paramsScope) lowlevel = paramsScope;
5505 while (tab->lexlevel >= lowlevel)
5507 DPRINTF (("Is guarded? [%s] %s",
5508 guardSet_unparse (tab->guards),
5509 sRef_unparseFull (s)));
5511 if (guardSet_isGuarded (tab->guards, s))
5514 if (!sRef_definitelyNull (s))
5516 sRef_setNotNull (s, fileloc_undefined);
5522 tab = usymtab_dropEnv (tab);
5528 void usymtab_unguard (sRef s) /*@modifies utab@*/
5531 sRef base = sRef_getRootBase (s);
5532 int lowlevel = paramsScope;
5533 int baselevel = sRef_lexLevel (base);
5535 if (sRef_isCvar (base))
5537 lowlevel = baselevel;
5538 if (lowlevel < paramsScope) lowlevel = paramsScope;
5541 while (tab->lexlevel >= lowlevel)
5543 if (guardSet_isGuarded (tab->guards, s))
5545 guardSet_delete (tab->guards, s);
5548 tab = usymtab_dropEnv (tab);
5552 bool usymtab_isGuarded (sRef s)
5554 DPRINTF (("Is guarded? %s", sRef_unparseFull (s)));
5555 return (sRef_aliasCompleteSimplePred (usymtab_isGuardedAux, s));
5558 bool usymtab_isDefinitelyNull (sRef s)
5560 return (sRef_aliasCheckSimplePred (usymtab_isDefinitelyNullAux, s));
5563 bool usymtab_isDefinitelyNullDeep (sRef s)
5565 return (sRef_deepPred (usymtab_isDefinitelyNull, s));
5568 static bool usymtab_isDefinitelyNullAux (sRef s)
5572 sRef base = sRef_getRootBase (s);
5573 int lowlevel = paramsScope;
5575 if (sRef_isCvar (base))
5577 lowlevel = sRef_lexLevel (base);
5578 if (lowlevel < paramsScope) lowlevel = paramsScope;
5581 while (tab->lexlevel >= lowlevel)
5583 if (guardSet_mustBeNull (tab->guards, s))
5588 while (tab->kind == US_CBRANCH)
5593 llassert (usymtab_isDefined (tab));
5595 if (tab->kind == US_FBRANCH)
5598 llassert (tab->kind == US_TBRANCH);
5608 usymtab_printGuards ()
5609 /*@globals utab, globtab@*/
5611 usymtab ttab = utab;
5613 while (ttab != globtab)
5615 llmsg (message ("Guards [%d]: %q", ttab->lexlevel,
5616 guardSet_unparse (ttab->guards)));
5622 usymtab_displayAllUses ()
5623 /*@globals utab, globtab@*/
5627 /* only in top scope */
5628 llassert (utab == globtab);
5630 /* need a copy, so order is not messed up by sort! */
5631 copy = usymtab_shallowCopy (globtab);
5633 qsort (copy->entries, (size_t)copy->nentries,
5634 sizeof (*copy->entries), (int (*)(const void *, const void *)) uentry_xcompareuses);
5636 usymtab_entries (copy, ue)
5638 if (uentry_isValid (ue) && !uentry_isGlobalMarker (ue))
5640 filelocList uses = uentry_getUses (ue);
5641 int size = filelocList_realSize (uses);
5643 if (fileloc_isDefined (uentry_whereDefined (ue))
5644 && !fileloc_isLib (uentry_whereDefined (ue))
5647 llmsg (message ("%q (%q), %d use%&:\n %q",
5648 uentry_getName (ue),
5649 fileloc_unparse (uentry_whereDefined (ue)),
5650 size, filelocList_unparseUses (uses)));
5653 } end_usymtab_entries;
5655 usymtab_shallowFree (copy);
5658 static /*@dependent@*/ /*@exposed@*/ usymtab
5659 usymtab_getFileTab ()
5660 /*@globals filetab@*/
5662 llassert (filetab != NULL);
5668 usymtab_unparseStack ()
5671 return (usymtab_unparseStackTab (utab));
5674 static /*@only@*/ cstring
5675 usymtab_unparseStackTab (usymtab t)
5677 bool firstOne = TRUE;
5678 cstring ret = cstring_makeLiteral ("[");
5680 while (t != GLOBAL_ENV)
5684 ret = message ("%q %q", ret, usymtab_typeName (t));
5689 ret = message ("%q, %q", ret, usymtab_typeName (t));
5694 ret = message ("%q ]", ret);
5698 static /*@only@*/ cstring
5699 usymtab_typeName (/*@notnull@*/ usymtab t)
5703 case US_GLOBAL: return cstring_makeLiteral ("global");
5704 case US_NORMAL: return cstring_makeLiteral ("normal");
5705 case US_TBRANCH: return cstring_makeLiteral ("true");
5706 case US_FBRANCH: return cstring_makeLiteral ("false");
5707 case US_CBRANCH: return cstring_makeLiteral ("case");
5708 case US_SWITCH: return cstring_makeLiteral ("switch");
5714 void usymtab_addMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5717 if (!sRef_similar (s, al))
5719 usymtab_addForceMustAlias (s, al);
5724 ** Same as usymtab_addMustAlias, except does not check sRef_isSimilar.
5727 void usymtab_addForceMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5730 /* evans 2002-03-3: was sRef_isMeaningful -- but we need to keep aliases for new storage also! */
5731 if (sRef_isMeaningful (s)
5732 && sRef_isMeaningful (al)
5733 && !(sRef_isConst (s) || sRef_isConst (al))
5734 && !(sRef_isAddress (al) && sRef_isDirectParam (sRef_getBase (al))))
5736 utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
5737 DPRINTF (("Must alias: %s", aliasTable_unparse (utab->aliases)));
5740 ** for local variable, aliasing is symmetric
5743 if (sRef_isLocalVar (s) && sRef_isLocalVar (al))
5745 utab->aliases = aliasTable_addMustAlias (utab->aliases, al, s);
5750 DPRINTF (("Not aliasing! %s / %s", sRef_unparseFull (s), sRef_unparseFull (al)));
5751 DPRINTF (("meaningful: %d %d", sRef_isMeaningful (s), sRef_isMeaningful (al)));
5755 void usymtab_addReallyForceMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5758 utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
5761 void usymtab_clearAlias (sRef s)
5762 /*@modifies utab, s@*/
5765 aliasTable_clearAliases (utab->aliases, s);
5768 sRefSet usymtab_allAliases (sRef s)
5771 if (sRef_isSomewhatMeaningful (s))
5775 ret = sRefSet_unionFree (aliasTable_aliasedBy (utab->aliases, s),
5776 aliasTable_canAlias (utab->aliases, s));
5781 DPRINTF (("NOT A MEANINGFUL SREF!"));
5782 return sRefSet_undefined;
5786 /*@only@*/ sRefSet usymtab_canAlias (sRef s)
5789 if (sRef_isSomewhatMeaningful (s))
5791 sRefSet res = aliasTable_canAlias (utab->aliases, s);
5795 return sRefSet_undefined;
5798 /*@only@*/ sRefSet usymtab_aliasedBy (sRef s)
5801 return (aliasTable_aliasedBy (utab->aliases, s));
5804 /*@only@*/ cstring usymtab_unparseAliases ()
5807 return (aliasTable_unparse (utab->aliases));
5811 ** Debugging routines:
5812 ** okay to leak storage here, only for debugging
5818 usymtab_printOut (void)
5824 char *ind = mstring_copy (" ");
5826 fprintf (g_warningstream, "<<< [symbol table] >>>\n");
5828 while (s != GLOBAL_ENV && s->env != GLOBAL_ENV)
5830 cstring tname = usymtab_typeName (s);
5834 ind[depth * 3 + 1] = '\0';
5837 fprintf (g_warningstream, "level: %d (%s)\n", s->lexlevel,
5838 cstring_toCharsSafe (tname));
5840 cstring_free (tname);
5842 for (i = 0; i < s->nentries; i++)
5844 cstring us = uentry_unparseFull (s->entries[i]);
5845 fprintf (g_warningstream, "%s\n", cstring_toCharsSafe (us));
5849 if (s->reftable != NULL && s->nentries > 0)
5851 fprintf (g_warningstream, "\t<< Ref table >>\n");
5853 for (i = 0; i < s->nentries; i++)
5855 fprintf (g_warningstream, "\t%s %3d: %d, %d\n", ind, i,
5856 s->reftable[i]->level,
5857 s->reftable[i]->index);
5861 ind[depth * 3 + 1] = ' ';
5865 fprintf (g_warningstream, "<<< end usymtab >>>\n");
5871 usymtab_printTypes ()
5872 /*@globals globtab@*/
5874 usymtab_printAllAux (globtab);
5878 usymtab_printAll (void)
5881 usymtab_printAllAux (utab);
5885 usymtab_printAllAux (usymtab s)
5886 /*@modifies g_warningstream@*/
5890 char *ind = mstring_copy (" ");
5892 printf ("[[[ usymtab ]]]");
5894 while (s != GLOBAL_ENV)
5897 ind[depth * 3 + 1] = '\0';
5899 if (s->env == GLOBAL_ENV)
5903 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5904 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5905 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5909 for (i = looplow; i < s->nentries; i++)
5911 printf ("%s%3d. %s\n", ind, i,
5912 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5917 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5918 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5919 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5921 for (i = 0; i < s->nentries; i++)
5923 printf ("%s%3d %s\n", ind, i,
5924 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5928 ind[depth * 3 + 1] = ' ';
5932 printf ("----------\n");
5936 usymtab_printComplete ()
5941 char *ind = mstring_copy (" ");
5944 while (s != GLOBAL_ENV)
5948 ind[depth * 3 + 1] = '\0';
5951 if (s->env == GLOBAL_ENV)
5955 printf ("level: %d\n", s->lexlevel);
5959 for (i = looplow; i < s->nentries; i++)
5961 printf ("%s%3d %s\n", ind, i,
5962 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5967 printf ("level: %d\n", s->lexlevel);
5968 for (i = 0; i < s->nentries; i++)
5970 printf ("%s%3d %s\n", ind, i,
5971 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5975 ind[depth * 3 + 1] = ' ';
5980 printf ("----------\n");
5985 static /*@only@*/ cstring /*@unused@*/
5986 usymtab_unparseLocalAux (/*@notnull@*/ usymtab s)
5988 cstring c = message ("lexlevel: %d\n", s->lexlevel);
5991 for (i = 0; i < s->nentries; i++)
5993 c = message ("%q\n%q", c, uentry_unparseFull (s->entries[i]));
5996 c = message ("%q\n=========", c);
6000 static cstring /*@unused@*/ /*@only@*/
6001 usymtab_unparseLocalList (/*@notnull@*/ usymtab s)
6003 cstring c = message ("[%d/%s/%s] ", s->lexlevel,
6004 bool_unparse (s->mustBreak),
6005 exitkind_unparse (s->exitCode));
6008 for (i = 0; i < s->nentries; i++)
6010 sRef sr = uentry_getSref (s->entries[i]);
6014 c = message ("%q: %q [%b]", c, uentry_getName (s->entries[i]),
6015 sRef_isStateDefined (sr));
6019 c = message ("%q, %q [%b]", c, uentry_getName (s->entries[i]),
6020 sRef_isStateDefined (sr));
6030 usymtab_printLocal (void)
6036 printf ("lexlevel: %d\n", s->lexlevel);
6038 for (i = 0; i < s->nentries; i++)
6040 printf ("%s\n", cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
6043 while (s->lexlevel > 1)
6048 llassert (usymtab_isDefined (s));
6050 printf ("Params:\n");
6052 for (i = 0; i < s->nentries; i++)
6054 printf ("%d: %s\n", i,
6055 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
6060 static bool checkDistinctExternalName (uentry e)
6061 /*@globals globtab@*/
6062 /*@modifies *g_warningstream@*/
6064 size_t checklen = size_fromInt (context_getValue (FLG_EXTERNALNAMELEN));
6065 bool ignorecase = context_getFlag (FLG_EXTERNALNAMECASEINSENSITIVE);
6066 bool gotone = FALSE;
6067 bool extras = FALSE;
6068 bool hasError = FALSE;
6069 cstring name = uentry_rawName (e);
6070 usymtab st = globtab;
6078 if (uentry_isAnyTag (e))
6080 checklen++; /* the tag marker doesn't count */
6084 usymtab_entries (st, oe)
6086 if (uentry_sameObject (oe, e))
6093 if (cstring_equalCaseInsensitive (uentry_rawName (oe), name))
6102 (FLG_DISTINCTEXTERNALNAMES,
6104 ("External identifier %q is not distinguishable from %q "
6105 "because alphabetical case is ignored",
6107 uentry_getName (oe)),
6108 uentry_whereLast (e)))
6110 uentry_showWhereAny (oe);
6111 uentry_setHasNameError (oe);
6120 if (cstring_equalLenCaseInsensitive (uentry_rawName (oe),
6129 if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6132 (FLG_DISTINCTEXTERNALNAMES,
6135 ("External identifier %q is not distinguishable from %q "
6136 "in the first %d characters (%q)",
6138 uentry_getName (oe),
6139 size_toInt (checklen),
6140 cstring_clip (uentry_getName (e), checklen)),
6142 uentry_whereLast (e)))
6144 uentry_showWhereAny (oe);
6145 uentry_setHasNameError (oe);
6158 (FLG_DISTINCTEXTERNALNAMES,
6160 ("External identifier %q is not distinguishable from %q "
6161 "in the first %d characters because alphabetical case "
6164 uentry_getName (oe),
6165 size_toInt (checklen)),
6166 uentry_whereLast (e)))
6168 uentry_showWhereAny (oe);
6169 uentry_setHasNameError (oe);
6175 else if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6184 (FLG_DISTINCTEXTERNALNAMES,
6187 ("External identifier %q is not distinguishable from %q "
6188 "in the first %d characters (%q)",
6190 uentry_getName (oe),
6191 size_toInt (checklen),
6192 cstring_clip (uentry_getName (e), checklen)),
6194 uentry_whereLast (e)))
6196 uentry_showWhereAny (oe);
6197 uentry_setHasNameError (oe);
6206 } end_usymtab_entries ;
6213 (cstring_makeLiteral ("One or more additional "
6214 "indistinguishable external "
6215 "names not reported"));
6221 static bool checkDistinctInternalName (uentry e)
6223 /*@modifies *g_warningstream@*/
6225 usymtab ttab = utab;
6226 cstring name = uentry_rawName (e);
6227 size_t numchars = size_fromInt (context_getValue (FLG_INTERNALNAMELEN));
6228 bool caseinsensitive = context_getFlag (FLG_INTERNALNAMECASEINSENSITIVE);
6229 bool lookalike = context_getFlag (FLG_INTERNALNAMELOOKALIKE);
6231 if (uentry_isAnyTag (e) && (numchars != 0))
6233 numchars++; /* the tag marker doesn't count */
6236 while (usymtab_isDefined (ttab))
6238 usymtab_entries (ttab, oe)
6240 if (uentry_sameObject (oe, e))
6242 /*@innercontinue@*/ continue;
6245 switch (cstring_genericEqual
6246 (name, uentry_rawName (oe),
6247 numchars, caseinsensitive, lookalike))
6249 case CGE_DISTINCT: /* okay */
6253 if (cstring_equal (name, uentry_rawName (oe)))
6255 ; /* got a shadow error */
6260 (FLG_DISTINCTINTERNALNAMES,
6263 ("Internal identifier %q is not distinguishable from %q "
6264 "in the first %d characters (%q)",
6266 uentry_getName (oe),
6267 size_toInt (numchars),
6268 cstring_clip (uentry_getName (e), numchars)),
6270 uentry_whereLast (e)))
6272 uentry_showWhereAny (oe);
6273 uentry_setHasNameError (oe);
6280 if (numchars == 0 || (cstring_length (name) <= numchars))
6283 (FLG_DISTINCTINTERNALNAMES,
6285 ("Internal identifier %q is not distinguishable from %q "
6286 "without case sensitivity",
6288 uentry_getName (oe)),
6289 uentry_whereLast (e)))
6291 uentry_showWhereAny (oe);
6292 uentry_setHasNameError (oe);
6299 (FLG_DISTINCTINTERNALNAMES,
6301 ("Internal identifier %q is not distinguishable from %q "
6302 "in the first %d characters without case sensitivity",
6304 uentry_getName (oe),
6305 size_toInt (numchars)),
6306 uentry_whereLast (e)))
6308 uentry_showWhereAny (oe);
6309 uentry_setHasNameError (oe);
6317 || (cstring_length (name) <= numchars))
6320 (FLG_DISTINCTINTERNALNAMES,
6322 ("Internal identifier %q is not distinguishable from %q "
6323 "except by lookalike characters",
6325 uentry_getName (oe)),
6326 uentry_whereLast (e)))
6328 uentry_showWhereAny (oe);
6329 uentry_setHasNameError (oe);
6336 (FLG_DISTINCTINTERNALNAMES,
6338 ("Internal identifier %q is not distinguishable from %q "
6339 "in the first %d characters except by lookalike characters",
6341 uentry_getName (oe),
6342 size_toInt (numchars)),
6343 uentry_whereLast (e)))
6345 uentry_showWhereAny (oe);
6346 uentry_setHasNameError (oe);
6351 } end_usymtab_entries ;
6359 void usymtab_checkDistinctName (uentry e, int scope)
6360 /*@globals utab, globtab@*/
6362 bool hasError = FALSE;
6363 fileloc where = uentry_whereLast (e);
6365 if (!fileloc_isPreproc (where) && !fileloc_isBuiltin (where))
6367 if (scope == globScope)
6369 if (context_getFlag (FLG_DISTINCTEXTERNALNAMES))
6371 hasError = checkDistinctExternalName (e);
6375 if (!hasError && context_getFlag (FLG_DISTINCTINTERNALNAMES))
6377 hasError = checkDistinctInternalName (e);
6383 uentry_setHasNameError (e);
6387 /*@exposed@*/ sRef usymtab_lookupGlobalMarker (void) /*@globals utab@*/
6391 ue = usymtab_lookupAux (utab, GLOBAL_MARKER_NAME);
6392 llassert (uentry_isValid (ue));
6394 return uentry_getSref (ue);
6400 ** For debugging only
6404 usymtab_checkAllValid () /*@globals utab@*/
6408 while (tab != GLOBAL_ENV)
6412 for (i = 0; i < utab->nentries; i++)
6414 uentry e = utab->entries[i];
6416 uentry_checkValid (e);
6419 aliasTable_checkValid (tab->aliases);