2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2000 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 lclint: lclint-request@cs.virginia.edu
21 ** To report a bug: lclint-bug@cs.virginia.edu
22 ** For more information: http://lclint.cs.virginia.edu
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 "lclintMacros.nf"
51 # include "structNames.h"
52 # include "exprChecks.h"
53 # include "aliasChecks.h"
56 ** Keep track of type definitions inside a function.
59 static uentryList functypes = uentryList_undefined;
61 static bool dbgfree = FALSE;
62 static bool dbgload = TRUE;
64 /*@access ekind usymId@*/
67 ** Hack to prevent shadow errors from appearing when function parameters
68 ** are entered into a new scope.
71 static bool noshadowerror = FALSE;
74 ** Constraint: static variables can live in 1 or > 2.
76 ** except for tags. All tags must be at the global level.
77 ** Static tags are handled in a kludgey way.
81 ** utab is the universal symbol table
82 ** globtab is the global environment of utab
83 ** oldtab is needed for conversions in dumping (after sorting the table)
85 ** there can be only one usymtab!
88 static /*@checkedstrict@*/ /*@owned@*/ /*@notnull@*/ usymtab utab;
90 /* Reachable environments from from utab */
91 static /*@checkedstrict@*/ /*@notnull@*/ /*@dependent@*/ usymtab globtab;
92 static /*@checkedstrict@*/ /*@dependent@*/ usymtab filetab;
94 /* Used for sorting for dumpage. */
95 static /*@checkedstrict@*/ /*@owned@*/ usymtab oldtab;
97 static int usymtab_lexicalLevel (void) /*@globals utab@*/ ;
98 static bool usymtab_isProbableNullAltBranch (sRef p_s) /*@globals utab@*/ ;
99 static void refTable_free (/*@only@*/ /*@null@*/ refTable p_x, int p_nentries);
100 static ctype usymtab_suFieldsType (uentryList p_f, bool p_isStruct) /*@globals globtab@*/ ;
103 usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab p_u)
104 /*@globals globtab, utab, filetab@*/ /*@modifies p_u@*/ ;
106 static bool usymtab_isProbableNullAux (sRef p_s) /*@globals utab@*/ ;
107 static /*@only@*/ cstring usymtab_unparseStackTab (usymtab p_t);
108 static /*@exposed@*/ /*@dependent@*/ uentry
109 usymtab_getRefTab (/*@notnull@*/ usymtab p_u, int p_level, usymId p_index);
110 static /*@unused@*/ /*@only@*/ cstring
111 usymtab_unparseLocalAux (/*@notnull@*/ usymtab p_s);
112 static /*@unused@*/ /*@only@*/ cstring
113 usymtab_unparseLocalList (/*@notnull@*/ usymtab p_s);
114 static /*@only@*/ cstring usymtab_typeName (/*@notnull@*/ usymtab p_t);
115 static void usymtab_handleParams (void)
116 /*@globals utab, globtab, filetab@*/
117 /*@modifies utab@*/ ;
119 static /*@exposed@*/ /*@dependent@*/ uentry
120 usymtab_addRefEntry (/*@notnull@*/ usymtab p_s, cstring p_k);
121 static /*@exposed@*/ /*@dependent@*/ usymtab
122 usymtab_dropEnv (/*@notnull@*/ usymtab p_s);
123 static /*@exposed@*/ /*@dependent@*/ uentry
124 usymtab_getRefNoisy (/*@notnull@*/ usymtab p_s, int p_level, usymId p_index);
126 static /*@exposed@*/ /*@dependent@*/ uentry
127 usymtab_lookupQuiet (usymtab p_s, cstring p_k);
128 static void usymtab_printAllAux (usymtab p_s) /*@modifies g_msgstream@*/ ;
129 static int usymtab_getIndex (/*@notnull@*/ usymtab p_s, cstring p_k);
130 static /*@exposed@*/ uentry usymtab_fetchIndex (/*@notnull@*/ usymtab p_s, int p_i);
131 static /*@exposed@*/ uentry
132 usymtab_lookupAux (usymtab p_s, cstring p_k);
133 static /*@exposed@*/ /*@dependent@*/ /*@notnull@*/ usymtab
134 usymtab_getFileTab (void) /*@globals filetab@*/ ;
135 static int refTable_lookup (/*@notnull@*/ usymtab p_ut, int p_level, int p_index);
136 static bool usymtab_mustBreak (usymtab p_s);
137 static bool usymtab_mustEscape (usymtab p_s);
139 static void recordFunctionType (uentry ue)
141 llassert (uentry_isDatatype (ue) || uentry_isAnyTag (ue)
142 || uentry_isEnumConstant (ue));
145 functypes = uentryList_add (functypes, ue);
149 static void clearFunctionTypes (void)
150 /*@modifies globtab@*/
152 uentryList_elements (functypes, el)
154 if (cstring_isDefined (uentry_rawName (el)))
156 if (globtab->htable != NULL)
158 hashTable_remove (globtab->htable, uentry_rawName (el));
161 uentry_setName (el, cstring_undefined);
165 llassert (uentry_isValid (el));
166 el->sref = sRef_undefined;
167 /*@noaccess uentry@*/
168 } end_uentryList_elements ;
170 uentryList_clear (functypes);
173 static /*@falsenull@*/ bool usymtab_isBranch (usymtab u)
175 return (usymtab_isDefined (u) &&
176 (u->kind == US_TBRANCH || u->kind == US_FBRANCH
177 || u->kind == US_CBRANCH || u->kind == US_SWITCH));
180 static bool usymtab_mustBreak (usymtab s)
182 llassert (s != GLOBAL_ENV);
183 return (s->mustBreak);
186 static bool usymtab_mustEscape (usymtab s)
188 llassert (s != GLOBAL_ENV);
189 return (exitkind_mustEscape (s->exitCode));
192 void usymtab_setMustBreak ()
195 llassert (utab != GLOBAL_ENV);
196 utab->mustBreak = TRUE;
199 void usymtab_setExitCode (exitkind ex)
202 llassert (utab != GLOBAL_ENV);
206 if (exitkind_mustEscape (ex))
208 utab->mustBreak = TRUE;
212 bool usymtab_isAltProbablyDeepNull (sRef s)
214 return (sRef_deepPred (usymtab_isProbableNullAltBranch, s));
217 static bool usymtab_isProbableNullAltBranch (sRef s)
225 llassert (utab->env != NULL);
227 /*@-mods@*/ /* These modifications are cancelled. */
228 utab->guards = utab->env->guards;
229 utab->env->guards = t;
232 llassert (usymtab_isDefined (utab));
233 res = usymtab_isProbableNull (s);
236 ** This reports a spurious error. It is okay, because of
237 ** the nesting relationship of usymtab environments.
240 /*@-mods@*/ /* Cancelling modifications. */
241 /*@i1@*/ utab->env->guards = utab->guards;
242 /*@i1@*/ utab->guards = t;
248 static /*@notnull@*/ /*@special@*/ usymtab
249 usymtab_create (uskind kind, /*@keep@*/ usymtab env, bool nextlevel)
251 /*@post:isnull result->htable, result->guards, result->aliases@*/
253 usymtab t = (usymtab) dmalloc (sizeof (*t));
256 t->nspace = CBASESIZE;
257 t->entries = (uentry *) dmalloc (sizeof (*t->entries) * CBASESIZE);
258 t->reftable = (nextlevel
260 : (refentry *) dmalloc (sizeof (*t->reftable) * CBASESIZE));
263 t->lexlevel = (env == GLOBAL_ENV ? 0 : env->lexlevel) + (nextlevel ? 1 : 0);
268 t->guards = guardSet_undefined;
269 t->aliases = aliasTable_undefined;
271 t->mustBreak = FALSE;
272 t->exitCode = XK_NEVERESCAPE;
281 static /*@only@*/ /*@notnull@*/ usymtab
282 usymtab_createRoot (void) /*@modifies nothing@*/
284 usymtab u = (usymtab) dmalloc (sizeof (*u));
287 u->nspace = CGLOBBASESIZE;
288 u->entries = (uentry *) dmalloc (sizeof (*u->entries) * CGLOBBASESIZE);
291 u->htable = hashTable_create (CGLOBHASHSIZE);
294 u->guards = guardSet_new ();
295 u->aliases = aliasTable_new ();
297 u->mustBreak = FALSE;
298 u->exitCode = XK_NEVERESCAPE;
305 usymtab_initMod (void)
306 /*@globals undef utab, undef oldtab, undef globtab, undef filetab @*/
307 /*@modifies utab, globtab, filetab, oldtab @*/
309 utab = usymtab_createRoot ();
311 filetab = usymtab_undefined;
312 oldtab = usymtab_undefined;
316 ** utab should be empty? (requires?)
318 ** Adds bool types to symbol table (these are built in for now)
319 ** Only do this is there is no library!
325 if (context_getFlag (FLG_NOLIB))
327 ctype boolt = ctype_bool;
329 if (context_getFlag (FLG_ABSTRACTBOOL))
331 uentry boolentry = uentry_makeBoolDatatype (YES);
333 usymtab_supGlobalEntry (boolentry);
334 context_addBoolAccess ();
338 uentry boolentry = uentry_makeBoolDatatype (NO);
340 usymtab_supGlobalEntry (boolentry);
344 ** We supply values 0 and 1 for the constants, so things like
345 ** while (TRUE) can be interpreted correctly.
348 usymtab_supGlobalEntry
349 (uentry_makeConstantAux (context_getFalseName (), boolt,
350 fileloc_getBuiltin (), FALSE,
351 multiVal_makeInt (0)));
352 usymtab_supGlobalEntry
353 (uentry_makeConstantAux (context_getTrueName (), boolt,
354 fileloc_getBuiltin (), FALSE,
355 multiVal_makeInt (1)));
364 usymtab_grow (/*@notnull@*/ usymtab s)
367 o_uentry *oldsyms = s->entries;
369 s->nspace = CBASESIZE;
370 s->entries = (uentry *) dmalloc (sizeof (*s->entries)
371 * (s->nentries + s->nspace));
373 for (i = 0; i < s->nentries; i++)
375 s->entries[i] = oldsyms[i];
380 if (s->reftable != NULL)
382 refTable oldRefs = s->reftable;
384 s->reftable = (refentry *) dmalloc (sizeof (*s->reftable)
385 * (s->nentries + CBASESIZE + 1));
387 for (i = 0; i < s->nentries; i++)
389 s->reftable[i] = oldRefs[i];
400 usymtab_addEntryQuiet (/*@notnull@*/ usymtab s, /*@keep@*/ uentry e)
402 if (!(s->lexlevel > fileScope || !sRef_modInFunction ()))
404 if (uentry_isDatatype (e)
405 || uentry_isFunction (e)
406 || uentry_isAnyTag (e)
407 || uentry_isEnumConstant (e)
408 || context_inMacro ())
411 ** Not a bug. Code like,
412 ** int f (void) { typedef int tint; ... }
416 /* was nothing here! */
417 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
422 (cstring_makeLiteral ("Declaration outside function scope"));
424 llcontbug (message ("usymtab_addEntryQuiet: inconsistent state "
425 "(lexlevel = %d, modFunction = %s) adding: %q",
426 s->lexlevel, bool_unparse (sRef_modInFunction ()),
427 uentry_unparse (e)));
428 sRef_setGlobalScope ();
429 /* make sure the sRef is not bashed! */
430 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
440 s->entries[s->nentries] = e;
443 if (s == globtab || s == filetab)
445 if (!fileloc_isLib (g_currentloc))
447 uentry_tallyAnnots (e, AN_UNKNOWN);
452 if (s->htable != NULL)
454 hashTable_insert (s->htable, uentry_rawName (e), s->nentries);
460 static /*@observer@*/ uentry /*@alt void@*/
461 usymtab_addEntryBase (/*@notnull@*/ usymtab s, /*@only@*/ uentry e)
464 ** In theory, we shouldn't need this test because it this is
465 ** only called when a library is being read, and it shouldn't
466 ** ever have a duplicate entry. In practice, its safer to
467 ** leave it in, though.
472 if (uentry_isValid (old = usymtab_lookupQuiet (s, uentry_rawName (e))))
474 DPRINTF (("Duplicate entry: %s", uentry_unparse (e)));
475 uentry_free (e); /* duplicate */
480 int thisentry = s->nentries;
482 if (uentry_isVar (e))
484 uentry_setSref (e, sRef_makeCvar (globScope, thisentry,
485 uentry_getType (e)));
488 usymtab_addEntryQuiet (s, e);
494 usymtab_addEntryAux (/*@notnull@*/ usymtab st, /*@keep@*/ uentry e, bool isSref)
495 /*@globals globtab@*/
498 usymId thisentry = st->nentries;
500 llassert (!uentry_isElipsisMarker (e));
504 ** llassert (usymtab_lookupSafe (uentry_rawName (e)) == uentry_undefined);
507 llassertprint (uentry_isAnyTag (e) ? st == globtab : TRUE,
508 ("non-global tag: %s / %d", uentry_unparseFull (e), st->lexlevel));
510 if (st->lexlevel == fileScope
511 && (!(uentry_isStatic (e)) || uentry_isAnyTag (e)))
518 ctype ct = uentry_getType (e);
520 if (uentry_isFunction (e) && ctype_isFunction (ct))
522 ct = ctype_returnValue (ct);
525 if (uentry_isStatic (e))
527 sRef sr = sRef_makeCvar (st->lexlevel, thisentry, ct);
529 if (sRef_isStack (sr) || sRef_isLocalState (sr))
531 sRef_setAliasKind (sr, AK_STATIC, uentry_whereLast (e));
532 sRef_setDefined (sr, uentry_whereLast (e));
535 uentry_setSref (e, sr);
539 uentry_setSref (e, sRef_makeCvar (st->lexlevel, thisentry, ct));
544 if (uentry_isDatatype (e))
547 uentry_setDatatype (e, thisentry);
550 if (uentry_isFunction (e))
552 ctype ct = uentry_getType (e);
554 if (ctype_isFunction (ct)
555 && uentryList_isMissingParams (ctype_argsFunction (ct)))
557 if (uentry_isDeclared (e))
561 message ("Function %q declared without parameter list",
563 uentry_whereDeclared (e));
569 message ("Function %q specified without parameter list",
571 uentry_whereSpecified (e));
576 if (st == globtab && !uentry_isSpecified (e))
578 exprChecks_checkExport (e);
582 uentry_checkName (e);
584 usymtab_addEntryQuiet (st, e);
589 usymtab_addEntry (uentry e)
590 /*@globals utab, globtab@*/
591 /*@modifies utab, e@*/
594 llassertprint (!usymtab_exists (uentry_rawName (e)),
595 ("Entry already exists: %s", uentry_unparse (e)));
597 return usymtab_addEntryAux (utab, e, FALSE);
601 usymtab_addGlobalEntry (uentry e)
602 /*@modifies globtab, e@*/
604 DPRINTF (("Add global: %s / %s", uentry_unparse (e), bool_unparse (uentry_isForward (e))));
606 (void) usymtab_addEntryAux (globtab, e, FALSE);
610 ** supercede and replace entry use elements of entries array, and
611 ** assign an element to a new value, and then free the old value.
612 ** Need -deparrays to avoid errors for this.
618 usymtab_supEntryAux (/*@notnull@*/ usymtab st,
619 /*@only@*/ uentry e, bool isSref)
620 /*@globals globtab, filetab@*/
621 /*@modifies st, globtab, e@*/
623 cstring ename = uentry_rawName (e);
624 bool staticEntry = FALSE;
627 DPRINTF (("Sup entry aux: %s", uentry_unparseFull (e)));
629 /* static tags in global scope */
630 if (st->lexlevel == fileScope
631 && (!(uentry_isStatic (e)) || uentry_isAnyTag (e)))
633 eindex = usymtab_getIndex (st, ename);
635 if (eindex != NOT_FOUND)
637 uentry ce = st->entries[eindex];
641 message ("%s %q shadows static declaration",
642 ekind_capName (uentry_getKind (e)),
644 uentry_whereDeclared (e)))
646 uentry_showWhereLast (ce);
649 if (eindex == st->nentries - 1)
655 st->entries[eindex] = st->entries[st->nentries - 1];
658 if (st->htable != NULL)
660 hashTable_replaceKey (st->htable, uentry_rawName (ce),
671 if (uentry_isStatic (e)) {
672 if (uentry_isFunction (e)) {
673 /* Static function declarations are at the file level, even if they are in a deeped scope. */
674 st = usymtab_getFileTab ();
677 if (!uentry_isAnyTag (e) && st == globtab)
679 st = usymtab_getFileTab ();
681 DPRINTF (("Static entry!"));
686 DPRINTF (("Using symtab: %s", usymtab_unparseLocalAux (st)));
688 eindex = usymtab_getIndex (st, ename);
690 if (eindex != NOT_FOUND)
692 uentry ce = st->entries[eindex];
694 DPRINTF (("Found entry: %s", uentry_unparse (ce)));
696 if (uentry_isPriv (ce)
697 /* || (fileloc_isImport (uentry_whereSpecified (ce))) */
698 || (uentry_isStatic (ce)
699 && uentry_isAnyTag (ce)
700 && (uentry_isDeclared (ce)
701 && !fileloc_sameFile (uentry_whereDefined (ce),
702 uentry_whereDefined (e)))))
706 ** if overloading import should do some checks!
709 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
711 st->entries[eindex] = e;
713 if (uentry_isDatatype (e))
715 uentry_setDatatype (e, eindex);
718 if (st == globtab && !uentry_isSpecified (e))
720 exprChecks_checkExport (e);
723 if (st->htable != NULL)
725 hashTable_replaceKey (st->htable, uentry_rawName (ce),
732 else if (uentry_isSpecified (ce))
734 if (uentry_isSpecified (e))
736 if (fileloc_isImport (uentry_whereSpecified (ce)))
739 if (st->htable != NULL)
741 hashTable_replaceKey (st->htable,
747 st->entries[eindex] = e;
750 if (uentry_isDatatype (e)) uentry_setDatatype (e, eindex);
754 if (fileloc_isImport (uentry_whereSpecified (e)))
760 /* respecification errors already reported */
762 if (uentry_isDatatype (e))
764 uentry_setDatatype (e, eindex);
767 if (st->htable != NULL)
769 hashTable_replaceKey (st->htable,
774 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
776 st->entries[eindex] = e;
781 else /* e not specified */
783 if (uentry_isDeclared (ce))
785 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
786 uentry_mergeDefinition (ce, e);
790 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
791 uentry_mergeEntries (ce, e);
795 else /* ce not specified */
797 if (!(st->lexlevel > fileScope || !sRef_modInFunction ()))
799 if (uentry_isDatatype (e) || uentry_isAnyTag (e)
800 || uentry_isEnumConstant (e))
803 ** Not a bug. Code like,
804 ** int f (void) { typedef int tint; ... }
810 llcontbug (message ("usymtab_supEntryAux: inconsistent state "
811 "(lexlevel = %d, modFunction = %s) adding: %q",
812 st->lexlevel, bool_unparse (sRef_modInFunction ()),
813 uentry_unparse (e)));
815 if (sRef_modInFunction ())
817 /* make sure the sRef is not bashed! */
818 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
823 uentry_mergeDefinition (ce, e);
828 ctype ct = uentry_getType (ce);
830 if (uentry_isFunction (ce) && ctype_isFunction (ct))
832 ct = ctype_returnValue (ct);
835 uentry_setSref (ce, sRef_makeCvar (st->lexlevel, eindex, ct));
838 else /* no previous entry */
842 if (st->lexlevel == globScope
843 && !uentry_isStatic (e)
844 && !uentry_isExtern (e)
845 && usymtab_isDefined (filetab))
848 ** check if there is a static entry: (i.e.,
855 eindex = usymtab_getIndex (filetab, ename);
857 if (eindex != NOT_FOUND)
859 uentry ce = filetab->entries[eindex];
861 uentry_setStatic (e);
862 uentry_mergeDefinition (ce, e);
868 outer = usymtab_lookupQuiet (st->env, ename);
871 ** no previous definition, add the new one
875 && uentry_isValid (outer)
876 && !(uentry_isYield (e) || uentry_isYield (outer))
877 && fileloc_isDefined (uentry_whereLast (e))
878 && fileloc_isDefined (uentry_whereLast (outer)))
880 if (!uentry_sameKind (outer, e))
886 if (ctype_isUnknown (uentry_getType (outer))
887 || uentry_isForward (outer))
895 message ("%s %q shadows outer declaration",
896 ekind_capName (uentry_getKind (e)),
898 uentry_whereLast (e)))
900 uentry_showWhereLast (outer);
906 if (st == globtab && context_getFlag (FLG_NEWDECL))
910 message ("New declaration: %q", uentry_getName (e)),
911 uentry_whereLast (e));
914 eindex = usymtab_addEntryAux (st, e, isSref);
918 return (staticEntry ? USYMIDINVALID : eindex);
923 usymtab_replaceEntryAux (/*@notnull@*/ usymtab st, /*@only@*/ uentry e)
924 /*@globals globtab@*/ /*@modifies st, e@*/
926 cstring ename = uentry_rawName (e);
929 /* static tags in global scope */
930 eindex = usymtab_getIndex (st, ename);
932 if (eindex != NOT_FOUND)
934 uentry ce = st->entries[eindex];
936 if (st->htable != NULL)
938 hashTable_replaceKey (st->htable, uentry_rawName (ce), uentry_rawName (e));
942 st->entries[eindex] = e;
946 eindex = usymtab_addEntryAux (st, e, FALSE);
953 void usymtab_supEntry (uentry e)
954 /*@globals utab, filetab, globtab@*/
955 /*@modifies utab, globtab, e@*/
957 (void) usymtab_supEntryAux (utab, e, FALSE);
961 ** this should be lots more efficient!
964 static /*@exposed@*/ uentry
965 usymtab_supEntryReturnAux (/*@notnull@*/ usymtab tab,
966 /*@only@*/ uentry e, bool isref)
967 /*@globals globtab, filetab@*/
968 /*@modifies tab, globtab, e@*/
970 cstring rawName = cstring_copy (uentry_rawName (e));
971 bool stat = (tab == globtab) && uentry_isStatic (e);
975 (void) usymtab_supEntryAux (tab, e, isref);
979 ret = usymtab_lookupAux (filetab, rawName);
983 ret = usymtab_lookupAux (tab, rawName);
985 if (uentry_isInvalid (ret) && usymtab_isDefined (filetab))
987 ret = usymtab_lookupAux (filetab, rawName);
991 cstring_free (rawName);
995 /*@dependent@*/ /*@exposed@*/ uentry
996 usymtab_supEntryReturn (/*@only@*/ uentry e)
997 /*@globals utab, filetab, globtab@*/
998 /*@modifies utab, globtab, e@*/
1000 return (usymtab_supEntryReturnAux (utab, e, FALSE));
1003 /*@dependent@*/ /*@exposed@*/ uentry
1004 usymtab_supEntrySrefReturn (/*@only@*/ uentry e)
1005 /*@globals utab, globtab, filetab@*/
1006 /*@modifies utab, globtab, e@*/
1008 return (usymtab_supEntryReturnAux (utab, e, TRUE));
1011 /*@dependent@*/ /*@exposed@*/ uentry
1012 usymtab_supGlobalEntryReturn (uentry e)
1013 /*@globals globtab, filetab@*/
1014 /*@modifies globtab, e@*/
1018 ret = usymtab_supEntryReturnAux (globtab, e, FALSE);
1020 if (sRef_modInFunction ())
1022 recordFunctionType (ret);
1029 usymtab_supTypeEntry (/*@only@*/ uentry e)
1030 /*@globals globtab, filetab@*/
1031 /*@modifies globtab, e@*/
1036 if (uentry_isAbstractDatatype (e))
1038 uid = usymtab_supAbstractTypeEntry (e, FALSE);
1039 ret = ctype_createAbstract (uid);
1043 uid = usymtab_supEntryAux (globtab, e, FALSE);
1044 ret = ctype_createUser (uid);
1047 if (sRef_modInFunction ())
1049 recordFunctionType (globtab->entries[uid]);
1056 usymtab_supReturnTypeEntry (/*@only@*/ uentry e)
1057 /*@globals globtab, filetab@*/
1058 /*@modifies globtab@*/
1062 if (uentry_isAbstractDatatype (e))
1064 uid = usymtab_supAbstractTypeEntry (e, FALSE);
1068 uid = usymtab_supEntryAux (globtab, e, FALSE);
1071 if (sRef_modInFunction ())
1073 recordFunctionType (globtab->entries[uid]);
1076 return (globtab->entries[uid]);
1080 usymtab_supAbstractTypeEntry (/*@only@*/ uentry e, bool dodef)
1081 /*@globals globtab, filetab@*/
1082 /*@modifies globtab, e@*/
1086 uid = usymtab_supEntryAux (globtab, e, FALSE);
1090 uentry ue = usymtab_getTypeEntry (uid);
1092 uentry_setDatatype (ue, uid);
1095 if (context_getFlag (FLG_ACCESSMODULE))
1097 context_addFileAccessType (uid);
1100 if (sRef_modInFunction ())
1102 recordFunctionType (globtab->entries[uid]);
1110 usymtab_supExposedTypeEntry (/*@only@*/ uentry e, bool dodef)
1111 /*@globals globtab, filetab@*/
1112 /*@modifies globtab, e@*/
1116 uid = usymtab_supEntryAux (globtab, e, FALSE);
1120 uentry ue = usymtab_getTypeEntry (uid);
1122 uentry_setDatatype (ue, uid);
1125 if (sRef_modInFunction ())
1127 recordFunctionType (globtab->entries[uid]);
1135 usymtab_supForwardTypeEntry (/*@only@*/ uentry e)
1136 /*@globals globtab, filetab@*/
1137 /*@modifies globtab, e@*/
1139 usymId uid = usymtab_supEntryAux (globtab, e, FALSE);
1140 uentry ue = usymtab_getTypeEntry (uid);
1142 uentry_setDatatype (ue, uid);
1144 if (sRef_modInFunction ())
1146 recordFunctionType (globtab->entries[uid]);
1149 return (uentry_getAbstractType (ue));
1153 usymtab_supEntrySref (uentry e)
1154 /*@globals utab, globtab, filetab@*/
1155 /*@modifies utab, globtab, e@*/
1157 sRef old = uentry_getSref (e);
1160 if (sRef_isType (old))
1162 uentry ue = usymtab_supEntryReturnAux (utab, e, TRUE);
1165 if (uentry_isValid (ue))
1167 sRef uref = uentry_getSref (ue);
1169 sRef_mergeStateQuiet (uref, old);
1170 sRef_clearDerived (uref);
1172 /*@noaccess uentry@*/
1174 else if (sRef_isKnown (old))
1176 usymtab_supEntry (e);
1180 (void) usymtab_supEntryAux (utab, e, TRUE);
1184 void usymtab_supGlobalEntry (/*@only@*/ uentry e)
1185 /*@globals globtab, filetab@*/
1186 /*@modifies globtab, filetab, e@*/
1190 DPRINTF (("Sup global entry: %s", uentry_unparse (e)));
1192 uid = usymtab_supEntryAux (globtab, e, FALSE);
1194 if (sRef_modInFunction ())
1196 recordFunctionType (globtab->entries[uid]);
1201 usymtab_supReturnFileEntry (/*@only@*/ uentry e)
1202 /*@globals filetab, globtab@*/
1203 /*@modifies filetab, globtab, e@*/
1205 llassert (filetab != usymtab_undefined);
1206 DPRINTF (("File entry: %s", uentry_unparse (e)));
1207 return (usymtab_supEntryReturnAux (filetab, e, FALSE));
1215 usymtab_inDeepScope () /*@globals utab@*/
1217 return (utab->lexlevel > paramsScope);
1221 usymtab_getIndex (/*@notnull@*/ usymtab s, cstring k)
1225 if (s->htable != NULL)
1227 i = hashTable_lookup (s->htable, k);
1233 for (i = 0; i < s->nentries; i++)
1235 uentry current = s->entries[i];
1237 if (!uentry_isUndefined (current)
1238 && cstring_equal (uentry_rawName (current), k))
1249 usymtab_fetchIndex (/*@notnull@*/ usymtab s, int i)
1251 llassert (i >= 0 && i < s->nentries);
1252 return (s->entries[i]);
1256 usymtab_getTypeId (cstring k) /*@globals globtab@*/
1258 usymId uid = usymtab_getIndex (globtab, k);
1260 if (uid == NOT_FOUND) return USYMIDINVALID;
1261 if (!(uentry_isDatatype (usymtab_getTypeEntry (uid)))) return USYMIDINVALID;
1266 /*@dependent@*/ uentry
1267 usymtab_lookupStructTag (cstring k)
1269 cstring sname = makeStruct (k);
1270 uentry ue = usymtab_lookupGlob (sname);
1271 cstring_free (sname);
1275 /*@dependent@*/ uentry
1276 usymtab_lookupUnionTag (cstring k)
1278 cstring uname = makeUnion (k);
1279 uentry res = usymtab_lookupGlob (uname);
1281 cstring_free (uname);
1285 /*@dependent@*/ uentry
1286 usymtab_lookupEnumTag (cstring k)
1288 cstring ename = makeEnum (k);
1289 uentry res = usymtab_lookupGlob (ename);
1291 cstring_free (ename);
1296 usymtab_getId (cstring k) /*@globals globtab@*/
1298 usymId uid = usymtab_getIndex (globtab, k);
1301 if (uid == NOT_FOUND)
1303 return USYMIDINVALID;
1306 ue = usymtab_getGlobalEntry (uid);
1308 if (uentry_isPriv (ue))
1310 return USYMIDINVALID;
1316 static /*@exposed@*/ uentry
1317 usymtab_getEntryAux (/*@notnull@*/ usymtab s, usymId uid)
1319 llassert (uid != USYMIDINVALID);
1321 if (uid < 0 || uid >= s->nentries)
1323 llcontbug (message ("usymtab_getEntry: out of range: level = %d [%d]",
1325 return uentry_undefined;
1328 llassertprint (uentry_isValid (s->entries[uid]),
1329 ("entry undefined: %d", uid));
1331 return s->entries[uid];
1334 /*@dependent@*/ /*@observer@*/ uentry
1335 usymtab_getGlobalEntry (usymId uid)
1336 /*@globals utab, globtab@*/
1338 if (dbgfree) return (uentry_undefined);
1340 if (utab->lexlevel > paramsScope)
1342 /* need to do this the awkward way, since it could be in conditional scope */
1343 return (usymtab_lookupSafe (uentry_rawName (globtab->entries[uid])));
1347 return (globtab->entries[uid]);
1351 /*@dependent@*/ /*@exposed@*/ uentry
1352 usymtab_getTypeEntry (usymId uid)
1353 /*@globals globtab@*/
1357 if (uid >= 0 && uid < globtab->nentries)
1359 return (globtab->entries[uid]);
1363 return (uentry_undefined);
1368 llassert (uid >= 0 && uid < globtab->nentries);
1370 return (globtab->entries[uid]);
1378 /*@dependent@*/ /*@exposed@*/ uentry
1379 usymtab_getTypeEntrySafe (usymId uid)
1380 /*@globals globtab@*/
1382 if (uid < 0 || uid >= globtab->nentries)
1384 return uentry_undefined;
1387 return (globtab->entries[uid]);
1391 usymtab_isBoolType (usymId uid)
1392 /*@globals globtab@*/
1394 llassert (uid >= 0 && uid < globtab->nentries);
1396 return (cstring_equal (uentry_rawName (globtab->entries[uid]),
1397 context_getBoolName ()));
1401 usymtab_getTypeEntryName (usymId uid)
1402 /*@globals globtab@*/
1408 return (cstring_makeLiteral ("<freetype>"));
1411 ue = usymtab_getTypeEntry (uid);
1413 if (dbgload && !uentry_isValid (ue))
1415 return (message ("<missing type: %d>", uid));
1418 llassertprint (uentry_isValid (ue), ("type undefined: %d", uid));
1420 return (uentry_getName (ue));
1424 usymtab_rehash (/*@notnull@*/ usymtab s)
1428 if (s->htable != NULL)
1430 hashTable_free (s->htable);
1433 s->htable = hashTable_create (LLHASHSIZE);
1435 for (i = 0; i < s->nentries; i++)
1437 hashTable_insert (s->htable, uentry_rawName (s->entries[i]), i);
1442 ** superficial copy of usymtab
1444 ** DO copy spec entries
1447 static /*@only@*/ /*@notnull@*/ usymtab
1448 usymtab_shallowCopy (/*@notnull@*/ usymtab s) /*@*/
1450 usymtab copytab = usymtab_createRoot ();
1453 for (i = 0; i < s->nentries; i++)
1455 usymtab_addEntryBase (copytab, s->entries[i]);
1462 usymtab_shallowFree (/*@only@*/ /*@notnull@*/ usymtab s)
1464 aliasTable_free (s->aliases);
1465 refTable_free (s->reftable, s->nentries);
1467 /*@-compdestroy@*/ sfree (s); /*@=compdestroy@*/
1471 ** converts usymId from old table to sorted one
1475 usymtab_convertId (usymId uid)
1476 /*@globals oldtab, utab@*/
1482 llassert (usymtab_isDefined (oldtab));
1484 ue = usymtab_getEntryAux (oldtab, uid);
1486 llassertprint (uentry_isValid (ue), ("convertId: undefined: %d", uid));
1488 name = uentry_rawName (ue);
1490 ret = usymtab_getIndex (utab, name);
1492 llassertprint (ret != USYMIDINVALID, ("convertId: return is invalid"));
1498 usymtab_prepareDump (void)
1499 /*@globals oldtab, utab@*/
1500 /*@modifies oldtab, utab@*/
1502 llassert (usymtab_inGlobalScope ());
1504 llassert (oldtab == usymtab_undefined);
1506 oldtab = usymtab_shallowCopy (utab);
1509 alpha compare - make sure order is same on different platforms
1510 error messages appear in same order
1513 qsort (utab->entries, (size_t)utab->nentries,
1514 sizeof (*utab->entries), (int (*)(const void *, const void *)) uentry_xcomparealpha);
1516 usymtab_rehash (utab);
1520 usymtab_dump (FILE *fout)
1521 /*@globals utab, oldtab@*/
1524 bool neednl = FALSE;
1525 uentry lastentry = uentry_undefined;
1526 ekind lastekind = KINVALID;
1530 ** must call prepareDump first
1533 llassert (oldtab != usymtab_undefined);
1535 for (i = 0; i < utab->nentries; i++)
1537 uentry thisentry = utab->entries[i];
1538 ekind thisekind = uentry_getKind (thisentry);
1541 if (uentry_hasRealName (thisentry)) {
1542 if (thisekind != lastekind)
1546 check (fputc ('\n', fout) == (int) '\n');
1550 lastentry = uentry_undefined;
1551 fprintf (fout, "*%d (%s)\n", ekind_toInt (thisekind),
1552 cstring_toCharsSafe (ekind_capName (thisekind)));
1553 lastekind = thisekind;
1557 if (uentry_isInvalid (lastentry) || !uentry_equiv (lastentry, thisentry)
1558 || (linelen > (MAX_DUMP_LINE_LENGTH - (2 * MAX_NAME_LENGTH))))
1560 cstring cdump = uentry_dump (thisentry);
1562 lastentry = thisentry;
1565 check (fputc ('\n', fout) == (int) '\n');
1569 linelen += cstring_length (cdump);
1571 /* no new line here! */
1572 if (cstring_length (cdump) > 0)
1574 check (fputs (cstring_toCharsSafe (cdump), fout) != EOF);
1577 cstring_free (cdump);
1582 cstring cdump = uentry_rawName (thisentry);
1583 linelen += cstring_length (cdump);
1584 fprintf (fout, "#%s", cstring_toCharsSafe (cdump));
1591 check (fputc ('\n', fout) == (int) '\n');
1595 void usymtab_load (FILE *f)
1596 /*@globals utab, globtab@*/
1597 /*@modifies utab, *f@*/
1599 char *s = mstring_create (MAX_DUMP_LINE_LENGTH);
1601 ekind kind = KINVALID;
1602 fileloc loc = g_currentloc;
1608 llassert (utab == globtab);
1609 llassert (utab->nentries == 0);
1611 while (fgets (s, MAX_DUMP_LINE_LENGTH, f) != NULL
1614 ; /* ignore ;-comments */
1617 while (s != NULL && *s != ';')
1623 kind = ekind_fromInt (getInt (&s));
1631 (cstring_makeLiteral
1632 ("Library is in obsolete format. Use lclint +whichlib "
1633 "to see which library is being loaded."));
1636 ue = uentry_undump (kind, loc, &s);
1637 DPRINTF (("Load: %s", uentry_unparseFull (ue)));
1639 if (uentry_isValid (ue))
1641 ue = usymtab_addEntryBase (utab, ue);
1647 ** now, any other names are the same uentry
1650 while (*(s++) == '#')
1652 cstring name = cstring_fromCharsO (getWord (&s));
1653 uentry nue = uentry_nameCopy (name, ue);
1655 DPRINTF (("Name copy: %s", uentry_unparseFull (nue)));
1656 usymtab_addEntryBase (utab, nue);
1659 while ((c = *s) != '\0' && (c !='\n'))
1661 if (c != ' ' || c != '\t')
1663 llbuglit ("Junk in load file");
1670 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
1678 ** file scope for static variables
1682 usymtab_enterFile ()
1683 /*@globals utab, globtab, filetab@*/
1684 /*@modifies filetab@*/
1686 llassert (utab == globtab);
1691 usymtab_entries (globtab, ue)
1693 if (sRef_hasDerived (uentry_getSref (ue)))
1695 fprintf (g_msgstream, "Derived Global: %s\n", uentry_unparse (ue));
1696 fprintf (g_msgstream, "sRef: %s\n", sRef_unparseFull (ue->sref));
1698 } end_usymtab_entries ;
1702 usymtab_enterScope ();
1708 /*@globals utab, filetab@*/
1709 /*@modifies filetab, utab@*/
1712 llassert (utab->lexlevel == 1);
1714 usymtab_exitScope (exprNode_undefined);
1719 usymtab_enterScope ()
1720 /*@globals utab, globtab, filetab@*/
1723 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
1725 /* unconditional scope: optimize to avoid copy */
1726 t->aliases = aliasTable_copy (utab->aliases);
1729 llassert (usymtab_isDefined (t->env));
1731 if (t->env->lexlevel == paramsScope && context_inFunctionLike ())
1733 noshadowerror = TRUE;
1734 usymtab_handleParams ();
1735 noshadowerror = FALSE;
1740 ** setup external references:
1741 ** o only, unique params alias external args
1742 ** o other params may alias anything of their type
1746 usymtab_handleParams (void)
1747 /*@globals utab, globtab, filetab@*/
1748 /*@modifies utab, globtab@*/
1750 usymtab ptab = utab->env;
1751 uentry fcn = context_getHeader ();
1754 usymtab_entries (ptab, param)
1758 if (!uentry_isYield (param))
1761 sRef pref = uentry_getSref (param);
1763 llassertprint (uentry_isAnyParam (param),
1765 uentry_unparseFull (param)));
1768 ue = uentry_makeVariable (fixParamName (uentry_rawName (param)),
1769 uentry_getType (param),
1770 fileloc_copy (uentry_whereDeclared (param)),
1773 uentry_copyState (ue, param);
1774 uentry_setRefParam (ue);
1776 ue = usymtab_supEntrySrefReturn (ue);
1778 /* must be after supercede! */
1780 if (!sRef_stateKnown (pref))
1782 uentry_setDefState (ue, SS_DEFINED);
1783 uentry_setDefState (param, SS_DEFINED);
1787 if (sRef_isStateSpecial (pref))
1789 uentry_setDefState (ue, SS_ALLOCATED);
1793 uentry_setDefState (ue, sRef_getDefState (pref));
1797 uref = uentry_getSref (ue);
1799 if (sRef_isStack (uref))
1801 alkind pkind = sRef_getAliasKind (pref);
1803 if (alkind_isKnown (pkind) && !alkind_isLocal (pkind)
1804 && !alkind_isStack (pkind))
1806 sRef_setAliasKind (uref, pkind, fileloc_undefined);
1807 sRef_setOrigAliasKind (uref, pkind);
1811 sRef_setAliasKind (uref, AK_IMPTEMP, fileloc_undefined);
1812 sRef_setOrigAliasKind (uref, AK_IMPTEMP);
1814 if (uentry_isOut (param))
1820 sRef_setDefined (uref, fileloc_undefined);
1826 usymtab_addMustAlias (uref, pref);
1828 if (!(uentry_isOnly (param) || uentry_isUnique (param)))
1830 sRef s = sRef_makeExternal (uref);
1832 usymtab_addMustAlias (uref, s);
1835 if (sRef_isKillRef (pref))
1837 sRef_setAliasKind (uref, AK_NEWREF, fileloc_undefined);
1838 sRef_setOrigAliasKind (uref, AK_KILLREF);
1840 else if (sRef_isRefCounted (uref))
1842 sRef_setOrigAliasKind (uref, AK_REFCOUNTED);
1847 sRef_setOrigAliasKind (uref, AK_LOCAL);
1853 } end_usymtab_entries;
1856 if (uentry_hasSpecialClauses (fcn))
1858 specialClauses clauses = uentry_getSpecialClauses (fcn);
1860 specialClauses_preElements (clauses, cl)
1862 sRefSet refs = specialClause_getRefs (cl);
1863 sRefMod modf = specialClause_getEntryFunction (cl);
1866 sRefSet_elements (refs, el)
1868 sRef base = sRef_getRootBase (el);
1870 if (sRef_isResult (base))
1872 ; /* nothing to do before */
1874 else if (sRef_isParam (base))
1878 sRef sb = sRef_updateSref (el);
1879 sRefSet aliases = usymtab_allAliases (sb);
1881 modf (sb, fileloc_undefined);
1883 sRefSet_elements (aliases, sr)
1885 modf (sr, fileloc_undefined);
1886 } end_sRefSet_elements ;
1888 sRefSet_free (aliases);
1893 if (sRef_isValid (base))
1898 } end_sRefSet_elements ;
1899 } end_specialClauses_preElements ;
1904 usymtab_enterFunctionScope (uentry fcn)
1905 /*@globals utab, filetab, globtab@*/
1908 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
1910 if (utab->lexlevel != fileScope)
1912 if (utab->lexlevel > fileScope)
1914 llparseerror (cstring_makeLiteral ("New function scope inside function."));
1916 while (utab->lexlevel > fileScope)
1918 /*@i@*/ utab = usymtab_dropEnv (utab);
1925 llfatalbug (cstring_makeLiteral ("New function not inside file."));
1927 /*@-branchstate@*/ } /*@=branchstate@*/
1929 globSet_allElements (uentry_getGlobs (fcn), el)
1932 if (sRef_isUndefGlob (el))
1934 int index = sRef_getScopeIndex (el);
1935 sRef sr = sRef_updateSref (el);
1936 fileloc loc = uentry_whereEarliest (fcn);
1938 if (sRef_isFileStatic (el))
1940 ctype ct = sRef_getType (el);
1943 llassert (usymtab_isDefined (filetab));
1945 ue = usymtab_fetchIndex (filetab, index);
1947 if (ctype_isRealArray (ct) || ctype_isRealSU (ct))
1949 sRef_setAllocated (sr, loc);
1953 sRef_setUndefined (sr, loc);
1958 uentry ue = globtab->entries[index];
1959 ctype ct = uentry_getType (ue);
1961 if (ctype_isArray (ct) || ctype_isSU (ct))
1963 sRef_setAllocated (sr, loc);
1967 sRef_setUndefined (sr, loc);
1971 else if (sRef_isAllocated (el))
1973 sRef sr = sRef_updateSref (el);
1974 fileloc loc = uentry_whereEarliest (fcn);
1976 sRef_setAllocated (sr, loc);
1978 else if (sRef_isPartial (el))
1980 sRef sr = sRef_updateSref (el);
1981 fileloc loc = uentry_whereEarliest (fcn);
1983 sRef_setPartial (sr, loc);
1989 } end_globSet_allElements;
1995 usymtab_caseBranch (void)
1998 usymtab t = usymtab_create (US_CBRANCH, utab, FALSE);
2003 usymtab_switchBranch (/*@unused@*/ exprNode s)
2006 usymtab t = usymtab_create (US_SWITCH, utab, FALSE);
2008 t->aliases = aliasTable_copy (utab->aliases);
2013 usymtab_trueBranch (/*@only@*/ guardSet guards)
2016 usymtab t = usymtab_create (US_TBRANCH, utab, FALSE);
2019 ** not true! (could be in a macro)
2021 ** llassertprint (utab->lexlevel > paramsScope,
2022 ** ("not in scope: %s", usymtab_unparseLocal ()));
2026 guardSet_free (t->guards);
2029 aliasTable_free (t->aliases);
2030 t->aliases = aliasTable_copy (utab->aliases);
2038 ** { int a; if (...) a = 3; < a may be undefined here!
2043 usymtab_popTrueBranch (exprNode pred, exprNode expr, clause cl)
2046 ** add a false branch
2047 ** (could be done more efficiently as a special case, but
2048 ** it is better to only maintain one version of the code)
2051 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2052 usymtab_popBranches (pred, expr, exprNode_undefined, TRUE, cl);
2056 usymtab_popCaseBranch () /*@modifies utab@*/
2058 llassert (utab->kind == US_CBRANCH);
2059 usymtab_quietPlainExitScope ();
2063 usymtab_popTrueExecBranch (exprNode pred, exprNode expr, clause cl)
2066 ** add a false branch that must return --- that is,
2067 ** the true branch is always executed!
2070 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2071 usymtab_popBranches (pred, expr, exprNode_makeMustExit (), FALSE, cl);
2075 usymtab_popOrBranch (exprNode pred, exprNode expr)
2079 usymtab env = utab->env;
2080 usymtab otab = utab;
2083 llassert (env != NULL);
2085 if (exprNode_isError (expr))
2091 mustReturn = exprNode_mustEscape (expr);
2095 llassert (utab->kind == US_TBRANCH);
2098 ** merge each entry in table with its original
2099 ** unless execution cannot continue after this branch
2102 for (i = 0; i < utab->nentries; i++)
2104 uentry current = utab->entries[i];
2105 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2107 uentry_mergeState (old, current, exprNode_loc (expr),
2108 mustReturn, FALSE, TRUE, ORCLAUSE);
2114 env->guards = guardSet_levelUnionFree (env->guards,
2115 guardSet_invert (exprNode_getGuards (pred)),
2120 env->aliases = aliasTable_levelUnion (env->aliases, otab->aliases, env->lexlevel);
2123 /* env is now utab */
2124 usymtab_quietPlainExitScope ();
2128 ** case syntax in C is very unrestricted. This is unfortunate.
2130 ** A switch case is ended either by a new case or default, or
2131 ** a close } that may close the switch or some other control
2136 usymtab_newCase (/*@unused@*/ exprNode pred, exprNode last)
2139 bool mustBreak = usymtab_mustBreak (utab);
2140 bool mustReturn = usymtab_mustEscape (utab);
2141 usymtab stab = utab;
2144 ** Find last case (or outer switch)
2147 while (stab->kind != US_CBRANCH && stab->kind != US_SWITCH)
2150 llassert (stab != GLOBAL_ENV);
2155 while (stab->kind == US_CBRANCH)
2158 llassert (stab != GLOBAL_ENV);
2162 ** if its a fall through case, merge in outside entries and last case.
2167 ** case 1: x = 3; <fall through>
2168 ** case 2: << x may not be defined
2172 if (!mustBreak && !mustReturn && utab->kind == US_CBRANCH)
2174 llassert (stab->kind == US_SWITCH || stab->kind == US_NORMAL);
2176 usymtab_entries (utab, ue) /* but, keep track of used variables */
2178 uentry old = usymtab_lookupAux (stab, uentry_rawName (ue));
2180 llassert (uentry_isValid (old));
2182 /* modifies ue, not old */
2184 uentry_mergeState (ue, old, exprNode_loc (last),
2185 FALSE, FALSE, TRUE, CASECLAUSE);
2186 } end_usymtab_entries;
2188 utab->aliases = aliasTable_levelUnion (utab->aliases,
2189 stab->aliases, utab->lexlevel);
2192 ** No need for a new branch.
2199 usymtab_caseBranch ();
2200 /*@-mustfree@*/ /*< utab->aliases >*/
2201 utab->aliases = aliasTable_copy (stab->aliases);
2209 ** for && (both pred and expr are executed)
2213 usymtab_popAndBranch (exprNode pred, /*@unused@*/ exprNode expr)
2216 usymtab env = utab->env;
2220 llassert (utab->kind == US_TBRANCH);
2223 ** merge each entry in table with its original
2224 ** unless execution cannot continue after this branch
2227 for (i = 0; i < utab->nentries; i++)
2229 uentry current = utab->entries[i];
2230 sRef tref = uentry_getSref (current);
2231 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2232 sRef oref = uentry_getSref (old);
2234 /* note that is current is in a nested branch,
2235 it may create a "new" old entry. */
2237 llassert (uentry_isValid (old));
2238 uentry_mergeState (old, current, exprNode_loc (expr),
2239 FALSE, FALSE, TRUE, ANDCLAUSE);
2242 ** if is it defined by the second clause, then it should be defined.
2245 if (sRef_isAnyDefined (tref)
2246 && (sRef_isAllocated (oref) || sRef_isStateUndefined (oref)))
2248 sRef_setDefined (oref, g_currentloc);
2252 utab->guards = guardSet_levelUnionFree (utab->guards,
2253 guardSet_invert (exprNode_getGuards (pred)),
2255 utab->aliases = aliasTable_levelUnion (utab->aliases, otab->aliases, utab->lexlevel);
2257 usymtab_quietPlainExitScope ();
2262 ** Stack should be [ US_CBRANCH+ US_SWITCH ]
2263 ** Only branches which do not return (except possibly the last branch) are included.
2265 ** Conditionally merge state from all CBRANCHes.
2267 ** If allpaths is TRUE, then all possible executions go through some switch
2268 ** case, and the original scope is not merged.
2272 usymtab_exitSwitch (/*@unused@*/ exprNode sw, bool allpaths)
2275 usymtab ttab = utab;
2276 usymtab stab = ttab;
2277 usymtab ltab = ttab;
2278 bool lastMustReturn = usymtab_mustEscape (utab);
2282 while (stab->kind == US_CBRANCH)
2285 llassert (stab != GLOBAL_ENV);
2288 while (stab->kind == US_NORMAL)
2291 llassert (stab != GLOBAL_ENV);
2294 llassert (stab->kind == US_SWITCH);
2296 /* go to the scope outside the switch (US_SWITCH is just a marker! */
2298 llassert (stab != GLOBAL_ENV);
2302 llassert (usymtab_isDefined (ttab));
2304 if (ttab->kind == US_CBRANCH)
2306 /* was quietPlainExitScope --- but, can't free it yet! */
2308 llassert (utab != GLOBAL_ENV);
2310 while (ttab->kind == US_CBRANCH)
2313 ** (from popTrueBranch)
2316 bool mustReturn = usymtab_mustEscape (ttab);
2317 bool mustBreak = usymtab_mustBreak (ttab);
2319 usymtab_entries (ttab, current)
2321 uentry old = /*@-compmempass@*/ usymtab_lookupAux (ltab, uentry_rawName (current));
2325 ** note that is this is in a nested branch,
2326 ** it may create a "new" old entry.
2329 if (uentry_isValid (old))
2333 uentry_mergeUses (current, old);
2334 uentry_setState (old, current);
2338 uentry_mergeState (old, current, exprNode_loc (sw),
2339 mustReturn, FALSE, TRUE, SWITCHCLAUSE);
2346 } end_usymtab_entries;
2349 ** if entry is not in symbol table for this case, merge with pre-switch
2353 if (!mustReturn && !mustBreak)
2355 usymtab_entries (stab, current)
2357 if (usymtab_getIndex (ttab, uentry_rawName (current)) == NOT_FOUND)
2359 uentry old = /*@-compmempass@*/
2360 usymtab_lookupAux (ltab, uentry_rawName (current));
2363 llassert (uentry_isValid (old));
2364 uentry_mergeState (old, current, exprNode_loc (sw),
2365 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2367 } end_usymtab_entries;
2370 ltab->env = ttab->env;
2374 ** Suprious error, becuase of environments.
2377 /*@i1@*/ utab = ltab;
2379 lastMustReturn = FALSE;
2386 ** now, there is one US_CBRANCH. Merge this with the stab.
2390 for (i = 0; i < ltab->nentries; i++)
2392 uentry current = ltab->entries[i];
2393 uentry old = usymtab_lookupAux (stab, uentry_rawName (current));
2395 /* note that is this is in a nested branch,
2396 it may create a "new" old entry. */
2399 if (uentry_isValid (old))
2403 uentry_mergeUses (current, old);
2404 uentry_setState (old, current);
2408 uentry_mergeState (old, current, exprNode_loc (sw),
2409 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2423 ** switch may or may not be followed by a new scope
2426 if (utab->kind == US_SWITCH)
2428 usymtab_quietPlainExitScope ();
2432 usymtab_quietPlainExitScope ();
2433 llassert (utab->kind == US_SWITCH);
2434 usymtab_quietPlainExitScope ();
2440 updateNullState (sRef el, /*@notnull@*/ usymtab ttab,
2441 /*@notnull@*/ usymtab ftab, bool trueGuard)
2443 sRef base = sRef_getRootBase (el);
2444 int level = sRef_lexLevel (base);
2448 if (sRef_isCvar (base))
2450 usymId index = sRef_getScopeIndex (base);
2451 uentry ue = usymtab_getRefTab (ttab, level, index);
2453 if (!uentry_isLset (ue))
2455 sRef sr = uentry_getSref (ue);
2459 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2463 if (!guardSet_isGuarded (ttab->guards, el)
2464 && !sRef_isNotNull (sr))
2466 sRef_setDerivNullState (sr, el, NS_DEFNULL);
2474 ue = usymtab_getRefTab (ftab, level, index);
2476 if (!uentry_isLset (ue))
2478 sRef sr = uentry_getSref (ue);
2481 if (!trueGuard) /* yikes! forgot the ! */
2483 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2488 if (!guardSet_isGuarded (ftab->guards, el)
2489 && !sRef_isNotNull (sr))
2491 sRef_setDerivNullState (sr, el, NS_DEFNULL);
2504 usymtab_popBranches (exprNode pred, exprNode tbranch, exprNode fbranch,
2505 bool isOpt, clause cl)
2509 usymtab ftab = utab;
2510 usymtab ttab = utab->env;
2514 guardSet guards = exprNode_getGuards (pred);
2515 sRefSet tguards = guardSet_getTrueGuards (guards);
2516 sRefSet fguards = guardSet_getFalseGuards (guards);
2517 bool mustReturnT = exprNode_mustEscape (tbranch);
2518 bool mustReturnF = exprNode_mustEscape (fbranch);
2520 if (exprNode_isDefined (fbranch))
2522 loc = exprNode_loc (fbranch);
2526 loc = exprNode_loc (tbranch);
2529 llassert (usymtab_isDefined (ttab));
2533 llassert (usymtab_isDefined (env));
2534 llassert (ftab->kind == US_FBRANCH);
2535 llassert (ttab->kind == US_TBRANCH);
2538 ** For each element that is true guarded (i.e., if (x != NULL))
2539 ** make x = null in false branch,
2540 ** and x = notnull in true branch.
2541 ** unless x was set locally in that branch.
2542 ** For each element that is false guarded (x == NULL)
2543 ** make x = null in true, notnull in false.
2545 ** For each element that is either guarded (pred(x))
2549 sRefSet_allElements (tguards, el)
2551 updateNullState (el, ttab, ftab, TRUE);
2552 } end_sRefSet_allElements;
2554 sRefSet_allElements (fguards, el)
2556 updateNullState (el, ttab, ftab, FALSE);
2557 } end_sRefSet_allElements;
2561 ** if an entry is in both true and false, merge the entries,
2562 ** then replace original with new state.
2564 ** if an entry is in one table, merge it with the original.
2567 for (i = 0; i < ftab->nentries; i++)
2569 uentry fthis = ftab->entries[i];
2570 uentry old = usymtab_lookupAux (env, uentry_rawName (fthis));
2571 int tindex = usymtab_getIndex (ttab, uentry_rawName (fthis));
2573 if (uentry_isUndefined (old))
2575 /* possible entry was added as an undefined id */
2579 if (tindex != NOT_FOUND)
2581 uentry tthis = ttab->entries[tindex];
2583 /* note that is this is in a nested branch,
2584 it may create a "new" old entry. */
2591 uentry_mergeState (fthis, tthis, loc,
2592 mustReturnT, FALSE, FALSE, cl);
2596 uentry_mergeUses (fthis, tthis);
2599 uentry_setState (old, fthis);
2606 uentry_setState (old, tthis);
2607 uentry_mergeState (old, fthis, loc, mustReturnF,
2611 ttab->entries[tindex] = uentry_undefined;
2612 uentry_free (tthis);
2616 uentry_mergeState (old, fthis, loc, mustReturnF, TRUE, FALSE, cl);
2620 for (i = 0; i < ttab->nentries; i++)
2622 uentry current = ttab->entries[i];
2624 if (!uentry_isUndefined (current))
2626 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2628 llassertprint (!uentry_isUndefined (old), ("name: <%s>",
2629 uentry_rawName (current)));
2632 uentry_mergeUses (current, old);
2633 uentry_setState (old, current);
2638 ** assumes false branch is a fall-through if
2639 ** fbranch is not defined. This is true, unless
2640 ** where was some greivous error in processing
2641 ** the else branch of an if-then, in which case
2642 ** this is probably the right thing to do anyway.
2645 uentry_mergeState (old, current, loc, mustReturnT,
2653 ** Plain levelUnion doesn't work, since we need to use the sRef's in env->aliases
2654 ** if they are present.
2657 llassert (NOALIAS (env->aliases, ttab->aliases));
2658 llassert (NOALIAS (env->aliases, ftab->aliases));
2660 aliasTable_free (env->aliases);
2662 env->aliases = aliasTable_levelUnionNew (ttab->aliases,
2663 ftab->aliases, env->lexlevel);
2665 aliasTable_fixSrefs (env->aliases);
2667 /* exit true and false scopes */
2668 usymtab_quietPlainExitScope ();
2669 usymtab_quietPlainExitScope ();
2673 utab->guards = guardSet_levelUnionFree
2675 guardSet_invert (exprNode_getGuards (pred)),
2681 utab->guards = guardSet_levelUnion (utab->guards,
2682 exprNode_getGuards (pred),
2686 DPRINTF (("Here."));
2689 static void usymtab_fixCases (void) /*@modifies utab@*/ {
2690 while (utab->kind == US_CBRANCH)
2692 usymtab_quietPlainExitScope ();
2695 llassert (utab->kind != US_CBRANCH);
2699 usymtab_altBranch (/*@only@*/ guardSet guards)
2702 usymtab t = usymtab_create (US_FBRANCH, utab, FALSE);
2703 usymtab parent = utab->env;
2706 ** If we are in a case, need to close it. The C syntax
2707 ** is very liberal, so this kludge is necessary.
2710 usymtab_fixCases ();
2712 DPRINTF (("Current kind: %s", usymtab_unparseStack ()));
2713 llassert (utab->kind == US_TBRANCH);
2714 llassert (parent != GLOBAL_ENV);
2716 guardSet_free (t->guards);
2719 aliasTable_free (t->aliases);
2720 t->aliases = aliasTable_copy (parent->aliases);
2726 usymtab_allDefined (void)
2727 /*@globals utab, globtab@*/
2731 llassert (utab == globtab);
2733 for (i = 0; i < utab->nentries; i++)
2735 uentry e = utab->entries[i];
2737 if (uentry_isPriv (e))
2739 ; /* no need to define it */
2743 if (context_getFlag (FLG_SPECUNDECL))
2745 fileloc sloc = uentry_whereSpecified (e);
2746 fileloc dloc = uentry_whereDeclared (e);
2748 if (fileloc_isDefined (sloc)
2749 && !uentry_isFakeTag (e)
2750 && !fileloc_isDefined (dloc))
2754 message ("%s %q specified but not declared",
2755 ekind_capName (uentry_getKind (e)),
2756 uentry_getName (e)),
2761 if (!uentry_isCodeDefined (e))
2763 fileloc dloc = uentry_whereDeclared (e);
2765 if (fileloc_isLib (dloc))
2769 else if (fileloc_isDefined (dloc))
2771 if (!uentry_isAnyTag (e))
2773 if (fileloc_isUser (dloc))
2777 message ("%s %q declared but not defined",
2778 ekind_capName (uentry_getKind (e)),
2779 uentry_getName (e)),
2786 fileloc sloc = uentry_whereSpecified (e);
2788 if (fileloc_isDefined (sloc)
2789 && !fileloc_isImport (sloc)
2790 && !fileloc_isLib (sloc)
2791 && !fileloc_isPreproc (sloc)
2792 && !uentry_isFakeTag (e))
2794 if (uentry_isVariable (e) || uentry_isFunction (e))
2798 message ("%s %q specified but not declared or defined",
2799 ekind_capName (uentry_getKind (e)),
2800 uentry_getName (e)),
2807 message ("%s %q specified but not defined",
2808 ekind_capName (uentry_getKind (e)),
2809 uentry_getName (e)),
2819 void usymtab_exportHeader (void)
2824 for (i = 0; i < utab->nentries; i++)
2826 uentry ce = utab->entries[i];
2828 if (!uentry_isDatatype (ce)
2829 && !uentry_isAnyTag (ce)
2830 && !uentry_isEitherConstant (ce) && !uentry_isStatic (ce)
2831 && !uentry_isExternal (ce)
2832 && !uentry_isForward (ce))
2834 fileloc fwhere = uentry_whereDeclared (ce);
2836 if (fileloc_isUndefined (fwhere)
2837 && uentry_isFunction (ce))
2839 fwhere = uentry_whereDefined (ce);
2842 if (fileloc_isDefined (fwhere)
2843 && !fileloc_isHeader (fwhere)
2844 && !(fileloc_isSpecialFile (fwhere)
2845 && !context_getFlag (FLG_UNUSEDSPECIAL)))
2847 if (uentry_isVariable (ce))
2850 (FLG_EXPORTHEADERVAR,
2851 message ("%s %q exported but not declared in header file",
2852 ekind_capName (uentry_getKind (ce)),
2853 uentry_getName (ce)),
2856 uentry_showDefSpecInfo (ce, fwhere);
2861 if (!uentry_isIter (ce)
2862 && !uentry_isEndIter (ce)
2863 && !uentry_isExpandedMacro (ce))
2865 if (uentry_isFunction (ce)
2866 && cstring_equalLit (uentry_rawName (ce), "main"))
2868 ; /* no error for main */
2874 message ("%s %q exported but not declared "
2876 ekind_capName (uentry_getKind (ce)),
2877 uentry_getName (ce)),
2880 uentry_showDefSpecInfo (ce, fwhere);
2890 void usymtab_exportLocal (void)
2896 for (i = 0; i < utab->nentries; i++)
2898 uentry ce = utab->entries[i];
2901 if (!uentry_isDatatype (ce) && !uentry_isAnyTag (ce)
2902 && !uentry_isEitherConstant (ce)
2903 && !uentry_isIter (ce)
2904 && !uentry_isEndIter (ce)
2905 && !uentry_isExpandedMacro (ce)
2906 && uentry_isUsed (ce))
2908 /* check static uses */
2909 filelocList fuses = uentry_getUses (ce);
2910 fileloc mod = uentry_whereDefined (ce);
2911 bool ok = filelocList_isEmpty (fuses);
2912 fileloc fwhere = uentry_whereDeclared (ce);
2914 if (fileloc_isSpecialFile (fwhere)
2915 && !context_getFlag (FLG_UNUSEDSPECIAL))
2917 ok = TRUE; /* no errors for special files */
2921 filelocList_elements (fuses, uloc)
2923 if (fileloc_isUndefined (uloc) || !fileloc_sameModule (uloc, mod))
2926 /*@innerbreak@*/ break;
2928 } end_filelocList_elements;
2935 message ("%s exported but not used outside %s: %q",
2936 ekind_capName (uentry_getKind (ce)),
2937 fileloc_getBase (mod),
2938 uentry_getName (ce)),
2941 uentry_showDefSpecInfo (ce, fwhere);
2949 usymtab_allUsed (void)
2953 bool isFileStatic = usymtab_inFileScope ();
2954 cstring last_file = cstring_undefined;
2956 for (i = 0; i < utab->nentries; i++)
2958 bool hasError = FALSE;
2959 uentry ce = utab->entries[i];
2960 fileloc fwhere = uentry_whereDeclared (ce);
2962 if (fileloc_isUndefined (fwhere))
2964 fwhere = uentry_whereDefined (ce);
2967 if (fileloc_isInvalid (fwhere)
2968 || fileloc_isLib (fwhere)
2969 || fileloc_isBuiltin (fwhere)
2970 || ((fileloc_isSpecialFile (fwhere)
2971 || fileloc_isSpecialFile (uentry_whereDefined (ce)))
2972 && !context_getFlag (FLG_UNUSEDSPECIAL)))
2976 else if (!uentry_wasUsed (ce) && !uentry_isAnyTag (ce))
2978 cstring fname = fileloc_filename (fwhere);
2980 if (cstring_isUndefined (last_file))
2984 else if (cstring_equal (fname, last_file))
2993 if (uentry_isParam (ce))
2995 if (context_inMacro ())
2997 sRef cref = uentry_getSref (ce);
2999 if (uentry_isYield (ce))
3001 ; /* no checks (for now) */
3003 else if (sRef_isSafe (cref))
3009 if (uentry_hasRealName (ce))
3012 optgenerror (FLG_MACROPARAMS,
3013 message ("Macro parameter %q not used",
3014 uentry_getName (ce)),
3021 if (cstring_equalFree (uentry_getName (ce),
3022 cstring_makeLiteral ("...")))
3028 hasError = optgenerror (FLG_PARAMUNUSED,
3029 message ("Parameter %q not used",
3030 uentry_getName (ce)),
3035 else if (uentry_isFunction (ce) || uentry_isIter (ce))
3037 if (fileloc_isUser (fwhere))
3039 hasError = optgenerror
3041 message ("%q %q declared but not used",
3043 (uentry_isIter (ce) ? "Iterator"
3044 : (isFileStatic ? "File static function" : "Function")),
3045 uentry_getName (ce)),
3049 else if (uentry_isEndIter (ce))
3051 ; /* no error (already reported for iter */
3053 else if (uentry_isEnumConstant (ce))
3055 if (fileloc_isUser (fwhere))
3057 hasError = optgenerror
3059 message ("Enum member %q not used",
3060 uentry_getName (ce)),
3064 else if (uentry_isConstant (ce))
3066 if (fileloc_isUser (fwhere))
3068 hasError = optgenerror
3070 message ("Constant %q declared but not used",
3071 uentry_getName (ce)),
3075 else if (uentry_isDatatype (ce))
3077 if (fileloc_isUser (fwhere))
3079 hasError = optgenerror
3081 message ("Type %q declared but not used",
3082 uentry_getName (ce)),
3086 else if (!uentry_isRefParam (ce) && !uentry_isExpandedMacro (ce))
3087 { /* errors for ref params will be reported in the next scope */
3088 llassertprint (uentry_isVar (ce),
3089 ("ce: %s", uentry_unparseFull (ce)));
3091 if (ctype_isFunction (uentry_getType (ce)))
3093 if (fileloc_isUser (fwhere))
3095 hasError = optgenerror
3097 message ("%q %q declared but not used",
3099 (isFileStatic ? "File static function"
3101 uentry_getName (ce)),
3107 if (fileloc_isUser (fwhere))
3111 hasError = optgenerror
3113 message ("%q %q declared but not used",
3115 (isFileStatic ? "File static variable"
3117 uentry_getName (ce)),
3127 else if (uentry_isDatatype (ce) || uentry_isAnyTag (ce))
3128 { /* check all fields */
3129 ctype ct = uentry_getRealType (ce);
3132 while (ctype_isAP (ct))
3134 ct = ctype_getBaseType (ct);
3138 if (ctype_isSU (ct))
3140 uentryList fields = ctype_getFields (ct);
3142 uentryList_elements (fields, field)
3144 if (!uentry_isUsed (field))
3146 if (uentry_hasName (ce))
3148 hasError |= optgenerror
3150 message ("Field %q of %s %q declared but not used",
3151 uentry_getName (field),
3152 cstring_makeLiteralTemp
3153 (ctype_isStruct (ct) ? "structure" : "union"),
3154 uentry_getName (ce)),
3155 uentry_whereEarliest (field));
3159 hasError |= optgenerror
3161 message ("Field %q of unnamed %s declared but not used",
3162 uentry_getName (field),
3163 cstring_makeLiteralTemp
3164 (ctype_isStruct (ct) ? "structure" : "union")),
3165 uentry_whereEarliest (field));
3168 uentry_setUsed (field, fileloc_undefined);
3170 } end_uentryList_elements;
3180 if (uentry_isParam (ce) && context_inMacro ())
3182 if (fileloc_isDefined (uentry_whereSpecified (ce)))
3184 uentry_showWhereSpecified (ce);
3189 uentry_showDefSpecInfo (ce, fwhere);
3192 uentry_setUsed (ce, fileloc_undefined);
3198 checkGlobalReturn (uentry glob, sRef orig)
3200 sRef sr = uentry_getSref (glob);
3203 if (context_getFlag (FLG_GLOBSTATE))
3205 if (sRef_isKilledGlob (orig))
3207 if (sRef_isStateUndefined (sr)
3208 || sRef_isUnuseable (sr)
3209 || sRef_isStateUnknown (sr)
3210 || sRef_isDead (sr))
3216 ctype ct = ctype_realType (uentry_getType (glob));
3218 if (ctype_isVisiblySharable (ct))
3223 ("Killed global %q not released before return",
3224 uentry_getName (glob)),
3227 sRef_showStateInfo (sr);
3232 sRef_protectDerivs ();
3233 (void) checkGlobalDestroyed (sr, g_currentloc);
3234 sRef_clearProtectDerivs ();
3240 if (sRef_isStateUndefined (sr))
3242 if (optgenerror (FLG_GLOBSTATE,
3244 ("Function returns with global %q undefined",
3245 uentry_getName (glob)),
3248 sRef_showStateInfo (sr);
3253 if (sRef_isDead (sr))
3257 message ("Function returns with global %q "
3258 "referencing released storage",
3259 uentry_getName (glob)),
3262 sRef_showStateInfo (sr);
3263 sRef_setDefState (sr, SS_UNKNOWN, fileloc_undefined);
3267 if (ctype_isRealPointer (uentry_getType (glob)) &&
3268 sRef_possiblyNull (sr) && !uentry_possiblyNull (glob))
3272 message ("Function returns with non-null global %q "
3273 "referencing null storage",
3274 uentry_getName (glob)),
3277 sRef_showNullInfo (sr);
3282 checkGlobReturn (glob);
3290 ** remember: check alias globals
3293 void usymtab_checkFinalScope (bool isReturn)
3296 bool mustFree = context_getFlag (FLG_MUSTFREE);
3297 bool mustDefine = context_getFlag (FLG_MUSTDEFINE);
3298 /* bool mustNotAlias = context_getFlag (FLG_MUSTNOTALIAS); */
3299 sRefSet checked = sRefSet_new ();
3300 usymtab stab = utab;
3304 ** need to check all scopes out to function parameters.
3309 for (i = 0; i < stab->nentries; i++)
3311 uentry ce = stab->entries[i];
3312 sRef sr = uentry_getSref (ce);
3313 sRef rb = sRef_getRootBase (sr);
3315 if (ctype_isFunction (uentry_getType (ce)))
3317 /*@innercontinue@*/ continue;
3322 DPRINTF (("Check entry: %s", uentry_unparseFull (ce)));
3324 if (!sRefSet_member (checked, sr) && !sRef_isGlobal (rb))
3326 if (ctype_isRealSU (uentry_getType (ce))
3327 && !uentry_isAnyParam (ce)
3328 && !uentry_isRefParam (ce)
3329 && !uentry_isStatic (ce)
3330 && !sRef_isDependent (sr)
3331 && !sRef_isOwned (sr))
3333 sRefSet als = usymtab_allAliases (sr);
3336 if (sRefSet_isEmpty (als))
3338 checkLocalDestroyed (sr, g_currentloc);
3342 /* aliased, no problem */ ;
3348 (!uentry_isStatic (ce)
3349 && ((sRef_isNewRef (sr))
3350 || (((sRef_isOnly (sr) || sRef_isFresh (sr)
3351 || sRef_isKeep (sr) || sRef_isOwned (sr))
3352 && !sRef_isDead (sr))
3353 && (!sRef_definitelyNull (sr))
3354 && (!usymtab_isProbableNull (sr)))))
3356 bool hasError = TRUE;
3359 ** If its a scope exit, check if there is an alias.
3360 ** If so, make it only. If not, there is an error.
3365 if (canLoseReference (sr, g_currentloc))
3373 if (sRef_hasLastReference (sr))
3375 sRef ar = sRef_getAliasInfoRef (sr);
3380 ("Last reference %q to %s storage %qnot %q before %q",
3382 alkind_unparse (sRef_getAliasKind (sr)),
3383 sRef_unparseOpt (ar),
3384 cstring_makeLiteral (sRef_isKeep (sr)
3385 ? "transferred" : "released"),
3386 cstring_makeLiteral (isReturn
3387 ? "return" : "scope exit")),
3390 sRef_showRefLost (sr);
3393 else if (sRef_isNewRef (sr))
3398 ("%q %q not released before %q",
3400 (alkind_isKillRef (sRef_getOrigAliasKind (sr))
3401 ? "Kill reference parameter" : "New reference"),
3402 uentry_getName (ce),
3403 cstring_makeLiteral (isReturn
3404 ? "return" : "scope exit")),
3407 sRef_showAliasInfo (sr);
3412 if (ctype_isRealSU (sRef_getType (sr)))
3414 checkStructDestroyed (sr, g_currentloc);
3421 ("%s storage %q not %q before %q",
3422 alkind_capName (sRef_getAliasKind (sr)),
3423 uentry_getName (ce),
3424 cstring_makeLiteral (sRef_isKeep (sr)
3425 ? "transferred" : "released"),
3426 cstring_makeLiteral (isReturn
3427 ? "return" : "scope exit")),
3430 sRef_showAliasInfo (sr);
3441 else if (mustDefine && uentry_isOut (ce))
3443 if (!ynm_toBoolStrict (sRef_isReadable (sr)))
3447 message ("Out storage %q not defined before %q",
3448 uentry_getName (ce),
3450 (isReturn ? "return" : "scope exit")),
3453 /* uentry_showWhereDeclared (ce); */
3462 ** also check state is okay
3465 if (usymtab_lexicalLevel () > functionScope
3466 && uentry_isVariable (ce)
3467 && (sRef_isLocalVar (sr)
3468 && (sRef_isDependent (sr) || sRef_isLocalState (sr))))
3470 sRefSet ab = usymtab_aliasedBy (sr);
3472 /* should do something more efficient here */
3474 if (sRefSet_isEmpty (ab))
3476 /* and no local ref */
3491 checked = sRefSet_insert (checked, sr);
3494 llassert (usymtab_isDefined (stab->env));
3496 if (usymtab_isBranch (stab))
3498 stab = usymtab_dropEnv (stab);
3505 llassert (stab != usymtab_undefined);
3506 } while (isReturn && (stab->lexlevel >= paramsScope));
3508 sRefSet_free (checked);
3512 ** all globals are appropriately defined
3513 ** all parameters are appropriately defined
3514 ** special clauses are followed
3517 if (isReturn || (utab->lexlevel == paramsScope))
3519 uentry fcn = context_getHeader ();
3520 uentryList params = context_getParams ();
3521 globSet uglobs = context_getUsedGlobs ();
3522 globSet sglobs = context_getGlobs ();
3525 if (isReturn && context_maybeSet (FLG_GLOBALIAS))
3527 aliasTable_checkGlobs (utab->aliases);
3531 ** special clauses (defines, sets, allocates, releases)
3534 if (uentry_hasSpecialClauses (fcn))
3536 specialClauses clauses = uentry_getSpecialClauses (fcn);
3538 specialClauses_elements (clauses, cl)
3540 sRefTest tst = specialClause_getPostTestFunction (cl);
3541 sRefSet rfs = specialClause_getRefs (cl);
3544 sRefSet_elements (rfs, el)
3546 sRef base = sRef_getRootBase (el);
3548 if (sRef_isResult (base))
3552 else if (sRef_isParam (base))
3554 sRef sr = sRef_updateSref (base);
3556 sr = sRef_fixBase (el, sr);
3559 if (tst != NULL && !tst (sr))
3562 (specialClause_postErrorCode (cl),
3563 message ("%s storage %qcorresponds to "
3564 "storage listed in %q clause",
3565 specialClause_postErrorString (cl, sr),
3566 sRef_unparseOpt (sr),
3567 specialClause_unparseKind (cl)),
3570 sRefShower ss = specialClause_getPostTestShower (cl);
3582 if (sRef_isMeaningful (el))
3587 } end_sRefSet_elements ;
3589 } end_specialClauses_elements ;
3594 ** check parameters on return
3597 uentryList_elements (params, arg)
3599 if (!uentry_isElipsisMarker (arg))
3601 ctype rt = ctype_realType (uentry_getType (arg));
3603 if (ctype_isMutable (rt) || ctype_isSU (rt))
3605 uentry param = usymtab_lookupQuiet (utab, uentry_rawName (arg));
3606 checkParamReturn (param);
3609 } end_uentryList_elements;
3611 globSet_allElements (sglobs, el)
3613 uentry current = sRef_getUentry (el);
3615 if (uentry_isVariable (current) && !uentry_isRealFunction (current))
3617 checkGlobalReturn (current, el);
3619 } end_globSet_allElements;
3621 globSet_allElements (uglobs, el)
3623 if (!globSet_member (sglobs, el))
3625 uentry current = sRef_getUentry (el);
3628 if (uentry_isVariable (current)
3629 && !uentry_isRealFunction (current))
3631 checkGlobalReturn (current, sRef_undefined);
3634 } end_globSet_allElements;
3640 usymtab_quietExitScope (fileloc loc)
3641 /*@globals utab, globtab, filetab; @*/
3644 usymtab t = utab->env;
3646 if (utab->reftable != NULL)
3650 for (i = 0; i < utab->nentries; i++)
3652 uentry current = utab->entries[i];
3653 uentry old = usymtab_lookupAux (t, uentry_rawName (current));
3655 uentry_mergeState (old, current, loc, FALSE, FALSE, FALSE, NOCLAUSE);
3659 llassert (t != NULL);
3661 if (t->lexlevel > paramsScope)
3663 t->guards = guardSet_levelUnion (t->guards, utab->guards, t->lexlevel);
3664 t->aliases = aliasTable_levelUnionSeq (t->aliases, utab->aliases,
3666 utab->aliases = aliasTable_undefined;
3669 t->mustBreak = utab->mustBreak;
3670 t->exitCode = utab->exitCode;
3672 usymtab_freeLevel (utab);
3678 ** Exit a scope with no checking, lose alias states.
3679 ** (When should this be used?)
3682 void usymtab_quietPlainExitScope (void)
3683 /*@globals utab, globtab, filetab@*/
3686 usymtab t = utab->env;
3688 llassert (t != NULL);
3689 llassert (NOALIAS (utab->aliases, t->aliases));
3690 usymtab_freeLevel (utab);
3694 void usymtab_exitScope (exprNode expr)
3695 /*@globals utab, filetab, globtab@*/
3696 /*@modifies utab, globtab@*/
3698 usymtab ctab = usymtab_undefined;
3699 usymtab lctab = usymtab_undefined;
3700 bool mustReturn = exprNode_mustEscape (expr);
3702 if (utab->kind == US_CBRANCH)
3705 ** save the case branches, remove the first non-cbranch
3710 while (utab->kind == US_CBRANCH)
3714 llassert (utab != GLOBAL_ENV);
3718 llassertprint (utab->kind != US_TBRANCH && utab->kind != US_FBRANCH
3719 && utab->kind != US_CBRANCH && utab->kind != US_SWITCH,
3720 ("exitScope: in branch: %s", usymtab_unparseStack()));
3723 ** check all variables in scope were used
3727 ** bogus errors if this is the normal inside a switch,
3728 ** since cases have not been merged yet. Should probably
3729 ** still check this, but I'm too lazy at the moment...
3732 llassertfatal (utab->env != GLOBAL_ENV);
3734 if (utab->env->kind != US_SWITCH)
3740 ** check aliasing: all only params are released (dead)
3741 ** definition: all out params are defined, all modified params
3742 ** are completely defined
3744 ** NOTE: note for exiting paramsScope, since checkReturn should be
3748 if (!mustReturn && (usymtab_lexicalLevel () > functionScope))
3751 ** should only call this is end of scope is reachable...
3754 usymtab_checkFinalScope (FALSE);
3757 if (usymtab_lexicalLevel () == paramsScope && context_inFunctionLike ())
3760 ** leaving a function, need to fix up globals
3763 uentryList params = context_getParams ();
3764 globSet globs = context_getUsedGlobs ();
3767 uentryList_elements (params, ue)
3769 uentry_fixupSref (ue);
3770 } end_uentryList_elements;
3772 clearFunctionTypes ();
3775 globSet_allElements (globs, el)
3777 if (sRef_isCvar (el))
3780 int index = sRef_getScopeIndex (el);
3782 if (sRef_isFileStatic (el))
3784 llassert (usymtab_isDefined (filetab));
3785 current = usymtab_fetchIndex (filetab, index);
3789 current = usymtab_fetchIndex (globtab, index);
3792 if (uentry_isVariable (current))
3794 uentry_fixupSref (current);
3798 sRef_clearDerived (uentry_getSref (current));
3801 } end_globSet_allElements;
3804 usymtab_quietExitScope (exprNode_loc (expr));
3806 if (lctab != usymtab_undefined)
3808 /*@i@*/ lctab->env = utab;
3809 /*@i@*/ utab = ctab;
3810 /*@-branchstate@*/ } /*@=branchstate@*/
3816 ** yikes! don't let the '170 kids see this one...
3820 uentry_directParamNo (uentry ue)
3822 if (uentry_isVar (ue))
3824 sRef sr = uentry_getSref (ue);
3826 if (sRef_lexLevel (sr) == functionScope)
3828 /*@access sRef@*/ /*@-null@*/
3829 int index = sr->info->cvar->index;
3830 /*@noaccess sRef@*/ /*@=null@*/
3832 if (index < uentryList_size (context_getParams ()))
3841 /*@dependent@*/ /*@exposed@*/ uentry
3842 usymtab_getParam (int paramno)
3846 ** requires in a function context (checked)
3848 ** depends on no nested functions --- the function
3849 ** parameters are ALWAYS one scope inside the global scope
3850 ** and entered in order!
3854 if (!context_inFunctionLike ())
3855 llfatalbug (message ("usymtab_getParam: not in function context: %q",
3856 context_unparse ()));
3858 while (s->lexlevel > paramsScope)
3863 llassert (usymtab_isDefined (s));
3865 if (paramno >= s->nentries)
3868 ** Parse errors lead to this.
3871 uentry err = uentry_makeVariableLoc (cstring_makeLiteralTemp ("<error>"),
3874 uentry_markOwned (err);
3878 return (s->entries[paramno]);
3881 static /*@dependent@*/ /*@exposed@*/ uentry
3882 usymtab_getRefTab (/*@notnull@*/ usymtab u, int level, usymId index)
3887 ue = usymtab_getRefNoisy (u, level, index);
3890 if (uentry_isUndefined (ue))
3892 llbug (message ("usymtab_getRef: out of range: %d. level = %d",
3900 static /*@dependent@*/ /*@exposed@*/ usymtab
3901 usymtab_dropEnv (/*@notnull@*/ usymtab s)
3903 if (s->kind == US_CBRANCH)
3911 llassert (s != GLOBAL_ENV);
3912 } while (s->kind == US_CBRANCH);
3913 /* drop all cases (except in nested scopes */
3916 llassert (s != GLOBAL_ENV);
3919 if (s->kind == US_FBRANCH)
3921 s = s->env; /* skip the true branch */
3922 llassert (usymtab_isDefined (s));
3923 llassert (s->kind == US_TBRANCH);
3926 llassert (s != GLOBAL_ENV);
3932 /*@dependent@*/ /*@exposed@*/ uentry
3933 usymtab_getRefQuiet (int level, usymId index)
3939 llassert (s != NULL);
3940 llassert (index >= 0);
3942 if (level > s->lexlevel)
3945 return uentry_undefined;
3948 llassertprint (level <= s->lexlevel, ("level: %d / lexlevel: %d",
3949 level, s->lexlevel));
3951 while (s->lexlevel > level)
3953 if (usymtab_isBranch (s))
3955 int eindex = refTable_lookup (s, level, index);
3957 if (eindex != NOT_FOUND)
3959 return (s->entries[eindex]);
3963 s = usymtab_dropEnv (s);
3966 while (usymtab_isBranch (s) && s->lexlevel == level)
3968 int eindex = refTable_lookup (s, level, index);
3970 if (eindex != NOT_FOUND)
3972 return (s->entries[eindex]);
3975 s = usymtab_dropEnv (s);
3978 if (index >= s->nentries)
3980 return uentry_undefined;
3983 llassert (!uentry_isUndefined (s->entries[index]));
3985 return s->entries[index];
3988 static /*@dependent@*/ /*@exposed@*/ uentry
3989 usymtab_getRefNoisy (/*@notnull@*/ usymtab s, int level, usymId index)
3992 uentry ue = uentry_undefined;
3995 llassert (index >= 0);
3998 while (s->lexlevel > level)
4001 if (usymtab_isBranch (s))
4003 int eindex = refTable_lookup (s, level, index);
4005 if (eindex != NOT_FOUND)
4007 ue = s->entries[eindex];
4011 while (!usymtab_isBranch (otab))
4013 otab = usymtab_dropEnv (otab);
4014 llassert (otab != GLOBAL_ENV);
4017 if (refTable_lookup (otab, level, index) == NOT_FOUND)
4019 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4031 s = usymtab_dropEnv (s);
4034 llassert (usymtab_isDefined (s));
4036 while (usymtab_isBranch (s) && s->lexlevel == level)
4038 int eindex = refTable_lookup (s, level, index);
4041 if (eindex != NOT_FOUND)
4043 ue = s->entries[eindex];
4047 while (!usymtab_isBranch (otab))
4049 otab = usymtab_dropEnv (otab);
4050 llassert (otab != GLOBAL_ENV);
4053 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4063 s = usymtab_dropEnv (s);
4066 if (s->lexlevel == level && (index < s->nentries))
4068 ue = s->entries[index];
4070 if (uentry_isValid (ue))
4074 while (!usymtab_isBranch (otab))
4076 otab = usymtab_dropEnv (otab);
4078 if (otab == GLOBAL_ENV)
4084 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4095 if (index >= s->nentries)
4097 return uentry_undefined;
4100 llassert (!uentry_isUndefined (s->entries[index]));
4102 return s->entries[index];
4106 ** looking up entries
4108 ** If entry is inside a branch, then copy it, and put it into
4109 ** the branch table.
4113 int refTable_lookup (/*@notnull@*/ usymtab ut, int level, int index)
4115 refTable rt = ut->reftable;
4118 llassert (rt != NULL);
4121 for (i = 0; i < ut->nentries; i++)
4123 if (rt[i]->level == level && rt[i]->index == index)
4133 /*@only@*/ refentry refentry_create (int level, int index)
4135 refentry r = (refentry) dmalloc (sizeof (*r));
4143 static /*@dependent@*/ /*@exposed@*/ uentry
4144 usymtab_addRefEntry (/*@notnull@*/ usymtab s, cstring k)
4149 llassert (ut->reftable != NULL);
4151 while (s != GLOBAL_ENV)
4153 eindex = usymtab_getIndex (s, k);
4155 if (eindex != NOT_FOUND)
4157 uentry current = s->entries[eindex];
4159 if (uentry_isVar (current) && !ctype_isFunction (uentry_getType (current)))
4163 DPRINTF (("Here: copying %s", uentry_unparseFull (current)));
4165 ue = uentry_copy (current);
4167 DPRINTF (("Here: copying %s", uentry_unparseFull (ue)));
4169 usymtab_addEntryQuiet (ut, ue);
4171 if (s->reftable != NULL)
4173 refentry ref = s->reftable[eindex];
4176 ut->reftable[ut->nentries - 1]
4177 = refentry_create (ref->level, ref->index);
4181 ut->reftable[ut->nentries - 1]
4182 = refentry_create (s->lexlevel, eindex);
4193 s = usymtab_dropEnv (s);
4196 return uentry_undefined;
4199 static uentry usymtab_lookupAux (usymtab s, cstring k)
4201 DPRINTF (("Lookup: %s", k));
4203 while (s != GLOBAL_ENV)
4205 int eindex = usymtab_getIndex (s, k);
4207 if (eindex != NOT_FOUND)
4209 uentry ret = s->entries[eindex];
4211 DPRINTF (("Found: %s", uentry_unparseFull (ret)));
4215 if (s->kind == US_TBRANCH || s->kind == US_FBRANCH
4216 || s->kind == US_CBRANCH)
4218 uentry ret = usymtab_addRefEntry (s, k);
4219 DPRINTF (("Ref entry: %s", uentry_unparseFull (ret)));
4226 return uentry_undefined;
4229 static /*@dependent@*/ /*@exposed@*/ uentry
4230 usymtab_lookupQuiet (usymtab s, cstring k)
4234 while (s != GLOBAL_ENV)
4236 eindex = usymtab_getIndex (s, k);
4238 if (eindex != NOT_FOUND)
4240 uentry ret = s->entries[eindex];
4247 return uentry_undefined;
4250 /*@dependent@*/ /*@observer@*/ uentry
4251 usymtab_lookupSafe (cstring k)
4254 DPRINTF (("Lookup safe: %s", k));
4255 return (usymtab_lookupAux (utab, k));
4259 usymtab_lookupExpose (cstring k)
4262 uentry ce = usymtab_lookupAux (utab, k);
4264 if (uentry_isUndefined (ce))
4266 llfatalbug (message ("usymtab_lookup: not found: *%s*", k));
4269 if (uentry_isPriv (ce))
4271 llfatalbug (message ("usymtab_lookup: private: *%s*", k));
4277 uentry usymtab_lookupExposeGlob (cstring k)
4279 return (usymtab_lookupGlobSafe (k));
4282 uentry usymtab_lookupGlob (cstring k)
4283 /*@globals globtab@*/
4285 uentry ce = usymtab_lookupAux (globtab, k);
4287 if (uentry_isUndefined (ce))
4288 llfatalbug (message ("usymtab_lookup: not found: %s", k));
4290 if (uentry_isPriv (ce))
4291 llfatalbug (message ("usymtab_lookup: private: %s", k));
4296 /*@observer@*/ uentry
4297 usymtab_lookupGlobSafe (cstring k)
4298 /*@globals globtab@*/
4300 uentry ce = usymtab_lookupAux (globtab, k);
4305 uentry usymtab_lookupEither (cstring k)
4308 uentry ce = usymtab_lookupSafe (k);
4310 if (uentry_isUndefined (ce))
4311 llfatalerror (message ("usymtab_lookup: not found: %s", k));
4318 usymtab_lookupType (cstring k)
4319 /*@globals globtab@*/
4321 usymId uid = usymtab_getTypeId (k);
4323 if (uid == USYMIDINVALID)
4325 llcontbug (message ("usymtab_lookupType: not found: %s", k));
4326 return ctype_unknown;
4329 return (uentry_getRealType (usymtab_getTypeEntry (uid)));
4334 usymtab_lookupAbstractType (cstring k) /*@globals globtab@*/
4336 usymId uid = usymtab_getTypeId (k);
4338 if (uid == USYMIDINVALID)
4340 llcontbug (message ("usymtab_lookupType: not found: %s", k));
4341 return ctype_unknown;
4344 return (uentry_getAbstractType (usymtab_getTypeEntry (uid)));
4348 ** if there is an unnamed lcl-specified struct tag matching
4349 ** the uentryList, return its datatype. Otherwise, returns
4354 usymtab_structFieldsType (uentryList f)
4355 /*@globals globtab@*/
4357 return (usymtab_suFieldsType (f, TRUE));
4361 usymtab_unionFieldsType (uentryList f)
4362 /*@globals globtab@*/
4364 return (usymtab_suFieldsType (f, FALSE));
4368 usymtab_suFieldsType (uentryList f, bool isStruct)
4369 /*@globals globtab@*/
4373 if (fileloc_isSpec (g_currentloc)) return (ctype_undefined);
4375 for (i = 0; i < globtab->nentries; i++)
4377 uentry current = globtab->entries[i];
4380 ? uentry_isStructTag (current) : uentry_isUnionTag (current)))
4382 if (isFakeTag (uentry_rawName (current)))
4384 ctype ct = uentry_getType (current);
4386 if ((isStruct ? ctype_isStruct (ct) : ctype_isUnion (ct))
4387 && (uentryList_matchFields (f, ctype_getFields (ct))))
4389 return uentry_getAbstractType (current);
4395 return ctype_undefined;
4399 usymtab_enumEnumNameListType (enumNameList f)
4400 /*@globals globtab@*/
4404 for (i = 0; i < globtab->nentries; i++)
4406 uentry current = globtab->entries[i];
4408 if (uentry_isEnumTag (current))
4410 if (isFakeTag (uentry_rawName (current)))
4412 ctype ct = uentry_getType (current);
4414 if (ctype_isEnum (ct) && (enumNameList_match (f, ctype_elist (ct))))
4416 return uentry_getType (current);
4422 return ctype_undefined;
4426 usymtab_exists (cstring k)
4429 uentry ce = usymtab_lookupSafe (k);
4431 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
4435 usymtab_existsReal (cstring k)
4438 uentry ce = usymtab_lookupSafe (k);
4440 return (!(uentry_isUndefined (ce))
4441 && !(uentry_isPriv (ce))
4442 && !(uentry_isExpandedMacro (ce)));
4446 usymtab_existsGlob (cstring k)
4447 /*@globals globtab@*/
4449 uentry ce = usymtab_lookupAux (globtab, k);
4451 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
4456 usymtab_existsEither (cstring k)
4459 uentry ce = usymtab_lookupAux (utab, k);
4461 return (uentry_isValid (ce));
4465 usymtab_existsGlobEither (cstring k)
4466 /*@globals globtab@*/
4468 uentry ce = usymtab_lookupAux (globtab, k);
4470 return (uentry_isValid (ce));
4475 usymtab_existsType (cstring k)
4476 /*@globals globtab@*/
4478 uentry ce = usymtab_lookupAux (globtab, k);
4480 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && uentry_isDatatype (ce));
4484 usymtab_existsTypeEither (cstring k)
4485 /*@globals globtab@*/
4487 uentry ce = usymtab_lookupAux (globtab, k);
4489 return (uentry_isValid (ce) && uentry_isDatatype (ce));
4493 usymtab_existsStructTag (cstring k) /*@globals globtab@*/
4495 cstring sname = makeStruct (k);
4496 uentry ce = usymtab_lookupAux (globtab, sname);
4498 cstring_free (sname);
4501 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
4505 usymtab_existsUnionTag (cstring k) /*@globals globtab@*/
4507 cstring uname = makeUnion (k);
4508 uentry ce = usymtab_lookupAux (globtab, uname);
4510 cstring_free (uname);
4512 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
4516 usymtab_existsEnumTag (cstring k) /*@globals globtab@*/
4518 cstring ename = makeEnum (k);
4519 uentry ce = usymtab_lookupAux (globtab, ename);
4521 cstring_free (ename);
4522 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
4526 bool usymtab_existsVar (cstring k)
4529 uentry ce = usymtab_lookupSafe (k);
4531 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && (uentry_isVar (ce)));
4540 refTable_free (/*@only@*/ /*@null@*/ refTable x, int nentries)
4546 for (i = 0; i < nentries; i++)
4556 usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab u)
4557 /*@globals globtab, utab, filetab@*/
4561 aliasTable_free (u->aliases);
4563 refTable_free (u->reftable, u->nentries);
4565 if (u == filetab || u == globtab)
4567 for (i = 0; i < u->nentries; i++)
4569 uentry_freeComplete (u->entries[i]);
4574 for (i = 0; i < u->nentries; i++)
4576 uentry_free (u->entries[i]);
4580 guardSet_free (u->guards);
4587 llassert (u->htable == NULL);
4595 usymtab_freeAux (/*@only@*/ usymtab u)
4596 /*@globals globtab, utab, filetab@*/
4599 while (u != GLOBAL_ENV)
4602 usymtab_freeLevel (u);
4609 void usymtab_free ()
4610 /*@globals killed utab, globtab, filetab@*/
4614 usymtab_freeAux (utab);
4617 static int usymtab_lexicalLevel (void) /*@globals utab@*/
4619 return (utab->lexlevel);
4622 bool usymtab_inGlobalScope () /*@globals utab, globtab@*/
4624 return (utab == globtab);
4627 bool usymtab_inFileScope () /*@globals utab@*/
4629 return (utab->lexlevel == fileScope);
4632 bool usymtab_inFunctionScope () /*@globals utab@*/
4634 return (utab->lexlevel == functionScope);
4639 usymtab_replaceEntry (uentry s)
4640 /*@globals utab, globtab@*/
4641 /*@modifies utab, s@*/
4643 usymtab_replaceEntryAux (utab, s);
4648 usymtab_matchForwardStruct (usymId u1, usymId u2)
4649 /*@globals globtab@*/
4651 uentry ue1 = usymtab_getTypeEntry (u1);
4652 uentry ue2 = usymtab_getTypeEntry (u2);
4654 if (uentry_isAnyTag (ue2))
4656 ctype reptype = uentry_getType (ue1);
4658 if (ctype_isPointer (reptype))
4660 ctype repbase = ctype_getBaseType (reptype);
4662 if (ctype_isUA (repbase))
4664 typeId rtuid = ctype_typeId (repbase);
4666 if (u2 == rtuid) return TRUE;
4668 if (usymId_isValid (rtuid))
4670 reptype = uentry_getType (usymtab_getTypeEntry (rtuid));
4672 return (ctype_isUA (reptype) && (u2 == (ctype_typeId (reptype))));
4681 void usymtab_addGuards (guardSet guards)
4684 utab->guards = guardSet_union (utab->guards, guards);
4687 static bool usymtab_isGuardedAux (sRef s)
4691 sRef base = sRef_getRootBase (s);
4692 int lowlevel = paramsScope;
4693 int baselevel = sRef_lexLevel (base);
4695 if (sRef_isCvar (base))
4697 lowlevel = baselevel;
4698 if (lowlevel < paramsScope) lowlevel = paramsScope;
4701 while (tab->lexlevel >= lowlevel)
4703 if (guardSet_isGuarded (tab->guards, s))
4706 if (!sRef_definitelyNull (s))
4708 sRef_setNotNull (s, fileloc_undefined);
4714 tab = usymtab_dropEnv (tab);
4720 void usymtab_unguard (sRef s) /*@modifies utab@*/
4723 sRef base = sRef_getRootBase (s);
4724 int lowlevel = paramsScope;
4725 int baselevel = sRef_lexLevel (base);
4727 if (sRef_isCvar (base))
4729 lowlevel = baselevel;
4730 if (lowlevel < paramsScope) lowlevel = paramsScope;
4733 while (tab->lexlevel >= lowlevel)
4735 if (guardSet_isGuarded (tab->guards, s))
4737 guardSet_delete (tab->guards, s);
4740 tab = usymtab_dropEnv (tab);
4744 bool usymtab_isGuarded (sRef s)
4747 return (sRef_aliasCompleteSimplePred (usymtab_isGuardedAux, s));
4750 bool usymtab_isProbableNull (sRef s)
4752 return (sRef_aliasCheckSimplePred (usymtab_isProbableNullAux, s));
4755 bool usymtab_isProbableDeepNull (sRef s)
4757 return (sRef_deepPred (usymtab_isProbableNull, s));
4760 static bool usymtab_isProbableNullAux (sRef s)
4764 sRef base = sRef_getRootBase (s);
4765 int lowlevel = paramsScope;
4767 if (sRef_isCvar (base))
4769 lowlevel = sRef_lexLevel (base);
4770 if (lowlevel < paramsScope) lowlevel = paramsScope;
4773 while (tab->lexlevel >= lowlevel)
4775 if (guardSet_isProbableNull (tab->guards, s))
4780 while (tab->kind == US_CBRANCH)
4785 llassert (usymtab_isDefined (tab));
4787 if (tab->kind == US_FBRANCH)
4790 llassert (tab->kind == US_TBRANCH);
4800 usymtab_printGuards ()
4801 /*@globals utab, globtab@*/
4803 usymtab ttab = utab;
4805 while (ttab != globtab)
4807 llmsg (message ("Guards [%d]: %q", ttab->lexlevel,
4808 guardSet_unparse (ttab->guards)));
4814 usymtab_displayAllUses ()
4815 /*@globals utab, globtab@*/
4819 /* only in top scope */
4820 llassert (utab == globtab);
4822 /* need a copy, so order is not messed up by sort! */
4823 copy = usymtab_shallowCopy (globtab);
4825 qsort (copy->entries, (size_t)copy->nentries,
4826 sizeof (*copy->entries), (int (*)(const void *, const void *)) uentry_xcompareuses);
4828 usymtab_entries (copy, ue)
4830 if (uentry_isValid (ue))
4832 filelocList uses = uentry_getUses (ue);
4833 int size = filelocList_realSize (uses);
4835 if (fileloc_isDefined (uentry_whereDefined (ue))
4836 && !fileloc_isLib (uentry_whereDefined (ue))
4839 llmsg (message ("%q (%q), %d use%p:\n %q",
4840 uentry_getName (ue),
4841 fileloc_unparse (uentry_whereDefined (ue)),
4842 size, filelocList_unparseUses (uses)));
4845 } end_usymtab_entries;
4847 usymtab_shallowFree (copy);
4850 static /*@dependent@*/ /*@exposed@*/ usymtab
4851 usymtab_getFileTab ()
4852 /*@globals filetab@*/
4854 llassert (filetab != NULL);
4860 usymtab_unparseStack ()
4863 return (usymtab_unparseStackTab (utab));
4866 static /*@only@*/ cstring
4867 usymtab_unparseStackTab (usymtab t)
4869 bool firstOne = TRUE;
4870 cstring ret = cstring_makeLiteral ("[");
4872 while (t != GLOBAL_ENV)
4876 ret = message ("%q %q", ret, usymtab_typeName (t));
4881 ret = message ("%q, %q", ret, usymtab_typeName (t));
4886 ret = message ("%q ]", ret);
4890 static /*@only@*/ cstring
4891 usymtab_typeName (/*@notnull@*/ usymtab t)
4895 case US_GLOBAL: return cstring_makeLiteral ("global");
4896 case US_NORMAL: return cstring_makeLiteral ("normal");
4897 case US_TBRANCH: return cstring_makeLiteral ("true");
4898 case US_FBRANCH: return cstring_makeLiteral ("false");
4899 case US_CBRANCH: return cstring_makeLiteral ("case");
4900 case US_SWITCH: return cstring_makeLiteral ("switch");
4906 void usymtab_addMustAlias (sRef s, sRef al)
4909 if (sRef_isMeaningful (s) && sRef_isMeaningful (al)
4910 && !(sRef_isConst (s) || sRef_isConst (al))
4911 && !(sRef_isAddress (al) && sRef_isDirectParam (sRef_getBase (al)))
4912 && !(sRef_similar (s, al)))
4914 utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
4915 DPRINTF (("Must alias: %s", aliasTable_unparse (utab->aliases)));
4918 ** for local variable, aliasing is symmetric
4921 if (sRef_isLocalVar (s) && sRef_isLocalVar (al))
4923 utab->aliases = aliasTable_addMustAlias (utab->aliases, al, s);
4933 ** Same as usymtab_addMustAlias, except does not check sRef_isSimilar.
4936 void usymtab_addForceMustAlias (sRef s, sRef al)
4939 if (sRef_isMeaningful (s)
4940 && sRef_isMeaningful (al)
4941 && !(sRef_isConst (s) || sRef_isConst (al))
4942 && !(sRef_isAddress (al) && sRef_isDirectParam (sRef_getBase (al))))
4944 utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
4945 DPRINTF (("Must alias: %s", aliasTable_unparse (utab->aliases)));
4948 ** for local variable, aliasing is symmetric
4951 if (sRef_isLocalVar (s) && sRef_isLocalVar (al))
4953 utab->aliases = aliasTable_addMustAlias (utab->aliases, al, s);
4962 void usymtab_clearAlias (sRef s)
4963 /*@modifies utab, s@*/
4966 aliasTable_clearAliases (utab->aliases, s);
4969 sRefSet usymtab_allAliases (sRef s)
4972 if (sRef_isMeaningful (s))
4977 ret = sRefSet_unionFree (aliasTable_aliasedBy (utab->aliases, s),
4978 aliasTable_canAlias (utab->aliases, s));
4983 return sRefSet_undefined;
4987 /*@only@*/ sRefSet usymtab_canAlias (sRef s)
4990 if (sRef_isMeaningful (s))
4992 sRefSet res = aliasTable_canAlias (utab->aliases, s);
4997 return sRefSet_undefined;
5000 /*@only@*/ sRefSet usymtab_aliasedBy (sRef s)
5003 return (aliasTable_aliasedBy (utab->aliases, s));
5006 /*@only@*/ cstring usymtab_unparseAliases ()
5009 return (aliasTable_unparse (utab->aliases));
5013 ** Debugging routines:
5014 ** okay to leak storage here, only for debugging
5020 usymtab_printOut (void)
5026 char *ind = mstring_copy (" ");
5028 fprintf (g_msgstream, "<<< [symbol table] >>>\n");
5030 while (s != GLOBAL_ENV && s->env != GLOBAL_ENV)
5032 cstring tname = usymtab_typeName (s);
5036 ind[depth * 3 + 1] = '\0';
5039 fprintf (g_msgstream, "level: %d (%s)\n", s->lexlevel,
5040 cstring_toCharsSafe (tname));
5042 cstring_free (tname);
5044 for (i = 0; i < s->nentries; i++)
5046 cstring us = uentry_unparseFull (s->entries[i]);
5047 fprintf (g_msgstream, "%s\n", cstring_toCharsSafe (us));
5051 if (s->reftable != NULL && s->nentries > 0)
5053 fprintf (g_msgstream, "\t<< Ref table >>\n");
5055 for (i = 0; i < s->nentries; i++)
5057 fprintf (g_msgstream, "\t%s %3d: %d, %d\n", ind, i,
5058 s->reftable[i]->level,
5059 s->reftable[i]->index);
5063 ind[depth * 3 + 1] = ' ';
5067 fprintf (g_msgstream, "<<< end usymtab >>>\n");
5073 usymtab_printTypes ()
5074 /*@globals globtab@*/
5076 usymtab_printAllAux (globtab);
5080 usymtab_printAll (void)
5083 usymtab_printAllAux (utab);
5087 usymtab_printAllAux (usymtab s)
5088 /*@modifies g_msgstream@*/
5092 char *ind = mstring_copy (" ");
5094 printf ("[[[ usymtab ]]]");
5096 while (s != GLOBAL_ENV)
5099 ind[depth * 3 + 1] = '\0';
5101 if (s->env == GLOBAL_ENV)
5105 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5106 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5107 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5111 for (i = looplow; i < s->nentries; i++)
5113 printf ("%s%3d. %s\n", ind, i,
5114 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5119 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5120 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5121 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5123 for (i = 0; i < s->nentries; i++)
5125 printf ("%s%3d %s\n", ind, i,
5126 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5130 ind[depth * 3 + 1] = ' ';
5134 printf ("----------\n");
5138 usymtab_printComplete ()
5143 char *ind = mstring_copy (" ");
5146 while (s != GLOBAL_ENV)
5150 ind[depth * 3 + 1] = '\0';
5153 if (s->env == GLOBAL_ENV)
5157 printf ("level: %d\n", s->lexlevel);
5161 for (i = looplow; i < s->nentries; i++)
5163 printf ("%s%3d %s\n", ind, i,
5164 cstring_toCharsSafe (uentry_unparse (s->entries[i])));
5169 printf ("level: %d\n", s->lexlevel);
5170 for (i = 0; i < s->nentries; i++)
5172 printf ("%s%3d %s\n", ind, i,
5173 cstring_toCharsSafe (uentry_unparse (s->entries[i])));
5177 ind[depth * 3 + 1] = ' ';
5182 printf ("----------\n");
5186 static /*@only@*/ cstring /*@unused@*/
5187 usymtab_unparseLocalAux (/*@notnull@*/ usymtab s)
5189 cstring c = message ("lexlevel: %d\n", s->lexlevel);
5192 for (i = 0; i < s->nentries; i++)
5194 c = message ("%q\n%q", c, uentry_unparseFull (s->entries[i]));
5197 c = message ("%q\n=========", c);
5201 static cstring /*@unused@*/ /*@only@*/
5202 usymtab_unparseLocalList (/*@notnull@*/ usymtab s)
5204 cstring c = message ("[%d/%s/%s] ", s->lexlevel,
5205 bool_unparse (s->mustBreak),
5206 exitkind_unparse (s->exitCode));
5209 for (i = 0; i < s->nentries; i++)
5211 sRef sr = uentry_getSref (s->entries[i]);
5215 c = message ("%q: %q [%b]", c, uentry_getName (s->entries[i]),
5216 sRef_isStateDefined (sr));
5220 c = message ("%q, %q [%b]", c, uentry_getName (s->entries[i]),
5221 sRef_isStateDefined (sr));
5230 usymtab_printLocal (void)
5236 printf ("lexlevel: %d\n", s->lexlevel);
5238 for (i = 0; i < s->nentries; i++)
5240 printf ("%s\n", cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5243 while (s->lexlevel > 1)
5248 llassert (usymtab_isDefined (s));
5250 printf ("Params:\n");
5252 for (i = 0; i < s->nentries; i++)
5254 printf ("%d: %s\n", i,
5255 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5260 static bool checkDistinctExternalName (uentry e)
5261 /*@globals globtab@*/
5262 /*@modifies *g_msgstream@*/
5264 int checklen = context_getValue (FLG_EXTERNALNAMELEN);
5265 bool ignorecase = context_getFlag (FLG_EXTERNALNAMECASEINSENSITIVE);
5266 bool gotone = FALSE;
5267 bool extras = FALSE;
5268 bool hasError = FALSE;
5269 cstring name = uentry_rawName (e);
5270 usymtab st = globtab;
5278 if (uentry_isAnyTag (e))
5280 checklen++; /* the tag marker doesn't count */
5284 usymtab_entries (st, oe)
5286 if (uentry_sameObject (oe, e))
5293 if (cstring_equalCaseInsensitive (uentry_rawName (oe), name))
5302 (FLG_DISTINCTEXTERNALNAMES,
5304 ("External identifier %q is not distinguishable from %q "
5305 "because alphabetical case is ignored",
5307 uentry_getName (oe)),
5308 uentry_whereLast (e)))
5310 uentry_showWhereAny (oe);
5311 uentry_setHasNameError (oe);
5320 if (cstring_equalLenCaseInsensitive (uentry_rawName (oe),
5329 if (cstring_equalLen (uentry_rawName (oe), name, checklen))
5332 (FLG_DISTINCTEXTERNALNAMES,
5335 ("External identifier %q is not distinguishable from %q "
5336 "in the first %d characters (%q)",
5338 uentry_getName (oe),
5340 cstring_clip (uentry_getName (e), checklen)),
5342 uentry_whereLast (e)))
5344 uentry_showWhereAny (oe);
5345 uentry_setHasNameError (oe);
5358 (FLG_DISTINCTEXTERNALNAMES,
5360 ("External identifier %q is not distinguishable from %q "
5361 "in the first %d characters because alphabetical case "
5364 uentry_getName (oe),
5366 uentry_whereLast (e)))
5368 uentry_showWhereAny (oe);
5369 uentry_setHasNameError (oe);
5375 else if (cstring_equalLen (uentry_rawName (oe), name, checklen))
5384 (FLG_DISTINCTEXTERNALNAMES,
5387 ("External identifier %q is not distinguishable from %q "
5388 "in the first %d characters (%q)",
5390 uentry_getName (oe),
5392 cstring_clip (uentry_getName (e), checklen)),
5394 uentry_whereLast (e)))
5396 uentry_showWhereAny (oe);
5397 uentry_setHasNameError (oe);
5406 } end_usymtab_entries ;
5413 (cstring_makeLiteral ("One or more additional "
5414 "indistinguishable external "
5415 "names not reported"));
5421 static bool checkDistinctInternalName (uentry e)
5423 /*@modifies *g_msgstream@*/
5425 usymtab ttab = utab;
5426 cstring name = uentry_rawName (e);
5427 int numchars = context_getValue (FLG_INTERNALNAMELEN);
5428 bool caseinsensitive = context_getFlag (FLG_INTERNALNAMECASEINSENSITIVE);
5429 bool lookalike = context_getFlag (FLG_INTERNALNAMELOOKALIKE);
5431 if (uentry_isAnyTag (e) && (numchars != 0))
5433 numchars++; /* the tag marker doesn't count */
5436 while (usymtab_isDefined (ttab))
5438 usymtab_entries (ttab, oe)
5440 if (uentry_sameObject (oe, e))
5442 /*@innercontinue@*/ continue;
5445 switch (cstring_genericEqual
5446 (name, uentry_rawName (oe),
5447 numchars, caseinsensitive, lookalike))
5449 case CGE_DISTINCT: /* okay */
5453 if (cstring_equal (name, uentry_rawName (oe)))
5455 ; /* got a shadow error */
5460 (FLG_DISTINCTINTERNALNAMES,
5463 ("Internal identifier %q is not distinguishable from %q "
5464 "in the first %d characters (%q)",
5466 uentry_getName (oe),
5468 cstring_clip (uentry_getName (e), numchars)),
5470 uentry_whereLast (e)))
5472 uentry_showWhereAny (oe);
5473 uentry_setHasNameError (oe);
5481 || (cstring_length (name) <= numchars))
5484 (FLG_DISTINCTINTERNALNAMES,
5486 ("Internal identifier %q is not distinguishable from %q "
5487 "without case sensitivity",
5489 uentry_getName (oe)),
5490 uentry_whereLast (e)))
5492 uentry_showWhereAny (oe);
5493 uentry_setHasNameError (oe);
5500 (FLG_DISTINCTINTERNALNAMES,
5502 ("Internal identifier %q is not distinguishable from %q "
5503 "in the first %d characters without case sensitivity",
5505 uentry_getName (oe),
5507 uentry_whereLast (e)))
5509 uentry_showWhereAny (oe);
5510 uentry_setHasNameError (oe);
5518 || (cstring_length (name) <= numchars))
5521 (FLG_DISTINCTINTERNALNAMES,
5523 ("Internal identifier %q is not distinguishable from %q "
5524 "except by lookalike characters",
5526 uentry_getName (oe)),
5527 uentry_whereLast (e)))
5529 uentry_showWhereAny (oe);
5530 uentry_setHasNameError (oe);
5537 (FLG_DISTINCTINTERNALNAMES,
5539 ("Internal identifier %q is not distinguishable from %q "
5540 "in the first %d characters except by lookalike characters",
5542 uentry_getName (oe),
5544 uentry_whereLast (e)))
5546 uentry_showWhereAny (oe);
5547 uentry_setHasNameError (oe);
5552 } end_usymtab_entries ;
5560 void usymtab_checkDistinctName (uentry e, int scope)
5561 /*@globals utab, globtab@*/
5563 bool hasError = FALSE;
5564 fileloc where = uentry_whereLast (e);
5566 if (!fileloc_isPreproc (where) && !fileloc_isBuiltin (where))
5568 if (scope == globScope)
5570 if (context_getFlag (FLG_DISTINCTEXTERNALNAMES))
5572 hasError = checkDistinctExternalName (e);
5576 if (!hasError && context_getFlag (FLG_DISTINCTINTERNALNAMES))
5578 hasError = checkDistinctInternalName (e);
5584 uentry_setHasNameError (e);