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;
301 /*@i23@*/ return (u);
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;
328 /* evs 2000-07-24: bool is now treated as abstract (always) */
330 uentry boolentry = uentry_makeBoolDatatype (YES);
331 usymtab_supGlobalEntry (boolentry);
332 context_addBoolAccess ();
335 ** We supply values 0 and 1 for the constants, so things like
336 ** while (TRUE) can be interpreted correctly.
339 usymtab_supGlobalEntry
340 (uentry_makeConstantAux (context_getFalseName (), boolt,
341 fileloc_getBuiltin (), FALSE,
342 multiVal_makeInt (0)));
343 usymtab_supGlobalEntry
344 (uentry_makeConstantAux (context_getTrueName (), boolt,
345 fileloc_getBuiltin (), FALSE,
346 multiVal_makeInt (1)));
355 usymtab_grow (/*@notnull@*/ usymtab s)
358 o_uentry *oldsyms = s->entries;
360 s->nspace = CBASESIZE;
361 s->entries = (uentry *) dmalloc (sizeof (*s->entries)
362 * (s->nentries + s->nspace));
364 for (i = 0; i < s->nentries; i++)
366 s->entries[i] = oldsyms[i];
371 if (s->reftable != NULL)
373 refTable oldRefs = s->reftable;
375 s->reftable = (refentry *) dmalloc (sizeof (*s->reftable)
376 * (s->nentries + CBASESIZE + 1));
378 for (i = 0; i < s->nentries; i++)
380 s->reftable[i] = oldRefs[i];
391 usymtab_addEntryQuiet (/*@notnull@*/ usymtab s, /*@keep@*/ uentry e)
393 if (!(s->lexlevel > fileScope || !sRef_modInFunction ()))
395 if (uentry_isDatatype (e)
396 || uentry_isFunction (e)
397 || uentry_isAnyTag (e)
398 || uentry_isEnumConstant (e)
399 || context_inMacro ())
402 ** Not a bug. Code like,
403 ** int f (void) { typedef int tint; ... }
407 /* was nothing here! */
408 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
413 (cstring_makeLiteral ("Declaration outside function scope"));
415 llcontbug (message ("usymtab_addEntryQuiet: inconsistent state "
416 "(lexlevel = %d, modFunction = %s) adding: %q",
417 s->lexlevel, bool_unparse (sRef_modInFunction ()),
418 uentry_unparse (e)));
419 sRef_setGlobalScope ();
420 /* make sure the sRef is not bashed! */
421 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
431 s->entries[s->nentries] = e;
434 if (s == globtab || s == filetab)
436 if (!fileloc_isLib (g_currentloc))
438 uentry_tallyAnnots (e, AN_UNKNOWN);
443 if (s->htable != NULL)
445 hashTable_insert (s->htable, uentry_rawName (e), s->nentries);
451 static /*@observer@*/ uentry /*@alt void@*/
452 usymtab_addEntryBase (/*@notnull@*/ usymtab s, /*@only@*/ uentry e)
455 ** In theory, we shouldn't need this test because it this is
456 ** only called when a library is being read, and it shouldn't
457 ** ever have a duplicate entry. In practice, its safer to
458 ** leave it in, though.
463 if (uentry_isValid (old = usymtab_lookupQuiet (s, uentry_rawName (e))))
465 DPRINTF (("Duplicate entry: %s", uentry_unparse (e)));
466 uentry_free (e); /* duplicate */
471 int thisentry = s->nentries;
473 if (uentry_isVar (e))
475 uentry_setSref (e, sRef_makeCvar (globScope, thisentry,
476 uentry_getType (e)));
479 usymtab_addEntryQuiet (s, e);
485 usymtab_addEntryAux (/*@notnull@*/ usymtab st, /*@keep@*/ uentry e, bool isSref)
486 /*@globals globtab@*/
489 usymId thisentry = st->nentries;
491 llassert (!uentry_isElipsisMarker (e));
495 ** llassert (usymtab_lookupSafe (uentry_rawName (e)) == uentry_undefined);
498 llassertprint (uentry_isAnyTag (e) ? st == globtab : TRUE,
499 ("non-global tag: %s / %d", uentry_unparseFull (e), st->lexlevel));
501 if (st->lexlevel == fileScope
502 && (!(uentry_isStatic (e)) || uentry_isAnyTag (e)))
509 ctype ct = uentry_getType (e);
511 if (uentry_isFunction (e) && ctype_isFunction (ct))
513 ct = ctype_returnValue (ct);
516 if (uentry_isStatic (e))
518 sRef sr = sRef_makeCvar (st->lexlevel, thisentry, ct);
520 if (sRef_isStack (sr) || sRef_isLocalState (sr))
522 sRef_setAliasKind (sr, AK_STATIC, uentry_whereLast (e));
523 sRef_setDefined (sr, uentry_whereLast (e));
526 uentry_setSref (e, sr);
530 uentry_setSref (e, sRef_makeCvar (st->lexlevel, thisentry, ct));
535 if (uentry_isDatatype (e))
538 uentry_setDatatype (e, thisentry);
541 if (uentry_isFunction (e))
543 ctype ct = uentry_getType (e);
545 if (ctype_isFunction (ct)
546 && uentryList_isMissingParams (ctype_argsFunction (ct)))
548 if (uentry_isDeclared (e))
552 message ("Function %q declared without parameter list",
554 uentry_whereDeclared (e));
560 message ("Function %q specified without parameter list",
562 uentry_whereSpecified (e));
567 if (st == globtab && !uentry_isSpecified (e))
569 exprChecks_checkExport (e);
573 uentry_checkName (e);
575 usymtab_addEntryQuiet (st, e);
580 usymtab_addEntry (uentry e)
581 /*@globals utab, globtab@*/
582 /*@modifies utab, e@*/
585 llassertprint (!usymtab_exists (uentry_rawName (e)),
586 ("Entry already exists: %s", uentry_unparse (e)));
588 return usymtab_addEntryAux (utab, e, FALSE);
592 usymtab_addGlobalEntry (uentry e)
593 /*@modifies globtab, e@*/
595 DPRINTF (("Add global: %s / %s", uentry_unparse (e), bool_unparse (uentry_isForward (e))));
597 (void) usymtab_addEntryAux (globtab, e, FALSE);
601 ** supercede and replace entry use elements of entries array, and
602 ** assign an element to a new value, and then free the old value.
603 ** Need -deparrays to avoid errors for this.
609 usymtab_supEntryAux (/*@notnull@*/ usymtab st,
610 /*@only@*/ uentry e, bool isSref)
611 /*@globals globtab, filetab@*/
612 /*@modifies st, globtab, e@*/
614 cstring ename = uentry_rawName (e);
615 bool staticEntry = FALSE;
618 /* static tags in global scope */
619 if (st->lexlevel == fileScope
620 && (!(uentry_isStatic (e)) || uentry_isAnyTag (e)))
622 eindex = usymtab_getIndex (st, ename);
624 if (eindex != NOT_FOUND)
626 uentry ce = st->entries[eindex];
630 message ("%s %q shadows static declaration",
631 ekind_capName (uentry_getKind (e)),
633 uentry_whereDeclared (e)))
635 uentry_showWhereLast (ce);
638 if (eindex == st->nentries - 1)
644 st->entries[eindex] = st->entries[st->nentries - 1];
647 if (st->htable != NULL)
649 hashTable_replaceKey (st->htable, uentry_rawName (ce),
660 if (uentry_isStatic (e)) {
661 if (uentry_isFunction (e)) {
662 /* Static function declarations are at the file level, even if they are in a deeped scope. */
663 st = usymtab_getFileTab ();
666 if (!uentry_isAnyTag (e) && st == globtab)
668 st = usymtab_getFileTab ();
670 DPRINTF (("Static entry!"));
675 DPRINTF (("Using symtab: %s", usymtab_unparseLocalAux (st)));
677 eindex = usymtab_getIndex (st, ename);
679 if (eindex != NOT_FOUND)
681 uentry ce = st->entries[eindex];
683 DPRINTF (("Found entry: %s", uentry_unparse (ce)));
685 if (uentry_isPriv (ce)
686 /* || (fileloc_isImport (uentry_whereSpecified (ce))) */
687 || (uentry_isStatic (ce)
688 && uentry_isAnyTag (ce)
689 && (uentry_isDeclared (ce)
690 && !fileloc_sameFile (uentry_whereDefined (ce),
691 uentry_whereDefined (e)))))
695 ** if overloading import should do some checks!
698 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
700 st->entries[eindex] = e;
702 if (uentry_isDatatype (e))
704 uentry_setDatatype (e, eindex);
707 if (st == globtab && !uentry_isSpecified (e))
709 exprChecks_checkExport (e);
712 if (st->htable != NULL)
714 hashTable_replaceKey (st->htable, uentry_rawName (ce),
721 else if (uentry_isSpecified (ce))
723 if (uentry_isSpecified (e))
725 if (fileloc_isImport (uentry_whereSpecified (ce)))
728 if (st->htable != NULL)
730 hashTable_replaceKey (st->htable,
736 st->entries[eindex] = e;
739 if (uentry_isDatatype (e)) uentry_setDatatype (e, eindex);
743 if (fileloc_isImport (uentry_whereSpecified (e)))
749 /* respecification errors already reported */
751 if (uentry_isDatatype (e))
753 uentry_setDatatype (e, eindex);
756 if (st->htable != NULL)
758 hashTable_replaceKey (st->htable,
763 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
765 st->entries[eindex] = e;
770 else /* e not specified */
772 if (uentry_isDeclared (ce))
774 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
775 uentry_mergeDefinition (ce, e);
779 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
780 uentry_mergeEntries (ce, e);
784 else /* ce not specified */
786 if (!(st->lexlevel > fileScope || !sRef_modInFunction ()))
788 if (uentry_isDatatype (e) || uentry_isAnyTag (e)
789 || uentry_isEnumConstant (e))
792 ** Not a bug. Code like,
793 ** int f (void) { typedef int tint; ... }
799 llcontbug (message ("usymtab_supEntryAux: inconsistent state "
800 "(lexlevel = %d, modFunction = %s) adding: %q",
801 st->lexlevel, bool_unparse (sRef_modInFunction ()),
802 uentry_unparse (e)));
804 if (sRef_modInFunction ())
806 /* make sure the sRef is not bashed! */
807 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
812 uentry_mergeDefinition (ce, e);
817 ctype ct = uentry_getType (ce);
819 if (uentry_isFunction (ce) && ctype_isFunction (ct))
821 ct = ctype_returnValue (ct);
824 uentry_setSref (ce, sRef_makeCvar (st->lexlevel, eindex, ct));
827 else /* no previous entry */
831 if (st->lexlevel == globScope
832 && !uentry_isStatic (e)
833 && !uentry_isExtern (e)
834 && usymtab_isDefined (filetab))
837 ** check if there is a static entry: (i.e.,
844 eindex = usymtab_getIndex (filetab, ename);
846 if (eindex != NOT_FOUND)
848 uentry ce = filetab->entries[eindex];
850 uentry_setStatic (e);
851 uentry_mergeDefinition (ce, e);
857 outer = usymtab_lookupQuiet (st->env, ename);
860 ** no previous definition, add the new one
864 && uentry_isValid (outer)
865 && !(uentry_isYield (e) || uentry_isYield (outer))
866 && fileloc_isDefined (uentry_whereLast (e))
867 && fileloc_isDefined (uentry_whereLast (outer)))
869 if (!uentry_sameKind (outer, e))
875 if (ctype_isUnknown (uentry_getType (outer))
876 || uentry_isForward (outer))
884 message ("%s %q shadows outer declaration",
885 ekind_capName (uentry_getKind (e)),
887 uentry_whereLast (e)))
889 uentry_showWhereLast (outer);
895 if (st == globtab && context_getFlag (FLG_NEWDECL))
899 message ("New declaration: %q", uentry_getName (e)),
900 uentry_whereLast (e));
903 eindex = usymtab_addEntryAux (st, e, isSref);
907 return (staticEntry ? USYMIDINVALID : eindex);
912 usymtab_replaceEntryAux (/*@notnull@*/ usymtab st, /*@only@*/ uentry e)
913 /*@globals globtab@*/ /*@modifies st, e@*/
915 cstring ename = uentry_rawName (e);
918 /* static tags in global scope */
919 eindex = usymtab_getIndex (st, ename);
921 if (eindex != NOT_FOUND)
923 uentry ce = st->entries[eindex];
925 if (st->htable != NULL)
927 hashTable_replaceKey (st->htable, uentry_rawName (ce), uentry_rawName (e));
931 st->entries[eindex] = e;
935 eindex = usymtab_addEntryAux (st, e, FALSE);
942 void usymtab_supEntry (uentry e)
943 /*@globals utab, filetab, globtab@*/
944 /*@modifies utab, globtab, e@*/
946 (void) usymtab_supEntryAux (utab, e, FALSE);
950 ** this should be lots more efficient!
953 static /*@exposed@*/ uentry
954 usymtab_supEntryReturnAux (/*@notnull@*/ usymtab tab,
955 /*@only@*/ uentry e, bool isref)
956 /*@globals globtab, filetab@*/
957 /*@modifies tab, globtab, e@*/
959 cstring rawName = cstring_copy (uentry_rawName (e));
960 bool stat = (tab == globtab) && uentry_isStatic (e);
964 (void) usymtab_supEntryAux (tab, e, isref);
968 ret = usymtab_lookupAux (filetab, rawName);
972 ret = usymtab_lookupAux (tab, rawName);
974 if (uentry_isInvalid (ret) && usymtab_isDefined (filetab))
976 ret = usymtab_lookupAux (filetab, rawName);
980 cstring_free (rawName);
984 /*@dependent@*/ /*@exposed@*/ uentry
985 usymtab_supEntryReturn (/*@only@*/ uentry e)
986 /*@globals utab, filetab, globtab@*/
987 /*@modifies utab, globtab, e@*/
989 return (usymtab_supEntryReturnAux (utab, e, FALSE));
992 /*@dependent@*/ /*@exposed@*/ uentry
993 usymtab_supEntrySrefReturn (/*@only@*/ uentry e)
994 /*@globals utab, globtab, filetab@*/
995 /*@modifies utab, globtab, e@*/
997 return (usymtab_supEntryReturnAux (utab, e, TRUE));
1000 /*@dependent@*/ /*@exposed@*/ uentry
1001 usymtab_supGlobalEntryReturn (uentry e)
1002 /*@globals globtab, filetab@*/
1003 /*@modifies globtab, e@*/
1007 ret = usymtab_supEntryReturnAux (globtab, e, FALSE);
1009 if (sRef_modInFunction ())
1011 recordFunctionType (ret);
1018 usymtab_supTypeEntry (/*@only@*/ uentry e)
1019 /*@globals globtab, filetab@*/
1020 /*@modifies globtab, e@*/
1025 if (uentry_isAbstractDatatype (e))
1027 uid = usymtab_supAbstractTypeEntry (e, FALSE);
1028 ret = ctype_createAbstract (uid);
1032 uid = usymtab_supEntryAux (globtab, e, FALSE);
1033 ret = ctype_createUser (uid);
1036 if (sRef_modInFunction ())
1038 recordFunctionType (globtab->entries[uid]);
1045 usymtab_supReturnTypeEntry (/*@only@*/ uentry e)
1046 /*@globals globtab, filetab@*/
1047 /*@modifies globtab@*/
1051 if (uentry_isAbstractDatatype (e))
1053 uid = usymtab_supAbstractTypeEntry (e, FALSE);
1057 uid = usymtab_supEntryAux (globtab, e, FALSE);
1060 if (sRef_modInFunction ())
1062 recordFunctionType (globtab->entries[uid]);
1065 return (globtab->entries[uid]);
1069 usymtab_supAbstractTypeEntry (/*@only@*/ uentry e, bool dodef)
1070 /*@globals globtab, filetab@*/
1071 /*@modifies globtab, e@*/
1074 uid = usymtab_supEntryAux (globtab, e, FALSE);
1078 uentry ue = usymtab_getTypeEntry (uid);
1079 uentry_setDatatype (ue, uid);
1082 if (context_getFlag (FLG_ACCESSMODULE))
1084 context_addFileAccessType (uid);
1087 if (sRef_modInFunction ())
1089 recordFunctionType (globtab->entries[uid]);
1097 usymtab_supExposedTypeEntry (/*@only@*/ uentry e, bool dodef)
1098 /*@globals globtab, filetab@*/
1099 /*@modifies globtab, e@*/
1103 uid = usymtab_supEntryAux (globtab, e, FALSE);
1107 uentry ue = usymtab_getTypeEntry (uid);
1109 uentry_setDatatype (ue, uid);
1112 if (sRef_modInFunction ())
1114 recordFunctionType (globtab->entries[uid]);
1122 usymtab_supForwardTypeEntry (/*@only@*/ uentry e)
1123 /*@globals globtab, filetab@*/
1124 /*@modifies globtab, e@*/
1126 usymId uid = usymtab_supEntryAux (globtab, e, FALSE);
1127 uentry ue = usymtab_getTypeEntry (uid);
1129 uentry_setDatatype (ue, uid);
1131 if (sRef_modInFunction ())
1133 recordFunctionType (globtab->entries[uid]);
1136 return (uentry_getAbstractType (ue));
1140 usymtab_supEntrySref (uentry e)
1141 /*@globals utab, globtab, filetab@*/
1142 /*@modifies utab, globtab, e@*/
1144 sRef old = uentry_getSref (e);
1147 if (sRef_isType (old))
1149 uentry ue = usymtab_supEntryReturnAux (utab, e, TRUE);
1152 if (uentry_isValid (ue))
1154 sRef uref = uentry_getSref (ue);
1156 sRef_mergeStateQuiet (uref, old);
1157 sRef_clearDerived (uref);
1159 /*@noaccess uentry@*/
1161 else if (sRef_isKnown (old))
1163 usymtab_supEntry (e);
1167 (void) usymtab_supEntryAux (utab, e, TRUE);
1171 void usymtab_supGlobalEntry (/*@only@*/ uentry e)
1172 /*@globals globtab, filetab@*/
1173 /*@modifies globtab, filetab, e@*/
1177 DPRINTF (("Sup global entry: %s", uentry_unparse (e)));
1179 uid = usymtab_supEntryAux (globtab, e, FALSE);
1181 if (sRef_modInFunction ())
1183 recordFunctionType (globtab->entries[uid]);
1188 usymtab_supReturnFileEntry (/*@only@*/ uentry e)
1189 /*@globals filetab, globtab@*/
1190 /*@modifies filetab, globtab, e@*/
1192 llassert (filetab != usymtab_undefined);
1193 DPRINTF (("File entry: %s", uentry_unparse (e)));
1194 return (usymtab_supEntryReturnAux (filetab, e, FALSE));
1202 usymtab_inDeepScope () /*@globals utab@*/
1204 return (utab->lexlevel > paramsScope);
1208 usymtab_getIndex (/*@notnull@*/ usymtab s, cstring k)
1212 if (s->htable != NULL)
1214 i = hashTable_lookup (s->htable, k);
1220 for (i = 0; i < s->nentries; i++)
1222 uentry current = s->entries[i];
1224 if (!uentry_isUndefined (current)
1225 && cstring_equal (uentry_rawName (current), k))
1236 usymtab_fetchIndex (/*@notnull@*/ usymtab s, int i)
1238 llassert (i >= 0 && i < s->nentries);
1239 return (s->entries[i]);
1243 usymtab_getTypeId (cstring k) /*@globals globtab@*/
1245 usymId uid = usymtab_getIndex (globtab, k);
1247 if (uid == NOT_FOUND) return USYMIDINVALID;
1249 if (!(uentry_isDatatype (usymtab_getTypeEntry (uid)))) {
1250 return USYMIDINVALID;
1256 /*@dependent@*/ uentry
1257 usymtab_lookupStructTag (cstring k)
1259 cstring sname = makeStruct (k);
1260 uentry ue = usymtab_lookupGlob (sname);
1261 cstring_free (sname);
1265 /*@dependent@*/ uentry
1266 usymtab_lookupUnionTag (cstring k)
1268 cstring uname = makeUnion (k);
1269 uentry res = usymtab_lookupGlob (uname);
1271 cstring_free (uname);
1275 /*@dependent@*/ uentry
1276 usymtab_lookupEnumTag (cstring k)
1278 cstring ename = makeEnum (k);
1279 uentry res = usymtab_lookupGlob (ename);
1281 cstring_free (ename);
1286 usymtab_getId (cstring k) /*@globals globtab@*/
1288 usymId uid = usymtab_getIndex (globtab, k);
1291 if (uid == NOT_FOUND)
1293 return USYMIDINVALID;
1296 ue = usymtab_getGlobalEntry (uid);
1298 if (uentry_isPriv (ue))
1300 return USYMIDINVALID;
1306 static /*@exposed@*/ uentry
1307 usymtab_getEntryAux (/*@notnull@*/ usymtab s, usymId uid)
1309 llassert (uid != USYMIDINVALID);
1311 if (uid < 0 || uid >= s->nentries)
1313 llcontbug (message ("usymtab_getEntry: out of range: level = %d [%d]",
1315 return uentry_undefined;
1318 llassertprint (uentry_isValid (s->entries[uid]),
1319 ("entry undefined: %d", uid));
1321 return s->entries[uid];
1324 /*@dependent@*/ /*@observer@*/ uentry
1325 usymtab_getGlobalEntry (usymId uid)
1326 /*@globals utab, globtab@*/
1328 if (dbgfree) return (uentry_undefined);
1330 if (utab->lexlevel > paramsScope)
1332 /* need to do this the awkward way, since it could be in conditional scope */
1333 return (usymtab_lookupSafe (uentry_rawName (globtab->entries[uid])));
1337 return (globtab->entries[uid]);
1341 /*@dependent@*/ /*@exposed@*/ uentry
1342 usymtab_getTypeEntry (usymId uid)
1343 /*@globals globtab@*/
1347 if (uid >= 0 && uid < globtab->nentries)
1349 return (globtab->entries[uid]);
1353 return (uentry_undefined);
1358 llassert (uid >= 0 && uid < globtab->nentries);
1360 return (globtab->entries[uid]);
1368 /*@dependent@*/ /*@exposed@*/ uentry
1369 usymtab_getTypeEntrySafe (usymId uid)
1370 /*@globals globtab@*/
1372 if (uid < 0 || uid >= globtab->nentries)
1374 return uentry_undefined;
1377 return (globtab->entries[uid]);
1381 usymtab_isBoolType (usymId uid)
1382 /*@globals globtab@*/
1384 llassert (uid >= 0 && uid < globtab->nentries);
1386 return (cstring_equal (uentry_rawName (globtab->entries[uid]),
1387 context_getBoolName ()));
1391 usymtab_getTypeEntryName (usymId uid)
1392 /*@globals globtab@*/
1398 return (cstring_makeLiteral ("<freetype>"));
1401 ue = usymtab_getTypeEntry (uid);
1403 if (dbgload && !uentry_isValid (ue))
1405 return (message ("<missing type: %d>", uid));
1408 llassertprint (uentry_isValid (ue), ("type undefined: %d", uid));
1410 return (uentry_getName (ue));
1414 usymtab_rehash (/*@notnull@*/ usymtab s)
1418 if (s->htable != NULL)
1420 hashTable_free (s->htable);
1423 s->htable = hashTable_create (LLHASHSIZE);
1425 for (i = 0; i < s->nentries; i++)
1427 hashTable_insert (s->htable, uentry_rawName (s->entries[i]), i);
1432 ** superficial copy of usymtab
1434 ** DO copy spec entries
1437 static /*@only@*/ /*@notnull@*/ usymtab
1438 usymtab_shallowCopy (/*@notnull@*/ usymtab s) /*@*/
1440 usymtab copytab = usymtab_createRoot ();
1443 for (i = 0; i < s->nentries; i++)
1445 usymtab_addEntryBase (copytab, s->entries[i]);
1452 usymtab_shallowFree (/*@only@*/ /*@notnull@*/ usymtab s)
1454 aliasTable_free (s->aliases);
1455 refTable_free (s->reftable, s->nentries);
1457 /*@-compdestroy@*/ sfree (s); /*@=compdestroy@*/
1461 ** converts usymId from old table to sorted one
1465 usymtab_convertId (usymId uid)
1466 /*@globals oldtab, utab@*/
1472 llassert (usymtab_isDefined (oldtab));
1474 ue = usymtab_getEntryAux (oldtab, uid);
1476 llassertprint (uentry_isValid (ue), ("convertId: undefined: %d", uid));
1478 name = uentry_rawName (ue);
1480 ret = usymtab_getIndex (utab, name);
1482 llassertprint (ret != USYMIDINVALID, ("convertId: return is invalid"));
1488 usymtab_prepareDump (void)
1489 /*@globals oldtab, utab@*/
1490 /*@modifies oldtab, utab@*/
1492 llassert (usymtab_inGlobalScope ());
1494 llassert (oldtab == usymtab_undefined);
1496 oldtab = usymtab_shallowCopy (utab);
1499 alpha compare - make sure order is same on different platforms
1500 error messages appear in same order
1503 qsort (utab->entries, (size_t)utab->nentries,
1504 sizeof (*utab->entries), (int (*)(const void *, const void *)) uentry_xcomparealpha);
1506 usymtab_rehash (utab);
1510 usymtab_dump (FILE *fout)
1511 /*@globals utab, oldtab@*/
1514 bool neednl = FALSE;
1515 uentry lastentry = uentry_undefined;
1516 ekind lastekind = KINVALID;
1520 ** must call prepareDump first
1523 llassert (oldtab != usymtab_undefined);
1525 for (i = 0; i < utab->nentries; i++)
1527 uentry thisentry = utab->entries[i];
1528 ekind thisekind = uentry_getKind (thisentry);
1531 if (uentry_hasRealName (thisentry)) {
1532 if (thisekind != lastekind)
1536 check (fputc ('\n', fout) == (int) '\n');
1540 lastentry = uentry_undefined;
1541 fprintf (fout, "*%d (%s)\n", ekind_toInt (thisekind),
1542 cstring_toCharsSafe (ekind_capName (thisekind)));
1543 lastekind = thisekind;
1547 if (uentry_isInvalid (lastentry) || !uentry_equiv (lastentry, thisentry)
1548 || (linelen > (MAX_DUMP_LINE_LENGTH - (2 * MAX_NAME_LENGTH))))
1550 cstring cdump = uentry_dump (thisentry);
1552 lastentry = thisentry;
1555 check (fputc ('\n', fout) == (int) '\n');
1559 linelen += cstring_length (cdump);
1561 /* no new line here! */
1562 if (cstring_length (cdump) > 0)
1564 check (fputs (cstring_toCharsSafe (cdump), fout) != EOF);
1567 cstring_free (cdump);
1572 cstring cdump = uentry_rawName (thisentry);
1573 linelen += cstring_length (cdump);
1574 fprintf (fout, "#%s", cstring_toCharsSafe (cdump));
1581 check (fputc ('\n', fout) == (int) '\n');
1585 void usymtab_load (FILE *f)
1586 /*@globals utab, globtab@*/
1587 /*@modifies utab, *f@*/
1589 char *s = mstring_create (MAX_DUMP_LINE_LENGTH);
1591 ekind kind = KINVALID;
1592 fileloc loc = g_currentloc;
1598 llassert (utab == globtab);
1599 llassert (utab->nentries == 0);
1601 while (fgets (s, MAX_DUMP_LINE_LENGTH, f) != NULL
1604 ; /* ignore ;-comments */
1607 while (s != NULL && *s != ';')
1613 kind = ekind_fromInt (getInt (&s));
1621 (cstring_makeLiteral
1622 ("Library is in obsolete format. Use lclint +whichlib "
1623 "to see which library is being loaded."));
1626 ue = uentry_undump (kind, loc, &s);
1627 DPRINTF (("Load: %s", uentry_unparseFull (ue)));
1629 if (uentry_isValid (ue))
1631 ue = usymtab_addEntryBase (utab, ue);
1637 ** now, any other names are the same uentry
1640 while (*(s++) == '#')
1642 cstring name = cstring_fromCharsO (getWord (&s));
1643 uentry nue = uentry_nameCopy (name, ue);
1645 DPRINTF (("Name copy: %s", uentry_unparseFull (nue)));
1646 usymtab_addEntryBase (utab, nue);
1649 while ((c = *s) != '\0' && (c !='\n'))
1651 if (c != ' ' || c != '\t')
1653 llbuglit ("Junk in load file");
1660 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
1668 ** file scope for static variables
1672 usymtab_enterFile ()
1673 /*@globals utab, globtab, filetab@*/
1674 /*@modifies filetab@*/
1676 llassert (utab == globtab);
1681 usymtab_entries (globtab, ue)
1683 if (sRef_hasDerived (uentry_getSref (ue)))
1685 fprintf (g_msgstream, "Derived Global: %s\n", uentry_unparse (ue));
1686 fprintf (g_msgstream, "sRef: %s\n", sRef_unparseFull (ue->sref));
1688 } end_usymtab_entries ;
1692 usymtab_enterScope ();
1698 /*@globals utab, filetab@*/
1699 /*@modifies filetab, utab@*/
1702 llassert (utab->lexlevel == 1);
1704 usymtab_exitScope (exprNode_undefined);
1709 usymtab_enterScope ()
1710 /*@globals utab, globtab, filetab@*/
1713 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
1715 /* unconditional scope: optimize to avoid copy */
1716 t->aliases = aliasTable_copy (utab->aliases);
1719 llassert (usymtab_isDefined (t->env));
1721 if (t->env->lexlevel == paramsScope && context_inFunctionLike ())
1723 noshadowerror = TRUE;
1724 usymtab_handleParams ();
1725 noshadowerror = FALSE;
1730 ** setup external references:
1731 ** o only, unique params alias external args
1732 ** o other params may alias anything of their type
1736 usymtab_handleParams (void)
1737 /*@globals utab, globtab, filetab@*/
1738 /*@modifies utab, globtab@*/
1740 usymtab ptab = utab->env;
1741 uentry fcn = context_getHeader ();
1744 usymtab_entries (ptab, param)
1748 if (!uentry_isYield (param))
1751 sRef pref = uentry_getSref (param);
1753 llassertprint (uentry_isAnyParam (param),
1755 uentry_unparseFull (param)));
1758 ue = uentry_makeVariable (fixParamName (uentry_rawName (param)),
1759 uentry_getType (param),
1760 fileloc_copy (uentry_whereDeclared (param)),
1763 uentry_copyState (ue, param);
1764 uentry_setRefParam (ue);
1766 ue = usymtab_supEntrySrefReturn (ue);
1768 /* must be after supercede! */
1770 if (!sRef_stateKnown (pref))
1772 uentry_setDefState (ue, SS_DEFINED);
1773 uentry_setDefState (param, SS_DEFINED);
1777 if (sRef_isStateSpecial (pref))
1779 uentry_setDefState (ue, SS_ALLOCATED);
1783 uentry_setDefState (ue, sRef_getDefState (pref));
1787 uref = uentry_getSref (ue);
1789 if (sRef_isStack (uref))
1791 alkind pkind = sRef_getAliasKind (pref);
1793 if (alkind_isKnown (pkind) && !alkind_isLocal (pkind)
1794 && !alkind_isStack (pkind))
1796 sRef_setAliasKind (uref, pkind, fileloc_undefined);
1797 sRef_setOrigAliasKind (uref, pkind);
1801 sRef_setAliasKind (uref, AK_IMPTEMP, fileloc_undefined);
1802 sRef_setOrigAliasKind (uref, AK_IMPTEMP);
1804 if (uentry_isOut (param))
1810 sRef_setDefined (uref, fileloc_undefined);
1816 usymtab_addMustAlias (uref, pref);
1818 if (!(uentry_isOnly (param) || uentry_isUnique (param)))
1820 sRef s = sRef_makeExternal (uref);
1822 usymtab_addMustAlias (uref, s);
1825 if (sRef_isKillRef (pref))
1827 sRef_setAliasKind (uref, AK_NEWREF, fileloc_undefined);
1828 sRef_setOrigAliasKind (uref, AK_KILLREF);
1830 else if (sRef_isRefCounted (uref))
1832 sRef_setOrigAliasKind (uref, AK_REFCOUNTED);
1837 sRef_setOrigAliasKind (uref, AK_LOCAL);
1843 } end_usymtab_entries;
1846 if (uentry_hasSpecialClauses (fcn))
1848 specialClauses clauses = uentry_getSpecialClauses (fcn);
1850 specialClauses_preElements (clauses, cl)
1852 sRefSet refs = specialClause_getRefs (cl);
1853 sRefMod modf = specialClause_getEntryFunction (cl);
1856 sRefSet_elements (refs, el)
1858 sRef base = sRef_getRootBase (el);
1860 if (sRef_isResult (base))
1862 ; /* nothing to do before */
1864 else if (sRef_isParam (base))
1868 sRef sb = sRef_updateSref (el);
1869 sRefSet aliases = usymtab_allAliases (sb);
1871 modf (sb, fileloc_undefined);
1873 sRefSet_elements (aliases, sr)
1875 modf (sr, fileloc_undefined);
1876 } end_sRefSet_elements ;
1878 sRefSet_free (aliases);
1883 if (sRef_isValid (base))
1888 } end_sRefSet_elements ;
1889 } end_specialClauses_preElements ;
1894 usymtab_enterFunctionScope (uentry fcn)
1895 /*@globals utab, filetab, globtab@*/
1898 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
1900 if (utab->lexlevel != fileScope)
1902 if (utab->lexlevel > fileScope)
1904 llparseerror (cstring_makeLiteral ("New function scope inside function."));
1906 while (utab->lexlevel > fileScope)
1908 /*@i@*/ utab = usymtab_dropEnv (utab);
1915 llfatalbug (cstring_makeLiteral ("New function not inside file."));
1917 /*@-branchstate@*/ } /*@=branchstate@*/
1919 globSet_allElements (uentry_getGlobs (fcn), el)
1922 if (sRef_isUndefGlob (el))
1924 int index = sRef_getScopeIndex (el);
1925 sRef sr = sRef_updateSref (el);
1926 fileloc loc = uentry_whereEarliest (fcn);
1928 if (sRef_isFileStatic (el))
1930 ctype ct = sRef_getType (el);
1933 llassert (usymtab_isDefined (filetab));
1935 ue = usymtab_fetchIndex (filetab, index);
1937 if (ctype_isRealArray (ct) || ctype_isRealSU (ct))
1939 sRef_setAllocated (sr, loc);
1943 sRef_setUndefined (sr, loc);
1948 uentry ue = globtab->entries[index];
1949 ctype ct = uentry_getType (ue);
1951 if (ctype_isArray (ct) || ctype_isSU (ct))
1953 sRef_setAllocated (sr, loc);
1957 sRef_setUndefined (sr, loc);
1961 else if (sRef_isAllocated (el))
1963 sRef sr = sRef_updateSref (el);
1964 fileloc loc = uentry_whereEarliest (fcn);
1966 sRef_setAllocated (sr, loc);
1968 else if (sRef_isPartial (el))
1970 sRef sr = sRef_updateSref (el);
1971 fileloc loc = uentry_whereEarliest (fcn);
1973 sRef_setPartial (sr, loc);
1979 } end_globSet_allElements;
1985 usymtab_caseBranch (void)
1988 usymtab t = usymtab_create (US_CBRANCH, utab, FALSE);
1993 usymtab_switchBranch (/*@unused@*/ exprNode s)
1996 usymtab t = usymtab_create (US_SWITCH, utab, FALSE);
1998 t->aliases = aliasTable_copy (utab->aliases);
2003 usymtab_trueBranch (/*@only@*/ guardSet guards)
2006 usymtab t = usymtab_create (US_TBRANCH, utab, FALSE);
2009 ** not true! (could be in a macro)
2011 ** llassertprint (utab->lexlevel > paramsScope,
2012 ** ("not in scope: %s", usymtab_unparseLocal ()));
2016 guardSet_free (t->guards);
2019 aliasTable_free (t->aliases);
2020 t->aliases = aliasTable_copy (utab->aliases);
2028 ** { int a; if (...) a = 3; < a may be undefined here!
2033 usymtab_popTrueBranch (exprNode pred, exprNode expr, clause cl)
2036 ** add a false branch
2037 ** (could be done more efficiently as a special case, but
2038 ** it is better to only maintain one version of the code)
2041 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2042 usymtab_popBranches (pred, expr, exprNode_undefined, TRUE, cl);
2046 usymtab_popCaseBranch () /*@modifies utab@*/
2048 llassert (utab->kind == US_CBRANCH);
2049 usymtab_quietPlainExitScope ();
2053 usymtab_popTrueExecBranch (exprNode pred, exprNode expr, clause cl)
2056 ** add a false branch that must return --- that is,
2057 ** the true branch is always executed!
2060 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2061 usymtab_popBranches (pred, expr, exprNode_makeMustExit (), FALSE, cl);
2065 usymtab_popOrBranch (exprNode pred, exprNode expr)
2069 usymtab env = utab->env;
2070 usymtab otab = utab;
2073 llassert (env != NULL);
2075 if (exprNode_isError (expr))
2081 mustReturn = exprNode_mustEscape (expr);
2085 llassert (utab->kind == US_TBRANCH);
2088 ** merge each entry in table with its original
2089 ** unless execution cannot continue after this branch
2092 for (i = 0; i < utab->nentries; i++)
2094 uentry current = utab->entries[i];
2095 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2097 uentry_mergeState (old, current, exprNode_loc (expr),
2098 mustReturn, FALSE, TRUE, ORCLAUSE);
2104 env->guards = guardSet_levelUnionFree (env->guards,
2105 guardSet_invert (exprNode_getGuards (pred)),
2110 env->aliases = aliasTable_levelUnion (env->aliases, otab->aliases, env->lexlevel);
2113 /* env is now utab */
2114 usymtab_quietPlainExitScope ();
2118 ** case syntax in C is very unrestricted. This is unfortunate.
2120 ** A switch case is ended either by a new case or default, or
2121 ** a close } that may close the switch or some other control
2126 usymtab_newCase (/*@unused@*/ exprNode pred, exprNode last)
2129 bool mustBreak = usymtab_mustBreak (utab);
2130 bool mustReturn = usymtab_mustEscape (utab);
2131 usymtab stab = utab;
2134 ** Find last case (or outer switch)
2137 while (stab->kind != US_CBRANCH && stab->kind != US_SWITCH)
2140 llassert (stab != GLOBAL_ENV);
2145 while (stab->kind == US_CBRANCH)
2148 llassert (stab != GLOBAL_ENV);
2152 ** if its a fall through case, merge in outside entries and last case.
2157 ** case 1: x = 3; <fall through>
2158 ** case 2: << x may not be defined
2162 if (!mustBreak && !mustReturn && utab->kind == US_CBRANCH)
2164 llassert (stab->kind == US_SWITCH || stab->kind == US_NORMAL);
2166 usymtab_entries (utab, ue) /* but, keep track of used variables */
2168 uentry old = usymtab_lookupAux (stab, uentry_rawName (ue));
2170 llassert (uentry_isValid (old));
2172 /* modifies ue, not old */
2174 uentry_mergeState (ue, old, exprNode_loc (last),
2175 FALSE, FALSE, TRUE, CASECLAUSE);
2176 } end_usymtab_entries;
2178 utab->aliases = aliasTable_levelUnion (utab->aliases,
2179 stab->aliases, utab->lexlevel);
2182 ** No need for a new branch.
2189 usymtab_caseBranch ();
2190 /*@-mustfree@*/ /*< utab->aliases >*/
2191 utab->aliases = aliasTable_copy (stab->aliases);
2199 ** for && (both pred and expr are executed)
2203 usymtab_popAndBranch (exprNode pred, /*@unused@*/ exprNode expr)
2206 usymtab env = utab->env;
2210 llassert (utab->kind == US_TBRANCH);
2213 ** merge each entry in table with its original
2214 ** unless execution cannot continue after this branch
2217 for (i = 0; i < utab->nentries; i++)
2219 uentry current = utab->entries[i];
2220 sRef tref = uentry_getSref (current);
2221 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2222 sRef oref = uentry_getSref (old);
2224 /* note that is current is in a nested branch,
2225 it may create a "new" old entry. */
2227 llassert (uentry_isValid (old));
2228 uentry_mergeState (old, current, exprNode_loc (expr),
2229 FALSE, FALSE, TRUE, ANDCLAUSE);
2232 ** if is it defined by the second clause, then it should be defined.
2235 if (sRef_isAnyDefined (tref)
2236 && (sRef_isAllocated (oref) || sRef_isStateUndefined (oref)))
2238 sRef_setDefined (oref, g_currentloc);
2242 utab->guards = guardSet_levelUnionFree (utab->guards,
2243 guardSet_invert (exprNode_getGuards (pred)),
2245 utab->aliases = aliasTable_levelUnion (utab->aliases, otab->aliases, utab->lexlevel);
2247 usymtab_quietPlainExitScope ();
2252 ** Stack should be [ US_CBRANCH+ US_SWITCH ]
2253 ** Only branches which do not return (except possibly the last branch) are included.
2255 ** Conditionally merge state from all CBRANCHes.
2257 ** If allpaths is TRUE, then all possible executions go through some switch
2258 ** case, and the original scope is not merged.
2262 usymtab_exitSwitch (/*@unused@*/ exprNode sw, bool allpaths)
2265 usymtab ttab = utab;
2266 usymtab stab = ttab;
2267 usymtab ltab = ttab;
2268 bool lastMustReturn = usymtab_mustEscape (utab);
2272 while (stab->kind == US_CBRANCH)
2275 llassert (stab != GLOBAL_ENV);
2278 while (stab->kind == US_NORMAL)
2281 llassert (stab != GLOBAL_ENV);
2284 llassert (stab->kind == US_SWITCH);
2286 /* go to the scope outside the switch (US_SWITCH is just a marker! */
2288 llassert (stab != GLOBAL_ENV);
2292 llassert (usymtab_isDefined (ttab));
2294 if (ttab->kind == US_CBRANCH)
2296 /* was quietPlainExitScope --- but, can't free it yet! */
2298 llassert (utab != GLOBAL_ENV);
2300 while (ttab->kind == US_CBRANCH)
2303 ** (from popTrueBranch)
2306 bool mustReturn = usymtab_mustEscape (ttab);
2307 bool mustBreak = usymtab_mustBreak (ttab);
2309 usymtab_entries (ttab, current)
2311 uentry old = /*@-compmempass@*/ usymtab_lookupAux (ltab, uentry_rawName (current));
2315 ** note that is this is in a nested branch,
2316 ** it may create a "new" old entry.
2319 if (uentry_isValid (old))
2323 uentry_mergeUses (current, old);
2324 uentry_setState (old, current);
2328 uentry_mergeState (old, current, exprNode_loc (sw),
2329 mustReturn, FALSE, TRUE, SWITCHCLAUSE);
2336 } end_usymtab_entries;
2339 ** if entry is not in symbol table for this case, merge with pre-switch
2343 if (!mustReturn && !mustBreak)
2345 usymtab_entries (stab, current)
2347 if (usymtab_getIndex (ttab, uentry_rawName (current)) == NOT_FOUND)
2349 uentry old = /*@-compmempass@*/
2350 usymtab_lookupAux (ltab, uentry_rawName (current));
2353 llassert (uentry_isValid (old));
2354 uentry_mergeState (old, current, exprNode_loc (sw),
2355 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2357 } end_usymtab_entries;
2360 ltab->env = ttab->env;
2364 ** Suprious error, becuase of environments.
2367 /*@i1@*/ utab = ltab;
2369 lastMustReturn = FALSE;
2376 ** now, there is one US_CBRANCH. Merge this with the stab.
2380 for (i = 0; i < ltab->nentries; i++)
2382 uentry current = ltab->entries[i];
2383 uentry old = usymtab_lookupAux (stab, uentry_rawName (current));
2385 /* note that is this is in a nested branch,
2386 it may create a "new" old entry. */
2389 if (uentry_isValid (old))
2393 uentry_mergeUses (current, old);
2394 uentry_setState (old, current);
2398 uentry_mergeState (old, current, exprNode_loc (sw),
2399 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2413 ** switch may or may not be followed by a new scope
2416 if (utab->kind == US_SWITCH)
2418 usymtab_quietPlainExitScope ();
2422 usymtab_quietPlainExitScope ();
2423 llassert (utab->kind == US_SWITCH);
2424 usymtab_quietPlainExitScope ();
2430 updateNullState (sRef el, /*@notnull@*/ usymtab ttab,
2431 /*@notnull@*/ usymtab ftab, bool trueGuard)
2433 sRef base = sRef_getRootBase (el);
2434 int level = sRef_lexLevel (base);
2438 if (sRef_isCvar (base))
2440 usymId index = sRef_getScopeIndex (base);
2441 uentry ue = usymtab_getRefTab (ttab, level, index);
2443 if (!uentry_isLset (ue))
2445 sRef sr = uentry_getSref (ue);
2449 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2453 if (!guardSet_isGuarded (ttab->guards, el)
2454 && !sRef_isNotNull (sr))
2456 sRef_setDerivNullState (sr, el, NS_DEFNULL);
2464 ue = usymtab_getRefTab (ftab, level, index);
2466 if (!uentry_isLset (ue))
2468 sRef sr = uentry_getSref (ue);
2471 if (!trueGuard) /* yikes! forgot the ! */
2473 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2478 if (!guardSet_isGuarded (ftab->guards, el)
2479 && !sRef_isNotNull (sr))
2481 sRef_setDerivNullState (sr, el, NS_DEFNULL);
2494 usymtab_popBranches (exprNode pred, exprNode tbranch, exprNode fbranch,
2495 bool isOpt, clause cl)
2499 usymtab ftab = utab;
2500 usymtab ttab = utab->env;
2504 guardSet guards = exprNode_getGuards (pred);
2505 sRefSet tguards = guardSet_getTrueGuards (guards);
2506 sRefSet fguards = guardSet_getFalseGuards (guards);
2507 bool mustReturnT = exprNode_mustEscape (tbranch);
2508 bool mustReturnF = exprNode_mustEscape (fbranch);
2510 if (exprNode_isDefined (fbranch))
2512 loc = exprNode_loc (fbranch);
2516 loc = exprNode_loc (tbranch);
2519 llassert (usymtab_isDefined (ttab));
2523 llassert (usymtab_isDefined (env));
2524 llassert (ftab->kind == US_FBRANCH);
2525 llassert (ttab->kind == US_TBRANCH);
2528 ** For each element that is true guarded (i.e., if (x != NULL))
2529 ** make x = null in false branch,
2530 ** and x = notnull in true branch.
2531 ** unless x was set locally in that branch.
2532 ** For each element that is false guarded (x == NULL)
2533 ** make x = null in true, notnull in false.
2535 ** For each element that is either guarded (pred(x))
2539 sRefSet_allElements (tguards, el)
2541 updateNullState (el, ttab, ftab, TRUE);
2542 } end_sRefSet_allElements;
2544 sRefSet_allElements (fguards, el)
2546 updateNullState (el, ttab, ftab, FALSE);
2547 } end_sRefSet_allElements;
2551 ** if an entry is in both true and false, merge the entries,
2552 ** then replace original with new state.
2554 ** if an entry is in one table, merge it with the original.
2557 for (i = 0; i < ftab->nentries; i++)
2559 uentry fthis = ftab->entries[i];
2560 uentry old = usymtab_lookupAux (env, uentry_rawName (fthis));
2561 int tindex = usymtab_getIndex (ttab, uentry_rawName (fthis));
2563 if (uentry_isUndefined (old))
2565 /* possible entry was added as an undefined id */
2569 if (tindex != NOT_FOUND)
2571 uentry tthis = ttab->entries[tindex];
2573 /* note that is this is in a nested branch,
2574 it may create a "new" old entry. */
2581 uentry_mergeState (fthis, tthis, loc,
2582 mustReturnT, FALSE, FALSE, cl);
2586 uentry_mergeUses (fthis, tthis);
2589 uentry_setState (old, fthis);
2596 uentry_setState (old, tthis);
2597 uentry_mergeState (old, fthis, loc, mustReturnF,
2601 ttab->entries[tindex] = uentry_undefined;
2602 uentry_free (tthis);
2606 uentry_mergeState (old, fthis, loc, mustReturnF, TRUE, FALSE, cl);
2610 for (i = 0; i < ttab->nentries; i++)
2612 uentry current = ttab->entries[i];
2614 if (!uentry_isUndefined (current))
2616 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2618 llassertprint (!uentry_isUndefined (old), ("name: <%s>",
2619 uentry_rawName (current)));
2622 uentry_mergeUses (current, old);
2623 uentry_setState (old, current);
2628 ** assumes false branch is a fall-through if
2629 ** fbranch is not defined. This is true, unless
2630 ** where was some greivous error in processing
2631 ** the else branch of an if-then, in which case
2632 ** this is probably the right thing to do anyway.
2635 uentry_mergeState (old, current, loc, mustReturnT,
2643 ** Plain levelUnion doesn't work, since we need to use the sRef's in env->aliases
2644 ** if they are present.
2647 llassert (NOALIAS (env->aliases, ttab->aliases));
2648 llassert (NOALIAS (env->aliases, ftab->aliases));
2650 aliasTable_free (env->aliases);
2652 env->aliases = aliasTable_levelUnionNew (ttab->aliases,
2653 ftab->aliases, env->lexlevel);
2655 aliasTable_fixSrefs (env->aliases);
2657 /* exit true and false scopes */
2658 usymtab_quietPlainExitScope ();
2659 usymtab_quietPlainExitScope ();
2663 utab->guards = guardSet_levelUnionFree
2665 guardSet_invert (exprNode_getGuards (pred)),
2671 utab->guards = guardSet_levelUnion (utab->guards,
2672 exprNode_getGuards (pred),
2676 DPRINTF (("Here."));
2679 static void usymtab_fixCases (void) /*@modifies utab@*/ {
2680 while (utab->kind == US_CBRANCH)
2682 usymtab_quietPlainExitScope ();
2685 llassert (utab->kind != US_CBRANCH);
2689 usymtab_altBranch (/*@only@*/ guardSet guards)
2692 usymtab t = usymtab_create (US_FBRANCH, utab, FALSE);
2693 usymtab parent = utab->env;
2696 ** If we are in a case, need to close it. The C syntax
2697 ** is very liberal, so this kludge is necessary.
2700 usymtab_fixCases ();
2702 DPRINTF (("Current kind: %s", usymtab_unparseStack ()));
2703 llassert (utab->kind == US_TBRANCH);
2704 llassert (parent != GLOBAL_ENV);
2706 guardSet_free (t->guards);
2709 aliasTable_free (t->aliases);
2710 t->aliases = aliasTable_copy (parent->aliases);
2716 usymtab_allDefined (void)
2717 /*@globals utab, globtab@*/
2721 llassert (utab == globtab);
2723 for (i = 0; i < utab->nentries; i++)
2725 uentry e = utab->entries[i];
2727 if (uentry_isPriv (e))
2729 ; /* no need to define it */
2733 if (context_getFlag (FLG_SPECUNDECL))
2735 fileloc sloc = uentry_whereSpecified (e);
2736 fileloc dloc = uentry_whereDeclared (e);
2738 if (fileloc_isDefined (sloc)
2739 && !uentry_isFakeTag (e)
2740 && !fileloc_isDefined (dloc))
2744 message ("%s %q specified but not declared",
2745 ekind_capName (uentry_getKind (e)),
2746 uentry_getName (e)),
2751 if (!uentry_isCodeDefined (e))
2753 fileloc dloc = uentry_whereDeclared (e);
2755 if (fileloc_isLib (dloc))
2759 else if (fileloc_isDefined (dloc))
2761 if (!uentry_isAnyTag (e))
2763 if (fileloc_isUser (dloc))
2767 message ("%s %q declared but not defined",
2768 ekind_capName (uentry_getKind (e)),
2769 uentry_getName (e)),
2776 fileloc sloc = uentry_whereSpecified (e);
2778 if (fileloc_isDefined (sloc)
2779 && !fileloc_isImport (sloc)
2780 && !fileloc_isLib (sloc)
2781 && !fileloc_isPreproc (sloc)
2782 && !uentry_isFakeTag (e))
2784 if (uentry_isVariable (e) || uentry_isFunction (e))
2788 message ("%s %q specified but not declared or defined",
2789 ekind_capName (uentry_getKind (e)),
2790 uentry_getName (e)),
2797 message ("%s %q specified but not defined",
2798 ekind_capName (uentry_getKind (e)),
2799 uentry_getName (e)),
2809 void usymtab_exportHeader (void)
2814 for (i = 0; i < utab->nentries; i++)
2816 uentry ce = utab->entries[i];
2818 if (!uentry_isDatatype (ce)
2819 && !uentry_isAnyTag (ce)
2820 && !uentry_isEitherConstant (ce) && !uentry_isStatic (ce)
2821 && !uentry_isExternal (ce)
2822 && !uentry_isForward (ce))
2824 fileloc fwhere = uentry_whereDeclared (ce);
2826 if (fileloc_isUndefined (fwhere)
2827 && uentry_isFunction (ce))
2829 fwhere = uentry_whereDefined (ce);
2832 if (fileloc_isDefined (fwhere)
2833 && !fileloc_isHeader (fwhere)
2834 && !(fileloc_isSpecialFile (fwhere)
2835 && !context_getFlag (FLG_UNUSEDSPECIAL)))
2837 if (uentry_isVariable (ce))
2840 (FLG_EXPORTHEADERVAR,
2841 message ("%s %q exported but not declared in header file",
2842 ekind_capName (uentry_getKind (ce)),
2843 uentry_getName (ce)),
2846 uentry_showDefSpecInfo (ce, fwhere);
2851 if (!uentry_isIter (ce)
2852 && !uentry_isEndIter (ce)
2853 && !uentry_isExpandedMacro (ce))
2855 if (uentry_isFunction (ce)
2856 && cstring_equalLit (uentry_rawName (ce), "main"))
2858 ; /* no error for main */
2864 message ("%s %q exported but not declared "
2866 ekind_capName (uentry_getKind (ce)),
2867 uentry_getName (ce)),
2870 uentry_showDefSpecInfo (ce, fwhere);
2880 void usymtab_exportLocal (void)
2886 for (i = 0; i < utab->nentries; i++)
2888 uentry ce = utab->entries[i];
2891 if (!uentry_isDatatype (ce) && !uentry_isAnyTag (ce)
2892 && !uentry_isEitherConstant (ce)
2893 && !uentry_isIter (ce)
2894 && !uentry_isEndIter (ce)
2895 && !uentry_isExpandedMacro (ce)
2896 && uentry_isUsed (ce))
2898 /* check static uses */
2899 filelocList fuses = uentry_getUses (ce);
2900 fileloc mod = uentry_whereDefined (ce);
2901 bool ok = filelocList_isEmpty (fuses);
2902 fileloc fwhere = uentry_whereDeclared (ce);
2904 if (fileloc_isSpecialFile (fwhere)
2905 && !context_getFlag (FLG_UNUSEDSPECIAL))
2907 ok = TRUE; /* no errors for special files */
2911 filelocList_elements (fuses, uloc)
2913 if (fileloc_isUndefined (uloc) || !fileloc_sameModule (uloc, mod))
2916 /*@innerbreak@*/ break;
2918 } end_filelocList_elements;
2925 message ("%s exported but not used outside %s: %q",
2926 ekind_capName (uentry_getKind (ce)),
2927 fileloc_getBase (mod),
2928 uentry_getName (ce)),
2931 uentry_showDefSpecInfo (ce, fwhere);
2939 usymtab_allUsed (void)
2943 bool isFileStatic = usymtab_inFileScope ();
2944 cstring last_file = cstring_undefined;
2946 for (i = 0; i < utab->nentries; i++)
2948 bool hasError = FALSE;
2949 uentry ce = utab->entries[i];
2950 fileloc fwhere = uentry_whereDeclared (ce);
2952 if (fileloc_isUndefined (fwhere))
2954 fwhere = uentry_whereDefined (ce);
2957 if (fileloc_isInvalid (fwhere)
2958 || fileloc_isLib (fwhere)
2959 || fileloc_isBuiltin (fwhere)
2960 || ((fileloc_isSpecialFile (fwhere)
2961 || fileloc_isSpecialFile (uentry_whereDefined (ce)))
2962 && !context_getFlag (FLG_UNUSEDSPECIAL)))
2966 else if (!uentry_wasUsed (ce) && !uentry_isAnyTag (ce))
2968 cstring fname = fileloc_filename (fwhere);
2970 if (cstring_isUndefined (last_file))
2974 else if (cstring_equal (fname, last_file))
2983 if (uentry_isParam (ce))
2985 if (context_inMacro ())
2987 sRef cref = uentry_getSref (ce);
2989 if (uentry_isYield (ce))
2991 ; /* no checks (for now) */
2993 else if (sRef_isSafe (cref))
2999 if (uentry_hasRealName (ce))
3002 optgenerror (FLG_MACROPARAMS,
3003 message ("Macro parameter %q not used",
3004 uentry_getName (ce)),
3011 if (cstring_equalFree (uentry_getName (ce),
3012 cstring_makeLiteral ("...")))
3018 hasError = optgenerror (FLG_PARAMUNUSED,
3019 message ("Parameter %q not used",
3020 uentry_getName (ce)),
3025 else if (uentry_isFunction (ce) || uentry_isIter (ce))
3027 if (fileloc_isUser (fwhere))
3029 hasError = optgenerror
3031 message ("%q %q declared but not used",
3033 (uentry_isIter (ce) ? "Iterator"
3034 : (isFileStatic ? "File static function" : "Function")),
3035 uentry_getName (ce)),
3039 else if (uentry_isEndIter (ce))
3041 ; /* no error (already reported for iter */
3043 else if (uentry_isEnumConstant (ce))
3045 if (fileloc_isUser (fwhere))
3047 hasError = optgenerror
3049 message ("Enum member %q not used",
3050 uentry_getName (ce)),
3054 else if (uentry_isConstant (ce))
3056 if (fileloc_isUser (fwhere))
3058 hasError = optgenerror
3060 message ("Constant %q declared but not used",
3061 uentry_getName (ce)),
3065 else if (uentry_isDatatype (ce))
3067 if (fileloc_isUser (fwhere))
3069 hasError = optgenerror
3071 message ("Type %q declared but not used",
3072 uentry_getName (ce)),
3076 else if (!uentry_isRefParam (ce) && !uentry_isExpandedMacro (ce))
3077 { /* errors for ref params will be reported in the next scope */
3078 llassertprint (uentry_isVar (ce),
3079 ("ce: %s", uentry_unparseFull (ce)));
3081 if (ctype_isFunction (uentry_getType (ce)))
3083 if (fileloc_isUser (fwhere))
3085 hasError = optgenerror
3087 message ("%q %q declared but not used",
3089 (isFileStatic ? "File static function"
3091 uentry_getName (ce)),
3097 if (fileloc_isUser (fwhere))
3101 hasError = optgenerror
3103 message ("%q %q declared but not used",
3105 (isFileStatic ? "File static variable"
3107 uentry_getName (ce)),
3117 else if (uentry_isDatatype (ce) || uentry_isAnyTag (ce))
3118 { /* check all fields */
3119 ctype ct = uentry_getRealType (ce);
3122 while (ctype_isAP (ct))
3124 ct = ctype_getBaseType (ct);
3128 if (ctype_isSU (ct))
3130 uentryList fields = ctype_getFields (ct);
3132 uentryList_elements (fields, field)
3134 if (!uentry_isUsed (field))
3136 if (uentry_hasName (ce))
3138 hasError |= optgenerror
3140 message ("Field %q of %s %q declared but not used",
3141 uentry_getName (field),
3142 cstring_makeLiteralTemp
3143 (ctype_isStruct (ct) ? "structure" : "union"),
3144 uentry_getName (ce)),
3145 uentry_whereEarliest (field));
3149 hasError |= optgenerror
3151 message ("Field %q of unnamed %s declared but not used",
3152 uentry_getName (field),
3153 cstring_makeLiteralTemp
3154 (ctype_isStruct (ct) ? "structure" : "union")),
3155 uentry_whereEarliest (field));
3158 uentry_setUsed (field, fileloc_undefined);
3160 } end_uentryList_elements;
3170 if (uentry_isParam (ce) && context_inMacro ())
3172 if (fileloc_isDefined (uentry_whereSpecified (ce)))
3174 uentry_showWhereSpecified (ce);
3179 uentry_showDefSpecInfo (ce, fwhere);
3182 uentry_setUsed (ce, fileloc_undefined);
3188 checkGlobalReturn (uentry glob, sRef orig)
3190 sRef sr = uentry_getSref (glob);
3193 if (context_getFlag (FLG_GLOBSTATE))
3195 if (sRef_isKilledGlob (orig))
3197 if (sRef_isStateUndefined (sr)
3198 || sRef_isUnuseable (sr)
3199 || sRef_isStateUnknown (sr)
3200 || sRef_isDead (sr))
3206 ctype ct = ctype_realType (uentry_getType (glob));
3208 if (ctype_isVisiblySharable (ct))
3213 ("Killed global %q not released before return",
3214 uentry_getName (glob)),
3217 sRef_showStateInfo (sr);
3222 sRef_protectDerivs ();
3223 (void) checkGlobalDestroyed (sr, g_currentloc);
3224 sRef_clearProtectDerivs ();
3230 if (sRef_isStateUndefined (sr))
3232 if (optgenerror (FLG_GLOBSTATE,
3234 ("Function returns with global %q undefined",
3235 uentry_getName (glob)),
3238 sRef_showStateInfo (sr);
3243 if (sRef_isDead (sr))
3247 message ("Function returns with global %q "
3248 "referencing released storage",
3249 uentry_getName (glob)),
3252 sRef_showStateInfo (sr);
3253 sRef_setDefState (sr, SS_UNKNOWN, fileloc_undefined);
3257 if (ctype_isRealPointer (uentry_getType (glob)) &&
3258 sRef_possiblyNull (sr) && !uentry_possiblyNull (glob))
3262 message ("Function returns with non-null global %q "
3263 "referencing null storage",
3264 uentry_getName (glob)),
3267 sRef_showNullInfo (sr);
3272 checkGlobReturn (glob);
3280 ** remember: check alias globals
3283 void usymtab_checkFinalScope (bool isReturn)
3286 bool mustFree = context_getFlag (FLG_MUSTFREE);
3287 bool mustDefine = context_getFlag (FLG_MUSTDEFINE);
3288 /* bool mustNotAlias = context_getFlag (FLG_MUSTNOTALIAS); */
3289 sRefSet checked = sRefSet_new ();
3290 usymtab stab = utab;
3294 ** need to check all scopes out to function parameters.
3299 for (i = 0; i < stab->nentries; i++)
3301 uentry ce = stab->entries[i];
3302 sRef sr = uentry_getSref (ce);
3303 sRef rb = sRef_getRootBase (sr);
3305 if (ctype_isFunction (uentry_getType (ce)))
3307 /*@innercontinue@*/ continue;
3312 DPRINTF (("Check entry: %s", uentry_unparseFull (ce)));
3314 if (!sRefSet_member (checked, sr) && !sRef_isGlobal (rb))
3316 if (ctype_isRealSU (uentry_getType (ce))
3317 && !uentry_isAnyParam (ce)
3318 && !uentry_isRefParam (ce)
3319 && !uentry_isStatic (ce)
3320 && !sRef_isDependent (sr)
3321 && !sRef_isOwned (sr))
3323 sRefSet als = usymtab_allAliases (sr);
3326 if (sRefSet_isEmpty (als))
3328 checkLocalDestroyed (sr, g_currentloc);
3332 /* aliased, no problem */ ;
3338 (!uentry_isStatic (ce)
3339 && ((sRef_isNewRef (sr))
3340 || (((sRef_isOnly (sr) || sRef_isFresh (sr)
3341 || sRef_isKeep (sr) || sRef_isOwned (sr))
3342 && !sRef_isDead (sr))
3343 && (!sRef_definitelyNull (sr))
3344 && (!usymtab_isProbableNull (sr)))))
3346 bool hasError = TRUE;
3349 ** If its a scope exit, check if there is an alias.
3350 ** If so, make it only. If not, there is an error.
3355 if (canLoseReference (sr, g_currentloc))
3363 if (sRef_hasLastReference (sr))
3365 sRef ar = sRef_getAliasInfoRef (sr);
3370 ("Last reference %q to %s storage %qnot %q before %q",
3372 alkind_unparse (sRef_getAliasKind (sr)),
3373 sRef_unparseOpt (ar),
3374 cstring_makeLiteral (sRef_isKeep (sr)
3375 ? "transferred" : "released"),
3376 cstring_makeLiteral (isReturn
3377 ? "return" : "scope exit")),
3380 sRef_showRefLost (sr);
3383 else if (sRef_isNewRef (sr))
3388 ("%q %q not released before %q",
3390 (alkind_isKillRef (sRef_getOrigAliasKind (sr))
3391 ? "Kill reference parameter" : "New reference"),
3392 uentry_getName (ce),
3393 cstring_makeLiteral (isReturn
3394 ? "return" : "scope exit")),
3397 sRef_showAliasInfo (sr);
3402 if (ctype_isRealSU (sRef_getType (sr)))
3404 checkStructDestroyed (sr, g_currentloc);
3411 ("%s storage %q not %q before %q",
3412 alkind_capName (sRef_getAliasKind (sr)),
3413 uentry_getName (ce),
3414 cstring_makeLiteral (sRef_isKeep (sr)
3415 ? "transferred" : "released"),
3416 cstring_makeLiteral (isReturn
3417 ? "return" : "scope exit")),
3420 sRef_showAliasInfo (sr);
3431 else if (mustDefine && uentry_isOut (ce))
3433 if (!ynm_toBoolStrict (sRef_isReadable (sr)))
3437 message ("Out storage %q not defined before %q",
3438 uentry_getName (ce),
3440 (isReturn ? "return" : "scope exit")),
3443 /* uentry_showWhereDeclared (ce); */
3452 ** also check state is okay
3455 if (usymtab_lexicalLevel () > functionScope
3456 && uentry_isVariable (ce)
3457 && (sRef_isLocalVar (sr)
3458 && (sRef_isDependent (sr) || sRef_isLocalState (sr))))
3460 sRefSet ab = usymtab_aliasedBy (sr);
3462 /* should do something more efficient here */
3464 if (sRefSet_isEmpty (ab))
3466 /* and no local ref */
3481 checked = sRefSet_insert (checked, sr);
3484 llassert (usymtab_isDefined (stab->env));
3486 if (usymtab_isBranch (stab))
3488 stab = usymtab_dropEnv (stab);
3495 llassert (stab != usymtab_undefined);
3496 } while (isReturn && (stab->lexlevel >= paramsScope));
3498 sRefSet_free (checked);
3502 ** all globals are appropriately defined
3503 ** all parameters are appropriately defined
3504 ** special clauses are followed
3507 if (isReturn || (utab->lexlevel == paramsScope))
3509 uentry fcn = context_getHeader ();
3510 uentryList params = context_getParams ();
3511 globSet uglobs = context_getUsedGlobs ();
3512 globSet sglobs = context_getGlobs ();
3515 if (isReturn && context_maybeSet (FLG_GLOBALIAS))
3517 aliasTable_checkGlobs (utab->aliases);
3521 ** special clauses (defines, sets, allocates, releases)
3524 if (uentry_hasSpecialClauses (fcn))
3526 specialClauses clauses = uentry_getSpecialClauses (fcn);
3528 specialClauses_elements (clauses, cl)
3530 if (specialClause_isAfter (cl))
3531 { /* evs - 2000 07 10 - added this */
3532 sRefTest tst = specialClause_getPostTestFunction (cl);
3533 sRefSet rfs = specialClause_getRefs (cl);
3535 sRefSet_elements (rfs, el)
3537 sRef base = sRef_getRootBase (el);
3539 if (sRef_isResult (base))
3543 else if (sRef_isParam (base))
3545 sRef sr = sRef_updateSref (base);
3546 sr = sRef_fixBase (el, sr);
3548 if (tst != NULL && !tst (sr))
3551 (specialClause_postErrorCode (cl),
3552 message ("%s storage %qcorresponds to "
3553 "storage listed in %q clause",
3554 specialClause_postErrorString (cl, sr),
3555 sRef_unparseOpt (sr),
3556 specialClause_unparseKind (cl)),
3559 sRefShower ss = specialClause_getPostTestShower (cl);
3570 if (sRef_isMeaningful (el))
3575 } end_sRefSet_elements ;
3577 } end_specialClauses_elements ;
3581 ** check parameters on return
3584 uentryList_elements (params, arg)
3586 if (!uentry_isElipsisMarker (arg))
3588 ctype rt = ctype_realType (uentry_getType (arg));
3590 if (ctype_isMutable (rt) || ctype_isSU (rt))
3592 uentry param = usymtab_lookupQuiet (utab, uentry_rawName (arg));
3593 checkParamReturn (param);
3596 } end_uentryList_elements;
3598 globSet_allElements (sglobs, el)
3600 uentry current = sRef_getUentry (el);
3602 if (uentry_isVariable (current) && !uentry_isRealFunction (current))
3604 checkGlobalReturn (current, el);
3606 } end_globSet_allElements;
3608 globSet_allElements (uglobs, el)
3610 if (!globSet_member (sglobs, el))
3612 uentry current = sRef_getUentry (el);
3615 if (uentry_isVariable (current)
3616 && !uentry_isRealFunction (current))
3618 checkGlobalReturn (current, sRef_undefined);
3621 } end_globSet_allElements;
3627 usymtab_quietExitScope (fileloc loc)
3628 /*@globals utab, globtab, filetab; @*/
3631 usymtab t = utab->env;
3633 if (utab->reftable != NULL)
3637 for (i = 0; i < utab->nentries; i++)
3639 uentry current = utab->entries[i];
3640 uentry old = usymtab_lookupAux (t, uentry_rawName (current));
3642 uentry_mergeState (old, current, loc, FALSE, FALSE, FALSE, NOCLAUSE);
3646 llassert (t != NULL);
3648 if (t->lexlevel > paramsScope)
3650 t->guards = guardSet_levelUnion (t->guards, utab->guards, t->lexlevel);
3651 t->aliases = aliasTable_levelUnionSeq (t->aliases, utab->aliases,
3653 utab->aliases = aliasTable_undefined;
3656 t->mustBreak = utab->mustBreak;
3657 t->exitCode = utab->exitCode;
3659 usymtab_freeLevel (utab);
3665 ** Exit a scope with no checking, lose alias states.
3666 ** (When should this be used?)
3669 void usymtab_quietPlainExitScope (void)
3670 /*@globals utab, globtab, filetab@*/
3673 usymtab t = utab->env;
3675 llassert (t != NULL);
3676 llassert (NOALIAS (utab->aliases, t->aliases));
3677 usymtab_freeLevel (utab);
3681 void usymtab_exitScope (exprNode expr)
3682 /*@globals utab, filetab, globtab@*/
3683 /*@modifies utab, globtab@*/
3685 usymtab ctab = usymtab_undefined;
3686 usymtab lctab = usymtab_undefined;
3687 bool mustReturn = exprNode_mustEscape (expr);
3689 if (utab->kind == US_CBRANCH)
3692 ** save the case branches, remove the first non-cbranch
3697 while (utab->kind == US_CBRANCH)
3701 llassert (utab != GLOBAL_ENV);
3705 if (utab->kind == US_TBRANCH || utab->kind == US_FBRANCH
3706 || utab->kind == US_CBRANCH || utab->kind == US_SWITCH) {
3708 if (context_inMacro ()) {
3709 /* evs 2000-07-25 */
3710 /* Unparseable macro may end inside nested scope. Deal with it. */
3712 llerror (FLG_SYNTAX, message ("Problem parsing macro body of %s (unbalanced scopes). Attempting to recover, recommend /*@notfunction@*/ before macro definition.",
3713 context_inFunctionName ()));
3715 while (utab->kind == US_TBRANCH
3716 || utab->kind == US_FBRANCH
3717 || utab->kind == US_CBRANCH
3718 || utab->kind == US_SWITCH)
3721 llassert (utab != GLOBAL_ENV);
3724 llcontbug (("exitScope: in branch: %s", usymtab_unparseStack ()));
3726 } /*@=branchstate@*/
3730 ** check all variables in scope were used
3734 ** bogus errors if this is the normal inside a switch,
3735 ** since cases have not been merged yet. Should probably
3736 ** still check this, but I'm too lazy at the moment...
3739 llassertfatal (utab->env != GLOBAL_ENV);
3741 if (utab->env->kind != US_SWITCH)
3747 ** check aliasing: all only params are released (dead)
3748 ** definition: all out params are defined, all modified params
3749 ** are completely defined
3751 ** NOTE: note for exiting paramsScope, since checkReturn should be
3755 if (!mustReturn && (usymtab_lexicalLevel () > functionScope))
3758 ** should only call this is end of scope is reachable...
3761 usymtab_checkFinalScope (FALSE);
3764 if (usymtab_lexicalLevel () == paramsScope && context_inFunctionLike ())
3767 ** leaving a function, need to fix up globals
3770 uentryList params = context_getParams ();
3771 globSet globs = context_getUsedGlobs ();
3774 uentryList_elements (params, ue)
3776 uentry_fixupSref (ue);
3777 } end_uentryList_elements;
3779 clearFunctionTypes ();
3782 globSet_allElements (globs, el)
3784 if (sRef_isCvar (el))
3787 int index = sRef_getScopeIndex (el);
3789 if (sRef_isFileStatic (el))
3791 llassert (usymtab_isDefined (filetab));
3792 current = usymtab_fetchIndex (filetab, index);
3796 current = usymtab_fetchIndex (globtab, index);
3799 if (uentry_isVariable (current))
3801 uentry_fixupSref (current);
3805 sRef_clearDerived (uentry_getSref (current));
3808 } end_globSet_allElements;
3811 usymtab_quietExitScope (exprNode_loc (expr));
3813 if (lctab != usymtab_undefined)
3815 /*@i@*/ lctab->env = utab;
3816 /*@i@*/ utab = ctab;
3817 /*@-branchstate@*/ } /*@=branchstate@*/
3823 ** yikes! don't let the '170 kids see this one...
3827 uentry_directParamNo (uentry ue)
3829 if (uentry_isVar (ue))
3831 sRef sr = uentry_getSref (ue);
3833 if (sRef_lexLevel (sr) == functionScope)
3835 /*@access sRef@*/ /*@-null@*/
3836 int index = sr->info->cvar->index;
3837 /*@noaccess sRef@*/ /*@=null@*/
3839 if (index < uentryList_size (context_getParams ()))
3848 /*@dependent@*/ /*@exposed@*/ uentry
3849 usymtab_getParam (int paramno)
3853 ** requires in a function context (checked)
3855 ** depends on no nested functions --- the function
3856 ** parameters are ALWAYS one scope inside the global scope
3857 ** and entered in order!
3861 if (!context_inFunctionLike ())
3862 llfatalbug (message ("usymtab_getParam: not in function context: %q",
3863 context_unparse ()));
3865 while (s->lexlevel > paramsScope)
3870 llassert (usymtab_isDefined (s));
3872 if (paramno >= s->nentries)
3875 ** Parse errors lead to this.
3878 uentry err = uentry_makeVariableLoc (cstring_makeLiteralTemp ("<error>"),
3881 uentry_markOwned (err);
3885 return (s->entries[paramno]);
3888 static /*@dependent@*/ /*@exposed@*/ uentry
3889 usymtab_getRefTab (/*@notnull@*/ usymtab u, int level, usymId index)
3894 ue = usymtab_getRefNoisy (u, level, index);
3897 if (uentry_isUndefined (ue))
3899 llbug (message ("usymtab_getRef: out of range: %d. level = %d",
3907 static /*@dependent@*/ /*@exposed@*/ usymtab
3908 usymtab_dropEnv (/*@notnull@*/ usymtab s)
3910 if (s->kind == US_CBRANCH)
3918 llassert (s != GLOBAL_ENV);
3919 } while (s->kind == US_CBRANCH);
3920 /* drop all cases (except in nested scopes */
3923 llassert (s != GLOBAL_ENV);
3926 if (s->kind == US_FBRANCH)
3928 s = s->env; /* skip the true branch */
3929 llassert (usymtab_isDefined (s));
3930 llassert (s->kind == US_TBRANCH);
3933 llassert (s != GLOBAL_ENV);
3939 /*@dependent@*/ /*@exposed@*/ uentry
3940 usymtab_getRefQuiet (int level, usymId index)
3946 llassert (s != NULL);
3947 llassert (index >= 0);
3949 if (level > s->lexlevel)
3952 return uentry_undefined;
3955 llassertprint (level <= s->lexlevel, ("level: %d / lexlevel: %d",
3956 level, s->lexlevel));
3958 while (s->lexlevel > level)
3960 if (usymtab_isBranch (s))
3962 int eindex = refTable_lookup (s, level, index);
3964 if (eindex != NOT_FOUND)
3966 return (s->entries[eindex]);
3970 s = usymtab_dropEnv (s);
3973 while (usymtab_isBranch (s) && s->lexlevel == level)
3975 int eindex = refTable_lookup (s, level, index);
3977 if (eindex != NOT_FOUND)
3979 return (s->entries[eindex]);
3982 s = usymtab_dropEnv (s);
3985 if (index >= s->nentries)
3987 return uentry_undefined;
3990 llassert (!uentry_isUndefined (s->entries[index]));
3992 return s->entries[index];
3995 static /*@dependent@*/ /*@exposed@*/ uentry
3996 usymtab_getRefNoisy (/*@notnull@*/ usymtab s, int level, usymId index)
3999 uentry ue = uentry_undefined;
4002 llassert (index >= 0);
4005 while (s->lexlevel > level)
4008 if (usymtab_isBranch (s))
4010 int eindex = refTable_lookup (s, level, index);
4012 if (eindex != NOT_FOUND)
4014 ue = s->entries[eindex];
4018 while (!usymtab_isBranch (otab))
4020 otab = usymtab_dropEnv (otab);
4021 llassert (otab != GLOBAL_ENV);
4024 if (refTable_lookup (otab, level, index) == NOT_FOUND)
4026 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4038 s = usymtab_dropEnv (s);
4041 llassert (usymtab_isDefined (s));
4043 while (usymtab_isBranch (s) && s->lexlevel == level)
4045 int eindex = refTable_lookup (s, level, index);
4048 if (eindex != NOT_FOUND)
4050 ue = s->entries[eindex];
4054 while (!usymtab_isBranch (otab))
4056 otab = usymtab_dropEnv (otab);
4057 llassert (otab != GLOBAL_ENV);
4060 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4070 s = usymtab_dropEnv (s);
4073 if (s->lexlevel == level && (index < s->nentries))
4075 ue = s->entries[index];
4077 if (uentry_isValid (ue))
4081 while (!usymtab_isBranch (otab))
4083 otab = usymtab_dropEnv (otab);
4085 if (otab == GLOBAL_ENV)
4091 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4102 if (index >= s->nentries)
4104 return uentry_undefined;
4107 llassert (!uentry_isUndefined (s->entries[index]));
4109 return s->entries[index];
4113 ** looking up entries
4115 ** If entry is inside a branch, then copy it, and put it into
4116 ** the branch table.
4120 int refTable_lookup (/*@notnull@*/ usymtab ut, int level, int index)
4122 refTable rt = ut->reftable;
4125 llassert (rt != NULL);
4128 for (i = 0; i < ut->nentries; i++)
4130 if (rt[i]->level == level && rt[i]->index == index)
4140 /*@only@*/ refentry refentry_create (int level, int index)
4142 refentry r = (refentry) dmalloc (sizeof (*r));
4150 static /*@dependent@*/ /*@exposed@*/ uentry
4151 usymtab_addRefEntry (/*@notnull@*/ usymtab s, cstring k)
4156 llassert (ut->reftable != NULL);
4158 while (s != GLOBAL_ENV)
4160 eindex = usymtab_getIndex (s, k);
4162 if (eindex != NOT_FOUND)
4164 uentry current = s->entries[eindex];
4166 if (uentry_isVar (current) && !ctype_isFunction (uentry_getType (current)))
4170 DPRINTF (("Here: copying %s", uentry_unparseFull (current)));
4172 ue = uentry_copy (current);
4174 DPRINTF (("Here: copying %s", uentry_unparseFull (ue)));
4176 usymtab_addEntryQuiet (ut, ue);
4178 if (s->reftable != NULL)
4180 refentry ref = s->reftable[eindex];
4183 ut->reftable[ut->nentries - 1]
4184 = refentry_create (ref->level, ref->index);
4188 ut->reftable[ut->nentries - 1]
4189 = refentry_create (s->lexlevel, eindex);
4200 s = usymtab_dropEnv (s);
4203 return uentry_undefined;
4206 static uentry usymtab_lookupAux (usymtab s, cstring k)
4208 DPRINTF (("Lookup: %s", k));
4210 while (s != GLOBAL_ENV)
4212 int eindex = usymtab_getIndex (s, k);
4214 if (eindex != NOT_FOUND)
4216 uentry ret = s->entries[eindex];
4218 DPRINTF (("Found: %s", uentry_unparseFull (ret)));
4222 if (s->kind == US_TBRANCH || s->kind == US_FBRANCH
4223 || s->kind == US_CBRANCH)
4225 uentry ret = usymtab_addRefEntry (s, k);
4226 DPRINTF (("Ref entry: %s", uentry_unparseFull (ret)));
4233 return uentry_undefined;
4236 static /*@dependent@*/ /*@exposed@*/ uentry
4237 usymtab_lookupQuiet (usymtab s, cstring k)
4241 while (s != GLOBAL_ENV)
4243 eindex = usymtab_getIndex (s, k);
4245 if (eindex != NOT_FOUND)
4247 uentry ret = s->entries[eindex];
4254 return uentry_undefined;
4257 /*@dependent@*/ /*@observer@*/ uentry
4258 usymtab_lookupSafe (cstring k)
4261 DPRINTF (("Lookup safe: %s", k));
4262 return (usymtab_lookupAux (utab, k));
4266 usymtab_lookupExpose (cstring k)
4269 uentry ce = usymtab_lookupAux (utab, k);
4271 if (uentry_isUndefined (ce))
4273 llfatalbug (message ("usymtab_lookup: not found: *%s*", k));
4276 if (uentry_isPriv (ce))
4278 llfatalbug (message ("usymtab_lookup: private: *%s*", k));
4284 uentry usymtab_lookupExposeGlob (cstring k)
4286 return (usymtab_lookupGlobSafe (k));
4289 uentry usymtab_lookupGlob (cstring k)
4290 /*@globals globtab@*/
4292 uentry ce = usymtab_lookupAux (globtab, k);
4294 if (uentry_isUndefined (ce))
4295 llfatalbug (message ("usymtab_lookup: not found: %s", k));
4297 if (uentry_isPriv (ce))
4298 llfatalbug (message ("usymtab_lookup: private: %s", k));
4303 /*@observer@*/ uentry
4304 usymtab_lookupGlobSafe (cstring k)
4305 /*@globals globtab@*/
4307 uentry ce = usymtab_lookupAux (globtab, k);
4312 uentry usymtab_lookupEither (cstring k)
4315 uentry ce = usymtab_lookupSafe (k);
4317 if (uentry_isUndefined (ce))
4318 llfatalerror (message ("usymtab_lookup: not found: %s", k));
4325 usymtab_lookupType (cstring k)
4326 /*@globals globtab@*/
4328 usymId uid = usymtab_getTypeId (k);
4330 if (uid == USYMIDINVALID)
4332 llcontbug (message ("usymtab_lookupType: not found: %s", k));
4333 return ctype_unknown;
4336 return (uentry_getRealType (usymtab_getTypeEntry (uid)));
4341 usymtab_lookupAbstractType (cstring k) /*@globals globtab@*/
4343 usymId uid = usymtab_getTypeId (k);
4345 if (uid == USYMIDINVALID)
4347 llcontbug (message ("usymtab_lookupType: not found: %s", k));
4348 return ctype_unknown;
4351 return (uentry_getAbstractType (usymtab_getTypeEntry (uid)));
4355 ** if there is an unnamed lcl-specified struct tag matching
4356 ** the uentryList, return its datatype. Otherwise, returns
4361 usymtab_structFieldsType (uentryList f)
4362 /*@globals globtab@*/
4364 return (usymtab_suFieldsType (f, TRUE));
4368 usymtab_unionFieldsType (uentryList f)
4369 /*@globals globtab@*/
4371 return (usymtab_suFieldsType (f, FALSE));
4375 usymtab_suFieldsType (uentryList f, bool isStruct)
4376 /*@globals globtab@*/
4380 if (fileloc_isSpec (g_currentloc)) return (ctype_undefined);
4382 for (i = 0; i < globtab->nentries; i++)
4384 uentry current = globtab->entries[i];
4387 ? uentry_isStructTag (current) : uentry_isUnionTag (current)))
4389 if (isFakeTag (uentry_rawName (current)))
4391 ctype ct = uentry_getType (current);
4393 if ((isStruct ? ctype_isStruct (ct) : ctype_isUnion (ct))
4394 && (uentryList_matchFields (f, ctype_getFields (ct))))
4396 return uentry_getAbstractType (current);
4402 return ctype_undefined;
4406 usymtab_enumEnumNameListType (enumNameList f)
4407 /*@globals globtab@*/
4411 for (i = 0; i < globtab->nentries; i++)
4413 uentry current = globtab->entries[i];
4415 if (uentry_isEnumTag (current))
4417 if (isFakeTag (uentry_rawName (current)))
4419 ctype ct = uentry_getType (current);
4421 if (ctype_isEnum (ct) && (enumNameList_match (f, ctype_elist (ct))))
4423 return uentry_getType (current);
4429 return ctype_undefined;
4433 usymtab_exists (cstring k)
4436 uentry ce = usymtab_lookupSafe (k);
4438 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
4442 usymtab_existsReal (cstring k)
4445 uentry ce = usymtab_lookupSafe (k);
4447 return (!(uentry_isUndefined (ce))
4448 && !(uentry_isPriv (ce))
4449 && !(uentry_isExpandedMacro (ce)));
4453 usymtab_existsGlob (cstring k)
4454 /*@globals globtab@*/
4456 uentry ce = usymtab_lookupAux (globtab, k);
4458 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
4463 usymtab_existsEither (cstring k)
4466 uentry ce = usymtab_lookupAux (utab, k);
4468 return (uentry_isValid (ce));
4472 usymtab_existsGlobEither (cstring k)
4473 /*@globals globtab@*/
4475 uentry ce = usymtab_lookupAux (globtab, k);
4477 return (uentry_isValid (ce));
4482 usymtab_existsType (cstring k)
4483 /*@globals globtab@*/
4485 uentry ce = usymtab_lookupAux (globtab, k);
4487 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && uentry_isDatatype (ce));
4491 usymtab_existsTypeEither (cstring k)
4492 /*@globals globtab@*/
4494 uentry ce = usymtab_lookupAux (globtab, k);
4496 return (uentry_isValid (ce) && uentry_isDatatype (ce));
4500 usymtab_existsStructTag (cstring k) /*@globals globtab@*/
4502 cstring sname = makeStruct (k);
4503 uentry ce = usymtab_lookupAux (globtab, sname);
4505 cstring_free (sname);
4508 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
4512 usymtab_existsUnionTag (cstring k) /*@globals globtab@*/
4514 cstring uname = makeUnion (k);
4515 uentry ce = usymtab_lookupAux (globtab, uname);
4517 cstring_free (uname);
4519 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
4523 usymtab_existsEnumTag (cstring k) /*@globals globtab@*/
4525 cstring ename = makeEnum (k);
4526 uentry ce = usymtab_lookupAux (globtab, ename);
4528 cstring_free (ename);
4529 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
4533 bool usymtab_existsVar (cstring k)
4536 uentry ce = usymtab_lookupSafe (k);
4538 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && (uentry_isVar (ce)));
4547 refTable_free (/*@only@*/ /*@null@*/ refTable x, int nentries)
4553 for (i = 0; i < nentries; i++)
4563 usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab u)
4564 /*@globals globtab, utab, filetab@*/
4568 aliasTable_free (u->aliases);
4569 environmentTable_free (u->environment);
4570 refTable_free (u->reftable, u->nentries);
4572 if (u == filetab || u == globtab)
4574 for (i = 0; i < u->nentries; i++)
4576 uentry_freeComplete (u->entries[i]);
4581 for (i = 0; i < u->nentries; i++)
4583 uentry_free (u->entries[i]);
4587 guardSet_free (u->guards);
4594 llassert (u->htable == NULL);
4602 usymtab_freeAux (/*@only@*/ usymtab u)
4603 /*@globals globtab, utab, filetab@*/
4606 while (u != GLOBAL_ENV)
4609 usymtab_freeLevel (u);
4616 void usymtab_free ()
4617 /*@globals killed utab, globtab, filetab@*/
4621 usymtab_freeAux (utab);
4624 static int usymtab_lexicalLevel (void) /*@globals utab@*/
4626 return (utab->lexlevel);
4629 bool usymtab_inGlobalScope () /*@globals utab, globtab@*/
4631 return (utab == globtab);
4634 bool usymtab_inFileScope () /*@globals utab@*/
4636 return (utab->lexlevel == fileScope);
4639 bool usymtab_inFunctionScope () /*@globals utab@*/
4641 return (utab->lexlevel == functionScope);
4646 usymtab_replaceEntry (uentry s)
4647 /*@globals utab, globtab@*/
4648 /*@modifies utab, s@*/
4650 usymtab_replaceEntryAux (utab, s);
4655 usymtab_matchForwardStruct (usymId u1, usymId u2)
4656 /*@globals globtab@*/
4658 uentry ue1 = usymtab_getTypeEntry (u1);
4659 uentry ue2 = usymtab_getTypeEntry (u2);
4661 if (uentry_isAnyTag (ue2))
4663 ctype reptype = uentry_getType (ue1);
4665 if (ctype_isPointer (reptype))
4667 ctype repbase = ctype_getBaseType (reptype);
4669 if (ctype_isUA (repbase))
4671 typeId rtuid = ctype_typeId (repbase);
4673 if (u2 == rtuid) return TRUE;
4675 if (usymId_isValid (rtuid))
4677 reptype = uentry_getType (usymtab_getTypeEntry (rtuid));
4679 return (ctype_isUA (reptype) && (u2 == (ctype_typeId (reptype))));
4688 void usymtab_addGuards (guardSet guards)
4691 utab->guards = guardSet_union (utab->guards, guards);
4694 static bool usymtab_isGuardedAux (sRef s)
4698 sRef base = sRef_getRootBase (s);
4699 int lowlevel = paramsScope;
4700 int baselevel = sRef_lexLevel (base);
4702 if (sRef_isCvar (base))
4704 lowlevel = baselevel;
4705 if (lowlevel < paramsScope) lowlevel = paramsScope;
4708 while (tab->lexlevel >= lowlevel)
4710 if (guardSet_isGuarded (tab->guards, s))
4713 if (!sRef_definitelyNull (s))
4715 sRef_setNotNull (s, fileloc_undefined);
4721 tab = usymtab_dropEnv (tab);
4727 void usymtab_unguard (sRef s) /*@modifies utab@*/
4730 sRef base = sRef_getRootBase (s);
4731 int lowlevel = paramsScope;
4732 int baselevel = sRef_lexLevel (base);
4734 if (sRef_isCvar (base))
4736 lowlevel = baselevel;
4737 if (lowlevel < paramsScope) lowlevel = paramsScope;
4740 while (tab->lexlevel >= lowlevel)
4742 if (guardSet_isGuarded (tab->guards, s))
4744 guardSet_delete (tab->guards, s);
4747 tab = usymtab_dropEnv (tab);
4751 bool usymtab_isGuarded (sRef s)
4754 return (sRef_aliasCompleteSimplePred (usymtab_isGuardedAux, s));
4757 bool usymtab_isProbableNull (sRef s)
4759 return (sRef_aliasCheckSimplePred (usymtab_isProbableNullAux, s));
4762 bool usymtab_isProbableDeepNull (sRef s)
4764 return (sRef_deepPred (usymtab_isProbableNull, s));
4767 static bool usymtab_isProbableNullAux (sRef s)
4771 sRef base = sRef_getRootBase (s);
4772 int lowlevel = paramsScope;
4774 if (sRef_isCvar (base))
4776 lowlevel = sRef_lexLevel (base);
4777 if (lowlevel < paramsScope) lowlevel = paramsScope;
4780 while (tab->lexlevel >= lowlevel)
4782 if (guardSet_isProbableNull (tab->guards, s))
4787 while (tab->kind == US_CBRANCH)
4792 llassert (usymtab_isDefined (tab));
4794 if (tab->kind == US_FBRANCH)
4797 llassert (tab->kind == US_TBRANCH);
4807 usymtab_printGuards ()
4808 /*@globals utab, globtab@*/
4810 usymtab ttab = utab;
4812 while (ttab != globtab)
4814 llmsg (message ("Guards [%d]: %q", ttab->lexlevel,
4815 guardSet_unparse (ttab->guards)));
4821 usymtab_displayAllUses ()
4822 /*@globals utab, globtab@*/
4826 /* only in top scope */
4827 llassert (utab == globtab);
4829 /* need a copy, so order is not messed up by sort! */
4830 copy = usymtab_shallowCopy (globtab);
4832 qsort (copy->entries, (size_t)copy->nentries,
4833 sizeof (*copy->entries), (int (*)(const void *, const void *)) uentry_xcompareuses);
4835 usymtab_entries (copy, ue)
4837 if (uentry_isValid (ue))
4839 filelocList uses = uentry_getUses (ue);
4840 int size = filelocList_realSize (uses);
4842 if (fileloc_isDefined (uentry_whereDefined (ue))
4843 && !fileloc_isLib (uentry_whereDefined (ue))
4846 llmsg (message ("%q (%q), %d use%p:\n %q",
4847 uentry_getName (ue),
4848 fileloc_unparse (uentry_whereDefined (ue)),
4849 size, filelocList_unparseUses (uses)));
4852 } end_usymtab_entries;
4854 usymtab_shallowFree (copy);
4857 static /*@dependent@*/ /*@exposed@*/ usymtab
4858 usymtab_getFileTab ()
4859 /*@globals filetab@*/
4861 llassert (filetab != NULL);
4867 usymtab_unparseStack ()
4870 return (usymtab_unparseStackTab (utab));
4873 static /*@only@*/ cstring
4874 usymtab_unparseStackTab (usymtab t)
4876 bool firstOne = TRUE;
4877 cstring ret = cstring_makeLiteral ("[");
4879 while (t != GLOBAL_ENV)
4883 ret = message ("%q %q", ret, usymtab_typeName (t));
4888 ret = message ("%q, %q", ret, usymtab_typeName (t));
4893 ret = message ("%q ]", ret);
4897 static /*@only@*/ cstring
4898 usymtab_typeName (/*@notnull@*/ usymtab t)
4902 case US_GLOBAL: return cstring_makeLiteral ("global");
4903 case US_NORMAL: return cstring_makeLiteral ("normal");
4904 case US_TBRANCH: return cstring_makeLiteral ("true");
4905 case US_FBRANCH: return cstring_makeLiteral ("false");
4906 case US_CBRANCH: return cstring_makeLiteral ("case");
4907 case US_SWITCH: return cstring_makeLiteral ("switch");
4913 void usymtab_testInRange (sRef s, int index) /*@globals utab;@*/
4917 environmentTable_testInRange (utab->environment, s, index);
4920 void usymtab_postopVar (sRef sr) /*@globals utab;@*/
4922 environmentTable_postOpvar (utab->environment, sr);
4925 /* doesn't do much check here assumes checking is done before call*/
4926 void usymtab_addExactValue(sRef s1, int val)
4928 /*@i22@*/ utab->environment = environmentTable_addExactValue (utab->environment, s1, val);
4931 void usymtab_addMustAlias (sRef s, sRef al)
4934 if (sRef_isMeaningful (s) && sRef_isMeaningful (al)
4935 && !(sRef_isConst (s) || sRef_isConst (al))
4936 && !(sRef_isAddress (al) && sRef_isDirectParam (sRef_getBase (al)))
4937 && !(sRef_similar (s, al)))
4939 utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
4940 DPRINTF (("Must alias: %s", aliasTable_unparse (utab->aliases)));
4943 ** for local variable, aliasing is symmetric
4946 if (sRef_isLocalVar (s) && sRef_isLocalVar (al))
4948 utab->aliases = aliasTable_addMustAlias (utab->aliases, al, s);
4958 ** Same as usymtab_addMustAlias, except does not check sRef_isSimilar.
4961 void usymtab_addForceMustAlias (sRef s, sRef al)
4964 if (sRef_isMeaningful (s)
4965 && sRef_isMeaningful (al)
4966 && !(sRef_isConst (s) || sRef_isConst (al))
4967 && !(sRef_isAddress (al) && sRef_isDirectParam (sRef_getBase (al))))
4969 utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
4970 DPRINTF (("Must alias: %s", aliasTable_unparse (utab->aliases)));
4973 ** for local variable, aliasing is symmetric
4976 if (sRef_isLocalVar (s) && sRef_isLocalVar (al))
4978 utab->aliases = aliasTable_addMustAlias (utab->aliases, al, s);
4987 void usymtab_clearAlias (sRef s)
4988 /*@modifies utab, s@*/
4991 aliasTable_clearAliases (utab->aliases, s);
4994 sRefSet usymtab_allAliases (sRef s)
4997 if (sRef_isMeaningful (s))
5002 ret = sRefSet_unionFree (aliasTable_aliasedBy (utab->aliases, s),
5003 aliasTable_canAlias (utab->aliases, s));
5008 return sRefSet_undefined;
5012 /*@only@*/ sRefSet usymtab_canAlias (sRef s)
5015 if (sRef_isMeaningful (s))
5017 sRefSet res = aliasTable_canAlias (utab->aliases, s);
5022 return sRefSet_undefined;
5025 /*@only@*/ sRefSet usymtab_aliasedBy (sRef s)
5028 return (aliasTable_aliasedBy (utab->aliases, s));
5031 /*@only@*/ cstring usymtab_unparseAliases ()
5034 return (aliasTable_unparse (utab->aliases));
5038 ** Debugging routines:
5039 ** okay to leak storage here, only for debugging
5045 usymtab_printOut (void)
5051 char *ind = mstring_copy (" ");
5053 fprintf (g_msgstream, "<<< [symbol table] >>>\n");
5055 while (s != GLOBAL_ENV && s->env != GLOBAL_ENV)
5057 cstring tname = usymtab_typeName (s);
5061 ind[depth * 3 + 1] = '\0';
5064 fprintf (g_msgstream, "level: %d (%s)\n", s->lexlevel,
5065 cstring_toCharsSafe (tname));
5067 cstring_free (tname);
5069 for (i = 0; i < s->nentries; i++)
5071 cstring us = uentry_unparseFull (s->entries[i]);
5072 fprintf (g_msgstream, "%s\n", cstring_toCharsSafe (us));
5076 if (s->reftable != NULL && s->nentries > 0)
5078 fprintf (g_msgstream, "\t<< Ref table >>\n");
5080 for (i = 0; i < s->nentries; i++)
5082 fprintf (g_msgstream, "\t%s %3d: %d, %d\n", ind, i,
5083 s->reftable[i]->level,
5084 s->reftable[i]->index);
5088 ind[depth * 3 + 1] = ' ';
5092 fprintf (g_msgstream, "<<< end usymtab >>>\n");
5098 usymtab_printTypes ()
5099 /*@globals globtab@*/
5101 usymtab_printAllAux (globtab);
5105 usymtab_printAll (void)
5108 usymtab_printAllAux (utab);
5112 usymtab_printAllAux (usymtab s)
5113 /*@modifies g_msgstream@*/
5117 char *ind = mstring_copy (" ");
5119 printf ("[[[ usymtab ]]]");
5121 while (s != GLOBAL_ENV)
5124 ind[depth * 3 + 1] = '\0';
5126 if (s->env == GLOBAL_ENV)
5130 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5131 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5132 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5136 for (i = looplow; i < s->nentries; i++)
5138 printf ("%s%3d. %s\n", ind, i,
5139 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5144 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5145 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5146 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5148 for (i = 0; i < s->nentries; i++)
5150 printf ("%s%3d %s\n", ind, i,
5151 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5155 ind[depth * 3 + 1] = ' ';
5159 printf ("----------\n");
5163 usymtab_printComplete ()
5168 char *ind = mstring_copy (" ");
5171 while (s != GLOBAL_ENV)
5175 ind[depth * 3 + 1] = '\0';
5178 if (s->env == GLOBAL_ENV)
5182 printf ("level: %d\n", s->lexlevel);
5186 for (i = looplow; i < s->nentries; i++)
5188 printf ("%s%3d %s\n", ind, i,
5189 cstring_toCharsSafe (uentry_unparse (s->entries[i])));
5194 printf ("level: %d\n", s->lexlevel);
5195 for (i = 0; i < s->nentries; i++)
5197 printf ("%s%3d %s\n", ind, i,
5198 cstring_toCharsSafe (uentry_unparse (s->entries[i])));
5202 ind[depth * 3 + 1] = ' ';
5207 printf ("----------\n");
5211 static /*@only@*/ cstring /*@unused@*/
5212 usymtab_unparseLocalAux (/*@notnull@*/ usymtab s)
5214 cstring c = message ("lexlevel: %d\n", s->lexlevel);
5217 for (i = 0; i < s->nentries; i++)
5219 c = message ("%q\n%q", c, uentry_unparseFull (s->entries[i]));
5222 c = message ("%q\n=========", c);
5226 static cstring /*@unused@*/ /*@only@*/
5227 usymtab_unparseLocalList (/*@notnull@*/ usymtab s)
5229 cstring c = message ("[%d/%s/%s] ", s->lexlevel,
5230 bool_unparse (s->mustBreak),
5231 exitkind_unparse (s->exitCode));
5234 for (i = 0; i < s->nentries; i++)
5236 sRef sr = uentry_getSref (s->entries[i]);
5240 c = message ("%q: %q [%b]", c, uentry_getName (s->entries[i]),
5241 sRef_isStateDefined (sr));
5245 c = message ("%q, %q [%b]", c, uentry_getName (s->entries[i]),
5246 sRef_isStateDefined (sr));
5255 usymtab_printLocal (void)
5261 printf ("lexlevel: %d\n", s->lexlevel);
5263 for (i = 0; i < s->nentries; i++)
5265 printf ("%s\n", cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5268 while (s->lexlevel > 1)
5273 llassert (usymtab_isDefined (s));
5275 printf ("Params:\n");
5277 for (i = 0; i < s->nentries; i++)
5279 printf ("%d: %s\n", i,
5280 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5285 static bool checkDistinctExternalName (uentry e)
5286 /*@globals globtab@*/
5287 /*@modifies *g_msgstream@*/
5289 int checklen = context_getValue (FLG_EXTERNALNAMELEN);
5290 bool ignorecase = context_getFlag (FLG_EXTERNALNAMECASEINSENSITIVE);
5291 bool gotone = FALSE;
5292 bool extras = FALSE;
5293 bool hasError = FALSE;
5294 cstring name = uentry_rawName (e);
5295 usymtab st = globtab;
5303 if (uentry_isAnyTag (e))
5305 checklen++; /* the tag marker doesn't count */
5309 usymtab_entries (st, oe)
5311 if (uentry_sameObject (oe, e))
5318 if (cstring_equalCaseInsensitive (uentry_rawName (oe), name))
5327 (FLG_DISTINCTEXTERNALNAMES,
5329 ("External identifier %q is not distinguishable from %q "
5330 "because alphabetical case is ignored",
5332 uentry_getName (oe)),
5333 uentry_whereLast (e)))
5335 uentry_showWhereAny (oe);
5336 uentry_setHasNameError (oe);
5345 if (cstring_equalLenCaseInsensitive (uentry_rawName (oe),
5354 if (cstring_equalLen (uentry_rawName (oe), name, checklen))
5357 (FLG_DISTINCTEXTERNALNAMES,
5360 ("External identifier %q is not distinguishable from %q "
5361 "in the first %d characters (%q)",
5363 uentry_getName (oe),
5365 cstring_clip (uentry_getName (e), checklen)),
5367 uentry_whereLast (e)))
5369 uentry_showWhereAny (oe);
5370 uentry_setHasNameError (oe);
5383 (FLG_DISTINCTEXTERNALNAMES,
5385 ("External identifier %q is not distinguishable from %q "
5386 "in the first %d characters because alphabetical case "
5389 uentry_getName (oe),
5391 uentry_whereLast (e)))
5393 uentry_showWhereAny (oe);
5394 uentry_setHasNameError (oe);
5400 else if (cstring_equalLen (uentry_rawName (oe), name, checklen))
5409 (FLG_DISTINCTEXTERNALNAMES,
5412 ("External identifier %q is not distinguishable from %q "
5413 "in the first %d characters (%q)",
5415 uentry_getName (oe),
5417 cstring_clip (uentry_getName (e), checklen)),
5419 uentry_whereLast (e)))
5421 uentry_showWhereAny (oe);
5422 uentry_setHasNameError (oe);
5431 } end_usymtab_entries ;
5438 (cstring_makeLiteral ("One or more additional "
5439 "indistinguishable external "
5440 "names not reported"));
5446 static bool checkDistinctInternalName (uentry e)
5448 /*@modifies *g_msgstream@*/
5450 usymtab ttab = utab;
5451 cstring name = uentry_rawName (e);
5452 int numchars = context_getValue (FLG_INTERNALNAMELEN);
5453 bool caseinsensitive = context_getFlag (FLG_INTERNALNAMECASEINSENSITIVE);
5454 bool lookalike = context_getFlag (FLG_INTERNALNAMELOOKALIKE);
5456 if (uentry_isAnyTag (e) && (numchars != 0))
5458 numchars++; /* the tag marker doesn't count */
5461 while (usymtab_isDefined (ttab))
5463 usymtab_entries (ttab, oe)
5465 if (uentry_sameObject (oe, e))
5467 /*@innercontinue@*/ continue;
5470 switch (cstring_genericEqual
5471 (name, uentry_rawName (oe),
5472 numchars, caseinsensitive, lookalike))
5474 case CGE_DISTINCT: /* okay */
5478 if (cstring_equal (name, uentry_rawName (oe)))
5480 ; /* got a shadow error */
5485 (FLG_DISTINCTINTERNALNAMES,
5488 ("Internal identifier %q is not distinguishable from %q "
5489 "in the first %d characters (%q)",
5491 uentry_getName (oe),
5493 cstring_clip (uentry_getName (e), numchars)),
5495 uentry_whereLast (e)))
5497 uentry_showWhereAny (oe);
5498 uentry_setHasNameError (oe);
5506 || (cstring_length (name) <= numchars))
5509 (FLG_DISTINCTINTERNALNAMES,
5511 ("Internal identifier %q is not distinguishable from %q "
5512 "without case sensitivity",
5514 uentry_getName (oe)),
5515 uentry_whereLast (e)))
5517 uentry_showWhereAny (oe);
5518 uentry_setHasNameError (oe);
5525 (FLG_DISTINCTINTERNALNAMES,
5527 ("Internal identifier %q is not distinguishable from %q "
5528 "in the first %d characters without case sensitivity",
5530 uentry_getName (oe),
5532 uentry_whereLast (e)))
5534 uentry_showWhereAny (oe);
5535 uentry_setHasNameError (oe);
5543 || (cstring_length (name) <= numchars))
5546 (FLG_DISTINCTINTERNALNAMES,
5548 ("Internal identifier %q is not distinguishable from %q "
5549 "except by lookalike characters",
5551 uentry_getName (oe)),
5552 uentry_whereLast (e)))
5554 uentry_showWhereAny (oe);
5555 uentry_setHasNameError (oe);
5562 (FLG_DISTINCTINTERNALNAMES,
5564 ("Internal identifier %q is not distinguishable from %q "
5565 "in the first %d characters except by lookalike characters",
5567 uentry_getName (oe),
5569 uentry_whereLast (e)))
5571 uentry_showWhereAny (oe);
5572 uentry_setHasNameError (oe);
5577 } end_usymtab_entries ;
5585 void usymtab_checkDistinctName (uentry e, int scope)
5586 /*@globals utab, globtab@*/
5588 bool hasError = FALSE;
5589 fileloc where = uentry_whereLast (e);
5591 if (!fileloc_isPreproc (where) && !fileloc_isBuiltin (where))
5593 if (scope == globScope)
5595 if (context_getFlag (FLG_DISTINCTEXTERNALNAMES))
5597 hasError = checkDistinctExternalName (e);
5601 if (!hasError && context_getFlag (FLG_DISTINCTINTERNALNAMES))
5603 hasError = checkDistinctInternalName (e);
5609 uentry_setHasNameError (e);