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");
1804 for (i = 0; i < utab->nentries; i++)
1806 uentry thisentry = utab->entries[i];
1808 if (uentry_isFunction (thisentry) )
1810 constraintList preconditions;
1811 constraintList postconditions;
1813 preconditions = uentry_getFcnPreconditions (thisentry);
1814 postconditions = uentry_getFcnPostconditions (thisentry);
1816 if ( constraintList_isDefined(preconditions) ||
1817 constraintList_isDefined(postconditions) )
1819 fprintf(fout,"%s\n", cstring_toCharsSafe (uentry_rawName(thisentry) ) );
1820 if (constraintList_isDefined(preconditions) )
1822 fprintf(fout,"pre:\n");
1823 constraintList_dump(preconditions, fout);
1824 fprintf (fout, ";; end precondition constraints\n" );
1825 constraintList_free(preconditions);
1829 fprintf(fout,"pre:EMPTY\n");
1831 if (constraintList_isDefined(postconditions) )
1833 fprintf(fout,"post:\n");
1834 constraintList_dump(postconditions, fout);
1835 fprintf (fout, ";; end precondition constraints\n" );
1836 constraintList_free(postconditions);
1840 fprintf(fout,"post:EMPTY\n");
1849 void usymtab_load (FILE *f)
1850 /*@globals utab, globtab@*/
1851 /*@modifies utab, *f@*/
1853 char *s = mstring_create (MAX_DUMP_LINE_LENGTH);
1855 ekind kind = KINVALID;
1856 fileloc loc = g_currentloc;
1862 llassert (utab == globtab);
1863 llassert (utab->nentries == 0);
1865 while (((s = reader_readLine (f, s, MAX_DUMP_LINE_LENGTH)) != NULL)
1868 /* ignore ; comments */ ;
1871 while (s != NULL && *s != ';')
1879 ek = reader_getInt (&s);
1881 if (ek == KGLOBALMARKER)
1883 uentry lue = uentry_makeGlobalMarker ();
1884 DPRINTF (("Adding global marker: %s", uentry_unparseFull (lue)));
1885 usymtab_addEntryAlways (utab, lue);
1891 kind = ekind_fromInt (ek);
1899 (cstring_makeLiteral
1900 ("Library is in obsolete format. Use splint +whichlib "
1901 "to see which library is being loaded."));
1904 if (reader_optCheckChar (&s, '^'))
1906 index = reader_getInt (&s);
1913 llassert (kind != KINVALID);
1914 ue = uentry_undump (kind, loc, &s);
1916 llassert (utab->nentries == index || index == -1);
1918 if (uentry_isValid (ue))
1920 int lastindex = utab->nentries;
1921 ue = usymtab_addEntryAlways (utab, ue);
1925 if (uentry_isConstant (ue)) /*@i23! isPreProcessorMacro */
1927 cstring uname = uentry_getName (ue);
1929 /* Also check its a macro... */
1930 DPRINTF (("Installing: %s", uname));
1932 cpphash_installMacro
1933 (mstring_copy (cstring_toCharsSafe (uname)),
1934 cstring_length (uname),
1935 cpplib_createDefinition (message ("%s 255", uname),
1938 cpphash_hashCode (cstring_toCharsSafe (uname),
1939 cstring_length (uname),
1942 DPRINTF (("After install: %s", uname));
1946 if (utab->nentries != lastindex + 1)
1948 DPRINTF (("No add: %s", uentry_unparseFull (ue)));
1956 ** now, any other names are the same uentry
1959 while (*(s++) == '#')
1961 cstring name = cstring_fromCharsO (reader_getWord (&s));
1962 uentry nue = uentry_nameCopy (name, ue);
1964 DPRINTF (("Name copy: %s", uentry_unparseFull (nue)));
1968 usymtab_addEntryAlways (utab, nue);
1971 while ((c = *s) != '\0' && (c !='\n'))
1973 if (c != ' ' || c != '\t')
1975 llbuglit ("Junk in load file");
1983 s = reader_readLine (f, os, MAX_DUMP_LINE_LENGTH);
1988 to handle reading of buffer overflow related constraints
1990 while (fgets (s, MAX_DUMP_LINE_LENGTH, f) != NULL
1993 ; /* ignore ;-comments */
1996 while (s != NULL && *s != ';')
1998 constraintList preconditions;
1999 constraintList postconditions;
2001 cstring name = cstring_fromChars(reader_getWord(&s) );
2003 ue = usymtab_lookup ( name );
2007 preconditions = constraintList_undefined;
2008 postconditions = constraintList_undefined;
2010 if (!uentry_isValid(ue) )
2012 llfatalbug ((message("Invalid uentry for %s library file may be corrupted", cstring_fromChars(s) ) ));
2014 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2016 temp = cstring_fromChars (reader_getWord(&s) );
2018 if (cstring_compareLit (temp,"pre:") == 0 )
2020 preconditions = constraintList_undump (f);
2024 if (cstring_compareLit (temp,"pre:EMPTY") != 0 )
2025 llfatalbug ((message("Error reading library file pre:EMPTY expected but got %s", temp ) ));
2030 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2032 temp = cstring_fromChars(reader_getWord(&s) );
2033 if (cstring_compareLit (temp, "post:") == 0 )
2035 postconditions = constraintList_undump (f);
2039 if (cstring_compareLit (temp, "post:EMPTY") != 0 )
2040 llfatalbug ((message("Error reading library file post:EMPTY expected but got %s", temp ) ));
2043 cstring_free (temp);
2045 uentry_setPreconditions (ue, functionConstraint_createBufferConstraint (preconditions));
2046 uentry_setPostconditions (ue, functionConstraint_createBufferConstraint (postconditions));
2048 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2056 ** file scope for static variables
2060 usymtab_enterFile ()
2061 /*@globals utab, globtab, filetab@*/
2062 /*@modifies filetab@*/
2064 llassert (utab == globtab);
2069 usymtab_entries (globtab, ue)
2071 if (sRef_hasDerived (uentry_getSref (ue)))
2073 fprintf (g_warningstream, "Derived Global: %s\n", uentry_unparse (ue));
2074 fprintf (g_warningstream, "sRef: %s\n", sRef_unparseFull (ue->sref));
2076 } end_usymtab_entries ;
2080 usymtab_enterScope ();
2086 /*@globals utab, filetab@*/
2087 /*@modifies filetab, utab@*/
2090 llassert (utab->lexlevel == 1);
2092 usymtab_exitScope (exprNode_undefined);
2097 usymtab_enterScope ()
2098 /*@globals utab, globtab, filetab@*/
2101 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
2103 /* unconditional scope: optimize to avoid copy */
2104 t->aliases = aliasTable_copy (utab->aliases);
2107 llassert (usymtab_isDefined (t->env));
2109 if (t->env->lexlevel == paramsScope && context_inFunctionLike ())
2111 noshadowerror = TRUE;
2112 usymtab_handleParams ();
2113 noshadowerror = FALSE;
2118 ** setup external references:
2119 ** o only, unique params alias external args
2120 ** o other params may alias anything of their type
2124 usymtab_handleParams (void)
2125 /*@globals utab, globtab, filetab@*/
2126 /*@modifies utab, globtab@*/
2128 usymtab ptab = utab->env;
2129 uentry fcn = context_getHeader ();
2131 usymtab_entries (ptab, param)
2135 if (!uentry_isYield (param))
2138 sRef pref = uentry_getSref (param);
2140 /* Could be a global. */
2142 if (uentry_isAnyParam (param))
2144 ue = uentry_makeVariable (fixParamName (uentry_rawName (param)),
2145 uentry_getType (param),
2146 fileloc_copy (uentry_whereDeclared (param)),
2149 uentry_copyState (ue, param);
2150 uentry_setRefParam (ue);
2152 ue = usymtab_supEntrySrefReturn (ue);
2154 /* must be after supercede! */
2156 if (!sRef_stateKnown (pref))
2158 uentry_setDefState (ue, SS_DEFINED);
2159 uentry_setDefState (param, SS_DEFINED);
2163 if (sRef_isStateSpecial (pref))
2165 uentry_setDefState (ue, SS_SPECIAL); /* ALLOCATED); */
2166 /* evans 2002-01-01: should be unnecessary, the pre clauses
2167 ** set the state if necessary.
2172 uentry_setDefState (ue, sRef_getDefState (pref));
2176 uref = uentry_getSref (ue);
2178 if (sRef_isStack (uref))
2180 alkind pkind = sRef_getAliasKind (pref);
2182 if (alkind_isKnown (pkind) && !alkind_isLocal (pkind)
2183 && !alkind_isStack (pkind))
2185 sRef_setAliasKind (uref, pkind, fileloc_undefined);
2186 sRef_setOrigAliasKind (uref, pkind);
2190 sRef_setAliasKind (uref, AK_IMPTEMP, fileloc_undefined);
2191 sRef_setOrigAliasKind (uref, AK_IMPTEMP);
2193 if (uentry_isOut (param))
2199 sRef_setDefined (uref, fileloc_undefined);
2205 usymtab_addMustAlias (uref, pref);
2207 if (!(uentry_isOnly (param) || uentry_isUnique (param)))
2210 ** This is needed for detecting possibly aliased parameters.
2213 sRef s = sRef_makeExternal (uref);
2214 usymtab_addMustAlias (uref, s);
2217 if (sRef_isKillRef (pref))
2219 sRef_setAliasKind (uref, AK_NEWREF, fileloc_undefined);
2220 sRef_setOrigAliasKind (uref, AK_KILLREF);
2222 else if (sRef_isRefCounted (uref))
2224 sRef_setOrigAliasKind (uref, AK_REFCOUNTED);
2229 sRef_setOrigAliasKind (uref, AK_LOCAL);
2236 } end_usymtab_entries;
2239 if (uentry_hasStateClauseList (fcn))
2241 stateClauseList clauses = uentry_getStateClauseList (fcn);
2243 stateClauseList_preElements (clauses, cl)
2245 fileloc loc = stateClause_loc (cl);
2246 sRefSet osrs = sRefSet_undefined;
2249 if (stateClause_isGlobal (cl))
2251 DPRINTF (("Global Marker: %s",
2252 sRef_unparseFull (usymtab_lookupGlobalMarker ())));
2253 llassert (sRef_isGlobalMarker (usymtab_lookupGlobalMarker ()));
2254 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
2259 srs = stateClause_getRefs (cl);
2262 sRefSet_elements (srs, el)
2264 sRef base = sRef_getRootBase (el);
2265 sRef sb = sRef_updateSref (el);
2267 if (sRef_isResult (base))
2269 ; /* nothing to do before */
2271 else if (sRef_isParam (base) || sRef_isGlobalMarker (base))
2273 if (stateClause_setsMetaState (cl))
2275 /* copied from exprNode.c:3040 */
2276 qual ql = stateClause_getMetaQual (cl);
2277 annotationInfo ainfo = qual_getAnnotationInfo (ql);
2278 metaStateInfo minfo = annotationInfo_getState (ainfo);
2279 cstring key = metaStateInfo_getName (minfo);
2280 int mvalue = annotationInfo_getValue (ainfo);
2282 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
2284 if (sRef_isResult (base))
2290 sRef_setMetaStateValueComplete (sb, key, mvalue, loc);
2295 sRefMod modf = stateClause_getEntryFunction (cl);
2299 sRefSet aliases = usymtab_allAliases (sb);
2303 sRefSet_elements (aliases, sr)
2306 } end_sRefSet_elements ;
2308 sRefSet_free (aliases);
2314 if (sRef_isValid (base))
2316 DPRINTF (("Base: %s", sRef_unparseFull (base)));
2320 } end_sRefSet_elements ;
2321 } end_stateClauseList_preElements ;
2326 usymtab_enterFunctionScope (uentry fcn)
2327 /*@globals utab, filetab, globtab@*/
2330 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
2332 DPRINTF (("Enter function: %s", uentry_unparse (fcn)));
2334 if (utab->lexlevel != fileScope)
2336 if (utab->lexlevel > fileScope)
2338 llparseerror (cstring_makeLiteral ("New function scope inside function"));
2340 while (utab->lexlevel > fileScope)
2342 /*@i@*/ utab = usymtab_dropEnv (utab);
2349 llfatalbug (cstring_makeLiteral ("New function not inside file."));
2351 /*@-branchstate@*/ } /*@=branchstate@*/
2355 DPRINTF (("Globs: %s", globSet_unparse (uentry_getGlobs (fcn))));
2357 globSet_allElements (uentry_getGlobs (fcn), el)
2359 DPRINTF (("Here we go: %s", sRef_unparseFull (el)));
2361 if (sRef_isUndefGlob (el))
2363 int index = sRef_getScopeIndex (el);
2364 sRef sr = sRef_updateSref (el);
2365 fileloc loc = uentry_whereEarliest (fcn);
2367 DPRINTF (("update: %s", sRef_unparseFull (sr)));
2368 DPRINTF (("Undef!"));
2369 if (sRef_isFileStatic (el))
2371 ctype ct = sRef_getType (el);
2374 llassert (usymtab_isDefined (filetab));
2376 ue = usymtab_fetchIndex (filetab, index);
2378 if (ctype_isRealArray (ct) || ctype_isRealSU (ct))
2380 sRef_setAllocated (sr, loc);
2384 sRef_setUndefined (sr, loc);
2389 uentry ue = globtab->entries[index];
2390 ctype ct = uentry_getType (ue);
2392 if (ctype_isArray (ct) || ctype_isSU (ct))
2394 sRef_setAllocated (sr, loc);
2398 sRef_setUndefined (sr, loc);
2402 else if (sRef_isAllocated (el))
2404 sRef sr = sRef_updateSref (el);
2405 fileloc loc = uentry_whereEarliest (fcn);
2407 sRef_setAllocated (sr, loc);
2409 else if (sRef_isPartial (el))
2411 sRef sr = sRef_updateSref (el);
2412 fileloc loc = uentry_whereEarliest (fcn);
2414 sRef_setPartial (sr, loc);
2419 sRef sr = sRef_updateSref (el);
2420 fileloc loc = uentry_whereEarliest (fcn);
2422 sRef_setDefined (sr, loc);
2426 /* shouldn't need to do anything! */
2428 } end_globSet_allElements;
2430 DPRINTF (("Globs after: %s", globSet_unparse (uentry_getGlobs (fcn))));
2432 usymtab_checkAllValid ();
2437 usymtab_caseBranch (void)
2440 usymtab t = usymtab_create (US_CBRANCH, utab, FALSE);
2445 usymtab_switchBranch (/*@unused@*/ exprNode s)
2448 usymtab t = usymtab_create (US_SWITCH, utab, FALSE);
2450 t->aliases = aliasTable_copy (utab->aliases);
2455 usymtab_trueBranch (/*@only@*/ guardSet guards)
2458 usymtab t = usymtab_create (US_TBRANCH, utab, FALSE);
2461 ** not true! (could be in a macro)
2463 ** llassertprint (utab->lexlevel > paramsScope,
2464 ** ("not in scope: %s", usymtab_unparseLocal ()));
2468 guardSet_free (t->guards);
2471 aliasTable_free (t->aliases);
2472 t->aliases = aliasTable_copy (utab->aliases);
2480 ** { int a; if (...) a = 3; < a may be undefined here!
2485 usymtab_popTrueBranch (exprNode pred, exprNode expr, clause cl) /*@modifies utab@*/
2488 ** add a false branch
2489 ** (could be done more efficiently as a special case, but
2490 ** it is better to only maintain one version of the code)
2493 if (utab->kind != US_TBRANCH
2494 && context_inIterDef ())
2496 usymtab_exitScope (expr);
2500 DPRINTF (("pop true branch.."));
2501 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2502 usymtab_popBranches (pred, expr, exprNode_undefined, TRUE, cl);
2507 usymtab_popCaseBranch () /*@modifies utab@*/
2509 llassert (utab->kind == US_CBRANCH);
2510 usymtab_quietPlainExitScope ();
2514 usymtab_popTrueExecBranch (exprNode pred, exprNode expr, clause cl)
2517 ** add a false branch that must return --- that is,
2518 ** the true branch is always executed!
2521 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2522 usymtab_popBranches (pred, expr, exprNode_makeMustExit (), FALSE, cl);
2526 usymtab_popOrBranch (exprNode pred, exprNode expr)
2530 usymtab env = utab->env;
2531 usymtab otab = utab;
2534 llassert (env != NULL);
2536 if (exprNode_isError (expr))
2542 mustReturn = exprNode_mustEscape (expr);
2546 llassert (utab->kind == US_TBRANCH);
2549 ** merge each entry in table with its original
2550 ** unless execution cannot continue after this branch
2553 for (i = 0; i < utab->nentries; i++)
2555 uentry current = utab->entries[i];
2556 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2558 uentry_mergeState (old, current, exprNode_loc (expr),
2559 mustReturn, FALSE, TRUE, ORCLAUSE);
2565 env->guards = guardSet_levelUnionFree (env->guards,
2566 guardSet_invert (exprNode_getGuards (pred)),
2571 env->aliases = aliasTable_levelUnion (env->aliases, otab->aliases, env->lexlevel);
2574 /* env is now utab */
2575 usymtab_quietPlainExitScope ();
2579 ** case syntax in C is very unrestricted. This is unfortunate.
2581 ** A switch case is ended either by a new case or default, or
2582 ** a close } that may close the switch or some other control
2587 usymtab_newCase (/*@unused@*/ exprNode pred, exprNode last)
2590 bool mustBreak = usymtab_mustBreak (utab);
2591 bool mustReturn = usymtab_mustEscape (utab);
2592 usymtab stab = utab;
2594 DPRINTF (("New case!"));
2597 ** Find last case (or outer switch)
2600 while (stab->kind != US_CBRANCH && stab->kind != US_SWITCH)
2603 llassert (stab != GLOBAL_ENV);
2606 while (stab->kind == US_CBRANCH)
2609 llassert (stab != GLOBAL_ENV);
2613 ** if its a fall through case, merge in outside entries and last case.
2618 ** case 1: x = 3; <fall through>
2619 ** case 2: << x may not be defined
2623 if (!mustBreak && !mustReturn && utab->kind == US_CBRANCH)
2625 llassert (stab->kind == US_SWITCH || stab->kind == US_NORMAL);
2627 usymtab_entries (utab, ue) /* but, keep track of used variables */
2629 uentry old = usymtab_lookupAux (stab, uentry_rawName (ue));
2631 llassert (uentry_isValid (old));
2633 /* modifies ue, not old */
2635 uentry_mergeState (ue, old, exprNode_loc (last),
2636 FALSE, FALSE, TRUE, CASECLAUSE);
2637 } end_usymtab_entries;
2639 utab->aliases = aliasTable_levelUnion (utab->aliases,
2640 stab->aliases, utab->lexlevel);
2643 ** No need for a new branch.
2650 usymtab_caseBranch ();
2651 /*@-mustfree@*/ /*< utab->aliases >*/
2652 utab->aliases = aliasTable_copy (stab->aliases);
2660 ** for && (both pred and expr are executed)
2664 usymtab_popAndBranch (exprNode pred, /*@unused@*/ exprNode expr)
2667 usymtab env = utab->env;
2671 llassert (utab->kind == US_TBRANCH);
2674 ** merge each entry in table with its original
2675 ** unless execution cannot continue after this branch
2678 for (i = 0; i < utab->nentries; i++)
2680 uentry current = utab->entries[i];
2681 sRef tref = uentry_getSref (current);
2682 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2683 sRef oref = uentry_getSref (old);
2685 /* note that is current is in a nested branch,
2686 it may create a "new" old entry. */
2688 llassert (uentry_isValid (old));
2689 uentry_mergeState (old, current, exprNode_loc (expr),
2690 FALSE, FALSE, TRUE, ANDCLAUSE);
2693 ** if is it defined by the second clause, then it should be defined.
2696 if (sRef_isAnyDefined (tref)
2697 && (sRef_isAllocated (oref) || sRef_isStateUndefined (oref)))
2699 sRef_setDefined (oref, g_currentloc);
2703 utab->guards = guardSet_levelUnionFree (utab->guards,
2704 guardSet_invert (exprNode_getGuards (pred)),
2706 utab->aliases = aliasTable_levelUnion (utab->aliases, otab->aliases, utab->lexlevel);
2708 usymtab_quietPlainExitScope ();
2713 ** Stack should be [ US_CBRANCH+ US_SWITCH ]
2714 ** Only branches which do not return (except possibly the last branch) are included.
2716 ** Conditionally merge state from all CBRANCHes.
2718 ** If allpaths is TRUE, then all possible executions go through some switch
2719 ** case, and the original scope is not merged.
2723 usymtab_exitSwitch (/*@unused@*/ exprNode sw, bool allpaths)
2726 usymtab ttab = utab;
2727 usymtab stab = ttab;
2728 usymtab ltab = ttab;
2729 bool lastMustReturn = usymtab_mustEscape (utab);
2733 while (stab->kind == US_CBRANCH)
2736 llassert (stab != GLOBAL_ENV);
2739 while (stab->kind == US_NORMAL)
2742 llassert (stab != GLOBAL_ENV);
2745 llassert (stab->kind == US_SWITCH);
2747 /* go to the scope outside the switch (US_SWITCH is just a marker! */
2749 llassert (stab != GLOBAL_ENV);
2753 llassert (usymtab_isDefined (ttab));
2755 if (ttab->kind == US_CBRANCH)
2757 /* was quietPlainExitScope --- but, can't free it yet! */
2759 llassert (utab != GLOBAL_ENV);
2761 while (ttab->kind == US_CBRANCH)
2764 ** (from popTrueBranch)
2767 bool mustReturn = usymtab_mustEscape (ttab);
2768 bool mustBreak = usymtab_mustBreak (ttab);
2770 usymtab_entries (ttab, current)
2772 uentry old = /*@-compmempass@*/ usymtab_lookupAux (ltab, uentry_rawName (current));
2776 ** note that is this is in a nested branch,
2777 ** it may create a "new" old entry.
2780 if (uentry_isValid (old))
2784 uentry_mergeUses (current, old);
2785 uentry_setState (old, current);
2789 uentry_mergeState (old, current, exprNode_loc (sw),
2790 mustReturn, FALSE, TRUE, SWITCHCLAUSE);
2797 } end_usymtab_entries;
2800 ** if entry is not in symbol table for this case, merge with pre-switch
2804 if (!mustReturn && !mustBreak)
2806 usymtab_entries (stab, current)
2808 if (usymtab_getIndex (ttab, uentry_rawName (current)) == NOT_FOUND)
2810 uentry old = /*@-compmempass@*/
2811 usymtab_lookupAux (ltab, uentry_rawName (current));
2814 llassert (uentry_isValid (old));
2815 uentry_mergeState (old, current, exprNode_loc (sw),
2816 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2818 } end_usymtab_entries;
2821 ltab->env = ttab->env;
2825 ** Suprious error, becuase of environments.
2828 /*@i1@*/ utab = ltab;
2830 lastMustReturn = FALSE;
2837 ** now, there is one US_CBRANCH. Merge this with the stab.
2841 for (i = 0; i < ltab->nentries; i++)
2843 uentry current = ltab->entries[i];
2844 uentry old = usymtab_lookupAux (stab, uentry_rawName (current));
2846 /* note that is this is in a nested branch,
2847 it may create a "new" old entry. */
2850 if (uentry_isValid (old))
2854 uentry_mergeUses (current, old);
2855 uentry_setState (old, current);
2859 uentry_mergeState (old, current, exprNode_loc (sw),
2860 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2874 ** switch may or may not be followed by a new scope
2877 if (utab->kind == US_SWITCH)
2879 usymtab_quietPlainExitScope ();
2883 usymtab_quietPlainExitScope ();
2884 llassert (utab->kind == US_SWITCH);
2885 usymtab_quietPlainExitScope ();
2891 updateNullState (sRef el, /*@notnull@*/ usymtab ttab,
2892 /*@notnull@*/ usymtab ftab, bool trueGuard)
2894 sRef base = sRef_getRootBase (el);
2895 int level = sRef_lexLevel (base);
2897 if (sRef_isCvar (base))
2899 usymId index = sRef_getScopeIndex (base);
2900 uentry ue = usymtab_getRefTab (ttab, level, index);
2902 if (!uentry_isLset (ue))
2904 sRef sr = uentry_getSref (ue);
2908 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2912 if (!guardSet_isGuarded (ttab->guards, el)
2913 && !sRef_isNotNull (sr))
2915 DPRINTF (("Here! %s / %s",
2916 sRef_unparseFull (sr),
2917 sRef_unparseFull (el)));
2918 sRef_setDerivNullState (sr, el, NS_DEFNULL);
2927 ue = usymtab_getRefTab (ftab, level, index);
2929 if (!uentry_isLset (ue))
2931 sRef sr = uentry_getSref (ue);
2933 if (!trueGuard) /* yikes! forgot the ! */
2935 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2940 if (!guardSet_isGuarded (ftab->guards, el)
2941 && !sRef_isNotNull (sr))
2943 sRef_setDerivNullState (sr, el, NS_DEFNULL);
2955 usymtab_popBranches (exprNode pred, exprNode tbranch, exprNode fbranch,
2956 bool isOpt, clause cl)
2960 usymtab ftab = utab;
2961 usymtab ttab = utab->env;
2965 guardSet guards = exprNode_getGuards (pred);
2966 sRefSet tguards = guardSet_getTrueGuards (guards);
2967 sRefSet fguards = guardSet_getFalseGuards (guards);
2968 bool mustReturnT = exprNode_mustEscape (tbranch);
2969 bool mustReturnF = exprNode_mustEscape (fbranch);
2971 DPRINTF (("Pop branches: %s [mustreturn: %s/%s]", exprNode_unparse (pred),
2972 bool_unparse (mustReturnT),
2973 bool_unparse (mustReturnF)));
2975 if (exprNode_isDefined (fbranch))
2977 loc = exprNode_loc (fbranch);
2981 loc = exprNode_loc (tbranch);
2984 llassert (usymtab_isDefined (ttab));
2988 llassert (usymtab_isDefined (env));
2989 llassert (ftab->kind == US_FBRANCH);
2990 llassert (ttab->kind == US_TBRANCH);
2993 ** For each element that is true guarded (i.e., if (x != NULL))
2994 ** make x = null in false branch,
2995 ** and x = notnull in true branch.
2996 ** unless x was set locally in that branch.
2997 ** For each element that is false guarded (x == NULL)
2998 ** make x = null in true, notnull in false.
3000 ** For each element that is either guarded (pred(x))
3004 sRefSet_allElements (tguards, el)
3006 updateNullState (el, ttab, ftab, TRUE);
3007 } end_sRefSet_allElements;
3009 sRefSet_allElements (fguards, el)
3011 updateNullState (el, ttab, ftab, FALSE);
3012 } end_sRefSet_allElements;
3016 ** if an entry is in both true and false, merge the entries,
3017 ** then replace original with new state.
3019 ** if an entry is in one table, merge it with the original.
3022 DPRINTF (("ftab: %d", ftab->nentries));
3024 for (i = 0; i < ftab->nentries; i++)
3026 uentry fthis = ftab->entries[i];
3027 uentry old = usymtab_lookupAux (env, uentry_rawName (fthis));
3028 int tindex = usymtab_getIndex (ttab, uentry_rawName (fthis));
3030 DPRINTF (("Entry: %s / %s", uentry_unparseFull (fthis), uentry_unparseFull (old)));
3032 if (uentry_isUndefined (old))
3034 /* possible entry was added as an undefined id */
3035 DPRINTF (("Undefined! %s", uentry_rawName (fthis)));
3039 if (tindex != NOT_FOUND)
3041 uentry tthis = ttab->entries[tindex];
3043 /* note that is this is in a nested branch,
3044 it may create a "new" old entry. */
3050 uentry_mergeState (fthis, tthis, loc,
3051 mustReturnT, FALSE, FALSE, cl);
3055 uentry_mergeUses (fthis, tthis);
3058 uentry_setState (old, fthis);
3065 uentry_setState (old, tthis);
3066 uentry_mergeState (old, fthis, loc, mustReturnF,
3070 ttab->entries[tindex] = uentry_undefined;
3071 uentry_free (tthis);
3075 uentry_mergeState (old, fthis, loc, mustReturnF, TRUE, FALSE, cl);
3079 for (i = 0; i < ttab->nentries; i++)
3081 uentry current = ttab->entries[i];
3083 DPRINTF (("ttab: %s", uentry_unparseFull (current)));
3085 if (!uentry_isUndefined (current))
3087 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
3089 DPRINTF (("Old: %s", uentry_unparseFull (old)));
3091 if (uentry_isUndefined (old))
3093 llcontbug (message ("Undefined entry: %s", uentry_rawName (current)));
3099 uentry_mergeUses (current, old);
3100 uentry_setState (old, current);
3105 ** Assumes false branch is a fall-through if
3106 ** fbranch is not defined. This is true, unless
3107 ** where was some greivous error in processing
3108 ** the else branch of an if-then, in which case
3109 ** this is probably the right thing to do anyway.
3112 uentry_mergeState (old, current, loc, mustReturnT,
3116 DPRINTF (("==> %s", uentry_unparseFull (old)));
3121 ** Plain levelUnion doesn't work, since we need to use the sRef's in env->aliases
3122 ** if they are present.
3125 llassert (NOALIAS (env->aliases, ttab->aliases));
3126 llassert (NOALIAS (env->aliases, ftab->aliases));
3128 aliasTable_free (env->aliases);
3130 env->aliases = aliasTable_levelUnionNew (ttab->aliases,
3131 ftab->aliases, env->lexlevel);
3133 aliasTable_fixSrefs (env->aliases);
3135 DPRINTF (("Aliases: %s", aliasTable_unparse (env->aliases)));
3137 /* exit true and false scopes */
3138 usymtab_quietPlainExitScope ();
3139 usymtab_quietPlainExitScope ();
3143 utab->guards = guardSet_levelUnionFree
3145 guardSet_invert (exprNode_getGuards (pred)),
3151 utab->guards = guardSet_levelUnion (utab->guards,
3152 exprNode_getGuards (pred),
3156 DPRINTF (("Here."));
3159 static void usymtab_fixCases (void) /*@modifies utab@*/ {
3160 while (utab->kind == US_CBRANCH)
3162 usymtab_quietPlainExitScope ();
3165 llassert (utab->kind != US_CBRANCH);
3169 usymtab_altBranch (/*@only@*/ guardSet guards)
3173 usymtab parent = utab->env;
3175 t = usymtab_create (US_FBRANCH, utab, FALSE);
3178 ** If we are in a case, need to close it. The C syntax
3179 ** is very liberal, so this kludge is necessary.
3182 usymtab_fixCases ();
3184 DPRINTF (("Current kind: %s", usymtab_unparseStack ()));
3186 llassert (utab->kind == US_TBRANCH);
3187 llassert (parent != GLOBAL_ENV);
3189 guardSet_free (t->guards);
3192 aliasTable_free (t->aliases);
3193 t->aliases = aliasTable_copy (parent->aliases);
3199 usymtab_allDefined (void)
3200 /*@globals utab, globtab@*/
3204 llassert (utab == globtab);
3206 for (i = 0; i < utab->nentries; i++)
3208 uentry e = utab->entries[i];
3210 if (uentry_isPriv (e))
3212 ; /* no need to define it */
3216 if (context_getFlag (FLG_SPECUNDECL))
3218 fileloc sloc = uentry_whereSpecified (e);
3219 fileloc dloc = uentry_whereDeclared (e);
3221 if (fileloc_isDefined (sloc)
3222 && !uentry_isFakeTag (e)
3223 && !fileloc_isDefined (dloc))
3227 message ("%s %q specified but not declared",
3228 ekind_capName (uentry_getKind (e)),
3229 uentry_getName (e)),
3234 if (!uentry_isCodeDefined (e))
3236 fileloc dloc = uentry_whereDeclared (e);
3238 if (fileloc_isLib (dloc) || fileloc_isXHFile (dloc))
3242 else if (fileloc_isDefined (dloc))
3244 if (!uentry_isAnyTag (e))
3246 if (fileloc_isUser (dloc))
3250 message ("%s %q declared but not defined",
3251 ekind_capName (uentry_getKind (e)),
3252 uentry_getName (e)),
3254 DPRINTF (("decl: %s", uentry_unparseFull (e)));
3260 fileloc sloc = uentry_whereSpecified (e);
3262 if (fileloc_isDefined (sloc)
3263 && !fileloc_isImport (sloc)
3264 && !fileloc_isLib (sloc)
3265 && !fileloc_isPreproc (sloc)
3266 && !uentry_isFakeTag (e))
3268 if (uentry_isVariable (e) || uentry_isFunction (e))
3272 message ("%s %q specified but not declared or defined",
3273 ekind_capName (uentry_getKind (e)),
3274 uentry_getName (e)),
3281 message ("%s %q specified but not defined",
3282 ekind_capName (uentry_getKind (e)),
3283 uentry_getName (e)),
3293 void usymtab_exportHeader (void)
3298 for (i = 0; i < utab->nentries; i++)
3300 uentry ce = utab->entries[i];
3302 if (!uentry_isDatatype (ce)
3303 && !uentry_isAnyTag (ce)
3304 && !uentry_isEitherConstant (ce) && !uentry_isStatic (ce)
3305 && !uentry_isExternal (ce)
3306 && !uentry_isForward (ce))
3308 fileloc fwhere = uentry_whereDeclared (ce);
3310 if (fileloc_isUndefined (fwhere)
3311 && uentry_isFunction (ce))
3313 fwhere = uentry_whereDefined (ce);
3316 if (fileloc_isDefined (fwhere)
3317 && !fileloc_isHeader (fwhere)
3318 && !fileloc_isXHFile (fwhere)
3319 && !(fileloc_isSpecialFile (fwhere)
3320 && !context_getFlag (FLG_UNUSEDSPECIAL)))
3322 if (uentry_isVariable (ce))
3325 (FLG_EXPORTHEADERVAR,
3326 message ("%s %q exported but not declared in header file",
3327 ekind_capName (uentry_getKind (ce)),
3328 uentry_getName (ce)),
3331 uentry_showDefSpecInfo (ce, fwhere);
3336 if (!uentry_isIter (ce)
3337 && !uentry_isEndIter (ce)
3338 && !uentry_isExpandedMacro (ce))
3340 if (uentry_isFunction (ce)
3341 && cstring_equalLit (uentry_rawName (ce), "main"))
3343 ; /* no error for main */
3349 message ("%s %q exported but not declared "
3351 ekind_capName (uentry_getKind (ce)),
3352 uentry_getName (ce)),
3355 uentry_showDefSpecInfo (ce, fwhere);
3365 void usymtab_exportLocal (void)
3370 for (i = 0; i < utab->nentries; i++)
3372 uentry ce = utab->entries[i];
3374 if (!uentry_isDatatype (ce) && !uentry_isAnyTag (ce)
3375 && !uentry_isEitherConstant (ce)
3376 && !uentry_isIter (ce)
3377 && !uentry_isEndIter (ce)
3378 && !uentry_isExpandedMacro (ce)
3379 && uentry_isUsed (ce))
3381 /* check static uses */
3382 filelocList fuses = uentry_getUses (ce);
3383 fileloc mod = uentry_whereDefined (ce);
3384 bool ok = filelocList_isEmpty (fuses);
3385 fileloc fwhere = uentry_whereDeclared (ce);
3387 if (fileloc_isSpecialFile (fwhere)
3388 && !context_getFlag (FLG_UNUSEDSPECIAL))
3390 ok = TRUE; /* no errors for special files */
3394 filelocList_elements (fuses, uloc)
3396 if (fileloc_isUndefined (uloc) || !fileloc_sameModule (uloc, mod))
3399 /*@innerbreak@*/ break;
3401 } end_filelocList_elements;
3408 message ("%s exported but not used outside %s: %q",
3409 ekind_capName (uentry_getKind (ce)),
3410 fileloc_getBase (mod),
3411 uentry_getName (ce)),
3414 uentry_showDefSpecInfo (ce, fwhere);
3422 usymtab_allUsed (void)
3426 bool isFileStatic = usymtab_inFileScope ();
3427 cstring last_file = cstring_undefined;
3429 for (i = 0; i < utab->nentries; i++)
3431 bool hasError = FALSE;
3432 uentry ce = utab->entries[i];
3433 fileloc fwhere = uentry_whereDeclared (ce);
3435 if (fileloc_isUndefined (fwhere))
3437 fwhere = uentry_whereDefined (ce);
3440 if (fileloc_isInvalid (fwhere)
3441 || fileloc_isLib (fwhere)
3442 || fileloc_isBuiltin (fwhere)
3443 || ((fileloc_isSpecialFile (fwhere)
3444 || fileloc_isSpecialFile (uentry_whereDefined (ce)))
3445 && !context_getFlag (FLG_UNUSEDSPECIAL)))
3449 else if (!uentry_wasUsed (ce) && !uentry_isAnyTag (ce))
3451 cstring fname = fileloc_filename (fwhere);
3453 if (cstring_isUndefined (last_file))
3457 else if (cstring_equal (fname, last_file))
3466 if (uentry_isParam (ce))
3468 if (context_inMacro ())
3470 sRef cref = uentry_getSref (ce);
3472 if (uentry_isYield (ce))
3474 ; /* no checks (for now) */
3476 else if (sRef_isSafe (cref))
3482 if (uentry_hasRealName (ce))
3485 optgenerror (FLG_MACROPARAMS,
3486 message ("Macro parameter %q not used",
3487 uentry_getName (ce)),
3494 if (cstring_equalFree (uentry_getName (ce),
3495 cstring_makeLiteral ("...")))
3501 hasError = optgenerror (FLG_PARAMUNUSED,
3502 message ("Parameter %q not used",
3503 uentry_getName (ce)),
3508 else if (uentry_isFunction (ce) || uentry_isIter (ce))
3510 if (fileloc_isUser (fwhere))
3512 hasError = optgenerror
3514 message ("%q %q declared but not used",
3516 (uentry_isIter (ce) ? "Iterator"
3517 : (isFileStatic ? "File static function" : "Function")),
3518 uentry_getName (ce)),
3522 else if (uentry_isEndIter (ce))
3524 ; /* no error (already reported for iter */
3526 else if (uentry_isEnumConstant (ce))
3528 if (fileloc_isUser (fwhere))
3530 hasError = optgenerror
3532 message ("Enum member %q not used",
3533 uentry_getName (ce)),
3537 else if (uentry_isConstant (ce))
3539 if (fileloc_isUser (fwhere))
3541 hasError = optgenerror
3543 message ("Constant %q declared but not used",
3544 uentry_getName (ce)),
3548 else if (uentry_isDatatype (ce))
3550 if (fileloc_isUser (fwhere))
3552 hasError = optgenerror
3554 message ("Type %q declared but not used",
3555 uentry_getName (ce)),
3559 else if (!uentry_isRefParam (ce) && !uentry_isExpandedMacro (ce))
3560 { /* errors for ref params will be reported in the next scope */
3561 llassertprint (uentry_isVar (ce),
3562 ("ce: %s", uentry_unparseFull (ce)));
3564 if (ctype_isFunction (uentry_getType (ce)))
3566 if (fileloc_isUser (fwhere))
3568 hasError = optgenerror
3570 message ("%q %q declared but not used",
3572 (isFileStatic ? "File static function"
3574 uentry_getName (ce)),
3580 if (fileloc_isUser (fwhere))
3584 hasError = optgenerror
3586 message ("%q %q declared but not used",
3588 (isFileStatic ? "File static variable"
3590 uentry_getName (ce)),
3600 else if ((uentry_isDatatype (ce) || uentry_isAnyTag (ce)))
3601 { /* check all fields */
3602 ctype ct = uentry_getRealType (ce);
3605 while (ctype_isAP (ct))
3607 ct = ctype_getBaseType (ct);
3610 if (ctype_isSU (ct))
3612 uentryList fields = ctype_getFields (ct);
3614 uentryList_elements (fields, field)
3616 if (!uentry_isUsed (field))
3618 if (uentry_hasName (ce))
3620 hasError |= optgenerror
3622 message ("Field %q of %s %q declared but not used",
3623 uentry_getName (field),
3624 cstring_makeLiteralTemp
3625 (ctype_isStruct (ct) ? "structure" : "union"),
3626 uentry_getName (ce)),
3627 uentry_whereEarliest (field));
3633 ** Can't report these errors for unnamed structs.
3634 ** No way to tell when there are multiple consistent
3635 ** unnamed structure types. (Could go through table
3636 ** and mark them all unused...)
3638 hasError |= optgenerror
3640 message ("Field %q of unnamed %s declared but not used",
3641 uentry_getName (field),
3642 cstring_makeLiteralTemp
3643 (ctype_isStruct (ct) ? "structure" : "union")),
3644 uentry_whereEarliest (field));
3649 uentry_setUsed (field, fileloc_undefined);
3651 } end_uentryList_elements;
3661 if (uentry_isParam (ce) && context_inMacro ())
3663 if (fileloc_isDefined (uentry_whereSpecified (ce)))
3665 uentry_showWhereSpecified (ce);
3670 uentry_showDefSpecInfo (ce, fwhere);
3673 uentry_setUsed (ce, fileloc_undefined);
3679 checkGlobalReturn (uentry glob, sRef orig)
3681 sRef sr = uentry_getSref (glob);
3683 DPRINTF (("Check global return: %s / orig: %s / sr: %s",
3684 uentry_unparseFull (glob),
3685 sRef_unparseFull (orig),
3686 sRef_unparseFull (sr)));
3688 DPRINTF (("Is killed: %s", bool_unparse (sRef_isKilledGlob (orig))));
3690 if (context_getFlag (FLG_GLOBSTATE))
3692 DPRINTF (("Is killed: %s", sRef_unparseFull (orig)));
3694 if (sRef_isKilledGlob (orig))
3696 if (sRef_isStateUndefined (sr)
3697 || sRef_isUnuseable (sr)
3698 || sRef_isStateUnknown (sr)
3699 || sRef_isDead (sr))
3705 ctype ct = ctype_realType (uentry_getType (glob));
3707 DPRINTF (("Check global destroyed: %s", uentry_unparseFull (glob)));
3709 if (ctype_isVisiblySharable (ct))
3714 ("Killed global %q (type %s) not released before return",
3715 uentry_getName (glob),
3716 ctype_unparse (ct)),
3719 sRef_showStateInfo (sr);
3724 sRef_protectDerivs ();
3725 (void) transferChecks_globalDestroyed (sr, g_currentloc);
3726 sRef_clearProtectDerivs ();
3732 if (sRef_isStateUndefined (sr))
3734 if (optgenerror (FLG_GLOBSTATE,
3736 ("Function returns with global %q undefined",
3737 uentry_getName (glob)),
3740 sRef_showStateInfo (sr);
3745 if (sRef_isDead (sr) || sRef_isKept (sr))
3749 message ("Function returns with global %q "
3750 "referencing %s storage",
3751 uentry_getName (glob),
3752 cstring_makeLiteralTemp (sRef_isDead (sr) ? "released" : "kept")),
3755 if (sRef_isKept (sr))
3757 sRef_showAliasInfo (sr);
3761 sRef_showStateInfo (sr);
3764 sRef_setDefState (sr, SS_UNKNOWN, fileloc_undefined);
3768 if (ctype_isRealPointer (uentry_getType (glob))
3769 && sRef_possiblyNull (sr)
3770 && !uentry_possiblyNull (glob))
3774 message ("Function returns with non-null global %q "
3775 "referencing null storage",
3776 uentry_getName (glob)),
3779 sRef_showNullInfo (sr);
3784 DPRINTF (("Check transfer: %s", uentry_unparseFull (glob)));
3785 transferChecks_globalReturn (glob);
3793 ** remember: check alias globals
3796 void usymtab_checkFinalScope (bool isReturn)
3799 bool mustFree = context_getFlag (FLG_MUSTFREEONLY) || context_getFlag (FLG_MUSTFREEFRESH); /*@i423 remove this mustFree */
3800 bool mustDefine = context_getFlag (FLG_MUSTDEFINE);
3801 /* bool mustNotAlias = context_getFlag (FLG_MUSTNOTALIAS); */
3802 sRefSet checked = sRefSet_new ();
3803 usymtab stab = utab;
3807 ** need to check all scopes out to function parameters.
3812 for (i = 0; i < stab->nentries; i++)
3814 uentry ce = stab->entries[i];
3815 sRef sr = uentry_getSref (ce);
3816 sRef rb = sRef_getRootBase (sr);
3820 ** Shouldn't check if shadow checked in deeper scope:
3825 uentry oue = usymtab_lookupQuietNoAlt (utab, uentry_observeRealName (ce));
3827 if (!uentry_sameObject (ce, oue))
3829 DPRINTF (("Skipping outer entry: %s / %s", uentry_unparseFull (ce),
3830 uentry_unparseFull (oue)));
3831 /*@i32 what if it is one an alternate branch? */
3832 /*@innercontinue@*/ continue;
3836 DPRINTF (("Here check final scope: %s", uentry_unparseFull (ce)));
3838 if (ctype_isFunction (uentry_getType (ce)))
3840 /*@innercontinue@*/ continue;
3843 if (uentry_isAnyParam (ce)
3844 || uentry_isRefParam (ce)
3845 || sRef_isFileOrGlobalScope (rb))
3847 /* Don't do the loseref check...but should check state! */
3848 DPRINTF (("Skipping check 1"));
3850 else if (sRef_isDefinitelyNull (sr)
3851 || usymtab_isDefinitelyNull (sr))
3854 ** No state reference errors for definitely null references.
3857 DPRINTF (("Skipping check 2"));
3861 DPRINTF (("Lose ref: %s / %s", uentry_unparse (ce),
3862 sRef_unparseFull (sr)));
3864 tvalues = sRef_getValueTable (sr);
3866 valueTable_elements (tvalues, fkey, fval) {
3867 metaStateInfo minfo;
3868 cstring msg = cstring_undefined;
3871 minfo = context_lookupMetaStateInfo (fkey);
3872 llassert (metaStateInfo_isDefined (minfo));
3874 if (stateValue_isError (fval)
3875 || sRef_isStateUndefined (sr)) /* No errors for undefined state */
3877 DPRINTF (("Skipping check 3"));
3881 DPRINTF (("Check: %s / %s / %s", fkey,
3882 metaStateInfo_unparse (minfo),
3883 stateValue_unparse (fval)));
3885 minfo = context_lookupMetaStateInfo (fkey);
3887 nval = stateCombinationTable_lookupLoseReference
3888 (metaStateInfo_getTransferTable (minfo),
3889 stateValue_getValue (fval), &msg);
3891 if (cstring_isDefined (msg))
3893 /*@i32 print extra info for assignments@*/
3894 DPRINTF (("From: %s", sRef_unparseFull (sr)));
3895 DPRINTF (("Null? %s / %s",
3896 bool_unparse (sRef_isDefinitelyNull (sr)),
3897 bool_unparse (usymtab_isGuarded (sr))));
3902 ("%s loses reference %q in invalid state %q (%s)",
3903 cstring_makeLiteralTemp (isReturn ? "Return" : "Scope exit"),
3904 uentry_getName (ce),
3905 stateValue_unparseValue (fval, minfo),
3909 stateValue_show (fval, minfo);
3913 DPRINTF (("Suppressed transfer error: %s", msg));
3917 } end_valueTable_elements;
3920 DPRINTF (("Here 1"));
3924 DPRINTF (("Check mustfree entry: %s", uentry_unparseFull (ce)));
3926 if (!sRefSet_member (checked, sr) && !sRef_isFileOrGlobalScope (rb))
3928 if (ctype_isRealSU (uentry_getType (ce))
3929 && !uentry_isAnyParam (ce)
3930 && !uentry_isRefParam (ce)
3931 && !uentry_isStatic (ce)
3932 && !sRef_isDependent (sr)
3933 && !sRef_isOwned (sr))
3935 sRefSet als = usymtab_allAliases (sr);
3937 if (sRefSet_isEmpty (als))
3939 transferChecks_localDestroyed (sr, g_currentloc);
3943 /* aliased, no problem */ ;
3949 (!uentry_isStatic (ce)
3950 && ((sRef_isNewRef (sr))
3951 || (((sRef_isOnly (sr) || sRef_isFresh (sr)
3952 || sRef_isKeep (sr) || sRef_isOwned (sr))
3953 && !sRef_isDead (sr))
3954 && (!sRef_definitelyNull (sr))
3955 && (!usymtab_isDefinitelyNull (sr)))))
3957 bool hasError = TRUE;
3959 DPRINTF (("Checking: %s", sRef_unparseFull (sr)));
3962 ** If its a scope exit, check if there is an alias.
3963 ** If so, make it only. If not, there is an error.
3968 if (transferChecks_canLoseReference (sr, g_currentloc))
3970 DPRINTF (("Can lose!"));
3977 if (sRef_hasLastReference (sr))
3979 sRef ar = sRef_getAliasInfoRef (sr);
3982 (sRef_isFresh (ar) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
3984 ("Last reference %q to %s storage %qnot %q before %q",
3986 alkind_unparse (sRef_getAliasKind (sr)),
3987 sRef_unparseOpt (ar),
3988 cstring_makeLiteral (sRef_isKeep (sr)
3989 ? "transferred" : "released"),
3990 cstring_makeLiteral (isReturn
3991 ? "return" : "scope exit")),
3994 sRef_showRefLost (sr);
3997 else if (sRef_isNewRef (sr))
4000 (sRef_isFresh (sr) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4002 ("%q %q not released before %q",
4004 (alkind_isKillRef (sRef_getOrigAliasKind (sr))
4005 ? "Kill reference parameter" : "New reference"),
4006 uentry_getName (ce),
4007 cstring_makeLiteral (isReturn
4008 ? "return" : "scope exit")),
4011 sRef_showAliasInfo (sr);
4016 if (ctype_isRealSU (sRef_getType (sr)))
4018 transferChecks_structDestroyed (sr, g_currentloc);
4022 DPRINTF (("Here we are: %s", sRef_unparseFull (sr)));
4025 (sRef_isFresh (sr) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4027 ("%s storage %q not %q before %q",
4028 alkind_capName (sRef_getAliasKind (sr)),
4029 uentry_getName (ce),
4030 cstring_makeLiteral (sRef_isKeep (sr)
4031 ? "transferred" : "released"),
4032 cstring_makeLiteral (isReturn
4033 ? "return" : "scope exit")),
4036 sRef_showAliasInfo (sr);
4037 DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
4050 if (mustDefine && uentry_isOut (ce))
4052 /* No error if its dead (either only or error already reported */
4053 if (!sRef_isReallyDefined (sr) && !sRef_isDead (sr))
4057 message ("Out storage %q not defined before %q",
4058 uentry_getName (ce),
4060 (isReturn ? "return" : "scope exit")),
4063 DPRINTF (("sr: %s", sRef_unparseFull (sr)));
4068 ** also check state is okay
4071 if (usymtab_lexicalLevel () > functionScope
4072 && uentry_isVariable (ce)
4073 && (sRef_isLocalVar (sr)
4074 && (sRef_isDependent (sr) || sRef_isLocalState (sr))))
4076 sRefSet ab = usymtab_aliasedBy (sr);
4078 /* should do something more efficient here */
4080 if (sRefSet_isEmpty (ab))
4082 /* and no local ref */
4083 DPRINTF (("Check lose ref: %s", uentry_unparseFull (ce)));
4084 transferChecks_loseReference (ce);
4098 checked = sRefSet_insert (checked, sr);
4101 llassert (usymtab_isDefined (stab->env));
4103 if (usymtab_isBranch (stab))
4105 stab = usymtab_dropEnv (stab);
4112 llassert (stab != usymtab_undefined);
4113 } while (isReturn && (stab->lexlevel >= paramsScope));
4115 sRefSet_free (checked);
4119 ** all globals are appropriately defined
4120 ** all parameters are appropriately defined
4121 ** special clauses are followed
4124 if (isReturn || (utab->lexlevel == paramsScope))
4126 uentry fcn = context_getHeader ();
4127 uentryList params = context_getParams ();
4128 globSet uglobs = context_getUsedGlobs ();
4129 globSet sglobs = context_getGlobs ();
4131 if (isReturn && context_maybeSet (FLG_GLOBALIAS))
4133 aliasTable_checkGlobs (utab->aliases);
4137 ** state clauses (ensures, defines, sets, allocates, releases)
4140 if (uentry_hasStateClauseList (fcn))
4142 stateClauseList clauses = uentry_getStateClauseList (fcn);
4144 stateClauseList_elements (clauses, cl)
4146 if (stateClause_isAfter (cl) && !stateClause_isGlobal (cl))
4148 if (stateClause_setsMetaState (cl))
4150 sRefSet rfs = stateClause_getRefs (cl);
4151 qual q = stateClause_getMetaQual (cl);
4152 annotationInfo ainfo = qual_getAnnotationInfo (q);
4153 metaStateInfo minfo = annotationInfo_getState (ainfo);
4154 cstring key = metaStateInfo_getName (minfo);
4155 int mvalue = annotationInfo_getValue (ainfo);
4157 DPRINTF (("Post meta state clause: %s", stateClause_unparse (cl)));
4159 sRefSet_elements (rfs, el)
4161 sRef base = sRef_getRootBase (el);
4163 if (sRef_isResult (base))
4166 ** This is checked for return transfers.
4170 else if (sRef_isParam (base) || sRef_isGlobalMarker (base))
4172 sRef sr = sRef_updateSref (base);
4173 sr = sRef_fixBase (el, sr);
4175 if (!sRef_checkMetaStateValue (sr, key, mvalue))
4180 ("Ensures clause not satisfied%q (state is %q): %q",
4181 sRef_isGlobalMarker (sr)
4183 : message (" by %q", sRef_unparse (sr)),
4184 stateValue_unparseValue (sRef_getMetaStateValue (sr, key),
4186 stateClause_unparse (cl)),
4189 sRef_showMetaStateInfo (sr, key);
4195 if (sRef_isMeaningful (el))
4200 } end_sRefSet_elements ;
4204 /* evs - 2000 07 10 - added this */
4205 sRefTest tst = stateClause_getPostTestFunction (cl);
4206 sRefSet rfs = stateClause_getRefs (cl);
4208 sRefSet_elements (rfs, el)
4210 sRef base = sRef_getRootBase (el);
4212 if (sRef_isResult (base))
4215 ** This is checked for return transfers.
4220 else if (sRef_isParam (base))
4222 sRef sr = sRef_updateSref (base);
4223 sr = sRef_fixBase (el, sr);
4225 if (tst != NULL && !tst (sr))
4228 (stateClause_postErrorCode (cl),
4229 message ("%s storage %qcorresponds to "
4230 "storage listed in %q clause",
4231 stateClause_postErrorString (cl, sr),
4232 sRef_unparseOpt (sr),
4233 stateClause_unparseKind (cl)),
4236 sRefShower ss = stateClause_getPostTestShower (cl);
4243 DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
4249 if (sRef_isMeaningful (el))
4254 } end_sRefSet_elements ;
4257 } end_stateClauseList_elements ;
4261 ** check parameters on return
4264 uentryList_elements (params, arg)
4266 if (!uentry_isElipsisMarker (arg))
4268 ctype rt = ctype_realType (uentry_getType (arg));
4270 if (ctype_isMutable (rt) || ctype_isSU (rt))
4272 uentry param = usymtab_lookupQuiet (utab, uentry_rawName (arg));
4273 DPRINTF (("Check param return: %s", uentry_unparseFull (param)));
4274 transferChecks_paramReturn (param);
4277 } end_uentryList_elements;
4279 DPRINTF (("Check global return: %s",
4280 globSet_unparse (sglobs)));
4282 globSet_allElements (sglobs, el)
4284 sRef orig = el; /*! sRef_updateSref (el); */ /*!!!*/
4285 uentry current = sRef_getUentry (el);
4287 DPRINTF (("Check global return: %s / %s", sRef_unparseFull (el),
4288 uentry_unparseFull (current)));
4290 if (uentry_isVariable (current) && !uentry_isRealFunction (current))
4292 checkGlobalReturn (current, orig);
4294 } end_globSet_allElements;
4296 globSet_allElements (uglobs, el)
4298 if (!globSet_member (sglobs, el))
4300 uentry current = sRef_getUentry (el);
4302 if (uentry_isVariable (current)
4303 && !uentry_isRealFunction (current))
4305 checkGlobalReturn (current, sRef_undefined);
4308 } end_globSet_allElements;
4313 usymtab_quietExitScope (fileloc loc)
4314 /*@globals utab, globtab, filetab; @*/
4317 usymtab t = utab->env;
4319 if (utab->reftable != NULL)
4323 for (i = 0; i < utab->nentries; i++)
4325 uentry current = utab->entries[i];
4326 uentry old = usymtab_lookupAux (t, uentry_rawName (current));
4328 uentry_mergeState (old, current, loc, FALSE, FALSE, FALSE, NOCLAUSE);
4332 llassert (t != NULL);
4334 if (t->lexlevel > paramsScope)
4336 t->guards = guardSet_levelUnion (t->guards, utab->guards, t->lexlevel);
4337 t->aliases = aliasTable_levelUnionSeq (t->aliases, utab->aliases,
4339 utab->aliases = aliasTable_undefined;
4342 t->mustBreak = utab->mustBreak;
4343 t->exitCode = utab->exitCode;
4345 usymtab_freeLevel (utab);
4350 usymtab_checkAllValid ();
4355 ** Exit a scope with no checking, lose alias states.
4356 ** (When should this be used?)
4359 void usymtab_quietPlainExitScope (void)
4360 /*@globals utab, globtab, filetab@*/
4363 usymtab t = utab->env;
4365 llassert (t != NULL);
4366 llassert (NOALIAS (utab->aliases, t->aliases));
4367 usymtab_freeLevel (utab);
4371 void usymtab_exitScope (exprNode expr)
4372 /*@globals utab, filetab, globtab@*/
4373 /*@modifies utab, globtab@*/
4375 usymtab ctab = usymtab_undefined;
4376 usymtab lctab = usymtab_undefined;
4377 bool mustReturn = exprNode_mustEscape (expr);
4379 DPRINTF (("Exit scope"));
4381 if (utab->kind == US_CBRANCH)
4384 ** save the case branches, remove the first non-cbranch
4389 while (utab->kind == US_CBRANCH)
4393 llassert (utab != GLOBAL_ENV);
4397 if (utab->kind == US_TBRANCH || utab->kind == US_FBRANCH
4398 || utab->kind == US_CBRANCH || utab->kind == US_SWITCH)
4400 if (context_inMacro ())
4402 /* evs 2000-07-25 */
4403 /* Unparseable macro may end inside nested scope. Deal with it. */
4405 llerror (FLG_SYNTAX,
4406 message ("Problem parsing macro body of %s (unbalanced scopes). "
4407 "Attempting to recover, recommend /*@notfunction@*/ before "
4408 "macro definition.",
4409 context_inFunctionName ()));
4411 while (utab->kind == US_TBRANCH
4412 || utab->kind == US_FBRANCH
4413 || utab->kind == US_CBRANCH
4414 || utab->kind == US_SWITCH)
4417 llassert (utab != GLOBAL_ENV);
4421 llcontbug (message ("exitScope: in branch: %q", usymtab_unparseStack ()));
4423 } /*@=branchstate@*/
4427 ** check all variables in scope were used
4431 ** bogus errors if this is the normal inside a switch,
4432 ** since cases have not been merged yet. Should probably
4433 ** still check this, but I'm too lazy at the moment...
4436 llassertfatal (utab->env != GLOBAL_ENV);
4438 if (utab->env->kind != US_SWITCH)
4444 ** check aliasing: all only params are released (dead)
4445 ** definition: all out params are defined, all modified params
4446 ** are completely defined
4448 ** NOTE: note for exiting paramsScope, since checkReturn should be
4452 if (!mustReturn && (usymtab_lexicalLevel () > functionScope))
4455 ** should only call this is end of scope is reachable...
4458 usymtab_checkFinalScope (FALSE);
4461 if (usymtab_lexicalLevel () == paramsScope && context_inFunctionLike ())
4464 ** leaving a function, need to fix up globals
4467 uentryList params = context_getParams ();
4468 globSet globs = context_getUsedGlobs ();
4470 uentryList_elements (params, ue)
4472 uentry_fixupSref (ue);
4473 } end_uentryList_elements;
4475 clearFunctionTypes ();
4477 DPRINTF (("Fixing up globals: %s", globSet_unparse (globs)));
4479 globSet_allElements (globs, el)
4481 DPRINTF (("Fix: %s", sRef_unparseDebug (el)));
4483 if (sRef_isCvar (el))
4486 int index = sRef_getScopeIndex (el);
4488 if (sRef_isFileStatic (el))
4490 llassert (usymtab_isDefined (filetab));
4491 current = usymtab_fetchIndex (filetab, index);
4495 current = usymtab_fetchIndex (globtab, index);
4498 if (uentry_isVariable (current))
4500 DPRINTF (("Fixup: %s", uentry_unparse (current)));
4501 uentry_fixupSref (current);
4505 DPRINTF (("Clear: %s", uentry_getSref (current)));
4506 sRef_clearDerived (uentry_getSref (current));
4510 sRef_clearDerived (el); /* evans 2002-03-14 - this is the likely source of many crashes! */
4511 } end_globSet_allElements;
4514 usymtab_quietExitScope (exprNode_loc (expr));
4516 if (lctab != usymtab_undefined)
4518 /*@i@*/ lctab->env = utab;
4519 /*@i@*/ utab = ctab;
4520 /*@-branchstate@*/ } /*@=branchstate@*/
4525 usymtab_checkAllValid ();
4531 ** yikes! don't let the '170 kids see this one...
4535 uentry_directParamNo (uentry ue)
4537 if (uentry_isVar (ue))
4539 sRef sr = uentry_getSref (ue);
4541 if (sRef_lexLevel (sr) == functionScope)
4543 int index = sRef_getScopeIndex (sr);
4545 if (index < uentryList_size (context_getParams ()))
4554 /*@dependent@*/ /*@exposed@*/ uentry
4555 usymtab_getParam (int paramno)
4559 ** requires in a function context (checked)
4561 ** depends on no nested functions --- the function
4562 ** parameters are ALWAYS one scope inside the global scope
4563 ** and entered in order!
4567 if (!context_inFunctionLike ())
4568 llfatalbug (message ("usymtab_getParam: not in function context: %q",
4569 context_unparse ()));
4571 while (s->lexlevel > paramsScope)
4576 llassert (usymtab_isDefined (s));
4578 if (paramno >= s->nentries)
4581 ** Parse errors lead to this.
4584 uentry err = uentry_makeVariableLoc (cstring_makeLiteralTemp ("<error>"),
4587 uentry_markOwned (err);
4591 return (s->entries[paramno]);
4594 static /*@dependent@*/ /*@exposed@*/ uentry
4595 usymtab_getRefTab (/*@notnull@*/ usymtab u, int level, usymId index)
4599 ue = usymtab_getRefNoisy (u, level, index);
4601 if (uentry_isUndefined (ue))
4603 llbug (message ("usymtab_getRef: out of range: %d. level = %d",
4610 static /*@dependent@*/ /*@exposed@*/ usymtab
4611 usymtab_dropEnv (/*@notnull@*/ usymtab s)
4613 if (s->kind == US_CBRANCH)
4621 llassert (s != GLOBAL_ENV);
4622 } while (s->kind == US_CBRANCH);
4623 /* drop all cases (except in nested scopes */
4626 llassert (s != GLOBAL_ENV);
4629 if (s->kind == US_FBRANCH)
4631 s = s->env; /* skip the true branch */
4632 llassert (usymtab_isDefined (s));
4633 llassert (s->kind == US_TBRANCH);
4636 llassert (s != GLOBAL_ENV);
4642 /*@dependent@*/ /*@exposed@*/ uentry
4643 usymtab_getRefQuiet (int level, usymId index)
4649 llassert (s != NULL);
4650 llassert (index >= 0);
4652 if (level > s->lexlevel)
4654 return uentry_undefined;
4657 llassertprint (level <= s->lexlevel, ("level: %d / lexlevel: %d",
4658 level, s->lexlevel));
4660 while (s->lexlevel > level)
4662 if (usymtab_isBranch (s))
4664 int eindex = refTable_lookup (s, level, index);
4666 if (eindex != NOT_FOUND)
4668 return (s->entries[eindex]);
4672 s = usymtab_dropEnv (s);
4675 while (usymtab_isBranch (s) && s->lexlevel == level)
4677 int eindex = refTable_lookup (s, level, index);
4679 if (eindex != NOT_FOUND)
4681 return (s->entries[eindex]);
4684 s = usymtab_dropEnv (s);
4687 if (index >= s->nentries)
4689 return uentry_undefined;
4692 llassert (!uentry_isUndefined (s->entries[index]));
4694 return s->entries[index];
4697 static /*@dependent@*/ /*@exposed@*/ uentry
4698 usymtab_getRefNoisy (/*@notnull@*/ usymtab s, int level, usymId index)
4701 uentry ue = uentry_undefined;
4703 llassert (index >= 0);
4705 while (s->lexlevel > level)
4707 if (usymtab_isBranch (s))
4709 int eindex = refTable_lookup (s, level, index);
4711 if (eindex != NOT_FOUND)
4713 ue = s->entries[eindex];
4717 while (!usymtab_isBranch (otab))
4719 otab = usymtab_dropEnv (otab);
4720 llassert (otab != GLOBAL_ENV);
4723 if (refTable_lookup (otab, level, index) == NOT_FOUND)
4725 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4737 s = usymtab_dropEnv (s);
4740 llassert (usymtab_isDefined (s));
4742 while (usymtab_isBranch (s) && s->lexlevel == level)
4744 int eindex = refTable_lookup (s, level, index);
4747 if (eindex != NOT_FOUND)
4749 ue = s->entries[eindex];
4753 while (!usymtab_isBranch (otab))
4755 otab = usymtab_dropEnv (otab);
4756 llassert (otab != GLOBAL_ENV);
4759 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4769 s = usymtab_dropEnv (s);
4772 if (s->lexlevel == level && (index < s->nentries))
4774 ue = s->entries[index];
4776 if (uentry_isValid (ue))
4780 while (!usymtab_isBranch (otab))
4782 otab = usymtab_dropEnv (otab);
4784 if (otab == GLOBAL_ENV)
4790 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4801 if (index >= s->nentries)
4803 return uentry_undefined;
4806 llassert (!uentry_isUndefined (s->entries[index]));
4808 return s->entries[index];
4812 ** looking up entries
4814 ** If entry is inside a branch, then copy it, and put it into
4815 ** the branch table.
4819 int refTable_lookup (/*@notnull@*/ usymtab ut, int level, int index)
4821 refTable rt = ut->reftable;
4824 llassert (rt != NULL);
4826 for (i = 0; i < ut->nentries; i++)
4828 if (rt[i]->level == level && rt[i]->index == index)
4838 /*@only@*/ refentry refentry_create (int level, int index)
4840 refentry r = (refentry) dmalloc (sizeof (*r));
4848 static /*@dependent@*/ /*@exposed@*/ uentry
4849 usymtab_addRefEntry (/*@notnull@*/ usymtab s, cstring k)
4854 if (ut->reftable == NULL)
4856 DPRINTF (("Adding ref entry without reftable: %s", k));
4857 return uentry_undefined;
4860 llassert (ut->reftable != NULL);
4862 while (s != GLOBAL_ENV)
4864 eindex = usymtab_getIndex (s, k);
4866 if (eindex != NOT_FOUND)
4868 uentry current = s->entries[eindex];
4870 if (uentry_isVar (current) && !ctype_isFunction (uentry_getType (current)))
4874 DPRINTF (("Here: copying %s", uentry_unparse (current)));
4875 ue = uentry_copy (current);
4876 DPRINTF (("Here: copying %s", uentry_unparse (ue)));
4877 usymtab_addEntryQuiet (ut, ue);
4878 DPRINTF (("Okay..."));
4880 if (s->reftable != NULL)
4882 refentry ref = s->reftable[eindex];
4884 ut->reftable[ut->nentries - 1]
4885 = refentry_create (ref->level, ref->index);
4889 ut->reftable[ut->nentries - 1]
4890 = refentry_create (s->lexlevel, eindex);
4901 s = usymtab_dropEnv (s);
4904 return uentry_undefined;
4907 static uentry usymtab_lookupAux (usymtab s, cstring k)
4909 DPRINTF (("Lookup: %s", k));
4911 while (s != GLOBAL_ENV)
4913 int eindex = usymtab_getIndex (s, k);
4915 if (eindex != NOT_FOUND)
4917 uentry ret = s->entries[eindex];
4921 if (s->kind == US_TBRANCH
4922 || s->kind == US_FBRANCH
4923 || s->kind == US_CBRANCH)
4924 /* uentry_isGlobalVariable (ret) && os->lexlevel > fileScope) */
4927 DPRINTF (("Adding global ref entry: %s", k));
4928 ret = usymtab_addRefEntry (os, k);
4929 DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
4934 DPRINTF (("Found: %s", uentry_unparseFull (ret)));
4938 if (s->kind == US_TBRANCH || s->kind == US_FBRANCH
4939 || s->kind == US_CBRANCH)
4941 /* why isn't this os??? */
4942 uentry ret = usymtab_addRefEntry (s, k);
4943 DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
4950 return uentry_undefined;
4953 static /*@dependent@*/ /*@exposed@*/ uentry
4954 usymtab_lookupQuietAux (usymtab s, cstring k, bool noalt)
4958 while (s != GLOBAL_ENV)
4960 eindex = usymtab_getIndex (s, k);
4962 if (eindex != NOT_FOUND)
4964 uentry ret = s->entries[eindex];
4968 if (noalt && usymtab_isBranch (s))
4970 s = usymtab_dropEnv (s);
4974 llassert (s != NULL); /*@i523 should not need this? */
4979 return uentry_undefined;
4982 static /*@exposed@*/ /*@dependent@*/ uentry
4983 usymtab_lookupQuiet (usymtab s, cstring k)
4985 return usymtab_lookupQuietAux (s, k, FALSE);
4988 static /*@exposed@*/ /*@dependent@*/ uentry
4989 usymtab_lookupQuietNoAlt (usymtab s, cstring k)
4991 return usymtab_lookupQuietAux (s, k, TRUE);
4994 /*@dependent@*/ /*@observer@*/ uentry
4995 usymtab_lookupSafe (cstring k)
4998 DPRINTF (("Lookup safe: %s", k));
4999 return (usymtab_lookupAux (utab, k));
5003 usymtab_lookupExpose (cstring k)
5006 uentry ce = usymtab_lookupAux (utab, k);
5008 if (uentry_isUndefined (ce))
5010 llfatalbug (message ("usymtab_lookup: not found: *%s*", k));
5013 if (uentry_isPriv (ce))
5015 llfatalbug (message ("usymtab_lookup: private: *%s*", k));
5021 uentry usymtab_lookupExposeGlob (cstring k)
5023 return (usymtab_lookupGlobSafe (k));
5026 uentry usymtab_lookupGlob (cstring k)
5027 /*@globals globtab@*/
5029 uentry ce = usymtab_lookupAux (globtab, k);
5031 if (uentry_isUndefined (ce))
5032 llfatalbug (message ("usymtab_lookup: not found: %s", k));
5034 if (uentry_isPriv (ce))
5035 llfatalbug (message ("usymtab_lookup: private: %s", k));
5037 DPRINTF (("Lookup global: %s", uentry_unparseFull (ce)));
5041 /*@observer@*/ uentry
5042 usymtab_lookupGlobSafe (cstring k)
5043 /*@globals globtab@*/
5045 uentry ce = usymtab_lookupAux (globtab, k);
5046 DPRINTF (("Lookup global: %s", uentry_unparseFull (ce)));
5050 uentry usymtab_lookupEither (cstring k)
5053 uentry ce = usymtab_lookupSafe (k);
5055 if (uentry_isUndefined (ce))
5056 llfatalerror (message ("usymtab_lookup: not found: %s", k));
5058 DPRINTF (("Lookup either: %s", uentry_unparseFull (ce)));
5064 usymtab_lookupType (cstring k)
5065 /*@globals globtab@*/
5067 usymId uid = usymtab_getTypeId (k);
5069 if (uid == USYMIDINVALID)
5071 llcontbug (message ("usymtab_lookupType: not found: %s", k));
5072 return ctype_unknown;
5075 return (uentry_getRealType (usymtab_getTypeEntry (uid)));
5080 usymtab_lookupAbstractType (cstring k) /*@globals globtab@*/
5082 usymId uid = usymtab_getTypeId (k);
5084 if (uid == USYMIDINVALID)
5086 llcontbug (message ("usymtab_lookupType: not found: %s", k));
5087 return ctype_unknown;
5090 return (uentry_getAbstractType (usymtab_getTypeEntry (uid)));
5094 ** if there is an unnamed lcl-specified struct tag matching
5095 ** the uentryList, return its datatype. Otherwise, returns
5100 usymtab_structFieldsType (uentryList f)
5101 /*@globals globtab@*/
5103 return (usymtab_suFieldsType (f, TRUE));
5107 usymtab_unionFieldsType (uentryList f)
5108 /*@globals globtab@*/
5110 return (usymtab_suFieldsType (f, FALSE));
5114 usymtab_suFieldsType (uentryList f, bool isStruct)
5115 /*@globals globtab@*/
5119 DPRINTF (("Fields: %s", uentryList_unparse (f)));
5121 if (fileloc_isSpec (g_currentloc))
5123 return (ctype_undefined);
5126 for (i = 0; i < globtab->nentries; i++)
5128 uentry current = globtab->entries[i];
5131 ? uentry_isStructTag (current) : uentry_isUnionTag (current)))
5133 if (isFakeTag (uentry_rawName (current)))
5135 ctype ct = uentry_getType (current);
5137 DPRINTF (("Check: %s", ctype_unparse (ct)));
5139 if ((isStruct ? ctype_isStruct (ct) : ctype_isUnion (ct))
5141 (uentry_isSpecified (current)
5142 && uentryList_equivFields (f, ctype_getFields (ct))))
5144 return uentry_getAbstractType (current);
5154 return ctype_undefined;
5158 usymtab_enumEnumNameListType (enumNameList f)
5159 /*@globals globtab@*/
5163 for (i = 0; i < globtab->nentries; i++)
5165 uentry current = globtab->entries[i];
5167 if (uentry_isEnumTag (current))
5169 if (isFakeTag (uentry_rawName (current)))
5171 ctype ct = uentry_getType (current);
5173 if (ctype_isEnum (ct) && (enumNameList_match (f, ctype_elist (ct))))
5175 return uentry_getType (current);
5181 return ctype_undefined;
5185 usymtab_exists (cstring k)
5188 uentry ce = usymtab_lookupSafe (k);
5189 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5193 usymtab_existsReal (cstring k)
5196 uentry ce = usymtab_lookupSafe (k);
5198 return (!(uentry_isUndefined (ce))
5199 && !(uentry_isPriv (ce))
5200 && !(uentry_isExpandedMacro (ce)));
5204 usymtab_existsGlob (cstring k)
5205 /*@globals globtab@*/
5207 uentry ce = usymtab_lookupAux (globtab, k);
5209 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5214 usymtab_existsEither (cstring k)
5217 uentry ce = usymtab_lookupAux (utab, k);
5219 return (uentry_isValid (ce));
5223 usymtab_existsGlobEither (cstring k)
5224 /*@globals globtab@*/
5226 uentry ce = usymtab_lookupAux (globtab, k);
5228 return (uentry_isValid (ce));
5233 usymtab_existsType (cstring k)
5234 /*@globals globtab@*/
5236 uentry ce = usymtab_lookupAux (globtab, k);
5238 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && uentry_isDatatype (ce));
5242 usymtab_existsTypeEither (cstring k)
5243 /*@globals globtab@*/
5246 ce = usymtab_lookupAux (globtab, k);
5247 return (uentry_isValid (ce) && uentry_isDatatype (ce));
5251 usymtab_existsStructTag (cstring k) /*@globals globtab@*/
5253 cstring sname = makeStruct (k);
5254 uentry ce = usymtab_lookupAux (globtab, sname);
5255 cstring_free (sname);
5256 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5260 usymtab_existsUnionTag (cstring k) /*@globals globtab@*/
5262 cstring uname = makeUnion (k);
5263 uentry ce = usymtab_lookupAux (globtab, uname);
5265 cstring_free (uname);
5267 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5271 usymtab_existsEnumTag (cstring k) /*@globals globtab@*/
5273 cstring ename = makeEnum (k);
5274 uentry ce = usymtab_lookupAux (globtab, ename);
5276 cstring_free (ename);
5277 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5281 bool usymtab_existsVar (cstring k)
5284 uentry ce = usymtab_lookupSafe (k);
5286 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && (uentry_isVar (ce)));
5295 refTable_free (/*@only@*/ /*@null@*/ refTable x, int nentries)
5301 for (i = 0; i < nentries; i++)
5311 usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab u)
5312 /*@globals globtab, utab, filetab@*/
5316 aliasTable_free (u->aliases);
5318 refTable_free (u->reftable, u->nentries);
5320 if (u == filetab || u == globtab)
5322 for (i = 0; i < u->nentries; i++)
5324 uentry_freeComplete (u->entries[i]);
5329 for (i = 0; i < u->nentries; i++)
5331 uentry_free (u->entries[i]);
5335 guardSet_free (u->guards);
5342 llassert (!cstringTable_isDefined (u->htable));
5350 usymtab_freeAux (/*@only@*/ usymtab u)
5351 /*@globals globtab, utab, filetab@*/
5354 while (u != GLOBAL_ENV)
5357 usymtab_freeLevel (u);
5364 void usymtab_free ()
5365 /*@globals killed utab, globtab, filetab@*/
5369 usymtab_freeAux (utab);
5372 static int usymtab_lexicalLevel (void) /*@globals utab@*/
5374 return (utab->lexlevel);
5377 bool usymtab_inGlobalScope () /*@globals utab, globtab@*/
5379 return (utab == globtab);
5382 bool usymtab_inFileScope () /*@globals utab@*/
5384 return (utab->lexlevel == fileScope);
5387 bool usymtab_inFunctionScope () /*@globals utab@*/
5389 return (utab->lexlevel == functionScope);
5394 usymtab_replaceEntry (uentry s)
5395 /*@globals utab, globtab@*/
5396 /*@modifies utab, s@*/
5398 usymtab_replaceEntryAux (utab, s);
5403 usymtab_matchForwardStruct (usymId u1, usymId u2)
5404 /*@globals globtab@*/
5406 uentry ue1 = usymtab_getTypeEntry (u1);
5407 uentry ue2 = usymtab_getTypeEntry (u2);
5409 if (uentry_isAnyTag (ue2))
5411 ctype reptype = uentry_getType (ue1);
5413 if (ctype_isPointer (reptype))
5415 ctype repbase = ctype_getBaseType (reptype);
5417 if (ctype_isUA (repbase))
5419 typeId rtuid = ctype_typeId (repbase);
5421 if (u2 == rtuid) return TRUE;
5423 if (usymId_isValid (rtuid))
5425 reptype = uentry_getType (usymtab_getTypeEntry (rtuid));
5427 return (ctype_isUA (reptype) && (u2 == (ctype_typeId (reptype))));
5436 void usymtab_addGuards (guardSet guards)
5439 utab->guards = guardSet_union (utab->guards, guards);
5442 static bool usymtab_isGuardedAux (sRef s)
5446 sRef base = sRef_getRootBase (s);
5447 int lowlevel = paramsScope;
5448 int baselevel = sRef_lexLevel (base);
5450 if (sRef_isCvar (base))
5452 lowlevel = baselevel;
5453 if (lowlevel < paramsScope) lowlevel = paramsScope;
5456 while (tab->lexlevel >= lowlevel)
5458 DPRINTF (("Is guarded? [%s] %s",
5459 guardSet_unparse (tab->guards),
5460 sRef_unparseFull (s)));
5462 if (guardSet_isGuarded (tab->guards, s))
5465 if (!sRef_definitelyNull (s))
5467 sRef_setNotNull (s, fileloc_undefined);
5473 tab = usymtab_dropEnv (tab);
5479 void usymtab_unguard (sRef s) /*@modifies utab@*/
5482 sRef base = sRef_getRootBase (s);
5483 int lowlevel = paramsScope;
5484 int baselevel = sRef_lexLevel (base);
5486 if (sRef_isCvar (base))
5488 lowlevel = baselevel;
5489 if (lowlevel < paramsScope) lowlevel = paramsScope;
5492 while (tab->lexlevel >= lowlevel)
5494 if (guardSet_isGuarded (tab->guards, s))
5496 guardSet_delete (tab->guards, s);
5499 tab = usymtab_dropEnv (tab);
5503 bool usymtab_isGuarded (sRef s)
5505 DPRINTF (("Is guarded? %s", sRef_unparseFull (s)));
5506 return (sRef_aliasCompleteSimplePred (usymtab_isGuardedAux, s));
5509 bool usymtab_isDefinitelyNull (sRef s)
5511 return (sRef_aliasCheckSimplePred (usymtab_isDefinitelyNullAux, s));
5514 bool usymtab_isDefinitelyNullDeep (sRef s)
5516 return (sRef_deepPred (usymtab_isDefinitelyNull, s));
5519 static bool usymtab_isDefinitelyNullAux (sRef s)
5523 sRef base = sRef_getRootBase (s);
5524 int lowlevel = paramsScope;
5526 if (sRef_isCvar (base))
5528 lowlevel = sRef_lexLevel (base);
5529 if (lowlevel < paramsScope) lowlevel = paramsScope;
5532 while (tab->lexlevel >= lowlevel)
5534 if (guardSet_mustBeNull (tab->guards, s))
5539 while (tab->kind == US_CBRANCH)
5544 llassert (usymtab_isDefined (tab));
5546 if (tab->kind == US_FBRANCH)
5549 llassert (tab->kind == US_TBRANCH);
5559 usymtab_printGuards ()
5560 /*@globals utab, globtab@*/
5562 usymtab ttab = utab;
5564 while (ttab != globtab)
5566 llmsg (message ("Guards [%d]: %q", ttab->lexlevel,
5567 guardSet_unparse (ttab->guards)));
5573 usymtab_displayAllUses ()
5574 /*@globals utab, globtab@*/
5578 /* only in top scope */
5579 llassert (utab == globtab);
5581 /* need a copy, so order is not messed up by sort! */
5582 copy = usymtab_shallowCopy (globtab);
5584 qsort (copy->entries, (size_t)copy->nentries,
5585 sizeof (*copy->entries), (int (*)(const void *, const void *)) uentry_xcompareuses);
5587 usymtab_entries (copy, ue)
5589 if (uentry_isValid (ue) && !uentry_isGlobalMarker (ue))
5591 filelocList uses = uentry_getUses (ue);
5592 int size = filelocList_realSize (uses);
5594 if (fileloc_isDefined (uentry_whereDefined (ue))
5595 && !fileloc_isLib (uentry_whereDefined (ue))
5598 llmsg (message ("%q (%q), %d use%&:\n %q",
5599 uentry_getName (ue),
5600 fileloc_unparse (uentry_whereDefined (ue)),
5601 size, filelocList_unparseUses (uses)));
5604 } end_usymtab_entries;
5606 usymtab_shallowFree (copy);
5609 static /*@dependent@*/ /*@exposed@*/ usymtab
5610 usymtab_getFileTab ()
5611 /*@globals filetab@*/
5613 llassert (filetab != NULL);
5619 usymtab_unparseStack ()
5622 return (usymtab_unparseStackTab (utab));
5625 static /*@only@*/ cstring
5626 usymtab_unparseStackTab (usymtab t)
5628 bool firstOne = TRUE;
5629 cstring ret = cstring_makeLiteral ("[");
5631 while (t != GLOBAL_ENV)
5635 ret = message ("%q %q", ret, usymtab_typeName (t));
5640 ret = message ("%q, %q", ret, usymtab_typeName (t));
5645 ret = message ("%q ]", ret);
5649 static /*@only@*/ cstring
5650 usymtab_typeName (/*@notnull@*/ usymtab t)
5654 case US_GLOBAL: return cstring_makeLiteral ("global");
5655 case US_NORMAL: return cstring_makeLiteral ("normal");
5656 case US_TBRANCH: return cstring_makeLiteral ("true");
5657 case US_FBRANCH: return cstring_makeLiteral ("false");
5658 case US_CBRANCH: return cstring_makeLiteral ("case");
5659 case US_SWITCH: return cstring_makeLiteral ("switch");
5665 void usymtab_addMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5668 if (!sRef_similar (s, al))
5670 usymtab_addForceMustAlias (s, al);
5675 ** Same as usymtab_addMustAlias, except does not check sRef_isSimilar.
5678 void usymtab_addForceMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5681 /* evans 2002-03-3: was sRef_isMeaningful -- but we need to keep aliases for new storage also! */
5682 if (sRef_isMeaningful (s)
5683 && sRef_isMeaningful (al)
5684 && !(sRef_isConst (s) || sRef_isConst (al))
5685 && !(sRef_isAddress (al) && sRef_isDirectParam (sRef_getBase (al))))
5687 utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
5688 DPRINTF (("Must alias: %s", aliasTable_unparse (utab->aliases)));
5691 ** for local variable, aliasing is symmetric
5694 if (sRef_isLocalVar (s) && sRef_isLocalVar (al))
5696 utab->aliases = aliasTable_addMustAlias (utab->aliases, al, s);
5701 DPRINTF (("Not aliasing! %s / %s", sRef_unparseFull (s), sRef_unparseFull (al)));
5702 DPRINTF (("meaningful: %d %d", sRef_isMeaningful (s), sRef_isMeaningful (al)));
5706 void usymtab_addReallyForceMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5709 utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
5712 void usymtab_clearAlias (sRef s)
5713 /*@modifies utab, s@*/
5716 aliasTable_clearAliases (utab->aliases, s);
5719 sRefSet usymtab_allAliases (sRef s)
5722 if (sRef_isSomewhatMeaningful (s))
5726 ret = sRefSet_unionFree (aliasTable_aliasedBy (utab->aliases, s),
5727 aliasTable_canAlias (utab->aliases, s));
5732 DPRINTF (("NOT A MEANINGFUL SREF!"));
5733 return sRefSet_undefined;
5737 /*@only@*/ sRefSet usymtab_canAlias (sRef s)
5740 if (sRef_isSomewhatMeaningful (s))
5742 sRefSet res = aliasTable_canAlias (utab->aliases, s);
5746 return sRefSet_undefined;
5749 /*@only@*/ sRefSet usymtab_aliasedBy (sRef s)
5752 return (aliasTable_aliasedBy (utab->aliases, s));
5755 /*@only@*/ cstring usymtab_unparseAliases ()
5758 return (aliasTable_unparse (utab->aliases));
5762 ** Debugging routines:
5763 ** okay to leak storage here, only for debugging
5769 usymtab_printOut (void)
5775 char *ind = mstring_copy (" ");
5777 fprintf (g_warningstream, "<<< [symbol table] >>>\n");
5779 while (s != GLOBAL_ENV && s->env != GLOBAL_ENV)
5781 cstring tname = usymtab_typeName (s);
5785 ind[depth * 3 + 1] = '\0';
5788 fprintf (g_warningstream, "level: %d (%s)\n", s->lexlevel,
5789 cstring_toCharsSafe (tname));
5791 cstring_free (tname);
5793 for (i = 0; i < s->nentries; i++)
5795 cstring us = uentry_unparseFull (s->entries[i]);
5796 fprintf (g_warningstream, "%s\n", cstring_toCharsSafe (us));
5800 if (s->reftable != NULL && s->nentries > 0)
5802 fprintf (g_warningstream, "\t<< Ref table >>\n");
5804 for (i = 0; i < s->nentries; i++)
5806 fprintf (g_warningstream, "\t%s %3d: %d, %d\n", ind, i,
5807 s->reftable[i]->level,
5808 s->reftable[i]->index);
5812 ind[depth * 3 + 1] = ' ';
5816 fprintf (g_warningstream, "<<< end usymtab >>>\n");
5822 usymtab_printTypes ()
5823 /*@globals globtab@*/
5825 usymtab_printAllAux (globtab);
5829 usymtab_printAll (void)
5832 usymtab_printAllAux (utab);
5836 usymtab_printAllAux (usymtab s)
5837 /*@modifies g_warningstream@*/
5841 char *ind = mstring_copy (" ");
5843 printf ("[[[ usymtab ]]]");
5845 while (s != GLOBAL_ENV)
5848 ind[depth * 3 + 1] = '\0';
5850 if (s->env == GLOBAL_ENV)
5854 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5855 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5856 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5860 for (i = looplow; i < s->nentries; i++)
5862 printf ("%s%3d. %s\n", ind, i,
5863 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5868 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5869 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5870 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5872 for (i = 0; i < s->nentries; i++)
5874 printf ("%s%3d %s\n", ind, i,
5875 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5879 ind[depth * 3 + 1] = ' ';
5883 printf ("----------\n");
5887 usymtab_printComplete ()
5892 char *ind = mstring_copy (" ");
5895 while (s != GLOBAL_ENV)
5899 ind[depth * 3 + 1] = '\0';
5902 if (s->env == GLOBAL_ENV)
5906 printf ("level: %d\n", s->lexlevel);
5910 for (i = looplow; i < s->nentries; i++)
5912 printf ("%s%3d %s\n", ind, i,
5913 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5918 printf ("level: %d\n", s->lexlevel);
5919 for (i = 0; i < s->nentries; i++)
5921 printf ("%s%3d %s\n", ind, i,
5922 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5926 ind[depth * 3 + 1] = ' ';
5931 printf ("----------\n");
5936 static /*@only@*/ cstring /*@unused@*/
5937 usymtab_unparseLocalAux (/*@notnull@*/ usymtab s)
5939 cstring c = message ("lexlevel: %d\n", s->lexlevel);
5942 for (i = 0; i < s->nentries; i++)
5944 c = message ("%q\n%q", c, uentry_unparseFull (s->entries[i]));
5947 c = message ("%q\n=========", c);
5951 static cstring /*@unused@*/ /*@only@*/
5952 usymtab_unparseLocalList (/*@notnull@*/ usymtab s)
5954 cstring c = message ("[%d/%s/%s] ", s->lexlevel,
5955 bool_unparse (s->mustBreak),
5956 exitkind_unparse (s->exitCode));
5959 for (i = 0; i < s->nentries; i++)
5961 sRef sr = uentry_getSref (s->entries[i]);
5965 c = message ("%q: %q [%b]", c, uentry_getName (s->entries[i]),
5966 sRef_isStateDefined (sr));
5970 c = message ("%q, %q [%b]", c, uentry_getName (s->entries[i]),
5971 sRef_isStateDefined (sr));
5981 usymtab_printLocal (void)
5987 printf ("lexlevel: %d\n", s->lexlevel);
5989 for (i = 0; i < s->nentries; i++)
5991 printf ("%s\n", cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5994 while (s->lexlevel > 1)
5999 llassert (usymtab_isDefined (s));
6001 printf ("Params:\n");
6003 for (i = 0; i < s->nentries; i++)
6005 printf ("%d: %s\n", i,
6006 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
6011 static bool checkDistinctExternalName (uentry e)
6012 /*@globals globtab@*/
6013 /*@modifies *g_warningstream@*/
6015 size_t checklen = size_fromInt (context_getValue (FLG_EXTERNALNAMELEN));
6016 bool ignorecase = context_getFlag (FLG_EXTERNALNAMECASEINSENSITIVE);
6017 bool gotone = FALSE;
6018 bool extras = FALSE;
6019 bool hasError = FALSE;
6020 cstring name = uentry_rawName (e);
6021 usymtab st = globtab;
6029 if (uentry_isAnyTag (e))
6031 checklen++; /* the tag marker doesn't count */
6035 usymtab_entries (st, oe)
6037 if (uentry_sameObject (oe, e))
6044 if (cstring_equalCaseInsensitive (uentry_rawName (oe), name))
6053 (FLG_DISTINCTEXTERNALNAMES,
6055 ("External identifier %q is not distinguishable from %q "
6056 "because alphabetical case is ignored",
6058 uentry_getName (oe)),
6059 uentry_whereLast (e)))
6061 uentry_showWhereAny (oe);
6062 uentry_setHasNameError (oe);
6071 if (cstring_equalLenCaseInsensitive (uentry_rawName (oe),
6080 if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6083 (FLG_DISTINCTEXTERNALNAMES,
6086 ("External identifier %q is not distinguishable from %q "
6087 "in the first %d characters (%q)",
6089 uentry_getName (oe),
6090 size_toInt (checklen),
6091 cstring_clip (uentry_getName (e), checklen)),
6093 uentry_whereLast (e)))
6095 uentry_showWhereAny (oe);
6096 uentry_setHasNameError (oe);
6109 (FLG_DISTINCTEXTERNALNAMES,
6111 ("External identifier %q is not distinguishable from %q "
6112 "in the first %d characters because alphabetical case "
6115 uentry_getName (oe),
6116 size_toInt (checklen)),
6117 uentry_whereLast (e)))
6119 uentry_showWhereAny (oe);
6120 uentry_setHasNameError (oe);
6126 else if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6135 (FLG_DISTINCTEXTERNALNAMES,
6138 ("External identifier %q is not distinguishable from %q "
6139 "in the first %d characters (%q)",
6141 uentry_getName (oe),
6142 size_toInt (checklen),
6143 cstring_clip (uentry_getName (e), checklen)),
6145 uentry_whereLast (e)))
6147 uentry_showWhereAny (oe);
6148 uentry_setHasNameError (oe);
6157 } end_usymtab_entries ;
6164 (cstring_makeLiteral ("One or more additional "
6165 "indistinguishable external "
6166 "names not reported"));
6172 static bool checkDistinctInternalName (uentry e)
6174 /*@modifies *g_warningstream@*/
6176 usymtab ttab = utab;
6177 cstring name = uentry_rawName (e);
6178 size_t numchars = size_fromInt (context_getValue (FLG_INTERNALNAMELEN));
6179 bool caseinsensitive = context_getFlag (FLG_INTERNALNAMECASEINSENSITIVE);
6180 bool lookalike = context_getFlag (FLG_INTERNALNAMELOOKALIKE);
6182 if (uentry_isAnyTag (e) && (numchars != 0))
6184 numchars++; /* the tag marker doesn't count */
6187 while (usymtab_isDefined (ttab))
6189 usymtab_entries (ttab, oe)
6191 if (uentry_sameObject (oe, e))
6193 /*@innercontinue@*/ continue;
6196 switch (cstring_genericEqual
6197 (name, uentry_rawName (oe),
6198 numchars, caseinsensitive, lookalike))
6200 case CGE_DISTINCT: /* okay */
6204 if (cstring_equal (name, uentry_rawName (oe)))
6206 ; /* got a shadow error */
6211 (FLG_DISTINCTINTERNALNAMES,
6214 ("Internal identifier %q is not distinguishable from %q "
6215 "in the first %d characters (%q)",
6217 uentry_getName (oe),
6218 size_toInt (numchars),
6219 cstring_clip (uentry_getName (e), numchars)),
6221 uentry_whereLast (e)))
6223 uentry_showWhereAny (oe);
6224 uentry_setHasNameError (oe);
6231 if (numchars == 0 || (cstring_length (name) <= numchars))
6234 (FLG_DISTINCTINTERNALNAMES,
6236 ("Internal identifier %q is not distinguishable from %q "
6237 "without case sensitivity",
6239 uentry_getName (oe)),
6240 uentry_whereLast (e)))
6242 uentry_showWhereAny (oe);
6243 uentry_setHasNameError (oe);
6250 (FLG_DISTINCTINTERNALNAMES,
6252 ("Internal identifier %q is not distinguishable from %q "
6253 "in the first %d characters without case sensitivity",
6255 uentry_getName (oe),
6256 size_toInt (numchars)),
6257 uentry_whereLast (e)))
6259 uentry_showWhereAny (oe);
6260 uentry_setHasNameError (oe);
6268 || (cstring_length (name) <= numchars))
6271 (FLG_DISTINCTINTERNALNAMES,
6273 ("Internal identifier %q is not distinguishable from %q "
6274 "except by lookalike characters",
6276 uentry_getName (oe)),
6277 uentry_whereLast (e)))
6279 uentry_showWhereAny (oe);
6280 uentry_setHasNameError (oe);
6287 (FLG_DISTINCTINTERNALNAMES,
6289 ("Internal identifier %q is not distinguishable from %q "
6290 "in the first %d characters except by lookalike characters",
6292 uentry_getName (oe),
6293 size_toInt (numchars)),
6294 uentry_whereLast (e)))
6296 uentry_showWhereAny (oe);
6297 uentry_setHasNameError (oe);
6302 } end_usymtab_entries ;
6310 void usymtab_checkDistinctName (uentry e, int scope)
6311 /*@globals utab, globtab@*/
6313 bool hasError = FALSE;
6314 fileloc where = uentry_whereLast (e);
6316 if (!fileloc_isPreproc (where) && !fileloc_isBuiltin (where))
6318 if (scope == globScope)
6320 if (context_getFlag (FLG_DISTINCTEXTERNALNAMES))
6322 hasError = checkDistinctExternalName (e);
6326 if (!hasError && context_getFlag (FLG_DISTINCTINTERNALNAMES))
6328 hasError = checkDistinctInternalName (e);
6334 uentry_setHasNameError (e);
6338 /*@exposed@*/ sRef usymtab_lookupGlobalMarker (void) /*@globals utab@*/
6342 ue = usymtab_lookupAux (utab, GLOBAL_MARKER_NAME);
6343 llassert (uentry_isValid (ue));
6345 return uentry_getSref (ue);
6351 ** For debugging only
6355 usymtab_checkAllValid () /*@globals utab@*/
6359 while (tab != GLOBAL_ENV)
6363 for (i = 0; i < utab->nentries; i++)
6365 uentry e = utab->entries[i];
6367 uentry_checkValid (e);
6370 aliasTable_checkValid (tab->aliases);