2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2002 University of Virginia,
4 ** Massachusetts Institute of Technology
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ** General Public License for more details.
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
20 ** For information on splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
27 ** Lexically scoped symbol table.
29 ** Unlike a normal symbol table, this table splits to reflect branches.
31 ** This is necessary since symbol table entries also reflect
32 ** some state information, like initialization, that may be
33 ** different on different branches.
35 ** For each control structure we split:
37 ** { } - a normal scope (no control) US_NORMAL
39 ** if <pred> { } - US_TBRANCH true branch
40 ** while <pred> { } US_FBRANCH else branch
42 ** switch <pred> { } - US_SWITCH
44 ** case x: - case scope US_CBRANCH
45 ** Should be kept in a separate table, because of
49 # include "splintMacros.nf"
51 # include "structNames.h"
52 # include "exprChecks.h"
53 # include "transferChecks.h"
55 /* Needed to install macros when loading libraries */
58 # include "cpperror.h"
62 ** Keep track of type definitions inside a function.
65 static uentryList functypes = uentryList_undefined;
67 static bool dbgfree = FALSE;
68 static bool dbgload = TRUE;
73 ** Hack to prevent shadow errors from appearing when function parameters
74 ** are entered into a new scope.
77 static bool noshadowerror = FALSE;
80 ** Constraint: static variables can live in 1 or > 2.
82 ** except for tags. All tags must be at the global level.
83 ** Static tags are handled in a kludgey way.
87 ** utab is the universal symbol table
88 ** globtab is the global environment of utab
89 ** oldtab is needed for conversions in dumping (after sorting the table)
91 ** there can be only one usymtab!
94 static /*@checkedstrict@*/ /*@owned@*/ /*@notnull@*/ usymtab utab;
96 /* Reachable environments from from utab */
97 static /*@checkedstrict@*/ /*@notnull@*/ /*@dependent@*/ usymtab globtab;
98 static /*@checkedstrict@*/ /*@dependent@*/ usymtab filetab;
100 /* Used for sorting for dumpage. */
101 static /*@checkedstrict@*/ /*@owned@*/ usymtab oldtab;
103 static int usymtab_lexicalLevel (void) /*@globals utab@*/ ;
104 static bool usymtab_isAltDefinitelyNull (sRef p_s) /*@globals utab@*/ ;
105 static void refTable_free (/*@only@*/ /*@null@*/ refTable p_x, int p_nentries);
106 static ctype usymtab_suFieldsType (uentryList p_f, bool p_isStruct) /*@globals globtab@*/ ;
108 extern int usymtab_getCurrentDepth (void) /*@globals utab@*/
110 return utab->lexlevel;
114 usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab p_u)
115 /*@globals globtab, utab, filetab@*/ /*@modifies p_u@*/ ;
117 static bool usymtab_isDefinitelyNullAux (sRef p_s) /*@globals utab@*/ ;
118 static /*@only@*/ cstring usymtab_unparseStackTab (usymtab p_t);
119 static /*@exposed@*/ /*@dependent@*/ uentry
120 usymtab_getRefTab (/*@notnull@*/ usymtab p_u, int p_level, usymId p_index);
123 /* These are not used anymore... */
124 static /*@unused@*/ /*@only@*/ cstring
125 usymtab_unparseLocalAux (/*@notnull@*/ usymtab p_s);
126 static /*@unused@*/ /*@only@*/ cstring
127 usymtab_unparseLocalList (/*@notnull@*/ usymtab p_s);
130 static /*@only@*/ cstring usymtab_typeName (/*@notnull@*/ usymtab p_t);
131 static void usymtab_handleParams (void)
132 /*@globals utab, globtab, filetab@*/
133 /*@modifies utab@*/ ;
135 static /*@exposed@*/ /*@dependent@*/ uentry
136 usymtab_addRefEntry (/*@notnull@*/ usymtab p_s, cstring p_k);
137 static /*@exposed@*/ /*@dependent@*/ usymtab
138 usymtab_dropEnv (/*@notnull@*/ usymtab p_s);
139 static /*@exposed@*/ /*@dependent@*/ uentry
140 usymtab_getRefNoisy (/*@notnull@*/ usymtab p_s, int p_level, usymId p_index);
142 static /*@exposed@*/ /*@dependent@*/ uentry
143 usymtab_lookupQuietAux (usymtab p_s, cstring p_k, bool p_noalt);
145 static /*@exposed@*/ /*@dependent@*/ uentry
146 usymtab_lookupQuiet (usymtab p_s, cstring p_k);
148 static /*@exposed@*/ /*@dependent@*/ uentry
149 usymtab_lookupQuietNoAlt (usymtab p_s, cstring p_k);
151 static void usymtab_printAllAux (usymtab p_s) /*@modifies g_warningstream@*/ ;
152 static int usymtab_getIndex (/*@notnull@*/ usymtab p_s, cstring p_k);
153 static /*@exposed@*/ uentry usymtab_fetchIndex (/*@notnull@*/ usymtab p_s, int p_i);
154 static /*@exposed@*/ uentry
155 usymtab_lookupAux (usymtab p_s, cstring p_k);
156 static /*@exposed@*/ /*@dependent@*/ /*@notnull@*/ usymtab
157 usymtab_getFileTab (void) /*@globals filetab@*/ ;
158 static int refTable_lookup (/*@notnull@*/ usymtab p_ut, int p_level, int p_index);
159 static bool usymtab_mustBreak (usymtab p_s);
160 static bool usymtab_mustEscape (usymtab p_s);
162 static void recordFunctionType (uentry ue)
164 llassert (uentry_isDatatype (ue) || uentry_isAnyTag (ue)
165 || uentry_isEnumConstant (ue));
166 DPRINTF (("Function type: %s", uentry_unparseFull (ue)));
168 functypes = uentryList_add (functypes, ue);
172 static void clearFunctionTypes (void)
173 /*@modifies globtab@*/
175 uentryList_elements (functypes, el)
177 if (cstring_isDefined (uentry_rawName (el)))
179 if (cstringTable_isDefined (globtab->htable))
181 cstringTable_remove (globtab->htable, uentry_rawName (el));
184 uentry_setName (el, cstring_undefined);
188 llassert (uentry_isValid (el));
189 el->sref = sRef_undefined;
190 /*@noaccess uentry@*/
191 } end_uentryList_elements ;
193 uentryList_clear (functypes);
196 static /*@falsewhennull@*/ bool usymtab_isBranch (usymtab u)
198 return (usymtab_isDefined (u) &&
199 (u->kind == US_TBRANCH || u->kind == US_FBRANCH
200 || u->kind == US_CBRANCH || u->kind == US_SWITCH));
203 static bool usymtab_mustBreak (usymtab s)
205 llassert (s != GLOBAL_ENV);
206 return (s->mustBreak);
209 static bool usymtab_mustEscape (usymtab s)
211 llassert (s != GLOBAL_ENV);
212 return (exitkind_mustEscape (s->exitCode));
215 void usymtab_setMustBreak ()
218 llassert (utab != GLOBAL_ENV);
219 utab->mustBreak = TRUE;
222 void usymtab_setExitCode (exitkind ex)
225 llassert (utab != GLOBAL_ENV);
229 if (exitkind_mustEscape (ex))
231 utab->mustBreak = TRUE;
235 bool usymtab_isAltDefinitelyNullDeep (sRef s)
237 return (sRef_deepPred (usymtab_isAltDefinitelyNull, s));
240 static bool usymtab_isAltDefinitelyNull (sRef s)
248 llassert (utab->env != NULL);
250 /*@-mods@*/ /* These modifications are cancelled. */
251 utab->guards = utab->env->guards;
252 utab->env->guards = t;
255 llassert (usymtab_isDefined (utab));
256 res = usymtab_isDefinitelyNull (s);
259 ** This reports a spurious error. It is okay, because of
260 ** the nesting relationship of usymtab environments.
263 /*@-mods@*/ /* Cancelling modifications. */
264 /*@i1@*/ utab->env->guards = utab->guards;
265 /*@i1@*/ utab->guards = t;
271 static /*@notnull@*/ /*@special@*/ usymtab
272 usymtab_create (uskind kind, /*@keep@*/ usymtab env, bool nextlevel)
274 /*@post:isnull result->htable, result->guards, result->aliases@*/
276 usymtab t = (usymtab) dmalloc (sizeof (*t));
279 t->nspace = CBASESIZE;
280 t->entries = (uentry *) dmalloc (sizeof (*t->entries) * CBASESIZE);
282 /* We only use a reftable for branch-level symbol tables.
285 t->reftable = (nextlevel
287 : (refentry *) dmalloc (sizeof (*t->reftable) * CBASESIZE));
290 t->lexlevel = (env == GLOBAL_ENV ? 0 : env->lexlevel) + (nextlevel ? 1 : 0);
295 t->guards = guardSet_undefined;
296 t->aliases = aliasTable_undefined;
298 t->mustBreak = FALSE;
299 t->exitCode = XK_NEVERESCAPE;
308 static /*@only@*/ /*@notnull@*/ usymtab
309 usymtab_createRoot (void) /*@modifies nothing@*/
311 usymtab u = (usymtab) dmalloc (sizeof (*u));
314 u->nspace = CGLOBBASESIZE;
315 u->entries = (uentry *) dmalloc (sizeof (*u->entries) * CGLOBBASESIZE);
318 u->htable = cstringTable_create (CGLOBHASHSIZE);
321 u->guards = guardSet_new ();
322 u->aliases = aliasTable_new ();
324 u->mustBreak = FALSE;
325 u->exitCode = XK_NEVERESCAPE;
332 usymtab_initMod (void)
333 /*@globals undef utab, undef oldtab, undef globtab, undef filetab @*/
334 /*@modifies utab, globtab, filetab, oldtab @*/
336 utab = usymtab_createRoot ();
338 filetab = usymtab_undefined;
339 oldtab = usymtab_undefined;
344 usymtab_initGlobalMarker () /*@globals globtab@*/
346 if (uentry_isValid (usymtab_lookupAux (globtab, GLOBAL_MARKER_NAME)))
348 ; /* Already entered from load table. */
352 usymtab_addGlobalEntry (uentry_makeGlobalMarker ());
357 ** utab should be empty? (requires?)
359 ** Adds bool types to symbol table (these are built in for now)
360 ** Only do this is there is no library!
366 DPRINTF (("Init bool!"));
368 if (context_getFlag (FLG_NOLIB))
370 ctype boolt = ctype_bool;
371 /* evs 2000-07-24: bool is now treated as abstract (always) */
373 uentry boolentry = uentry_makeBoolDatatype (YES);
374 usymtab_supGlobalEntry (boolentry);
375 context_addBoolAccess ();
378 ** We supply values 0 and 1 for the constants, so things like
379 ** while (TRUE) can be interpreted correctly.
382 usymtab_supGlobalEntry
383 (uentry_makeConstantValue (context_getFalseName (), boolt,
384 fileloc_getBuiltin (), FALSE,
385 multiVal_makeInt (0)));
387 usymtab_supGlobalEntry
388 (uentry_makeConstantValue (context_getTrueName (), boolt,
389 fileloc_getBuiltin (), FALSE,
390 multiVal_makeInt (1)));
399 usymtab_grow (/*@notnull@*/ usymtab s)
402 o_uentry *oldsyms = s->entries;
404 s->nspace = CBASESIZE;
405 s->entries = (uentry *) dmalloc (sizeof (*s->entries)
406 * (s->nentries + s->nspace));
408 for (i = 0; i < s->nentries; i++)
410 s->entries[i] = oldsyms[i];
415 if (s->reftable != NULL)
417 refTable oldRefs = s->reftable;
419 s->reftable = (refentry *) dmalloc (sizeof (*s->reftable)
420 * (s->nentries + CBASESIZE + 1));
422 for (i = 0; i < s->nentries; i++)
424 s->reftable[i] = oldRefs[i];
435 usymtab_addEntryQuiet (/*@notnull@*/ usymtab s, /*@keep@*/ uentry e)
437 if (!(s->lexlevel > fileScope || !sRef_modInFunction ()))
439 if (uentry_isDatatype (e)
440 || uentry_isFunction (e)
441 || uentry_isAnyTag (e)
442 || uentry_isEnumConstant (e)
443 || context_inMacro ())
446 ** Not a bug. Code like,
447 ** int f (void) { typedef int tint; ... }
451 /* was nothing here! */
452 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
457 (cstring_makeLiteral ("Declaration outside function scope"));
459 llcontbug (message ("usymtab_addEntryQuiet: inconsistent state "
460 "(lexlevel = %d, modFunction = %s) adding: %q",
461 s->lexlevel, bool_unparse (sRef_modInFunction ()),
462 uentry_unparse (e)));
463 sRef_setGlobalScope ();
464 /* make sure the sRef is not bashed! */
465 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
475 s->entries[s->nentries] = e;
478 if (s == globtab || s == filetab)
480 if (!fileloc_isLib (g_currentloc))
482 uentry_tallyAnnots (e, AN_UNKNOWN);
487 if (cstringTable_isDefined (s->htable))
489 cstringTable_insert (s->htable, cstring_copy (uentry_rawName (e)), s->nentries);
495 static /*@observer@*/ uentry /*@alt void@*/
496 usymtab_addEntryBase (/*@notnull@*/ usymtab s, /*@only@*/ uentry e)
499 ** In theory, we shouldn't need this test because it this is
500 ** only called when a library is being read, and it shouldn't
501 ** ever have a duplicate entry. In practice, its safer to
502 ** leave it in, though.
507 if (uentry_isValid (old = usymtab_lookupQuiet (s, uentry_rawName (e))))
509 DPRINTF (("Duplicate entry: %s", uentry_unparse (e)));
510 uentry_free (e); /* duplicate */
515 int thisentry = s->nentries;
517 if (uentry_isVar (e))
519 uentry_setSref (e, sRef_makeCvar (globScope, thisentry,
521 stateInfo_makeLoc (uentry_whereLast (e))));
524 usymtab_addEntryQuiet (s, e);
530 static /*@observer@*/ uentry /*@alt void@*/
531 usymtab_addEntryAlways (/*@notnull@*/ usymtab s, /*@only@*/ uentry e)
534 ** In theory, we shouldn't need this test because it this is
535 ** only called when a library is being read, and it shouldn't
536 ** ever have a duplicate entry. In practice, its safer to
537 ** leave it in, though.
541 int thisentry = s->nentries;
543 if (uentry_isValid (old = usymtab_lookupQuiet (s, uentry_rawName (e))))
546 (message ("Duplicate entry in load library: %s. "
547 "Old entry: %q. New entry: %q",
549 uentry_unparseFull (old),
550 uentry_unparseFull (e)));
552 uentry_setName (e, message ("__x_%s", uentry_rawName (e)));
553 /* This shouldn't happen...unless the library is bad! */
557 if (uentry_isVar (e) && !uentry_isGlobalMarker (e))
559 uentry_setSref (e, sRef_makeCvar (globScope, thisentry,
561 stateInfo_makeLoc (uentry_whereLast (e))));
564 usymtab_addEntryQuiet (s, e);
569 usymtab_addEntryAux (/*@notnull@*/ usymtab st, /*@keep@*/ uentry e, bool isSref)
570 /*@globals globtab@*/
573 usymId thisentry = st->nentries;
575 llassert (!uentry_isElipsisMarker (e));
579 ** llassert (usymtab_lookupSafe (uentry_rawName (e)) == uentry_undefined);
582 llassertprint (uentry_isAnyTag (e) ? st == globtab : TRUE,
583 ("non-global tag: %s / %d", uentry_unparseFull (e), st->lexlevel));
585 if (st->lexlevel == fileScope
586 && (!(uentry_isStatic (e)) || uentry_isAnyTag (e)))
593 ctype ct = uentry_getType (e);
595 if (uentry_isFunction (e) && ctype_isFunction (ct))
597 ct = ctype_getReturnType (ct);
600 if (uentry_isStatic (e))
602 sRef sr = sRef_makeCvar (st->lexlevel, thisentry, ct, stateInfo_makeLoc (uentry_whereLast (e)));
604 if (sRef_isStack (sr) || sRef_isLocalState (sr))
606 sRef_setAliasKind (sr, AK_STATIC, uentry_whereLast (e));
607 sRef_setDefined (sr, uentry_whereLast (e));
610 uentry_setSref (e, sr);
614 uentry_setSref (e, sRef_makeCvar (st->lexlevel, thisentry, ct, stateInfo_makeLoc (uentry_whereLast (e))));
618 if (uentry_isDatatype (e))
621 uentry_setDatatype (e, thisentry);
624 if (uentry_isFunction (e))
626 ctype ct = uentry_getType (e);
628 if (ctype_isFunction (ct)
629 && uentryList_isMissingParams (ctype_argsFunction (ct)))
631 if (uentry_isDeclared (e))
635 message ("Function %q declared without parameter list",
637 uentry_whereDeclared (e));
643 message ("Function %q specified without parameter list",
645 uentry_whereSpecified (e));
650 if (st == globtab && !uentry_isSpecified (e))
652 exprChecks_checkExport (e);
655 uentry_checkName (e);
657 usymtab_addEntryQuiet (st, e);
658 DPRINTF (("Adding entry: [%p] %s", e, uentry_unparseFull (e)));
663 usymtab_addEntry (uentry e)
664 /*@globals utab, globtab@*/
665 /*@modifies utab, e@*/
667 llassertprint (!usymtab_exists (uentry_rawName (e)),
668 ("Entry already exists: %s", uentry_unparse (e)));
670 return usymtab_addEntryAux (utab, e, FALSE);
674 usymtab_addGlobalEntry (uentry e)
675 /*@modifies globtab, e@*/
677 DPRINTF (("Add global: %s / %s", uentry_unparse (e), bool_unparse (uentry_isForward (e))));
679 (void) usymtab_addEntryAux (globtab, e, FALSE);
683 ** supercede and replace entry use elements of entries array, and
684 ** assign an element to a new value, and then free the old value.
685 ** Need -deparrays to avoid errors for this.
691 usymtab_supEntryAux (/*@notnull@*/ usymtab st,
692 /*@only@*/ uentry e, bool isSref)
693 /*@globals globtab, filetab@*/
694 /*@modifies st, globtab, e@*/
696 cstring ename = uentry_rawName (e);
697 bool staticEntry = FALSE;
700 DPRINTF (("Sup entry aux: %s", uentry_unparseFull (e)));
702 /* static tags in global scope */
703 if (st->lexlevel == fileScope
704 && (!(uentry_isStatic (e)) || uentry_isAnyTag (e)))
706 eindex = usymtab_getIndex (st, ename);
708 if (eindex != NOT_FOUND)
710 uentry ce = st->entries[eindex];
714 message ("%s %q shadows static declaration",
715 ekind_capName (uentry_getKind (e)),
717 uentry_whereDeclared (e)))
719 uentry_showWhereLast (ce);
722 if (eindex == st->nentries - 1)
728 st->entries[eindex] = st->entries[st->nentries - 1];
731 if (cstringTable_isDefined (st->htable))
733 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
734 cstring_copy (uentry_rawName (e)));
744 if (uentry_isStatic (e)) {
745 if (uentry_isFunction (e)) {
747 ** Static function declarations are at the file level,
748 ** even if they are in a deeper scope.
751 st = usymtab_getFileTab ();
754 if (!uentry_isAnyTag (e) && st == globtab)
756 st = usymtab_getFileTab ();
758 DPRINTF (("Static entry!"));
763 eindex = usymtab_getIndex (st, ename);
765 if (eindex != NOT_FOUND)
767 uentry ce = st->entries[eindex];
769 DPRINTF (("Found entry: %s", uentry_unparse (ce)));
771 if (uentry_isPriv (ce)
772 /* || (fileloc_isImport (uentry_whereSpecified (ce))) */
773 || (uentry_isStatic (ce)
774 && uentry_isAnyTag (ce)
775 && (uentry_isDeclared (ce)
776 && !fileloc_sameFile (uentry_whereDefined (ce),
777 uentry_whereDefined (e)))))
781 ** if overloading import should do some checks!
784 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
786 DPRINTF (("Overloading!"));
788 st->entries[eindex] = e;
790 if (uentry_isDatatype (e))
792 uentry_setDatatype (e, eindex);
795 if (st == globtab && !uentry_isSpecified (e))
797 exprChecks_checkExport (e);
800 if (cstringTable_isDefined (st->htable))
802 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
803 cstring_copy (uentry_rawName (e)));
809 else if (uentry_isSpecified (ce))
811 if (uentry_isSpecified (e))
813 DPRINTF (("Here we are: %s", uentry_unparseFull (e)));
815 if (fileloc_isImport (uentry_whereSpecified (ce)))
817 if (cstringTable_isDefined (st->htable))
819 cstringTable_replaceKey (st->htable,
821 cstring_copy (uentry_rawName (e)));
825 st->entries[eindex] = e;
828 if (uentry_isDatatype (e)) uentry_setDatatype (e, eindex);
832 if (fileloc_isImport (uentry_whereSpecified (e)))
838 /* Respecification errors already reported */
839 DPRINTF (("Respecification: %s / %s",
840 fileloc_unparse (uentry_whereSpecified (e)),
841 bool_unparse (fileloc_isSpec (uentry_whereSpecified (e)))));
843 if (uentry_isDatatype (e))
845 uentry_setDatatype (e, eindex);
848 if (cstringTable_isDefined (st->htable))
850 cstringTable_replaceKey (st->htable,
852 cstring_copy (uentry_rawName (e)));
855 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
857 st->entries[eindex] = e;
862 else /* e not specified */
864 DPRINTF (("Merging..."));
866 if (uentry_isDeclared (ce))
869 No - this can happen for internal typedefs
870 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
873 DPRINTF (("Merge defn"));
874 uentry_mergeDefinition (ce, e);
879 No - this can happen for internal typedefs
880 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
883 DPRINTF (("Merge entries..."));
884 uentry_mergeEntries (ce, e);
885 DPRINTF (("After: %s", uentry_unparseFull (ce)));
889 else /* ce not specified */
891 if (!(st->lexlevel > fileScope || !sRef_modInFunction ()))
893 if (uentry_isDatatype (e) || uentry_isAnyTag (e)
894 || uentry_isEnumConstant (e)
895 || uentry_isStatic (e)) /* bug fix from Brian St. Pierre */
898 ** Not a bug. Code like,
899 ** int f (void) { typedef int tint; ... }
905 llcontbug (message ("usymtab_supEntryAux: inconsistent state "
906 "(lexlevel = %d, modFunction = %s) adding: %q",
907 st->lexlevel, bool_unparse (sRef_modInFunction ()),
908 uentry_unparse (e)));
910 if (sRef_modInFunction ())
912 /* make sure the sRef is not bashed! */
913 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
918 DPRINTF (("Merge.."));
919 uentry_mergeDefinition (ce, e);
924 ctype ct = uentry_getType (ce);
926 if (uentry_isFunction (ce) && ctype_isFunction (ct))
928 ct = ctype_getReturnType (ct);
931 uentry_setSref (ce, sRef_makeCvar (st->lexlevel, eindex, ct, stateInfo_makeLoc (uentry_whereLast (ce))));
934 else /* no previous entry */
938 if (st->lexlevel == globScope
939 && !uentry_isStatic (e)
940 && !uentry_isExtern (e)
941 && usymtab_isDefined (filetab))
944 ** check if there is a static entry: (i.e.,
951 eindex = usymtab_getIndex (filetab, ename);
953 if (eindex != NOT_FOUND)
955 uentry ce = filetab->entries[eindex];
957 uentry_setStatic (e);
958 uentry_mergeDefinition (ce, e);
964 outer = usymtab_lookupQuiet (st->env, ename);
966 DPRINTF (("New : [%p] %s", e, uentry_unparseFull (e)));
967 DPRINTF (("Outer: [%p] %s", outer, uentry_unparseFull (outer)));
970 ** no previous definition, add the new one
974 && uentry_isValid (outer)
975 && !(uentry_isYield (e) || uentry_isYield (outer))
976 && fileloc_isDefined (uentry_whereLast (e))
977 && !fileloc_isXHFile (uentry_whereLast (e))
978 && fileloc_isDefined (uentry_whereLast (outer))
979 && !fileloc_isXHFile (uentry_whereLast (outer)))
981 if (!uentry_sameKind (outer, e))
987 if (ctype_isUnknown (uentry_getType (outer))
988 || uentry_isForward (outer))
996 message ("%s %q shadows outer declaration",
997 ekind_capName (uentry_getKind (e)),
999 uentry_whereLast (e)))
1001 uentry_showWhereLast (outer);
1007 if (st == globtab && context_getFlag (FLG_NEWDECL))
1011 message ("New declaration: %q", uentry_getName (e)),
1012 uentry_whereLast (e));
1015 eindex = usymtab_addEntryAux (st, e, isSref);
1019 return (staticEntry ? USYMIDINVALID : eindex);
1024 usymtab_replaceEntryAux (/*@notnull@*/ usymtab st, /*@only@*/ uentry e)
1025 /*@globals globtab@*/ /*@modifies st, e@*/
1027 cstring ename = uentry_rawName (e);
1030 /* static tags in global scope */
1031 eindex = usymtab_getIndex (st, ename);
1033 if (eindex != NOT_FOUND)
1035 uentry ce = st->entries[eindex];
1037 if (cstringTable_isDefined (st->htable))
1039 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
1040 cstring_copy (uentry_rawName (e)));
1044 st->entries[eindex] = e;
1048 eindex = usymtab_addEntryAux (st, e, FALSE);
1055 void usymtab_supEntry (uentry e)
1056 /*@globals utab, filetab, globtab@*/
1057 /*@modifies utab, globtab, e@*/
1059 (void) usymtab_supEntryAux (utab, e, FALSE);
1063 ** this should be lots more efficient!
1066 static /*@exposed@*/ uentry
1067 usymtab_supEntryReturnAux (/*@notnull@*/ usymtab tab,
1068 /*@only@*/ uentry e, bool isref)
1069 /*@globals globtab, filetab@*/
1070 /*@modifies tab, globtab, e@*/
1072 cstring rawName = cstring_copy (uentry_rawName (e));
1073 bool stat = (tab == globtab) && uentry_isStatic (e);
1076 (void) usymtab_supEntryAux (tab, e, isref);
1080 ret = usymtab_lookupAux (filetab, rawName);
1084 ret = usymtab_lookupAux (tab, rawName);
1086 if (uentry_isInvalid (ret) && usymtab_isDefined (filetab))
1088 ret = usymtab_lookupAux (filetab, rawName);
1092 cstring_free (rawName);
1096 /*@dependent@*/ /*@exposed@*/ uentry
1097 usymtab_supEntryReturn (/*@only@*/ uentry e)
1098 /*@globals utab, filetab, globtab@*/
1099 /*@modifies utab, globtab, e@*/
1101 return (usymtab_supEntryReturnAux (utab, e, FALSE));
1104 /*@dependent@*/ /*@exposed@*/ uentry
1105 usymtab_supEntrySrefReturn (/*@only@*/ uentry e)
1106 /*@globals utab, globtab, filetab@*/
1107 /*@modifies utab, globtab, e@*/
1109 return (usymtab_supEntryReturnAux (utab, e, TRUE));
1112 /*@dependent@*/ /*@exposed@*/ uentry
1113 usymtab_supGlobalEntryReturn (uentry e)
1114 /*@globals globtab, filetab@*/
1115 /*@modifies globtab, e@*/
1119 ret = usymtab_supEntryReturnAux (globtab, e, FALSE);
1122 ** We need to keep track of internal function declarations, so
1123 ** we can remove them from the symbol table after exiting this
1124 ** function. This is a bit bogus, of course.
1127 if (sRef_modInFunction ())
1129 recordFunctionType (ret);
1136 usymtab_supTypeEntry (/*@only@*/ uentry e)
1137 /*@globals globtab, filetab@*/
1138 /*@modifies globtab, e@*/
1143 if (uentry_isAbstractDatatype (e))
1145 uid = usymtab_supAbstractTypeEntry (e, FALSE);
1146 ret = ctype_createAbstract (uid);
1150 uid = usymtab_supEntryAux (globtab, e, FALSE);
1151 ret = ctype_createUser (uid);
1154 if (sRef_modInFunction ())
1156 recordFunctionType (globtab->entries[uid]);
1163 usymtab_supReturnTypeEntry (/*@only@*/ uentry e)
1164 /*@globals globtab, filetab@*/
1165 /*@modifies globtab@*/
1169 DPRINTF (("Abstract? %s", uentry_unparseFull (e)));
1171 if (uentry_isAbstractDatatype (e))
1173 uid = usymtab_supAbstractTypeEntry (e, FALSE);
1175 else if (uentry_isMaybeAbstract (e) && context_getFlag (FLG_IMPABSTRACT))
1177 bool maybeabs = TRUE;
1178 cstring sname = uentry_getName (e);
1179 uentry ue = usymtab_lookupGlobSafe (sname);
1180 cstring_free (sname);
1182 if (uentry_isValid (ue))
1184 DPRINTF (("Lookup: %s", uentry_unparseFull (ue)));
1186 if (uentry_isDatatype (ue))
1188 if (uentry_isMaybeAbstract (ue))
1199 DPRINTF (("Not datatype!"));
1206 uid = usymtab_supAbstractTypeEntry (e, FALSE);
1207 ux = usymtab_getTypeEntry (uid);
1208 uentry_setAbstract (ux);
1212 uid = usymtab_supEntryAux (globtab, e, FALSE);
1213 e = usymtab_getTypeEntry (uid);
1215 if (uentry_isMaybeAbstract (e))
1217 uentry_setConcrete (e);
1223 uid = usymtab_supEntryAux (globtab, e, FALSE);
1224 e = usymtab_getTypeEntry (uid);
1226 if (uentry_isMaybeAbstract (e))
1228 uentry_setConcrete (e);
1232 if (sRef_modInFunction ())
1234 recordFunctionType (globtab->entries[uid]);
1237 return (globtab->entries[uid]);
1241 usymtab_supAbstractTypeEntry (/*@only@*/ uentry e, bool dodef)
1242 /*@globals globtab, filetab@*/
1243 /*@modifies globtab, e@*/
1248 uid = usymtab_supEntryAux (globtab, e, FALSE);
1249 ue = usymtab_getTypeEntry (uid);
1253 uentry_setDatatype (ue, uid);
1256 if (context_getFlag (FLG_ACCESSMODULE)) /* was accessfile */
1258 context_addFileAccessType (uid);
1261 if (sRef_modInFunction ())
1263 recordFunctionType (globtab->entries[uid]);
1271 usymtab_supExposedTypeEntry (/*@only@*/ uentry e, bool dodef)
1272 /*@globals globtab, filetab@*/
1273 /*@modifies globtab, e@*/
1277 uid = usymtab_supEntryAux (globtab, e, FALSE);
1281 uentry ue = usymtab_getTypeEntry (uid);
1283 uentry_setDatatype (ue, uid);
1286 if (sRef_modInFunction ())
1288 recordFunctionType (globtab->entries[uid]);
1296 usymtab_supForwardTypeEntry (/*@only@*/ uentry e)
1297 /*@globals globtab, filetab@*/
1298 /*@modifies globtab, e@*/
1300 usymId uid = usymtab_supEntryAux (globtab, e, FALSE);
1301 uentry ue = usymtab_getTypeEntry (uid);
1303 uentry_setDatatype (ue, uid);
1305 if (sRef_modInFunction ())
1307 recordFunctionType (globtab->entries[uid]);
1310 return (uentry_getAbstractType (ue));
1314 usymtab_supEntrySref (uentry e)
1315 /*@globals utab, globtab, filetab@*/
1316 /*@modifies utab, globtab, e@*/
1318 sRef old = uentry_getSref (e);
1320 if (sRef_isType (old))
1322 uentry ue = usymtab_supEntryReturnAux (utab, e, TRUE);
1325 if (uentry_isValid (ue))
1327 sRef uref = uentry_getSref (ue);
1329 sRef_mergeStateQuiet (uref, old);
1330 sRef_clearDerived (uref);
1332 /*@noaccess uentry@*/
1334 else if (sRef_isKnown (old))
1336 usymtab_supEntry (e);
1340 (void) usymtab_supEntryAux (utab, e, TRUE);
1344 void usymtab_supGlobalEntry (/*@only@*/ uentry e)
1345 /*@globals globtab, filetab@*/
1346 /*@modifies globtab, filetab, e@*/
1350 DPRINTF (("Sup global entry: %s", uentry_unparse (e)));
1352 uid = usymtab_supEntryAux (globtab, e, FALSE);
1354 if (sRef_modInFunction ())
1356 recordFunctionType (globtab->entries[uid]);
1361 usymtab_supReturnFileEntry (/*@only@*/ uentry e)
1362 /*@globals filetab, globtab@*/
1363 /*@modifies filetab, globtab, e@*/
1365 llassert (filetab != usymtab_undefined);
1366 DPRINTF (("File entry: %s", uentry_unparse (e)));
1367 return (usymtab_supEntryReturnAux (filetab, e, FALSE));
1375 usymtab_inDeepScope () /*@globals utab@*/
1377 return (utab->lexlevel > paramsScope);
1381 usymtab_getIndex (/*@notnull@*/ usymtab s, cstring k)
1385 DPRINTF (("Lookup %s", k));
1387 if (cstringTable_isDefined (s->htable))
1389 i = cstringTable_lookup (s->htable, k);
1394 for (i = 0; i < s->nentries; i++)
1396 uentry current = s->entries[i];
1398 DPRINTF (("Check %d: %s", i, uentry_rawName (current)));
1400 if (!uentry_isUndefined (current)
1401 && cstring_equal (uentry_rawName (current), k))
1412 usymtab_fetchIndex (/*@notnull@*/ usymtab s, int i)
1414 llassert (i >= 0 && i < s->nentries);
1415 return (s->entries[i]);
1419 usymtab_getTypeId (cstring k) /*@globals globtab@*/
1421 usymId uid = usymtab_getIndex (globtab, k);
1423 if (uid == NOT_FOUND) return USYMIDINVALID;
1425 if (!(uentry_isDatatype (usymtab_getTypeEntry (uid)))) {
1426 return USYMIDINVALID;
1432 /*@dependent@*/ uentry
1433 usymtab_lookupStructTag (cstring k)
1435 cstring sname = makeStruct (k);
1436 uentry ue = usymtab_lookupGlob (sname);
1438 cstring_free (sname);
1442 /*@dependent@*/ uentry
1443 usymtab_lookupUnionTag (cstring k)
1445 cstring uname = makeUnion (k);
1446 uentry res = usymtab_lookupGlob (uname);
1448 cstring_free (uname);
1452 /*@dependent@*/ uentry
1453 usymtab_lookupEnumTag (cstring k)
1455 cstring ename = makeEnum (k);
1456 uentry res = usymtab_lookupGlob (ename);
1458 cstring_free (ename);
1463 usymtab_getId (cstring k) /*@globals globtab@*/
1465 usymId uid = usymtab_getIndex (globtab, k);
1468 if (uid == NOT_FOUND)
1470 return USYMIDINVALID;
1473 ue = usymtab_getGlobalEntry (uid);
1475 if (uentry_isPriv (ue))
1477 return USYMIDINVALID;
1483 static /*@exposed@*/ uentry
1484 usymtab_getEntryAux (/*@notnull@*/ usymtab s, usymId uid)
1486 llassert (uid != USYMIDINVALID);
1488 if (uid < 0 || uid >= s->nentries)
1490 llcontbug (message ("usymtab_getEntry: out of range: level = %d [%d]",
1492 return uentry_undefined;
1495 llassertprint (uentry_isValid (s->entries[uid]),
1496 ("entry undefined: %d", uid));
1498 return s->entries[uid];
1501 /*@dependent@*/ /*@observer@*/ uentry
1502 usymtab_getGlobalEntry (usymId uid)
1503 /*@globals utab, globtab@*/
1505 if (dbgfree) return (uentry_undefined);
1507 if (utab->lexlevel > paramsScope)
1509 /* need to do this the awkward way, since it could be in conditional scope */
1510 return (usymtab_lookupSafe (uentry_rawName (globtab->entries[uid])));
1514 return (globtab->entries[uid]);
1518 /*@dependent@*/ /*@exposed@*/ uentry
1519 usymtab_getTypeEntry (usymId uid)
1520 /*@globals globtab@*/
1524 if (uid >= 0 && uid < globtab->nentries)
1526 return (globtab->entries[uid]);
1530 return (uentry_undefined);
1535 llassert (uid >= 0 && uid < globtab->nentries);
1536 return (globtab->entries[uid]);
1544 /*@dependent@*/ /*@exposed@*/ uentry
1545 usymtab_getTypeEntrySafe (usymId uid)
1546 /*@globals globtab@*/
1548 if (uid < 0 || uid >= globtab->nentries)
1550 return uentry_undefined;
1553 return (globtab->entries[uid]);
1557 usymtab_isBoolType (usymId uid)
1558 /*@globals globtab@*/
1560 llassert (uid >= 0 && uid < globtab->nentries);
1562 return (cstring_equal (uentry_rawName (globtab->entries[uid]),
1563 context_getBoolName ()));
1567 usymtab_getTypeEntryName (usymId uid)
1568 /*@globals globtab@*/
1574 return (cstring_makeLiteral ("<freetype>"));
1577 ue = usymtab_getTypeEntry (uid);
1579 if (dbgload && !uentry_isValid (ue))
1581 return (message ("<missing type: %d>", uid));
1584 llassertprint (uentry_isValid (ue), ("type undefined: %d", uid));
1586 return (uentry_getName (ue));
1590 /*@unused@*/ static void
1591 usymtab_rehash (/*@notnull@*/ usymtab s)
1595 if (cstringTable_isDefined (s->htable))
1597 cstringTable_free (s->htable);
1600 s->htable = cstringTable_create (LLAHSHSIZE);
1602 for (i = 0; i < s->nentries; i++)
1604 cstringTable_insert (s->htable, cstring_copy (uentry_rawName (s->entries[i])), i);
1610 ** superficial copy of usymtab
1612 ** DO copy spec entries
1615 static /*@only@*/ /*@notnull@*/ usymtab
1616 usymtab_shallowCopy (/*@notnull@*/ usymtab s) /*@*/
1618 usymtab copytab = usymtab_createRoot ();
1621 for (i = 0; i < s->nentries; i++)
1623 usymtab_addEntryBase (copytab, s->entries[i]);
1630 usymtab_shallowFree (/*@only@*/ /*@notnull@*/ usymtab s)
1632 aliasTable_free (s->aliases);
1633 refTable_free (s->reftable, s->nentries);
1635 /*@-compdestroy@*/ sfree (s); /*@=compdestroy@*/
1639 ** converts usymId from old table to sorted one
1643 usymtab_convertId (usymId uid)
1644 /*@globals oldtab, utab@*/
1650 llassert (usymtab_isDefined (oldtab));
1652 ue = usymtab_getEntryAux (oldtab, uid);
1654 llassertprint (uentry_isValid (ue), ("convertId: undefined: %d", uid));
1656 name = uentry_rawName (ue);
1658 ret = usymtab_getIndex (utab, name);
1659 llassert (ret == uid); /*! for now, no rehash! */
1660 DPRINTF (("Convert: %s [%d] -> %s [%d]",
1661 uentry_unparse (ue), uid,
1662 uentry_unparse (utab->entries[ret]), ret));
1664 llassertprint (ret != USYMIDINVALID, ("convertId: return is invalid"));
1670 usymtab_prepareDump (void)
1671 /*@globals oldtab, utab@*/
1672 /*@modifies oldtab, utab@*/
1674 llassert (usymtab_inGlobalScope ());
1675 llassert (oldtab == usymtab_undefined);
1678 DPRINTF (("Preparing to dump:"));
1679 usymtab_printAll ();
1682 oldtab = usymtab_shallowCopy (utab);
1685 ** alpha compare - make sure order is same on different platforms
1686 ** error messages appear in same order
1690 qsort (utab->entries, (size_t)utab->nentries,
1691 sizeof (*utab->entries),
1692 (int (*)(const void *, const void *)) uentry_xcomparealpha);
1694 usymtab_rehash (utab);
1698 DPRINTF (("After rehash:"));
1699 usymtab_printAll ();
1703 void usymtab_dump (FILE *fout)
1704 /*@globals utab, oldtab@*/
1707 bool neednl = FALSE;
1708 uentry lastentry = uentry_undefined;
1709 ekind lastekind = KINVALID;
1713 ** must call prepareDump first
1716 llassert (oldtab != usymtab_undefined);
1718 for (i = 0; i < utab->nentries; i++)
1720 uentry thisentry = utab->entries[i];
1721 ekind thisekind = uentry_getKind (thisentry);
1723 if (!uentry_hasRealName (thisentry))
1725 llassert (uentry_isGlobalMarker (thisentry));
1729 check (fputc ('\n', fout) == (int) '\n');
1732 fprintf (fout, "*%d (GlobalMarker)\n", KGLOBALMARKER);
1733 lastekind = KINVALID;
1739 if (thisekind != lastekind)
1743 check (fputc ('\n', fout) == (int) '\n');
1747 lastentry = uentry_undefined;
1748 fprintf (fout, "*%d (%s)\n", ekind_toInt (thisekind),
1749 cstring_toCharsSafe (ekind_capName (thisekind)));
1750 lastekind = thisekind;
1755 ** evans - 2001-02-18 - added the - 48 fudge factor...
1756 ** extra characters dumped, but I haven't counded them carefully...
1759 if (uentry_isInvalid (lastentry) || !uentry_equiv (lastentry, thisentry)
1760 || (linelen > (MAX_DUMP_LINE_LENGTH - (2 * MAX_NAME_LENGTH) - 48)))
1764 DPRINTF (("Dumping entry: %d", i));
1765 cdump = message ("^%d %q", i, uentry_dump (thisentry));
1766 /* was: cdump = uentry_dump (thisentry)); */
1768 lastentry = thisentry;
1771 check (fputc ('\n', fout) == (int) '\n');
1775 linelen += cstring_length (cdump);
1777 /* no new line here! */
1778 if (cstring_length (cdump) > 0)
1780 check (fputs (cstring_toCharsSafe (cdump), fout) != EOF);
1783 cstring_free (cdump);
1788 cstring cdump = uentry_rawName (thisentry);
1789 DPRINTF (("Raw name: %s", cdump));
1790 linelen += (cstring_length (cdump) + 1);
1791 fprintf (fout, "#%s", cstring_toCharsSafe (cdump));
1798 check (fputc ('\n', fout) == (int) '\n');
1801 lastekind = KINVALID;
1803 fprintf(fout, ";; Library constraints\n");
1805 /*drl July 27 added this so that libraries without
1806 buffer constraints would be handled correctly.
1807 I'm trying to do this without breaking older libraries.
1809 Splint should still be able to handle libraries without this message.
1813 fprintf(fout, "start_Buffer_Constraints\n");
1815 for (i = 0; i < utab->nentries; i++)
1817 uentry thisentry = utab->entries[i];
1819 if (uentry_isFunction (thisentry) )
1821 constraintList preconditions;
1822 constraintList postconditions;
1824 preconditions = uentry_getFcnPreconditions (thisentry);
1825 postconditions = uentry_getFcnPostconditions (thisentry);
1827 if ( constraintList_isDefined(preconditions) ||
1828 constraintList_isDefined(postconditions) )
1830 fprintf(fout,"%s\n", cstring_toCharsSafe (uentry_rawName(thisentry) ) );
1831 if (constraintList_isDefined(preconditions) )
1833 fprintf(fout,"pre:\n");
1834 constraintList_dump(preconditions, fout);
1835 fprintf (fout, ";; end precondition constraints\n" );
1836 constraintList_free(preconditions);
1840 fprintf(fout,"pre:EMPTY\n");
1842 if (constraintList_isDefined(postconditions) )
1844 fprintf(fout,"post:\n");
1845 constraintList_dump(postconditions, fout);
1846 fprintf (fout, ";; end precondition constraints\n" );
1847 constraintList_free(postconditions);
1851 fprintf(fout,"post:EMPTY\n");
1860 void usymtab_load (FILE *f)
1861 /*@globals utab, globtab@*/
1862 /*@modifies utab, *f@*/
1864 char *s = mstring_create (MAX_DUMP_LINE_LENGTH);
1866 ekind kind = KINVALID;
1867 fileloc loc = g_currentloc;
1873 llassert (utab == globtab);
1874 llassert (utab->nentries == 0);
1876 while (((s = reader_readLine (f, s, MAX_DUMP_LINE_LENGTH)) != NULL)
1879 /* ignore ; comments */ ;
1882 while (s != NULL && *s != ';')
1890 ek = reader_getInt (&s);
1892 if (ek == KGLOBALMARKER)
1894 uentry lue = uentry_makeGlobalMarker ();
1895 DPRINTF (("Adding global marker: %s", uentry_unparseFull (lue)));
1896 usymtab_addEntryAlways (utab, lue);
1902 kind = ekind_fromInt (ek);
1910 (cstring_makeLiteral
1911 ("Library is in obsolete format. Use splint +whichlib "
1912 "to see which library is being loaded."));
1915 if (reader_optCheckChar (&s, '^'))
1917 index = reader_getInt (&s);
1924 llassert (kind != KINVALID);
1925 ue = uentry_undump (kind, loc, &s);
1927 llassert (utab->nentries == index || index == -1);
1929 if (uentry_isValid (ue))
1931 int lastindex = utab->nentries;
1932 ue = usymtab_addEntryAlways (utab, ue);
1936 if (uentry_isConstant (ue)) /*@i23! isPreProcessorMacro */
1938 cstring uname = uentry_getName (ue);
1940 /* Also check its a macro... */
1941 DPRINTF (("Installing: %s", uname));
1943 cpphash_installMacro
1944 (mstring_copy (cstring_toCharsSafe (uname)),
1945 cstring_length (uname),
1946 cpplib_createDefinition (message ("%s 255", uname),
1949 cpphash_hashCode (cstring_toCharsSafe (uname),
1950 cstring_length (uname),
1953 DPRINTF (("After install: %s", uname));
1957 if (utab->nentries != lastindex + 1)
1959 DPRINTF (("No add: %s", uentry_unparseFull (ue)));
1967 ** now, any other names are the same uentry
1970 while (*(s++) == '#')
1972 cstring name = cstring_fromCharsO (reader_getWord (&s));
1973 uentry nue = uentry_nameCopy (name, ue);
1975 DPRINTF (("Name copy: %s", uentry_unparseFull (nue)));
1979 usymtab_addEntryAlways (utab, nue);
1982 while ((c = *s) != '\0' && (c !='\n'))
1984 if (c != ' ' || c != '\t')
1986 llbuglit ("Junk in load file");
1994 s = reader_readLine (f, os, MAX_DUMP_LINE_LENGTH);
1999 to handle reading of buffer overflow related constraints
2001 while (fgets (s, MAX_DUMP_LINE_LENGTH, f) != NULL
2004 ; /* ignore ;-comments */
2007 /*drl July 27 added this so that libraries without
2008 buffer constraints would be handled correctly.
2009 I'm trying to do this without breaking older libraries*/
2011 /*check for "optional" start buffer constraints message*/
2012 if (cstring_compareLit(cstring_fromChars(s), "start_Buffer_Constraints\n") == 0 )
2014 (void)fgets (s, MAX_DUMP_LINE_LENGTH, f);
2017 while (s != NULL && *s != ';')
2019 constraintList preconditions;
2020 constraintList postconditions;
2022 cstring name = cstring_fromChars(reader_getWord(&s) );
2024 ue = usymtab_lookup ( name );
2028 preconditions = constraintList_undefined;
2029 postconditions = constraintList_undefined;
2031 if (!uentry_isValid(ue) )
2033 llfatalbug ((message("Invalid uentry for %s library file may be corrupted", cstring_fromChars(s) ) ));
2035 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2037 temp = cstring_fromChars (reader_getWord(&s) );
2039 if (cstring_compareLit (temp,"pre:") == 0 )
2041 preconditions = constraintList_undump (f);
2045 if (cstring_compareLit (temp,"pre:EMPTY") != 0 )
2046 llfatalbug ((message("Error reading library file pre:EMPTY expected but got %s", temp ) ));
2051 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2053 temp = cstring_fromChars(reader_getWord(&s) );
2054 if (cstring_compareLit (temp, "post:") == 0 )
2056 postconditions = constraintList_undump (f);
2060 if (cstring_compareLit (temp, "post:EMPTY") != 0 )
2061 llfatalbug ((message("Error reading library file post:EMPTY expected but got %s", temp ) ));
2064 cstring_free (temp);
2066 uentry_setPreconditions (ue, functionConstraint_createBufferConstraint (preconditions));
2067 uentry_setPostconditions (ue, functionConstraint_createBufferConstraint (postconditions));
2069 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2077 ** file scope for static variables
2081 usymtab_enterFile ()
2082 /*@globals utab, globtab, filetab@*/
2083 /*@modifies filetab@*/
2085 llassert (utab == globtab);
2090 usymtab_entries (globtab, ue)
2092 if (sRef_hasDerived (uentry_getSref (ue)))
2094 fprintf (g_warningstream, "Derived Global: %s\n", uentry_unparse (ue));
2095 fprintf (g_warningstream, "sRef: %s\n", sRef_unparseFull (ue->sref));
2097 } end_usymtab_entries ;
2101 usymtab_enterScope ();
2107 /*@globals utab, filetab@*/
2108 /*@modifies filetab, utab@*/
2111 llassert (utab->lexlevel == 1);
2113 usymtab_exitScope (exprNode_undefined);
2118 usymtab_enterScope ()
2119 /*@globals utab, globtab, filetab@*/
2122 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
2124 /* unconditional scope: optimize to avoid copy */
2125 t->aliases = aliasTable_copy (utab->aliases);
2128 llassert (usymtab_isDefined (t->env));
2130 if (t->env->lexlevel == paramsScope && context_inFunctionLike ())
2132 noshadowerror = TRUE;
2133 usymtab_handleParams ();
2134 noshadowerror = FALSE;
2139 ** setup external references:
2140 ** o only, unique params alias external args
2141 ** o other params may alias anything of their type
2145 usymtab_handleParams (void)
2146 /*@globals utab, globtab, filetab@*/
2147 /*@modifies utab, globtab@*/
2149 usymtab ptab = utab->env;
2150 uentry fcn = context_getHeader ();
2152 usymtab_entries (ptab, param)
2156 if (!uentry_isYield (param))
2159 sRef pref = uentry_getSref (param);
2161 /* Could be a global. */
2163 if (uentry_isAnyParam (param))
2165 ue = uentry_makeVariable (fixParamName (uentry_rawName (param)),
2166 uentry_getType (param),
2167 fileloc_copy (uentry_whereDeclared (param)),
2170 uentry_copyState (ue, param);
2171 uentry_setRefParam (ue);
2173 ue = usymtab_supEntrySrefReturn (ue);
2175 /* must be after supercede! */
2177 if (!sRef_stateKnown (pref))
2179 uentry_setDefState (ue, SS_DEFINED);
2180 uentry_setDefState (param, SS_DEFINED);
2184 if (sRef_isStateSpecial (pref))
2186 uentry_setDefState (ue, SS_SPECIAL); /* ALLOCATED); */
2187 /* evans 2002-01-01: should be unnecessary, the pre clauses
2188 ** set the state if necessary.
2193 uentry_setDefState (ue, sRef_getDefState (pref));
2197 uref = uentry_getSref (ue);
2199 if (sRef_isStack (uref))
2201 alkind pkind = sRef_getAliasKind (pref);
2203 if (alkind_isKnown (pkind) && !alkind_isLocal (pkind)
2204 && !alkind_isStack (pkind))
2206 sRef_setAliasKind (uref, pkind, fileloc_undefined);
2207 sRef_setOrigAliasKind (uref, pkind);
2211 sRef_setAliasKind (uref, AK_IMPTEMP, fileloc_undefined);
2212 sRef_setOrigAliasKind (uref, AK_IMPTEMP);
2214 if (uentry_isOut (param))
2220 sRef_setDefined (uref, fileloc_undefined);
2226 usymtab_addMustAlias (uref, pref);
2228 if (!(uentry_isOnly (param) || uentry_isUnique (param)))
2231 ** This is needed for detecting possibly aliased parameters.
2234 sRef s = sRef_makeExternal (uref);
2235 usymtab_addMustAlias (uref, s);
2238 if (sRef_isKillRef (pref))
2240 sRef_setAliasKind (uref, AK_NEWREF, fileloc_undefined);
2241 sRef_setOrigAliasKind (uref, AK_KILLREF);
2243 else if (sRef_isRefCounted (uref))
2245 sRef_setOrigAliasKind (uref, AK_REFCOUNTED);
2250 sRef_setOrigAliasKind (uref, AK_LOCAL);
2257 } end_usymtab_entries;
2260 if (uentry_hasStateClauseList (fcn))
2262 stateClauseList clauses = uentry_getStateClauseList (fcn);
2264 stateClauseList_preElements (clauses, cl)
2266 fileloc loc = stateClause_loc (cl);
2267 sRefSet osrs = sRefSet_undefined;
2270 if (stateClause_isGlobal (cl))
2272 DPRINTF (("Global Marker: %s",
2273 sRef_unparseFull (usymtab_lookupGlobalMarker ())));
2274 llassert (sRef_isGlobalMarker (usymtab_lookupGlobalMarker ()));
2275 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
2280 srs = stateClause_getRefs (cl);
2283 sRefSet_elements (srs, el)
2285 sRef base = sRef_getRootBase (el);
2286 sRef sb = sRef_updateSref (el);
2288 if (sRef_isResult (base))
2290 ; /* nothing to do before */
2292 else if (sRef_isParam (base) || sRef_isGlobalMarker (base))
2294 if (stateClause_setsMetaState (cl))
2296 /* copied from exprNode.c:3040 */
2297 qual ql = stateClause_getMetaQual (cl);
2298 annotationInfo ainfo = qual_getAnnotationInfo (ql);
2299 metaStateInfo minfo = annotationInfo_getState (ainfo);
2300 cstring key = metaStateInfo_getName (minfo);
2301 int mvalue = annotationInfo_getValue (ainfo);
2303 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
2305 if (sRef_isResult (base))
2311 sRef_setMetaStateValueComplete (sb, key, mvalue, loc);
2316 sRefMod modf = stateClause_getEntryFunction (cl);
2320 sRefSet aliases = usymtab_allAliases (sb);
2324 sRefSet_elements (aliases, sr)
2327 } end_sRefSet_elements ;
2329 sRefSet_free (aliases);
2335 if (sRef_isValid (base))
2337 DPRINTF (("Base: %s", sRef_unparseFull (base)));
2341 } end_sRefSet_elements ;
2342 } end_stateClauseList_preElements ;
2347 usymtab_enterFunctionScope (uentry fcn)
2348 /*@globals utab, filetab, globtab@*/
2351 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
2353 DPRINTF (("Enter function: %s", uentry_unparse (fcn)));
2355 if (utab->lexlevel != fileScope)
2357 if (utab->lexlevel > fileScope)
2359 llparseerror (cstring_makeLiteral ("New function scope inside function"));
2361 while (utab->lexlevel > fileScope)
2363 /*@i@*/ utab = usymtab_dropEnv (utab);
2370 llfatalbug (cstring_makeLiteral ("New function not inside file."));
2372 /*@-branchstate@*/ } /*@=branchstate@*/
2376 DPRINTF (("Globs: %s", globSet_unparse (uentry_getGlobs (fcn))));
2378 globSet_allElements (uentry_getGlobs (fcn), el)
2380 DPRINTF (("Here we go: %s", sRef_unparseFull (el)));
2382 if (sRef_isUndefGlob (el))
2384 int index = sRef_getScopeIndex (el);
2385 sRef sr = sRef_updateSref (el);
2386 fileloc loc = uentry_whereEarliest (fcn);
2388 DPRINTF (("update: %s", sRef_unparseFull (sr)));
2389 DPRINTF (("Undef!"));
2390 if (sRef_isFileStatic (el))
2392 ctype ct = sRef_getType (el);
2395 llassert (usymtab_isDefined (filetab));
2397 ue = usymtab_fetchIndex (filetab, index);
2399 if (ctype_isRealArray (ct) || ctype_isRealSU (ct))
2401 sRef_setAllocated (sr, loc);
2405 sRef_setUndefined (sr, loc);
2410 uentry ue = globtab->entries[index];
2411 ctype ct = uentry_getType (ue);
2413 if (ctype_isArray (ct) || ctype_isSU (ct))
2415 sRef_setAllocated (sr, loc);
2419 sRef_setUndefined (sr, loc);
2423 else if (sRef_isAllocated (el))
2425 sRef sr = sRef_updateSref (el);
2426 fileloc loc = uentry_whereEarliest (fcn);
2428 sRef_setAllocated (sr, loc);
2430 else if (sRef_isPartial (el))
2432 sRef sr = sRef_updateSref (el);
2433 fileloc loc = uentry_whereEarliest (fcn);
2435 sRef_setPartial (sr, loc);
2440 sRef sr = sRef_updateSref (el);
2441 fileloc loc = uentry_whereEarliest (fcn);
2443 sRef_setDefined (sr, loc);
2447 /* shouldn't need to do anything! */
2449 } end_globSet_allElements;
2451 DPRINTF (("Globs after: %s", globSet_unparse (uentry_getGlobs (fcn))));
2453 usymtab_checkAllValid ();
2458 usymtab_caseBranch (void)
2461 usymtab t = usymtab_create (US_CBRANCH, utab, FALSE);
2466 usymtab_switchBranch (/*@unused@*/ exprNode s)
2469 usymtab t = usymtab_create (US_SWITCH, utab, FALSE);
2471 t->aliases = aliasTable_copy (utab->aliases);
2476 usymtab_trueBranch (/*@only@*/ guardSet guards)
2479 usymtab t = usymtab_create (US_TBRANCH, utab, FALSE);
2482 ** not true! (could be in a macro)
2484 ** llassertprint (utab->lexlevel > paramsScope,
2485 ** ("not in scope: %s", usymtab_unparseLocal ()));
2489 guardSet_free (t->guards);
2492 aliasTable_free (t->aliases);
2493 t->aliases = aliasTable_copy (utab->aliases);
2501 ** { int a; if (...) a = 3; < a may be undefined here!
2506 usymtab_popTrueBranch (exprNode pred, exprNode expr, clause cl) /*@modifies utab@*/
2509 ** add a false branch
2510 ** (could be done more efficiently as a special case, but
2511 ** it is better to only maintain one version of the code)
2514 if (utab->kind != US_TBRANCH
2515 && context_inIterDef ())
2517 usymtab_exitScope (expr);
2521 DPRINTF (("pop true branch.."));
2522 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2523 usymtab_popBranches (pred, expr, exprNode_undefined, TRUE, cl);
2528 usymtab_popCaseBranch () /*@modifies utab@*/
2530 llassert (utab->kind == US_CBRANCH);
2531 usymtab_quietPlainExitScope ();
2535 usymtab_popTrueExecBranch (exprNode pred, exprNode expr, clause cl)
2538 ** add a false branch that must return --- that is,
2539 ** the true branch is always executed!
2542 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2543 usymtab_popBranches (pred, expr, exprNode_makeMustExit (), FALSE, cl);
2547 usymtab_popOrBranch (exprNode pred, exprNode expr)
2551 usymtab env = utab->env;
2552 usymtab otab = utab;
2555 llassert (env != NULL);
2557 if (exprNode_isError (expr))
2563 mustReturn = exprNode_mustEscape (expr);
2567 llassert (utab->kind == US_TBRANCH);
2570 ** merge each entry in table with its original
2571 ** unless execution cannot continue after this branch
2574 for (i = 0; i < utab->nentries; i++)
2576 uentry current = utab->entries[i];
2577 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2579 uentry_mergeState (old, current, exprNode_loc (expr),
2580 mustReturn, FALSE, TRUE, ORCLAUSE);
2586 env->guards = guardSet_levelUnionFree (env->guards,
2587 guardSet_invert (exprNode_getGuards (pred)),
2592 env->aliases = aliasTable_levelUnion (env->aliases, otab->aliases, env->lexlevel);
2595 /* env is now utab */
2596 usymtab_quietPlainExitScope ();
2600 ** case syntax in C is very unrestricted. This is unfortunate.
2602 ** A switch case is ended either by a new case or default, or
2603 ** a close } that may close the switch or some other control
2608 usymtab_newCase (/*@unused@*/ exprNode pred, exprNode last)
2611 bool mustBreak = usymtab_mustBreak (utab);
2612 bool mustReturn = usymtab_mustEscape (utab);
2613 usymtab stab = utab;
2615 DPRINTF (("New case!"));
2618 ** Find last case (or outer switch)
2621 while (stab->kind != US_CBRANCH && stab->kind != US_SWITCH)
2624 llassert (stab != GLOBAL_ENV);
2627 while (stab->kind == US_CBRANCH)
2630 llassert (stab != GLOBAL_ENV);
2634 ** if its a fall through case, merge in outside entries and last case.
2639 ** case 1: x = 3; <fall through>
2640 ** case 2: << x may not be defined
2644 if (!mustBreak && !mustReturn && utab->kind == US_CBRANCH)
2646 llassert (stab->kind == US_SWITCH || stab->kind == US_NORMAL);
2648 usymtab_entries (utab, ue) /* but, keep track of used variables */
2650 uentry old = usymtab_lookupAux (stab, uentry_rawName (ue));
2652 llassert (uentry_isValid (old));
2654 /* modifies ue, not old */
2656 uentry_mergeState (ue, old, exprNode_loc (last),
2657 FALSE, FALSE, TRUE, CASECLAUSE);
2658 } end_usymtab_entries;
2660 utab->aliases = aliasTable_levelUnion (utab->aliases,
2661 stab->aliases, utab->lexlevel);
2664 ** No need for a new branch.
2671 usymtab_caseBranch ();
2672 /*@-mustfree@*/ /*< utab->aliases >*/
2673 utab->aliases = aliasTable_copy (stab->aliases);
2681 ** for && (both pred and expr are executed)
2685 usymtab_popAndBranch (exprNode pred, /*@unused@*/ exprNode expr)
2688 usymtab env = utab->env;
2692 llassert (utab->kind == US_TBRANCH);
2695 ** merge each entry in table with its original
2696 ** unless execution cannot continue after this branch
2699 for (i = 0; i < utab->nentries; i++)
2701 uentry current = utab->entries[i];
2702 sRef tref = uentry_getSref (current);
2703 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2704 sRef oref = uentry_getSref (old);
2706 /* note that is current is in a nested branch,
2707 it may create a "new" old entry. */
2709 llassert (uentry_isValid (old));
2710 uentry_mergeState (old, current, exprNode_loc (expr),
2711 FALSE, FALSE, TRUE, ANDCLAUSE);
2714 ** if is it defined by the second clause, then it should be defined.
2717 if (sRef_isAnyDefined (tref)
2718 && (sRef_isAllocated (oref) || sRef_isStateUndefined (oref)))
2720 sRef_setDefined (oref, g_currentloc);
2724 utab->guards = guardSet_levelUnionFree (utab->guards,
2725 guardSet_invert (exprNode_getGuards (pred)),
2727 utab->aliases = aliasTable_levelUnion (utab->aliases, otab->aliases, utab->lexlevel);
2729 usymtab_quietPlainExitScope ();
2734 ** Stack should be [ US_CBRANCH+ US_SWITCH ]
2735 ** Only branches which do not return (except possibly the last branch) are included.
2737 ** Conditionally merge state from all CBRANCHes.
2739 ** If allpaths is TRUE, then all possible executions go through some switch
2740 ** case, and the original scope is not merged.
2744 usymtab_exitSwitch (/*@unused@*/ exprNode sw, bool allpaths)
2747 usymtab ttab = utab;
2748 usymtab stab = ttab;
2749 usymtab ltab = ttab;
2750 bool lastMustReturn = usymtab_mustEscape (utab);
2754 while (stab->kind == US_CBRANCH)
2757 llassert (stab != GLOBAL_ENV);
2760 while (stab->kind == US_NORMAL)
2763 llassert (stab != GLOBAL_ENV);
2766 llassert (stab->kind == US_SWITCH);
2768 /* go to the scope outside the switch (US_SWITCH is just a marker! */
2770 llassert (stab != GLOBAL_ENV);
2774 llassert (usymtab_isDefined (ttab));
2776 if (ttab->kind == US_CBRANCH)
2778 /* was quietPlainExitScope --- but, can't free it yet! */
2780 llassert (utab != GLOBAL_ENV);
2782 while (ttab->kind == US_CBRANCH)
2785 ** (from popTrueBranch)
2788 bool mustReturn = usymtab_mustEscape (ttab);
2789 bool mustBreak = usymtab_mustBreak (ttab);
2791 usymtab_entries (ttab, current)
2793 uentry old = /*@-compmempass@*/ usymtab_lookupAux (ltab, uentry_rawName (current));
2797 ** note that is this is in a nested branch,
2798 ** it may create a "new" old entry.
2801 if (uentry_isValid (old))
2805 uentry_mergeUses (current, old);
2806 uentry_setState (old, current);
2810 uentry_mergeState (old, current, exprNode_loc (sw),
2811 mustReturn, FALSE, TRUE, SWITCHCLAUSE);
2818 } end_usymtab_entries;
2821 ** if entry is not in symbol table for this case, merge with pre-switch
2825 if (!mustReturn && !mustBreak)
2827 usymtab_entries (stab, current)
2829 if (usymtab_getIndex (ttab, uentry_rawName (current)) == NOT_FOUND)
2831 uentry old = /*@-compmempass@*/
2832 usymtab_lookupAux (ltab, uentry_rawName (current));
2835 llassert (uentry_isValid (old));
2836 uentry_mergeState (old, current, exprNode_loc (sw),
2837 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2839 } end_usymtab_entries;
2842 ltab->env = ttab->env;
2846 ** Suprious error, becuase of environments.
2849 /*@i1@*/ utab = ltab;
2851 lastMustReturn = FALSE;
2858 ** now, there is one US_CBRANCH. Merge this with the stab.
2862 for (i = 0; i < ltab->nentries; i++)
2864 uentry current = ltab->entries[i];
2865 uentry old = usymtab_lookupAux (stab, uentry_rawName (current));
2867 /* note that is this is in a nested branch,
2868 it may create a "new" old entry. */
2871 if (uentry_isValid (old))
2875 uentry_mergeUses (current, old);
2876 uentry_setState (old, current);
2880 uentry_mergeState (old, current, exprNode_loc (sw),
2881 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2895 ** switch may or may not be followed by a new scope
2898 if (utab->kind == US_SWITCH)
2900 usymtab_quietPlainExitScope ();
2904 usymtab_quietPlainExitScope ();
2905 llassert (utab->kind == US_SWITCH);
2906 usymtab_quietPlainExitScope ();
2912 updateNullState (sRef el, /*@notnull@*/ usymtab ttab,
2913 /*@notnull@*/ usymtab ftab, bool trueGuard)
2915 sRef base = sRef_getRootBase (el);
2916 int level = sRef_lexLevel (base);
2918 if (sRef_isCvar (base))
2920 usymId index = sRef_getScopeIndex (base);
2921 uentry ue = usymtab_getRefTab (ttab, level, index);
2923 if (!uentry_isLset (ue))
2925 sRef sr = uentry_getSref (ue);
2929 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2933 if (!guardSet_isGuarded (ttab->guards, el)
2934 && !sRef_isNotNull (sr))
2936 DPRINTF (("Here! %s / %s",
2937 sRef_unparseFull (sr),
2938 sRef_unparseFull (el)));
2939 sRef_setDerivNullState (sr, el, NS_DEFNULL);
2948 ue = usymtab_getRefTab (ftab, level, index);
2950 if (!uentry_isLset (ue))
2952 sRef sr = uentry_getSref (ue);
2954 if (!trueGuard) /* yikes! forgot the ! */
2956 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2961 if (!guardSet_isGuarded (ftab->guards, el)
2962 && !sRef_isNotNull (sr))
2964 sRef_setDerivNullState (sr, el, NS_DEFNULL);
2976 usymtab_popBranches (exprNode pred, exprNode tbranch, exprNode fbranch,
2977 bool isOpt, clause cl)
2981 usymtab ftab = utab;
2982 usymtab ttab = utab->env;
2986 guardSet guards = exprNode_getGuards (pred);
2987 sRefSet tguards = guardSet_getTrueGuards (guards);
2988 sRefSet fguards = guardSet_getFalseGuards (guards);
2989 bool mustReturnT = exprNode_mustEscape (tbranch);
2990 bool mustReturnF = exprNode_mustEscape (fbranch);
2992 DPRINTF (("Pop branches: %s [mustreturn: %s/%s]", exprNode_unparse (pred),
2993 bool_unparse (mustReturnT),
2994 bool_unparse (mustReturnF)));
2996 if (exprNode_isDefined (fbranch))
2998 loc = exprNode_loc (fbranch);
3002 loc = exprNode_loc (tbranch);
3005 llassert (usymtab_isDefined (ttab));
3009 llassert (usymtab_isDefined (env));
3010 llassert (ftab->kind == US_FBRANCH);
3011 llassert (ttab->kind == US_TBRANCH);
3014 ** For each element that is true guarded (i.e., if (x != NULL))
3015 ** make x = null in false branch,
3016 ** and x = notnull in true branch.
3017 ** unless x was set locally in that branch.
3018 ** For each element that is false guarded (x == NULL)
3019 ** make x = null in true, notnull in false.
3021 ** For each element that is either guarded (pred(x))
3025 sRefSet_allElements (tguards, el)
3027 updateNullState (el, ttab, ftab, TRUE);
3028 } end_sRefSet_allElements;
3030 sRefSet_allElements (fguards, el)
3032 updateNullState (el, ttab, ftab, FALSE);
3033 } end_sRefSet_allElements;
3037 ** if an entry is in both true and false, merge the entries,
3038 ** then replace original with new state.
3040 ** if an entry is in one table, merge it with the original.
3043 DPRINTF (("ftab: %d", ftab->nentries));
3045 for (i = 0; i < ftab->nentries; i++)
3047 uentry fthis = ftab->entries[i];
3048 uentry old = usymtab_lookupAux (env, uentry_rawName (fthis));
3049 int tindex = usymtab_getIndex (ttab, uentry_rawName (fthis));
3051 DPRINTF (("Entry: %s / %s", uentry_unparseFull (fthis), uentry_unparseFull (old)));
3053 if (uentry_isUndefined (old))
3055 /* possible entry was added as an undefined id */
3056 DPRINTF (("Undefined! %s", uentry_rawName (fthis)));
3060 if (tindex != NOT_FOUND)
3062 uentry tthis = ttab->entries[tindex];
3064 /* note that is this is in a nested branch,
3065 it may create a "new" old entry. */
3071 uentry_mergeState (fthis, tthis, loc,
3072 mustReturnT, FALSE, FALSE, cl);
3076 uentry_mergeUses (fthis, tthis);
3079 uentry_setState (old, fthis);
3086 uentry_setState (old, tthis);
3087 uentry_mergeState (old, fthis, loc, mustReturnF,
3091 ttab->entries[tindex] = uentry_undefined;
3092 uentry_free (tthis);
3096 uentry_mergeState (old, fthis, loc, mustReturnF, TRUE, FALSE, cl);
3100 for (i = 0; i < ttab->nentries; i++)
3102 uentry current = ttab->entries[i];
3104 DPRINTF (("ttab: %s", uentry_unparseFull (current)));
3106 if (!uentry_isUndefined (current))
3108 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
3110 DPRINTF (("Old: %s", uentry_unparseFull (old)));
3112 if (uentry_isUndefined (old))
3114 llcontbug (message ("Undefined entry: %s", uentry_rawName (current)));
3120 uentry_mergeUses (current, old);
3121 uentry_setState (old, current);
3126 ** Assumes false branch is a fall-through if
3127 ** fbranch is not defined. This is true, unless
3128 ** where was some greivous error in processing
3129 ** the else branch of an if-then, in which case
3130 ** this is probably the right thing to do anyway.
3133 uentry_mergeState (old, current, loc, mustReturnT,
3137 DPRINTF (("==> %s", uentry_unparseFull (old)));
3142 ** Plain levelUnion doesn't work, since we need to use the sRef's in env->aliases
3143 ** if they are present.
3146 llassert (NOALIAS (env->aliases, ttab->aliases));
3147 llassert (NOALIAS (env->aliases, ftab->aliases));
3149 aliasTable_free (env->aliases);
3151 env->aliases = aliasTable_levelUnionNew (ttab->aliases,
3152 ftab->aliases, env->lexlevel);
3154 aliasTable_fixSrefs (env->aliases);
3156 DPRINTF (("Aliases: %s", aliasTable_unparse (env->aliases)));
3158 /* exit true and false scopes */
3159 usymtab_quietPlainExitScope ();
3160 usymtab_quietPlainExitScope ();
3164 utab->guards = guardSet_levelUnionFree
3166 guardSet_invert (exprNode_getGuards (pred)),
3172 utab->guards = guardSet_levelUnion (utab->guards,
3173 exprNode_getGuards (pred),
3177 DPRINTF (("Here."));
3180 static void usymtab_fixCases (void) /*@modifies utab@*/ {
3181 while (utab->kind == US_CBRANCH)
3183 usymtab_quietPlainExitScope ();
3186 llassert (utab->kind != US_CBRANCH);
3190 usymtab_altBranch (/*@only@*/ guardSet guards)
3194 usymtab parent = utab->env;
3196 t = usymtab_create (US_FBRANCH, utab, FALSE);
3199 ** If we are in a case, need to close it. The C syntax
3200 ** is very liberal, so this kludge is necessary.
3203 usymtab_fixCases ();
3205 DPRINTF (("Current kind: %s", usymtab_unparseStack ()));
3207 llassert (utab->kind == US_TBRANCH);
3208 llassert (parent != GLOBAL_ENV);
3210 guardSet_free (t->guards);
3213 aliasTable_free (t->aliases);
3214 t->aliases = aliasTable_copy (parent->aliases);
3220 usymtab_allDefined (void)
3221 /*@globals utab, globtab@*/
3225 llassert (utab == globtab);
3227 for (i = 0; i < utab->nentries; i++)
3229 uentry e = utab->entries[i];
3231 if (uentry_isPriv (e))
3233 ; /* no need to define it */
3237 if (context_getFlag (FLG_SPECUNDECL))
3239 fileloc sloc = uentry_whereSpecified (e);
3240 fileloc dloc = uentry_whereDeclared (e);
3242 if (fileloc_isDefined (sloc)
3243 && !uentry_isFakeTag (e)
3244 && !fileloc_isDefined (dloc))
3248 message ("%s %q specified but not declared",
3249 ekind_capName (uentry_getKind (e)),
3250 uentry_getName (e)),
3255 if (!uentry_isCodeDefined (e))
3257 fileloc dloc = uentry_whereDeclared (e);
3259 if (fileloc_isLib (dloc) || fileloc_isXHFile (dloc))
3263 else if (fileloc_isDefined (dloc))
3265 if (!uentry_isAnyTag (e))
3267 if (fileloc_isUser (dloc))
3271 message ("%s %q declared but not defined",
3272 ekind_capName (uentry_getKind (e)),
3273 uentry_getName (e)),
3275 DPRINTF (("decl: %s", uentry_unparseFull (e)));
3281 fileloc sloc = uentry_whereSpecified (e);
3283 if (fileloc_isDefined (sloc)
3284 && !fileloc_isImport (sloc)
3285 && !fileloc_isLib (sloc)
3286 && !fileloc_isPreproc (sloc)
3287 && !uentry_isFakeTag (e))
3289 if (uentry_isVariable (e) || uentry_isFunction (e))
3293 message ("%s %q specified but not declared or defined",
3294 ekind_capName (uentry_getKind (e)),
3295 uentry_getName (e)),
3302 message ("%s %q specified but not defined",
3303 ekind_capName (uentry_getKind (e)),
3304 uentry_getName (e)),
3314 void usymtab_exportHeader (void)
3319 for (i = 0; i < utab->nentries; i++)
3321 uentry ce = utab->entries[i];
3323 if (!uentry_isDatatype (ce)
3324 && !uentry_isAnyTag (ce)
3325 && !uentry_isEitherConstant (ce) && !uentry_isStatic (ce)
3326 && !uentry_isExternal (ce)
3327 && !uentry_isForward (ce))
3329 fileloc fwhere = uentry_whereDeclared (ce);
3331 if (fileloc_isUndefined (fwhere)
3332 && uentry_isFunction (ce))
3334 fwhere = uentry_whereDefined (ce);
3337 if (fileloc_isDefined (fwhere)
3338 && !fileloc_isHeader (fwhere)
3339 && !fileloc_isXHFile (fwhere)
3340 && !(fileloc_isSpecialFile (fwhere)
3341 && !context_getFlag (FLG_UNUSEDSPECIAL)))
3343 if (uentry_isVariable (ce))
3346 (FLG_EXPORTHEADERVAR,
3347 message ("%s %q exported but not declared in header file",
3348 ekind_capName (uentry_getKind (ce)),
3349 uentry_getName (ce)),
3352 uentry_showDefSpecInfo (ce, fwhere);
3357 if (!uentry_isIter (ce)
3358 && !uentry_isEndIter (ce)
3359 && !uentry_isExpandedMacro (ce))
3361 if (uentry_isFunction (ce)
3362 && cstring_equalLit (uentry_rawName (ce), "main"))
3364 ; /* no error for main */
3370 message ("%s %q exported but not declared "
3372 ekind_capName (uentry_getKind (ce)),
3373 uentry_getName (ce)),
3376 uentry_showDefSpecInfo (ce, fwhere);
3386 void usymtab_exportLocal (void)
3391 for (i = 0; i < utab->nentries; i++)
3393 uentry ce = utab->entries[i];
3395 if (!uentry_isDatatype (ce) && !uentry_isAnyTag (ce)
3396 && !uentry_isEitherConstant (ce)
3397 && !uentry_isIter (ce)
3398 && !uentry_isEndIter (ce)
3399 && !uentry_isExpandedMacro (ce)
3400 && uentry_isUsed (ce))
3402 /* check static uses */
3403 filelocList fuses = uentry_getUses (ce);
3404 fileloc mod = uentry_whereDefined (ce);
3405 bool ok = filelocList_isEmpty (fuses);
3406 fileloc fwhere = uentry_whereDeclared (ce);
3408 if (fileloc_isSpecialFile (fwhere)
3409 && !context_getFlag (FLG_UNUSEDSPECIAL))
3411 ok = TRUE; /* no errors for special files */
3415 filelocList_elements (fuses, uloc)
3417 if (fileloc_isUndefined (uloc) || !fileloc_sameModule (uloc, mod))
3420 /*@innerbreak@*/ break;
3422 } end_filelocList_elements;
3429 message ("%s exported but not used outside %s: %q",
3430 ekind_capName (uentry_getKind (ce)),
3431 fileloc_getBase (mod),
3432 uentry_getName (ce)),
3435 uentry_showDefSpecInfo (ce, fwhere);
3443 usymtab_allUsed (void)
3447 bool isFileStatic = usymtab_inFileScope ();
3448 cstring last_file = cstring_undefined;
3450 for (i = 0; i < utab->nentries; i++)
3452 bool hasError = FALSE;
3453 uentry ce = utab->entries[i];
3454 fileloc fwhere = uentry_whereDeclared (ce);
3456 if (fileloc_isUndefined (fwhere))
3458 fwhere = uentry_whereDefined (ce);
3461 if (fileloc_isInvalid (fwhere)
3462 || fileloc_isLib (fwhere)
3463 || fileloc_isBuiltin (fwhere)
3464 || ((fileloc_isSpecialFile (fwhere)
3465 || fileloc_isSpecialFile (uentry_whereDefined (ce)))
3466 && !context_getFlag (FLG_UNUSEDSPECIAL)))
3470 else if (!uentry_wasUsed (ce) && !uentry_isAnyTag (ce))
3472 cstring fname = fileloc_filename (fwhere);
3474 if (cstring_isUndefined (last_file))
3478 else if (cstring_equal (fname, last_file))
3487 if (uentry_isParam (ce))
3489 if (context_inMacro ())
3491 sRef cref = uentry_getSref (ce);
3493 if (uentry_isYield (ce))
3495 ; /* no checks (for now) */
3497 else if (sRef_isSafe (cref))
3503 if (uentry_hasRealName (ce))
3506 optgenerror (FLG_MACROPARAMS,
3507 message ("Macro parameter %q not used",
3508 uentry_getName (ce)),
3515 if (cstring_equalFree (uentry_getName (ce),
3516 cstring_makeLiteral ("...")))
3522 hasError = optgenerror (FLG_PARAMUNUSED,
3523 message ("Parameter %q not used",
3524 uentry_getName (ce)),
3529 else if (uentry_isFunction (ce) || uentry_isIter (ce))
3531 if (fileloc_isUser (fwhere))
3533 hasError = optgenerror
3535 message ("%q %q declared but not used",
3537 (uentry_isIter (ce) ? "Iterator"
3538 : (isFileStatic ? "File static function" : "Function")),
3539 uentry_getName (ce)),
3543 else if (uentry_isEndIter (ce))
3545 ; /* no error (already reported for iter */
3547 else if (uentry_isEnumConstant (ce))
3549 if (fileloc_isUser (fwhere))
3551 hasError = optgenerror
3553 message ("Enum member %q not used",
3554 uentry_getName (ce)),
3558 else if (uentry_isConstant (ce))
3560 if (fileloc_isUser (fwhere))
3562 hasError = optgenerror
3564 message ("Constant %q declared but not used",
3565 uentry_getName (ce)),
3569 else if (uentry_isDatatype (ce))
3571 if (fileloc_isUser (fwhere))
3573 hasError = optgenerror
3575 message ("Type %q declared but not used",
3576 uentry_getName (ce)),
3580 else if (!uentry_isRefParam (ce) && !uentry_isExpandedMacro (ce))
3581 { /* errors for ref params will be reported in the next scope */
3582 llassertprint (uentry_isVar (ce),
3583 ("ce: %s", uentry_unparseFull (ce)));
3585 if (ctype_isFunction (uentry_getType (ce)))
3587 if (fileloc_isUser (fwhere))
3589 hasError = optgenerror
3591 message ("%q %q declared but not used",
3593 (isFileStatic ? "File static function"
3595 uentry_getName (ce)),
3601 if (fileloc_isUser (fwhere))
3605 hasError = optgenerror
3607 message ("%q %q declared but not used",
3609 (isFileStatic ? "File static variable"
3611 uentry_getName (ce)),
3621 else if ((uentry_isDatatype (ce) || uentry_isAnyTag (ce)))
3622 { /* check all fields */
3623 ctype ct = uentry_getRealType (ce);
3626 while (ctype_isAP (ct))
3628 ct = ctype_getBaseType (ct);
3631 if (ctype_isSU (ct))
3633 uentryList fields = ctype_getFields (ct);
3635 uentryList_elements (fields, field)
3637 if (!uentry_isUsed (field))
3639 if (uentry_hasName (ce))
3641 hasError |= optgenerror
3643 message ("Field %q of %s %q declared but not used",
3644 uentry_getName (field),
3645 cstring_makeLiteralTemp
3646 (ctype_isStruct (ct) ? "structure" : "union"),
3647 uentry_getName (ce)),
3648 uentry_whereEarliest (field));
3654 ** Can't report these errors for unnamed structs.
3655 ** No way to tell when there are multiple consistent
3656 ** unnamed structure types. (Could go through table
3657 ** and mark them all unused...)
3659 hasError |= optgenerror
3661 message ("Field %q of unnamed %s declared but not used",
3662 uentry_getName (field),
3663 cstring_makeLiteralTemp
3664 (ctype_isStruct (ct) ? "structure" : "union")),
3665 uentry_whereEarliest (field));
3670 uentry_setUsed (field, fileloc_undefined);
3672 } end_uentryList_elements;
3682 if (uentry_isParam (ce) && context_inMacro ())
3684 if (fileloc_isDefined (uentry_whereSpecified (ce)))
3686 uentry_showWhereSpecified (ce);
3691 uentry_showDefSpecInfo (ce, fwhere);
3694 uentry_setUsed (ce, fileloc_undefined);
3700 checkGlobalReturn (uentry glob, sRef orig)
3702 sRef sr = uentry_getSref (glob);
3704 DPRINTF (("Check global return: %s / orig: %s / sr: %s",
3705 uentry_unparseFull (glob),
3706 sRef_unparseFull (orig),
3707 sRef_unparseFull (sr)));
3709 DPRINTF (("Is killed: %s", bool_unparse (sRef_isKilledGlob (orig))));
3711 if (context_getFlag (FLG_GLOBSTATE))
3713 DPRINTF (("Is killed: %s", sRef_unparseFull (orig)));
3715 if (sRef_isKilledGlob (orig))
3717 if (sRef_isStateUndefined (sr)
3718 || sRef_isUnuseable (sr)
3719 || sRef_isStateUnknown (sr)
3720 || sRef_isDead (sr))
3726 ctype ct = ctype_realType (uentry_getType (glob));
3728 DPRINTF (("Check global destroyed: %s", uentry_unparseFull (glob)));
3730 if (ctype_isVisiblySharable (ct))
3735 ("Killed global %q (type %s) not released before return",
3736 uentry_getName (glob),
3737 ctype_unparse (ct)),
3740 sRef_showStateInfo (sr);
3745 sRef_protectDerivs ();
3746 (void) transferChecks_globalDestroyed (sr, g_currentloc);
3747 sRef_clearProtectDerivs ();
3753 if (sRef_isStateUndefined (sr))
3755 if (optgenerror (FLG_GLOBSTATE,
3757 ("Function returns with global %q undefined",
3758 uentry_getName (glob)),
3761 sRef_showStateInfo (sr);
3766 if (sRef_isDead (sr) || sRef_isKept (sr))
3770 message ("Function returns with global %q "
3771 "referencing %s storage",
3772 uentry_getName (glob),
3773 cstring_makeLiteralTemp (sRef_isDead (sr) ? "released" : "kept")),
3776 if (sRef_isKept (sr))
3778 sRef_showAliasInfo (sr);
3782 sRef_showStateInfo (sr);
3785 sRef_setDefState (sr, SS_UNKNOWN, fileloc_undefined);
3789 if (ctype_isRealPointer (uentry_getType (glob))
3790 && sRef_possiblyNull (sr)
3791 && !uentry_possiblyNull (glob))
3795 message ("Function returns with non-null global %q "
3796 "referencing null storage",
3797 uentry_getName (glob)),
3800 sRef_showNullInfo (sr);
3805 DPRINTF (("Check transfer: %s", uentry_unparseFull (glob)));
3806 transferChecks_globalReturn (glob);
3814 ** remember: check alias globals
3817 void usymtab_checkFinalScope (bool isReturn)
3820 bool mustFree = context_getFlag (FLG_MUSTFREEONLY) || context_getFlag (FLG_MUSTFREEFRESH); /*@i423 remove this mustFree */
3821 bool mustDefine = context_getFlag (FLG_MUSTDEFINE);
3822 /* bool mustNotAlias = context_getFlag (FLG_MUSTNOTALIAS); */
3823 sRefSet checked = sRefSet_new ();
3824 usymtab stab = utab;
3828 ** need to check all scopes out to function parameters.
3833 for (i = 0; i < stab->nentries; i++)
3835 uentry ce = stab->entries[i];
3836 sRef sr = uentry_getSref (ce);
3837 sRef rb = sRef_getRootBase (sr);
3841 ** Shouldn't check if shadow checked in deeper scope:
3846 uentry oue = usymtab_lookupQuietNoAlt (utab, uentry_observeRealName (ce));
3848 if (!uentry_sameObject (ce, oue))
3850 DPRINTF (("Skipping outer entry: %s / %s", uentry_unparseFull (ce),
3851 uentry_unparseFull (oue)));
3852 /*@i32 what if it is one an alternate branch? */
3853 /*@innercontinue@*/ continue;
3857 DPRINTF (("Here check final scope: %s", uentry_unparseFull (ce)));
3859 if (ctype_isFunction (uentry_getType (ce)))
3861 /*@innercontinue@*/ continue;
3864 if (uentry_isAnyParam (ce)
3865 || uentry_isRefParam (ce)
3866 || sRef_isFileOrGlobalScope (rb))
3868 /* Don't do the loseref check...but should check state! */
3869 DPRINTF (("Skipping check 1"));
3871 else if (sRef_isDefinitelyNull (sr)
3872 || usymtab_isDefinitelyNull (sr))
3875 ** No state reference errors for definitely null references.
3878 DPRINTF (("Skipping check 2"));
3882 DPRINTF (("Lose ref: %s / %s", uentry_unparse (ce),
3883 sRef_unparseFull (sr)));
3885 tvalues = sRef_getValueTable (sr);
3887 valueTable_elements (tvalues, fkey, fval) {
3888 metaStateInfo minfo;
3889 cstring msg = cstring_undefined;
3892 minfo = context_lookupMetaStateInfo (fkey);
3893 llassert (metaStateInfo_isDefined (minfo));
3895 if (stateValue_isError (fval)
3896 || sRef_isStateUndefined (sr)) /* No errors for undefined state */
3898 DPRINTF (("Skipping check 3"));
3902 DPRINTF (("Check: %s / %s / %s", fkey,
3903 metaStateInfo_unparse (minfo),
3904 stateValue_unparse (fval)));
3906 minfo = context_lookupMetaStateInfo (fkey);
3908 nval = stateCombinationTable_lookupLoseReference
3909 (metaStateInfo_getTransferTable (minfo),
3910 stateValue_getValue (fval), &msg);
3912 if (cstring_isDefined (msg))
3914 /*@i32 print extra info for assignments@*/
3915 DPRINTF (("From: %s", sRef_unparseFull (sr)));
3916 DPRINTF (("Null? %s / %s",
3917 bool_unparse (sRef_isDefinitelyNull (sr)),
3918 bool_unparse (usymtab_isGuarded (sr))));
3923 ("%s loses reference %q in invalid state %q (%s)",
3924 cstring_makeLiteralTemp (isReturn ? "Return" : "Scope exit"),
3925 uentry_getName (ce),
3926 stateValue_unparseValue (fval, minfo),
3930 stateValue_show (fval, minfo);
3934 DPRINTF (("Suppressed transfer error: %s", msg));
3938 } end_valueTable_elements;
3941 DPRINTF (("Here 1"));
3945 DPRINTF (("Check mustfree entry: %s", uentry_unparseFull (ce)));
3947 if (!sRefSet_member (checked, sr) && !sRef_isFileOrGlobalScope (rb))
3949 if (ctype_isRealSU (uentry_getType (ce))
3950 && !uentry_isAnyParam (ce)
3951 && !uentry_isRefParam (ce)
3952 && !uentry_isStatic (ce)
3953 && !sRef_isDependent (sr)
3954 && !sRef_isOwned (sr))
3956 sRefSet als = usymtab_allAliases (sr);
3958 if (sRefSet_isEmpty (als))
3960 transferChecks_localDestroyed (sr, g_currentloc);
3964 /* aliased, no problem */ ;
3970 (!uentry_isStatic (ce)
3971 && ((sRef_isNewRef (sr))
3972 || (((sRef_isOnly (sr) || sRef_isFresh (sr)
3973 || sRef_isKeep (sr) || sRef_isOwned (sr))
3974 && !sRef_isDead (sr))
3975 && (!sRef_definitelyNull (sr))
3976 && (!usymtab_isDefinitelyNull (sr)))))
3978 bool hasError = TRUE;
3980 DPRINTF (("Checking: %s", sRef_unparseFull (sr)));
3983 ** If its a scope exit, check if there is an alias.
3984 ** If so, make it only. If not, there is an error.
3989 if (transferChecks_canLoseReference (sr, g_currentloc))
3991 DPRINTF (("Can lose!"));
3998 if (sRef_hasLastReference (sr))
4000 sRef ar = sRef_getAliasInfoRef (sr);
4003 (sRef_isFresh (ar) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4005 ("Last reference %q to %s storage %qnot %q before %q",
4007 alkind_unparse (sRef_getAliasKind (sr)),
4008 sRef_unparseOpt (ar),
4009 cstring_makeLiteral (sRef_isKeep (sr)
4010 ? "transferred" : "released"),
4011 cstring_makeLiteral (isReturn
4012 ? "return" : "scope exit")),
4015 sRef_showRefLost (sr);
4018 else if (sRef_isNewRef (sr))
4021 (sRef_isFresh (sr) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4023 ("%q %q not released before %q",
4025 (alkind_isKillRef (sRef_getOrigAliasKind (sr))
4026 ? "Kill reference parameter" : "New reference"),
4027 uentry_getName (ce),
4028 cstring_makeLiteral (isReturn
4029 ? "return" : "scope exit")),
4032 sRef_showAliasInfo (sr);
4037 if (ctype_isRealSU (sRef_getType (sr)))
4039 transferChecks_structDestroyed (sr, g_currentloc);
4043 DPRINTF (("Here we are: %s", sRef_unparseFull (sr)));
4046 (sRef_isFresh (sr) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4048 ("%s storage %q not %q before %q",
4049 alkind_capName (sRef_getAliasKind (sr)),
4050 uentry_getName (ce),
4051 cstring_makeLiteral (sRef_isKeep (sr)
4052 ? "transferred" : "released"),
4053 cstring_makeLiteral (isReturn
4054 ? "return" : "scope exit")),
4057 sRef_showAliasInfo (sr);
4058 DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
4071 if (mustDefine && uentry_isOut (ce))
4073 /* No error if its dead (either only or error already reported */
4074 if (!sRef_isReallyDefined (sr) && !sRef_isDead (sr))
4078 message ("Out storage %q not defined before %q",
4079 uentry_getName (ce),
4081 (isReturn ? "return" : "scope exit")),
4084 DPRINTF (("sr: %s", sRef_unparseFull (sr)));
4089 ** also check state is okay
4092 if (usymtab_lexicalLevel () > functionScope
4093 && uentry_isVariable (ce)
4094 && (sRef_isLocalVar (sr)
4095 && (sRef_isDependent (sr) || sRef_isLocalState (sr))))
4097 sRefSet ab = usymtab_aliasedBy (sr);
4099 /* should do something more efficient here */
4101 if (sRefSet_isEmpty (ab))
4103 /* and no local ref */
4104 DPRINTF (("Check lose ref: %s", uentry_unparseFull (ce)));
4105 transferChecks_loseReference (ce);
4119 checked = sRefSet_insert (checked, sr);
4122 llassert (usymtab_isDefined (stab->env));
4124 if (usymtab_isBranch (stab))
4126 stab = usymtab_dropEnv (stab);
4133 llassert (stab != usymtab_undefined);
4134 } while (isReturn && (stab->lexlevel >= paramsScope));
4136 sRefSet_free (checked);
4140 ** all globals are appropriately defined
4141 ** all parameters are appropriately defined
4142 ** special clauses are followed
4145 if (isReturn || (utab->lexlevel == paramsScope))
4147 uentry fcn = context_getHeader ();
4148 uentryList params = context_getParams ();
4149 globSet uglobs = context_getUsedGlobs ();
4150 globSet sglobs = context_getGlobs ();
4152 if (isReturn && context_maybeSet (FLG_GLOBALIAS))
4154 aliasTable_checkGlobs (utab->aliases);
4158 ** state clauses (ensures, defines, sets, allocates, releases)
4161 if (uentry_hasStateClauseList (fcn))
4163 stateClauseList clauses = uentry_getStateClauseList (fcn);
4165 stateClauseList_elements (clauses, cl)
4167 if (stateClause_isAfter (cl) && !stateClause_isGlobal (cl))
4169 if (stateClause_setsMetaState (cl))
4171 sRefSet rfs = stateClause_getRefs (cl);
4172 qual q = stateClause_getMetaQual (cl);
4173 annotationInfo ainfo = qual_getAnnotationInfo (q);
4174 metaStateInfo minfo = annotationInfo_getState (ainfo);
4175 cstring key = metaStateInfo_getName (minfo);
4176 int mvalue = annotationInfo_getValue (ainfo);
4178 DPRINTF (("Post meta state clause: %s", stateClause_unparse (cl)));
4180 sRefSet_elements (rfs, el)
4182 sRef base = sRef_getRootBase (el);
4184 if (sRef_isResult (base))
4187 ** This is checked for return transfers.
4191 else if (sRef_isParam (base) || sRef_isGlobalMarker (base))
4193 sRef sr = sRef_updateSref (base);
4194 sr = sRef_fixBase (el, sr);
4196 if (!sRef_checkMetaStateValue (sr, key, mvalue))
4201 ("Ensures clause not satisfied%q (state is %q): %q",
4202 sRef_isGlobalMarker (sr)
4204 : message (" by %q", sRef_unparse (sr)),
4205 stateValue_unparseValue (sRef_getMetaStateValue (sr, key),
4207 stateClause_unparse (cl)),
4210 sRef_showMetaStateInfo (sr, key);
4216 if (sRef_isMeaningful (el))
4221 } end_sRefSet_elements ;
4225 /* evs - 2000 07 10 - added this */
4226 sRefTest tst = stateClause_getPostTestFunction (cl);
4227 sRefSet rfs = stateClause_getRefs (cl);
4229 sRefSet_elements (rfs, el)
4231 sRef base = sRef_getRootBase (el);
4233 if (sRef_isResult (base))
4236 ** This is checked for return transfers.
4241 else if (sRef_isParam (base))
4243 sRef sr = sRef_updateSref (base);
4244 sr = sRef_fixBase (el, sr);
4246 if (tst != NULL && !tst (sr))
4249 (stateClause_postErrorCode (cl),
4250 message ("%s storage %qcorresponds to "
4251 "storage listed in %q clause",
4252 stateClause_postErrorString (cl, sr),
4253 sRef_unparseOpt (sr),
4254 stateClause_unparseKind (cl)),
4257 sRefShower ss = stateClause_getPostTestShower (cl);
4264 DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
4270 if (sRef_isMeaningful (el))
4275 } end_sRefSet_elements ;
4278 } end_stateClauseList_elements ;
4282 ** check parameters on return
4285 uentryList_elements (params, arg)
4287 if (!uentry_isElipsisMarker (arg))
4289 ctype rt = ctype_realType (uentry_getType (arg));
4291 if (ctype_isMutable (rt) || ctype_isSU (rt))
4293 uentry param = usymtab_lookupQuiet (utab, uentry_rawName (arg));
4294 DPRINTF (("Check param return: %s", uentry_unparseFull (param)));
4295 transferChecks_paramReturn (param);
4298 } end_uentryList_elements;
4300 DPRINTF (("Check global return: %s",
4301 globSet_unparse (sglobs)));
4303 globSet_allElements (sglobs, el)
4305 sRef orig = el; /*! sRef_updateSref (el); */ /*!!!*/
4306 uentry current = sRef_getUentry (el);
4308 DPRINTF (("Check global return: %s / %s", sRef_unparseFull (el),
4309 uentry_unparseFull (current)));
4311 if (uentry_isVariable (current) && !uentry_isRealFunction (current))
4313 checkGlobalReturn (current, orig);
4315 } end_globSet_allElements;
4317 globSet_allElements (uglobs, el)
4319 if (!globSet_member (sglobs, el))
4321 uentry current = sRef_getUentry (el);
4323 if (uentry_isVariable (current)
4324 && !uentry_isRealFunction (current))
4326 checkGlobalReturn (current, sRef_undefined);
4329 } end_globSet_allElements;
4334 usymtab_quietExitScope (fileloc loc)
4335 /*@globals utab, globtab, filetab; @*/
4338 usymtab t = utab->env;
4340 if (utab->reftable != NULL)
4344 for (i = 0; i < utab->nentries; i++)
4346 uentry current = utab->entries[i];
4347 uentry old = usymtab_lookupAux (t, uentry_rawName (current));
4349 uentry_mergeState (old, current, loc, FALSE, FALSE, FALSE, NOCLAUSE);
4353 llassert (t != NULL);
4355 if (t->lexlevel > paramsScope)
4357 t->guards = guardSet_levelUnion (t->guards, utab->guards, t->lexlevel);
4358 t->aliases = aliasTable_levelUnionSeq (t->aliases, utab->aliases,
4360 utab->aliases = aliasTable_undefined;
4363 t->mustBreak = utab->mustBreak;
4364 t->exitCode = utab->exitCode;
4366 usymtab_freeLevel (utab);
4371 usymtab_checkAllValid ();
4376 ** Exit a scope with no checking, lose alias states.
4377 ** (When should this be used?)
4380 void usymtab_quietPlainExitScope (void)
4381 /*@globals utab, globtab, filetab@*/
4384 usymtab t = utab->env;
4386 llassert (t != NULL);
4387 llassert (NOALIAS (utab->aliases, t->aliases));
4388 usymtab_freeLevel (utab);
4392 void usymtab_exitScope (exprNode expr)
4393 /*@globals utab, filetab, globtab@*/
4394 /*@modifies utab, globtab@*/
4396 usymtab ctab = usymtab_undefined;
4397 usymtab lctab = usymtab_undefined;
4398 bool mustReturn = exprNode_mustEscape (expr);
4400 DPRINTF (("Exit scope"));
4402 if (utab->kind == US_CBRANCH)
4405 ** save the case branches, remove the first non-cbranch
4410 while (utab->kind == US_CBRANCH)
4414 llassert (utab != GLOBAL_ENV);
4418 if (utab->kind == US_TBRANCH || utab->kind == US_FBRANCH
4419 || utab->kind == US_CBRANCH || utab->kind == US_SWITCH)
4421 if (context_inMacro ())
4423 /* evs 2000-07-25 */
4424 /* Unparseable macro may end inside nested scope. Deal with it. */
4426 llerror (FLG_SYNTAX,
4427 message ("Problem parsing macro body of %s (unbalanced scopes). "
4428 "Attempting to recover, recommend /*@notfunction@*/ before "
4429 "macro definition.",
4430 context_inFunctionName ()));
4432 while (utab->kind == US_TBRANCH
4433 || utab->kind == US_FBRANCH
4434 || utab->kind == US_CBRANCH
4435 || utab->kind == US_SWITCH)
4438 llassert (utab != GLOBAL_ENV);
4442 llcontbug (message ("exitScope: in branch: %q", usymtab_unparseStack ()));
4444 } /*@=branchstate@*/
4448 ** check all variables in scope were used
4452 ** bogus errors if this is the normal inside a switch,
4453 ** since cases have not been merged yet. Should probably
4454 ** still check this, but I'm too lazy at the moment...
4457 llassertfatal (utab->env != GLOBAL_ENV);
4459 if (utab->env->kind != US_SWITCH)
4465 ** check aliasing: all only params are released (dead)
4466 ** definition: all out params are defined, all modified params
4467 ** are completely defined
4469 ** NOTE: note for exiting paramsScope, since checkReturn should be
4473 if (!mustReturn && (usymtab_lexicalLevel () > functionScope))
4476 ** should only call this is end of scope is reachable...
4479 usymtab_checkFinalScope (FALSE);
4482 if (usymtab_lexicalLevel () == paramsScope && context_inFunctionLike ())
4485 ** leaving a function, need to fix up globals
4488 uentryList params = context_getParams ();
4489 globSet globs = context_getUsedGlobs ();
4491 uentryList_elements (params, ue)
4493 uentry_fixupSref (ue);
4494 } end_uentryList_elements;
4496 clearFunctionTypes ();
4498 DPRINTF (("Fixing up globals: %s", globSet_unparse (globs)));
4500 globSet_allElements (globs, el)
4502 DPRINTF (("Fix: %s", sRef_unparseDebug (el)));
4504 if (sRef_isCvar (el))
4507 int index = sRef_getScopeIndex (el);
4509 if (sRef_isFileStatic (el))
4511 llassert (usymtab_isDefined (filetab));
4512 current = usymtab_fetchIndex (filetab, index);
4516 current = usymtab_fetchIndex (globtab, index);
4519 if (uentry_isVariable (current))
4521 DPRINTF (("Fixup: %s", uentry_unparse (current)));
4522 uentry_fixupSref (current);
4526 DPRINTF (("Clear: %s", uentry_getSref (current)));
4527 sRef_clearDerived (uentry_getSref (current));
4531 sRef_clearDerived (el); /* evans 2002-03-14 - this is the likely source of many crashes! */
4532 } end_globSet_allElements;
4535 usymtab_quietExitScope (exprNode_loc (expr));
4537 if (lctab != usymtab_undefined)
4539 /*@i@*/ lctab->env = utab;
4540 /*@i@*/ utab = ctab;
4541 /*@-branchstate@*/ } /*@=branchstate@*/
4546 usymtab_checkAllValid ();
4552 ** yikes! don't let the '170 kids see this one...
4556 uentry_directParamNo (uentry ue)
4558 if (uentry_isVar (ue))
4560 sRef sr = uentry_getSref (ue);
4562 if (sRef_lexLevel (sr) == functionScope)
4564 int index = sRef_getScopeIndex (sr);
4566 if (index < uentryList_size (context_getParams ()))
4575 /*@dependent@*/ /*@exposed@*/ uentry
4576 usymtab_getParam (int paramno)
4580 ** requires in a function context (checked)
4582 ** depends on no nested functions --- the function
4583 ** parameters are ALWAYS one scope inside the global scope
4584 ** and entered in order!
4588 if (!context_inFunctionLike ())
4589 llfatalbug (message ("usymtab_getParam: not in function context: %q",
4590 context_unparse ()));
4592 while (s->lexlevel > paramsScope)
4597 llassert (usymtab_isDefined (s));
4599 if (paramno >= s->nentries)
4602 ** Parse errors lead to this.
4605 uentry err = uentry_makeVariableLoc (cstring_makeLiteralTemp ("<error>"),
4608 uentry_markOwned (err);
4612 return (s->entries[paramno]);
4615 static /*@dependent@*/ /*@exposed@*/ uentry
4616 usymtab_getRefTab (/*@notnull@*/ usymtab u, int level, usymId index)
4620 ue = usymtab_getRefNoisy (u, level, index);
4622 if (uentry_isUndefined (ue))
4624 llbug (message ("usymtab_getRef: out of range: %d. level = %d",
4631 static /*@dependent@*/ /*@exposed@*/ usymtab
4632 usymtab_dropEnv (/*@notnull@*/ usymtab s)
4634 if (s->kind == US_CBRANCH)
4642 llassert (s != GLOBAL_ENV);
4643 } while (s->kind == US_CBRANCH);
4644 /* drop all cases (except in nested scopes */
4647 llassert (s != GLOBAL_ENV);
4650 if (s->kind == US_FBRANCH)
4652 s = s->env; /* skip the true branch */
4653 llassert (usymtab_isDefined (s));
4654 llassert (s->kind == US_TBRANCH);
4657 llassert (s != GLOBAL_ENV);
4663 /*@dependent@*/ /*@exposed@*/ uentry
4664 usymtab_getRefQuiet (int level, usymId index)
4670 llassert (s != NULL);
4671 llassert (index >= 0);
4673 if (level > s->lexlevel)
4675 return uentry_undefined;
4678 llassertprint (level <= s->lexlevel, ("level: %d / lexlevel: %d",
4679 level, s->lexlevel));
4681 while (s->lexlevel > level)
4683 if (usymtab_isBranch (s))
4685 int eindex = refTable_lookup (s, level, index);
4687 if (eindex != NOT_FOUND)
4689 return (s->entries[eindex]);
4693 s = usymtab_dropEnv (s);
4696 while (usymtab_isBranch (s) && s->lexlevel == level)
4698 int eindex = refTable_lookup (s, level, index);
4700 if (eindex != NOT_FOUND)
4702 return (s->entries[eindex]);
4705 s = usymtab_dropEnv (s);
4708 if (index >= s->nentries)
4710 return uentry_undefined;
4713 llassert (!uentry_isUndefined (s->entries[index]));
4715 return s->entries[index];
4718 static /*@dependent@*/ /*@exposed@*/ uentry
4719 usymtab_getRefNoisy (/*@notnull@*/ usymtab s, int level, usymId index)
4722 uentry ue = uentry_undefined;
4724 llassert (index >= 0);
4726 while (s->lexlevel > level)
4728 if (usymtab_isBranch (s))
4730 int eindex = refTable_lookup (s, level, index);
4732 if (eindex != NOT_FOUND)
4734 ue = s->entries[eindex];
4738 while (!usymtab_isBranch (otab))
4740 otab = usymtab_dropEnv (otab);
4741 llassert (otab != GLOBAL_ENV);
4744 if (refTable_lookup (otab, level, index) == NOT_FOUND)
4746 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4758 s = usymtab_dropEnv (s);
4761 llassert (usymtab_isDefined (s));
4763 while (usymtab_isBranch (s) && s->lexlevel == level)
4765 int eindex = refTable_lookup (s, level, index);
4768 if (eindex != NOT_FOUND)
4770 ue = s->entries[eindex];
4774 while (!usymtab_isBranch (otab))
4776 otab = usymtab_dropEnv (otab);
4777 llassert (otab != GLOBAL_ENV);
4780 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4790 s = usymtab_dropEnv (s);
4793 if (s->lexlevel == level && (index < s->nentries))
4795 ue = s->entries[index];
4797 if (uentry_isValid (ue))
4801 while (!usymtab_isBranch (otab))
4803 otab = usymtab_dropEnv (otab);
4805 if (otab == GLOBAL_ENV)
4811 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4822 if (index >= s->nentries)
4824 return uentry_undefined;
4827 llassert (!uentry_isUndefined (s->entries[index]));
4829 return s->entries[index];
4833 ** looking up entries
4835 ** If entry is inside a branch, then copy it, and put it into
4836 ** the branch table.
4840 int refTable_lookup (/*@notnull@*/ usymtab ut, int level, int index)
4842 refTable rt = ut->reftable;
4845 llassert (rt != NULL);
4847 for (i = 0; i < ut->nentries; i++)
4849 if (rt[i]->level == level && rt[i]->index == index)
4859 /*@only@*/ refentry refentry_create (int level, int index)
4861 refentry r = (refentry) dmalloc (sizeof (*r));
4869 static /*@dependent@*/ /*@exposed@*/ uentry
4870 usymtab_addRefEntry (/*@notnull@*/ usymtab s, cstring k)
4875 if (ut->reftable == NULL)
4877 DPRINTF (("Adding ref entry without reftable: %s", k));
4878 return uentry_undefined;
4881 llassert (ut->reftable != NULL);
4883 while (s != GLOBAL_ENV)
4885 eindex = usymtab_getIndex (s, k);
4887 if (eindex != NOT_FOUND)
4889 uentry current = s->entries[eindex];
4891 if (uentry_isVar (current) && !ctype_isFunction (uentry_getType (current)))
4895 DPRINTF (("Here: copying %s", uentry_unparse (current)));
4896 ue = uentry_copy (current);
4897 DPRINTF (("Here: copying %s", uentry_unparse (ue)));
4898 usymtab_addEntryQuiet (ut, ue);
4899 DPRINTF (("Okay..."));
4901 if (s->reftable != NULL)
4903 refentry ref = s->reftable[eindex];
4905 ut->reftable[ut->nentries - 1]
4906 = refentry_create (ref->level, ref->index);
4910 ut->reftable[ut->nentries - 1]
4911 = refentry_create (s->lexlevel, eindex);
4922 s = usymtab_dropEnv (s);
4925 return uentry_undefined;
4928 static uentry usymtab_lookupAux (usymtab s, cstring k)
4930 DPRINTF (("Lookup: %s", k));
4932 while (s != GLOBAL_ENV)
4934 int eindex = usymtab_getIndex (s, k);
4936 if (eindex != NOT_FOUND)
4938 uentry ret = s->entries[eindex];
4942 if (s->kind == US_TBRANCH
4943 || s->kind == US_FBRANCH
4944 || s->kind == US_CBRANCH)
4945 /* uentry_isGlobalVariable (ret) && os->lexlevel > fileScope) */
4948 DPRINTF (("Adding global ref entry: %s", k));
4949 ret = usymtab_addRefEntry (os, k);
4950 DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
4955 DPRINTF (("Found: %s", uentry_unparseFull (ret)));
4959 if (s->kind == US_TBRANCH || s->kind == US_FBRANCH
4960 || s->kind == US_CBRANCH)
4962 /* why isn't this os??? */
4963 uentry ret = usymtab_addRefEntry (s, k);
4964 DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
4971 return uentry_undefined;
4974 static /*@dependent@*/ /*@exposed@*/ uentry
4975 usymtab_lookupQuietAux (usymtab s, cstring k, bool noalt)
4979 while (s != GLOBAL_ENV)
4981 eindex = usymtab_getIndex (s, k);
4983 if (eindex != NOT_FOUND)
4985 uentry ret = s->entries[eindex];
4989 if (noalt && usymtab_isBranch (s))
4991 s = usymtab_dropEnv (s);
4995 llassert (s != NULL); /*@i523 should not need this? */
5000 return uentry_undefined;
5003 static /*@exposed@*/ /*@dependent@*/ uentry
5004 usymtab_lookupQuiet (usymtab s, cstring k)
5006 return usymtab_lookupQuietAux (s, k, FALSE);
5009 static /*@exposed@*/ /*@dependent@*/ uentry
5010 usymtab_lookupQuietNoAlt (usymtab s, cstring k)
5012 return usymtab_lookupQuietAux (s, k, TRUE);
5015 /*@dependent@*/ /*@observer@*/ uentry
5016 usymtab_lookupSafe (cstring k)
5019 DPRINTF (("Lookup safe: %s", k));
5020 return (usymtab_lookupAux (utab, k));
5024 usymtab_lookupExpose (cstring k)
5027 uentry ce = usymtab_lookupAux (utab, k);
5029 if (uentry_isUndefined (ce))
5031 llfatalbug (message ("usymtab_lookup: not found: *%s*", k));
5034 if (uentry_isPriv (ce))
5036 llfatalbug (message ("usymtab_lookup: private: *%s*", k));
5042 uentry usymtab_lookupExposeGlob (cstring k)
5044 return (usymtab_lookupGlobSafe (k));
5047 uentry usymtab_lookupGlob (cstring k)
5048 /*@globals globtab@*/
5050 uentry ce = usymtab_lookupAux (globtab, k);
5052 if (uentry_isUndefined (ce))
5053 llfatalbug (message ("usymtab_lookup: not found: %s", k));
5055 if (uentry_isPriv (ce))
5056 llfatalbug (message ("usymtab_lookup: private: %s", k));
5058 DPRINTF (("Lookup global: %s", uentry_unparseFull (ce)));
5062 /*@observer@*/ uentry
5063 usymtab_lookupGlobSafe (cstring k)
5064 /*@globals globtab@*/
5066 uentry ce = usymtab_lookupAux (globtab, k);
5067 DPRINTF (("Lookup global: %s", uentry_unparseFull (ce)));
5071 uentry usymtab_lookupEither (cstring k)
5074 uentry ce = usymtab_lookupSafe (k);
5076 if (uentry_isUndefined (ce))
5077 llfatalerror (message ("usymtab_lookup: not found: %s", k));
5079 DPRINTF (("Lookup either: %s", uentry_unparseFull (ce)));
5085 usymtab_lookupType (cstring k)
5086 /*@globals globtab@*/
5088 usymId uid = usymtab_getTypeId (k);
5090 if (uid == USYMIDINVALID)
5092 llcontbug (message ("usymtab_lookupType: not found: %s", k));
5093 return ctype_unknown;
5096 return (uentry_getRealType (usymtab_getTypeEntry (uid)));
5101 usymtab_lookupAbstractType (cstring k) /*@globals globtab@*/
5103 usymId uid = usymtab_getTypeId (k);
5105 if (uid == USYMIDINVALID)
5107 llcontbug (message ("usymtab_lookupType: not found: %s", k));
5108 return ctype_unknown;
5111 return (uentry_getAbstractType (usymtab_getTypeEntry (uid)));
5115 ** if there is an unnamed lcl-specified struct tag matching
5116 ** the uentryList, return its datatype. Otherwise, returns
5121 usymtab_structFieldsType (uentryList f)
5122 /*@globals globtab@*/
5124 return (usymtab_suFieldsType (f, TRUE));
5128 usymtab_unionFieldsType (uentryList f)
5129 /*@globals globtab@*/
5131 return (usymtab_suFieldsType (f, FALSE));
5135 usymtab_suFieldsType (uentryList f, bool isStruct)
5136 /*@globals globtab@*/
5140 DPRINTF (("Fields: %s", uentryList_unparse (f)));
5142 if (fileloc_isSpec (g_currentloc))
5144 return (ctype_undefined);
5147 for (i = 0; i < globtab->nentries; i++)
5149 uentry current = globtab->entries[i];
5152 ? uentry_isStructTag (current) : uentry_isUnionTag (current)))
5154 if (isFakeTag (uentry_rawName (current)))
5156 ctype ct = uentry_getType (current);
5158 DPRINTF (("Check: %s", ctype_unparse (ct)));
5160 if ((isStruct ? ctype_isStruct (ct) : ctype_isUnion (ct))
5162 (uentry_isSpecified (current)
5163 && uentryList_equivFields (f, ctype_getFields (ct))))
5165 return uentry_getAbstractType (current);
5175 return ctype_undefined;
5179 usymtab_enumEnumNameListType (enumNameList f)
5180 /*@globals globtab@*/
5184 for (i = 0; i < globtab->nentries; i++)
5186 uentry current = globtab->entries[i];
5188 if (uentry_isEnumTag (current))
5190 if (isFakeTag (uentry_rawName (current)))
5192 ctype ct = uentry_getType (current);
5194 if (ctype_isEnum (ct) && (enumNameList_match (f, ctype_elist (ct))))
5196 return uentry_getType (current);
5202 return ctype_undefined;
5206 usymtab_exists (cstring k)
5209 uentry ce = usymtab_lookupSafe (k);
5210 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5214 usymtab_existsReal (cstring k)
5217 uentry ce = usymtab_lookupSafe (k);
5219 return (!(uentry_isUndefined (ce))
5220 && !(uentry_isPriv (ce))
5221 && !(uentry_isExpandedMacro (ce)));
5225 usymtab_existsGlob (cstring k)
5226 /*@globals globtab@*/
5228 uentry ce = usymtab_lookupAux (globtab, k);
5230 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5235 usymtab_existsEither (cstring k)
5238 uentry ce = usymtab_lookupAux (utab, k);
5240 return (uentry_isValid (ce));
5244 usymtab_existsGlobEither (cstring k)
5245 /*@globals globtab@*/
5247 uentry ce = usymtab_lookupAux (globtab, k);
5249 return (uentry_isValid (ce));
5254 usymtab_existsType (cstring k)
5255 /*@globals globtab@*/
5257 uentry ce = usymtab_lookupAux (globtab, k);
5259 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && uentry_isDatatype (ce));
5263 usymtab_existsTypeEither (cstring k)
5264 /*@globals globtab@*/
5267 ce = usymtab_lookupAux (globtab, k);
5268 return (uentry_isValid (ce) && uentry_isDatatype (ce));
5272 usymtab_existsStructTag (cstring k) /*@globals globtab@*/
5274 cstring sname = makeStruct (k);
5275 uentry ce = usymtab_lookupAux (globtab, sname);
5276 cstring_free (sname);
5277 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5281 usymtab_existsUnionTag (cstring k) /*@globals globtab@*/
5283 cstring uname = makeUnion (k);
5284 uentry ce = usymtab_lookupAux (globtab, uname);
5286 cstring_free (uname);
5288 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5292 usymtab_existsEnumTag (cstring k) /*@globals globtab@*/
5294 cstring ename = makeEnum (k);
5295 uentry ce = usymtab_lookupAux (globtab, ename);
5297 cstring_free (ename);
5298 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5302 bool usymtab_existsVar (cstring k)
5305 uentry ce = usymtab_lookupSafe (k);
5307 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && (uentry_isVar (ce)));
5316 refTable_free (/*@only@*/ /*@null@*/ refTable x, int nentries)
5322 for (i = 0; i < nentries; i++)
5332 usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab u)
5333 /*@globals globtab, utab, filetab@*/
5337 aliasTable_free (u->aliases);
5339 refTable_free (u->reftable, u->nentries);
5341 if (u == filetab || u == globtab)
5343 for (i = 0; i < u->nentries; i++)
5345 uentry_freeComplete (u->entries[i]);
5350 for (i = 0; i < u->nentries; i++)
5352 uentry_free (u->entries[i]);
5356 guardSet_free (u->guards);
5363 llassert (!cstringTable_isDefined (u->htable));
5371 usymtab_freeAux (/*@only@*/ usymtab u)
5372 /*@globals globtab, utab, filetab@*/
5375 while (u != GLOBAL_ENV)
5378 usymtab_freeLevel (u);
5385 void usymtab_free ()
5386 /*@globals killed utab, globtab, filetab@*/
5390 usymtab_freeAux (utab);
5393 static int usymtab_lexicalLevel (void) /*@globals utab@*/
5395 return (utab->lexlevel);
5398 bool usymtab_inGlobalScope () /*@globals utab, globtab@*/
5400 return (utab == globtab);
5403 bool usymtab_inFileScope () /*@globals utab@*/
5405 return (utab->lexlevel == fileScope);
5408 bool usymtab_inFunctionScope () /*@globals utab@*/
5410 return (utab->lexlevel == functionScope);
5415 usymtab_replaceEntry (uentry s)
5416 /*@globals utab, globtab@*/
5417 /*@modifies utab, s@*/
5419 usymtab_replaceEntryAux (utab, s);
5424 usymtab_matchForwardStruct (usymId u1, usymId u2)
5425 /*@globals globtab@*/
5427 uentry ue1 = usymtab_getTypeEntry (u1);
5428 uentry ue2 = usymtab_getTypeEntry (u2);
5430 if (uentry_isAnyTag (ue2))
5432 ctype reptype = uentry_getType (ue1);
5434 if (ctype_isPointer (reptype))
5436 ctype repbase = ctype_getBaseType (reptype);
5438 if (ctype_isUA (repbase))
5440 typeId rtuid = ctype_typeId (repbase);
5442 if (u2 == rtuid) return TRUE;
5444 if (usymId_isValid (rtuid))
5446 reptype = uentry_getType (usymtab_getTypeEntry (rtuid));
5448 return (ctype_isUA (reptype) && (u2 == (ctype_typeId (reptype))));
5457 void usymtab_addGuards (guardSet guards)
5460 utab->guards = guardSet_union (utab->guards, guards);
5463 static bool usymtab_isGuardedAux (sRef s)
5467 sRef base = sRef_getRootBase (s);
5468 int lowlevel = paramsScope;
5469 int baselevel = sRef_lexLevel (base);
5471 if (sRef_isCvar (base))
5473 lowlevel = baselevel;
5474 if (lowlevel < paramsScope) lowlevel = paramsScope;
5477 while (tab->lexlevel >= lowlevel)
5479 DPRINTF (("Is guarded? [%s] %s",
5480 guardSet_unparse (tab->guards),
5481 sRef_unparseFull (s)));
5483 if (guardSet_isGuarded (tab->guards, s))
5486 if (!sRef_definitelyNull (s))
5488 sRef_setNotNull (s, fileloc_undefined);
5494 tab = usymtab_dropEnv (tab);
5500 void usymtab_unguard (sRef s) /*@modifies utab@*/
5503 sRef base = sRef_getRootBase (s);
5504 int lowlevel = paramsScope;
5505 int baselevel = sRef_lexLevel (base);
5507 if (sRef_isCvar (base))
5509 lowlevel = baselevel;
5510 if (lowlevel < paramsScope) lowlevel = paramsScope;
5513 while (tab->lexlevel >= lowlevel)
5515 if (guardSet_isGuarded (tab->guards, s))
5517 guardSet_delete (tab->guards, s);
5520 tab = usymtab_dropEnv (tab);
5524 bool usymtab_isGuarded (sRef s)
5526 DPRINTF (("Is guarded? %s", sRef_unparseFull (s)));
5527 return (sRef_aliasCompleteSimplePred (usymtab_isGuardedAux, s));
5530 bool usymtab_isDefinitelyNull (sRef s)
5532 return (sRef_aliasCheckSimplePred (usymtab_isDefinitelyNullAux, s));
5535 bool usymtab_isDefinitelyNullDeep (sRef s)
5537 return (sRef_deepPred (usymtab_isDefinitelyNull, s));
5540 static bool usymtab_isDefinitelyNullAux (sRef s)
5544 sRef base = sRef_getRootBase (s);
5545 int lowlevel = paramsScope;
5547 if (sRef_isCvar (base))
5549 lowlevel = sRef_lexLevel (base);
5550 if (lowlevel < paramsScope) lowlevel = paramsScope;
5553 while (tab->lexlevel >= lowlevel)
5555 if (guardSet_mustBeNull (tab->guards, s))
5560 while (tab->kind == US_CBRANCH)
5565 llassert (usymtab_isDefined (tab));
5567 if (tab->kind == US_FBRANCH)
5570 llassert (tab->kind == US_TBRANCH);
5580 usymtab_printGuards ()
5581 /*@globals utab, globtab@*/
5583 usymtab ttab = utab;
5585 while (ttab != globtab)
5587 llmsg (message ("Guards [%d]: %q", ttab->lexlevel,
5588 guardSet_unparse (ttab->guards)));
5594 usymtab_displayAllUses ()
5595 /*@globals utab, globtab@*/
5599 /* only in top scope */
5600 llassert (utab == globtab);
5602 /* need a copy, so order is not messed up by sort! */
5603 copy = usymtab_shallowCopy (globtab);
5605 qsort (copy->entries, (size_t)copy->nentries,
5606 sizeof (*copy->entries), (int (*)(const void *, const void *)) uentry_xcompareuses);
5608 usymtab_entries (copy, ue)
5610 if (uentry_isValid (ue) && !uentry_isGlobalMarker (ue))
5612 filelocList uses = uentry_getUses (ue);
5613 int size = filelocList_realSize (uses);
5615 if (fileloc_isDefined (uentry_whereDefined (ue))
5616 && !fileloc_isLib (uentry_whereDefined (ue))
5619 llmsg (message ("%q (%q), %d use%&:\n %q",
5620 uentry_getName (ue),
5621 fileloc_unparse (uentry_whereDefined (ue)),
5622 size, filelocList_unparseUses (uses)));
5625 } end_usymtab_entries;
5627 usymtab_shallowFree (copy);
5630 static /*@dependent@*/ /*@exposed@*/ usymtab
5631 usymtab_getFileTab ()
5632 /*@globals filetab@*/
5634 llassert (filetab != NULL);
5640 usymtab_unparseStack ()
5643 return (usymtab_unparseStackTab (utab));
5646 static /*@only@*/ cstring
5647 usymtab_unparseStackTab (usymtab t)
5649 bool firstOne = TRUE;
5650 cstring ret = cstring_makeLiteral ("[");
5652 while (t != GLOBAL_ENV)
5656 ret = message ("%q %q", ret, usymtab_typeName (t));
5661 ret = message ("%q, %q", ret, usymtab_typeName (t));
5666 ret = message ("%q ]", ret);
5670 static /*@only@*/ cstring
5671 usymtab_typeName (/*@notnull@*/ usymtab t)
5675 case US_GLOBAL: return cstring_makeLiteral ("global");
5676 case US_NORMAL: return cstring_makeLiteral ("normal");
5677 case US_TBRANCH: return cstring_makeLiteral ("true");
5678 case US_FBRANCH: return cstring_makeLiteral ("false");
5679 case US_CBRANCH: return cstring_makeLiteral ("case");
5680 case US_SWITCH: return cstring_makeLiteral ("switch");
5686 void usymtab_addMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5689 if (!sRef_similar (s, al))
5691 usymtab_addForceMustAlias (s, al);
5696 ** Same as usymtab_addMustAlias, except does not check sRef_isSimilar.
5699 void usymtab_addForceMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5702 /* evans 2002-03-3: was sRef_isMeaningful -- but we need to keep aliases for new storage also! */
5703 if (sRef_isMeaningful (s)
5704 && sRef_isMeaningful (al)
5705 && !(sRef_isConst (s) || sRef_isConst (al))
5706 && !(sRef_isAddress (al) && sRef_isDirectParam (sRef_getBase (al))))
5708 utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
5709 DPRINTF (("Must alias: %s", aliasTable_unparse (utab->aliases)));
5712 ** for local variable, aliasing is symmetric
5715 if (sRef_isLocalVar (s) && sRef_isLocalVar (al))
5717 utab->aliases = aliasTable_addMustAlias (utab->aliases, al, s);
5722 DPRINTF (("Not aliasing! %s / %s", sRef_unparseFull (s), sRef_unparseFull (al)));
5723 DPRINTF (("meaningful: %d %d", sRef_isMeaningful (s), sRef_isMeaningful (al)));
5727 void usymtab_addReallyForceMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5730 utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
5733 void usymtab_clearAlias (sRef s)
5734 /*@modifies utab, s@*/
5737 aliasTable_clearAliases (utab->aliases, s);
5740 sRefSet usymtab_allAliases (sRef s)
5743 if (sRef_isSomewhatMeaningful (s))
5747 ret = sRefSet_unionFree (aliasTable_aliasedBy (utab->aliases, s),
5748 aliasTable_canAlias (utab->aliases, s));
5753 DPRINTF (("NOT A MEANINGFUL SREF!"));
5754 return sRefSet_undefined;
5758 /*@only@*/ sRefSet usymtab_canAlias (sRef s)
5761 if (sRef_isSomewhatMeaningful (s))
5763 sRefSet res = aliasTable_canAlias (utab->aliases, s);
5767 return sRefSet_undefined;
5770 /*@only@*/ sRefSet usymtab_aliasedBy (sRef s)
5773 return (aliasTable_aliasedBy (utab->aliases, s));
5776 /*@only@*/ cstring usymtab_unparseAliases ()
5779 return (aliasTable_unparse (utab->aliases));
5783 ** Debugging routines:
5784 ** okay to leak storage here, only for debugging
5790 usymtab_printOut (void)
5796 char *ind = mstring_copy (" ");
5798 fprintf (g_warningstream, "<<< [symbol table] >>>\n");
5800 while (s != GLOBAL_ENV && s->env != GLOBAL_ENV)
5802 cstring tname = usymtab_typeName (s);
5806 ind[depth * 3 + 1] = '\0';
5809 fprintf (g_warningstream, "level: %d (%s)\n", s->lexlevel,
5810 cstring_toCharsSafe (tname));
5812 cstring_free (tname);
5814 for (i = 0; i < s->nentries; i++)
5816 cstring us = uentry_unparseFull (s->entries[i]);
5817 fprintf (g_warningstream, "%s\n", cstring_toCharsSafe (us));
5821 if (s->reftable != NULL && s->nentries > 0)
5823 fprintf (g_warningstream, "\t<< Ref table >>\n");
5825 for (i = 0; i < s->nentries; i++)
5827 fprintf (g_warningstream, "\t%s %3d: %d, %d\n", ind, i,
5828 s->reftable[i]->level,
5829 s->reftable[i]->index);
5833 ind[depth * 3 + 1] = ' ';
5837 fprintf (g_warningstream, "<<< end usymtab >>>\n");
5843 usymtab_printTypes ()
5844 /*@globals globtab@*/
5846 usymtab_printAllAux (globtab);
5850 usymtab_printAll (void)
5853 usymtab_printAllAux (utab);
5857 usymtab_printAllAux (usymtab s)
5858 /*@modifies g_warningstream@*/
5862 char *ind = mstring_copy (" ");
5864 printf ("[[[ usymtab ]]]");
5866 while (s != GLOBAL_ENV)
5869 ind[depth * 3 + 1] = '\0';
5871 if (s->env == GLOBAL_ENV)
5875 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5876 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5877 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5881 for (i = looplow; i < s->nentries; i++)
5883 printf ("%s%3d. %s\n", ind, i,
5884 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5889 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5890 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5891 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5893 for (i = 0; i < s->nentries; i++)
5895 printf ("%s%3d %s\n", ind, i,
5896 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5900 ind[depth * 3 + 1] = ' ';
5904 printf ("----------\n");
5908 usymtab_printComplete ()
5913 char *ind = mstring_copy (" ");
5916 while (s != GLOBAL_ENV)
5920 ind[depth * 3 + 1] = '\0';
5923 if (s->env == GLOBAL_ENV)
5927 printf ("level: %d\n", s->lexlevel);
5931 for (i = looplow; i < s->nentries; i++)
5933 printf ("%s%3d %s\n", ind, i,
5934 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5939 printf ("level: %d\n", s->lexlevel);
5940 for (i = 0; i < s->nentries; i++)
5942 printf ("%s%3d %s\n", ind, i,
5943 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5947 ind[depth * 3 + 1] = ' ';
5952 printf ("----------\n");
5957 static /*@only@*/ cstring /*@unused@*/
5958 usymtab_unparseLocalAux (/*@notnull@*/ usymtab s)
5960 cstring c = message ("lexlevel: %d\n", s->lexlevel);
5963 for (i = 0; i < s->nentries; i++)
5965 c = message ("%q\n%q", c, uentry_unparseFull (s->entries[i]));
5968 c = message ("%q\n=========", c);
5972 static cstring /*@unused@*/ /*@only@*/
5973 usymtab_unparseLocalList (/*@notnull@*/ usymtab s)
5975 cstring c = message ("[%d/%s/%s] ", s->lexlevel,
5976 bool_unparse (s->mustBreak),
5977 exitkind_unparse (s->exitCode));
5980 for (i = 0; i < s->nentries; i++)
5982 sRef sr = uentry_getSref (s->entries[i]);
5986 c = message ("%q: %q [%b]", c, uentry_getName (s->entries[i]),
5987 sRef_isStateDefined (sr));
5991 c = message ("%q, %q [%b]", c, uentry_getName (s->entries[i]),
5992 sRef_isStateDefined (sr));
6002 usymtab_printLocal (void)
6008 printf ("lexlevel: %d\n", s->lexlevel);
6010 for (i = 0; i < s->nentries; i++)
6012 printf ("%s\n", cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
6015 while (s->lexlevel > 1)
6020 llassert (usymtab_isDefined (s));
6022 printf ("Params:\n");
6024 for (i = 0; i < s->nentries; i++)
6026 printf ("%d: %s\n", i,
6027 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
6032 static bool checkDistinctExternalName (uentry e)
6033 /*@globals globtab@*/
6034 /*@modifies *g_warningstream@*/
6036 size_t checklen = size_fromInt (context_getValue (FLG_EXTERNALNAMELEN));
6037 bool ignorecase = context_getFlag (FLG_EXTERNALNAMECASEINSENSITIVE);
6038 bool gotone = FALSE;
6039 bool extras = FALSE;
6040 bool hasError = FALSE;
6041 cstring name = uentry_rawName (e);
6042 usymtab st = globtab;
6050 if (uentry_isAnyTag (e))
6052 checklen++; /* the tag marker doesn't count */
6056 usymtab_entries (st, oe)
6058 if (uentry_sameObject (oe, e))
6065 if (cstring_equalCaseInsensitive (uentry_rawName (oe), name))
6074 (FLG_DISTINCTEXTERNALNAMES,
6076 ("External identifier %q is not distinguishable from %q "
6077 "because alphabetical case is ignored",
6079 uentry_getName (oe)),
6080 uentry_whereLast (e)))
6082 uentry_showWhereAny (oe);
6083 uentry_setHasNameError (oe);
6092 if (cstring_equalLenCaseInsensitive (uentry_rawName (oe),
6101 if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6104 (FLG_DISTINCTEXTERNALNAMES,
6107 ("External identifier %q is not distinguishable from %q "
6108 "in the first %d characters (%q)",
6110 uentry_getName (oe),
6111 size_toInt (checklen),
6112 cstring_clip (uentry_getName (e), checklen)),
6114 uentry_whereLast (e)))
6116 uentry_showWhereAny (oe);
6117 uentry_setHasNameError (oe);
6130 (FLG_DISTINCTEXTERNALNAMES,
6132 ("External identifier %q is not distinguishable from %q "
6133 "in the first %d characters because alphabetical case "
6136 uentry_getName (oe),
6137 size_toInt (checklen)),
6138 uentry_whereLast (e)))
6140 uentry_showWhereAny (oe);
6141 uentry_setHasNameError (oe);
6147 else if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6156 (FLG_DISTINCTEXTERNALNAMES,
6159 ("External identifier %q is not distinguishable from %q "
6160 "in the first %d characters (%q)",
6162 uentry_getName (oe),
6163 size_toInt (checklen),
6164 cstring_clip (uentry_getName (e), checklen)),
6166 uentry_whereLast (e)))
6168 uentry_showWhereAny (oe);
6169 uentry_setHasNameError (oe);
6178 } end_usymtab_entries ;
6185 (cstring_makeLiteral ("One or more additional "
6186 "indistinguishable external "
6187 "names not reported"));
6193 static bool checkDistinctInternalName (uentry e)
6195 /*@modifies *g_warningstream@*/
6197 usymtab ttab = utab;
6198 cstring name = uentry_rawName (e);
6199 size_t numchars = size_fromInt (context_getValue (FLG_INTERNALNAMELEN));
6200 bool caseinsensitive = context_getFlag (FLG_INTERNALNAMECASEINSENSITIVE);
6201 bool lookalike = context_getFlag (FLG_INTERNALNAMELOOKALIKE);
6203 if (uentry_isAnyTag (e) && (numchars != 0))
6205 numchars++; /* the tag marker doesn't count */
6208 while (usymtab_isDefined (ttab))
6210 usymtab_entries (ttab, oe)
6212 if (uentry_sameObject (oe, e))
6214 /*@innercontinue@*/ continue;
6217 switch (cstring_genericEqual
6218 (name, uentry_rawName (oe),
6219 numchars, caseinsensitive, lookalike))
6221 case CGE_DISTINCT: /* okay */
6225 if (cstring_equal (name, uentry_rawName (oe)))
6227 ; /* got a shadow error */
6232 (FLG_DISTINCTINTERNALNAMES,
6235 ("Internal identifier %q is not distinguishable from %q "
6236 "in the first %d characters (%q)",
6238 uentry_getName (oe),
6239 size_toInt (numchars),
6240 cstring_clip (uentry_getName (e), numchars)),
6242 uentry_whereLast (e)))
6244 uentry_showWhereAny (oe);
6245 uentry_setHasNameError (oe);
6252 if (numchars == 0 || (cstring_length (name) <= numchars))
6255 (FLG_DISTINCTINTERNALNAMES,
6257 ("Internal identifier %q is not distinguishable from %q "
6258 "without case sensitivity",
6260 uentry_getName (oe)),
6261 uentry_whereLast (e)))
6263 uentry_showWhereAny (oe);
6264 uentry_setHasNameError (oe);
6271 (FLG_DISTINCTINTERNALNAMES,
6273 ("Internal identifier %q is not distinguishable from %q "
6274 "in the first %d characters without case sensitivity",
6276 uentry_getName (oe),
6277 size_toInt (numchars)),
6278 uentry_whereLast (e)))
6280 uentry_showWhereAny (oe);
6281 uentry_setHasNameError (oe);
6289 || (cstring_length (name) <= numchars))
6292 (FLG_DISTINCTINTERNALNAMES,
6294 ("Internal identifier %q is not distinguishable from %q "
6295 "except by lookalike characters",
6297 uentry_getName (oe)),
6298 uentry_whereLast (e)))
6300 uentry_showWhereAny (oe);
6301 uentry_setHasNameError (oe);
6308 (FLG_DISTINCTINTERNALNAMES,
6310 ("Internal identifier %q is not distinguishable from %q "
6311 "in the first %d characters except by lookalike characters",
6313 uentry_getName (oe),
6314 size_toInt (numchars)),
6315 uentry_whereLast (e)))
6317 uentry_showWhereAny (oe);
6318 uentry_setHasNameError (oe);
6323 } end_usymtab_entries ;
6331 void usymtab_checkDistinctName (uentry e, int scope)
6332 /*@globals utab, globtab@*/
6334 bool hasError = FALSE;
6335 fileloc where = uentry_whereLast (e);
6337 if (!fileloc_isPreproc (where) && !fileloc_isBuiltin (where))
6339 if (scope == globScope)
6341 if (context_getFlag (FLG_DISTINCTEXTERNALNAMES))
6343 hasError = checkDistinctExternalName (e);
6347 if (!hasError && context_getFlag (FLG_DISTINCTINTERNALNAMES))
6349 hasError = checkDistinctInternalName (e);
6355 uentry_setHasNameError (e);
6359 /*@exposed@*/ sRef usymtab_lookupGlobalMarker (void) /*@globals utab@*/
6363 ue = usymtab_lookupAux (utab, GLOBAL_MARKER_NAME);
6364 llassert (uentry_isValid (ue));
6366 return uentry_getSref (ue);
6372 ** For debugging only
6376 usymtab_checkAllValid () /*@globals utab@*/
6380 while (tab != GLOBAL_ENV)
6384 for (i = 0; i < utab->nentries; i++)
6386 uentry e = utab->entries[i];
6388 uentry_checkValid (e);
6391 aliasTable_checkValid (tab->aliases);