2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2002 University of Virginia,
4 ** Massachusetts Institute of Technology
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ** General Public License for more details.
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
20 ** For information on splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
27 ** Lexically scoped symbol table.
29 ** Unlike a normal symbol table, this table splits to reflect branches.
31 ** This is necessary since symbol table entries also reflect
32 ** some state information, like initialization, that may be
33 ** different on different branches.
35 ** For each control structure we split:
37 ** { } - a normal scope (no control) US_NORMAL
39 ** if <pred> { } - US_TBRANCH true branch
40 ** while <pred> { } US_FBRANCH else branch
42 ** switch <pred> { } - US_SWITCH
44 ** case x: - case scope US_CBRANCH
45 ** Should be kept in a separate table, because of
49 # include "splintMacros.nf"
51 # include "structNames.h"
52 # include "exprChecks.h"
53 # include "transferChecks.h"
55 /* Needed to install macros when loading libraries */
58 # include "cpperror.h"
62 ** Keep track of type definitions inside a function.
65 static uentryList functypes = uentryList_undefined;
67 static bool dbgfree = FALSE;
68 static bool dbgload = TRUE;
73 ** Hack to prevent shadow errors from appearing when function parameters
74 ** are entered into a new scope.
77 static bool noshadowerror = FALSE;
80 ** Constraint: static variables can live in 1 or > 2.
82 ** except for tags. All tags must be at the global level.
83 ** Static tags are handled in a kludgey way.
87 ** utab is the universal symbol table
88 ** globtab is the global environment of utab
89 ** oldtab is needed for conversions in dumping (after sorting the table)
91 ** there can be only one usymtab!
94 static /*@checkedstrict@*/ /*@owned@*/ /*@notnull@*/ usymtab utab;
96 /* Reachable environments from from utab */
97 static /*@checkedstrict@*/ /*@notnull@*/ /*@dependent@*/ usymtab globtab;
98 static /*@checkedstrict@*/ /*@dependent@*/ usymtab filetab;
100 /* Used for sorting for dumpage. */
101 static /*@checkedstrict@*/ /*@owned@*/ usymtab oldtab;
103 static int usymtab_lexicalLevel (void) /*@globals utab@*/ ;
104 static bool usymtab_isAltDefinitelyNull (sRef p_s) /*@globals utab@*/ ;
105 static void refTable_free (/*@only@*/ /*@null@*/ refTable p_x, int p_nentries);
106 static ctype usymtab_suFieldsType (uentryList p_f, bool p_isStruct) /*@globals globtab@*/ ;
108 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;
356 usymtab_initGlobalMarker () /*@globals globtab@*/
358 if (uentry_isValid (usymtab_lookupAux (globtab, GLOBAL_MARKER_NAME)))
360 ; /* Already entered from load table. */
364 usymtab_addGlobalEntry (uentry_makeGlobalMarker ());
369 ** utab should be empty? (requires?)
371 ** Adds bool types to symbol table (these are built in for now)
372 ** Only do this is there is no library!
378 DPRINTF (("Init bool!"));
380 if (context_getFlag (FLG_NOLIB))
382 ctype boolt = ctype_bool;
383 /* evs 2000-07-24: bool is now treated as abstract (always) */
385 uentry boolentry = uentry_makeBoolDatatype (YES);
386 usymtab_supGlobalEntry (boolentry);
387 context_addBoolAccess ();
390 ** We supply values 0 and 1 for the constants, so things like
391 ** while (TRUE) can be interpreted correctly.
394 usymtab_supGlobalEntry
395 (uentry_makeConstantValue (context_getFalseName (), boolt,
396 fileloc_getBuiltin (), FALSE,
397 multiVal_makeInt (0)));
399 usymtab_supGlobalEntry
400 (uentry_makeConstantValue (context_getTrueName (), boolt,
401 fileloc_getBuiltin (), FALSE,
402 multiVal_makeInt (1)));
411 usymtab_grow (/*@notnull@*/ usymtab s)
414 o_uentry *oldsyms = s->entries;
416 s->nspace = CBASESIZE;
417 s->entries = (uentry *) dmalloc (sizeof (*s->entries)
418 * (s->nentries + s->nspace));
420 for (i = 0; i < s->nentries; i++)
422 s->entries[i] = oldsyms[i];
427 if (s->reftable != NULL)
429 refTable oldRefs = s->reftable;
431 s->reftable = (refentry *) dmalloc (sizeof (*s->reftable)
432 * (s->nentries + CBASESIZE + 1));
434 for (i = 0; i < s->nentries; i++)
436 s->reftable[i] = oldRefs[i];
447 usymtab_addEntryQuiet (/*@notnull@*/ usymtab s, /*@keep@*/ uentry e)
449 if (!(s->lexlevel > fileScope || !sRef_modInFunction ()))
451 if (uentry_isDatatype (e)
452 || uentry_isFunction (e)
453 || uentry_isAnyTag (e)
454 || uentry_isEnumConstant (e)
455 || context_inMacro ())
458 ** Not a bug. Code like,
459 ** int f (void) { typedef int tint; ... }
463 /* was nothing here! */
464 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
469 (cstring_makeLiteral ("Declaration outside function scope"));
471 llcontbug (message ("usymtab_addEntryQuiet: inconsistent state "
472 "(lexlevel = %d, modFunction = %s) adding: %q",
473 s->lexlevel, bool_unparse (sRef_modInFunction ()),
474 uentry_unparse (e)));
475 sRef_setGlobalScope ();
476 /* make sure the sRef is not bashed! */
477 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
487 s->entries[s->nentries] = e;
490 if (s == globtab || s == filetab)
492 if (!fileloc_isLib (g_currentloc))
494 uentry_tallyAnnots (e, AN_UNKNOWN);
499 if (cstringTable_isDefined (s->htable))
501 cstringTable_insert (s->htable, cstring_copy (uentry_rawName (e)), s->nentries);
507 static /*@observer@*/ uentry /*@alt void@*/
508 usymtab_addEntryBase (/*@notnull@*/ usymtab s, /*@only@*/ uentry e)
511 ** In theory, we shouldn't need this test because it this is
512 ** only called when a library is being read, and it shouldn't
513 ** ever have a duplicate entry. In practice, its safer to
514 ** leave it in, though.
519 if (uentry_isValid (old = usymtab_lookupQuiet (s, uentry_rawName (e))))
521 DPRINTF (("Duplicate entry: %s", uentry_unparse (e)));
522 uentry_free (e); /* duplicate */
527 int thisentry = s->nentries;
529 if (uentry_isVar (e))
531 uentry_setSref (e, sRef_makeCvar (globScope, thisentry,
533 stateInfo_makeLoc (uentry_whereLast (e))));
536 usymtab_addEntryQuiet (s, e);
542 static /*@observer@*/ uentry /*@alt void@*/
543 usymtab_addEntryAlways (/*@notnull@*/ usymtab s, /*@only@*/ uentry e)
546 ** In theory, we shouldn't need this test because it this is
547 ** only called when a library is being read, and it shouldn't
548 ** ever have a duplicate entry. In practice, its safer to
549 ** leave it in, though.
553 int thisentry = s->nentries;
555 if (uentry_isValid (old = usymtab_lookupQuiet (s, uentry_rawName (e))))
558 (message ("Duplicate entry in load library: %s. "
559 "Old entry: %q. New entry: %q",
561 uentry_unparseFull (old),
562 uentry_unparseFull (e)));
564 uentry_setName (e, message ("__x_%s", uentry_rawName (e)));
565 /* This shouldn't happen...unless the library is bad! */
569 if (uentry_isVar (e) && !uentry_isGlobalMarker (e))
571 uentry_setSref (e, sRef_makeCvar (globScope, thisentry,
573 stateInfo_makeLoc (uentry_whereLast (e))));
576 usymtab_addEntryQuiet (s, e);
581 usymtab_addEntryAux (/*@notnull@*/ usymtab st, /*@keep@*/ uentry e, bool isSref)
582 /*@globals globtab@*/
585 usymId thisentry = st->nentries;
587 llassert (!uentry_isElipsisMarker (e));
591 ** llassert (usymtab_lookupSafe (uentry_rawName (e)) == uentry_undefined);
594 llassertprint (uentry_isAnyTag (e) ? st == globtab : TRUE,
595 ("non-global tag: %s / %d", uentry_unparseFull (e), st->lexlevel));
597 if (st->lexlevel == fileScope
598 && (!(uentry_isStatic (e)) || uentry_isAnyTag (e)))
605 ctype ct = uentry_getType (e);
607 if (uentry_isFunction (e) && ctype_isFunction (ct))
609 ct = ctype_getReturnType (ct);
612 if (uentry_isStatic (e))
614 sRef sr = sRef_makeCvar (st->lexlevel, thisentry, ct, stateInfo_makeLoc (uentry_whereLast (e)));
616 if (sRef_isStack (sr) || sRef_isLocalState (sr))
618 sRef_setAliasKind (sr, AK_STATIC, uentry_whereLast (e));
619 sRef_setDefined (sr, uentry_whereLast (e));
622 uentry_setSref (e, sr);
626 uentry_setSref (e, sRef_makeCvar (st->lexlevel, thisentry, ct, stateInfo_makeLoc (uentry_whereLast (e))));
630 if (uentry_isDatatype (e))
633 uentry_setDatatype (e, thisentry);
636 if (uentry_isFunction (e))
638 ctype ct = uentry_getType (e);
640 if (ctype_isFunction (ct)
641 && uentryList_isMissingParams (ctype_argsFunction (ct)))
643 if (uentry_isDeclared (e))
647 message ("Function %q declared without parameter list",
649 uentry_whereDeclared (e));
655 message ("Function %q specified without parameter list",
657 uentry_whereSpecified (e));
662 if (st == globtab && !uentry_isSpecified (e))
664 exprChecks_checkExport (e);
667 uentry_checkName (e);
669 usymtab_addEntryQuiet (st, e);
670 DPRINTF (("Adding entry: [%p] %s", e, uentry_unparseFull (e)));
675 usymtab_addEntry (uentry e)
676 /*@globals utab, globtab@*/
677 /*@modifies utab, e@*/
679 llassertprint (!usymtab_exists (uentry_rawName (e)),
680 ("Entry already exists: %s", uentry_unparse (e)));
682 return usymtab_addEntryAux (utab, e, FALSE);
686 usymtab_addGlobalEntry (uentry e)
687 /*@modifies globtab, e@*/
689 DPRINTF (("Add global: %s / %s", uentry_unparse (e), bool_unparse (uentry_isForward (e))));
691 (void) usymtab_addEntryAux (globtab, e, FALSE);
695 ** supercede and replace entry use elements of entries array, and
696 ** assign an element to a new value, and then free the old value.
697 ** Need -deparrays to avoid errors for this.
703 usymtab_supEntryAux (/*@notnull@*/ usymtab st,
704 /*@only@*/ uentry e, bool isSref)
705 /*@globals globtab, filetab@*/
706 /*@modifies st, globtab, e@*/
708 cstring ename = uentry_rawName (e);
709 bool staticEntry = FALSE;
712 DPRINTF (("Sup entry aux: %s", uentry_unparseFull (e)));
714 /* static tags in global scope */
715 if (st->lexlevel == fileScope
716 && (!(uentry_isStatic (e)) || uentry_isAnyTag (e)))
718 eindex = usymtab_getIndex (st, ename);
720 if (eindex != NOT_FOUND)
722 uentry ce = st->entries[eindex];
726 message ("%s %q shadows static declaration",
727 ekind_capName (uentry_getKind (e)),
729 uentry_whereDeclared (e)))
731 uentry_showWhereLast (ce);
734 if (eindex == st->nentries - 1)
740 st->entries[eindex] = st->entries[st->nentries - 1];
743 if (cstringTable_isDefined (st->htable))
745 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
746 cstring_copy (uentry_rawName (e)));
756 if (uentry_isStatic (e)) {
757 if (uentry_isFunction (e)) {
759 ** Static function declarations are at the file level,
760 ** even if they are in a deeper scope.
763 st = usymtab_getFileTab ();
766 if (!uentry_isAnyTag (e) && st == globtab)
768 st = usymtab_getFileTab ();
770 DPRINTF (("Static entry!"));
775 eindex = usymtab_getIndex (st, ename);
777 if (eindex != NOT_FOUND)
779 uentry ce = st->entries[eindex];
781 DPRINTF (("Found entry: %s", uentry_unparse (ce)));
783 if (uentry_isPriv (ce)
784 /* || (fileloc_isImport (uentry_whereSpecified (ce))) */
785 || (uentry_isStatic (ce)
786 && uentry_isAnyTag (ce)
787 && (uentry_isDeclared (ce)
788 && !fileloc_sameFile (uentry_whereDefined (ce),
789 uentry_whereDefined (e)))))
793 ** if overloading import should do some checks!
796 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
798 DPRINTF (("Overloading!"));
800 st->entries[eindex] = e;
802 if (uentry_isDatatype (e))
804 uentry_setDatatype (e, eindex);
807 if (st == globtab && !uentry_isSpecified (e))
809 exprChecks_checkExport (e);
812 if (cstringTable_isDefined (st->htable))
814 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
815 cstring_copy (uentry_rawName (e)));
821 else if (uentry_isSpecified (ce))
823 if (uentry_isSpecified (e))
825 DPRINTF (("Here we are: %s", uentry_unparseFull (e)));
827 if (fileloc_isImport (uentry_whereSpecified (ce)))
829 if (cstringTable_isDefined (st->htable))
831 cstringTable_replaceKey (st->htable,
833 cstring_copy (uentry_rawName (e)));
837 st->entries[eindex] = e;
840 if (uentry_isDatatype (e)) uentry_setDatatype (e, eindex);
844 if (fileloc_isImport (uentry_whereSpecified (e)))
850 /* Respecification errors already reported */
851 DPRINTF (("Respecification: %s / %s",
852 fileloc_unparse (uentry_whereSpecified (e)),
853 bool_unparse (fileloc_isSpec (uentry_whereSpecified (e)))));
855 if (uentry_isDatatype (e))
857 uentry_setDatatype (e, eindex);
860 if (cstringTable_isDefined (st->htable))
862 cstringTable_replaceKey (st->htable,
864 cstring_copy (uentry_rawName (e)));
867 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
869 st->entries[eindex] = e;
874 else /* e not specified */
876 DPRINTF (("Merging..."));
878 if (uentry_isDeclared (ce))
881 No - this can happen for internal typedefs
882 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
885 DPRINTF (("Merge defn"));
886 uentry_mergeDefinition (ce, e);
891 No - this can happen for internal typedefs
892 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
895 DPRINTF (("Merge entries..."));
896 uentry_mergeEntries (ce, e);
897 DPRINTF (("After: %s", uentry_unparseFull (ce)));
901 else /* ce not specified */
903 if (!(st->lexlevel > fileScope || !sRef_modInFunction ()))
905 if (uentry_isDatatype (e) || uentry_isAnyTag (e)
906 || uentry_isEnumConstant (e)
907 || uentry_isStatic (e)) /* bug fix from Brian St. Pierre */
910 ** Not a bug. Code like,
911 ** int f (void) { typedef int tint; ... }
917 llcontbug (message ("usymtab_supEntryAux: inconsistent state "
918 "(lexlevel = %d, modFunction = %s) adding: %q",
919 st->lexlevel, bool_unparse (sRef_modInFunction ()),
920 uentry_unparse (e)));
922 if (sRef_modInFunction ())
924 /* make sure the sRef is not bashed! */
925 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
930 DPRINTF (("Merge.."));
931 uentry_mergeDefinition (ce, e);
936 ctype ct = uentry_getType (ce);
938 if (uentry_isFunction (ce) && ctype_isFunction (ct))
940 ct = ctype_getReturnType (ct);
943 uentry_setSref (ce, sRef_makeCvar (st->lexlevel, eindex, ct, stateInfo_makeLoc (uentry_whereLast (ce))));
946 else /* no previous entry */
950 if (st->lexlevel == globScope
951 && !uentry_isStatic (e)
952 && !uentry_isExtern (e)
953 && usymtab_isDefined (filetab))
956 ** check if there is a static entry: (i.e.,
963 eindex = usymtab_getIndex (filetab, ename);
965 if (eindex != NOT_FOUND)
967 uentry ce = filetab->entries[eindex];
969 uentry_setStatic (e);
970 uentry_mergeDefinition (ce, e);
976 outer = usymtab_lookupQuiet (st->env, ename);
978 DPRINTF (("New : [%p] %s", e, uentry_unparseFull (e)));
979 DPRINTF (("Outer: [%p] %s", outer, uentry_unparseFull (outer)));
982 ** no previous definition, add the new one
986 && uentry_isValid (outer)
987 && !(uentry_isYield (e) || uentry_isYield (outer))
988 && fileloc_isDefined (uentry_whereLast (e))
989 && !fileloc_isXHFile (uentry_whereLast (e))
990 && fileloc_isDefined (uentry_whereLast (outer))
991 && !fileloc_isXHFile (uentry_whereLast (outer)))
993 if (!uentry_sameKind (outer, e))
999 if (ctype_isUnknown (uentry_getType (outer))
1000 || uentry_isForward (outer))
1008 message ("%s %q shadows outer declaration",
1009 ekind_capName (uentry_getKind (e)),
1010 uentry_getName (e)),
1011 uentry_whereLast (e)))
1013 uentry_showWhereLast (outer);
1019 if (st == globtab && context_getFlag (FLG_NEWDECL))
1023 message ("New declaration: %q", uentry_getName (e)),
1024 uentry_whereLast (e));
1027 eindex = usymtab_addEntryAux (st, e, isSref);
1031 return (staticEntry ? USYMIDINVALID : eindex);
1035 usymtab_replaceEntryAux (/*@notnull@*/ usymtab st, /*@only@*/ uentry e)
1036 /*@globals globtab@*/ /*@modifies st, e@*/
1038 cstring ename = uentry_rawName (e);
1041 /* static tags in global scope */
1042 eindex = usymtab_getIndex (st, ename);
1044 if (eindex != NOT_FOUND)
1046 uentry ce = st->entries[eindex];
1048 if (cstringTable_isDefined (st->htable))
1050 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
1051 cstring_copy (uentry_rawName (e)));
1055 st->entries[eindex] = e;
1059 eindex = usymtab_addEntryAux (st, e, FALSE);
1065 void usymtab_supEntry (uentry e)
1066 /*@globals utab, filetab, globtab@*/
1067 /*@modifies utab, globtab, e@*/
1069 (void) usymtab_supEntryAux (utab, e, FALSE);
1073 ** this should be lots more efficient!
1076 static /*@exposed@*/ uentry
1077 usymtab_supEntryReturnAux (/*@notnull@*/ usymtab tab,
1078 /*@only@*/ uentry e, bool isref)
1079 /*@globals globtab, filetab@*/
1080 /*@modifies tab, globtab, e@*/
1082 cstring rawName = cstring_copy (uentry_rawName (e));
1083 bool stat = (tab == globtab) && uentry_isStatic (e);
1086 (void) usymtab_supEntryAux (tab, e, isref);
1090 ret = usymtab_lookupAux (filetab, rawName);
1094 ret = usymtab_lookupAux (tab, rawName);
1096 if (uentry_isInvalid (ret) && usymtab_isDefined (filetab))
1098 ret = usymtab_lookupAux (filetab, rawName);
1102 cstring_free (rawName);
1106 /*@dependent@*/ /*@exposed@*/ uentry
1107 usymtab_supEntryReturn (/*@only@*/ uentry e)
1108 /*@globals utab, filetab, globtab@*/
1109 /*@modifies utab, globtab, e@*/
1111 return (usymtab_supEntryReturnAux (utab, e, FALSE));
1114 /*@dependent@*/ /*@exposed@*/ uentry
1115 usymtab_supEntrySrefReturn (/*@only@*/ uentry e)
1116 /*@globals utab, globtab, filetab@*/
1117 /*@modifies utab, globtab, e@*/
1119 return (usymtab_supEntryReturnAux (utab, e, TRUE));
1122 /*@dependent@*/ /*@exposed@*/ uentry
1123 usymtab_supGlobalEntryReturn (uentry e)
1124 /*@globals globtab, filetab@*/
1125 /*@modifies globtab, e@*/
1129 ret = usymtab_supEntryReturnAux (globtab, e, FALSE);
1132 ** We need to keep track of internal function declarations, so
1133 ** we can remove them from the symbol table after exiting this
1134 ** function. This is a bit bogus, of course.
1137 if (sRef_modInFunction ())
1139 recordFunctionType (ret);
1146 usymtab_supTypeEntry (/*@only@*/ uentry e)
1147 /*@globals globtab, filetab@*/
1148 /*@modifies globtab, e@*/
1153 if (uentry_isAbstractDatatype (e))
1155 uid = usymtab_supAbstractTypeEntry (e, FALSE);
1156 ret = ctype_createAbstract (uid);
1160 uid = usymtab_supEntryAux (globtab, e, FALSE);
1161 ret = ctype_createUser (uid);
1164 if (sRef_modInFunction ())
1166 recordFunctionType (globtab->entries[uid]);
1173 usymtab_supReturnTypeEntry (/*@only@*/ uentry e)
1174 /*@globals globtab, filetab@*/
1175 /*@modifies globtab@*/
1179 DPRINTF (("Abstract? %s", uentry_unparseFull (e)));
1181 if (uentry_isAbstractDatatype (e))
1183 uid = usymtab_supAbstractTypeEntry (e, FALSE);
1185 else if (uentry_isMaybeAbstract (e) && context_getFlag (FLG_IMPABSTRACT))
1187 bool maybeabs = TRUE;
1188 cstring sname = uentry_getName (e);
1189 uentry ue = usymtab_lookupGlobSafe (sname);
1190 cstring_free (sname);
1192 if (uentry_isValid (ue))
1194 DPRINTF (("Lookup: %s", uentry_unparseFull (ue)));
1196 if (uentry_isDatatype (ue))
1198 if (uentry_isMaybeAbstract (ue))
1209 DPRINTF (("Not datatype!"));
1216 uid = usymtab_supAbstractTypeEntry (e, FALSE);
1217 ux = usymtab_getTypeEntry (uid);
1218 uentry_setAbstract (ux);
1222 uid = usymtab_supEntryAux (globtab, e, FALSE);
1223 e = usymtab_getTypeEntry (uid);
1225 if (uentry_isMaybeAbstract (e))
1227 uentry_setConcrete (e);
1233 uid = usymtab_supEntryAux (globtab, e, FALSE);
1234 e = usymtab_getTypeEntry (uid);
1236 if (uentry_isMaybeAbstract (e))
1238 uentry_setConcrete (e);
1242 if (sRef_modInFunction ())
1244 recordFunctionType (globtab->entries[uid]);
1247 return (globtab->entries[uid]);
1251 usymtab_supAbstractTypeEntry (/*@only@*/ uentry e, bool dodef)
1252 /*@globals globtab, filetab@*/
1253 /*@modifies globtab, e@*/
1258 uid = usymtab_supEntryAux (globtab, e, FALSE);
1259 ue = usymtab_getTypeEntry (uid);
1263 uentry_setDatatype (ue, uid);
1266 if (context_getFlag (FLG_ACCESSMODULE)) /* was accessfile */
1268 context_addFileAccessType (uid);
1271 if (sRef_modInFunction ())
1273 recordFunctionType (globtab->entries[uid]);
1280 usymtab_supExposedTypeEntry (/*@only@*/ uentry e, bool dodef)
1281 /*@globals globtab, filetab@*/
1282 /*@modifies globtab, e@*/
1286 uid = usymtab_supEntryAux (globtab, e, FALSE);
1290 uentry ue = usymtab_getTypeEntry (uid);
1292 uentry_setDatatype (ue, uid);
1295 if (sRef_modInFunction ())
1297 recordFunctionType (globtab->entries[uid]);
1304 usymtab_supForwardTypeEntry (/*@only@*/ uentry e)
1305 /*@globals globtab, filetab@*/
1306 /*@modifies globtab, e@*/
1308 usymId uid = usymtab_supEntryAux (globtab, e, FALSE);
1309 uentry ue = usymtab_getTypeEntry (uid);
1311 uentry_setDatatype (ue, uid);
1313 if (sRef_modInFunction ())
1315 recordFunctionType (globtab->entries[uid]);
1318 return (uentry_getAbstractType (ue));
1322 usymtab_supEntrySref (uentry e)
1323 /*@globals utab, globtab, filetab@*/
1324 /*@modifies utab, globtab, e@*/
1326 sRef old = uentry_getSref (e);
1328 if (sRef_isType (old))
1330 uentry ue = usymtab_supEntryReturnAux (utab, e, TRUE);
1333 if (uentry_isValid (ue))
1335 sRef uref = uentry_getSref (ue);
1337 sRef_mergeStateQuiet (uref, old);
1338 sRef_clearDerived (uref);
1340 /*@noaccess uentry@*/
1342 else if (sRef_isKnown (old))
1344 usymtab_supEntry (e);
1348 (void) usymtab_supEntryAux (utab, e, TRUE);
1352 void usymtab_supGlobalEntry (/*@only@*/ uentry e)
1353 /*@globals globtab, filetab@*/
1354 /*@modifies globtab, filetab, e@*/
1358 DPRINTF (("Sup global entry: %s", uentry_unparse (e)));
1360 uid = usymtab_supEntryAux (globtab, e, FALSE);
1362 if (sRef_modInFunction ())
1364 recordFunctionType (globtab->entries[uid]);
1369 usymtab_supReturnFileEntry (/*@only@*/ uentry e)
1370 /*@globals filetab, globtab@*/
1371 /*@modifies filetab, globtab, e@*/
1373 llassert (filetab != usymtab_undefined);
1374 DPRINTF (("File entry: %s", uentry_unparse (e)));
1375 return (usymtab_supEntryReturnAux (filetab, e, FALSE));
1383 usymtab_inDeepScope () /*@globals utab@*/
1385 return (utab->lexlevel > paramsScope);
1389 usymtab_getIndex (/*@notnull@*/ usymtab s, cstring k)
1393 DPRINTF (("Lookup %s", k));
1395 if (cstringTable_isDefined (s->htable))
1397 i = cstringTable_lookup (s->htable, k);
1402 for (i = 0; i < s->nentries; i++)
1404 uentry current = s->entries[i];
1406 DPRINTF (("Check %d: %s", i, uentry_rawName (current)));
1408 if (!uentry_isUndefined (current)
1409 && cstring_equal (uentry_rawName (current), k))
1420 usymtab_fetchIndex (/*@notnull@*/ usymtab s, int i)
1422 llassert (i >= 0 && i < s->nentries);
1423 return (s->entries[i]);
1427 usymtab_getTypeId (cstring k) /*@globals globtab@*/
1429 usymId uid = usymtab_getIndex (globtab, k);
1431 if (uid == NOT_FOUND) return USYMIDINVALID;
1433 if (!(uentry_isDatatype (usymtab_getTypeEntry (uid)))) {
1434 return USYMIDINVALID;
1440 /*@dependent@*/ uentry
1441 usymtab_lookupStructTag (cstring k)
1443 cstring sname = makeStruct (k);
1444 uentry ue = usymtab_lookupGlob (sname);
1446 cstring_free (sname);
1450 /*@dependent@*/ uentry
1451 usymtab_lookupUnionTag (cstring k)
1453 cstring uname = makeUnion (k);
1454 uentry res = usymtab_lookupGlob (uname);
1456 cstring_free (uname);
1460 /*@dependent@*/ uentry
1461 usymtab_lookupEnumTag (cstring k)
1463 cstring ename = makeEnum (k);
1464 uentry res = usymtab_lookupGlob (ename);
1466 cstring_free (ename);
1471 usymtab_getId (cstring k) /*@globals globtab@*/
1473 usymId uid = usymtab_getIndex (globtab, k);
1476 if (uid == NOT_FOUND)
1478 return USYMIDINVALID;
1481 ue = usymtab_getGlobalEntry (uid);
1483 if (uentry_isPriv (ue))
1485 return USYMIDINVALID;
1491 static /*@exposed@*/ uentry
1492 usymtab_getEntryAux (/*@notnull@*/ usymtab s, usymId uid)
1494 llassert (uid != USYMIDINVALID);
1496 if (uid < 0 || uid >= s->nentries)
1498 llcontbug (message ("usymtab_getEntry: out of range: level = %d [%d]",
1500 return uentry_undefined;
1503 llassertprint (uentry_isValid (s->entries[uid]),
1504 ("entry undefined: %d", uid));
1506 return s->entries[uid];
1509 /*@dependent@*/ /*@observer@*/ uentry
1510 usymtab_getGlobalEntry (usymId uid)
1511 /*@globals utab, globtab@*/
1513 if (dbgfree) return (uentry_undefined);
1515 if (utab->lexlevel > paramsScope)
1517 /* need to do this the awkward way, since it could be in conditional scope */
1518 return (usymtab_lookupSafe (uentry_rawName (globtab->entries[uid])));
1522 return (globtab->entries[uid]);
1526 /*@dependent@*/ /*@exposed@*/ uentry
1527 usymtab_getTypeEntry (usymId uid)
1528 /*@globals globtab@*/
1532 if (uid >= 0 && uid < globtab->nentries)
1534 return (globtab->entries[uid]);
1538 return (uentry_undefined);
1543 llassert (uid >= 0 && uid < globtab->nentries);
1544 return (globtab->entries[uid]);
1552 /*@dependent@*/ /*@exposed@*/ uentry
1553 usymtab_getTypeEntrySafe (usymId uid)
1554 /*@globals globtab@*/
1556 if (uid < 0 || uid >= globtab->nentries)
1558 return uentry_undefined;
1561 return (globtab->entries[uid]);
1565 usymtab_isBoolType (usymId uid)
1566 /*@globals globtab@*/
1568 llassert (uid >= 0 && uid < globtab->nentries);
1570 return (cstring_equal (uentry_rawName (globtab->entries[uid]),
1571 context_getBoolName ()));
1575 usymtab_getTypeEntryName (usymId uid)
1576 /*@globals globtab@*/
1582 return (cstring_makeLiteral ("<freetype>"));
1585 ue = usymtab_getTypeEntry (uid);
1587 if (dbgload && !uentry_isValid (ue))
1589 return (message ("<missing type: %d>", uid));
1592 llassertprint (uentry_isValid (ue), ("type undefined: %d", uid));
1594 return (uentry_getName (ue));
1598 /*@unused@*/ static void
1599 usymtab_rehash (/*@notnull@*/ usymtab s)
1603 if (cstringTable_isDefined (s->htable))
1605 cstringTable_free (s->htable);
1608 s->htable = cstringTable_create (LLAHSHSIZE);
1610 for (i = 0; i < s->nentries; i++)
1612 cstringTable_insert (s->htable, cstring_copy (uentry_rawName (s->entries[i])), i);
1618 ** superficial copy of usymtab
1620 ** DO copy spec entries
1623 static /*@only@*/ /*@notnull@*/ usymtab
1624 usymtab_shallowCopy (/*@notnull@*/ usymtab s) /*@*/
1626 usymtab copytab = usymtab_createRoot ();
1629 for (i = 0; i < s->nentries; i++)
1631 usymtab_addEntryBase (copytab, s->entries[i]);
1638 usymtab_shallowFree (/*@only@*/ /*@notnull@*/ usymtab s)
1640 aliasTable_free (s->aliases);
1641 refTable_free (s->reftable, s->nentries);
1643 /*@-compdestroy@*/ sfree (s); /*@=compdestroy@*/
1647 ** converts usymId from old table to sorted one
1651 usymtab_convertId (usymId uid)
1652 /*@globals oldtab, utab@*/
1658 llassert (usymtab_isDefined (oldtab));
1660 ue = usymtab_getEntryAux (oldtab, uid);
1662 llassertprint (uentry_isValid (ue), ("convertId: undefined: %d", uid));
1664 name = uentry_rawName (ue);
1666 ret = usymtab_getIndex (utab, name);
1667 llassert (ret == uid); /*! for now, no rehash! */
1668 DPRINTF (("Convert: %s [%d] -> %s [%d]",
1669 uentry_unparse (ue), uid,
1670 uentry_unparse (utab->entries[ret]), ret));
1672 llassertprint (ret != USYMIDINVALID, ("convertId: return is invalid"));
1678 usymtab_prepareDump (void)
1679 /*@globals oldtab, utab@*/
1680 /*@modifies oldtab, utab@*/
1682 llassert (usymtab_inGlobalScope ());
1683 llassert (oldtab == usymtab_undefined);
1686 DPRINTF (("Preparing to dump:"));
1687 usymtab_printAll ();
1690 oldtab = usymtab_shallowCopy (utab);
1693 ** alpha compare - make sure order is same on different platforms
1694 ** error messages appear in same order
1698 qsort (utab->entries, (size_t)utab->nentries,
1699 sizeof (*utab->entries),
1700 (int (*)(const void *, const void *)) uentry_xcomparealpha);
1702 usymtab_rehash (utab);
1706 DPRINTF (("After rehash:"));
1707 usymtab_printAll ();
1711 void usymtab_dump (FILE *fout)
1712 /*@globals utab, oldtab@*/
1715 bool neednl = FALSE;
1716 uentry lastentry = uentry_undefined;
1717 ekind lastekind = KINVALID;
1721 ** must call prepareDump first
1724 llassert (oldtab != usymtab_undefined);
1726 for (i = 0; i < utab->nentries; i++)
1728 uentry thisentry = utab->entries[i];
1729 ekind thisekind = uentry_getKind (thisentry);
1731 if (!uentry_hasRealName (thisentry))
1733 llassert (uentry_isGlobalMarker (thisentry));
1737 check (fputc ('\n', fout) == (int) '\n');
1740 fprintf (fout, "*%d (GlobalMarker)\n", KGLOBALMARKER);
1741 lastekind = KINVALID;
1747 if (thisekind != lastekind)
1751 check (fputc ('\n', fout) == (int) '\n');
1755 lastentry = uentry_undefined;
1756 fprintf (fout, "*%d (%s)\n", ekind_toInt (thisekind),
1757 cstring_toCharsSafe (ekind_capName (thisekind)));
1758 lastekind = thisekind;
1763 ** evans - 2001-02-18 - added the - 48 fudge factor...
1764 ** extra characters dumped, but I haven't counded them carefully...
1767 if (uentry_isInvalid (lastentry) || !uentry_equiv (lastentry, thisentry)
1768 || (linelen > (MAX_DUMP_LINE_LENGTH - (2 * MAX_NAME_LENGTH) - 48)))
1772 DPRINTF (("Dumping entry: %d", i));
1773 cdump = message ("^%d %q", i, uentry_dump (thisentry));
1774 /* was: cdump = uentry_dump (thisentry)); */
1776 lastentry = thisentry;
1779 check (fputc ('\n', fout) == (int) '\n');
1783 linelen += cstring_length (cdump);
1785 /* no new line here! */
1786 if (cstring_length (cdump) > 0)
1788 check (fputs (cstring_toCharsSafe (cdump), fout) != EOF);
1791 cstring_free (cdump);
1796 cstring cdump = uentry_rawName (thisentry);
1797 DPRINTF (("Raw name: %s", cdump));
1798 linelen += (cstring_length (cdump) + 1);
1799 fprintf (fout, "#%s", cstring_toCharsSafe (cdump));
1806 check (fputc ('\n', fout) == (int) '\n');
1809 lastekind = KINVALID;
1811 fprintf(fout, ";; Library constraints\n");
1813 /*drl July 27 added this so that libraries without
1814 buffer constraints would be handled correctly.
1815 I'm trying to do this without breaking older libraries.
1817 Splint should still be able to handle libraries without this message.
1821 fprintf(fout, "start_Buffer_Constraints\n");
1823 for (i = 0; i < utab->nentries; i++)
1825 uentry thisentry = utab->entries[i];
1827 if (uentry_isFunction (thisentry) )
1829 constraintList preconditions;
1830 constraintList postconditions;
1832 preconditions = uentry_getFcnPreconditions (thisentry);
1833 postconditions = uentry_getFcnPostconditions (thisentry);
1835 if ( constraintList_isDefined(preconditions) ||
1836 constraintList_isDefined(postconditions) )
1838 fprintf(fout,"%s\n", cstring_toCharsSafe (uentry_rawName(thisentry) ) );
1839 if (constraintList_isDefined(preconditions) )
1841 fprintf(fout,"pre:\n");
1842 constraintList_dump(preconditions, fout);
1843 fprintf (fout, ";; end precondition constraints\n" );
1844 constraintList_free(preconditions);
1848 fprintf(fout,"pre:EMPTY\n");
1850 if (constraintList_isDefined(postconditions) )
1852 fprintf(fout,"post:\n");
1853 constraintList_dump(postconditions, fout);
1854 fprintf (fout, ";; end precondition constraints\n" );
1855 constraintList_free(postconditions);
1859 fprintf(fout,"post:EMPTY\n");
1868 void usymtab_load (FILE *f)
1869 /*@globals utab, globtab@*/
1870 /*@modifies utab, *f@*/
1872 char *s = mstring_create (MAX_DUMP_LINE_LENGTH);
1874 ekind kind = KINVALID;
1875 fileloc loc = g_currentloc;
1881 llassert (utab == globtab);
1882 llassert (utab->nentries == 0);
1884 while (((s = reader_readLine (f, s, MAX_DUMP_LINE_LENGTH)) != NULL)
1887 /* ignore ; comments */ ;
1890 while (s != NULL && *s != ';')
1898 ek = reader_getInt (&s);
1900 if (ek == KGLOBALMARKER)
1902 uentry lue = uentry_makeGlobalMarker ();
1903 DPRINTF (("Adding global marker: %s", uentry_unparseFull (lue)));
1904 usymtab_addEntryAlways (utab, lue);
1910 kind = ekind_fromInt (ek);
1918 (cstring_makeLiteral
1919 ("Library is in obsolete format. Use splint +whichlib "
1920 "to see which library is being loaded."));
1923 if (reader_optCheckChar (&s, '^'))
1925 index = reader_getInt (&s);
1932 llassert (kind != KINVALID);
1933 ue = uentry_undump (kind, loc, &s);
1935 llassert (utab->nentries == index || index == -1);
1937 if (uentry_isValid (ue))
1939 int lastindex = utab->nentries;
1940 ue = usymtab_addEntryAlways (utab, ue);
1944 if (uentry_isConstant (ue)) /*@i23! isPreProcessorMacro */
1946 cstring uname = uentry_getName (ue);
1948 /* Also check its a macro... */
1949 DPRINTF (("Installing: %s", uname));
1951 cpphash_installMacro
1952 (mstring_copy (cstring_toCharsSafe (uname)),
1953 cstring_length (uname),
1954 cpplib_createDefinition (message ("%s 255", uname),
1957 cpphash_hashCode (cstring_toCharsSafe (uname),
1958 cstring_length (uname),
1961 DPRINTF (("After install: %s", uname));
1965 if (utab->nentries != lastindex + 1)
1967 DPRINTF (("No add: %s", uentry_unparseFull (ue)));
1975 ** now, any other names are the same uentry
1978 while (*(s++) == '#')
1980 cstring name = cstring_fromCharsO (reader_getWord (&s));
1981 uentry nue = uentry_nameCopy (name, ue);
1983 DPRINTF (("Name copy: %s", uentry_unparseFull (nue)));
1987 usymtab_addEntryAlways (utab, nue);
1990 while ((c = *s) != '\0' && (c !='\n'))
1992 if (c != ' ' || c != '\t')
1994 llbuglit ("Junk in load file");
2002 s = reader_readLine (f, os, MAX_DUMP_LINE_LENGTH);
2007 to handle reading of buffer overflow related constraints
2009 while (fgets (s, MAX_DUMP_LINE_LENGTH, f) != NULL
2012 ; /* ignore ;-comments */
2015 /*drl July 27 added this so that libraries without
2016 buffer constraints would be handled correctly.
2017 I'm trying to do this without breaking older libraries*/
2019 /*check for "optional" start buffer constraints message*/
2021 if (mstring_equalPrefix (s, "start_Buffer_Constraints"))
2023 (void) fgets (s, MAX_DUMP_LINE_LENGTH, f);
2026 while (s != NULL && *s != ';')
2028 constraintList preconditions;
2029 constraintList postconditions;
2031 cstring name = cstring_fromChars(reader_getWord(&s) );
2033 ue = usymtab_lookup ( name );
2037 preconditions = constraintList_undefined;
2038 postconditions = constraintList_undefined;
2040 if (!uentry_isValid(ue) )
2042 llfatalbug ((message("Invalid uentry for %s library file may be corrupted", cstring_fromChars(s) ) ));
2044 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2046 temp = cstring_fromChars (reader_getWord(&s) );
2048 if (cstring_compareLit (temp,"pre:") == 0 )
2050 preconditions = constraintList_undump (f);
2054 if (cstring_compareLit (temp,"pre:EMPTY") != 0 )
2055 llfatalbug ((message("Error reading library file pre:EMPTY expected but got %s", temp ) ));
2060 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2062 temp = cstring_fromChars(reader_getWord(&s) );
2063 if (cstring_compareLit (temp, "post:") == 0 )
2065 postconditions = constraintList_undump (f);
2069 if (cstring_compareLit (temp, "post:EMPTY") != 0 )
2070 llfatalbug ((message("Error reading library file post:EMPTY expected but got %s", temp ) ));
2073 cstring_free (temp);
2075 uentry_setPreconditions (ue, functionConstraint_createBufferConstraint (preconditions));
2076 uentry_setPostconditions (ue, functionConstraint_createBufferConstraint (postconditions));
2078 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2086 ** file scope for static variables
2090 usymtab_enterFile ()
2091 /*@globals utab, globtab, filetab@*/
2092 /*@modifies filetab@*/
2094 llassert (utab == globtab);
2099 usymtab_entries (globtab, ue)
2101 if (sRef_hasDerived (uentry_getSref (ue)))
2103 fprintf (g_warningstream, "Derived Global: %s\n", uentry_unparse (ue));
2104 fprintf (g_warningstream, "sRef: %s\n", sRef_unparseFull (ue->sref));
2106 } end_usymtab_entries ;
2110 usymtab_enterScope ();
2116 /*@globals utab, filetab@*/
2117 /*@modifies filetab, utab@*/
2120 llassert (utab->lexlevel == 1);
2122 usymtab_exitScope (exprNode_undefined);
2127 usymtab_enterScope ()
2128 /*@globals utab, globtab, filetab@*/
2131 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
2133 /* unconditional scope: optimize to avoid copy */
2134 t->aliases = aliasTable_copy (utab->aliases);
2137 llassert (usymtab_isDefined (t->env));
2139 if (t->env->lexlevel == paramsScope && context_inFunctionLike ())
2141 noshadowerror = TRUE;
2142 usymtab_handleParams ();
2143 noshadowerror = FALSE;
2148 ** setup external references:
2149 ** o only, unique params alias external args
2150 ** o other params may alias anything of their type
2154 usymtab_handleParams (void)
2155 /*@globals utab, globtab, filetab@*/
2156 /*@modifies utab, globtab@*/
2158 usymtab ptab = utab->env;
2159 uentry fcn = context_getHeader ();
2161 usymtab_entries (ptab, param)
2165 if (!uentry_isYield (param))
2168 sRef pref = uentry_getSref (param);
2170 /* Could be a global. */
2172 if (uentry_isAnyParam (param))
2174 ue = uentry_makeVariable (fixParamName (uentry_rawName (param)),
2175 uentry_getType (param),
2176 fileloc_copy (uentry_whereDeclared (param)),
2179 uentry_copyState (ue, param);
2180 uentry_setRefParam (ue);
2182 ue = usymtab_supEntrySrefReturn (ue);
2184 /* must be after supercede! */
2186 if (!sRef_stateKnown (pref))
2188 uentry_setDefState (ue, SS_DEFINED);
2189 uentry_setDefState (param, SS_DEFINED);
2193 if (sRef_isStateSpecial (pref))
2195 uentry_setDefState (ue, SS_SPECIAL); /* ALLOCATED); */
2196 /* evans 2002-01-01: should be unnecessary, the pre clauses
2197 ** set the state if necessary.
2202 uentry_setDefState (ue, sRef_getDefState (pref));
2206 uref = uentry_getSref (ue);
2208 if (sRef_isStack (uref))
2210 alkind pkind = sRef_getAliasKind (pref);
2212 if (alkind_isKnown (pkind) && !alkind_isLocal (pkind)
2213 && !alkind_isStack (pkind))
2215 sRef_setAliasKind (uref, pkind, fileloc_undefined);
2216 sRef_setOrigAliasKind (uref, pkind);
2220 sRef_setAliasKind (uref, AK_IMPTEMP, fileloc_undefined);
2221 sRef_setOrigAliasKind (uref, AK_IMPTEMP);
2223 if (uentry_isOut (param))
2229 sRef_setDefined (uref, fileloc_undefined);
2235 usymtab_addMustAlias (uref, pref);
2237 if (!(uentry_isOnly (param) || uentry_isUnique (param)))
2240 ** This is needed for detecting possibly aliased parameters.
2243 sRef s = sRef_makeExternal (uref);
2244 usymtab_addMustAlias (uref, s);
2247 if (sRef_isKillRef (pref))
2249 sRef_setAliasKind (uref, AK_NEWREF, fileloc_undefined);
2250 sRef_setOrigAliasKind (uref, AK_KILLREF);
2252 else if (sRef_isRefCounted (uref))
2254 sRef_setOrigAliasKind (uref, AK_REFCOUNTED);
2259 sRef_setOrigAliasKind (uref, AK_LOCAL);
2266 } end_usymtab_entries;
2269 if (uentry_hasStateClauseList (fcn))
2271 stateClauseList clauses = uentry_getStateClauseList (fcn);
2273 stateClauseList_preElements (clauses, cl)
2275 fileloc loc = stateClause_loc (cl);
2276 sRefSet osrs = sRefSet_undefined;
2279 if (stateClause_isGlobal (cl))
2281 DPRINTF (("Global Marker: %s",
2282 sRef_unparseFull (usymtab_lookupGlobalMarker ())));
2283 llassert (sRef_isGlobalMarker (usymtab_lookupGlobalMarker ()));
2284 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
2289 srs = stateClause_getRefs (cl);
2292 sRefSet_elements (srs, el)
2294 sRef base = sRef_getRootBase (el);
2295 sRef sb = sRef_updateSref (el);
2297 if (sRef_isResult (base))
2299 ; /* nothing to do before */
2301 else if (sRef_isParam (base) || sRef_isGlobalMarker (base))
2303 if (stateClause_setsMetaState (cl))
2305 /* copied from exprNode.c:3040 */
2306 qual ql = stateClause_getMetaQual (cl);
2307 annotationInfo ainfo = qual_getAnnotationInfo (ql);
2308 metaStateInfo minfo = annotationInfo_getState (ainfo);
2309 cstring key = metaStateInfo_getName (minfo);
2310 int mvalue = annotationInfo_getValue (ainfo);
2312 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
2314 if (sRef_isResult (base))
2320 sRef_setMetaStateValueComplete (sb, key, mvalue, loc);
2325 sRefMod modf = stateClause_getEntryFunction (cl);
2329 sRefSet aliases = usymtab_allAliases (sb);
2333 sRefSet_elements (aliases, sr)
2336 } end_sRefSet_elements ;
2338 sRefSet_free (aliases);
2344 if (sRef_isValid (base))
2346 DPRINTF (("Base: %s", sRef_unparseFull (base)));
2350 } end_sRefSet_elements ;
2351 } end_stateClauseList_preElements ;
2356 usymtab_enterFunctionScope (uentry fcn)
2357 /*@globals utab, filetab, globtab@*/
2360 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
2362 DPRINTF (("Enter function: %s", uentry_unparse (fcn)));
2364 if (utab->lexlevel != fileScope)
2366 if (utab->lexlevel > fileScope)
2368 llparseerror (cstring_makeLiteral ("New function scope inside function"));
2370 while (utab->lexlevel > fileScope)
2372 /*@i@*/ utab = usymtab_dropEnv (utab);
2379 llfatalbug (cstring_makeLiteral ("New function not inside file."));
2381 /*@-branchstate@*/ } /*@=branchstate@*/
2385 DPRINTF (("Globs: %s", globSet_unparse (uentry_getGlobs (fcn))));
2387 globSet_allElements (uentry_getGlobs (fcn), el)
2389 DPRINTF (("Here we go: %s", sRef_unparseFull (el)));
2391 if (sRef_isUndefGlob (el))
2393 int index = sRef_getScopeIndex (el);
2394 sRef sr = sRef_updateSref (el);
2395 fileloc loc = uentry_whereEarliest (fcn);
2397 DPRINTF (("update: %s", sRef_unparseFull (sr)));
2398 DPRINTF (("Undef!"));
2399 if (sRef_isFileStatic (el))
2401 ctype ct = sRef_getType (el);
2404 llassert (usymtab_isDefined (filetab));
2406 ue = usymtab_fetchIndex (filetab, index);
2408 if (ctype_isRealArray (ct) || ctype_isRealSU (ct))
2410 sRef_setAllocated (sr, loc);
2414 sRef_setUndefined (sr, loc);
2419 uentry ue = globtab->entries[index];
2420 ctype ct = uentry_getType (ue);
2422 if (ctype_isArray (ct) || ctype_isSU (ct))
2424 sRef_setAllocated (sr, loc);
2428 sRef_setUndefined (sr, loc);
2432 else if (sRef_isAllocated (el))
2434 sRef sr = sRef_updateSref (el);
2435 fileloc loc = uentry_whereEarliest (fcn);
2437 sRef_setAllocated (sr, loc);
2439 else if (sRef_isPartial (el))
2441 sRef sr = sRef_updateSref (el);
2442 fileloc loc = uentry_whereEarliest (fcn);
2444 sRef_setPartial (sr, loc);
2449 sRef sr = sRef_updateSref (el);
2450 fileloc loc = uentry_whereEarliest (fcn);
2452 sRef_setDefined (sr, loc);
2456 /* shouldn't need to do anything! */
2458 } end_globSet_allElements;
2460 DPRINTF (("Globs after: %s", globSet_unparse (uentry_getGlobs (fcn))));
2462 usymtab_checkAllValid ();
2467 usymtab_caseBranch (void)
2470 usymtab t = usymtab_create (US_CBRANCH, utab, FALSE);
2475 usymtab_switchBranch (/*@unused@*/ exprNode s)
2478 usymtab t = usymtab_create (US_SWITCH, utab, FALSE);
2480 t->aliases = aliasTable_copy (utab->aliases);
2485 usymtab_trueBranch (/*@only@*/ guardSet guards)
2488 usymtab t = usymtab_create (US_TBRANCH, utab, FALSE);
2491 ** not true! (could be in a macro)
2493 ** llassertprint (utab->lexlevel > paramsScope,
2494 ** ("not in scope: %s", usymtab_unparseLocal ()));
2498 guardSet_free (t->guards);
2501 aliasTable_free (t->aliases);
2502 t->aliases = aliasTable_copy (utab->aliases);
2510 ** { int a; if (...) a = 3; < a may be undefined here!
2515 usymtab_popTrueBranch (exprNode pred, exprNode expr, clause cl) /*@modifies utab@*/
2518 ** add a false branch
2519 ** (could be done more efficiently as a special case, but
2520 ** it is better to only maintain one version of the code)
2523 if (utab->kind != US_TBRANCH
2524 && context_inIterDef ())
2526 usymtab_exitScope (expr);
2530 DPRINTF (("pop true branch.."));
2531 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2532 usymtab_popBranches (pred, expr, exprNode_undefined, TRUE, cl);
2537 usymtab_popCaseBranch () /*@modifies utab@*/
2539 llassert (utab->kind == US_CBRANCH);
2540 usymtab_quietPlainExitScope ();
2544 usymtab_popTrueExecBranch (exprNode pred, exprNode expr, clause cl)
2547 ** add a false branch that must return --- that is,
2548 ** the true branch is always executed!
2551 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2552 usymtab_popBranches (pred, expr, exprNode_makeMustExit (), FALSE, cl);
2556 usymtab_popOrBranch (exprNode pred, exprNode expr)
2560 usymtab env = utab->env;
2561 usymtab otab = utab;
2564 llassert (env != NULL);
2566 if (exprNode_isError (expr))
2572 mustReturn = exprNode_mustEscape (expr);
2576 llassert (utab->kind == US_TBRANCH);
2579 ** merge each entry in table with its original
2580 ** unless execution cannot continue after this branch
2583 for (i = 0; i < utab->nentries; i++)
2585 uentry current = utab->entries[i];
2586 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2588 uentry_mergeState (old, current, exprNode_loc (expr),
2589 mustReturn, FALSE, TRUE, ORCLAUSE);
2595 env->guards = guardSet_levelUnionFree (env->guards,
2596 guardSet_invert (exprNode_getGuards (pred)),
2601 env->aliases = aliasTable_levelUnion (env->aliases, otab->aliases, env->lexlevel);
2604 /* env is now utab */
2605 usymtab_quietPlainExitScope ();
2609 ** case syntax in C is very unrestricted. This is unfortunate.
2611 ** A switch case is ended either by a new case or default, or
2612 ** a close } that may close the switch or some other control
2617 usymtab_newCase (/*@unused@*/ exprNode pred, exprNode last)
2620 bool mustBreak = usymtab_mustBreak (utab);
2621 bool mustReturn = usymtab_mustEscape (utab);
2622 usymtab stab = utab;
2624 DPRINTF (("New case!"));
2627 ** Find last case (or outer switch)
2630 while (stab->kind != US_CBRANCH && stab->kind != US_SWITCH)
2633 llassert (stab != GLOBAL_ENV);
2636 while (stab->kind == US_CBRANCH)
2639 llassert (stab != GLOBAL_ENV);
2643 ** if its a fall through case, merge in outside entries and last case.
2648 ** case 1: x = 3; <fall through>
2649 ** case 2: << x may not be defined
2653 if (!mustBreak && !mustReturn && utab->kind == US_CBRANCH)
2655 llassert (stab->kind == US_SWITCH || stab->kind == US_NORMAL);
2657 usymtab_entries (utab, ue) /* but, keep track of used variables */
2659 uentry old = usymtab_lookupAux (stab, uentry_rawName (ue));
2661 llassert (uentry_isValid (old));
2663 /* modifies ue, not old */
2665 uentry_mergeState (ue, old, exprNode_loc (last),
2666 FALSE, FALSE, TRUE, CASECLAUSE);
2667 } end_usymtab_entries;
2669 utab->aliases = aliasTable_levelUnion (utab->aliases,
2670 stab->aliases, utab->lexlevel);
2673 ** No need for a new branch.
2680 usymtab_caseBranch ();
2681 /*@-mustfree@*/ /*< utab->aliases >*/
2682 utab->aliases = aliasTable_copy (stab->aliases);
2690 ** for && (both pred and expr are executed)
2694 usymtab_popAndBranch (exprNode pred, /*@unused@*/ exprNode expr)
2697 usymtab env = utab->env;
2701 llassert (utab->kind == US_TBRANCH);
2704 ** merge each entry in table with its original
2705 ** unless execution cannot continue after this branch
2708 for (i = 0; i < utab->nentries; i++)
2710 uentry current = utab->entries[i];
2711 sRef tref = uentry_getSref (current);
2712 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2713 sRef oref = uentry_getSref (old);
2715 /* note that is current is in a nested branch,
2716 it may create a "new" old entry. */
2718 llassert (uentry_isValid (old));
2719 uentry_mergeState (old, current, exprNode_loc (expr),
2720 FALSE, FALSE, TRUE, ANDCLAUSE);
2723 ** if is it defined by the second clause, then it should be defined.
2726 if (sRef_isAnyDefined (tref)
2727 && (sRef_isAllocated (oref) || sRef_isStateUndefined (oref)))
2729 sRef_setDefined (oref, g_currentloc);
2733 utab->guards = guardSet_levelUnionFree (utab->guards,
2734 guardSet_invert (exprNode_getGuards (pred)),
2736 utab->aliases = aliasTable_levelUnion (utab->aliases, otab->aliases, utab->lexlevel);
2738 usymtab_quietPlainExitScope ();
2743 ** Stack should be [ US_CBRANCH+ US_SWITCH ]
2744 ** Only branches which do not return (except possibly the last branch) are included.
2746 ** Conditionally merge state from all CBRANCHes.
2748 ** If allpaths is TRUE, then all possible executions go through some switch
2749 ** case, and the original scope is not merged.
2753 usymtab_exitSwitch (/*@unused@*/ exprNode sw, bool allpaths)
2756 usymtab ttab = utab;
2757 usymtab stab = ttab;
2758 usymtab ltab = ttab;
2759 bool lastMustReturn = usymtab_mustEscape (utab);
2763 while (stab->kind == US_CBRANCH)
2766 llassert (stab != GLOBAL_ENV);
2769 while (stab->kind == US_NORMAL)
2772 llassert (stab != GLOBAL_ENV);
2775 llassert (stab->kind == US_SWITCH);
2777 /* go to the scope outside the switch (US_SWITCH is just a marker! */
2779 llassert (stab != GLOBAL_ENV);
2783 llassert (usymtab_isDefined (ttab));
2785 if (ttab->kind == US_CBRANCH)
2787 /* was quietPlainExitScope --- but, can't free it yet! */
2789 llassert (utab != GLOBAL_ENV);
2791 while (ttab->kind == US_CBRANCH)
2794 ** (from popTrueBranch)
2797 bool mustReturn = usymtab_mustEscape (ttab);
2798 bool mustBreak = usymtab_mustBreak (ttab);
2800 usymtab_entries (ttab, current)
2802 uentry old = /*@-compmempass@*/ usymtab_lookupAux (ltab, uentry_rawName (current));
2806 ** note that is this is in a nested branch,
2807 ** it may create a "new" old entry.
2810 if (uentry_isValid (old))
2814 uentry_mergeUses (current, old);
2815 uentry_setState (old, current);
2819 uentry_mergeState (old, current, exprNode_loc (sw),
2820 mustReturn, FALSE, TRUE, SWITCHCLAUSE);
2827 } end_usymtab_entries;
2830 ** if entry is not in symbol table for this case, merge with pre-switch
2834 if (!mustReturn && !mustBreak)
2836 usymtab_entries (stab, current)
2838 if (usymtab_getIndex (ttab, uentry_rawName (current)) == NOT_FOUND)
2840 uentry old = /*@-compmempass@*/
2841 usymtab_lookupAux (ltab, uentry_rawName (current));
2844 llassert (uentry_isValid (old));
2845 uentry_mergeState (old, current, exprNode_loc (sw),
2846 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2848 } end_usymtab_entries;
2851 ltab->env = ttab->env;
2855 ** Suprious error, becuase of environments.
2858 /*@i1@*/ utab = ltab;
2860 lastMustReturn = FALSE;
2867 ** now, there is one US_CBRANCH. Merge this with the stab.
2871 for (i = 0; i < ltab->nentries; i++)
2873 uentry current = ltab->entries[i];
2874 uentry old = usymtab_lookupAux (stab, uentry_rawName (current));
2876 /* note that is this is in a nested branch,
2877 it may create a "new" old entry. */
2880 if (uentry_isValid (old))
2884 uentry_mergeUses (current, old);
2885 uentry_setState (old, current);
2889 uentry_mergeState (old, current, exprNode_loc (sw),
2890 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2904 ** switch may or may not be followed by a new scope
2907 if (utab->kind == US_SWITCH)
2909 usymtab_quietPlainExitScope ();
2913 usymtab_quietPlainExitScope ();
2914 llassert (utab->kind == US_SWITCH);
2915 usymtab_quietPlainExitScope ();
2921 updateNullState (sRef el, /*@notnull@*/ usymtab ttab,
2922 /*@notnull@*/ usymtab ftab, bool trueGuard)
2924 sRef base = sRef_getRootBase (el);
2925 int level = sRef_lexLevel (base);
2927 if (sRef_isCvar (base))
2929 usymId index = sRef_getScopeIndex (base);
2930 uentry ue = usymtab_getRefTab (ttab, level, index);
2932 if (!uentry_isLset (ue))
2934 sRef sr = uentry_getSref (ue);
2938 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2942 if (!guardSet_isGuarded (ttab->guards, el)
2943 && !sRef_isNotNull (sr))
2945 DPRINTF (("Here! %s / %s",
2946 sRef_unparseFull (sr),
2947 sRef_unparseFull (el)));
2948 sRef_setDerivNullState (sr, el, NS_DEFNULL);
2957 ue = usymtab_getRefTab (ftab, level, index);
2959 if (!uentry_isLset (ue))
2961 sRef sr = uentry_getSref (ue);
2963 if (!trueGuard) /* yikes! forgot the ! */
2965 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2970 if (!guardSet_isGuarded (ftab->guards, el)
2971 && !sRef_isNotNull (sr))
2973 sRef_setDerivNullState (sr, el, NS_DEFNULL);
2985 usymtab_popBranches (exprNode pred, exprNode tbranch, exprNode fbranch,
2986 bool isOpt, clause cl)
2990 usymtab ftab = utab;
2991 usymtab ttab = utab->env;
2995 guardSet guards = exprNode_getGuards (pred);
2996 sRefSet tguards = guardSet_getTrueGuards (guards);
2997 sRefSet fguards = guardSet_getFalseGuards (guards);
2998 bool mustReturnT = exprNode_mustEscape (tbranch);
2999 bool mustReturnF = exprNode_mustEscape (fbranch);
3001 DPRINTF (("Pop branches: %s [mustreturn: %s/%s]", exprNode_unparse (pred),
3002 bool_unparse (mustReturnT),
3003 bool_unparse (mustReturnF)));
3005 if (exprNode_isDefined (fbranch))
3007 loc = exprNode_loc (fbranch);
3011 loc = exprNode_loc (tbranch);
3014 llassert (usymtab_isDefined (ttab));
3018 llassert (usymtab_isDefined (env));
3019 llassert (ftab->kind == US_FBRANCH);
3020 llassert (ttab->kind == US_TBRANCH);
3023 ** For each element that is true guarded (i.e., if (x != NULL))
3024 ** make x = null in false branch,
3025 ** and x = notnull in true branch.
3026 ** unless x was set locally in that branch.
3027 ** For each element that is false guarded (x == NULL)
3028 ** make x = null in true, notnull in false.
3030 ** For each element that is either guarded (pred(x))
3034 sRefSet_allElements (tguards, el)
3036 updateNullState (el, ttab, ftab, TRUE);
3037 } end_sRefSet_allElements;
3039 sRefSet_allElements (fguards, el)
3041 updateNullState (el, ttab, ftab, FALSE);
3042 } end_sRefSet_allElements;
3046 ** if an entry is in both true and false, merge the entries,
3047 ** then replace original with new state.
3049 ** if an entry is in one table, merge it with the original.
3052 DPRINTF (("ftab: %d", ftab->nentries));
3054 for (i = 0; i < ftab->nentries; i++)
3056 uentry fthis = ftab->entries[i];
3057 uentry old = usymtab_lookupAux (env, uentry_rawName (fthis));
3058 int tindex = usymtab_getIndex (ttab, uentry_rawName (fthis));
3060 DPRINTF (("Entry: %s / %s", uentry_unparseFull (fthis), uentry_unparseFull (old)));
3062 if (uentry_isUndefined (old))
3064 /* possible entry was added as an undefined id */
3065 DPRINTF (("Undefined! %s", uentry_rawName (fthis)));
3069 if (tindex != NOT_FOUND)
3071 uentry tthis = ttab->entries[tindex];
3073 /* note that is this is in a nested branch,
3074 it may create a "new" old entry. */
3080 uentry_mergeState (fthis, tthis, loc,
3081 mustReturnT, FALSE, FALSE, cl);
3085 uentry_mergeUses (fthis, tthis);
3088 uentry_setState (old, fthis);
3095 uentry_setState (old, tthis);
3096 uentry_mergeState (old, fthis, loc, mustReturnF,
3100 ttab->entries[tindex] = uentry_undefined;
3101 uentry_free (tthis);
3105 uentry_mergeState (old, fthis, loc, mustReturnF, TRUE, FALSE, cl);
3109 for (i = 0; i < ttab->nentries; i++)
3111 uentry current = ttab->entries[i];
3113 DPRINTF (("ttab: %s", uentry_unparseFull (current)));
3115 if (!uentry_isUndefined (current))
3117 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
3119 DPRINTF (("Old: %s", uentry_unparseFull (old)));
3121 if (uentry_isUndefined (old))
3123 llcontbug (message ("Undefined entry: %s", uentry_rawName (current)));
3129 uentry_mergeUses (current, old);
3130 uentry_setState (old, current);
3135 ** Assumes false branch is a fall-through if
3136 ** fbranch is not defined. This is true, unless
3137 ** where was some greivous error in processing
3138 ** the else branch of an if-then, in which case
3139 ** this is probably the right thing to do anyway.
3142 uentry_mergeState (old, current, loc, mustReturnT,
3146 DPRINTF (("==> %s", uentry_unparseFull (old)));
3151 ** Plain levelUnion doesn't work, since we need to use the sRef's in env->aliases
3152 ** if they are present.
3155 llassert (NOALIAS (env->aliases, ttab->aliases));
3156 llassert (NOALIAS (env->aliases, ftab->aliases));
3158 aliasTable_free (env->aliases);
3160 env->aliases = aliasTable_levelUnionNew (ttab->aliases,
3161 ftab->aliases, env->lexlevel);
3163 aliasTable_fixSrefs (env->aliases);
3165 DPRINTF (("Aliases: %s", aliasTable_unparse (env->aliases)));
3167 /* exit true and false scopes */
3168 usymtab_quietPlainExitScope ();
3169 usymtab_quietPlainExitScope ();
3173 utab->guards = guardSet_levelUnionFree
3175 guardSet_invert (exprNode_getGuards (pred)),
3181 utab->guards = guardSet_levelUnion (utab->guards,
3182 exprNode_getGuards (pred),
3186 DPRINTF (("Here."));
3189 static void usymtab_fixCases (void) /*@modifies utab@*/ {
3190 while (utab->kind == US_CBRANCH)
3192 usymtab_quietPlainExitScope ();
3195 llassert (utab->kind != US_CBRANCH);
3199 usymtab_altBranch (/*@only@*/ guardSet guards)
3203 usymtab parent = utab->env;
3205 t = usymtab_create (US_FBRANCH, utab, FALSE);
3208 ** If we are in a case, need to close it. The C syntax
3209 ** is very liberal, so this kludge is necessary.
3212 usymtab_fixCases ();
3214 DPRINTF (("Current kind: %s", usymtab_unparseStack ()));
3216 llassert (utab->kind == US_TBRANCH);
3217 llassert (parent != GLOBAL_ENV);
3219 guardSet_free (t->guards);
3222 aliasTable_free (t->aliases);
3223 t->aliases = aliasTable_copy (parent->aliases);
3229 usymtab_allDefined (void)
3230 /*@globals utab, globtab@*/
3234 llassert (utab == globtab);
3236 for (i = 0; i < utab->nentries; i++)
3238 uentry e = utab->entries[i];
3240 if (uentry_isPriv (e))
3242 ; /* no need to define it */
3246 if (context_getFlag (FLG_SPECUNDECL))
3248 fileloc sloc = uentry_whereSpecified (e);
3249 fileloc dloc = uentry_whereDeclared (e);
3251 if (fileloc_isDefined (sloc)
3252 && !uentry_isFakeTag (e)
3253 && !fileloc_isDefined (dloc))
3257 message ("%s %q specified but not declared",
3258 ekind_capName (uentry_getKind (e)),
3259 uentry_getName (e)),
3264 if (!uentry_isCodeDefined (e))
3266 fileloc dloc = uentry_whereDeclared (e);
3268 if (fileloc_isLib (dloc) || fileloc_isXHFile (dloc))
3272 else if (fileloc_isDefined (dloc))
3274 if (!uentry_isAnyTag (e))
3276 if (fileloc_isUser (dloc))
3280 message ("%s %q declared but not defined",
3281 ekind_capName (uentry_getKind (e)),
3282 uentry_getName (e)),
3284 DPRINTF (("decl: %s", uentry_unparseFull (e)));
3290 fileloc sloc = uentry_whereSpecified (e);
3292 if (fileloc_isDefined (sloc)
3293 && !fileloc_isImport (sloc)
3294 && !fileloc_isLib (sloc)
3295 && !fileloc_isPreproc (sloc)
3296 && !uentry_isFakeTag (e))
3298 if (uentry_isVariable (e) || uentry_isFunction (e))
3302 message ("%s %q specified but not declared or defined",
3303 ekind_capName (uentry_getKind (e)),
3304 uentry_getName (e)),
3311 message ("%s %q specified but not defined",
3312 ekind_capName (uentry_getKind (e)),
3313 uentry_getName (e)),
3323 void usymtab_exportHeader (void)
3328 for (i = 0; i < utab->nentries; i++)
3330 uentry ce = utab->entries[i];
3332 if (!uentry_isDatatype (ce)
3333 && !uentry_isAnyTag (ce)
3334 && !uentry_isEitherConstant (ce) && !uentry_isStatic (ce)
3335 && !uentry_isExternal (ce)
3336 && !uentry_isForward (ce))
3338 fileloc fwhere = uentry_whereDeclared (ce);
3340 if (fileloc_isUndefined (fwhere)
3341 && uentry_isFunction (ce))
3343 fwhere = uentry_whereDefined (ce);
3346 if (fileloc_isDefined (fwhere)
3347 && !fileloc_isHeader (fwhere)
3348 && !fileloc_isXHFile (fwhere)
3349 && !(fileloc_isSpecialFile (fwhere)
3350 && !context_getFlag (FLG_UNUSEDSPECIAL)))
3352 if (uentry_isVariable (ce))
3355 (FLG_EXPORTHEADERVAR,
3356 message ("%s %q exported but not declared in header file",
3357 ekind_capName (uentry_getKind (ce)),
3358 uentry_getName (ce)),
3361 uentry_showDefSpecInfo (ce, fwhere);
3366 if (!uentry_isIter (ce)
3367 && !uentry_isEndIter (ce)
3368 && !uentry_isExpandedMacro (ce))
3370 if (uentry_isFunction (ce)
3371 && cstring_equalLit (uentry_rawName (ce), "main"))
3373 ; /* no error for main */
3379 message ("%s %q exported but not declared "
3381 ekind_capName (uentry_getKind (ce)),
3382 uentry_getName (ce)),
3385 uentry_showDefSpecInfo (ce, fwhere);
3395 void usymtab_exportLocal (void)
3400 for (i = 0; i < utab->nentries; i++)
3402 uentry ce = utab->entries[i];
3404 if (!uentry_isDatatype (ce) && !uentry_isAnyTag (ce)
3405 && !uentry_isEitherConstant (ce)
3406 && !uentry_isIter (ce)
3407 && !uentry_isEndIter (ce)
3408 && !uentry_isExpandedMacro (ce)
3409 && uentry_isUsed (ce))
3411 /* check static uses */
3412 filelocList fuses = uentry_getUses (ce);
3413 fileloc mod = uentry_whereDefined (ce);
3414 bool ok = filelocList_isEmpty (fuses);
3415 fileloc fwhere = uentry_whereDeclared (ce);
3417 if (fileloc_isSpecialFile (fwhere)
3418 && !context_getFlag (FLG_UNUSEDSPECIAL))
3420 ok = TRUE; /* no errors for special files */
3424 filelocList_elements (fuses, uloc)
3426 if (fileloc_isUndefined (uloc) || !fileloc_sameModule (uloc, mod))
3429 /*@innerbreak@*/ break;
3431 } end_filelocList_elements;
3438 message ("%s exported but not used outside %s: %q",
3439 ekind_capName (uentry_getKind (ce)),
3440 fileloc_getBase (mod),
3441 uentry_getName (ce)),
3444 uentry_showDefSpecInfo (ce, fwhere);
3452 usymtab_allUsed (void)
3456 bool isFileStatic = usymtab_inFileScope ();
3457 cstring last_file = cstring_undefined;
3459 for (i = 0; i < utab->nentries; i++)
3461 bool hasError = FALSE;
3462 uentry ce = utab->entries[i];
3463 fileloc fwhere = uentry_whereDeclared (ce);
3465 if (fileloc_isUndefined (fwhere))
3467 fwhere = uentry_whereDefined (ce);
3470 if (fileloc_isInvalid (fwhere)
3471 || fileloc_isLib (fwhere)
3472 || fileloc_isBuiltin (fwhere)
3473 || ((fileloc_isSpecialFile (fwhere)
3474 || fileloc_isSpecialFile (uentry_whereDefined (ce)))
3475 && !context_getFlag (FLG_UNUSEDSPECIAL)))
3479 else if (!uentry_wasUsed (ce) && !uentry_isAnyTag (ce))
3481 cstring fname = fileloc_filename (fwhere);
3483 if (cstring_isUndefined (last_file))
3487 else if (cstring_equal (fname, last_file))
3496 if (uentry_isParam (ce))
3498 if (context_inMacro ())
3500 sRef cref = uentry_getSref (ce);
3502 if (uentry_isYield (ce))
3504 ; /* no checks (for now) */
3506 else if (sRef_isSafe (cref))
3512 if (uentry_hasRealName (ce))
3515 optgenerror (FLG_MACROPARAMS,
3516 message ("Macro parameter %q not used",
3517 uentry_getName (ce)),
3524 if (cstring_equalFree (uentry_getName (ce),
3525 cstring_makeLiteral ("...")))
3531 hasError = optgenerror (FLG_PARAMUNUSED,
3532 message ("Parameter %q not used",
3533 uentry_getName (ce)),
3538 else if (uentry_isFunction (ce) || uentry_isIter (ce))
3540 if (fileloc_isUser (fwhere))
3542 hasError = optgenerror
3544 message ("%q %q declared but not used",
3546 (uentry_isIter (ce) ? "Iterator"
3547 : (isFileStatic ? "File static function" : "Function")),
3548 uentry_getName (ce)),
3552 else if (uentry_isEndIter (ce))
3554 ; /* no error (already reported for iter */
3556 else if (uentry_isEnumConstant (ce))
3558 if (fileloc_isUser (fwhere))
3560 hasError = optgenerror
3562 message ("Enum member %q not used",
3563 uentry_getName (ce)),
3567 else if (uentry_isConstant (ce))
3569 if (fileloc_isUser (fwhere))
3571 hasError = optgenerror
3573 message ("Constant %q declared but not used",
3574 uentry_getName (ce)),
3578 else if (uentry_isDatatype (ce))
3580 if (fileloc_isUser (fwhere))
3582 hasError = optgenerror
3584 message ("Type %q declared but not used",
3585 uentry_getName (ce)),
3589 else if (!uentry_isRefParam (ce) && !uentry_isExpandedMacro (ce))
3590 { /* errors for ref params will be reported in the next scope */
3591 llassertprint (uentry_isVar (ce),
3592 ("ce: %s", uentry_unparseFull (ce)));
3594 if (ctype_isFunction (uentry_getType (ce)))
3596 if (fileloc_isUser (fwhere))
3598 hasError = optgenerror
3600 message ("%q %q declared but not used",
3602 (isFileStatic ? "File static function"
3604 uentry_getName (ce)),
3610 if (fileloc_isUser (fwhere))
3614 hasError = optgenerror
3616 message ("%q %q declared but not used",
3618 (isFileStatic ? "File static variable"
3620 uentry_getName (ce)),
3630 else if ((uentry_isDatatype (ce) || uentry_isAnyTag (ce)))
3631 { /* check all fields */
3632 ctype ct = uentry_getRealType (ce);
3635 while (ctype_isAP (ct))
3637 ct = ctype_getBaseType (ct);
3640 if (ctype_isSU (ct))
3642 uentryList fields = ctype_getFields (ct);
3644 uentryList_elements (fields, field)
3646 if (!uentry_isUsed (field))
3648 if (uentry_hasName (ce))
3650 hasError |= optgenerror
3652 message ("Field %q of %s %q declared but not used",
3653 uentry_getName (field),
3654 cstring_makeLiteralTemp
3655 (ctype_isStruct (ct) ? "structure" : "union"),
3656 uentry_getName (ce)),
3657 uentry_whereEarliest (field));
3663 ** Can't report these errors for unnamed structs.
3664 ** No way to tell when there are multiple consistent
3665 ** unnamed structure types. (Could go through table
3666 ** and mark them all unused...)
3668 hasError |= optgenerror
3670 message ("Field %q of unnamed %s declared but not used",
3671 uentry_getName (field),
3672 cstring_makeLiteralTemp
3673 (ctype_isStruct (ct) ? "structure" : "union")),
3674 uentry_whereEarliest (field));
3679 uentry_setUsed (field, fileloc_undefined);
3681 } end_uentryList_elements;
3691 if (uentry_isParam (ce) && context_inMacro ())
3693 if (fileloc_isDefined (uentry_whereSpecified (ce)))
3695 uentry_showWhereSpecified (ce);
3700 uentry_showDefSpecInfo (ce, fwhere);
3703 uentry_setUsed (ce, fileloc_undefined);
3709 checkGlobalReturn (uentry glob, sRef orig)
3711 sRef sr = uentry_getSref (glob);
3713 DPRINTF (("Check global return: %s / orig: %s / sr: %s",
3714 uentry_unparseFull (glob),
3715 sRef_unparseFull (orig),
3716 sRef_unparseFull (sr)));
3718 DPRINTF (("Is killed: %s", bool_unparse (sRef_isKilledGlob (orig))));
3720 if (context_getFlag (FLG_GLOBSTATE))
3722 DPRINTF (("Is killed: %s", sRef_unparseFull (orig)));
3724 if (sRef_isKilledGlob (orig))
3726 if (sRef_isStateUndefined (sr)
3727 || sRef_isUnuseable (sr)
3728 || sRef_isStateUnknown (sr)
3729 || sRef_isDead (sr))
3735 ctype ct = ctype_realType (uentry_getType (glob));
3737 DPRINTF (("Check global destroyed: %s", uentry_unparseFull (glob)));
3739 if (ctype_isVisiblySharable (ct))
3744 ("Killed global %q (type %s) not released before return",
3745 uentry_getName (glob),
3746 ctype_unparse (ct)),
3749 sRef_showStateInfo (sr);
3754 sRef_protectDerivs ();
3755 (void) transferChecks_globalDestroyed (sr, g_currentloc);
3756 sRef_clearProtectDerivs ();
3762 if (sRef_isStateUndefined (sr))
3764 if (optgenerror (FLG_GLOBSTATE,
3766 ("Function returns with global %q undefined",
3767 uentry_getName (glob)),
3770 sRef_showStateInfo (sr);
3775 if (sRef_isDead (sr) || sRef_isKept (sr))
3779 message ("Function returns with global %q "
3780 "referencing %s storage",
3781 uentry_getName (glob),
3782 cstring_makeLiteralTemp (sRef_isDead (sr) ? "released" : "kept")),
3785 if (sRef_isKept (sr))
3787 sRef_showAliasInfo (sr);
3791 sRef_showStateInfo (sr);
3794 sRef_setDefState (sr, SS_UNKNOWN, fileloc_undefined);
3798 if (ctype_isRealPointer (uentry_getType (glob))
3799 && sRef_possiblyNull (sr)
3800 && !uentry_possiblyNull (glob))
3804 message ("Function returns with non-null global %q "
3805 "referencing null storage",
3806 uentry_getName (glob)),
3809 sRef_showNullInfo (sr);
3814 DPRINTF (("Check transfer: %s", uentry_unparseFull (glob)));
3815 transferChecks_globalReturn (glob);
3823 ** remember: check alias globals
3826 void usymtab_checkFinalScope (bool isReturn)
3829 bool mustFree = context_getFlag (FLG_MUSTFREEONLY) || context_getFlag (FLG_MUSTFREEFRESH); /*@i423 remove this mustFree */
3830 bool mustDefine = context_getFlag (FLG_MUSTDEFINE);
3831 /* bool mustNotAlias = context_getFlag (FLG_MUSTNOTALIAS); */
3832 sRefSet checked = sRefSet_new ();
3833 usymtab stab = utab;
3837 ** need to check all scopes out to function parameters.
3842 for (i = 0; i < stab->nentries; i++)
3844 uentry ce = stab->entries[i];
3845 sRef sr = uentry_getSref (ce);
3846 sRef rb = sRef_getRootBase (sr);
3850 ** Shouldn't check if shadow checked in deeper scope:
3855 uentry oue = usymtab_lookupQuietNoAlt (utab, uentry_observeRealName (ce));
3857 if (!uentry_sameObject (ce, oue))
3859 DPRINTF (("Skipping outer entry: %s / %s", uentry_unparseFull (ce),
3860 uentry_unparseFull (oue)));
3861 /*@i32 what if it is one an alternate branch? */
3862 /*@innercontinue@*/ continue;
3866 DPRINTF (("Here check final scope: %s", uentry_unparseFull (ce)));
3868 if (ctype_isFunction (uentry_getType (ce)))
3870 /*@innercontinue@*/ continue;
3873 if (uentry_isAnyParam (ce)
3874 || uentry_isRefParam (ce)
3875 || sRef_isFileOrGlobalScope (rb))
3877 /* Don't do the loseref check...but should check state! */
3878 DPRINTF (("Skipping check 1"));
3880 else if (sRef_isDefinitelyNull (sr)
3881 || usymtab_isDefinitelyNull (sr))
3884 ** No state reference errors for definitely null references.
3887 DPRINTF (("Skipping check 2"));
3891 DPRINTF (("Lose ref: %s / %s", uentry_unparse (ce),
3892 sRef_unparseFull (sr)));
3894 tvalues = sRef_getValueTable (sr);
3896 valueTable_elements (tvalues, fkey, fval) {
3897 metaStateInfo minfo;
3898 cstring msg = cstring_undefined;
3901 minfo = context_lookupMetaStateInfo (fkey);
3902 llassert (metaStateInfo_isDefined (minfo));
3904 if (stateValue_isError (fval)
3905 || sRef_isStateUndefined (sr)) /* No errors for undefined state */
3907 DPRINTF (("Skipping check 3"));
3911 DPRINTF (("Check: %s / %s / %s", fkey,
3912 metaStateInfo_unparse (minfo),
3913 stateValue_unparse (fval)));
3915 minfo = context_lookupMetaStateInfo (fkey);
3917 nval = stateCombinationTable_lookupLoseReference
3918 (metaStateInfo_getTransferTable (minfo),
3919 stateValue_getValue (fval), &msg);
3921 if (cstring_isDefined (msg))
3923 /*@i32 print extra info for assignments@*/
3924 DPRINTF (("From: %s", sRef_unparseFull (sr)));
3925 DPRINTF (("Null? %s / %s",
3926 bool_unparse (sRef_isDefinitelyNull (sr)),
3927 bool_unparse (usymtab_isGuarded (sr))));
3932 ("%s loses reference %q in invalid state %q (%s)",
3933 cstring_makeLiteralTemp (isReturn ? "Return" : "Scope exit"),
3934 uentry_getName (ce),
3935 stateValue_unparseValue (fval, minfo),
3939 stateValue_show (fval, minfo);
3943 DPRINTF (("Suppressed transfer error: %s", msg));
3947 } end_valueTable_elements;
3950 DPRINTF (("Here 1"));
3954 DPRINTF (("Check mustfree entry: %s", uentry_unparseFull (ce)));
3956 if (!sRefSet_member (checked, sr) && !sRef_isFileOrGlobalScope (rb))
3958 if (ctype_isRealSU (uentry_getType (ce))
3959 && !uentry_isAnyParam (ce)
3960 && !uentry_isRefParam (ce)
3961 && !uentry_isStatic (ce)
3962 && !sRef_isDependent (sr)
3963 && !sRef_isOwned (sr))
3965 sRefSet als = usymtab_allAliases (sr);
3967 if (sRefSet_isEmpty (als))
3969 transferChecks_localDestroyed (sr, g_currentloc);
3973 /* aliased, no problem */ ;
3979 (!uentry_isStatic (ce)
3980 && ((sRef_isNewRef (sr))
3981 || (((sRef_isOnly (sr) || sRef_isFresh (sr)
3982 || sRef_isKeep (sr) || sRef_isOwned (sr))
3983 && !sRef_isDead (sr))
3984 && (!sRef_definitelyNull (sr))
3985 && (!usymtab_isDefinitelyNull (sr)))))
3987 bool hasError = TRUE;
3989 DPRINTF (("Checking: %s", sRef_unparseFull (sr)));
3992 ** If its a scope exit, check if there is an alias.
3993 ** If so, make it only. If not, there is an error.
3998 if (transferChecks_canLoseReference (sr, g_currentloc))
4000 DPRINTF (("Can lose!"));
4007 if (sRef_hasLastReference (sr))
4009 sRef ar = sRef_getAliasInfoRef (sr);
4012 (sRef_isFresh (ar) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4014 ("Last reference %q to %s storage %qnot %q before %q",
4016 alkind_unparse (sRef_getAliasKind (sr)),
4017 sRef_unparseOpt (ar),
4018 cstring_makeLiteral (sRef_isKeep (sr)
4019 ? "transferred" : "released"),
4020 cstring_makeLiteral (isReturn
4021 ? "return" : "scope exit")),
4024 sRef_showRefLost (sr);
4027 else if (sRef_isNewRef (sr))
4030 (sRef_isFresh (sr) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4032 ("%q %q not released before %q",
4034 (alkind_isKillRef (sRef_getOrigAliasKind (sr))
4035 ? "Kill reference parameter" : "New reference"),
4036 uentry_getName (ce),
4037 cstring_makeLiteral (isReturn
4038 ? "return" : "scope exit")),
4041 sRef_showAliasInfo (sr);
4046 if (ctype_isRealSU (sRef_getType (sr)))
4048 transferChecks_structDestroyed (sr, g_currentloc);
4052 DPRINTF (("Here we are: %s", sRef_unparseFull (sr)));
4055 (sRef_isFresh (sr) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4057 ("%s storage %q not %q before %q",
4058 alkind_capName (sRef_getAliasKind (sr)),
4059 uentry_getName (ce),
4060 cstring_makeLiteral (sRef_isKeep (sr)
4061 ? "transferred" : "released"),
4062 cstring_makeLiteral (isReturn
4063 ? "return" : "scope exit")),
4066 sRef_showAliasInfo (sr);
4067 DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
4080 if (mustDefine && uentry_isOut (ce))
4082 /* No error if its dead (either only or error already reported */
4083 if (!sRef_isReallyDefined (sr) && !sRef_isDead (sr))
4087 message ("Out storage %q not defined before %q",
4088 uentry_getName (ce),
4090 (isReturn ? "return" : "scope exit")),
4093 DPRINTF (("sr: %s", sRef_unparseFull (sr)));
4098 ** also check state is okay
4101 if (usymtab_lexicalLevel () > functionScope
4102 && uentry_isVariable (ce)
4103 && (sRef_isLocalVar (sr)
4104 && (sRef_isDependent (sr) || sRef_isLocalState (sr))))
4106 sRefSet ab = usymtab_aliasedBy (sr);
4108 /* should do something more efficient here */
4110 if (sRefSet_isEmpty (ab))
4112 /* and no local ref */
4113 DPRINTF (("Check lose ref: %s", uentry_unparseFull (ce)));
4114 transferChecks_loseReference (ce);
4128 checked = sRefSet_insert (checked, sr);
4131 llassert (usymtab_isDefined (stab->env));
4133 if (usymtab_isBranch (stab))
4135 stab = usymtab_dropEnv (stab);
4142 llassert (stab != usymtab_undefined);
4143 } while (isReturn && (stab->lexlevel >= paramsScope));
4145 sRefSet_free (checked);
4149 ** all globals are appropriately defined
4150 ** all parameters are appropriately defined
4151 ** special clauses are followed
4154 if (isReturn || (utab->lexlevel == paramsScope))
4156 uentry fcn = context_getHeader ();
4157 uentryList params = context_getParams ();
4158 globSet uglobs = context_getUsedGlobs ();
4159 globSet sglobs = context_getGlobs ();
4161 if (isReturn && context_maybeSet (FLG_GLOBALIAS))
4163 aliasTable_checkGlobs (utab->aliases);
4167 ** state clauses (ensures, defines, sets, allocates, releases)
4170 if (uentry_hasStateClauseList (fcn))
4172 stateClauseList clauses = uentry_getStateClauseList (fcn);
4174 stateClauseList_elements (clauses, cl)
4176 if (stateClause_isAfter (cl) && !stateClause_isGlobal (cl))
4178 if (stateClause_setsMetaState (cl))
4180 sRefSet rfs = stateClause_getRefs (cl);
4181 qual q = stateClause_getMetaQual (cl);
4182 annotationInfo ainfo = qual_getAnnotationInfo (q);
4183 metaStateInfo minfo = annotationInfo_getState (ainfo);
4184 cstring key = metaStateInfo_getName (minfo);
4185 int mvalue = annotationInfo_getValue (ainfo);
4187 DPRINTF (("Post meta state clause: %s", stateClause_unparse (cl)));
4189 sRefSet_elements (rfs, el)
4191 sRef base = sRef_getRootBase (el);
4193 if (sRef_isResult (base))
4196 ** This is checked for return transfers.
4200 else if (sRef_isParam (base) || sRef_isGlobalMarker (base))
4202 sRef sr = sRef_updateSref (base);
4203 sr = sRef_fixBase (el, sr);
4205 if (!sRef_checkMetaStateValue (sr, key, mvalue))
4210 ("Ensures clause not satisfied%q (state is %q): %q",
4211 sRef_isGlobalMarker (sr)
4213 : message (" by %q", sRef_unparse (sr)),
4214 stateValue_unparseValue (sRef_getMetaStateValue (sr, key),
4216 stateClause_unparse (cl)),
4219 sRef_showMetaStateInfo (sr, key);
4225 if (sRef_isMeaningful (el))
4230 } end_sRefSet_elements ;
4234 /* evs - 2000 07 10 - added this */
4235 sRefTest tst = stateClause_getPostTestFunction (cl);
4236 sRefSet rfs = stateClause_getRefs (cl);
4238 sRefSet_elements (rfs, el)
4240 sRef base = sRef_getRootBase (el);
4242 if (sRef_isResult (base))
4245 ** This is checked for return transfers.
4250 else if (sRef_isParam (base))
4252 sRef sr = sRef_updateSref (base);
4253 sr = sRef_fixBase (el, sr);
4255 if (tst != NULL && !tst (sr))
4258 (stateClause_postErrorCode (cl),
4259 message ("%s storage %qcorresponds to "
4260 "storage listed in %q clause",
4261 stateClause_postErrorString (cl, sr),
4262 sRef_unparseOpt (sr),
4263 stateClause_unparseKind (cl)),
4266 sRefShower ss = stateClause_getPostTestShower (cl);
4273 DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
4279 if (sRef_isMeaningful (el))
4284 } end_sRefSet_elements ;
4287 } end_stateClauseList_elements ;
4291 ** check parameters on return
4294 uentryList_elements (params, arg)
4296 if (!uentry_isElipsisMarker (arg))
4298 ctype rt = ctype_realType (uentry_getType (arg));
4300 if (ctype_isMutable (rt) || ctype_isSU (rt))
4302 uentry param = usymtab_lookupQuiet (utab, uentry_rawName (arg));
4303 DPRINTF (("Check param return: %s", uentry_unparseFull (param)));
4304 transferChecks_paramReturn (param);
4307 } end_uentryList_elements;
4309 DPRINTF (("Check global return: %s",
4310 globSet_unparse (sglobs)));
4312 globSet_allElements (sglobs, el)
4314 sRef orig = el; /*! sRef_updateSref (el); */ /*!!!*/
4315 uentry current = sRef_getUentry (el);
4317 DPRINTF (("Check global return: %s / %s", sRef_unparseFull (el),
4318 uentry_unparseFull (current)));
4320 if (uentry_isVariable (current) && !uentry_isRealFunction (current))
4322 checkGlobalReturn (current, orig);
4324 } end_globSet_allElements;
4326 globSet_allElements (uglobs, el)
4328 if (!globSet_member (sglobs, el))
4330 uentry current = sRef_getUentry (el);
4332 if (uentry_isVariable (current)
4333 && !uentry_isRealFunction (current))
4335 checkGlobalReturn (current, sRef_undefined);
4338 } end_globSet_allElements;
4343 usymtab_quietExitScope (fileloc loc)
4344 /*@globals utab, globtab, filetab; @*/
4347 usymtab t = utab->env;
4349 DPRINTF (("Quiet exit scope [%p]", utab));
4351 if (utab->reftable != NULL)
4355 for (i = 0; i < utab->nentries; i++)
4357 uentry current = utab->entries[i];
4358 uentry old = usymtab_lookupAux (t, uentry_rawName (current));
4360 uentry_mergeState (old, current, loc, FALSE, FALSE, FALSE, NOCLAUSE);
4364 llassert (t != NULL);
4366 if (t->lexlevel > paramsScope)
4368 t->guards = guardSet_levelUnion (t->guards, utab->guards, t->lexlevel);
4369 t->aliases = aliasTable_levelUnionSeq (t->aliases, utab->aliases,
4371 utab->aliases = aliasTable_undefined;
4374 t->mustBreak = utab->mustBreak;
4375 t->exitCode = utab->exitCode;
4377 DPRINTF (("Free level [%p]", utab));
4378 usymtab_freeLevel (utab);
4383 usymtab_checkAllValid ();
4388 ** Exit a scope with no checking, lose alias states.
4389 ** (When should this be used?)
4392 void usymtab_quietPlainExitScope (void)
4393 /*@globals utab, globtab, filetab@*/
4396 usymtab t = utab->env;
4398 llassert (t != NULL);
4399 llassert (NOALIAS (utab->aliases, t->aliases));
4400 usymtab_freeLevel (utab);
4404 void usymtab_exitScope (exprNode expr)
4405 /*@globals utab, filetab, globtab@*/
4406 /*@modifies utab, globtab@*/
4408 usymtab ctab = usymtab_undefined;
4409 usymtab lctab = usymtab_undefined;
4410 bool mustReturn = exprNode_mustEscape (expr);
4412 DPRINTF (("Exit scope [%p]", utab));
4414 if (utab->kind == US_CBRANCH)
4417 ** save the case branches, remove the first non-cbranch
4422 while (utab->kind == US_CBRANCH)
4426 llassert (utab != GLOBAL_ENV);
4430 if (utab->kind == US_TBRANCH || utab->kind == US_FBRANCH
4431 || utab->kind == US_CBRANCH || utab->kind == US_SWITCH)
4433 if (context_inMacro ())
4435 /* evs 2000-07-25 */
4436 /* Unparseable macro may end inside nested scope. Deal with it. */
4438 llerror (FLG_SYNTAX,
4439 message ("Problem parsing macro body of %s (unbalanced scopes). "
4440 "Attempting to recover, recommend /*@notfunction@*/ before "
4441 "macro definition.",
4442 context_inFunctionName ()));
4444 while (utab->kind == US_TBRANCH
4445 || utab->kind == US_FBRANCH
4446 || utab->kind == US_CBRANCH
4447 || utab->kind == US_SWITCH)
4450 llassert (utab != GLOBAL_ENV);
4454 llcontbug (message ("exitScope: in branch: %q", usymtab_unparseStack ()));
4456 } /*@=branchstate@*/
4460 ** check all variables in scope were used
4464 ** bogus errors if this is the normal inside a switch,
4465 ** since cases have not been merged yet. Should probably
4466 ** still check this, but I'm too lazy at the moment...
4469 llassertfatal (utab->env != GLOBAL_ENV);
4471 if (utab->env->kind != US_SWITCH)
4477 ** check aliasing: all only params are released (dead)
4478 ** definition: all out params are defined, all modified params
4479 ** are completely defined
4481 ** NOTE: note for exiting paramsScope, since checkReturn should be
4485 if (!mustReturn && (usymtab_lexicalLevel () > functionScope))
4488 ** should only call this is end of scope is reachable...
4491 usymtab_checkFinalScope (FALSE);
4494 if (usymtab_lexicalLevel () == paramsScope && context_inFunctionLike ())
4497 ** leaving a function, need to fix up globals
4500 uentryList params = context_getParams ();
4501 globSet globs = context_getUsedGlobs ();
4503 uentryList_elements (params, ue)
4505 uentry_fixupSref (ue);
4506 } end_uentryList_elements;
4508 clearFunctionTypes ();
4510 DPRINTF (("Fixing up globals: %s", globSet_unparse (globs)));
4512 globSet_allElements (globs, el)
4514 DPRINTF (("Fix: %s", sRef_unparseDebug (el)));
4516 if (sRef_isCvar (el))
4519 int index = sRef_getScopeIndex (el);
4521 if (sRef_isFileStatic (el))
4523 llassert (usymtab_isDefined (filetab));
4524 current = usymtab_fetchIndex (filetab, index);
4528 current = usymtab_fetchIndex (globtab, index);
4531 if (uentry_isVariable (current))
4533 DPRINTF (("Fixup: %s", uentry_unparse (current)));
4534 uentry_fixupSref (current);
4538 DPRINTF (("Clear: %s", uentry_getSref (current)));
4539 sRef_clearDerived (uentry_getSref (current));
4543 sRef_clearDerived (el); /* evans 2002-03-14 - this is the likely source of many crashes! */
4544 } end_globSet_allElements;
4547 usymtab_quietExitScope (exprNode_loc (expr));
4549 if (lctab != usymtab_undefined)
4551 /*@i@*/ lctab->env = utab;
4552 /*@i@*/ utab = ctab;
4553 /*@-branchstate@*/ } /*@=branchstate@*/
4558 usymtab_checkAllValid ();
4564 ** yikes! don't let the '170 kids see this one...
4568 uentry_directParamNo (uentry ue)
4570 if (uentry_isVar (ue))
4572 sRef sr = uentry_getSref (ue);
4574 if (sRef_lexLevel (sr) == functionScope)
4576 int index = sRef_getScopeIndex (sr);
4578 if (index < uentryList_size (context_getParams ()))
4587 /*@dependent@*/ /*@exposed@*/ uentry
4588 usymtab_getParam (int paramno)
4592 ** requires in a function context (checked)
4594 ** depends on no nested functions --- the function
4595 ** parameters are ALWAYS one scope inside the global scope
4596 ** and entered in order!
4600 if (!context_inFunctionLike ())
4601 llfatalbug (message ("usymtab_getParam: not in function context: %q",
4602 context_unparse ()));
4604 while (s->lexlevel > paramsScope)
4609 llassert (usymtab_isDefined (s));
4611 if (paramno >= s->nentries)
4614 ** Parse errors lead to this.
4617 uentry err = uentry_makeVariableLoc (cstring_makeLiteralTemp ("<error>"),
4620 uentry_markOwned (err);
4624 return (s->entries[paramno]);
4627 static /*@dependent@*/ /*@exposed@*/ uentry
4628 usymtab_getRefTab (/*@notnull@*/ usymtab u, int level, usymId index)
4632 ue = usymtab_getRefNoisy (u, level, index);
4634 if (uentry_isUndefined (ue))
4636 llbug (message ("usymtab_getRef: out of range: %d. level = %d",
4643 static /*@dependent@*/ /*@exposed@*/ usymtab
4644 usymtab_dropEnv (/*@notnull@*/ usymtab s)
4646 if (s->kind == US_CBRANCH)
4654 llassert (s != GLOBAL_ENV);
4655 } while (s->kind == US_CBRANCH);
4656 /* drop all cases (except in nested scopes */
4659 llassert (s != GLOBAL_ENV);
4662 if (s->kind == US_FBRANCH)
4664 s = s->env; /* skip the true branch */
4665 llassert (usymtab_isDefined (s));
4666 llassert (s->kind == US_TBRANCH);
4669 llassert (s != GLOBAL_ENV);
4675 /*@dependent@*/ /*@exposed@*/ uentry
4676 usymtab_getRefQuiet (int level, usymId index)
4682 llassert (s != NULL);
4683 llassert (index >= 0);
4685 if (level > s->lexlevel)
4687 return uentry_undefined;
4690 llassertprint (level <= s->lexlevel, ("level: %d / lexlevel: %d",
4691 level, s->lexlevel));
4693 while (s->lexlevel > level)
4695 if (usymtab_isBranch (s))
4697 int eindex = refTable_lookup (s, level, index);
4699 if (eindex != NOT_FOUND)
4701 return (s->entries[eindex]);
4705 s = usymtab_dropEnv (s);
4708 while (usymtab_isBranch (s) && s->lexlevel == level)
4710 int eindex = refTable_lookup (s, level, index);
4712 if (eindex != NOT_FOUND)
4714 return (s->entries[eindex]);
4717 s = usymtab_dropEnv (s);
4720 if (index >= s->nentries)
4722 return uentry_undefined;
4725 llassert (!uentry_isUndefined (s->entries[index]));
4727 return s->entries[index];
4730 static /*@dependent@*/ /*@exposed@*/ uentry
4731 usymtab_getRefNoisy (/*@notnull@*/ usymtab s, int level, usymId index)
4734 uentry ue = uentry_undefined;
4736 llassert (index >= 0);
4738 while (s->lexlevel > level)
4740 if (usymtab_isBranch (s))
4742 int eindex = refTable_lookup (s, level, index);
4744 if (eindex != NOT_FOUND)
4746 ue = s->entries[eindex];
4750 while (!usymtab_isBranch (otab))
4752 otab = usymtab_dropEnv (otab);
4753 llassert (otab != GLOBAL_ENV);
4756 if (refTable_lookup (otab, level, index) == NOT_FOUND)
4758 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4770 s = usymtab_dropEnv (s);
4773 llassert (usymtab_isDefined (s));
4775 while (usymtab_isBranch (s) && s->lexlevel == level)
4777 int eindex = refTable_lookup (s, level, index);
4780 if (eindex != NOT_FOUND)
4782 ue = s->entries[eindex];
4786 while (!usymtab_isBranch (otab))
4788 otab = usymtab_dropEnv (otab);
4789 llassert (otab != GLOBAL_ENV);
4792 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4802 s = usymtab_dropEnv (s);
4805 if (s->lexlevel == level && (index < s->nentries))
4807 ue = s->entries[index];
4809 if (uentry_isValid (ue))
4813 while (!usymtab_isBranch (otab))
4815 otab = usymtab_dropEnv (otab);
4817 if (otab == GLOBAL_ENV)
4823 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4834 if (index >= s->nentries)
4836 return uentry_undefined;
4839 llassert (!uentry_isUndefined (s->entries[index]));
4841 return s->entries[index];
4845 ** looking up entries
4847 ** If entry is inside a branch, then copy it, and put it into
4848 ** the branch table.
4852 int refTable_lookup (/*@notnull@*/ usymtab ut, int level, int index)
4854 refTable rt = ut->reftable;
4857 llassert (rt != NULL);
4859 for (i = 0; i < ut->nentries; i++)
4861 if (rt[i]->level == level && rt[i]->index == index)
4871 /*@only@*/ refentry refentry_create (int level, int index)
4873 refentry r = (refentry) dmalloc (sizeof (*r));
4881 static /*@dependent@*/ /*@exposed@*/ uentry
4882 usymtab_addRefEntry (/*@notnull@*/ usymtab s, cstring k)
4887 if (ut->reftable == NULL)
4889 DPRINTF (("Adding ref entry without reftable: %s", k));
4890 return uentry_undefined;
4893 llassert (ut->reftable != NULL);
4895 while (s != GLOBAL_ENV)
4897 eindex = usymtab_getIndex (s, k);
4899 if (eindex != NOT_FOUND)
4901 uentry current = s->entries[eindex];
4903 if (uentry_isVar (current) && !ctype_isFunction (uentry_getType (current)))
4907 DPRINTF (("Here: copying %s", uentry_unparse (current)));
4908 if (uentry_isNonLocal (current))
4910 ue = uentry_copy (current);
4914 ue = uentry_copyNoSave (current);
4917 DPRINTF (("Here: copying %s", uentry_unparse (ue)));
4918 usymtab_addEntryQuiet (ut, ue);
4919 DPRINTF (("Okay..."));
4921 if (s->reftable != NULL)
4923 refentry ref = s->reftable[eindex];
4925 ut->reftable[ut->nentries - 1]
4926 = refentry_create (ref->level, ref->index);
4930 ut->reftable[ut->nentries - 1]
4931 = refentry_create (s->lexlevel, eindex);
4942 s = usymtab_dropEnv (s);
4945 return uentry_undefined;
4948 static uentry usymtab_lookupAux (usymtab s, cstring k)
4950 DPRINTF (("Lookup: %s", k));
4952 while (s != GLOBAL_ENV)
4954 int eindex = usymtab_getIndex (s, k);
4956 if (eindex != NOT_FOUND)
4958 uentry ret = s->entries[eindex];
4962 if (s->kind == US_TBRANCH
4963 || s->kind == US_FBRANCH
4964 || s->kind == US_CBRANCH)
4965 /* uentry_isGlobalVariable (ret) && os->lexlevel > fileScope) */
4968 DPRINTF (("Adding global ref entry: %s", k));
4969 ret = usymtab_addRefEntry (os, k);
4970 DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
4975 DPRINTF (("Found: %s", uentry_unparseFull (ret)));
4979 if (s->kind == US_TBRANCH || s->kind == US_FBRANCH
4980 || s->kind == US_CBRANCH)
4982 /* why isn't this os??? */
4983 uentry ret = usymtab_addRefEntry (s, k);
4984 DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
4991 return uentry_undefined;
4994 static /*@dependent@*/ /*@exposed@*/ uentry
4995 usymtab_lookupQuietAux (usymtab s, cstring k, bool noalt)
4999 while (s != GLOBAL_ENV)
5001 eindex = usymtab_getIndex (s, k);
5003 if (eindex != NOT_FOUND)
5005 uentry ret = s->entries[eindex];
5009 if (noalt && usymtab_isBranch (s))
5011 s = usymtab_dropEnv (s);
5015 llassert (s != NULL); /*@i523 should not need this? */
5020 return uentry_undefined;
5023 static /*@exposed@*/ /*@dependent@*/ uentry
5024 usymtab_lookupQuiet (usymtab s, cstring k)
5026 return usymtab_lookupQuietAux (s, k, FALSE);
5029 static /*@exposed@*/ /*@dependent@*/ uentry
5030 usymtab_lookupQuietNoAlt (usymtab s, cstring k)
5032 return usymtab_lookupQuietAux (s, k, TRUE);
5035 /*@dependent@*/ /*@observer@*/ uentry
5036 usymtab_lookupSafe (cstring k)
5039 DPRINTF (("Lookup safe: %s", k));
5040 return (usymtab_lookupAux (utab, k));
5044 usymtab_lookupExpose (cstring k)
5047 uentry ce = usymtab_lookupAux (utab, k);
5049 if (uentry_isUndefined (ce))
5051 llfatalbug (message ("usymtab_lookup: not found: *%s*", k));
5054 if (uentry_isPriv (ce))
5056 llfatalbug (message ("usymtab_lookup: private: *%s*", k));
5062 uentry usymtab_lookupExposeGlob (cstring k)
5064 return (usymtab_lookupGlobSafe (k));
5067 uentry usymtab_lookupGlob (cstring k)
5068 /*@globals globtab@*/
5070 uentry ce = usymtab_lookupAux (globtab, k);
5072 if (uentry_isUndefined (ce))
5073 llfatalbug (message ("usymtab_lookup: not found: %s", k));
5075 if (uentry_isPriv (ce))
5076 llfatalbug (message ("usymtab_lookup: private: %s", k));
5078 DPRINTF (("Lookup global: %s", uentry_unparseFull (ce)));
5082 /*@observer@*/ uentry
5083 usymtab_lookupGlobSafe (cstring k)
5084 /*@globals globtab@*/
5086 uentry ce = usymtab_lookupAux (globtab, k);
5087 DPRINTF (("Lookup global: %s", uentry_unparseFull (ce)));
5091 uentry usymtab_lookupEither (cstring k)
5094 uentry ce = usymtab_lookupSafe (k);
5096 if (uentry_isUndefined (ce))
5097 llfatalerror (message ("usymtab_lookup: not found: %s", k));
5099 DPRINTF (("Lookup either: %s", uentry_unparseFull (ce)));
5104 usymtab_lookupType (cstring k)
5105 /*@globals globtab@*/
5107 usymId uid = usymtab_getTypeId (k);
5109 if (uid == USYMIDINVALID)
5111 llcontbug (message ("usymtab_lookupType: not found: %s", k));
5112 return ctype_unknown;
5115 return (uentry_getRealType (usymtab_getTypeEntry (uid)));
5119 usymtab_lookupAbstractType (cstring k) /*@globals globtab@*/
5121 usymId uid = usymtab_getTypeId (k);
5123 if (uid == USYMIDINVALID)
5125 llcontbug (message ("usymtab_lookupType: not found: %s", k));
5126 return ctype_unknown;
5129 return (uentry_getAbstractType (usymtab_getTypeEntry (uid)));
5133 ** if there is an unnamed lcl-specified struct tag matching
5134 ** the uentryList, return its datatype. Otherwise, returns
5139 usymtab_structFieldsType (uentryList f)
5140 /*@globals globtab@*/
5142 return (usymtab_suFieldsType (f, TRUE));
5146 usymtab_unionFieldsType (uentryList f)
5147 /*@globals globtab@*/
5149 return (usymtab_suFieldsType (f, FALSE));
5153 usymtab_suFieldsType (uentryList f, bool isStruct)
5154 /*@globals globtab@*/
5158 DPRINTF (("Fields: %s", uentryList_unparse (f)));
5160 if (fileloc_isSpec (g_currentloc))
5162 return (ctype_undefined);
5165 for (i = 0; i < globtab->nentries; i++)
5167 uentry current = globtab->entries[i];
5170 ? uentry_isStructTag (current) : uentry_isUnionTag (current)))
5172 if (isFakeTag (uentry_rawName (current)))
5174 ctype ct = uentry_getType (current);
5176 DPRINTF (("Check: %s", ctype_unparse (ct)));
5178 if ((isStruct ? ctype_isStruct (ct) : ctype_isUnion (ct))
5180 (uentry_isSpecified (current)
5181 && uentryList_equivFields (f, ctype_getFields (ct))))
5183 return uentry_getAbstractType (current);
5193 return ctype_undefined;
5197 usymtab_enumEnumNameListType (enumNameList f)
5198 /*@globals globtab@*/
5202 for (i = 0; i < globtab->nentries; i++)
5204 uentry current = globtab->entries[i];
5206 if (uentry_isEnumTag (current))
5208 if (isFakeTag (uentry_rawName (current)))
5210 ctype ct = uentry_getType (current);
5212 if (ctype_isEnum (ct) && (enumNameList_match (f, ctype_elist (ct))))
5214 return uentry_getType (current);
5220 return ctype_undefined;
5224 usymtab_exists (cstring k)
5227 uentry ce = usymtab_lookupSafe (k);
5228 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5232 usymtab_existsReal (cstring k)
5235 uentry ce = usymtab_lookupSafe (k);
5237 return (!(uentry_isUndefined (ce))
5238 && !(uentry_isPriv (ce))
5239 && !(uentry_isExpandedMacro (ce)));
5243 usymtab_existsGlob (cstring k)
5244 /*@globals globtab@*/
5246 uentry ce = usymtab_lookupAux (globtab, k);
5248 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5252 usymtab_existsEither (cstring k)
5255 uentry ce = usymtab_lookupAux (utab, k);
5257 return (uentry_isValid (ce));
5261 usymtab_existsGlobEither (cstring k)
5262 /*@globals globtab@*/
5264 uentry ce = usymtab_lookupAux (globtab, k);
5266 return (uentry_isValid (ce));
5270 usymtab_existsType (cstring k)
5271 /*@globals globtab@*/
5273 uentry ce = usymtab_lookupAux (globtab, k);
5275 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && uentry_isDatatype (ce));
5279 usymtab_existsTypeEither (cstring k)
5280 /*@globals globtab@*/
5283 ce = usymtab_lookupAux (globtab, k);
5284 return (uentry_isValid (ce) && uentry_isDatatype (ce));
5288 usymtab_existsStructTag (cstring k) /*@globals globtab@*/
5290 cstring sname = makeStruct (k);
5291 uentry ce = usymtab_lookupAux (globtab, sname);
5292 cstring_free (sname);
5293 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5297 usymtab_existsUnionTag (cstring k) /*@globals globtab@*/
5299 cstring uname = makeUnion (k);
5300 uentry ce = usymtab_lookupAux (globtab, uname);
5302 cstring_free (uname);
5304 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5308 usymtab_existsEnumTag (cstring k) /*@globals globtab@*/
5310 cstring ename = makeEnum (k);
5311 uentry ce = usymtab_lookupAux (globtab, ename);
5313 cstring_free (ename);
5314 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5317 bool usymtab_existsVar (cstring k)
5320 uentry ce = usymtab_lookupSafe (k);
5322 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && (uentry_isVar (ce)));
5330 refTable_free (/*@only@*/ /*@null@*/ refTable x, int nentries)
5336 for (i = 0; i < nentries; i++)
5346 usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab u)
5347 /*@globals globtab, utab, filetab@*/
5351 DPRINTF (("Free level [%p]", u));
5352 aliasTable_free (u->aliases);
5354 refTable_free (u->reftable, u->nentries);
5356 if (u == filetab || u == globtab)
5358 for (i = 0; i < u->nentries; i++)
5360 DPRINTF (("Free complete: %d", i));
5361 DPRINTF (("Uentry: %s", uentry_unparse (u->entries[i])));
5362 uentry_freeComplete (u->entries[i]);
5363 u->entries[i] = uentry_undefined;
5368 for (i = 0; i < u->nentries; i++)
5370 uentry_free (u->entries[i]);
5371 u->entries[i] = uentry_undefined;
5375 guardSet_free (u->guards);
5382 llassert (!cstringTable_isDefined (u->htable));
5385 sfree (u); /* evans 2002-07-12: was inside if */
5390 usymtab_freeAux (/*@only@*/ usymtab u)
5391 /*@globals globtab, utab, filetab@*/
5394 while (u != GLOBAL_ENV)
5397 usymtab_freeLevel (u);
5404 void usymtab_free ()
5405 /*@globals killed utab, globtab, filetab@*/
5409 usymtab_freeAux (utab);
5410 utab = usymtab_undefined;
5413 static int usymtab_lexicalLevel (void) /*@globals utab@*/
5415 return (utab->lexlevel);
5418 bool usymtab_inGlobalScope () /*@globals utab, globtab@*/
5420 return (utab == globtab);
5423 bool usymtab_inFileScope () /*@globals utab@*/
5425 return (utab->lexlevel == fileScope);
5428 bool usymtab_inFunctionScope () /*@globals utab@*/
5430 return (utab->lexlevel == functionScope);
5434 usymtab_replaceEntry (uentry s)
5435 /*@globals utab, globtab@*/
5436 /*@modifies utab, s@*/
5438 usymtab_replaceEntryAux (utab, s);
5442 usymtab_matchForwardStruct (usymId u1, usymId u2)
5443 /*@globals globtab@*/
5445 uentry ue1 = usymtab_getTypeEntry (u1);
5446 uentry ue2 = usymtab_getTypeEntry (u2);
5448 if (uentry_isAnyTag (ue2))
5450 ctype reptype = uentry_getType (ue1);
5452 if (ctype_isPointer (reptype))
5454 ctype repbase = ctype_getBaseType (reptype);
5456 if (ctype_isUA (repbase))
5458 typeId rtuid = ctype_typeId (repbase);
5460 if (u2 == rtuid) return TRUE;
5462 if (usymId_isValid (rtuid))
5464 reptype = uentry_getType (usymtab_getTypeEntry (rtuid));
5466 return (ctype_isUA (reptype) && (u2 == (ctype_typeId (reptype))));
5475 void usymtab_addGuards (guardSet guards)
5478 utab->guards = guardSet_union (utab->guards, guards);
5481 static bool usymtab_isGuardedAux (sRef s)
5485 sRef base = sRef_getRootBase (s);
5486 int lowlevel = paramsScope;
5487 int baselevel = sRef_lexLevel (base);
5489 if (sRef_isCvar (base))
5491 lowlevel = baselevel;
5492 if (lowlevel < paramsScope) lowlevel = paramsScope;
5495 while (tab->lexlevel >= lowlevel)
5497 DPRINTF (("Is guarded? [%s] %s",
5498 guardSet_unparse (tab->guards),
5499 sRef_unparseFull (s)));
5501 if (guardSet_isGuarded (tab->guards, s))
5504 if (!sRef_definitelyNull (s))
5506 sRef_setNotNull (s, fileloc_undefined);
5512 tab = usymtab_dropEnv (tab);
5518 void usymtab_unguard (sRef s) /*@modifies utab@*/
5521 sRef base = sRef_getRootBase (s);
5522 int lowlevel = paramsScope;
5523 int baselevel = sRef_lexLevel (base);
5525 if (sRef_isCvar (base))
5527 lowlevel = baselevel;
5528 if (lowlevel < paramsScope) lowlevel = paramsScope;
5531 while (tab->lexlevel >= lowlevel)
5533 if (guardSet_isGuarded (tab->guards, s))
5535 guardSet_delete (tab->guards, s);
5538 tab = usymtab_dropEnv (tab);
5542 bool usymtab_isGuarded (sRef s)
5544 DPRINTF (("Is guarded? %s", sRef_unparseFull (s)));
5545 return (sRef_aliasCompleteSimplePred (usymtab_isGuardedAux, s));
5548 bool usymtab_isDefinitelyNull (sRef s)
5550 return (sRef_aliasCheckSimplePred (usymtab_isDefinitelyNullAux, s));
5553 bool usymtab_isDefinitelyNullDeep (sRef s)
5555 return (sRef_deepPred (usymtab_isDefinitelyNull, s));
5558 static bool usymtab_isDefinitelyNullAux (sRef s)
5562 sRef base = sRef_getRootBase (s);
5563 int lowlevel = paramsScope;
5565 if (sRef_isCvar (base))
5567 lowlevel = sRef_lexLevel (base);
5568 if (lowlevel < paramsScope) lowlevel = paramsScope;
5571 while (tab->lexlevel >= lowlevel)
5573 if (guardSet_mustBeNull (tab->guards, s))
5578 while (tab->kind == US_CBRANCH)
5583 llassert (usymtab_isDefined (tab));
5585 if (tab->kind == US_FBRANCH)
5588 llassert (tab->kind == US_TBRANCH);
5598 usymtab_printGuards ()
5599 /*@globals utab, globtab@*/
5601 usymtab ttab = utab;
5603 while (ttab != globtab)
5605 llmsg (message ("Guards [%d]: %q", ttab->lexlevel,
5606 guardSet_unparse (ttab->guards)));
5612 usymtab_displayAllUses ()
5613 /*@globals utab, globtab@*/
5617 /* only in top scope */
5618 llassert (utab == globtab);
5620 /* need a copy, so order is not messed up by sort! */
5621 copy = usymtab_shallowCopy (globtab);
5623 qsort (copy->entries, (size_t)copy->nentries,
5624 sizeof (*copy->entries), (int (*)(const void *, const void *)) uentry_xcompareuses);
5626 usymtab_entries (copy, ue)
5628 if (uentry_isValid (ue) && !uentry_isGlobalMarker (ue))
5630 filelocList uses = uentry_getUses (ue);
5631 int size = filelocList_realSize (uses);
5633 if (fileloc_isDefined (uentry_whereDefined (ue))
5634 && !fileloc_isLib (uentry_whereDefined (ue))
5637 llmsg (message ("%q (%q), %d use%&:\n %q",
5638 uentry_getName (ue),
5639 fileloc_unparse (uentry_whereDefined (ue)),
5640 size, filelocList_unparseUses (uses)));
5643 } end_usymtab_entries;
5645 usymtab_shallowFree (copy);
5648 static /*@dependent@*/ /*@exposed@*/ usymtab
5649 usymtab_getFileTab ()
5650 /*@globals filetab@*/
5652 llassert (filetab != NULL);
5658 usymtab_unparseStack ()
5661 return (usymtab_unparseStackTab (utab));
5664 static /*@only@*/ cstring
5665 usymtab_unparseStackTab (usymtab t)
5667 bool firstOne = TRUE;
5668 cstring ret = cstring_makeLiteral ("[");
5670 while (t != GLOBAL_ENV)
5674 ret = message ("%q %q", ret, usymtab_typeName (t));
5679 ret = message ("%q, %q", ret, usymtab_typeName (t));
5684 ret = message ("%q ]", ret);
5688 static /*@only@*/ cstring
5689 usymtab_typeName (/*@notnull@*/ usymtab t)
5693 case US_GLOBAL: return cstring_makeLiteral ("global");
5694 case US_NORMAL: return cstring_makeLiteral ("normal");
5695 case US_TBRANCH: return cstring_makeLiteral ("true");
5696 case US_FBRANCH: return cstring_makeLiteral ("false");
5697 case US_CBRANCH: return cstring_makeLiteral ("case");
5698 case US_SWITCH: return cstring_makeLiteral ("switch");
5704 void usymtab_addMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5707 if (!sRef_similar (s, al))
5709 usymtab_addForceMustAlias (s, al);
5714 ** Same as usymtab_addMustAlias, except does not check sRef_isSimilar.
5717 void usymtab_addForceMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5720 /* evans 2002-03-3: was sRef_isMeaningful -- but we need to keep aliases for new storage also! */
5721 if (sRef_isMeaningful (s)
5722 && sRef_isMeaningful (al)
5723 && !(sRef_isConst (s) || sRef_isConst (al))
5724 && !(sRef_isAddress (al) && sRef_isDirectParam (sRef_getBase (al))))
5726 utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
5727 DPRINTF (("Must alias: %s", aliasTable_unparse (utab->aliases)));
5730 ** for local variable, aliasing is symmetric
5733 if (sRef_isLocalVar (s) && sRef_isLocalVar (al))
5735 utab->aliases = aliasTable_addMustAlias (utab->aliases, al, s);
5740 DPRINTF (("Not aliasing! %s / %s", sRef_unparseFull (s), sRef_unparseFull (al)));
5741 DPRINTF (("meaningful: %d %d", sRef_isMeaningful (s), sRef_isMeaningful (al)));
5745 void usymtab_addReallyForceMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5748 utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
5751 void usymtab_clearAlias (sRef s)
5752 /*@modifies utab, s@*/
5755 aliasTable_clearAliases (utab->aliases, s);
5758 sRefSet usymtab_allAliases (sRef s)
5761 if (sRef_isSomewhatMeaningful (s))
5765 ret = sRefSet_unionFree (aliasTable_aliasedBy (utab->aliases, s),
5766 aliasTable_canAlias (utab->aliases, s));
5771 DPRINTF (("NOT A MEANINGFUL SREF!"));
5772 return sRefSet_undefined;
5776 /*@only@*/ sRefSet usymtab_canAlias (sRef s)
5779 if (sRef_isSomewhatMeaningful (s))
5781 sRefSet res = aliasTable_canAlias (utab->aliases, s);
5785 return sRefSet_undefined;
5788 /*@only@*/ sRefSet usymtab_aliasedBy (sRef s)
5791 return (aliasTable_aliasedBy (utab->aliases, s));
5794 /*@only@*/ cstring usymtab_unparseAliases ()
5797 return (aliasTable_unparse (utab->aliases));
5801 ** Debugging routines:
5802 ** okay to leak storage here, only for debugging
5808 usymtab_printOut (void)
5814 char *ind = mstring_copy (" ");
5816 fprintf (g_warningstream, "<<< [symbol table] >>>\n");
5818 while (s != GLOBAL_ENV && s->env != GLOBAL_ENV)
5820 cstring tname = usymtab_typeName (s);
5824 ind[depth * 3 + 1] = '\0';
5827 fprintf (g_warningstream, "level: %d (%s)\n", s->lexlevel,
5828 cstring_toCharsSafe (tname));
5830 cstring_free (tname);
5832 for (i = 0; i < s->nentries; i++)
5834 cstring us = uentry_unparseFull (s->entries[i]);
5835 fprintf (g_warningstream, "%s\n", cstring_toCharsSafe (us));
5839 if (s->reftable != NULL && s->nentries > 0)
5841 fprintf (g_warningstream, "\t<< Ref table >>\n");
5843 for (i = 0; i < s->nentries; i++)
5845 fprintf (g_warningstream, "\t%s %3d: %d, %d\n", ind, i,
5846 s->reftable[i]->level,
5847 s->reftable[i]->index);
5851 ind[depth * 3 + 1] = ' ';
5855 fprintf (g_warningstream, "<<< end usymtab >>>\n");
5861 usymtab_printTypes ()
5862 /*@globals globtab@*/
5864 usymtab_printAllAux (globtab);
5868 usymtab_printAll (void)
5871 usymtab_printAllAux (utab);
5875 usymtab_printAllAux (usymtab s)
5876 /*@modifies g_warningstream@*/
5880 char *ind = mstring_copy (" ");
5882 printf ("[[[ usymtab ]]]");
5884 while (s != GLOBAL_ENV)
5887 ind[depth * 3 + 1] = '\0';
5889 if (s->env == GLOBAL_ENV)
5893 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5894 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5895 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5899 for (i = looplow; i < s->nentries; i++)
5901 printf ("%s%3d. %s\n", ind, i,
5902 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5907 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5908 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5909 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5911 for (i = 0; i < s->nentries; i++)
5913 printf ("%s%3d %s\n", ind, i,
5914 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5918 ind[depth * 3 + 1] = ' ';
5922 printf ("----------\n");
5926 usymtab_printComplete ()
5931 char *ind = mstring_copy (" ");
5934 while (s != GLOBAL_ENV)
5938 ind[depth * 3 + 1] = '\0';
5941 if (s->env == GLOBAL_ENV)
5945 printf ("level: %d\n", s->lexlevel);
5949 for (i = looplow; i < s->nentries; i++)
5951 printf ("%s%3d %s\n", ind, i,
5952 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5957 printf ("level: %d\n", s->lexlevel);
5958 for (i = 0; i < s->nentries; i++)
5960 printf ("%s%3d %s\n", ind, i,
5961 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5965 ind[depth * 3 + 1] = ' ';
5970 printf ("----------\n");
5975 static /*@only@*/ cstring /*@unused@*/
5976 usymtab_unparseLocalAux (/*@notnull@*/ usymtab s)
5978 cstring c = message ("lexlevel: %d\n", s->lexlevel);
5981 for (i = 0; i < s->nentries; i++)
5983 c = message ("%q\n%q", c, uentry_unparseFull (s->entries[i]));
5986 c = message ("%q\n=========", c);
5990 static cstring /*@unused@*/ /*@only@*/
5991 usymtab_unparseLocalList (/*@notnull@*/ usymtab s)
5993 cstring c = message ("[%d/%s/%s] ", s->lexlevel,
5994 bool_unparse (s->mustBreak),
5995 exitkind_unparse (s->exitCode));
5998 for (i = 0; i < s->nentries; i++)
6000 sRef sr = uentry_getSref (s->entries[i]);
6004 c = message ("%q: %q [%b]", c, uentry_getName (s->entries[i]),
6005 sRef_isStateDefined (sr));
6009 c = message ("%q, %q [%b]", c, uentry_getName (s->entries[i]),
6010 sRef_isStateDefined (sr));
6020 usymtab_printLocal (void)
6026 printf ("lexlevel: %d\n", s->lexlevel);
6028 for (i = 0; i < s->nentries; i++)
6030 printf ("%s\n", cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
6033 while (s->lexlevel > 1)
6038 llassert (usymtab_isDefined (s));
6040 printf ("Params:\n");
6042 for (i = 0; i < s->nentries; i++)
6044 printf ("%d: %s\n", i,
6045 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
6050 static bool checkDistinctExternalName (uentry e)
6051 /*@globals globtab@*/
6052 /*@modifies *g_warningstream@*/
6054 size_t checklen = size_fromInt (context_getValue (FLG_EXTERNALNAMELEN));
6055 bool ignorecase = context_getFlag (FLG_EXTERNALNAMECASEINSENSITIVE);
6056 bool gotone = FALSE;
6057 bool extras = FALSE;
6058 bool hasError = FALSE;
6059 cstring name = uentry_rawName (e);
6060 usymtab st = globtab;
6068 if (uentry_isAnyTag (e))
6070 checklen++; /* the tag marker doesn't count */
6074 usymtab_entries (st, oe)
6076 if (uentry_sameObject (oe, e))
6083 if (cstring_equalCaseInsensitive (uentry_rawName (oe), name))
6092 (FLG_DISTINCTEXTERNALNAMES,
6094 ("External identifier %q is not distinguishable from %q "
6095 "because alphabetical case is ignored",
6097 uentry_getName (oe)),
6098 uentry_whereLast (e)))
6100 uentry_showWhereAny (oe);
6101 uentry_setHasNameError (oe);
6110 if (cstring_equalLenCaseInsensitive (uentry_rawName (oe),
6119 if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6122 (FLG_DISTINCTEXTERNALNAMES,
6125 ("External identifier %q is not distinguishable from %q "
6126 "in the first %d characters (%q)",
6128 uentry_getName (oe),
6129 size_toInt (checklen),
6130 cstring_clip (uentry_getName (e), checklen)),
6132 uentry_whereLast (e)))
6134 uentry_showWhereAny (oe);
6135 uentry_setHasNameError (oe);
6148 (FLG_DISTINCTEXTERNALNAMES,
6150 ("External identifier %q is not distinguishable from %q "
6151 "in the first %d characters because alphabetical case "
6154 uentry_getName (oe),
6155 size_toInt (checklen)),
6156 uentry_whereLast (e)))
6158 uentry_showWhereAny (oe);
6159 uentry_setHasNameError (oe);
6165 else if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6174 (FLG_DISTINCTEXTERNALNAMES,
6177 ("External identifier %q is not distinguishable from %q "
6178 "in the first %d characters (%q)",
6180 uentry_getName (oe),
6181 size_toInt (checklen),
6182 cstring_clip (uentry_getName (e), checklen)),
6184 uentry_whereLast (e)))
6186 uentry_showWhereAny (oe);
6187 uentry_setHasNameError (oe);
6196 } end_usymtab_entries ;
6203 (cstring_makeLiteral ("One or more additional "
6204 "indistinguishable external "
6205 "names not reported"));
6211 static bool checkDistinctInternalName (uentry e)
6213 /*@modifies *g_warningstream@*/
6215 usymtab ttab = utab;
6216 cstring name = uentry_rawName (e);
6217 size_t numchars = size_fromInt (context_getValue (FLG_INTERNALNAMELEN));
6218 bool caseinsensitive = context_getFlag (FLG_INTERNALNAMECASEINSENSITIVE);
6219 bool lookalike = context_getFlag (FLG_INTERNALNAMELOOKALIKE);
6221 if (uentry_isAnyTag (e) && (numchars != 0))
6223 numchars++; /* the tag marker doesn't count */
6226 while (usymtab_isDefined (ttab))
6228 usymtab_entries (ttab, oe)
6230 if (uentry_sameObject (oe, e))
6232 /*@innercontinue@*/ continue;
6235 switch (cstring_genericEqual
6236 (name, uentry_rawName (oe),
6237 numchars, caseinsensitive, lookalike))
6239 case CGE_DISTINCT: /* okay */
6243 if (cstring_equal (name, uentry_rawName (oe)))
6245 ; /* got a shadow error */
6250 (FLG_DISTINCTINTERNALNAMES,
6253 ("Internal identifier %q is not distinguishable from %q "
6254 "in the first %d characters (%q)",
6256 uentry_getName (oe),
6257 size_toInt (numchars),
6258 cstring_clip (uentry_getName (e), numchars)),
6260 uentry_whereLast (e)))
6262 uentry_showWhereAny (oe);
6263 uentry_setHasNameError (oe);
6270 if (numchars == 0 || (cstring_length (name) <= numchars))
6273 (FLG_DISTINCTINTERNALNAMES,
6275 ("Internal identifier %q is not distinguishable from %q "
6276 "without case sensitivity",
6278 uentry_getName (oe)),
6279 uentry_whereLast (e)))
6281 uentry_showWhereAny (oe);
6282 uentry_setHasNameError (oe);
6289 (FLG_DISTINCTINTERNALNAMES,
6291 ("Internal identifier %q is not distinguishable from %q "
6292 "in the first %d characters without case sensitivity",
6294 uentry_getName (oe),
6295 size_toInt (numchars)),
6296 uentry_whereLast (e)))
6298 uentry_showWhereAny (oe);
6299 uentry_setHasNameError (oe);
6307 || (cstring_length (name) <= numchars))
6310 (FLG_DISTINCTINTERNALNAMES,
6312 ("Internal identifier %q is not distinguishable from %q "
6313 "except by lookalike characters",
6315 uentry_getName (oe)),
6316 uentry_whereLast (e)))
6318 uentry_showWhereAny (oe);
6319 uentry_setHasNameError (oe);
6326 (FLG_DISTINCTINTERNALNAMES,
6328 ("Internal identifier %q is not distinguishable from %q "
6329 "in the first %d characters except by lookalike characters",
6331 uentry_getName (oe),
6332 size_toInt (numchars)),
6333 uentry_whereLast (e)))
6335 uentry_showWhereAny (oe);
6336 uentry_setHasNameError (oe);
6341 } end_usymtab_entries ;
6349 void usymtab_checkDistinctName (uentry e, int scope)
6350 /*@globals utab, globtab@*/
6352 bool hasError = FALSE;
6353 fileloc where = uentry_whereLast (e);
6355 if (!fileloc_isPreproc (where) && !fileloc_isBuiltin (where))
6357 if (scope == globScope)
6359 if (context_getFlag (FLG_DISTINCTEXTERNALNAMES))
6361 hasError = checkDistinctExternalName (e);
6365 if (!hasError && context_getFlag (FLG_DISTINCTINTERNALNAMES))
6367 hasError = checkDistinctInternalName (e);
6373 uentry_setHasNameError (e);
6377 /*@exposed@*/ sRef usymtab_lookupGlobalMarker (void) /*@globals utab@*/
6381 ue = usymtab_lookupAux (utab, GLOBAL_MARKER_NAME);
6382 llassert (uentry_isValid (ue));
6384 return uentry_getSref (ue);
6390 ** For debugging only
6394 usymtab_checkAllValid () /*@globals utab@*/
6398 while (tab != GLOBAL_ENV)
6402 for (i = 0; i < utab->nentries; i++)
6404 uentry e = utab->entries[i];
6406 uentry_checkValid (e);
6409 aliasTable_checkValid (tab->aliases);