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;
357 usymtab_initGlobalMarker () /*@globals globtab@*/
359 if (uentry_isValid (usymtab_lookupAux (globtab, GLOBAL_MARKER_NAME)))
361 ; /* Already entered from load table. */
365 usymtab_addGlobalEntry (uentry_makeGlobalMarker ());
370 ** utab should be empty? (requires?)
372 ** Adds bool types to symbol table (these are built in for now)
373 ** Only do this is there is no library!
379 DPRINTF (("Init bool!"));
381 if (context_getFlag (FLG_NOLIB))
383 ctype boolt = ctype_bool;
384 /* evs 2000-07-24: bool is now treated as abstract (always) */
386 uentry boolentry = uentry_makeBoolDatatype (YES);
387 usymtab_supGlobalEntry (boolentry);
388 context_addBoolAccess ();
391 ** We supply values 0 and 1 for the constants, so things like
392 ** while (TRUE) can be interpreted correctly.
395 usymtab_supGlobalEntry
396 (uentry_makeConstantValue (context_getFalseName (), boolt,
397 fileloc_getBuiltin (), FALSE,
398 multiVal_makeInt (0)));
400 usymtab_supGlobalEntry
401 (uentry_makeConstantValue (context_getTrueName (), boolt,
402 fileloc_getBuiltin (), FALSE,
403 multiVal_makeInt (1)));
412 usymtab_grow (/*@notnull@*/ usymtab s)
415 o_uentry *oldsyms = s->entries;
417 s->nspace = CBASESIZE;
418 s->entries = (uentry *) dmalloc (sizeof (*s->entries)
419 * (s->nentries + s->nspace));
421 for (i = 0; i < s->nentries; i++)
423 s->entries[i] = oldsyms[i];
428 if (s->reftable != NULL)
430 refTable oldRefs = s->reftable;
432 s->reftable = (refentry *) dmalloc (sizeof (*s->reftable)
433 * (s->nentries + CBASESIZE + 1));
435 for (i = 0; i < s->nentries; i++)
437 s->reftable[i] = oldRefs[i];
448 usymtab_addEntryQuiet (/*@notnull@*/ usymtab s, /*@keep@*/ uentry e)
450 if (!(s->lexlevel > fileScope || !sRef_modInFunction ()))
452 if (uentry_isDatatype (e)
453 || uentry_isFunction (e)
454 || uentry_isAnyTag (e)
455 || uentry_isEnumConstant (e)
456 || context_inMacro ())
459 ** Not a bug. Code like,
460 ** int f (void) { typedef int tint; ... }
464 /* was nothing here! */
465 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
470 (cstring_makeLiteral ("Declaration outside function scope"));
472 llcontbug (message ("usymtab_addEntryQuiet: inconsistent state "
473 "(lexlevel = %d, modFunction = %s) adding: %q",
474 s->lexlevel, bool_unparse (sRef_modInFunction ()),
475 uentry_unparse (e)));
476 sRef_setGlobalScope ();
477 /* make sure the sRef is not bashed! */
478 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
488 s->entries[s->nentries] = e;
491 if (s == globtab || s == filetab)
493 if (!fileloc_isLib (g_currentloc))
495 uentry_tallyAnnots (e, AN_UNKNOWN);
500 if (cstringTable_isDefined (s->htable))
502 cstringTable_insert (s->htable, cstring_copy (uentry_rawName (e)), s->nentries);
508 static /*@observer@*/ uentry /*@alt void@*/
509 usymtab_addEntryBase (/*@notnull@*/ usymtab s, /*@only@*/ uentry e)
512 ** In theory, we shouldn't need this test because it this is
513 ** only called when a library is being read, and it shouldn't
514 ** ever have a duplicate entry. In practice, its safer to
515 ** leave it in, though.
520 if (uentry_isValid (old = usymtab_lookupQuiet (s, uentry_rawName (e))))
522 DPRINTF (("Duplicate entry: %s", uentry_unparse (e)));
523 uentry_free (e); /* duplicate */
528 int thisentry = s->nentries;
530 if (uentry_isVar (e))
532 uentry_setSref (e, sRef_makeCvar (globScope, thisentry,
534 stateInfo_makeLoc (uentry_whereLast (e))));
537 usymtab_addEntryQuiet (s, e);
543 static /*@observer@*/ uentry /*@alt void@*/
544 usymtab_addEntryAlways (/*@notnull@*/ usymtab s, /*@only@*/ uentry e)
547 ** In theory, we shouldn't need this test because it this is
548 ** only called when a library is being read, and it shouldn't
549 ** ever have a duplicate entry. In practice, its safer to
550 ** leave it in, though.
554 int thisentry = s->nentries;
556 if (uentry_isValid (old = usymtab_lookupQuiet (s, uentry_rawName (e))))
559 (message ("Duplicate entry in load library: %s. "
560 "Old entry: %q. New entry: %q",
562 uentry_unparseFull (old),
563 uentry_unparseFull (e)));
565 uentry_setName (e, message ("__x_%s", uentry_rawName (e)));
566 /* This shouldn't happen...unless the library is bad! */
570 if (uentry_isVar (e) && !uentry_isGlobalMarker (e))
572 uentry_setSref (e, sRef_makeCvar (globScope, thisentry,
574 stateInfo_makeLoc (uentry_whereLast (e))));
577 usymtab_addEntryQuiet (s, e);
582 usymtab_addEntryAux (/*@notnull@*/ usymtab st, /*@keep@*/ uentry e, bool isSref)
583 /*@globals globtab@*/
586 usymId thisentry = st->nentries;
588 llassert (!uentry_isElipsisMarker (e));
592 ** llassert (usymtab_lookupSafe (uentry_rawName (e)) == uentry_undefined);
595 llassertprint (uentry_isAnyTag (e) ? st == globtab : TRUE,
596 ("non-global tag: %s / %d", uentry_unparseFull (e), st->lexlevel));
598 if (st->lexlevel == fileScope
599 && (!(uentry_isStatic (e)) || uentry_isAnyTag (e)))
606 ctype ct = uentry_getType (e);
608 if (uentry_isFunction (e) && ctype_isFunction (ct))
610 ct = ctype_getReturnType (ct);
613 if (uentry_isStatic (e))
615 sRef sr = sRef_makeCvar (st->lexlevel, thisentry, ct, stateInfo_makeLoc (uentry_whereLast (e)));
617 if (sRef_isStack (sr) || sRef_isLocalState (sr))
619 sRef_setAliasKind (sr, AK_STATIC, uentry_whereLast (e));
620 sRef_setDefined (sr, uentry_whereLast (e));
623 uentry_setSref (e, sr);
627 uentry_setSref (e, sRef_makeCvar (st->lexlevel, thisentry, ct, stateInfo_makeLoc (uentry_whereLast (e))));
631 if (uentry_isDatatype (e))
634 uentry_setDatatype (e, thisentry);
637 if (uentry_isFunction (e))
639 ctype ct = uentry_getType (e);
641 if (ctype_isFunction (ct)
642 && uentryList_isMissingParams (ctype_argsFunction (ct)))
644 if (uentry_isDeclared (e))
648 message ("Function %q declared without parameter list",
650 uentry_whereDeclared (e));
656 message ("Function %q specified without parameter list",
658 uentry_whereSpecified (e));
663 if (st == globtab && !uentry_isSpecified (e))
665 exprChecks_checkExport (e);
668 uentry_checkName (e);
670 usymtab_addEntryQuiet (st, e);
671 DPRINTF (("Adding entry: [%p] %s", e, uentry_unparseFull (e)));
676 usymtab_addEntry (uentry e)
677 /*@globals utab, globtab@*/
678 /*@modifies utab, e@*/
680 llassertprint (!usymtab_exists (uentry_rawName (e)),
681 ("Entry already exists: %s", uentry_unparse (e)));
683 return usymtab_addEntryAux (utab, e, FALSE);
687 usymtab_addGlobalEntry (uentry e)
688 /*@modifies globtab, e@*/
690 DPRINTF (("Add global: %s / %s", uentry_unparse (e), bool_unparse (uentry_isForward (e))));
692 (void) usymtab_addEntryAux (globtab, e, FALSE);
696 ** supercede and replace entry use elements of entries array, and
697 ** assign an element to a new value, and then free the old value.
698 ** Need -deparrays to avoid errors for this.
704 usymtab_supEntryAux (/*@notnull@*/ usymtab st,
705 /*@only@*/ uentry e, bool isSref)
706 /*@globals globtab, filetab@*/
707 /*@modifies st, globtab, e@*/
709 cstring ename = uentry_rawName (e);
710 bool staticEntry = FALSE;
713 DPRINTF (("Sup entry aux: %s", uentry_unparseFull (e)));
715 /* static tags in global scope */
716 if (st->lexlevel == fileScope
717 && (!(uentry_isStatic (e)) || uentry_isAnyTag (e)))
719 eindex = usymtab_getIndex (st, ename);
721 if (eindex != NOT_FOUND)
723 uentry ce = st->entries[eindex];
727 message ("%s %q shadows static declaration",
728 ekind_capName (uentry_getKind (e)),
730 uentry_whereDeclared (e)))
732 uentry_showWhereLast (ce);
735 if (eindex == st->nentries - 1)
741 st->entries[eindex] = st->entries[st->nentries - 1];
744 if (cstringTable_isDefined (st->htable))
746 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
747 cstring_copy (uentry_rawName (e)));
757 if (uentry_isStatic (e)) {
758 if (uentry_isFunction (e)) {
760 ** Static function declarations are at the file level,
761 ** even if they are in a deeper scope.
764 st = usymtab_getFileTab ();
767 if (!uentry_isAnyTag (e) && st == globtab)
769 st = usymtab_getFileTab ();
771 DPRINTF (("Static entry!"));
776 eindex = usymtab_getIndex (st, ename);
778 if (eindex != NOT_FOUND)
780 uentry ce = st->entries[eindex];
782 DPRINTF (("Found entry: %s", uentry_unparse (ce)));
784 if (uentry_isPriv (ce)
785 /* || (fileloc_isImport (uentry_whereSpecified (ce))) */
786 || (uentry_isStatic (ce)
787 && uentry_isAnyTag (ce)
788 && (uentry_isDeclared (ce)
789 && !fileloc_sameFile (uentry_whereDefined (ce),
790 uentry_whereDefined (e)))))
794 ** if overloading import should do some checks!
797 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
799 DPRINTF (("Overloading!"));
801 st->entries[eindex] = e;
803 if (uentry_isDatatype (e))
805 uentry_setDatatype (e, eindex);
808 if (st == globtab && !uentry_isSpecified (e))
810 exprChecks_checkExport (e);
813 if (cstringTable_isDefined (st->htable))
815 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
816 cstring_copy (uentry_rawName (e)));
822 else if (uentry_isSpecified (ce))
824 if (uentry_isSpecified (e))
826 DPRINTF (("Here we are: %s", uentry_unparseFull (e)));
828 if (fileloc_isImport (uentry_whereSpecified (ce)))
830 if (cstringTable_isDefined (st->htable))
832 cstringTable_replaceKey (st->htable,
834 cstring_copy (uentry_rawName (e)));
838 st->entries[eindex] = e;
841 if (uentry_isDatatype (e)) uentry_setDatatype (e, eindex);
845 if (fileloc_isImport (uentry_whereSpecified (e)))
851 /* Respecification errors already reported */
852 DPRINTF (("Respecification: %s / %s",
853 fileloc_unparse (uentry_whereSpecified (e)),
854 bool_unparse (fileloc_isSpec (uentry_whereSpecified (e)))));
856 if (uentry_isDatatype (e))
858 uentry_setDatatype (e, eindex);
861 if (cstringTable_isDefined (st->htable))
863 cstringTable_replaceKey (st->htable,
865 cstring_copy (uentry_rawName (e)));
868 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
870 st->entries[eindex] = e;
875 else /* e not specified */
877 DPRINTF (("Merging..."));
879 if (uentry_isDeclared (ce))
882 No - this can happen for internal typedefs
883 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
886 DPRINTF (("Merge defn"));
887 uentry_mergeDefinition (ce, e);
892 No - this can happen for internal typedefs
893 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
896 DPRINTF (("Merge entries..."));
897 uentry_mergeEntries (ce, e);
898 DPRINTF (("After: %s", uentry_unparseFull (ce)));
902 else /* ce not specified */
904 if (!(st->lexlevel > fileScope || !sRef_modInFunction ()))
906 if (uentry_isDatatype (e) || uentry_isAnyTag (e)
907 || uentry_isEnumConstant (e)
908 || uentry_isStatic (e)) /* bug fix from Brian St. Pierre */
911 ** Not a bug. Code like,
912 ** int f (void) { typedef int tint; ... }
918 llcontbug (message ("usymtab_supEntryAux: inconsistent state "
919 "(lexlevel = %d, modFunction = %s) adding: %q",
920 st->lexlevel, bool_unparse (sRef_modInFunction ()),
921 uentry_unparse (e)));
923 if (sRef_modInFunction ())
925 /* make sure the sRef is not bashed! */
926 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
931 DPRINTF (("Merge.."));
932 uentry_mergeDefinition (ce, e);
937 ctype ct = uentry_getType (ce);
939 if (uentry_isFunction (ce) && ctype_isFunction (ct))
941 ct = ctype_getReturnType (ct);
944 uentry_setSref (ce, sRef_makeCvar (st->lexlevel, eindex, ct, stateInfo_makeLoc (uentry_whereLast (ce))));
947 else /* no previous entry */
951 if (st->lexlevel == globScope
952 && !uentry_isStatic (e)
953 && !uentry_isExtern (e)
954 && usymtab_isDefined (filetab))
957 ** check if there is a static entry: (i.e.,
964 eindex = usymtab_getIndex (filetab, ename);
966 if (eindex != NOT_FOUND)
968 uentry ce = filetab->entries[eindex];
970 uentry_setStatic (e);
971 uentry_mergeDefinition (ce, e);
977 outer = usymtab_lookupQuiet (st->env, ename);
979 DPRINTF (("New : [%p] %s", e, uentry_unparseFull (e)));
980 DPRINTF (("Outer: [%p] %s", outer, uentry_unparseFull (outer)));
983 ** no previous definition, add the new one
987 && uentry_isValid (outer)
988 && !(uentry_isYield (e) || uentry_isYield (outer))
989 && fileloc_isDefined (uentry_whereLast (e))
990 && !fileloc_isXHFile (uentry_whereLast (e))
991 && fileloc_isDefined (uentry_whereLast (outer))
992 && !fileloc_isXHFile (uentry_whereLast (outer)))
994 if (!uentry_sameKind (outer, e))
1000 if (ctype_isUnknown (uentry_getType (outer))
1001 || uentry_isForward (outer))
1009 message ("%s %q shadows outer declaration",
1010 ekind_capName (uentry_getKind (e)),
1011 uentry_getName (e)),
1012 uentry_whereLast (e)))
1014 uentry_showWhereLast (outer);
1020 if (st == globtab && context_getFlag (FLG_NEWDECL))
1024 message ("New declaration: %q", uentry_getName (e)),
1025 uentry_whereLast (e));
1028 eindex = usymtab_addEntryAux (st, e, isSref);
1032 return (staticEntry ? USYMIDINVALID : eindex);
1036 usymtab_replaceEntryAux (/*@notnull@*/ usymtab st, /*@only@*/ uentry e)
1037 /*@globals globtab@*/ /*@modifies st, e@*/
1039 cstring ename = uentry_rawName (e);
1042 /* static tags in global scope */
1043 eindex = usymtab_getIndex (st, ename);
1045 if (eindex != NOT_FOUND)
1047 uentry ce = st->entries[eindex];
1049 if (cstringTable_isDefined (st->htable))
1051 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
1052 cstring_copy (uentry_rawName (e)));
1056 st->entries[eindex] = e;
1060 eindex = usymtab_addEntryAux (st, e, FALSE);
1066 void usymtab_supEntry (uentry e)
1067 /*@globals utab, filetab, globtab@*/
1068 /*@modifies utab, globtab, e@*/
1070 (void) usymtab_supEntryAux (utab, e, FALSE);
1074 ** this should be lots more efficient!
1077 static /*@exposed@*/ uentry
1078 usymtab_supEntryReturnAux (/*@notnull@*/ usymtab tab,
1079 /*@only@*/ uentry e, bool isref)
1080 /*@globals globtab, filetab@*/
1081 /*@modifies tab, globtab, e@*/
1083 cstring rawName = cstring_copy (uentry_rawName (e));
1084 bool stat = (tab == globtab) && uentry_isStatic (e);
1087 (void) usymtab_supEntryAux (tab, e, isref);
1091 ret = usymtab_lookupAux (filetab, rawName);
1095 ret = usymtab_lookupAux (tab, rawName);
1097 if (uentry_isInvalid (ret) && usymtab_isDefined (filetab))
1099 ret = usymtab_lookupAux (filetab, rawName);
1103 cstring_free (rawName);
1107 /*@dependent@*/ /*@exposed@*/ uentry
1108 usymtab_supEntryReturn (/*@only@*/ uentry e)
1109 /*@globals utab, filetab, globtab@*/
1110 /*@modifies utab, globtab, e@*/
1112 return (usymtab_supEntryReturnAux (utab, e, FALSE));
1115 /*@dependent@*/ /*@exposed@*/ uentry
1116 usymtab_supEntrySrefReturn (/*@only@*/ uentry e)
1117 /*@globals utab, globtab, filetab@*/
1118 /*@modifies utab, globtab, e@*/
1120 return (usymtab_supEntryReturnAux (utab, e, TRUE));
1123 /*@dependent@*/ /*@exposed@*/ uentry
1124 usymtab_supGlobalEntryReturn (uentry e)
1125 /*@globals globtab, filetab@*/
1126 /*@modifies globtab, e@*/
1130 ret = usymtab_supEntryReturnAux (globtab, e, FALSE);
1133 ** We need to keep track of internal function declarations, so
1134 ** we can remove them from the symbol table after exiting this
1135 ** function. This is a bit bogus, of course.
1138 if (sRef_modInFunction ())
1140 recordFunctionType (ret);
1147 usymtab_supTypeEntry (/*@only@*/ uentry e)
1148 /*@globals globtab, filetab@*/
1149 /*@modifies globtab, e@*/
1154 if (uentry_isAbstractDatatype (e))
1156 uid = usymtab_supAbstractTypeEntry (e, FALSE);
1157 ret = ctype_createAbstract (uid);
1161 uid = usymtab_supEntryAux (globtab, e, FALSE);
1162 ret = ctype_createUser (uid);
1165 if (sRef_modInFunction ())
1167 recordFunctionType (globtab->entries[uid]);
1174 usymtab_supReturnTypeEntry (/*@only@*/ uentry e)
1175 /*@globals globtab, filetab@*/
1176 /*@modifies globtab@*/
1180 DPRINTF (("Abstract? %s", uentry_unparseFull (e)));
1182 if (uentry_isAbstractDatatype (e))
1184 uid = usymtab_supAbstractTypeEntry (e, FALSE);
1186 else if (uentry_isMaybeAbstract (e) && context_getFlag (FLG_IMPABSTRACT))
1188 bool maybeabs = TRUE;
1189 cstring sname = uentry_getName (e);
1190 uentry ue = usymtab_lookupGlobSafe (sname);
1191 cstring_free (sname);
1193 if (uentry_isValid (ue))
1195 DPRINTF (("Lookup: %s", uentry_unparseFull (ue)));
1197 if (uentry_isDatatype (ue))
1199 if (uentry_isMaybeAbstract (ue))
1210 DPRINTF (("Not datatype!"));
1217 uid = usymtab_supAbstractTypeEntry (e, FALSE);
1218 ux = usymtab_getTypeEntry (uid);
1219 uentry_setAbstract (ux);
1223 uid = usymtab_supEntryAux (globtab, e, FALSE);
1224 e = usymtab_getTypeEntry (uid);
1226 if (uentry_isMaybeAbstract (e))
1228 uentry_setConcrete (e);
1234 uid = usymtab_supEntryAux (globtab, e, FALSE);
1235 e = usymtab_getTypeEntry (uid);
1237 if (uentry_isMaybeAbstract (e))
1239 uentry_setConcrete (e);
1243 if (sRef_modInFunction ())
1245 recordFunctionType (globtab->entries[uid]);
1248 return (globtab->entries[uid]);
1252 usymtab_supAbstractTypeEntry (/*@only@*/ uentry e, bool dodef)
1253 /*@globals globtab, filetab@*/
1254 /*@modifies globtab, e@*/
1259 uid = usymtab_supEntryAux (globtab, e, FALSE);
1260 ue = usymtab_getTypeEntry (uid);
1264 uentry_setDatatype (ue, uid);
1267 if (context_getFlag (FLG_ACCESSMODULE)) /* was accessfile */
1269 context_addFileAccessType (uid);
1272 if (sRef_modInFunction ())
1274 recordFunctionType (globtab->entries[uid]);
1281 usymtab_supExposedTypeEntry (/*@only@*/ uentry e, bool dodef)
1282 /*@globals globtab, filetab@*/
1283 /*@modifies globtab, e@*/
1287 uid = usymtab_supEntryAux (globtab, e, FALSE);
1291 uentry ue = usymtab_getTypeEntry (uid);
1293 uentry_setDatatype (ue, uid);
1296 if (sRef_modInFunction ())
1298 recordFunctionType (globtab->entries[uid]);
1305 usymtab_supForwardTypeEntry (/*@only@*/ uentry e)
1306 /*@globals globtab, filetab@*/
1307 /*@modifies globtab, e@*/
1309 usymId uid = usymtab_supEntryAux (globtab, e, FALSE);
1310 uentry ue = usymtab_getTypeEntry (uid);
1312 uentry_setDatatype (ue, uid);
1314 if (sRef_modInFunction ())
1316 recordFunctionType (globtab->entries[uid]);
1319 return (uentry_getAbstractType (ue));
1323 usymtab_supEntrySref (uentry e)
1324 /*@globals utab, globtab, filetab@*/
1325 /*@modifies utab, globtab, e@*/
1327 sRef old = uentry_getSref (e);
1329 if (sRef_isType (old))
1331 uentry ue = usymtab_supEntryReturnAux (utab, e, TRUE);
1334 if (uentry_isValid (ue))
1336 sRef uref = uentry_getSref (ue);
1338 sRef_mergeStateQuiet (uref, old);
1339 sRef_clearDerived (uref);
1341 /*@noaccess uentry@*/
1343 else if (sRef_isKnown (old))
1345 usymtab_supEntry (e);
1349 (void) usymtab_supEntryAux (utab, e, TRUE);
1353 void usymtab_supGlobalEntry (/*@only@*/ uentry e)
1354 /*@globals globtab, filetab@*/
1355 /*@modifies globtab, filetab, e@*/
1359 DPRINTF (("Sup global entry: %s", uentry_unparse (e)));
1361 uid = usymtab_supEntryAux (globtab, e, FALSE);
1363 if (sRef_modInFunction ())
1365 recordFunctionType (globtab->entries[uid]);
1370 usymtab_supReturnFileEntry (/*@only@*/ uentry e)
1371 /*@globals filetab, globtab@*/
1372 /*@modifies filetab, globtab, e@*/
1374 llassert (filetab != usymtab_undefined);
1375 DPRINTF (("File entry: %s", uentry_unparse (e)));
1376 return (usymtab_supEntryReturnAux (filetab, e, FALSE));
1384 usymtab_inDeepScope () /*@globals utab@*/
1386 return (utab->lexlevel > paramsScope);
1390 usymtab_getIndex (/*@notnull@*/ usymtab s, cstring k)
1394 DPRINTF (("Lookup %s", k));
1396 if (cstringTable_isDefined (s->htable))
1398 i = cstringTable_lookup (s->htable, k);
1403 for (i = 0; i < s->nentries; i++)
1405 uentry current = s->entries[i];
1407 DPRINTF (("Check %d: %s", i, uentry_rawName (current)));
1409 if (!uentry_isUndefined (current)
1410 && cstring_equal (uentry_rawName (current), k))
1421 usymtab_fetchIndex (/*@notnull@*/ usymtab s, int i)
1423 llassert (i >= 0 && i < s->nentries);
1424 return (s->entries[i]);
1428 usymtab_getTypeId (cstring k) /*@globals globtab@*/
1430 usymId uid = usymtab_getIndex (globtab, k);
1432 if (uid == NOT_FOUND) return USYMIDINVALID;
1434 if (!(uentry_isDatatype (usymtab_getTypeEntry (uid)))) {
1435 return USYMIDINVALID;
1441 /*@dependent@*/ uentry
1442 usymtab_lookupStructTag (cstring k)
1444 cstring sname = makeStruct (k);
1445 uentry ue = usymtab_lookupGlob (sname);
1447 cstring_free (sname);
1451 /*@dependent@*/ uentry
1452 usymtab_lookupUnionTag (cstring k)
1454 cstring uname = makeUnion (k);
1455 uentry res = usymtab_lookupGlob (uname);
1457 cstring_free (uname);
1461 /*@dependent@*/ uentry
1462 usymtab_lookupEnumTag (cstring k)
1464 cstring ename = makeEnum (k);
1465 uentry res = usymtab_lookupGlob (ename);
1467 cstring_free (ename);
1472 usymtab_getId (cstring k) /*@globals globtab@*/
1474 usymId uid = usymtab_getIndex (globtab, k);
1477 if (uid == NOT_FOUND)
1479 return USYMIDINVALID;
1482 ue = usymtab_getGlobalEntry (uid);
1484 if (uentry_isPriv (ue))
1486 return USYMIDINVALID;
1492 static /*@exposed@*/ uentry
1493 usymtab_getEntryAux (/*@notnull@*/ usymtab s, usymId uid)
1495 llassert (uid != USYMIDINVALID);
1497 if (uid < 0 || uid >= s->nentries)
1499 llcontbug (message ("usymtab_getEntry: out of range: level = %d [%d]",
1501 return uentry_undefined;
1504 llassertprint (uentry_isValid (s->entries[uid]),
1505 ("entry undefined: %d", uid));
1507 return s->entries[uid];
1510 /*@dependent@*/ /*@observer@*/ uentry
1511 usymtab_getGlobalEntry (usymId uid)
1512 /*@globals utab, globtab@*/
1514 if (dbgfree) return (uentry_undefined);
1516 if (utab->lexlevel > paramsScope)
1518 /* need to do this the awkward way, since it could be in conditional scope */
1519 return (usymtab_lookupSafe (uentry_rawName (globtab->entries[uid])));
1523 return (globtab->entries[uid]);
1527 /*@dependent@*/ /*@exposed@*/ uentry
1528 usymtab_getTypeEntry (usymId uid)
1529 /*@globals globtab@*/
1533 if (uid >= 0 && uid < globtab->nentries)
1535 return (globtab->entries[uid]);
1539 return (uentry_undefined);
1544 llassert (uid >= 0 && uid < globtab->nentries);
1545 return (globtab->entries[uid]);
1553 /*@dependent@*/ /*@exposed@*/ uentry
1554 usymtab_getTypeEntrySafe (usymId uid)
1555 /*@globals globtab@*/
1557 if (uid < 0 || uid >= globtab->nentries)
1559 return uentry_undefined;
1562 return (globtab->entries[uid]);
1566 usymtab_isBoolType (usymId uid)
1567 /*@globals globtab@*/
1569 llassert (uid >= 0 && uid < globtab->nentries);
1571 return (cstring_equal (uentry_rawName (globtab->entries[uid]),
1572 context_getBoolName ()));
1576 usymtab_getTypeEntryName (usymId uid)
1577 /*@globals globtab@*/
1583 return (cstring_makeLiteral ("<freetype>"));
1586 ue = usymtab_getTypeEntry (uid);
1588 if (dbgload && !uentry_isValid (ue))
1590 return (message ("<missing type: %d>", uid));
1593 llassertprint (uentry_isValid (ue), ("type undefined: %d", uid));
1595 return (uentry_getName (ue));
1599 /*@unused@*/ static void
1600 usymtab_rehash (/*@notnull@*/ usymtab s)
1604 if (cstringTable_isDefined (s->htable))
1606 cstringTable_free (s->htable);
1609 s->htable = cstringTable_create (LLAHSHSIZE);
1611 for (i = 0; i < s->nentries; i++)
1613 cstringTable_insert (s->htable, cstring_copy (uentry_rawName (s->entries[i])), i);
1619 ** superficial copy of usymtab
1621 ** DO copy spec entries
1624 static /*@only@*/ /*@notnull@*/ usymtab
1625 usymtab_shallowCopy (/*@notnull@*/ usymtab s) /*@*/
1627 usymtab copytab = usymtab_createRoot ();
1630 for (i = 0; i < s->nentries; i++)
1632 usymtab_addEntryBase (copytab, s->entries[i]);
1639 usymtab_shallowFree (/*@only@*/ /*@notnull@*/ usymtab s)
1641 aliasTable_free (s->aliases);
1642 refTable_free (s->reftable, s->nentries);
1644 /*@-compdestroy@*/ sfree (s); /*@=compdestroy@*/
1648 ** converts usymId from old table to sorted one
1652 usymtab_convertId (usymId uid)
1653 /*@globals oldtab, utab@*/
1659 llassert (usymtab_isDefined (oldtab));
1661 ue = usymtab_getEntryAux (oldtab, uid);
1663 llassertprint (uentry_isValid (ue), ("convertId: undefined: %d", uid));
1665 name = uentry_rawName (ue);
1667 ret = usymtab_getIndex (utab, name);
1668 llassert (ret == uid); /*! for now, no rehash! */
1669 DPRINTF (("Convert: %s [%d] -> %s [%d]",
1670 uentry_unparse (ue), uid,
1671 uentry_unparse (utab->entries[ret]), ret));
1673 llassertprint (ret != USYMIDINVALID, ("convertId: return is invalid"));
1679 usymtab_prepareDump (void)
1680 /*@globals oldtab, utab@*/
1681 /*@modifies oldtab, utab@*/
1683 llassert (usymtab_inGlobalScope ());
1684 llassert (oldtab == usymtab_undefined);
1687 DPRINTF (("Preparing to dump:"));
1688 usymtab_printAll ();
1691 oldtab = usymtab_shallowCopy (utab);
1694 ** alpha compare - make sure order is same on different platforms
1695 ** error messages appear in same order
1699 qsort (utab->entries, (size_t)utab->nentries,
1700 sizeof (*utab->entries),
1701 (int (*)(const void *, const void *)) uentry_xcomparealpha);
1703 usymtab_rehash (utab);
1707 DPRINTF (("After rehash:"));
1708 usymtab_printAll ();
1712 void usymtab_dump (FILE *fout)
1713 /*@globals utab, oldtab@*/
1716 bool neednl = FALSE;
1717 uentry lastentry = uentry_undefined;
1718 ekind lastekind = KINVALID;
1722 ** must call prepareDump first
1725 llassert (oldtab != usymtab_undefined);
1727 for (i = 0; i < utab->nentries; i++)
1729 uentry thisentry = utab->entries[i];
1730 ekind thisekind = uentry_getKind (thisentry);
1732 if (!uentry_hasRealName (thisentry))
1734 llassert (uentry_isGlobalMarker (thisentry));
1738 check (fputc ('\n', fout) == (int) '\n');
1741 fprintf (fout, "*%d (GlobalMarker)\n", KGLOBALMARKER);
1742 lastekind = KINVALID;
1748 if (thisekind != lastekind)
1752 check (fputc ('\n', fout) == (int) '\n');
1756 lastentry = uentry_undefined;
1757 fprintf (fout, "*%d (%s)\n", ekind_toInt (thisekind),
1758 cstring_toCharsSafe (ekind_capName (thisekind)));
1759 lastekind = thisekind;
1764 ** evans - 2001-02-18 - added the - 48 fudge factor...
1765 ** extra characters dumped, but I haven't counded them carefully...
1768 if (uentry_isInvalid (lastentry) || !uentry_equiv (lastentry, thisentry)
1769 || (linelen > (MAX_DUMP_LINE_LENGTH - (2 * MAX_NAME_LENGTH) - 48)))
1773 DPRINTF (("Dumping entry: %d", i));
1774 cdump = message ("^%d %q", i, uentry_dump (thisentry));
1775 /* was: cdump = uentry_dump (thisentry)); */
1777 lastentry = thisentry;
1780 check (fputc ('\n', fout) == (int) '\n');
1784 linelen += cstring_length (cdump);
1786 /* no new line here! */
1787 if (cstring_length (cdump) > 0)
1789 check (fputs (cstring_toCharsSafe (cdump), fout) != EOF);
1792 cstring_free (cdump);
1797 cstring cdump = uentry_rawName (thisentry);
1798 DPRINTF (("Raw name: %s", cdump));
1799 linelen += (cstring_length (cdump) + 1);
1800 fprintf (fout, "#%s", cstring_toCharsSafe (cdump));
1807 check (fputc ('\n', fout) == (int) '\n');
1810 lastekind = KINVALID;
1812 fprintf(fout, ";; Library constraints\n");
1814 /*drl July 27 added this so that libraries without
1815 buffer constraints would be handled correctly.
1816 I'm trying to do this without breaking older libraries.
1818 Splint should still be able to handle libraries without this message.
1822 fprintf(fout, "start_Buffer_Constraints\n");
1824 for (i = 0; i < utab->nentries; i++)
1826 uentry thisentry = utab->entries[i];
1828 if (uentry_isFunction (thisentry) )
1830 constraintList preconditions;
1831 constraintList postconditions;
1833 preconditions = uentry_getFcnPreconditions (thisentry);
1834 postconditions = uentry_getFcnPostconditions (thisentry);
1836 if ( constraintList_isDefined(preconditions) ||
1837 constraintList_isDefined(postconditions) )
1839 fprintf(fout,"%s\n", cstring_toCharsSafe (uentry_rawName(thisentry) ) );
1840 if (constraintList_isDefined(preconditions) )
1842 fprintf(fout,"pre:\n");
1843 constraintList_dump(preconditions, fout);
1844 fprintf (fout, ";; end precondition constraints\n" );
1845 constraintList_free(preconditions);
1849 fprintf(fout,"pre:EMPTY\n");
1851 if (constraintList_isDefined(postconditions) )
1853 fprintf(fout,"post:\n");
1854 constraintList_dump(postconditions, fout);
1855 fprintf (fout, ";; end precondition constraints\n" );
1856 constraintList_free(postconditions);
1860 fprintf(fout,"post:EMPTY\n");
1869 void usymtab_load (FILE *f)
1870 /*@globals utab, globtab@*/
1871 /*@modifies utab, *f@*/
1873 char *s = mstring_create (MAX_DUMP_LINE_LENGTH);
1875 ekind kind = KINVALID;
1876 fileloc loc = g_currentloc;
1882 llassert (utab == globtab);
1883 llassert (utab->nentries == 0);
1885 while (((s = reader_readLine (f, s, MAX_DUMP_LINE_LENGTH)) != NULL)
1888 /* ignore ; comments */ ;
1891 while (s != NULL && *s != ';')
1899 ek = reader_getInt (&s);
1901 if (ek == KGLOBALMARKER)
1903 uentry lue = uentry_makeGlobalMarker ();
1904 DPRINTF (("Adding global marker: %s", uentry_unparseFull (lue)));
1905 usymtab_addEntryAlways (utab, lue);
1911 kind = ekind_fromInt (ek);
1919 (cstring_makeLiteral
1920 ("Library is in obsolete format. Use splint +whichlib "
1921 "to see which library is being loaded."));
1924 if (reader_optCheckChar (&s, '^'))
1926 index = reader_getInt (&s);
1933 llassert (kind != KINVALID);
1934 ue = uentry_undump (kind, loc, &s);
1936 llassert (utab->nentries == index || index == -1);
1938 if (uentry_isValid (ue))
1940 int lastindex = utab->nentries;
1941 ue = usymtab_addEntryAlways (utab, ue);
1945 if (uentry_isConstant (ue)) /*@i23! isPreProcessorMacro */
1947 cstring uname = uentry_getName (ue);
1949 /* Also check its a macro... */
1950 DPRINTF (("Installing: %s", uname));
1952 cpphash_installMacro
1953 (mstring_copy (cstring_toCharsSafe (uname)),
1954 cstring_length (uname),
1955 cpplib_createDefinition (message ("%s 255", uname),
1958 cpphash_hashCode (cstring_toCharsSafe (uname),
1959 cstring_length (uname),
1962 DPRINTF (("After install: %s", uname));
1966 if (utab->nentries != lastindex + 1)
1968 DPRINTF (("No add: %s", uentry_unparseFull (ue)));
1976 ** now, any other names are the same uentry
1979 while (*(s++) == '#')
1981 cstring name = cstring_fromCharsO (reader_getWord (&s));
1982 uentry nue = uentry_nameCopy (name, ue);
1984 DPRINTF (("Name copy: %s", uentry_unparseFull (nue)));
1988 usymtab_addEntryAlways (utab, nue);
1991 while ((c = *s) != '\0' && (c !='\n'))
1993 if (c != ' ' || c != '\t')
1995 llbuglit ("Junk in load file");
2003 s = reader_readLine (f, os, MAX_DUMP_LINE_LENGTH);
2008 to handle reading of buffer overflow related constraints
2010 while (fgets (s, MAX_DUMP_LINE_LENGTH, f) != NULL
2013 ; /* ignore ;-comments */
2016 /*drl July 27 added this so that libraries without
2017 buffer constraints would be handled correctly.
2018 I'm trying to do this without breaking older libraries*/
2020 /*check for "optional" start buffer constraints message*/
2022 if (mstring_equalPrefix (s, "start_Buffer_Constraints"))
2024 (void) fgets (s, MAX_DUMP_LINE_LENGTH, f);
2027 while (s != NULL && *s != ';')
2029 constraintList preconditions;
2030 constraintList postconditions;
2032 cstring name = cstring_fromChars(reader_getWord(&s) );
2034 ue = usymtab_lookup ( name );
2038 preconditions = constraintList_undefined;
2039 postconditions = constraintList_undefined;
2041 if (!uentry_isValid(ue) )
2043 llfatalbug ((message("Invalid uentry for %s library file may be corrupted", cstring_fromChars(s) ) ));
2045 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2047 temp = cstring_fromChars (reader_getWord(&s) );
2049 if (cstring_compareLit (temp,"pre:") == 0 )
2051 preconditions = constraintList_undump (f);
2055 if (cstring_compareLit (temp,"pre:EMPTY") != 0 )
2056 llfatalbug ((message("Error reading library file pre:EMPTY expected but got %s", temp ) ));
2061 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2063 temp = cstring_fromChars(reader_getWord(&s) );
2064 if (cstring_compareLit (temp, "post:") == 0 )
2066 postconditions = constraintList_undump (f);
2070 if (cstring_compareLit (temp, "post:EMPTY") != 0 )
2071 llfatalbug ((message("Error reading library file post:EMPTY expected but got %s", temp ) ));
2074 cstring_free (temp);
2076 uentry_setPreconditions (ue, functionConstraint_createBufferConstraint (preconditions));
2077 uentry_setPostconditions (ue, functionConstraint_createBufferConstraint (postconditions));
2079 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2087 ** file scope for static variables
2091 usymtab_enterFile ()
2092 /*@globals utab, globtab, filetab@*/
2093 /*@modifies filetab@*/
2095 llassert (utab == globtab);
2100 usymtab_entries (globtab, ue)
2102 if (sRef_hasDerived (uentry_getSref (ue)))
2104 fprintf (g_warningstream, "Derived Global: %s\n", uentry_unparse (ue));
2105 fprintf (g_warningstream, "sRef: %s\n", sRef_unparseFull (ue->sref));
2107 } end_usymtab_entries ;
2111 usymtab_enterScope ();
2117 /*@globals utab, filetab@*/
2118 /*@modifies filetab, utab@*/
2121 llassert (utab->lexlevel == 1);
2123 usymtab_exitScope (exprNode_undefined);
2128 usymtab_enterScope ()
2129 /*@globals utab, globtab, filetab@*/
2132 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
2134 /* unconditional scope: optimize to avoid copy */
2135 t->aliases = aliasTable_copy (utab->aliases);
2138 llassert (usymtab_isDefined (t->env));
2140 if (t->env->lexlevel == paramsScope && context_inFunctionLike ())
2142 noshadowerror = TRUE;
2143 usymtab_handleParams ();
2144 noshadowerror = FALSE;
2149 ** setup external references:
2150 ** o only, unique params alias external args
2151 ** o other params may alias anything of their type
2155 usymtab_handleParams (void)
2156 /*@globals utab, globtab, filetab@*/
2157 /*@modifies utab, globtab@*/
2159 usymtab ptab = utab->env;
2160 uentry fcn = context_getHeader ();
2162 usymtab_entries (ptab, param)
2166 if (!uentry_isYield (param))
2169 sRef pref = uentry_getSref (param);
2171 /* Could be a global. */
2173 if (uentry_isAnyParam (param))
2175 ue = uentry_makeVariable (fixParamName (uentry_rawName (param)),
2176 uentry_getType (param),
2177 fileloc_copy (uentry_whereDeclared (param)),
2180 uentry_copyState (ue, param);
2181 uentry_setRefParam (ue);
2183 ue = usymtab_supEntrySrefReturn (ue);
2185 /* must be after supercede! */
2187 if (!sRef_stateKnown (pref))
2189 uentry_setDefState (ue, SS_DEFINED);
2190 uentry_setDefState (param, SS_DEFINED);
2194 if (sRef_isStateSpecial (pref))
2196 uentry_setDefState (ue, SS_SPECIAL); /* ALLOCATED); */
2197 /* evans 2002-01-01: should be unnecessary, the pre clauses
2198 ** set the state if necessary.
2203 uentry_setDefState (ue, sRef_getDefState (pref));
2207 uref = uentry_getSref (ue);
2209 if (sRef_isStack (uref))
2211 alkind pkind = sRef_getAliasKind (pref);
2213 if (alkind_isKnown (pkind) && !alkind_isLocal (pkind)
2214 && !alkind_isStack (pkind))
2216 sRef_setAliasKind (uref, pkind, fileloc_undefined);
2217 sRef_setOrigAliasKind (uref, pkind);
2221 sRef_setAliasKind (uref, AK_IMPTEMP, fileloc_undefined);
2222 sRef_setOrigAliasKind (uref, AK_IMPTEMP);
2224 if (uentry_isOut (param))
2230 sRef_setDefined (uref, fileloc_undefined);
2236 usymtab_addMustAlias (uref, pref);
2238 if (!(uentry_isOnly (param) || uentry_isUnique (param)))
2241 ** This is needed for detecting possibly aliased parameters.
2244 sRef s = sRef_makeExternal (uref);
2245 usymtab_addMustAlias (uref, s);
2248 if (sRef_isKillRef (pref))
2250 sRef_setAliasKind (uref, AK_NEWREF, fileloc_undefined);
2251 sRef_setOrigAliasKind (uref, AK_KILLREF);
2253 else if (sRef_isRefCounted (uref))
2255 sRef_setOrigAliasKind (uref, AK_REFCOUNTED);
2260 sRef_setOrigAliasKind (uref, AK_LOCAL);
2267 } end_usymtab_entries;
2270 if (uentry_hasStateClauseList (fcn))
2272 stateClauseList clauses = uentry_getStateClauseList (fcn);
2274 stateClauseList_preElements (clauses, cl)
2276 fileloc loc = stateClause_loc (cl);
2277 sRefSet osrs = sRefSet_undefined;
2280 if (stateClause_isGlobal (cl))
2282 DPRINTF (("Global Marker: %s",
2283 sRef_unparseFull (usymtab_lookupGlobalMarker ())));
2284 llassert (sRef_isGlobalMarker (usymtab_lookupGlobalMarker ()));
2285 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
2290 srs = stateClause_getRefs (cl);
2293 sRefSet_elements (srs, el)
2295 sRef base = sRef_getRootBase (el);
2296 sRef sb = sRef_updateSref (el);
2298 if (sRef_isResult (base))
2300 ; /* nothing to do before */
2302 else if (sRef_isParam (base) || sRef_isGlobalMarker (base))
2304 if (stateClause_setsMetaState (cl))
2306 /* copied from exprNode.c:3040 */
2307 qual ql = stateClause_getMetaQual (cl);
2308 annotationInfo ainfo = qual_getAnnotationInfo (ql);
2309 metaStateInfo minfo = annotationInfo_getState (ainfo);
2310 cstring key = metaStateInfo_getName (minfo);
2311 int mvalue = annotationInfo_getValue (ainfo);
2313 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
2315 if (sRef_isResult (base))
2321 sRef_setMetaStateValueComplete (sb, key, mvalue, loc);
2326 sRefMod modf = stateClause_getEntryFunction (cl);
2330 sRefSet aliases = usymtab_allAliases (sb);
2334 sRefSet_elements (aliases, sr)
2337 } end_sRefSet_elements ;
2339 sRefSet_free (aliases);
2345 if (sRef_isValid (base))
2347 DPRINTF (("Base: %s", sRef_unparseFull (base)));
2351 } end_sRefSet_elements ;
2352 } end_stateClauseList_preElements ;
2357 usymtab_enterFunctionScope (uentry fcn)
2358 /*@globals utab, filetab, globtab@*/
2361 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
2363 DPRINTF (("Enter function: %s", uentry_unparse (fcn)));
2365 if (utab->lexlevel != fileScope)
2367 if (utab->lexlevel > fileScope)
2369 llparseerror (cstring_makeLiteral ("New function scope inside function"));
2371 while (utab->lexlevel > fileScope)
2373 /*@i@*/ utab = usymtab_dropEnv (utab);
2380 llfatalbug (cstring_makeLiteral ("New function not inside file."));
2382 /*@-branchstate@*/ } /*@=branchstate@*/
2386 DPRINTF (("Globs: %s", globSet_unparse (uentry_getGlobs (fcn))));
2388 globSet_allElements (uentry_getGlobs (fcn), el)
2390 DPRINTF (("Here we go: %s", sRef_unparseFull (el)));
2392 if (sRef_isUndefGlob (el))
2394 int index = sRef_getScopeIndex (el);
2395 sRef sr = sRef_updateSref (el);
2396 fileloc loc = uentry_whereEarliest (fcn);
2398 DPRINTF (("update: %s", sRef_unparseFull (sr)));
2399 DPRINTF (("Undef!"));
2400 if (sRef_isFileStatic (el))
2402 ctype ct = sRef_getType (el);
2405 llassert (usymtab_isDefined (filetab));
2407 ue = usymtab_fetchIndex (filetab, index);
2409 if (ctype_isRealArray (ct) || ctype_isRealSU (ct))
2411 sRef_setAllocated (sr, loc);
2415 sRef_setUndefined (sr, loc);
2420 uentry ue = globtab->entries[index];
2421 ctype ct = uentry_getType (ue);
2423 if (ctype_isArray (ct) || ctype_isSU (ct))
2425 sRef_setAllocated (sr, loc);
2429 sRef_setUndefined (sr, loc);
2433 else if (sRef_isAllocated (el))
2435 sRef sr = sRef_updateSref (el);
2436 fileloc loc = uentry_whereEarliest (fcn);
2438 sRef_setAllocated (sr, loc);
2440 else if (sRef_isPartial (el))
2442 sRef sr = sRef_updateSref (el);
2443 fileloc loc = uentry_whereEarliest (fcn);
2445 sRef_setPartial (sr, loc);
2450 sRef sr = sRef_updateSref (el);
2451 fileloc loc = uentry_whereEarliest (fcn);
2453 sRef_setDefined (sr, loc);
2457 /* shouldn't need to do anything! */
2459 } end_globSet_allElements;
2461 DPRINTF (("Globs after: %s", globSet_unparse (uentry_getGlobs (fcn))));
2463 usymtab_checkAllValid ();
2468 usymtab_caseBranch (void)
2471 usymtab t = usymtab_create (US_CBRANCH, utab, FALSE);
2476 usymtab_switchBranch (/*@unused@*/ exprNode s)
2479 usymtab t = usymtab_create (US_SWITCH, utab, FALSE);
2481 t->aliases = aliasTable_copy (utab->aliases);
2486 usymtab_trueBranch (/*@only@*/ guardSet guards)
2489 usymtab t = usymtab_create (US_TBRANCH, utab, FALSE);
2492 ** not true! (could be in a macro)
2494 ** llassertprint (utab->lexlevel > paramsScope,
2495 ** ("not in scope: %s", usymtab_unparseLocal ()));
2499 guardSet_free (t->guards);
2502 aliasTable_free (t->aliases);
2503 t->aliases = aliasTable_copy (utab->aliases);
2511 ** { int a; if (...) a = 3; < a may be undefined here!
2516 usymtab_popTrueBranch (exprNode pred, exprNode expr, clause cl) /*@modifies utab@*/
2519 ** add a false branch
2520 ** (could be done more efficiently as a special case, but
2521 ** it is better to only maintain one version of the code)
2524 if (utab->kind != US_TBRANCH
2525 && context_inIterDef ())
2527 usymtab_exitScope (expr);
2531 DPRINTF (("pop true branch.."));
2532 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2533 usymtab_popBranches (pred, expr, exprNode_undefined, TRUE, cl);
2538 usymtab_popCaseBranch () /*@modifies utab@*/
2540 llassert (utab->kind == US_CBRANCH);
2541 usymtab_quietPlainExitScope ();
2545 usymtab_popTrueExecBranch (exprNode pred, exprNode expr, clause cl)
2548 ** add a false branch that must return --- that is,
2549 ** the true branch is always executed!
2552 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2553 usymtab_popBranches (pred, expr, exprNode_makeMustExit (), FALSE, cl);
2557 usymtab_popOrBranch (exprNode pred, exprNode expr)
2561 usymtab env = utab->env;
2562 usymtab otab = utab;
2565 llassert (env != NULL);
2567 if (exprNode_isError (expr))
2573 mustReturn = exprNode_mustEscape (expr);
2577 llassert (utab->kind == US_TBRANCH);
2580 ** merge each entry in table with its original
2581 ** unless execution cannot continue after this branch
2584 for (i = 0; i < utab->nentries; i++)
2586 uentry current = utab->entries[i];
2587 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2589 uentry_mergeState (old, current, exprNode_loc (expr),
2590 mustReturn, FALSE, TRUE, ORCLAUSE);
2596 env->guards = guardSet_levelUnionFree (env->guards,
2597 guardSet_invert (exprNode_getGuards (pred)),
2602 env->aliases = aliasTable_levelUnion (env->aliases, otab->aliases, env->lexlevel);
2605 /* env is now utab */
2606 usymtab_quietPlainExitScope ();
2610 ** case syntax in C is very unrestricted. This is unfortunate.
2612 ** A switch case is ended either by a new case or default, or
2613 ** a close } that may close the switch or some other control
2618 usymtab_newCase (/*@unused@*/ exprNode pred, exprNode last)
2621 bool mustBreak = usymtab_mustBreak (utab);
2622 bool mustReturn = usymtab_mustEscape (utab);
2623 usymtab stab = utab;
2625 DPRINTF (("New case!"));
2628 ** Find last case (or outer switch)
2631 while (stab->kind != US_CBRANCH && stab->kind != US_SWITCH)
2634 llassert (stab != GLOBAL_ENV);
2637 while (stab->kind == US_CBRANCH)
2640 llassert (stab != GLOBAL_ENV);
2644 ** if its a fall through case, merge in outside entries and last case.
2649 ** case 1: x = 3; <fall through>
2650 ** case 2: << x may not be defined
2654 if (!mustBreak && !mustReturn && utab->kind == US_CBRANCH)
2656 llassert (stab->kind == US_SWITCH || stab->kind == US_NORMAL);
2658 usymtab_entries (utab, ue) /* but, keep track of used variables */
2660 uentry old = usymtab_lookupAux (stab, uentry_rawName (ue));
2662 llassert (uentry_isValid (old));
2664 /* modifies ue, not old */
2666 uentry_mergeState (ue, old, exprNode_loc (last),
2667 FALSE, FALSE, TRUE, CASECLAUSE);
2668 } end_usymtab_entries;
2670 utab->aliases = aliasTable_levelUnion (utab->aliases,
2671 stab->aliases, utab->lexlevel);
2674 ** No need for a new branch.
2681 usymtab_caseBranch ();
2682 /*@-mustfree@*/ /*< utab->aliases >*/
2683 utab->aliases = aliasTable_copy (stab->aliases);
2691 ** for && (both pred and expr are executed)
2695 usymtab_popAndBranch (exprNode pred, /*@unused@*/ exprNode expr)
2698 usymtab env = utab->env;
2702 llassert (utab->kind == US_TBRANCH);
2705 ** merge each entry in table with its original
2706 ** unless execution cannot continue after this branch
2709 for (i = 0; i < utab->nentries; i++)
2711 uentry current = utab->entries[i];
2712 sRef tref = uentry_getSref (current);
2713 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2714 sRef oref = uentry_getSref (old);
2716 /* note that is current is in a nested branch,
2717 it may create a "new" old entry. */
2719 llassert (uentry_isValid (old));
2720 uentry_mergeState (old, current, exprNode_loc (expr),
2721 FALSE, FALSE, TRUE, ANDCLAUSE);
2724 ** if is it defined by the second clause, then it should be defined.
2727 if (sRef_isAnyDefined (tref)
2728 && (sRef_isAllocated (oref) || sRef_isStateUndefined (oref)))
2730 sRef_setDefined (oref, g_currentloc);
2734 utab->guards = guardSet_levelUnionFree (utab->guards,
2735 guardSet_invert (exprNode_getGuards (pred)),
2737 utab->aliases = aliasTable_levelUnion (utab->aliases, otab->aliases, utab->lexlevel);
2739 usymtab_quietPlainExitScope ();
2744 ** Stack should be [ US_CBRANCH+ US_SWITCH ]
2745 ** Only branches which do not return (except possibly the last branch) are included.
2747 ** Conditionally merge state from all CBRANCHes.
2749 ** If allpaths is TRUE, then all possible executions go through some switch
2750 ** case, and the original scope is not merged.
2754 usymtab_exitSwitch (/*@unused@*/ exprNode sw, bool allpaths)
2757 usymtab ttab = utab;
2758 usymtab stab = ttab;
2759 usymtab ltab = ttab;
2760 bool lastMustReturn = usymtab_mustEscape (utab);
2764 while (stab->kind == US_CBRANCH)
2767 llassert (stab != GLOBAL_ENV);
2770 while (stab->kind == US_NORMAL)
2773 llassert (stab != GLOBAL_ENV);
2776 llassert (stab->kind == US_SWITCH);
2778 /* go to the scope outside the switch (US_SWITCH is just a marker! */
2780 llassert (stab != GLOBAL_ENV);
2784 llassert (usymtab_isDefined (ttab));
2786 if (ttab->kind == US_CBRANCH)
2788 /* was quietPlainExitScope --- but, can't free it yet! */
2790 llassert (utab != GLOBAL_ENV);
2792 while (ttab->kind == US_CBRANCH)
2795 ** (from popTrueBranch)
2798 bool mustReturn = usymtab_mustEscape (ttab);
2799 bool mustBreak = usymtab_mustBreak (ttab);
2801 usymtab_entries (ttab, current)
2803 uentry old = /*@-compmempass@*/ usymtab_lookupAux (ltab, uentry_rawName (current));
2807 ** note that is this is in a nested branch,
2808 ** it may create a "new" old entry.
2811 if (uentry_isValid (old))
2815 uentry_mergeUses (current, old);
2816 uentry_setState (old, current);
2820 uentry_mergeState (old, current, exprNode_loc (sw),
2821 mustReturn, FALSE, TRUE, SWITCHCLAUSE);
2828 } end_usymtab_entries;
2831 ** if entry is not in symbol table for this case, merge with pre-switch
2835 if (!mustReturn && !mustBreak)
2837 usymtab_entries (stab, current)
2839 if (usymtab_getIndex (ttab, uentry_rawName (current)) == NOT_FOUND)
2841 uentry old = /*@-compmempass@*/
2842 usymtab_lookupAux (ltab, uentry_rawName (current));
2845 llassert (uentry_isValid (old));
2846 uentry_mergeState (old, current, exprNode_loc (sw),
2847 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2849 } end_usymtab_entries;
2852 ltab->env = ttab->env;
2856 ** Suprious error, becuase of environments.
2859 /*@i1@*/ utab = ltab;
2861 lastMustReturn = FALSE;
2868 ** now, there is one US_CBRANCH. Merge this with the stab.
2872 for (i = 0; i < ltab->nentries; i++)
2874 uentry current = ltab->entries[i];
2875 uentry old = usymtab_lookupAux (stab, uentry_rawName (current));
2877 /* note that is this is in a nested branch,
2878 it may create a "new" old entry. */
2881 if (uentry_isValid (old))
2885 uentry_mergeUses (current, old);
2886 uentry_setState (old, current);
2890 uentry_mergeState (old, current, exprNode_loc (sw),
2891 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2905 ** switch may or may not be followed by a new scope
2908 if (utab->kind == US_SWITCH)
2910 usymtab_quietPlainExitScope ();
2914 usymtab_quietPlainExitScope ();
2915 llassert (utab->kind == US_SWITCH);
2916 usymtab_quietPlainExitScope ();
2922 updateNullState (sRef el, /*@notnull@*/ usymtab ttab,
2923 /*@notnull@*/ usymtab ftab, bool trueGuard)
2925 sRef base = sRef_getRootBase (el);
2926 int level = sRef_lexLevel (base);
2928 if (sRef_isCvar (base))
2930 usymId index = sRef_getScopeIndex (base);
2931 uentry ue = usymtab_getRefTab (ttab, level, index);
2933 if (!uentry_isLset (ue))
2935 sRef sr = uentry_getSref (ue);
2939 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2943 if (!guardSet_isGuarded (ttab->guards, el)
2944 && !sRef_isNotNull (sr))
2946 DPRINTF (("Here! %s / %s",
2947 sRef_unparseFull (sr),
2948 sRef_unparseFull (el)));
2949 sRef_setDerivNullState (sr, el, NS_DEFNULL);
2958 ue = usymtab_getRefTab (ftab, level, index);
2960 if (!uentry_isLset (ue))
2962 sRef sr = uentry_getSref (ue);
2964 if (!trueGuard) /* yikes! forgot the ! */
2966 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2971 if (!guardSet_isGuarded (ftab->guards, el)
2972 && !sRef_isNotNull (sr))
2974 sRef_setDerivNullState (sr, el, NS_DEFNULL);
2986 usymtab_popBranches (exprNode pred, exprNode tbranch, exprNode fbranch,
2987 bool isOpt, clause cl)
2991 usymtab ftab = utab;
2992 usymtab ttab = utab->env;
2996 guardSet guards = exprNode_getGuards (pred);
2997 sRefSet tguards = guardSet_getTrueGuards (guards);
2998 sRefSet fguards = guardSet_getFalseGuards (guards);
2999 bool mustReturnT = exprNode_mustEscape (tbranch);
3000 bool mustReturnF = exprNode_mustEscape (fbranch);
3002 DPRINTF (("Pop branches: %s [mustreturn: %s/%s]", exprNode_unparse (pred),
3003 bool_unparse (mustReturnT),
3004 bool_unparse (mustReturnF)));
3006 if (exprNode_isDefined (fbranch))
3008 loc = exprNode_loc (fbranch);
3012 loc = exprNode_loc (tbranch);
3015 llassert (usymtab_isDefined (ttab));
3019 llassert (usymtab_isDefined (env));
3020 llassert (ftab->kind == US_FBRANCH);
3021 llassert (ttab->kind == US_TBRANCH);
3024 ** For each element that is true guarded (i.e., if (x != NULL))
3025 ** make x = null in false branch,
3026 ** and x = notnull in true branch.
3027 ** unless x was set locally in that branch.
3028 ** For each element that is false guarded (x == NULL)
3029 ** make x = null in true, notnull in false.
3031 ** For each element that is either guarded (pred(x))
3035 sRefSet_allElements (tguards, el)
3037 updateNullState (el, ttab, ftab, TRUE);
3038 } end_sRefSet_allElements;
3040 sRefSet_allElements (fguards, el)
3042 updateNullState (el, ttab, ftab, FALSE);
3043 } end_sRefSet_allElements;
3047 ** if an entry is in both true and false, merge the entries,
3048 ** then replace original with new state.
3050 ** if an entry is in one table, merge it with the original.
3053 DPRINTF (("ftab: %d", ftab->nentries));
3055 for (i = 0; i < ftab->nentries; i++)
3057 uentry fthis = ftab->entries[i];
3058 uentry old = usymtab_lookupAux (env, uentry_rawName (fthis));
3059 int tindex = usymtab_getIndex (ttab, uentry_rawName (fthis));
3061 DPRINTF (("Entry: %s / %s", uentry_unparseFull (fthis), uentry_unparseFull (old)));
3063 if (uentry_isUndefined (old))
3065 /* possible entry was added as an undefined id */
3066 DPRINTF (("Undefined! %s", uentry_rawName (fthis)));
3070 if (tindex != NOT_FOUND)
3072 uentry tthis = ttab->entries[tindex];
3074 /* note that is this is in a nested branch,
3075 it may create a "new" old entry. */
3081 uentry_mergeState (fthis, tthis, loc,
3082 mustReturnT, FALSE, FALSE, cl);
3086 uentry_mergeUses (fthis, tthis);
3089 uentry_setState (old, fthis);
3096 uentry_setState (old, tthis);
3097 uentry_mergeState (old, fthis, loc, mustReturnF,
3101 ttab->entries[tindex] = uentry_undefined;
3102 uentry_free (tthis);
3106 uentry_mergeState (old, fthis, loc, mustReturnF, TRUE, FALSE, cl);
3110 for (i = 0; i < ttab->nentries; i++)
3112 uentry current = ttab->entries[i];
3114 DPRINTF (("ttab: %s", uentry_unparseFull (current)));
3116 if (!uentry_isUndefined (current))
3118 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
3120 DPRINTF (("Old: %s", uentry_unparseFull (old)));
3122 if (uentry_isUndefined (old))
3124 llcontbug (message ("Undefined entry: %s", uentry_rawName (current)));
3130 uentry_mergeUses (current, old);
3131 uentry_setState (old, current);
3136 ** Assumes false branch is a fall-through if
3137 ** fbranch is not defined. This is true, unless
3138 ** where was some greivous error in processing
3139 ** the else branch of an if-then, in which case
3140 ** this is probably the right thing to do anyway.
3143 uentry_mergeState (old, current, loc, mustReturnT,
3147 DPRINTF (("==> %s", uentry_unparseFull (old)));
3152 ** Plain levelUnion doesn't work, since we need to use the sRef's in env->aliases
3153 ** if they are present.
3156 llassert (NOALIAS (env->aliases, ttab->aliases));
3157 llassert (NOALIAS (env->aliases, ftab->aliases));
3159 aliasTable_free (env->aliases);
3161 env->aliases = aliasTable_levelUnionNew (ttab->aliases,
3162 ftab->aliases, env->lexlevel);
3164 aliasTable_fixSrefs (env->aliases);
3166 DPRINTF (("Aliases: %s", aliasTable_unparse (env->aliases)));
3168 /* exit true and false scopes */
3169 usymtab_quietPlainExitScope ();
3170 usymtab_quietPlainExitScope ();
3174 utab->guards = guardSet_levelUnionFree
3176 guardSet_invert (exprNode_getGuards (pred)),
3182 utab->guards = guardSet_levelUnion (utab->guards,
3183 exprNode_getGuards (pred),
3187 DPRINTF (("Here."));
3190 static void usymtab_fixCases (void) /*@modifies utab@*/ {
3191 while (utab->kind == US_CBRANCH)
3193 usymtab_quietPlainExitScope ();
3196 llassert (utab->kind != US_CBRANCH);
3200 usymtab_altBranch (/*@only@*/ guardSet guards)
3204 usymtab parent = utab->env;
3206 t = usymtab_create (US_FBRANCH, utab, FALSE);
3209 ** If we are in a case, need to close it. The C syntax
3210 ** is very liberal, so this kludge is necessary.
3213 usymtab_fixCases ();
3215 DPRINTF (("Current kind: %s", usymtab_unparseStack ()));
3217 llassert (utab->kind == US_TBRANCH);
3218 llassert (parent != GLOBAL_ENV);
3220 guardSet_free (t->guards);
3223 aliasTable_free (t->aliases);
3224 t->aliases = aliasTable_copy (parent->aliases);
3230 usymtab_allDefined (void)
3231 /*@globals utab, globtab@*/
3235 llassert (utab == globtab);
3237 for (i = 0; i < utab->nentries; i++)
3239 uentry e = utab->entries[i];
3241 if (uentry_isPriv (e))
3243 ; /* no need to define it */
3247 if (context_getFlag (FLG_SPECUNDECL))
3249 fileloc sloc = uentry_whereSpecified (e);
3250 fileloc dloc = uentry_whereDeclared (e);
3252 if (fileloc_isDefined (sloc)
3253 && !uentry_isFakeTag (e)
3254 && !fileloc_isDefined (dloc))
3258 message ("%s %q specified but not declared",
3259 ekind_capName (uentry_getKind (e)),
3260 uentry_getName (e)),
3265 if (!uentry_isCodeDefined (e))
3267 fileloc dloc = uentry_whereDeclared (e);
3269 if (fileloc_isLib (dloc) || fileloc_isXHFile (dloc))
3273 else if (fileloc_isDefined (dloc))
3275 if (!uentry_isAnyTag (e))
3277 if (fileloc_isUser (dloc))
3281 message ("%s %q declared but not defined",
3282 ekind_capName (uentry_getKind (e)),
3283 uentry_getName (e)),
3285 DPRINTF (("decl: %s", uentry_unparseFull (e)));
3291 fileloc sloc = uentry_whereSpecified (e);
3293 if (fileloc_isDefined (sloc)
3294 && !fileloc_isImport (sloc)
3295 && !fileloc_isLib (sloc)
3296 && !fileloc_isPreproc (sloc)
3297 && !uentry_isFakeTag (e))
3299 if (uentry_isVariable (e) || uentry_isFunction (e))
3303 message ("%s %q specified but not declared or defined",
3304 ekind_capName (uentry_getKind (e)),
3305 uentry_getName (e)),
3312 message ("%s %q specified but not defined",
3313 ekind_capName (uentry_getKind (e)),
3314 uentry_getName (e)),
3324 void usymtab_exportHeader (void)
3329 for (i = 0; i < utab->nentries; i++)
3331 uentry ce = utab->entries[i];
3333 if (!uentry_isDatatype (ce)
3334 && !uentry_isAnyTag (ce)
3335 && !uentry_isEitherConstant (ce) && !uentry_isStatic (ce)
3336 && !uentry_isExternal (ce)
3337 && !uentry_isForward (ce))
3339 fileloc fwhere = uentry_whereDeclared (ce);
3341 if (fileloc_isUndefined (fwhere)
3342 && uentry_isFunction (ce))
3344 fwhere = uentry_whereDefined (ce);
3347 if (fileloc_isDefined (fwhere)
3348 && !fileloc_isHeader (fwhere)
3349 && !fileloc_isXHFile (fwhere)
3350 && !(fileloc_isSpecialFile (fwhere)
3351 && !context_getFlag (FLG_UNUSEDSPECIAL)))
3353 if (uentry_isVariable (ce))
3356 (FLG_EXPORTHEADERVAR,
3357 message ("%s %q exported but not declared in header file",
3358 ekind_capName (uentry_getKind (ce)),
3359 uentry_getName (ce)),
3362 uentry_showDefSpecInfo (ce, fwhere);
3367 if (!uentry_isIter (ce)
3368 && !uentry_isEndIter (ce)
3369 && !uentry_isExpandedMacro (ce))
3371 if (uentry_isFunction (ce)
3372 && cstring_equalLit (uentry_rawName (ce), "main"))
3374 ; /* no error for main */
3380 message ("%s %q exported but not declared "
3382 ekind_capName (uentry_getKind (ce)),
3383 uentry_getName (ce)),
3386 uentry_showDefSpecInfo (ce, fwhere);
3396 void usymtab_exportLocal (void)
3401 for (i = 0; i < utab->nentries; i++)
3403 uentry ce = utab->entries[i];
3405 if (!uentry_isDatatype (ce) && !uentry_isAnyTag (ce)
3406 && !uentry_isEitherConstant (ce)
3407 && !uentry_isIter (ce)
3408 && !uentry_isEndIter (ce)
3409 && !uentry_isExpandedMacro (ce)
3410 && uentry_isUsed (ce))
3412 /* check static uses */
3413 filelocList fuses = uentry_getUses (ce);
3414 fileloc mod = uentry_whereDefined (ce);
3415 bool ok = filelocList_isEmpty (fuses);
3416 fileloc fwhere = uentry_whereDeclared (ce);
3418 if (fileloc_isSpecialFile (fwhere)
3419 && !context_getFlag (FLG_UNUSEDSPECIAL))
3421 ok = TRUE; /* no errors for special files */
3425 filelocList_elements (fuses, uloc)
3427 if (fileloc_isUndefined (uloc) || !fileloc_sameModule (uloc, mod))
3430 /*@innerbreak@*/ break;
3432 } end_filelocList_elements;
3439 message ("%s exported but not used outside %s: %q",
3440 ekind_capName (uentry_getKind (ce)),
3441 fileloc_getBase (mod),
3442 uentry_getName (ce)),
3445 uentry_showDefSpecInfo (ce, fwhere);
3453 usymtab_allUsed (void)
3457 bool isFileStatic = usymtab_inFileScope ();
3458 cstring last_file = cstring_undefined;
3460 for (i = 0; i < utab->nentries; i++)
3462 bool hasError = FALSE;
3463 uentry ce = utab->entries[i];
3464 fileloc fwhere = uentry_whereDeclared (ce);
3466 if (fileloc_isUndefined (fwhere))
3468 fwhere = uentry_whereDefined (ce);
3471 if (fileloc_isInvalid (fwhere)
3472 || fileloc_isLib (fwhere)
3473 || fileloc_isBuiltin (fwhere)
3474 || ((fileloc_isSpecialFile (fwhere)
3475 || fileloc_isSpecialFile (uentry_whereDefined (ce)))
3476 && !context_getFlag (FLG_UNUSEDSPECIAL)))
3480 else if (!uentry_wasUsed (ce) && !uentry_isAnyTag (ce))
3482 cstring fname = fileloc_filename (fwhere);
3484 if (cstring_isUndefined (last_file))
3488 else if (cstring_equal (fname, last_file))
3497 if (uentry_isParam (ce))
3499 if (context_inMacro ())
3501 sRef cref = uentry_getSref (ce);
3503 if (uentry_isYield (ce))
3505 ; /* no checks (for now) */
3507 else if (sRef_isSafe (cref))
3513 if (uentry_hasRealName (ce))
3516 optgenerror (FLG_MACROPARAMS,
3517 message ("Macro parameter %q not used",
3518 uentry_getName (ce)),
3525 if (cstring_equalFree (uentry_getName (ce),
3526 cstring_makeLiteral ("...")))
3532 hasError = optgenerror (FLG_PARAMUNUSED,
3533 message ("Parameter %q not used",
3534 uentry_getName (ce)),
3539 else if (uentry_isFunction (ce) || uentry_isIter (ce))
3541 if (fileloc_isUser (fwhere))
3543 hasError = optgenerror
3545 message ("%q %q declared but not used",
3547 (uentry_isIter (ce) ? "Iterator"
3548 : (isFileStatic ? "File static function" : "Function")),
3549 uentry_getName (ce)),
3553 else if (uentry_isEndIter (ce))
3555 ; /* no error (already reported for iter */
3557 else if (uentry_isEnumConstant (ce))
3559 if (fileloc_isUser (fwhere))
3561 hasError = optgenerror
3563 message ("Enum member %q not used",
3564 uentry_getName (ce)),
3568 else if (uentry_isConstant (ce))
3570 if (fileloc_isUser (fwhere))
3572 hasError = optgenerror
3574 message ("Constant %q declared but not used",
3575 uentry_getName (ce)),
3579 else if (uentry_isDatatype (ce))
3581 if (fileloc_isUser (fwhere))
3583 hasError = optgenerror
3585 message ("Type %q declared but not used",
3586 uentry_getName (ce)),
3590 else if (!uentry_isRefParam (ce) && !uentry_isExpandedMacro (ce))
3591 { /* errors for ref params will be reported in the next scope */
3592 llassertprint (uentry_isVar (ce),
3593 ("ce: %s", uentry_unparseFull (ce)));
3595 if (ctype_isFunction (uentry_getType (ce)))
3597 if (fileloc_isUser (fwhere))
3599 hasError = optgenerror
3601 message ("%q %q declared but not used",
3603 (isFileStatic ? "File static function"
3605 uentry_getName (ce)),
3611 if (fileloc_isUser (fwhere))
3615 hasError = optgenerror
3617 message ("%q %q declared but not used",
3619 (isFileStatic ? "File static variable"
3621 uentry_getName (ce)),
3631 else if ((uentry_isDatatype (ce) || uentry_isAnyTag (ce)))
3632 { /* check all fields */
3633 ctype ct = uentry_getRealType (ce);
3636 while (ctype_isAP (ct))
3638 ct = ctype_getBaseType (ct);
3641 if (ctype_isSU (ct))
3643 uentryList fields = ctype_getFields (ct);
3645 uentryList_elements (fields, field)
3647 if (!uentry_isUsed (field))
3649 if (uentry_hasName (ce))
3651 hasError |= optgenerror
3653 message ("Field %q of %s %q declared but not used",
3654 uentry_getName (field),
3655 cstring_makeLiteralTemp
3656 (ctype_isStruct (ct) ? "structure" : "union"),
3657 uentry_getName (ce)),
3658 uentry_whereEarliest (field));
3664 ** Can't report these errors for unnamed structs.
3665 ** No way to tell when there are multiple consistent
3666 ** unnamed structure types. (Could go through table
3667 ** and mark them all unused...)
3669 hasError |= optgenerror
3671 message ("Field %q of unnamed %s declared but not used",
3672 uentry_getName (field),
3673 cstring_makeLiteralTemp
3674 (ctype_isStruct (ct) ? "structure" : "union")),
3675 uentry_whereEarliest (field));
3680 uentry_setUsed (field, fileloc_undefined);
3682 } end_uentryList_elements;
3692 if (uentry_isParam (ce) && context_inMacro ())
3694 if (fileloc_isDefined (uentry_whereSpecified (ce)))
3696 uentry_showWhereSpecified (ce);
3701 uentry_showDefSpecInfo (ce, fwhere);
3704 uentry_setUsed (ce, fileloc_undefined);
3710 checkGlobalReturn (uentry glob, sRef orig)
3712 sRef sr = uentry_getSref (glob);
3714 DPRINTF (("Check global return: %s / orig: %s / sr: %s",
3715 uentry_unparseFull (glob),
3716 sRef_unparseFull (orig),
3717 sRef_unparseFull (sr)));
3719 DPRINTF (("Is killed: %s", bool_unparse (sRef_isKilledGlob (orig))));
3721 if (context_getFlag (FLG_GLOBSTATE))
3723 DPRINTF (("Is killed: %s", sRef_unparseFull (orig)));
3725 if (sRef_isKilledGlob (orig))
3727 if (sRef_isStateUndefined (sr)
3728 || sRef_isUnuseable (sr)
3729 || sRef_isStateUnknown (sr)
3730 || sRef_isDead (sr))
3736 ctype ct = ctype_realType (uentry_getType (glob));
3738 DPRINTF (("Check global destroyed: %s", uentry_unparseFull (glob)));
3740 if (ctype_isVisiblySharable (ct))
3745 ("Killed global %q (type %s) not released before return",
3746 uentry_getName (glob),
3747 ctype_unparse (ct)),
3750 sRef_showStateInfo (sr);
3755 sRef_protectDerivs ();
3756 (void) transferChecks_globalDestroyed (sr, g_currentloc);
3757 sRef_clearProtectDerivs ();
3763 if (sRef_isStateUndefined (sr))
3765 if (optgenerror (FLG_GLOBSTATE,
3767 ("Function returns with global %q undefined",
3768 uentry_getName (glob)),
3771 sRef_showStateInfo (sr);
3776 if (sRef_isDead (sr) || sRef_isKept (sr))
3780 message ("Function returns with global %q "
3781 "referencing %s storage",
3782 uentry_getName (glob),
3783 cstring_makeLiteralTemp (sRef_isDead (sr) ? "released" : "kept")),
3786 if (sRef_isKept (sr))
3788 sRef_showAliasInfo (sr);
3792 sRef_showStateInfo (sr);
3795 sRef_setDefState (sr, SS_UNKNOWN, fileloc_undefined);
3799 if (ctype_isRealPointer (uentry_getType (glob))
3800 && sRef_possiblyNull (sr)
3801 && !uentry_possiblyNull (glob))
3805 message ("Function returns with non-null global %q "
3806 "referencing null storage",
3807 uentry_getName (glob)),
3810 sRef_showNullInfo (sr);
3815 DPRINTF (("Check transfer: %s", uentry_unparseFull (glob)));
3816 transferChecks_globalReturn (glob);
3824 ** remember: check alias globals
3827 void usymtab_checkFinalScope (bool isReturn)
3830 bool mustFree = context_getFlag (FLG_MUSTFREEONLY) || context_getFlag (FLG_MUSTFREEFRESH); /*@i423 remove this mustFree */
3831 bool mustDefine = context_getFlag (FLG_MUSTDEFINE);
3832 /* bool mustNotAlias = context_getFlag (FLG_MUSTNOTALIAS); */
3833 sRefSet checked = sRefSet_new ();
3834 usymtab stab = utab;
3838 ** need to check all scopes out to function parameters.
3843 for (i = 0; i < stab->nentries; i++)
3845 uentry ce = stab->entries[i];
3846 sRef sr = uentry_getSref (ce);
3847 sRef rb = sRef_getRootBase (sr);
3851 ** Shouldn't check if shadow checked in deeper scope:
3856 uentry oue = usymtab_lookupQuietNoAlt (utab, uentry_observeRealName (ce));
3858 if (!uentry_sameObject (ce, oue))
3860 DPRINTF (("Skipping outer entry: %s / %s", uentry_unparseFull (ce),
3861 uentry_unparseFull (oue)));
3862 /*@i32 what if it is one an alternate branch? */
3863 /*@innercontinue@*/ continue;
3867 DPRINTF (("Here check final scope: %s", uentry_unparseFull (ce)));
3869 if (ctype_isFunction (uentry_getType (ce)))
3871 /*@innercontinue@*/ continue;
3874 if (uentry_isAnyParam (ce)
3875 || uentry_isRefParam (ce)
3876 || sRef_isFileOrGlobalScope (rb))
3878 /* Don't do the loseref check...but should check state! */
3879 DPRINTF (("Skipping check 1"));
3881 else if (sRef_isDefinitelyNull (sr)
3882 || usymtab_isDefinitelyNull (sr))
3885 ** No state reference errors for definitely null references.
3888 DPRINTF (("Skipping check 2"));
3892 DPRINTF (("Lose ref: %s / %s", uentry_unparse (ce),
3893 sRef_unparseFull (sr)));
3895 tvalues = sRef_getValueTable (sr);
3897 valueTable_elements (tvalues, fkey, fval) {
3898 metaStateInfo minfo;
3899 cstring msg = cstring_undefined;
3902 minfo = context_lookupMetaStateInfo (fkey);
3903 llassert (metaStateInfo_isDefined (minfo));
3905 if (stateValue_isError (fval)
3906 || sRef_isStateUndefined (sr)) /* No errors for undefined state */
3908 DPRINTF (("Skipping check 3"));
3912 DPRINTF (("Check: %s / %s / %s", fkey,
3913 metaStateInfo_unparse (minfo),
3914 stateValue_unparse (fval)));
3916 minfo = context_lookupMetaStateInfo (fkey);
3918 nval = stateCombinationTable_lookupLoseReference
3919 (metaStateInfo_getTransferTable (minfo),
3920 stateValue_getValue (fval), &msg);
3922 if (cstring_isDefined (msg))
3924 /*@i32 print extra info for assignments@*/
3925 DPRINTF (("From: %s", sRef_unparseFull (sr)));
3926 DPRINTF (("Null? %s / %s",
3927 bool_unparse (sRef_isDefinitelyNull (sr)),
3928 bool_unparse (usymtab_isGuarded (sr))));
3933 ("%s loses reference %q in invalid state %q (%s)",
3934 cstring_makeLiteralTemp (isReturn ? "Return" : "Scope exit"),
3935 uentry_getName (ce),
3936 stateValue_unparseValue (fval, minfo),
3940 stateValue_show (fval, minfo);
3944 DPRINTF (("Suppressed transfer error: %s", msg));
3948 } end_valueTable_elements;
3951 DPRINTF (("Here 1"));
3955 DPRINTF (("Check mustfree entry: %s", uentry_unparseFull (ce)));
3957 if (!sRefSet_member (checked, sr) && !sRef_isFileOrGlobalScope (rb))
3959 if (ctype_isRealSU (uentry_getType (ce))
3960 && !uentry_isAnyParam (ce)
3961 && !uentry_isRefParam (ce)
3962 && !uentry_isStatic (ce)
3963 && !sRef_isDependent (sr)
3964 && !sRef_isOwned (sr))
3966 sRefSet als = usymtab_allAliases (sr);
3968 if (sRefSet_isEmpty (als))
3970 transferChecks_localDestroyed (sr, g_currentloc);
3974 /* aliased, no problem */ ;
3980 (!uentry_isStatic (ce)
3981 && ((sRef_isNewRef (sr))
3982 || (((sRef_isOnly (sr) || sRef_isFresh (sr)
3983 || sRef_isKeep (sr) || sRef_isOwned (sr))
3984 && !sRef_isDead (sr))
3985 && (!sRef_definitelyNull (sr))
3986 && (!usymtab_isDefinitelyNull (sr)))))
3988 bool hasError = TRUE;
3990 DPRINTF (("Checking: %s", sRef_unparseFull (sr)));
3993 ** If its a scope exit, check if there is an alias.
3994 ** If so, make it only. If not, there is an error.
3999 if (transferChecks_canLoseReference (sr, g_currentloc))
4001 DPRINTF (("Can lose!"));
4008 if (sRef_hasLastReference (sr))
4010 sRef ar = sRef_getAliasInfoRef (sr);
4013 (sRef_isFresh (ar) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4015 ("Last reference %q to %s storage %qnot %q before %q",
4017 alkind_unparse (sRef_getAliasKind (sr)),
4018 sRef_unparseOpt (ar),
4019 cstring_makeLiteral (sRef_isKeep (sr)
4020 ? "transferred" : "released"),
4021 cstring_makeLiteral (isReturn
4022 ? "return" : "scope exit")),
4025 sRef_showRefLost (sr);
4028 else if (sRef_isNewRef (sr))
4031 (sRef_isFresh (sr) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4033 ("%q %q not released before %q",
4035 (alkind_isKillRef (sRef_getOrigAliasKind (sr))
4036 ? "Kill reference parameter" : "New reference"),
4037 uentry_getName (ce),
4038 cstring_makeLiteral (isReturn
4039 ? "return" : "scope exit")),
4042 sRef_showAliasInfo (sr);
4047 if (ctype_isRealSU (sRef_getType (sr)))
4049 transferChecks_structDestroyed (sr, g_currentloc);
4053 DPRINTF (("Here we are: %s", sRef_unparseFull (sr)));
4056 (sRef_isFresh (sr) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4058 ("%s storage %q not %q before %q",
4059 alkind_capName (sRef_getAliasKind (sr)),
4060 uentry_getName (ce),
4061 cstring_makeLiteral (sRef_isKeep (sr)
4062 ? "transferred" : "released"),
4063 cstring_makeLiteral (isReturn
4064 ? "return" : "scope exit")),
4067 sRef_showAliasInfo (sr);
4068 DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
4081 if (mustDefine && uentry_isOut (ce))
4083 /* No error if its dead (either only or error already reported */
4084 if (!sRef_isReallyDefined (sr) && !sRef_isDead (sr))
4088 message ("Out storage %q not defined before %q",
4089 uentry_getName (ce),
4091 (isReturn ? "return" : "scope exit")),
4094 DPRINTF (("sr: %s", sRef_unparseFull (sr)));
4099 ** also check state is okay
4102 if (usymtab_lexicalLevel () > functionScope
4103 && uentry_isVariable (ce)
4104 && (sRef_isLocalVar (sr)
4105 && (sRef_isDependent (sr) || sRef_isLocalState (sr))))
4107 sRefSet ab = usymtab_aliasedBy (sr);
4109 /* should do something more efficient here */
4111 if (sRefSet_isEmpty (ab))
4113 /* and no local ref */
4114 DPRINTF (("Check lose ref: %s", uentry_unparseFull (ce)));
4115 transferChecks_loseReference (ce);
4129 checked = sRefSet_insert (checked, sr);
4132 llassert (usymtab_isDefined (stab->env));
4134 if (usymtab_isBranch (stab))
4136 stab = usymtab_dropEnv (stab);
4143 llassert (stab != usymtab_undefined);
4144 } while (isReturn && (stab->lexlevel >= paramsScope));
4146 sRefSet_free (checked);
4150 ** all globals are appropriately defined
4151 ** all parameters are appropriately defined
4152 ** special clauses are followed
4155 if (isReturn || (utab->lexlevel == paramsScope))
4157 uentry fcn = context_getHeader ();
4158 uentryList params = context_getParams ();
4159 globSet uglobs = context_getUsedGlobs ();
4160 globSet sglobs = context_getGlobs ();
4162 if (isReturn && context_maybeSet (FLG_GLOBALIAS))
4164 aliasTable_checkGlobs (utab->aliases);
4168 ** state clauses (ensures, defines, sets, allocates, releases)
4171 if (uentry_hasStateClauseList (fcn))
4173 stateClauseList clauses = uentry_getStateClauseList (fcn);
4175 stateClauseList_elements (clauses, cl)
4177 if (stateClause_isAfter (cl) && !stateClause_isGlobal (cl))
4179 if (stateClause_setsMetaState (cl))
4181 sRefSet rfs = stateClause_getRefs (cl);
4182 qual q = stateClause_getMetaQual (cl);
4183 annotationInfo ainfo = qual_getAnnotationInfo (q);
4184 metaStateInfo minfo = annotationInfo_getState (ainfo);
4185 cstring key = metaStateInfo_getName (minfo);
4186 int mvalue = annotationInfo_getValue (ainfo);
4188 DPRINTF (("Post meta state clause: %s", stateClause_unparse (cl)));
4190 sRefSet_elements (rfs, el)
4192 sRef base = sRef_getRootBase (el);
4194 if (sRef_isResult (base))
4197 ** This is checked for return transfers.
4201 else if (sRef_isParam (base) || sRef_isGlobalMarker (base))
4203 sRef sr = sRef_updateSref (base);
4204 sr = sRef_fixBase (el, sr);
4206 if (!sRef_checkMetaStateValue (sr, key, mvalue))
4211 ("Ensures clause not satisfied%q (state is %q): %q",
4212 sRef_isGlobalMarker (sr)
4214 : message (" by %q", sRef_unparse (sr)),
4215 stateValue_unparseValue (sRef_getMetaStateValue (sr, key),
4217 stateClause_unparse (cl)),
4220 sRef_showMetaStateInfo (sr, key);
4226 if (sRef_isMeaningful (el))
4231 } end_sRefSet_elements ;
4235 /* evs - 2000 07 10 - added this */
4236 sRefTest tst = stateClause_getPostTestFunction (cl);
4237 sRefSet rfs = stateClause_getRefs (cl);
4239 sRefSet_elements (rfs, el)
4241 sRef base = sRef_getRootBase (el);
4243 if (sRef_isResult (base))
4246 ** This is checked for return transfers.
4251 else if (sRef_isParam (base))
4253 sRef sr = sRef_updateSref (base);
4254 sr = sRef_fixBase (el, sr);
4256 if (tst != NULL && !tst (sr))
4259 (stateClause_postErrorCode (cl),
4260 message ("%s storage %qcorresponds to "
4261 "storage listed in %q clause",
4262 stateClause_postErrorString (cl, sr),
4263 sRef_unparseOpt (sr),
4264 stateClause_unparseKind (cl)),
4267 sRefShower ss = stateClause_getPostTestShower (cl);
4274 DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
4280 if (sRef_isMeaningful (el))
4285 } end_sRefSet_elements ;
4288 } end_stateClauseList_elements ;
4292 ** check parameters on return
4295 uentryList_elements (params, arg)
4297 if (!uentry_isElipsisMarker (arg))
4299 ctype rt = ctype_realType (uentry_getType (arg));
4301 if (ctype_isMutable (rt) || ctype_isSU (rt))
4303 uentry param = usymtab_lookupQuiet (utab, uentry_rawName (arg));
4304 DPRINTF (("Check param return: %s", uentry_unparseFull (param)));
4305 transferChecks_paramReturn (param);
4308 } end_uentryList_elements;
4310 DPRINTF (("Check global return: %s",
4311 globSet_unparse (sglobs)));
4313 globSet_allElements (sglobs, el)
4315 sRef orig = el; /*! sRef_updateSref (el); */ /*!!!*/
4316 uentry current = sRef_getUentry (el);
4318 DPRINTF (("Check global return: %s / %s", sRef_unparseFull (el),
4319 uentry_unparseFull (current)));
4321 if (uentry_isVariable (current) && !uentry_isRealFunction (current))
4323 checkGlobalReturn (current, orig);
4325 } end_globSet_allElements;
4327 globSet_allElements (uglobs, el)
4329 if (!globSet_member (sglobs, el))
4331 uentry current = sRef_getUentry (el);
4333 if (uentry_isVariable (current)
4334 && !uentry_isRealFunction (current))
4336 checkGlobalReturn (current, sRef_undefined);
4339 } end_globSet_allElements;
4344 usymtab_quietExitScope (fileloc loc)
4345 /*@globals utab, globtab, filetab; @*/
4348 usymtab t = utab->env;
4350 DPRINTF (("Quiet exit scope [%p]", utab));
4352 if (utab->reftable != NULL)
4356 for (i = 0; i < utab->nentries; i++)
4358 uentry current = utab->entries[i];
4359 uentry old = usymtab_lookupAux (t, uentry_rawName (current));
4361 uentry_mergeState (old, current, loc, FALSE, FALSE, FALSE, NOCLAUSE);
4365 llassert (t != NULL);
4367 if (t->lexlevel > paramsScope)
4369 t->guards = guardSet_levelUnion (t->guards, utab->guards, t->lexlevel);
4370 t->aliases = aliasTable_levelUnionSeq (t->aliases, utab->aliases,
4372 utab->aliases = aliasTable_undefined;
4375 t->mustBreak = utab->mustBreak;
4376 t->exitCode = utab->exitCode;
4378 DPRINTF (("Free level [%p]", utab));
4379 usymtab_freeLevel (utab);
4384 usymtab_checkAllValid ();
4389 ** Exit a scope with no checking, lose alias states.
4390 ** (When should this be used?)
4393 void usymtab_quietPlainExitScope (void)
4394 /*@globals utab, globtab, filetab@*/
4397 usymtab t = utab->env;
4399 llassert (t != NULL);
4400 llassert (NOALIAS (utab->aliases, t->aliases));
4401 usymtab_freeLevel (utab);
4405 void usymtab_exitScope (exprNode expr)
4406 /*@globals utab, filetab, globtab@*/
4407 /*@modifies utab, globtab@*/
4409 usymtab ctab = usymtab_undefined;
4410 usymtab lctab = usymtab_undefined;
4411 bool mustReturn = exprNode_mustEscape (expr);
4413 DPRINTF (("Exit scope [%p]", utab));
4415 if (utab->kind == US_CBRANCH)
4418 ** save the case branches, remove the first non-cbranch
4423 while (utab->kind == US_CBRANCH)
4427 llassert (utab != GLOBAL_ENV);
4431 if (utab->kind == US_TBRANCH || utab->kind == US_FBRANCH
4432 || utab->kind == US_CBRANCH || utab->kind == US_SWITCH)
4434 if (context_inMacro ())
4436 /* evs 2000-07-25 */
4437 /* Unparseable macro may end inside nested scope. Deal with it. */
4439 llerror (FLG_SYNTAX,
4440 message ("Problem parsing macro body of %s (unbalanced scopes). "
4441 "Attempting to recover, recommend /*@notfunction@*/ before "
4442 "macro definition.",
4443 context_inFunctionName ()));
4445 while (utab->kind == US_TBRANCH
4446 || utab->kind == US_FBRANCH
4447 || utab->kind == US_CBRANCH
4448 || utab->kind == US_SWITCH)
4451 llassert (utab != GLOBAL_ENV);
4455 llcontbug (message ("exitScope: in branch: %q", usymtab_unparseStack ()));
4457 } /*@=branchstate@*/
4461 ** check all variables in scope were used
4465 ** bogus errors if this is the normal inside a switch,
4466 ** since cases have not been merged yet. Should probably
4467 ** still check this, but I'm too lazy at the moment...
4470 llassertfatal (utab->env != GLOBAL_ENV);
4472 if (utab->env->kind != US_SWITCH)
4478 ** check aliasing: all only params are released (dead)
4479 ** definition: all out params are defined, all modified params
4480 ** are completely defined
4482 ** NOTE: note for exiting paramsScope, since checkReturn should be
4486 if (!mustReturn && (usymtab_lexicalLevel () > functionScope))
4489 ** should only call this is end of scope is reachable...
4492 usymtab_checkFinalScope (FALSE);
4495 if (usymtab_lexicalLevel () == paramsScope && context_inFunctionLike ())
4498 ** leaving a function, need to fix up globals
4501 uentryList params = context_getParams ();
4502 globSet globs = context_getUsedGlobs ();
4504 uentryList_elements (params, ue)
4506 uentry_fixupSref (ue);
4507 } end_uentryList_elements;
4509 clearFunctionTypes ();
4511 DPRINTF (("Fixing up globals: %s", globSet_unparse (globs)));
4513 globSet_allElements (globs, el)
4515 DPRINTF (("Fix: %s", sRef_unparseDebug (el)));
4517 if (sRef_isCvar (el))
4520 int index = sRef_getScopeIndex (el);
4522 if (sRef_isFileStatic (el))
4524 llassert (usymtab_isDefined (filetab));
4525 current = usymtab_fetchIndex (filetab, index);
4529 current = usymtab_fetchIndex (globtab, index);
4532 if (uentry_isVariable (current))
4534 DPRINTF (("Fixup: %s", uentry_unparse (current)));
4535 uentry_fixupSref (current);
4539 DPRINTF (("Clear: %s", uentry_getSref (current)));
4540 sRef_clearDerived (uentry_getSref (current));
4544 sRef_clearDerived (el); /* evans 2002-03-14 - this is the likely source of many crashes! */
4545 } end_globSet_allElements;
4548 usymtab_quietExitScope (exprNode_loc (expr));
4550 if (lctab != usymtab_undefined)
4552 /*@i@*/ lctab->env = utab;
4553 /*@i@*/ utab = ctab;
4554 /*@-branchstate@*/ } /*@=branchstate@*/
4559 usymtab_checkAllValid ();
4565 ** yikes! don't let the '170 kids see this one...
4569 uentry_directParamNo (uentry ue)
4571 if (uentry_isVar (ue))
4573 sRef sr = uentry_getSref (ue);
4575 if (sRef_lexLevel (sr) == functionScope)
4577 int index = sRef_getScopeIndex (sr);
4579 if (index < uentryList_size (context_getParams ()))
4588 /*@dependent@*/ /*@exposed@*/ uentry
4589 usymtab_getParam (int paramno)
4593 ** requires in a function context (checked)
4595 ** depends on no nested functions --- the function
4596 ** parameters are ALWAYS one scope inside the global scope
4597 ** and entered in order!
4601 if (!context_inFunctionLike ())
4602 llfatalbug (message ("usymtab_getParam: not in function context: %q",
4603 context_unparse ()));
4605 while (s->lexlevel > paramsScope)
4610 llassert (usymtab_isDefined (s));
4612 if (paramno >= s->nentries)
4615 ** Parse errors lead to this.
4618 uentry err = uentry_makeVariableLoc (cstring_makeLiteralTemp ("<error>"),
4621 uentry_markOwned (err);
4625 return (s->entries[paramno]);
4628 static /*@dependent@*/ /*@exposed@*/ uentry
4629 usymtab_getRefTab (/*@notnull@*/ usymtab u, int level, usymId index)
4633 ue = usymtab_getRefNoisy (u, level, index);
4635 if (uentry_isUndefined (ue))
4637 llbug (message ("usymtab_getRef: out of range: %d. level = %d",
4644 static /*@dependent@*/ /*@exposed@*/ usymtab
4645 usymtab_dropEnv (/*@notnull@*/ usymtab s)
4647 if (s->kind == US_CBRANCH)
4655 llassert (s != GLOBAL_ENV);
4656 } while (s->kind == US_CBRANCH);
4657 /* drop all cases (except in nested scopes */
4660 llassert (s != GLOBAL_ENV);
4663 if (s->kind == US_FBRANCH)
4665 s = s->env; /* skip the true branch */
4666 llassert (usymtab_isDefined (s));
4667 llassert (s->kind == US_TBRANCH);
4670 llassert (s != GLOBAL_ENV);
4676 /*@dependent@*/ /*@exposed@*/ uentry
4677 usymtab_getRefQuiet (int level, usymId index)
4683 llassert (s != NULL);
4684 llassert (index >= 0);
4686 if (level > s->lexlevel)
4688 return uentry_undefined;
4691 llassertprint (level <= s->lexlevel, ("level: %d / lexlevel: %d",
4692 level, s->lexlevel));
4694 while (s->lexlevel > level)
4696 if (usymtab_isBranch (s))
4698 int eindex = refTable_lookup (s, level, index);
4700 if (eindex != NOT_FOUND)
4702 return (s->entries[eindex]);
4706 s = usymtab_dropEnv (s);
4709 while (usymtab_isBranch (s) && s->lexlevel == level)
4711 int eindex = refTable_lookup (s, level, index);
4713 if (eindex != NOT_FOUND)
4715 return (s->entries[eindex]);
4718 s = usymtab_dropEnv (s);
4721 if (index >= s->nentries)
4723 return uentry_undefined;
4726 llassert (!uentry_isUndefined (s->entries[index]));
4728 return s->entries[index];
4731 static /*@dependent@*/ /*@exposed@*/ uentry
4732 usymtab_getRefNoisy (/*@notnull@*/ usymtab s, int level, usymId index)
4735 uentry ue = uentry_undefined;
4737 llassert (index >= 0);
4739 while (s->lexlevel > level)
4741 if (usymtab_isBranch (s))
4743 int eindex = refTable_lookup (s, level, index);
4745 if (eindex != NOT_FOUND)
4747 ue = s->entries[eindex];
4751 while (!usymtab_isBranch (otab))
4753 otab = usymtab_dropEnv (otab);
4754 llassert (otab != GLOBAL_ENV);
4757 if (refTable_lookup (otab, level, index) == NOT_FOUND)
4759 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4771 s = usymtab_dropEnv (s);
4774 llassert (usymtab_isDefined (s));
4776 while (usymtab_isBranch (s) && s->lexlevel == level)
4778 int eindex = refTable_lookup (s, level, index);
4781 if (eindex != NOT_FOUND)
4783 ue = s->entries[eindex];
4787 while (!usymtab_isBranch (otab))
4789 otab = usymtab_dropEnv (otab);
4790 llassert (otab != GLOBAL_ENV);
4793 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4803 s = usymtab_dropEnv (s);
4806 if (s->lexlevel == level && (index < s->nentries))
4808 ue = s->entries[index];
4810 if (uentry_isValid (ue))
4814 while (!usymtab_isBranch (otab))
4816 otab = usymtab_dropEnv (otab);
4818 if (otab == GLOBAL_ENV)
4824 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4835 if (index >= s->nentries)
4837 return uentry_undefined;
4840 llassert (!uentry_isUndefined (s->entries[index]));
4842 return s->entries[index];
4846 ** looking up entries
4848 ** If entry is inside a branch, then copy it, and put it into
4849 ** the branch table.
4853 int refTable_lookup (/*@notnull@*/ usymtab ut, int level, int index)
4855 refTable rt = ut->reftable;
4858 llassert (rt != NULL);
4860 for (i = 0; i < ut->nentries; i++)
4862 if (rt[i]->level == level && rt[i]->index == index)
4872 /*@only@*/ refentry refentry_create (int level, int index)
4874 refentry r = (refentry) dmalloc (sizeof (*r));
4882 static /*@dependent@*/ /*@exposed@*/ uentry
4883 usymtab_addRefEntry (/*@notnull@*/ usymtab s, cstring k)
4888 if (ut->reftable == NULL)
4890 DPRINTF (("Adding ref entry without reftable: %s", k));
4891 return uentry_undefined;
4894 llassert (ut->reftable != NULL);
4896 while (s != GLOBAL_ENV)
4898 eindex = usymtab_getIndex (s, k);
4900 if (eindex != NOT_FOUND)
4902 uentry current = s->entries[eindex];
4904 if (uentry_isVar (current) && !ctype_isFunction (uentry_getType (current)))
4908 DPRINTF (("Here: copying %s", uentry_unparse (current)));
4909 if (uentry_isNonLocal (current))
4911 ue = uentry_copy (current);
4915 ue = uentry_copyNoSave (current);
4918 DPRINTF (("Here: copying %s", uentry_unparse (ue)));
4919 usymtab_addEntryQuiet (ut, ue);
4920 DPRINTF (("Okay..."));
4922 if (s->reftable != NULL)
4924 refentry ref = s->reftable[eindex];
4926 ut->reftable[ut->nentries - 1]
4927 = refentry_create (ref->level, ref->index);
4931 ut->reftable[ut->nentries - 1]
4932 = refentry_create (s->lexlevel, eindex);
4943 s = usymtab_dropEnv (s);
4946 return uentry_undefined;
4949 static uentry usymtab_lookupAux (usymtab s, cstring k)
4951 DPRINTF (("Lookup: %s", k));
4953 while (s != GLOBAL_ENV)
4955 int eindex = usymtab_getIndex (s, k);
4957 if (eindex != NOT_FOUND)
4959 uentry ret = s->entries[eindex];
4963 if (s->kind == US_TBRANCH
4964 || s->kind == US_FBRANCH
4965 || s->kind == US_CBRANCH)
4966 /* uentry_isGlobalVariable (ret) && os->lexlevel > fileScope) */
4969 DPRINTF (("Adding global ref entry: %s", k));
4970 ret = usymtab_addRefEntry (os, k);
4971 DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
4976 DPRINTF (("Found: %s", uentry_unparseFull (ret)));
4980 if (s->kind == US_TBRANCH || s->kind == US_FBRANCH
4981 || s->kind == US_CBRANCH)
4983 /* why isn't this os??? */
4984 uentry ret = usymtab_addRefEntry (s, k);
4985 DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
4992 return uentry_undefined;
4995 static /*@dependent@*/ /*@exposed@*/ uentry
4996 usymtab_lookupQuietAux (usymtab s, cstring k, bool noalt)
5000 while (s != GLOBAL_ENV)
5002 eindex = usymtab_getIndex (s, k);
5004 if (eindex != NOT_FOUND)
5006 uentry ret = s->entries[eindex];
5010 if (noalt && usymtab_isBranch (s))
5012 s = usymtab_dropEnv (s);
5016 llassert (s != NULL); /*@i523 should not need this? */
5021 return uentry_undefined;
5024 static /*@exposed@*/ /*@dependent@*/ uentry
5025 usymtab_lookupQuiet (usymtab s, cstring k)
5027 return usymtab_lookupQuietAux (s, k, FALSE);
5030 static /*@exposed@*/ /*@dependent@*/ uentry
5031 usymtab_lookupQuietNoAlt (usymtab s, cstring k)
5033 return usymtab_lookupQuietAux (s, k, TRUE);
5036 /*@dependent@*/ /*@observer@*/ uentry
5037 usymtab_lookupSafe (cstring k)
5040 DPRINTF (("Lookup safe: %s", k));
5041 return (usymtab_lookupAux (utab, k));
5045 usymtab_lookupExpose (cstring k)
5048 uentry ce = usymtab_lookupAux (utab, k);
5050 if (uentry_isUndefined (ce))
5052 llfatalbug (message ("usymtab_lookup: not found: *%s*", k));
5055 if (uentry_isPriv (ce))
5057 llfatalbug (message ("usymtab_lookup: private: *%s*", k));
5063 uentry usymtab_lookupExposeGlob (cstring k)
5065 return (usymtab_lookupGlobSafe (k));
5068 uentry usymtab_lookupGlob (cstring k)
5069 /*@globals globtab@*/
5071 uentry ce = usymtab_lookupAux (globtab, k);
5073 if (uentry_isUndefined (ce))
5074 llfatalbug (message ("usymtab_lookup: not found: %s", k));
5076 if (uentry_isPriv (ce))
5077 llfatalbug (message ("usymtab_lookup: private: %s", k));
5079 DPRINTF (("Lookup global: %s", uentry_unparseFull (ce)));
5083 /*@observer@*/ uentry
5084 usymtab_lookupGlobSafe (cstring k)
5085 /*@globals globtab@*/
5087 uentry ce = usymtab_lookupAux (globtab, k);
5088 DPRINTF (("Lookup global: %s", uentry_unparseFull (ce)));
5092 uentry usymtab_lookupEither (cstring k)
5095 uentry ce = usymtab_lookupSafe (k);
5097 if (uentry_isUndefined (ce))
5098 llfatalerror (message ("usymtab_lookup: not found: %s", k));
5100 DPRINTF (("Lookup either: %s", uentry_unparseFull (ce)));
5105 usymtab_lookupType (cstring k)
5106 /*@globals globtab@*/
5108 usymId uid = usymtab_getTypeId (k);
5110 if (uid == USYMIDINVALID)
5112 llcontbug (message ("usymtab_lookupType: not found: %s", k));
5113 return ctype_unknown;
5116 return (uentry_getRealType (usymtab_getTypeEntry (uid)));
5120 usymtab_lookupAbstractType (cstring k) /*@globals globtab@*/
5122 usymId uid = usymtab_getTypeId (k);
5124 if (uid == USYMIDINVALID)
5126 llcontbug (message ("usymtab_lookupType: not found: %s", k));
5127 return ctype_unknown;
5130 return (uentry_getAbstractType (usymtab_getTypeEntry (uid)));
5134 ** if there is an unnamed lcl-specified struct tag matching
5135 ** the uentryList, return its datatype. Otherwise, returns
5140 usymtab_structFieldsType (uentryList f)
5141 /*@globals globtab@*/
5143 return (usymtab_suFieldsType (f, TRUE));
5147 usymtab_unionFieldsType (uentryList f)
5148 /*@globals globtab@*/
5150 return (usymtab_suFieldsType (f, FALSE));
5154 usymtab_suFieldsType (uentryList f, bool isStruct)
5155 /*@globals globtab@*/
5159 DPRINTF (("Fields: %s", uentryList_unparse (f)));
5161 if (fileloc_isSpec (g_currentloc))
5163 return (ctype_undefined);
5166 for (i = 0; i < globtab->nentries; i++)
5168 uentry current = globtab->entries[i];
5171 ? uentry_isStructTag (current) : uentry_isUnionTag (current)))
5173 if (isFakeTag (uentry_rawName (current)))
5175 ctype ct = uentry_getType (current);
5177 DPRINTF (("Check: %s", ctype_unparse (ct)));
5179 if ((isStruct ? ctype_isStruct (ct) : ctype_isUnion (ct))
5181 (uentry_isSpecified (current)
5182 && uentryList_equivFields (f, ctype_getFields (ct))))
5184 return uentry_getAbstractType (current);
5194 return ctype_undefined;
5198 usymtab_enumEnumNameListType (enumNameList f)
5199 /*@globals globtab@*/
5203 for (i = 0; i < globtab->nentries; i++)
5205 uentry current = globtab->entries[i];
5207 if (uentry_isEnumTag (current))
5209 if (isFakeTag (uentry_rawName (current)))
5211 ctype ct = uentry_getType (current);
5213 if (ctype_isEnum (ct) && (enumNameList_match (f, ctype_elist (ct))))
5215 return uentry_getType (current);
5221 return ctype_undefined;
5225 usymtab_exists (cstring k)
5228 uentry ce = usymtab_lookupSafe (k);
5229 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5233 usymtab_existsReal (cstring k)
5236 uentry ce = usymtab_lookupSafe (k);
5238 return (!(uentry_isUndefined (ce))
5239 && !(uentry_isPriv (ce))
5240 && !(uentry_isExpandedMacro (ce)));
5244 usymtab_existsGlob (cstring k)
5245 /*@globals globtab@*/
5247 uentry ce = usymtab_lookupAux (globtab, k);
5249 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5253 usymtab_existsEither (cstring k)
5256 uentry ce = usymtab_lookupAux (utab, k);
5258 return (uentry_isValid (ce));
5262 usymtab_existsGlobEither (cstring k)
5263 /*@globals globtab@*/
5265 uentry ce = usymtab_lookupAux (globtab, k);
5267 return (uentry_isValid (ce));
5271 usymtab_existsType (cstring k)
5272 /*@globals globtab@*/
5274 uentry ce = usymtab_lookupAux (globtab, k);
5276 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && uentry_isDatatype (ce));
5280 usymtab_existsTypeEither (cstring k)
5281 /*@globals globtab@*/
5284 ce = usymtab_lookupAux (globtab, k);
5285 return (uentry_isValid (ce) && uentry_isDatatype (ce));
5289 usymtab_existsStructTag (cstring k) /*@globals globtab@*/
5291 cstring sname = makeStruct (k);
5292 uentry ce = usymtab_lookupAux (globtab, sname);
5293 cstring_free (sname);
5294 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5298 usymtab_existsUnionTag (cstring k) /*@globals globtab@*/
5300 cstring uname = makeUnion (k);
5301 uentry ce = usymtab_lookupAux (globtab, uname);
5303 cstring_free (uname);
5305 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5309 usymtab_existsEnumTag (cstring k) /*@globals globtab@*/
5311 cstring ename = makeEnum (k);
5312 uentry ce = usymtab_lookupAux (globtab, ename);
5314 cstring_free (ename);
5315 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5318 bool usymtab_existsVar (cstring k)
5321 uentry ce = usymtab_lookupSafe (k);
5323 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && (uentry_isVar (ce)));
5331 refTable_free (/*@only@*/ /*@null@*/ refTable x, int nentries)
5337 for (i = 0; i < nentries; i++)
5347 usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab u)
5348 /*@globals globtab, utab, filetab@*/
5352 DPRINTF (("Free level [%p]", u));
5353 aliasTable_free (u->aliases);
5355 refTable_free (u->reftable, u->nentries);
5357 if (u == filetab || u == globtab)
5359 for (i = 0; i < u->nentries; i++)
5361 DPRINTF (("Free complete: %d", i));
5362 DPRINTF (("Uentry: %s", uentry_unparse (u->entries[i])));
5363 uentry_freeComplete (u->entries[i]);
5364 u->entries[i] = uentry_undefined;
5369 for (i = 0; i < u->nentries; i++)
5371 uentry_free (u->entries[i]);
5372 u->entries[i] = uentry_undefined;
5376 guardSet_free (u->guards);
5383 llassert (!cstringTable_isDefined (u->htable));
5386 sfree (u); /* evans 2002-07-12: was inside if */
5391 usymtab_freeAux (/*@only@*/ usymtab u)
5392 /*@globals globtab, utab, filetab@*/
5395 while (u != GLOBAL_ENV)
5398 usymtab_freeLevel (u);
5405 void usymtab_free ()
5406 /*@globals killed utab, globtab, filetab@*/
5410 usymtab_freeAux (utab);
5411 utab = usymtab_undefined;
5414 static int usymtab_lexicalLevel (void) /*@globals utab@*/
5416 return (utab->lexlevel);
5419 bool usymtab_inGlobalScope () /*@globals utab, globtab@*/
5421 return (utab == globtab);
5424 bool usymtab_inFileScope () /*@globals utab@*/
5426 return (utab->lexlevel == fileScope);
5429 bool usymtab_inFunctionScope () /*@globals utab@*/
5431 return (utab->lexlevel == functionScope);
5435 usymtab_replaceEntry (uentry s)
5436 /*@globals utab, globtab@*/
5437 /*@modifies utab, s@*/
5439 usymtab_replaceEntryAux (utab, s);
5443 usymtab_matchForwardStruct (usymId u1, usymId u2)
5444 /*@globals globtab@*/
5446 uentry ue1 = usymtab_getTypeEntry (u1);
5447 uentry ue2 = usymtab_getTypeEntry (u2);
5449 if (uentry_isAnyTag (ue2))
5451 ctype reptype = uentry_getType (ue1);
5453 if (ctype_isPointer (reptype))
5455 ctype repbase = ctype_getBaseType (reptype);
5457 if (ctype_isUA (repbase))
5459 typeId rtuid = ctype_typeId (repbase);
5461 if (u2 == rtuid) return TRUE;
5463 if (usymId_isValid (rtuid))
5465 reptype = uentry_getType (usymtab_getTypeEntry (rtuid));
5467 return (ctype_isUA (reptype) && (u2 == (ctype_typeId (reptype))));
5476 void usymtab_addGuards (guardSet guards)
5479 utab->guards = guardSet_union (utab->guards, guards);
5482 static bool usymtab_isGuardedAux (sRef s)
5486 sRef base = sRef_getRootBase (s);
5487 int lowlevel = paramsScope;
5488 int baselevel = sRef_lexLevel (base);
5490 if (sRef_isCvar (base))
5492 lowlevel = baselevel;
5493 if (lowlevel < paramsScope) lowlevel = paramsScope;
5496 while (tab->lexlevel >= lowlevel)
5498 DPRINTF (("Is guarded? [%s] %s",
5499 guardSet_unparse (tab->guards),
5500 sRef_unparseFull (s)));
5502 if (guardSet_isGuarded (tab->guards, s))
5505 if (!sRef_definitelyNull (s))
5507 sRef_setNotNull (s, fileloc_undefined);
5513 tab = usymtab_dropEnv (tab);
5519 void usymtab_unguard (sRef s) /*@modifies utab@*/
5522 sRef base = sRef_getRootBase (s);
5523 int lowlevel = paramsScope;
5524 int baselevel = sRef_lexLevel (base);
5526 if (sRef_isCvar (base))
5528 lowlevel = baselevel;
5529 if (lowlevel < paramsScope) lowlevel = paramsScope;
5532 while (tab->lexlevel >= lowlevel)
5534 if (guardSet_isGuarded (tab->guards, s))
5536 guardSet_delete (tab->guards, s);
5539 tab = usymtab_dropEnv (tab);
5543 bool usymtab_isGuarded (sRef s)
5545 DPRINTF (("Is guarded? %s", sRef_unparseFull (s)));
5546 return (sRef_aliasCompleteSimplePred (usymtab_isGuardedAux, s));
5549 bool usymtab_isDefinitelyNull (sRef s)
5551 return (sRef_aliasCheckSimplePred (usymtab_isDefinitelyNullAux, s));
5554 bool usymtab_isDefinitelyNullDeep (sRef s)
5556 return (sRef_deepPred (usymtab_isDefinitelyNull, s));
5559 static bool usymtab_isDefinitelyNullAux (sRef s)
5563 sRef base = sRef_getRootBase (s);
5564 int lowlevel = paramsScope;
5566 if (sRef_isCvar (base))
5568 lowlevel = sRef_lexLevel (base);
5569 if (lowlevel < paramsScope) lowlevel = paramsScope;
5572 while (tab->lexlevel >= lowlevel)
5574 if (guardSet_mustBeNull (tab->guards, s))
5579 while (tab->kind == US_CBRANCH)
5584 llassert (usymtab_isDefined (tab));
5586 if (tab->kind == US_FBRANCH)
5589 llassert (tab->kind == US_TBRANCH);
5599 usymtab_printGuards ()
5600 /*@globals utab, globtab@*/
5602 usymtab ttab = utab;
5604 while (ttab != globtab)
5606 llmsg (message ("Guards [%d]: %q", ttab->lexlevel,
5607 guardSet_unparse (ttab->guards)));
5613 usymtab_displayAllUses ()
5614 /*@globals utab, globtab@*/
5618 /* only in top scope */
5619 llassert (utab == globtab);
5621 /* need a copy, so order is not messed up by sort! */
5622 copy = usymtab_shallowCopy (globtab);
5624 qsort (copy->entries, (size_t)copy->nentries,
5625 sizeof (*copy->entries), (int (*)(const void *, const void *)) uentry_xcompareuses);
5627 usymtab_entries (copy, ue)
5629 if (uentry_isValid (ue) && !uentry_isGlobalMarker (ue))
5631 filelocList uses = uentry_getUses (ue);
5632 int size = filelocList_realSize (uses);
5634 if (fileloc_isDefined (uentry_whereDefined (ue))
5635 && !fileloc_isLib (uentry_whereDefined (ue))
5638 llmsg (message ("%q (%q), %d use%&:\n %q",
5639 uentry_getName (ue),
5640 fileloc_unparse (uentry_whereDefined (ue)),
5641 size, filelocList_unparseUses (uses)));
5644 } end_usymtab_entries;
5646 usymtab_shallowFree (copy);
5649 static /*@dependent@*/ /*@exposed@*/ usymtab
5650 usymtab_getFileTab ()
5651 /*@globals filetab@*/
5653 llassert (filetab != NULL);
5659 usymtab_unparseStack ()
5662 return (usymtab_unparseStackTab (utab));
5665 static /*@only@*/ cstring
5666 usymtab_unparseStackTab (usymtab t)
5668 bool firstOne = TRUE;
5669 cstring ret = cstring_makeLiteral ("[");
5671 while (t != GLOBAL_ENV)
5675 ret = message ("%q %q", ret, usymtab_typeName (t));
5680 ret = message ("%q, %q", ret, usymtab_typeName (t));
5685 ret = message ("%q ]", ret);
5689 static /*@only@*/ cstring
5690 usymtab_typeName (/*@notnull@*/ usymtab t)
5694 case US_GLOBAL: return cstring_makeLiteral ("global");
5695 case US_NORMAL: return cstring_makeLiteral ("normal");
5696 case US_TBRANCH: return cstring_makeLiteral ("true");
5697 case US_FBRANCH: return cstring_makeLiteral ("false");
5698 case US_CBRANCH: return cstring_makeLiteral ("case");
5699 case US_SWITCH: return cstring_makeLiteral ("switch");
5705 void usymtab_addMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5708 if (!sRef_similar (s, al))
5710 usymtab_addForceMustAlias (s, al);
5715 ** Same as usymtab_addMustAlias, except does not check sRef_isSimilar.
5718 void usymtab_addForceMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5721 /* evans 2002-03-3: was sRef_isMeaningful -- but we need to keep aliases for new storage also! */
5722 if (sRef_isMeaningful (s)
5723 && sRef_isMeaningful (al)
5724 && !(sRef_isConst (s) || sRef_isConst (al))
5725 && !(sRef_isAddress (al) && sRef_isDirectParam (sRef_getBase (al))))
5727 utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
5728 DPRINTF (("Must alias: %s", aliasTable_unparse (utab->aliases)));
5731 ** for local variable, aliasing is symmetric
5734 if (sRef_isLocalVar (s) && sRef_isLocalVar (al))
5736 utab->aliases = aliasTable_addMustAlias (utab->aliases, al, s);
5741 DPRINTF (("Not aliasing! %s / %s", sRef_unparseFull (s), sRef_unparseFull (al)));
5742 DPRINTF (("meaningful: %d %d", sRef_isMeaningful (s), sRef_isMeaningful (al)));
5746 void usymtab_addReallyForceMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5749 utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
5752 void usymtab_clearAlias (sRef s)
5753 /*@modifies utab, s@*/
5756 aliasTable_clearAliases (utab->aliases, s);
5759 sRefSet usymtab_allAliases (sRef s)
5762 if (sRef_isSomewhatMeaningful (s))
5766 ret = sRefSet_unionFree (aliasTable_aliasedBy (utab->aliases, s),
5767 aliasTable_canAlias (utab->aliases, s));
5772 DPRINTF (("NOT A MEANINGFUL SREF!"));
5773 return sRefSet_undefined;
5777 /*@only@*/ sRefSet usymtab_canAlias (sRef s)
5780 if (sRef_isSomewhatMeaningful (s))
5782 sRefSet res = aliasTable_canAlias (utab->aliases, s);
5786 return sRefSet_undefined;
5789 /*@only@*/ sRefSet usymtab_aliasedBy (sRef s)
5792 return (aliasTable_aliasedBy (utab->aliases, s));
5795 /*@only@*/ cstring usymtab_unparseAliases ()
5798 return (aliasTable_unparse (utab->aliases));
5802 ** Debugging routines:
5803 ** okay to leak storage here, only for debugging
5809 usymtab_printOut (void)
5815 char *ind = mstring_copy (" ");
5817 fprintf (g_warningstream, "<<< [symbol table] >>>\n");
5819 while (s != GLOBAL_ENV && s->env != GLOBAL_ENV)
5821 cstring tname = usymtab_typeName (s);
5825 ind[depth * 3 + 1] = '\0';
5828 fprintf (g_warningstream, "level: %d (%s)\n", s->lexlevel,
5829 cstring_toCharsSafe (tname));
5831 cstring_free (tname);
5833 for (i = 0; i < s->nentries; i++)
5835 cstring us = uentry_unparseFull (s->entries[i]);
5836 fprintf (g_warningstream, "%s\n", cstring_toCharsSafe (us));
5840 if (s->reftable != NULL && s->nentries > 0)
5842 fprintf (g_warningstream, "\t<< Ref table >>\n");
5844 for (i = 0; i < s->nentries; i++)
5846 fprintf (g_warningstream, "\t%s %3d: %d, %d\n", ind, i,
5847 s->reftable[i]->level,
5848 s->reftable[i]->index);
5852 ind[depth * 3 + 1] = ' ';
5856 fprintf (g_warningstream, "<<< end usymtab >>>\n");
5862 usymtab_printTypes ()
5863 /*@globals globtab@*/
5865 usymtab_printAllAux (globtab);
5869 usymtab_printAll (void)
5872 usymtab_printAllAux (utab);
5876 usymtab_printAllAux (usymtab s)
5877 /*@modifies g_warningstream@*/
5881 char *ind = mstring_copy (" ");
5883 printf ("[[[ usymtab ]]]");
5885 while (s != GLOBAL_ENV)
5888 ind[depth * 3 + 1] = '\0';
5890 if (s->env == GLOBAL_ENV)
5894 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5895 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5896 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5900 for (i = looplow; i < s->nentries; i++)
5902 printf ("%s%3d. %s\n", ind, i,
5903 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5908 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5909 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5910 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5912 for (i = 0; i < s->nentries; i++)
5914 printf ("%s%3d %s\n", ind, i,
5915 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5919 ind[depth * 3 + 1] = ' ';
5923 printf ("----------\n");
5927 usymtab_printComplete ()
5932 char *ind = mstring_copy (" ");
5935 while (s != GLOBAL_ENV)
5939 ind[depth * 3 + 1] = '\0';
5942 if (s->env == GLOBAL_ENV)
5946 printf ("level: %d\n", s->lexlevel);
5950 for (i = looplow; i < s->nentries; i++)
5952 printf ("%s%3d %s\n", ind, i,
5953 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5958 printf ("level: %d\n", s->lexlevel);
5959 for (i = 0; i < s->nentries; i++)
5961 printf ("%s%3d %s\n", ind, i,
5962 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5966 ind[depth * 3 + 1] = ' ';
5971 printf ("----------\n");
5976 static /*@only@*/ cstring /*@unused@*/
5977 usymtab_unparseLocalAux (/*@notnull@*/ usymtab s)
5979 cstring c = message ("lexlevel: %d\n", s->lexlevel);
5982 for (i = 0; i < s->nentries; i++)
5984 c = message ("%q\n%q", c, uentry_unparseFull (s->entries[i]));
5987 c = message ("%q\n=========", c);
5991 static cstring /*@unused@*/ /*@only@*/
5992 usymtab_unparseLocalList (/*@notnull@*/ usymtab s)
5994 cstring c = message ("[%d/%s/%s] ", s->lexlevel,
5995 bool_unparse (s->mustBreak),
5996 exitkind_unparse (s->exitCode));
5999 for (i = 0; i < s->nentries; i++)
6001 sRef sr = uentry_getSref (s->entries[i]);
6005 c = message ("%q: %q [%b]", c, uentry_getName (s->entries[i]),
6006 sRef_isStateDefined (sr));
6010 c = message ("%q, %q [%b]", c, uentry_getName (s->entries[i]),
6011 sRef_isStateDefined (sr));
6021 usymtab_printLocal (void)
6027 printf ("lexlevel: %d\n", s->lexlevel);
6029 for (i = 0; i < s->nentries; i++)
6031 printf ("%s\n", cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
6034 while (s->lexlevel > 1)
6039 llassert (usymtab_isDefined (s));
6041 printf ("Params:\n");
6043 for (i = 0; i < s->nentries; i++)
6045 printf ("%d: %s\n", i,
6046 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
6051 static bool checkDistinctExternalName (uentry e)
6052 /*@globals globtab@*/
6053 /*@modifies *g_warningstream@*/
6055 size_t checklen = size_fromInt (context_getValue (FLG_EXTERNALNAMELEN));
6056 bool ignorecase = context_getFlag (FLG_EXTERNALNAMECASEINSENSITIVE);
6057 bool gotone = FALSE;
6058 bool extras = FALSE;
6059 bool hasError = FALSE;
6060 cstring name = uentry_rawName (e);
6061 usymtab st = globtab;
6069 if (uentry_isAnyTag (e))
6071 checklen++; /* the tag marker doesn't count */
6075 usymtab_entries (st, oe)
6077 if (uentry_sameObject (oe, e))
6084 if (cstring_equalCaseInsensitive (uentry_rawName (oe), name))
6093 (FLG_DISTINCTEXTERNALNAMES,
6095 ("External identifier %q is not distinguishable from %q "
6096 "because alphabetical case is ignored",
6098 uentry_getName (oe)),
6099 uentry_whereLast (e)))
6101 uentry_showWhereAny (oe);
6102 uentry_setHasNameError (oe);
6111 if (cstring_equalLenCaseInsensitive (uentry_rawName (oe),
6120 if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6123 (FLG_DISTINCTEXTERNALNAMES,
6126 ("External identifier %q is not distinguishable from %q "
6127 "in the first %d characters (%q)",
6129 uentry_getName (oe),
6130 size_toInt (checklen),
6131 cstring_clip (uentry_getName (e), checklen)),
6133 uentry_whereLast (e)))
6135 uentry_showWhereAny (oe);
6136 uentry_setHasNameError (oe);
6149 (FLG_DISTINCTEXTERNALNAMES,
6151 ("External identifier %q is not distinguishable from %q "
6152 "in the first %d characters because alphabetical case "
6155 uentry_getName (oe),
6156 size_toInt (checklen)),
6157 uentry_whereLast (e)))
6159 uentry_showWhereAny (oe);
6160 uentry_setHasNameError (oe);
6166 else if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6175 (FLG_DISTINCTEXTERNALNAMES,
6178 ("External identifier %q is not distinguishable from %q "
6179 "in the first %d characters (%q)",
6181 uentry_getName (oe),
6182 size_toInt (checklen),
6183 cstring_clip (uentry_getName (e), checklen)),
6185 uentry_whereLast (e)))
6187 uentry_showWhereAny (oe);
6188 uentry_setHasNameError (oe);
6197 } end_usymtab_entries ;
6204 (cstring_makeLiteral ("One or more additional "
6205 "indistinguishable external "
6206 "names not reported"));
6212 static bool checkDistinctInternalName (uentry e)
6214 /*@modifies *g_warningstream@*/
6216 usymtab ttab = utab;
6217 cstring name = uentry_rawName (e);
6218 size_t numchars = size_fromInt (context_getValue (FLG_INTERNALNAMELEN));
6219 bool caseinsensitive = context_getFlag (FLG_INTERNALNAMECASEINSENSITIVE);
6220 bool lookalike = context_getFlag (FLG_INTERNALNAMELOOKALIKE);
6222 if (uentry_isAnyTag (e) && (numchars != 0))
6224 numchars++; /* the tag marker doesn't count */
6227 while (usymtab_isDefined (ttab))
6229 usymtab_entries (ttab, oe)
6231 if (uentry_sameObject (oe, e))
6233 /*@innercontinue@*/ continue;
6236 switch (cstring_genericEqual
6237 (name, uentry_rawName (oe),
6238 numchars, caseinsensitive, lookalike))
6240 case CGE_DISTINCT: /* okay */
6244 if (cstring_equal (name, uentry_rawName (oe)))
6246 ; /* got a shadow error */
6251 (FLG_DISTINCTINTERNALNAMES,
6254 ("Internal identifier %q is not distinguishable from %q "
6255 "in the first %d characters (%q)",
6257 uentry_getName (oe),
6258 size_toInt (numchars),
6259 cstring_clip (uentry_getName (e), numchars)),
6261 uentry_whereLast (e)))
6263 uentry_showWhereAny (oe);
6264 uentry_setHasNameError (oe);
6271 if (numchars == 0 || (cstring_length (name) <= numchars))
6274 (FLG_DISTINCTINTERNALNAMES,
6276 ("Internal identifier %q is not distinguishable from %q "
6277 "without case sensitivity",
6279 uentry_getName (oe)),
6280 uentry_whereLast (e)))
6282 uentry_showWhereAny (oe);
6283 uentry_setHasNameError (oe);
6290 (FLG_DISTINCTINTERNALNAMES,
6292 ("Internal identifier %q is not distinguishable from %q "
6293 "in the first %d characters without case sensitivity",
6295 uentry_getName (oe),
6296 size_toInt (numchars)),
6297 uentry_whereLast (e)))
6299 uentry_showWhereAny (oe);
6300 uentry_setHasNameError (oe);
6308 || (cstring_length (name) <= numchars))
6311 (FLG_DISTINCTINTERNALNAMES,
6313 ("Internal identifier %q is not distinguishable from %q "
6314 "except by lookalike characters",
6316 uentry_getName (oe)),
6317 uentry_whereLast (e)))
6319 uentry_showWhereAny (oe);
6320 uentry_setHasNameError (oe);
6327 (FLG_DISTINCTINTERNALNAMES,
6329 ("Internal identifier %q is not distinguishable from %q "
6330 "in the first %d characters except by lookalike characters",
6332 uentry_getName (oe),
6333 size_toInt (numchars)),
6334 uentry_whereLast (e)))
6336 uentry_showWhereAny (oe);
6337 uentry_setHasNameError (oe);
6342 } end_usymtab_entries ;
6350 void usymtab_checkDistinctName (uentry e, int scope)
6351 /*@globals utab, globtab@*/
6353 bool hasError = FALSE;
6354 fileloc where = uentry_whereLast (e);
6356 if (!fileloc_isPreproc (where) && !fileloc_isBuiltin (where))
6358 if (scope == globScope)
6360 if (context_getFlag (FLG_DISTINCTEXTERNALNAMES))
6362 hasError = checkDistinctExternalName (e);
6366 if (!hasError && context_getFlag (FLG_DISTINCTINTERNALNAMES))
6368 hasError = checkDistinctInternalName (e);
6374 uentry_setHasNameError (e);
6378 /*@exposed@*/ sRef usymtab_lookupGlobalMarker (void) /*@globals utab@*/
6382 ue = usymtab_lookupAux (utab, GLOBAL_MARKER_NAME);
6383 llassert (uentry_isValid (ue));
6385 return uentry_getSref (ue);
6391 ** For debugging only
6395 usymtab_checkAllValid () /*@globals utab@*/
6399 while (tab != GLOBAL_ENV)
6403 for (i = 0; i < utab->nentries; i++)
6405 uentry e = utab->entries[i];
6407 uentry_checkValid (e);
6410 aliasTable_checkValid (tab->aliases);