2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2001 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 "transferChecks.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;
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_isAltDefinitelyNull (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@*/ ;
102 extern int usymtab_getCurrentDepth (void) /*@globals utab@*/
104 return utab->lexlevel;
108 usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab p_u)
109 /*@globals globtab, utab, filetab@*/ /*@modifies p_u@*/ ;
111 static bool usymtab_isDefinitelyNullAux (sRef p_s) /*@globals utab@*/ ;
112 static /*@only@*/ cstring usymtab_unparseStackTab (usymtab p_t);
113 static /*@exposed@*/ /*@dependent@*/ uentry
114 usymtab_getRefTab (/*@notnull@*/ usymtab p_u, int p_level, usymId p_index);
115 static /*@unused@*/ /*@only@*/ cstring
116 usymtab_unparseLocalAux (/*@notnull@*/ usymtab p_s);
117 static /*@unused@*/ /*@only@*/ cstring
118 usymtab_unparseLocalList (/*@notnull@*/ usymtab p_s);
119 static /*@only@*/ cstring usymtab_typeName (/*@notnull@*/ usymtab p_t);
120 static void usymtab_handleParams (void)
121 /*@globals utab, globtab, filetab@*/
122 /*@modifies utab@*/ ;
124 static /*@exposed@*/ /*@dependent@*/ uentry
125 usymtab_addRefEntry (/*@notnull@*/ usymtab p_s, cstring p_k);
126 static /*@exposed@*/ /*@dependent@*/ usymtab
127 usymtab_dropEnv (/*@notnull@*/ usymtab p_s);
128 static /*@exposed@*/ /*@dependent@*/ uentry
129 usymtab_getRefNoisy (/*@notnull@*/ usymtab p_s, int p_level, usymId p_index);
131 static /*@exposed@*/ /*@dependent@*/ uentry
132 usymtab_lookupQuietAux (usymtab p_s, cstring p_k, bool p_noalt);
134 static /*@exposed@*/ /*@dependent@*/ uentry
135 usymtab_lookupQuiet (usymtab p_s, cstring p_k);
137 static /*@exposed@*/ /*@dependent@*/ uentry
138 usymtab_lookupQuietNoAlt (usymtab p_s, cstring p_k);
140 static void usymtab_printAllAux (usymtab p_s) /*@modifies g_msgstream@*/ ;
141 static int usymtab_getIndex (/*@notnull@*/ usymtab p_s, cstring p_k);
142 static /*@exposed@*/ uentry usymtab_fetchIndex (/*@notnull@*/ usymtab p_s, int p_i);
143 static /*@exposed@*/ uentry
144 usymtab_lookupAux (usymtab p_s, cstring p_k);
145 static /*@exposed@*/ /*@dependent@*/ /*@notnull@*/ usymtab
146 usymtab_getFileTab (void) /*@globals filetab@*/ ;
147 static int refTable_lookup (/*@notnull@*/ usymtab p_ut, int p_level, int p_index);
148 static bool usymtab_mustBreak (usymtab p_s);
149 static bool usymtab_mustEscape (usymtab p_s);
151 static void recordFunctionType (uentry ue)
153 llassert (uentry_isDatatype (ue) || uentry_isAnyTag (ue)
154 || uentry_isEnumConstant (ue));
157 functypes = uentryList_add (functypes, ue);
161 static void clearFunctionTypes (void)
162 /*@modifies globtab@*/
164 uentryList_elements (functypes, el)
166 if (cstring_isDefined (uentry_rawName (el)))
168 if (cstringTable_isDefined (globtab->htable))
170 cstringTable_remove (globtab->htable, uentry_rawName (el));
173 uentry_setName (el, cstring_undefined);
177 llassert (uentry_isValid (el));
178 el->sref = sRef_undefined;
179 /*@noaccess uentry@*/
180 } end_uentryList_elements ;
182 uentryList_clear (functypes);
185 static /*@falsenull@*/ bool usymtab_isBranch (usymtab u)
187 return (usymtab_isDefined (u) &&
188 (u->kind == US_TBRANCH || u->kind == US_FBRANCH
189 || u->kind == US_CBRANCH || u->kind == US_SWITCH));
192 static bool usymtab_mustBreak (usymtab s)
194 llassert (s != GLOBAL_ENV);
195 return (s->mustBreak);
198 static bool usymtab_mustEscape (usymtab s)
200 llassert (s != GLOBAL_ENV);
201 return (exitkind_mustEscape (s->exitCode));
204 void usymtab_setMustBreak ()
207 llassert (utab != GLOBAL_ENV);
208 utab->mustBreak = TRUE;
211 void usymtab_setExitCode (exitkind ex)
214 llassert (utab != GLOBAL_ENV);
218 if (exitkind_mustEscape (ex))
220 utab->mustBreak = TRUE;
224 bool usymtab_isAltDefinitelyNullDeep (sRef s)
226 return (sRef_deepPred (usymtab_isAltDefinitelyNull, s));
229 static bool usymtab_isAltDefinitelyNull (sRef s)
237 llassert (utab->env != NULL);
239 /*@-mods@*/ /* These modifications are cancelled. */
240 utab->guards = utab->env->guards;
241 utab->env->guards = t;
244 llassert (usymtab_isDefined (utab));
245 res = usymtab_isDefinitelyNull (s);
248 ** This reports a spurious error. It is okay, because of
249 ** the nesting relationship of usymtab environments.
252 /*@-mods@*/ /* Cancelling modifications. */
253 /*@i1@*/ utab->env->guards = utab->guards;
254 /*@i1@*/ utab->guards = t;
260 static /*@notnull@*/ /*@special@*/ usymtab
261 usymtab_create (uskind kind, /*@keep@*/ usymtab env, bool nextlevel)
263 /*@post:isnull result->htable, result->guards, result->aliases@*/
265 usymtab t = (usymtab) dmalloc (sizeof (*t));
268 t->nspace = CBASESIZE;
269 t->entries = (uentry *) dmalloc (sizeof (*t->entries) * CBASESIZE);
271 /* We only use a reftable for branch-level symbol tables.
274 t->reftable = (nextlevel
276 : (refentry *) dmalloc (sizeof (*t->reftable) * CBASESIZE));
279 t->lexlevel = (env == GLOBAL_ENV ? 0 : env->lexlevel) + (nextlevel ? 1 : 0);
284 t->guards = guardSet_undefined;
285 t->aliases = aliasTable_undefined;
287 t->mustBreak = FALSE;
288 t->exitCode = XK_NEVERESCAPE;
297 static /*@only@*/ /*@notnull@*/ usymtab
298 usymtab_createRoot (void) /*@modifies nothing@*/
300 usymtab u = (usymtab) dmalloc (sizeof (*u));
303 u->nspace = CGLOBBASESIZE;
304 u->entries = (uentry *) dmalloc (sizeof (*u->entries) * CGLOBBASESIZE);
307 u->htable = cstringTable_create (CGLOBHASHSIZE);
310 u->guards = guardSet_new ();
311 u->aliases = aliasTable_new ();
313 u->mustBreak = FALSE;
314 u->exitCode = XK_NEVERESCAPE;
321 usymtab_initMod (void)
322 /*@globals undef utab, undef oldtab, undef globtab, undef filetab @*/
323 /*@modifies utab, globtab, filetab, oldtab @*/
325 utab = usymtab_createRoot ();
327 filetab = usymtab_undefined;
328 oldtab = usymtab_undefined;
333 usymtab_initGlobalMarker () /*@globals globtab@*/
335 if (uentry_isValid (usymtab_lookupAux (globtab, GLOBAL_MARKER_NAME)))
337 ; /* Already entered from load table. */
341 usymtab_addGlobalEntry (uentry_makeGlobalMarker ());
346 ** utab should be empty? (requires?)
348 ** Adds bool types to symbol table (these are built in for now)
349 ** Only do this is there is no library!
355 if (context_getFlag (FLG_NOLIB))
357 ctype boolt = ctype_bool;
358 /* evs 2000-07-24: bool is now treated as abstract (always) */
360 uentry boolentry = uentry_makeBoolDatatype (YES);
361 usymtab_supGlobalEntry (boolentry);
362 context_addBoolAccess ();
365 ** We supply values 0 and 1 for the constants, so things like
366 ** while (TRUE) can be interpreted correctly.
369 usymtab_supGlobalEntry
370 (uentry_makeConstantAux (context_getFalseName (), boolt,
371 fileloc_getBuiltin (), FALSE,
372 multiVal_makeInt (0)));
373 usymtab_supGlobalEntry
374 (uentry_makeConstantAux (context_getTrueName (), boolt,
375 fileloc_getBuiltin (), FALSE,
376 multiVal_makeInt (1)));
385 usymtab_grow (/*@notnull@*/ usymtab s)
388 o_uentry *oldsyms = s->entries;
390 s->nspace = CBASESIZE;
391 s->entries = (uentry *) dmalloc (sizeof (*s->entries)
392 * (s->nentries + s->nspace));
394 for (i = 0; i < s->nentries; i++)
396 s->entries[i] = oldsyms[i];
401 if (s->reftable != NULL)
403 refTable oldRefs = s->reftable;
405 s->reftable = (refentry *) dmalloc (sizeof (*s->reftable)
406 * (s->nentries + CBASESIZE + 1));
408 for (i = 0; i < s->nentries; i++)
410 s->reftable[i] = oldRefs[i];
421 usymtab_addEntryQuiet (/*@notnull@*/ usymtab s, /*@keep@*/ uentry e)
423 if (!(s->lexlevel > fileScope || !sRef_modInFunction ()))
425 if (uentry_isDatatype (e)
426 || uentry_isFunction (e)
427 || uentry_isAnyTag (e)
428 || uentry_isEnumConstant (e)
429 || context_inMacro ())
432 ** Not a bug. Code like,
433 ** int f (void) { typedef int tint; ... }
437 /* was nothing here! */
438 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
443 (cstring_makeLiteral ("Declaration outside function scope"));
445 llcontbug (message ("usymtab_addEntryQuiet: inconsistent state "
446 "(lexlevel = %d, modFunction = %s) adding: %q",
447 s->lexlevel, bool_unparse (sRef_modInFunction ()),
448 uentry_unparse (e)));
449 sRef_setGlobalScope ();
450 /* make sure the sRef is not bashed! */
451 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
461 s->entries[s->nentries] = e;
464 if (s == globtab || s == filetab)
466 if (!fileloc_isLib (g_currentloc))
468 uentry_tallyAnnots (e, AN_UNKNOWN);
473 if (cstringTable_isDefined (s->htable))
475 cstringTable_insert (s->htable, cstring_copy (uentry_rawName (e)), s->nentries);
481 static /*@observer@*/ uentry /*@alt void@*/
482 usymtab_addEntryBase (/*@notnull@*/ usymtab s, /*@only@*/ uentry e)
485 ** In theory, we shouldn't need this test because it this is
486 ** only called when a library is being read, and it shouldn't
487 ** ever have a duplicate entry. In practice, its safer to
488 ** leave it in, though.
493 if (uentry_isValid (old = usymtab_lookupQuiet (s, uentry_rawName (e))))
495 DPRINTF (("Duplicate entry: %s", uentry_unparse (e)));
496 uentry_free (e); /* duplicate */
501 int thisentry = s->nentries;
503 if (uentry_isVar (e))
505 uentry_setSref (e, sRef_makeCvar (globScope, thisentry,
506 uentry_getType (e)));
509 usymtab_addEntryQuiet (s, e);
515 static /*@observer@*/ uentry /*@alt void@*/
516 usymtab_addEntryAlways (/*@notnull@*/ usymtab s, /*@only@*/ uentry e)
519 ** In theory, we shouldn't need this test because it this is
520 ** only called when a library is being read, and it shouldn't
521 ** ever have a duplicate entry. In practice, its safer to
522 ** leave it in, though.
526 int thisentry = s->nentries;
528 if (uentry_isValid (old = usymtab_lookupQuiet (s, uentry_rawName (e))))
531 (message ("Duplicate entry in load library: %s. "
532 "Old entry: %q. New entry: %q",
534 uentry_unparseFull (old),
535 uentry_unparseFull (e)));
537 uentry_setName (e, message ("__x_%s", uentry_rawName (e)));
538 /* This shouldn't happen...unless the library is bad! */
542 if (uentry_isVar (e) && !uentry_isGlobalMarker (e))
544 uentry_setSref (e, sRef_makeCvar (globScope, thisentry,
545 uentry_getType (e)));
548 usymtab_addEntryQuiet (s, e);
553 usymtab_addEntryAux (/*@notnull@*/ usymtab st, /*@keep@*/ uentry e, bool isSref)
554 /*@globals globtab@*/
557 usymId thisentry = st->nentries;
559 llassert (!uentry_isElipsisMarker (e));
563 ** llassert (usymtab_lookupSafe (uentry_rawName (e)) == uentry_undefined);
566 llassertprint (uentry_isAnyTag (e) ? st == globtab : TRUE,
567 ("non-global tag: %s / %d", uentry_unparseFull (e), st->lexlevel));
569 if (st->lexlevel == fileScope
570 && (!(uentry_isStatic (e)) || uentry_isAnyTag (e)))
577 ctype ct = uentry_getType (e);
579 if (uentry_isFunction (e) && ctype_isFunction (ct))
581 ct = ctype_getReturnType (ct);
584 if (uentry_isStatic (e))
586 sRef sr = sRef_makeCvar (st->lexlevel, thisentry, ct);
588 if (sRef_isStack (sr) || sRef_isLocalState (sr))
590 sRef_setAliasKind (sr, AK_STATIC, uentry_whereLast (e));
591 sRef_setDefined (sr, uentry_whereLast (e));
594 uentry_setSref (e, sr);
598 uentry_setSref (e, sRef_makeCvar (st->lexlevel, thisentry, ct));
603 if (uentry_isDatatype (e))
606 uentry_setDatatype (e, thisentry);
609 if (uentry_isFunction (e))
611 ctype ct = uentry_getType (e);
613 if (ctype_isFunction (ct)
614 && uentryList_isMissingParams (ctype_argsFunction (ct)))
616 if (uentry_isDeclared (e))
620 message ("Function %q declared without parameter list",
622 uentry_whereDeclared (e));
628 message ("Function %q specified without parameter list",
630 uentry_whereSpecified (e));
635 if (st == globtab && !uentry_isSpecified (e))
637 exprChecks_checkExport (e);
640 uentry_checkName (e);
642 usymtab_addEntryQuiet (st, e);
643 DPRINTF (("Adding entry: [%p] %s", e, uentry_unparseFull (e)));
648 usymtab_addEntry (uentry e)
649 /*@globals utab, globtab@*/
650 /*@modifies utab, e@*/
652 llassertprint (!usymtab_exists (uentry_rawName (e)),
653 ("Entry already exists: %s", uentry_unparse (e)));
655 return usymtab_addEntryAux (utab, e, FALSE);
659 usymtab_addGlobalEntry (uentry e)
660 /*@modifies globtab, e@*/
662 DPRINTF (("Add global: %s / %s", uentry_unparse (e), bool_unparse (uentry_isForward (e))));
664 (void) usymtab_addEntryAux (globtab, e, FALSE);
668 ** supercede and replace entry use elements of entries array, and
669 ** assign an element to a new value, and then free the old value.
670 ** Need -deparrays to avoid errors for this.
676 usymtab_supEntryAux (/*@notnull@*/ usymtab st,
677 /*@only@*/ uentry e, bool isSref)
678 /*@globals globtab, filetab@*/
679 /*@modifies st, globtab, e@*/
681 cstring ename = uentry_rawName (e);
682 bool staticEntry = FALSE;
685 DPRINTF (("Sup entry aux: %s", uentry_unparseFull (e)));
687 /* static tags in global scope */
688 if (st->lexlevel == fileScope
689 && (!(uentry_isStatic (e)) || uentry_isAnyTag (e)))
691 eindex = usymtab_getIndex (st, ename);
693 if (eindex != NOT_FOUND)
695 uentry ce = st->entries[eindex];
699 message ("%s %q shadows static declaration",
700 ekind_capName (uentry_getKind (e)),
702 uentry_whereDeclared (e)))
704 uentry_showWhereLast (ce);
707 if (eindex == st->nentries - 1)
713 st->entries[eindex] = st->entries[st->nentries - 1];
716 if (cstringTable_isDefined (st->htable))
718 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
719 cstring_copy (uentry_rawName (e)));
729 if (uentry_isStatic (e)) {
730 if (uentry_isFunction (e)) {
732 ** Static function declarations are at the file level,
733 ** even if they are in a deeper scope.
736 st = usymtab_getFileTab ();
739 if (!uentry_isAnyTag (e) && st == globtab)
741 st = usymtab_getFileTab ();
743 DPRINTF (("Static entry!"));
748 DPRINTF (("Using symtab: %s", usymtab_unparseLocalAux (st)));
750 eindex = usymtab_getIndex (st, ename);
752 if (eindex != NOT_FOUND)
754 uentry ce = st->entries[eindex];
756 DPRINTF (("Found entry: %s", uentry_unparse (ce)));
758 if (uentry_isPriv (ce)
759 /* || (fileloc_isImport (uentry_whereSpecified (ce))) */
760 || (uentry_isStatic (ce)
761 && uentry_isAnyTag (ce)
762 && (uentry_isDeclared (ce)
763 && !fileloc_sameFile (uentry_whereDefined (ce),
764 uentry_whereDefined (e)))))
768 ** if overloading import should do some checks!
771 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
773 DPRINTF (("Overloading!"));
775 st->entries[eindex] = e;
777 if (uentry_isDatatype (e))
779 uentry_setDatatype (e, eindex);
782 if (st == globtab && !uentry_isSpecified (e))
784 exprChecks_checkExport (e);
787 if (cstringTable_isDefined (st->htable))
789 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
790 cstring_copy (uentry_rawName (e)));
796 else if (uentry_isSpecified (ce))
798 if (uentry_isSpecified (e))
800 DPRINTF (("Here we are: %s", uentry_unparseFull (e)));
802 if (fileloc_isImport (uentry_whereSpecified (ce)))
804 if (cstringTable_isDefined (st->htable))
806 cstringTable_replaceKey (st->htable,
808 cstring_copy (uentry_rawName (e)));
812 st->entries[eindex] = e;
815 if (uentry_isDatatype (e)) uentry_setDatatype (e, eindex);
819 if (fileloc_isImport (uentry_whereSpecified (e)))
825 /* Respecification errors already reported */
826 DPRINTF (("Respecification: %s / %s",
827 fileloc_unparse (uentry_whereSpecified (e)),
828 bool_unparse (fileloc_isSpec (uentry_whereSpecified (e)))));
830 if (uentry_isDatatype (e))
832 uentry_setDatatype (e, eindex);
835 if (cstringTable_isDefined (st->htable))
837 cstringTable_replaceKey (st->htable,
839 cstring_copy (uentry_rawName (e)));
842 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
844 st->entries[eindex] = e;
849 else /* e not specified */
851 DPRINTF (("Merging..."));
853 if (uentry_isDeclared (ce))
855 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
856 DPRINTF (("Merge defn"));
857 uentry_mergeDefinition (ce, e);
861 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
862 DPRINTF (("Merge entries..."));
863 uentry_mergeEntries (ce, e);
864 DPRINTF (("After: %s", uentry_unparseFull (ce)));
868 else /* ce not specified */
870 if (!(st->lexlevel > fileScope || !sRef_modInFunction ()))
872 if (uentry_isDatatype (e) || uentry_isAnyTag (e)
873 || uentry_isEnumConstant (e))
876 ** Not a bug. Code like,
877 ** int f (void) { typedef int tint; ... }
883 llcontbug (message ("usymtab_supEntryAux: inconsistent state "
884 "(lexlevel = %d, modFunction = %s) adding: %q",
885 st->lexlevel, bool_unparse (sRef_modInFunction ()),
886 uentry_unparse (e)));
888 if (sRef_modInFunction ())
890 /* make sure the sRef is not bashed! */
891 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
896 DPRINTF (("Merge.."));
897 uentry_mergeDefinition (ce, e);
902 ctype ct = uentry_getType (ce);
904 if (uentry_isFunction (ce) && ctype_isFunction (ct))
906 ct = ctype_getReturnType (ct);
909 uentry_setSref (ce, sRef_makeCvar (st->lexlevel, eindex, ct));
912 else /* no previous entry */
916 if (st->lexlevel == globScope
917 && !uentry_isStatic (e)
918 && !uentry_isExtern (e)
919 && usymtab_isDefined (filetab))
922 ** check if there is a static entry: (i.e.,
929 eindex = usymtab_getIndex (filetab, ename);
931 if (eindex != NOT_FOUND)
933 uentry ce = filetab->entries[eindex];
935 uentry_setStatic (e);
936 uentry_mergeDefinition (ce, e);
942 outer = usymtab_lookupQuiet (st->env, ename);
945 ** no previous definition, add the new one
949 && uentry_isValid (outer)
950 && !(uentry_isYield (e) || uentry_isYield (outer))
951 && fileloc_isDefined (uentry_whereLast (e))
952 && fileloc_isDefined (uentry_whereLast (outer)))
954 if (!uentry_sameKind (outer, e))
960 if (ctype_isUnknown (uentry_getType (outer))
961 || uentry_isForward (outer))
969 message ("%s %q shadows outer declaration",
970 ekind_capName (uentry_getKind (e)),
972 uentry_whereLast (e)))
974 uentry_showWhereLast (outer);
980 if (st == globtab && context_getFlag (FLG_NEWDECL))
984 message ("New declaration: %q", uentry_getName (e)),
985 uentry_whereLast (e));
988 eindex = usymtab_addEntryAux (st, e, isSref);
992 return (staticEntry ? USYMIDINVALID : eindex);
997 usymtab_replaceEntryAux (/*@notnull@*/ usymtab st, /*@only@*/ uentry e)
998 /*@globals globtab@*/ /*@modifies st, e@*/
1000 cstring ename = uentry_rawName (e);
1003 /* static tags in global scope */
1004 eindex = usymtab_getIndex (st, ename);
1006 if (eindex != NOT_FOUND)
1008 uentry ce = st->entries[eindex];
1010 if (cstringTable_isDefined (st->htable))
1012 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
1013 cstring_copy (uentry_rawName (e)));
1017 st->entries[eindex] = e;
1021 eindex = usymtab_addEntryAux (st, e, FALSE);
1028 void usymtab_supEntry (uentry e)
1029 /*@globals utab, filetab, globtab@*/
1030 /*@modifies utab, globtab, e@*/
1032 (void) usymtab_supEntryAux (utab, e, FALSE);
1036 ** this should be lots more efficient!
1039 static /*@exposed@*/ uentry
1040 usymtab_supEntryReturnAux (/*@notnull@*/ usymtab tab,
1041 /*@only@*/ uentry e, bool isref)
1042 /*@globals globtab, filetab@*/
1043 /*@modifies tab, globtab, e@*/
1045 cstring rawName = cstring_copy (uentry_rawName (e));
1046 bool stat = (tab == globtab) && uentry_isStatic (e);
1050 (void) usymtab_supEntryAux (tab, e, isref);
1054 ret = usymtab_lookupAux (filetab, rawName);
1058 ret = usymtab_lookupAux (tab, rawName);
1060 if (uentry_isInvalid (ret) && usymtab_isDefined (filetab))
1062 ret = usymtab_lookupAux (filetab, rawName);
1066 cstring_free (rawName);
1070 /*@dependent@*/ /*@exposed@*/ uentry
1071 usymtab_supEntryReturn (/*@only@*/ uentry e)
1072 /*@globals utab, filetab, globtab@*/
1073 /*@modifies utab, globtab, e@*/
1075 return (usymtab_supEntryReturnAux (utab, e, FALSE));
1078 /*@dependent@*/ /*@exposed@*/ uentry
1079 usymtab_supEntrySrefReturn (/*@only@*/ uentry e)
1080 /*@globals utab, globtab, filetab@*/
1081 /*@modifies utab, globtab, e@*/
1083 return (usymtab_supEntryReturnAux (utab, e, TRUE));
1086 /*@dependent@*/ /*@exposed@*/ uentry
1087 usymtab_supGlobalEntryReturn (uentry e)
1088 /*@globals globtab, filetab@*/
1089 /*@modifies globtab, e@*/
1093 ret = usymtab_supEntryReturnAux (globtab, e, FALSE);
1095 if (sRef_modInFunction ())
1097 recordFunctionType (ret);
1104 usymtab_supTypeEntry (/*@only@*/ uentry e)
1105 /*@globals globtab, filetab@*/
1106 /*@modifies globtab, e@*/
1111 if (uentry_isAbstractDatatype (e))
1113 uid = usymtab_supAbstractTypeEntry (e, FALSE);
1114 ret = ctype_createAbstract (uid);
1118 uid = usymtab_supEntryAux (globtab, e, FALSE);
1119 ret = ctype_createUser (uid);
1122 if (sRef_modInFunction ())
1124 recordFunctionType (globtab->entries[uid]);
1131 usymtab_supReturnTypeEntry (/*@only@*/ uentry e)
1132 /*@globals globtab, filetab@*/
1133 /*@modifies globtab@*/
1137 DPRINTF (("Abstract? %s", uentry_unparseFull (e)));
1139 if (uentry_isAbstractDatatype (e))
1141 uid = usymtab_supAbstractTypeEntry (e, FALSE);
1143 else if (uentry_isMaybeAbstract (e) && context_getFlag (FLG_IMPABSTRACT))
1145 bool maybeabs = TRUE;
1146 cstring sname = uentry_getName (e);
1147 uentry ue = usymtab_lookupGlobSafe (sname);
1148 cstring_free (sname);
1150 if (uentry_isValid (ue))
1152 DPRINTF (("Lookup: %s", uentry_unparseFull (ue)));
1154 if (uentry_isDatatype (ue))
1156 if (uentry_isMaybeAbstract (ue))
1167 DPRINTF (("Not datatype!"));
1174 uid = usymtab_supAbstractTypeEntry (e, FALSE);
1175 ux = usymtab_getTypeEntry (uid);
1176 uentry_setAbstract (ux);
1180 uid = usymtab_supEntryAux (globtab, e, FALSE);
1181 e = usymtab_getTypeEntry (uid);
1183 if (uentry_isMaybeAbstract (e))
1185 uentry_setConcrete (e);
1191 uid = usymtab_supEntryAux (globtab, e, FALSE);
1192 e = usymtab_getTypeEntry (uid);
1194 if (uentry_isMaybeAbstract (e))
1196 uentry_setConcrete (e);
1200 if (sRef_modInFunction ())
1202 recordFunctionType (globtab->entries[uid]);
1205 return (globtab->entries[uid]);
1209 usymtab_supAbstractTypeEntry (/*@only@*/ uentry e, bool dodef)
1210 /*@globals globtab, filetab@*/
1211 /*@modifies globtab, e@*/
1216 uid = usymtab_supEntryAux (globtab, e, FALSE);
1217 ue = usymtab_getTypeEntry (uid);
1221 uentry_setDatatype (ue, uid);
1224 if (context_getFlag (FLG_ACCESSMODULE)) /* was accessfile */
1226 context_addFileAccessType (uid);
1229 if (sRef_modInFunction ())
1231 recordFunctionType (globtab->entries[uid]);
1239 usymtab_supExposedTypeEntry (/*@only@*/ uentry e, bool dodef)
1240 /*@globals globtab, filetab@*/
1241 /*@modifies globtab, e@*/
1245 uid = usymtab_supEntryAux (globtab, e, FALSE);
1249 uentry ue = usymtab_getTypeEntry (uid);
1251 uentry_setDatatype (ue, uid);
1254 if (sRef_modInFunction ())
1256 recordFunctionType (globtab->entries[uid]);
1264 usymtab_supForwardTypeEntry (/*@only@*/ uentry e)
1265 /*@globals globtab, filetab@*/
1266 /*@modifies globtab, e@*/
1268 usymId uid = usymtab_supEntryAux (globtab, e, FALSE);
1269 uentry ue = usymtab_getTypeEntry (uid);
1271 uentry_setDatatype (ue, uid);
1273 if (sRef_modInFunction ())
1275 recordFunctionType (globtab->entries[uid]);
1278 return (uentry_getAbstractType (ue));
1282 usymtab_supEntrySref (uentry e)
1283 /*@globals utab, globtab, filetab@*/
1284 /*@modifies utab, globtab, e@*/
1286 sRef old = uentry_getSref (e);
1289 if (sRef_isType (old))
1291 uentry ue = usymtab_supEntryReturnAux (utab, e, TRUE);
1294 if (uentry_isValid (ue))
1296 sRef uref = uentry_getSref (ue);
1298 sRef_mergeStateQuiet (uref, old);
1299 sRef_clearDerived (uref);
1301 /*@noaccess uentry@*/
1303 else if (sRef_isKnown (old))
1305 usymtab_supEntry (e);
1309 (void) usymtab_supEntryAux (utab, e, TRUE);
1313 void usymtab_supGlobalEntry (/*@only@*/ uentry e)
1314 /*@globals globtab, filetab@*/
1315 /*@modifies globtab, filetab, e@*/
1319 DPRINTF (("Sup global entry: %s", uentry_unparse (e)));
1321 uid = usymtab_supEntryAux (globtab, e, FALSE);
1323 if (sRef_modInFunction ())
1325 recordFunctionType (globtab->entries[uid]);
1330 usymtab_supReturnFileEntry (/*@only@*/ uentry e)
1331 /*@globals filetab, globtab@*/
1332 /*@modifies filetab, globtab, e@*/
1334 llassert (filetab != usymtab_undefined);
1335 DPRINTF (("File entry: %s", uentry_unparse (e)));
1336 return (usymtab_supEntryReturnAux (filetab, e, FALSE));
1344 usymtab_inDeepScope () /*@globals utab@*/
1346 return (utab->lexlevel > paramsScope);
1350 usymtab_getIndex (/*@notnull@*/ usymtab s, cstring k)
1354 DPRINTF (("Lookup %s", k));
1356 if (cstringTable_isDefined (s->htable))
1358 i = cstringTable_lookup (s->htable, k);
1363 for (i = 0; i < s->nentries; i++)
1365 uentry current = s->entries[i];
1367 DPRINTF (("Check %d: %s", i, uentry_rawName (current)));
1369 if (!uentry_isUndefined (current)
1370 && cstring_equal (uentry_rawName (current), k))
1381 usymtab_fetchIndex (/*@notnull@*/ usymtab s, int i)
1383 llassert (i >= 0 && i < s->nentries);
1384 return (s->entries[i]);
1388 usymtab_getTypeId (cstring k) /*@globals globtab@*/
1390 usymId uid = usymtab_getIndex (globtab, k);
1392 if (uid == NOT_FOUND) return USYMIDINVALID;
1394 if (!(uentry_isDatatype (usymtab_getTypeEntry (uid)))) {
1395 return USYMIDINVALID;
1401 /*@dependent@*/ uentry
1402 usymtab_lookupStructTag (cstring k)
1404 cstring sname = makeStruct (k);
1405 uentry ue = usymtab_lookupGlob (sname);
1407 cstring_free (sname);
1411 /*@dependent@*/ uentry
1412 usymtab_lookupUnionTag (cstring k)
1414 cstring uname = makeUnion (k);
1415 uentry res = usymtab_lookupGlob (uname);
1417 cstring_free (uname);
1421 /*@dependent@*/ uentry
1422 usymtab_lookupEnumTag (cstring k)
1424 cstring ename = makeEnum (k);
1425 uentry res = usymtab_lookupGlob (ename);
1427 cstring_free (ename);
1432 usymtab_getId (cstring k) /*@globals globtab@*/
1434 usymId uid = usymtab_getIndex (globtab, k);
1437 if (uid == NOT_FOUND)
1439 return USYMIDINVALID;
1442 ue = usymtab_getGlobalEntry (uid);
1444 if (uentry_isPriv (ue))
1446 return USYMIDINVALID;
1452 static /*@exposed@*/ uentry
1453 usymtab_getEntryAux (/*@notnull@*/ usymtab s, usymId uid)
1455 llassert (uid != USYMIDINVALID);
1457 if (uid < 0 || uid >= s->nentries)
1459 llcontbug (message ("usymtab_getEntry: out of range: level = %d [%d]",
1461 return uentry_undefined;
1464 llassertprint (uentry_isValid (s->entries[uid]),
1465 ("entry undefined: %d", uid));
1467 return s->entries[uid];
1470 /*@dependent@*/ /*@observer@*/ uentry
1471 usymtab_getGlobalEntry (usymId uid)
1472 /*@globals utab, globtab@*/
1474 if (dbgfree) return (uentry_undefined);
1476 if (utab->lexlevel > paramsScope)
1478 /* need to do this the awkward way, since it could be in conditional scope */
1479 return (usymtab_lookupSafe (uentry_rawName (globtab->entries[uid])));
1483 return (globtab->entries[uid]);
1487 /*@dependent@*/ /*@exposed@*/ uentry
1488 usymtab_getTypeEntry (usymId uid)
1489 /*@globals globtab@*/
1493 if (uid >= 0 && uid < globtab->nentries)
1495 return (globtab->entries[uid]);
1499 return (uentry_undefined);
1504 llassert (uid >= 0 && uid < globtab->nentries);
1505 return (globtab->entries[uid]);
1513 /*@dependent@*/ /*@exposed@*/ uentry
1514 usymtab_getTypeEntrySafe (usymId uid)
1515 /*@globals globtab@*/
1517 if (uid < 0 || uid >= globtab->nentries)
1519 return uentry_undefined;
1522 return (globtab->entries[uid]);
1526 usymtab_isBoolType (usymId uid)
1527 /*@globals globtab@*/
1529 llassert (uid >= 0 && uid < globtab->nentries);
1531 return (cstring_equal (uentry_rawName (globtab->entries[uid]),
1532 context_getBoolName ()));
1536 usymtab_getTypeEntryName (usymId uid)
1537 /*@globals globtab@*/
1543 return (cstring_makeLiteral ("<freetype>"));
1546 ue = usymtab_getTypeEntry (uid);
1548 if (dbgload && !uentry_isValid (ue))
1550 return (message ("<missing type: %d>", uid));
1553 llassertprint (uentry_isValid (ue), ("type undefined: %d", uid));
1555 return (uentry_getName (ue));
1558 /*@unused@*/ static void
1559 usymtab_rehash (/*@notnull@*/ usymtab s)
1563 if (cstringTable_isDefined (s->htable))
1565 cstringTable_free (s->htable);
1568 s->htable = cstringTable_create (LLHASHSIZE);
1570 for (i = 0; i < s->nentries; i++)
1572 cstringTable_insert (s->htable, cstring_copy (uentry_rawName (s->entries[i])), i);
1577 ** superficial copy of usymtab
1579 ** DO copy spec entries
1582 static /*@only@*/ /*@notnull@*/ usymtab
1583 usymtab_shallowCopy (/*@notnull@*/ usymtab s) /*@*/
1585 usymtab copytab = usymtab_createRoot ();
1588 for (i = 0; i < s->nentries; i++)
1590 usymtab_addEntryBase (copytab, s->entries[i]);
1597 usymtab_shallowFree (/*@only@*/ /*@notnull@*/ usymtab s)
1599 aliasTable_free (s->aliases);
1600 refTable_free (s->reftable, s->nentries);
1602 /*@-compdestroy@*/ sfree (s); /*@=compdestroy@*/
1606 ** converts usymId from old table to sorted one
1610 usymtab_convertId (usymId uid)
1611 /*@globals oldtab, utab@*/
1617 llassert (usymtab_isDefined (oldtab));
1619 ue = usymtab_getEntryAux (oldtab, uid);
1621 llassertprint (uentry_isValid (ue), ("convertId: undefined: %d", uid));
1623 name = uentry_rawName (ue);
1625 ret = usymtab_getIndex (utab, name);
1626 llassert (ret == uid); /*! for now, no rehash! */
1627 DPRINTF (("Convert: %s [%d] -> %s [%d]",
1628 uentry_unparse (ue), uid,
1629 uentry_unparse (utab->entries[ret]), ret));
1631 llassertprint (ret != USYMIDINVALID, ("convertId: return is invalid"));
1637 usymtab_prepareDump (void)
1638 /*@globals oldtab, utab@*/
1639 /*@modifies oldtab, utab@*/
1641 llassert (usymtab_inGlobalScope ());
1642 llassert (oldtab == usymtab_undefined);
1645 DPRINTF (("Preparing to dump:"));
1646 usymtab_printAll ();
1649 oldtab = usymtab_shallowCopy (utab);
1652 ** alpha compare - make sure order is same on different platforms
1653 ** error messages appear in same order
1657 qsort (utab->entries, (size_t)utab->nentries,
1658 sizeof (*utab->entries),
1659 (int (*)(const void *, const void *)) uentry_xcomparealpha);
1661 usymtab_rehash (utab);
1665 DPRINTF (("After rehash:"));
1666 usymtab_printAll ();
1670 void usymtab_dump (FILE *fout)
1671 /*@globals utab, oldtab@*/
1674 bool neednl = FALSE;
1675 uentry lastentry = uentry_undefined;
1676 ekind lastekind = KINVALID;
1680 ** must call prepareDump first
1683 llassert (oldtab != usymtab_undefined);
1685 for (i = 0; i < utab->nentries; i++)
1687 uentry thisentry = utab->entries[i];
1688 ekind thisekind = uentry_getKind (thisentry);
1690 if (!uentry_hasRealName (thisentry))
1692 llassert (uentry_isGlobalMarker (thisentry));
1696 check (fputc ('\n', fout) == (int) '\n');
1699 fprintf (fout, "*%d (GlobalMarker)\n", KGLOBALMARKER);
1700 lastekind = KINVALID;
1706 if (thisekind != lastekind)
1710 check (fputc ('\n', fout) == (int) '\n');
1714 lastentry = uentry_undefined;
1715 fprintf (fout, "*%d (%s)\n", ekind_toInt (thisekind),
1716 cstring_toCharsSafe (ekind_capName (thisekind)));
1717 lastekind = thisekind;
1722 ** evans - 2001-02-18 - added the - 48 fudge factor...
1723 ** extra characters dumped, but I haven't counded them carefully...
1726 if (uentry_isInvalid (lastentry) || !uentry_equiv (lastentry, thisentry)
1727 || (linelen > (MAX_DUMP_LINE_LENGTH - (2 * MAX_NAME_LENGTH) - 48)))
1731 DPRINTF (("Dumping entry: %d", i));
1732 cdump = message ("^%d %q", i, uentry_dump (thisentry));
1733 /* was: cdump = uentry_dump (thisentry)); */
1735 lastentry = thisentry;
1738 check (fputc ('\n', fout) == (int) '\n');
1742 linelen += cstring_length (cdump);
1744 /* no new line here! */
1745 if (cstring_length (cdump) > 0)
1747 check (fputs (cstring_toCharsSafe (cdump), fout) != EOF);
1750 cstring_free (cdump);
1755 cstring cdump = uentry_rawName (thisentry);
1756 DPRINTF (("Raw name: %s", cdump));
1757 linelen += (cstring_length (cdump) + 1);
1758 fprintf (fout, "#%s", cstring_toCharsSafe (cdump));
1765 check (fputc ('\n', fout) == (int) '\n');
1768 lastekind = KINVALID;
1770 fprintf(fout, ";; Library constraints\n");
1771 for (i = 0; i < utab->nentries; i++)
1773 uentry thisentry = utab->entries[i];
1775 if (uentry_isFunction (thisentry) )
1777 constraintList preconditions;
1778 constraintList postconditions;
1780 preconditions = uentry_getFcnPreconditions (thisentry);
1781 postconditions = uentry_getFcnPostconditions (thisentry);
1783 if ( constraintList_isDefined(preconditions) ||
1784 constraintList_isDefined(postconditions) )
1786 fprintf(fout,"%s\n", cstring_toCharsSafe (uentry_rawName(thisentry) ) );
1787 if (constraintList_isDefined(preconditions) )
1789 fprintf(fout,"pre:\n");
1790 constraintList_dump(preconditions, fout);
1791 fprintf (fout, ";; end precondition constraints\n" );
1792 constraintList_free(preconditions);
1796 fprintf(fout,"pre:EMPTY\n");
1798 if (constraintList_isDefined(postconditions) )
1800 fprintf(fout,"post:\n");
1801 constraintList_dump(postconditions, fout);
1802 fprintf (fout, ";; end precondition constraints\n" );
1803 constraintList_free(postconditions);
1807 fprintf(fout,"post:EMPTY\n");
1818 void usymtab_load (FILE *f)
1819 /*@globals utab, globtab@*/
1820 /*@modifies utab, *f@*/
1822 char *s = mstring_create (MAX_DUMP_LINE_LENGTH);
1824 ekind kind = KINVALID;
1825 fileloc loc = g_currentloc;
1831 llassert (utab == globtab);
1832 llassert (utab->nentries == 0);
1834 while (((s = reader_readLine (f, s, MAX_DUMP_LINE_LENGTH)) != NULL)
1837 /* ignore ; comments */ ;
1840 while (s != NULL && *s != ';')
1848 ek = reader_getInt (&s);
1850 if (ek == KGLOBALMARKER)
1852 uentry lue = uentry_makeGlobalMarker ();
1853 DPRINTF (("Adding global marker: %s", uentry_unparseFull (lue)));
1854 usymtab_addEntryAlways (utab, lue);
1860 kind = ekind_fromInt (ek);
1868 (cstring_makeLiteral
1869 ("Library is in obsolete format. Use lclint +whichlib "
1870 "to see which library is being loaded."));
1873 if (reader_optCheckChar (&s, '^'))
1875 index = reader_getInt (&s);
1882 llassert (kind != KINVALID);
1883 ue = uentry_undump (kind, loc, &s);
1885 llassert (utab->nentries == index || index == -1);
1887 if (uentry_isValid (ue))
1889 int lastindex = utab->nentries;
1890 ue = usymtab_addEntryAlways (utab, ue);
1891 if (utab->nentries != lastindex + 1)
1893 DPRINTF (("No add: %s", uentry_unparseFull (ue)));
1901 ** now, any other names are the same uentry
1904 while (*(s++) == '#')
1906 cstring name = cstring_fromCharsO (reader_getWord (&s));
1907 uentry nue = uentry_nameCopy (name, ue);
1909 DPRINTF (("Name copy: %s", uentry_unparseFull (nue)));
1913 usymtab_addEntryAlways (utab, nue);
1916 while ((c = *s) != '\0' && (c !='\n'))
1918 if (c != ' ' || c != '\t')
1920 llbuglit ("Junk in load file");
1928 s = reader_readLine (f, os, MAX_DUMP_LINE_LENGTH);
1933 to handle reading of buffer overflow related constraints
1935 while (fgets (s, MAX_DUMP_LINE_LENGTH, f) != NULL
1938 ; /* ignore ;-comments */
1941 while (s != NULL && *s != ';')
1943 constraintList preconditions;
1944 constraintList postconditions;
1946 cstring name = cstring_fromChars(reader_getWord(&s) );
1948 ue = usymtab_lookup ( name );
1952 preconditions = constraintList_undefined;
1953 postconditions = constraintList_undefined;
1955 if (!uentry_isValid(ue) )
1957 llfatalbug ((message("Invalid uentry for %s library file may be corrupted", cstring_fromChars(s) ) ));
1959 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
1961 temp = cstring_fromChars(reader_getWord(&s) );
1963 if (cstring_compareLit (temp,"pre:") == 0 )
1965 preconditions = constraintList_undump (f);
1969 if (cstring_compareLit (temp,"pre:EMPTY") != 0 )
1970 llfatalbug ((message("Error reading library file pre:EMPTY expected but got %s", temp ) ));
1975 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
1977 temp = cstring_fromChars(reader_getWord(&s) );
1978 if (cstring_compareLit (temp,"post:") == 0 )
1980 postconditions = constraintList_undump (f);
1984 if (cstring_compareLit (temp,"post:EMPTY") != 0 )
1985 llfatalbug ((message("Error reading library file post:EMPTY expected but got %s", temp ) ));
1990 uentry_setPreconditions (ue, functionConstraint_createBufferConstraint (preconditions));
1991 uentry_setPostconditions (ue, functionConstraint_createBufferConstraint (postconditions));
1993 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2001 ** file scope for static variables
2005 usymtab_enterFile ()
2006 /*@globals utab, globtab, filetab@*/
2007 /*@modifies filetab@*/
2009 llassert (utab == globtab);
2014 usymtab_entries (globtab, ue)
2016 if (sRef_hasDerived (uentry_getSref (ue)))
2018 fprintf (g_msgstream, "Derived Global: %s\n", uentry_unparse (ue));
2019 fprintf (g_msgstream, "sRef: %s\n", sRef_unparseFull (ue->sref));
2021 } end_usymtab_entries ;
2025 usymtab_enterScope ();
2031 /*@globals utab, filetab@*/
2032 /*@modifies filetab, utab@*/
2035 llassert (utab->lexlevel == 1);
2037 usymtab_exitScope (exprNode_undefined);
2042 usymtab_enterScope ()
2043 /*@globals utab, globtab, filetab@*/
2046 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
2048 /* unconditional scope: optimize to avoid copy */
2049 t->aliases = aliasTable_copy (utab->aliases);
2052 llassert (usymtab_isDefined (t->env));
2054 if (t->env->lexlevel == paramsScope && context_inFunctionLike ())
2056 noshadowerror = TRUE;
2057 usymtab_handleParams ();
2058 noshadowerror = FALSE;
2063 ** setup external references:
2064 ** o only, unique params alias external args
2065 ** o other params may alias anything of their type
2069 usymtab_handleParams (void)
2070 /*@globals utab, globtab, filetab@*/
2071 /*@modifies utab, globtab@*/
2073 usymtab ptab = utab->env;
2074 uentry fcn = context_getHeader ();
2076 usymtab_entries (ptab, param)
2080 if (!uentry_isYield (param))
2083 sRef pref = uentry_getSref (param);
2085 /* Could be a global. */
2087 if (uentry_isAnyParam (param))
2089 ue = uentry_makeVariable (fixParamName (uentry_rawName (param)),
2090 uentry_getType (param),
2091 fileloc_copy (uentry_whereDeclared (param)),
2094 uentry_copyState (ue, param);
2095 uentry_setRefParam (ue);
2097 ue = usymtab_supEntrySrefReturn (ue);
2099 /* must be after supercede! */
2101 if (!sRef_stateKnown (pref))
2103 uentry_setDefState (ue, SS_DEFINED);
2104 uentry_setDefState (param, SS_DEFINED);
2108 if (sRef_isStateSpecial (pref))
2110 uentry_setDefState (ue, SS_ALLOCATED);
2114 uentry_setDefState (ue, sRef_getDefState (pref));
2118 uref = uentry_getSref (ue);
2120 if (sRef_isStack (uref))
2122 alkind pkind = sRef_getAliasKind (pref);
2124 if (alkind_isKnown (pkind) && !alkind_isLocal (pkind)
2125 && !alkind_isStack (pkind))
2127 sRef_setAliasKind (uref, pkind, fileloc_undefined);
2128 sRef_setOrigAliasKind (uref, pkind);
2132 sRef_setAliasKind (uref, AK_IMPTEMP, fileloc_undefined);
2133 sRef_setOrigAliasKind (uref, AK_IMPTEMP);
2135 if (uentry_isOut (param))
2141 sRef_setDefined (uref, fileloc_undefined);
2147 usymtab_addMustAlias (uref, pref);
2149 if (!(uentry_isOnly (param) || uentry_isUnique (param)))
2152 ** This is needed for detecting possibly aliased parameters.
2155 sRef s = sRef_makeExternal (uref);
2156 usymtab_addMustAlias (uref, s);
2159 if (sRef_isKillRef (pref))
2161 sRef_setAliasKind (uref, AK_NEWREF, fileloc_undefined);
2162 sRef_setOrigAliasKind (uref, AK_KILLREF);
2164 else if (sRef_isRefCounted (uref))
2166 sRef_setOrigAliasKind (uref, AK_REFCOUNTED);
2171 sRef_setOrigAliasKind (uref, AK_LOCAL);
2178 } end_usymtab_entries;
2181 if (uentry_hasStateClauseList (fcn))
2183 stateClauseList clauses = uentry_getStateClauseList (fcn);
2185 stateClauseList_preElements (clauses, cl)
2187 fileloc loc = stateClause_loc (cl);
2188 sRefSet osrs = sRefSet_undefined;
2191 if (stateClause_isGlobal (cl))
2193 DPRINTF (("Global Marker: %s",
2194 sRef_unparseFull (usymtab_lookupGlobalMarker ())));
2195 llassert (sRef_isGlobalMarker (usymtab_lookupGlobalMarker ()));
2196 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
2201 srs = stateClause_getRefs (cl);
2204 sRefSet_elements (srs, el)
2206 sRef base = sRef_getRootBase (el);
2207 sRef sb = sRef_updateSref (el);
2209 if (sRef_isResult (base))
2211 ; /* nothing to do before */
2213 else if (sRef_isParam (base) || sRef_isGlobalMarker (base))
2215 if (stateClause_setsMetaState (cl))
2217 /* copied from exprNode.c:3040 */
2218 qual ql = stateClause_getMetaQual (cl);
2219 annotationInfo ainfo = qual_getAnnotationInfo (ql);
2220 metaStateInfo minfo = annotationInfo_getState (ainfo);
2221 cstring key = metaStateInfo_getName (minfo);
2222 int mvalue = annotationInfo_getValue (ainfo);
2224 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
2226 if (sRef_isResult (base))
2232 sRef_setMetaStateValueComplete (sb, key, mvalue, loc);
2237 sRefMod modf = stateClause_getEntryFunction (cl);
2241 sRefSet aliases = usymtab_allAliases (sb);
2245 sRefSet_elements (aliases, sr)
2248 } end_sRefSet_elements ;
2250 sRefSet_free (aliases);
2256 if (sRef_isValid (base))
2258 DPRINTF (("Base: %s", sRef_unparseFull (base)));
2262 } end_sRefSet_elements ;
2263 } end_stateClauseList_preElements ;
2268 usymtab_enterFunctionScope (uentry fcn)
2269 /*@globals utab, filetab, globtab@*/
2272 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
2274 if (utab->lexlevel != fileScope)
2276 if (utab->lexlevel > fileScope)
2278 llparseerror (cstring_makeLiteral ("New function scope inside function."));
2280 while (utab->lexlevel > fileScope)
2282 /*@i@*/ utab = usymtab_dropEnv (utab);
2289 llfatalbug (cstring_makeLiteral ("New function not inside file."));
2291 /*@-branchstate@*/ } /*@=branchstate@*/
2295 DPRINTF (("Globs: %s", globSet_unparse (uentry_getGlobs (fcn))));
2297 globSet_allElements (uentry_getGlobs (fcn), el)
2299 DPRINTF (("Here we go: %s", sRef_unparseFull (el)));
2301 if (sRef_isUndefGlob (el))
2303 int index = sRef_getScopeIndex (el);
2304 sRef sr = sRef_updateSref (el);
2305 fileloc loc = uentry_whereEarliest (fcn);
2307 DPRINTF (("update: %s", sRef_unparseFull (sr)));
2308 DPRINTF (("Undef!"));
2309 if (sRef_isFileStatic (el))
2311 ctype ct = sRef_getType (el);
2314 llassert (usymtab_isDefined (filetab));
2316 ue = usymtab_fetchIndex (filetab, index);
2318 if (ctype_isRealArray (ct) || ctype_isRealSU (ct))
2320 sRef_setAllocated (sr, loc);
2324 sRef_setUndefined (sr, loc);
2329 uentry ue = globtab->entries[index];
2330 ctype ct = uentry_getType (ue);
2332 if (ctype_isArray (ct) || ctype_isSU (ct))
2334 sRef_setAllocated (sr, loc);
2338 sRef_setUndefined (sr, loc);
2342 else if (sRef_isAllocated (el))
2344 sRef sr = sRef_updateSref (el);
2345 fileloc loc = uentry_whereEarliest (fcn);
2347 sRef_setAllocated (sr, loc);
2349 else if (sRef_isPartial (el))
2351 sRef sr = sRef_updateSref (el);
2352 fileloc loc = uentry_whereEarliest (fcn);
2354 sRef_setPartial (sr, loc);
2359 sRef sr = sRef_updateSref (el);
2360 fileloc loc = uentry_whereEarliest (fcn);
2362 sRef_setDefined (sr, loc);
2366 /* shouldn't need to do anything! */
2368 } end_globSet_allElements;
2370 DPRINTF (("Globs after: %s", globSet_unparse (uentry_getGlobs (fcn))));
2374 usymtab_caseBranch (void)
2377 usymtab t = usymtab_create (US_CBRANCH, utab, FALSE);
2382 usymtab_switchBranch (/*@unused@*/ exprNode s)
2385 usymtab t = usymtab_create (US_SWITCH, utab, FALSE);
2387 t->aliases = aliasTable_copy (utab->aliases);
2392 usymtab_trueBranch (/*@only@*/ guardSet guards)
2395 usymtab t = usymtab_create (US_TBRANCH, utab, FALSE);
2398 ** not true! (could be in a macro)
2400 ** llassertprint (utab->lexlevel > paramsScope,
2401 ** ("not in scope: %s", usymtab_unparseLocal ()));
2405 guardSet_free (t->guards);
2408 aliasTable_free (t->aliases);
2409 t->aliases = aliasTable_copy (utab->aliases);
2417 ** { int a; if (...) a = 3; < a may be undefined here!
2422 usymtab_popTrueBranch (exprNode pred, exprNode expr, clause cl) /*@modifies utab@*/
2425 ** add a false branch
2426 ** (could be done more efficiently as a special case, but
2427 ** it is better to only maintain one version of the code)
2430 if (utab->kind != US_TBRANCH
2431 && context_inIterDef ())
2433 usymtab_exitScope (expr);
2437 DPRINTF (("pop true branch.."));
2438 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2439 usymtab_popBranches (pred, expr, exprNode_undefined, TRUE, cl);
2444 usymtab_popCaseBranch () /*@modifies utab@*/
2446 llassert (utab->kind == US_CBRANCH);
2447 usymtab_quietPlainExitScope ();
2451 usymtab_popTrueExecBranch (exprNode pred, exprNode expr, clause cl)
2454 ** add a false branch that must return --- that is,
2455 ** the true branch is always executed!
2458 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2459 usymtab_popBranches (pred, expr, exprNode_makeMustExit (), FALSE, cl);
2463 usymtab_popOrBranch (exprNode pred, exprNode expr)
2467 usymtab env = utab->env;
2468 usymtab otab = utab;
2471 llassert (env != NULL);
2473 if (exprNode_isError (expr))
2479 mustReturn = exprNode_mustEscape (expr);
2483 llassert (utab->kind == US_TBRANCH);
2486 ** merge each entry in table with its original
2487 ** unless execution cannot continue after this branch
2490 for (i = 0; i < utab->nentries; i++)
2492 uentry current = utab->entries[i];
2493 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2495 uentry_mergeState (old, current, exprNode_loc (expr),
2496 mustReturn, FALSE, TRUE, ORCLAUSE);
2502 env->guards = guardSet_levelUnionFree (env->guards,
2503 guardSet_invert (exprNode_getGuards (pred)),
2508 env->aliases = aliasTable_levelUnion (env->aliases, otab->aliases, env->lexlevel);
2511 /* env is now utab */
2512 usymtab_quietPlainExitScope ();
2516 ** case syntax in C is very unrestricted. This is unfortunate.
2518 ** A switch case is ended either by a new case or default, or
2519 ** a close } that may close the switch or some other control
2524 usymtab_newCase (/*@unused@*/ exprNode pred, exprNode last)
2527 bool mustBreak = usymtab_mustBreak (utab);
2528 bool mustReturn = usymtab_mustEscape (utab);
2529 usymtab stab = utab;
2532 ** Find last case (or outer switch)
2535 while (stab->kind != US_CBRANCH && stab->kind != US_SWITCH)
2538 llassert (stab != GLOBAL_ENV);
2543 while (stab->kind == US_CBRANCH)
2546 llassert (stab != GLOBAL_ENV);
2550 ** if its a fall through case, merge in outside entries and last case.
2555 ** case 1: x = 3; <fall through>
2556 ** case 2: << x may not be defined
2560 if (!mustBreak && !mustReturn && utab->kind == US_CBRANCH)
2562 llassert (stab->kind == US_SWITCH || stab->kind == US_NORMAL);
2564 usymtab_entries (utab, ue) /* but, keep track of used variables */
2566 uentry old = usymtab_lookupAux (stab, uentry_rawName (ue));
2568 llassert (uentry_isValid (old));
2570 /* modifies ue, not old */
2572 uentry_mergeState (ue, old, exprNode_loc (last),
2573 FALSE, FALSE, TRUE, CASECLAUSE);
2574 } end_usymtab_entries;
2576 utab->aliases = aliasTable_levelUnion (utab->aliases,
2577 stab->aliases, utab->lexlevel);
2580 ** No need for a new branch.
2587 usymtab_caseBranch ();
2588 /*@-mustfree@*/ /*< utab->aliases >*/
2589 utab->aliases = aliasTable_copy (stab->aliases);
2597 ** for && (both pred and expr are executed)
2601 usymtab_popAndBranch (exprNode pred, /*@unused@*/ exprNode expr)
2604 usymtab env = utab->env;
2608 llassert (utab->kind == US_TBRANCH);
2611 ** merge each entry in table with its original
2612 ** unless execution cannot continue after this branch
2615 for (i = 0; i < utab->nentries; i++)
2617 uentry current = utab->entries[i];
2618 sRef tref = uentry_getSref (current);
2619 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2620 sRef oref = uentry_getSref (old);
2622 /* note that is current is in a nested branch,
2623 it may create a "new" old entry. */
2625 llassert (uentry_isValid (old));
2626 uentry_mergeState (old, current, exprNode_loc (expr),
2627 FALSE, FALSE, TRUE, ANDCLAUSE);
2630 ** if is it defined by the second clause, then it should be defined.
2633 if (sRef_isAnyDefined (tref)
2634 && (sRef_isAllocated (oref) || sRef_isStateUndefined (oref)))
2636 sRef_setDefined (oref, g_currentloc);
2640 utab->guards = guardSet_levelUnionFree (utab->guards,
2641 guardSet_invert (exprNode_getGuards (pred)),
2643 utab->aliases = aliasTable_levelUnion (utab->aliases, otab->aliases, utab->lexlevel);
2645 usymtab_quietPlainExitScope ();
2650 ** Stack should be [ US_CBRANCH+ US_SWITCH ]
2651 ** Only branches which do not return (except possibly the last branch) are included.
2653 ** Conditionally merge state from all CBRANCHes.
2655 ** If allpaths is TRUE, then all possible executions go through some switch
2656 ** case, and the original scope is not merged.
2660 usymtab_exitSwitch (/*@unused@*/ exprNode sw, bool allpaths)
2663 usymtab ttab = utab;
2664 usymtab stab = ttab;
2665 usymtab ltab = ttab;
2666 bool lastMustReturn = usymtab_mustEscape (utab);
2670 while (stab->kind == US_CBRANCH)
2673 llassert (stab != GLOBAL_ENV);
2676 while (stab->kind == US_NORMAL)
2679 llassert (stab != GLOBAL_ENV);
2682 llassert (stab->kind == US_SWITCH);
2684 /* go to the scope outside the switch (US_SWITCH is just a marker! */
2686 llassert (stab != GLOBAL_ENV);
2690 llassert (usymtab_isDefined (ttab));
2692 if (ttab->kind == US_CBRANCH)
2694 /* was quietPlainExitScope --- but, can't free it yet! */
2696 llassert (utab != GLOBAL_ENV);
2698 while (ttab->kind == US_CBRANCH)
2701 ** (from popTrueBranch)
2704 bool mustReturn = usymtab_mustEscape (ttab);
2705 bool mustBreak = usymtab_mustBreak (ttab);
2707 usymtab_entries (ttab, current)
2709 uentry old = /*@-compmempass@*/ usymtab_lookupAux (ltab, uentry_rawName (current));
2713 ** note that is this is in a nested branch,
2714 ** it may create a "new" old entry.
2717 if (uentry_isValid (old))
2721 uentry_mergeUses (current, old);
2722 uentry_setState (old, current);
2726 uentry_mergeState (old, current, exprNode_loc (sw),
2727 mustReturn, FALSE, TRUE, SWITCHCLAUSE);
2734 } end_usymtab_entries;
2737 ** if entry is not in symbol table for this case, merge with pre-switch
2741 if (!mustReturn && !mustBreak)
2743 usymtab_entries (stab, current)
2745 if (usymtab_getIndex (ttab, uentry_rawName (current)) == NOT_FOUND)
2747 uentry old = /*@-compmempass@*/
2748 usymtab_lookupAux (ltab, uentry_rawName (current));
2751 llassert (uentry_isValid (old));
2752 uentry_mergeState (old, current, exprNode_loc (sw),
2753 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2755 } end_usymtab_entries;
2758 ltab->env = ttab->env;
2762 ** Suprious error, becuase of environments.
2765 /*@i1@*/ utab = ltab;
2767 lastMustReturn = FALSE;
2774 ** now, there is one US_CBRANCH. Merge this with the stab.
2778 for (i = 0; i < ltab->nentries; i++)
2780 uentry current = ltab->entries[i];
2781 uentry old = usymtab_lookupAux (stab, uentry_rawName (current));
2783 /* note that is this is in a nested branch,
2784 it may create a "new" old entry. */
2787 if (uentry_isValid (old))
2791 uentry_mergeUses (current, old);
2792 uentry_setState (old, current);
2796 uentry_mergeState (old, current, exprNode_loc (sw),
2797 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2811 ** switch may or may not be followed by a new scope
2814 if (utab->kind == US_SWITCH)
2816 usymtab_quietPlainExitScope ();
2820 usymtab_quietPlainExitScope ();
2821 llassert (utab->kind == US_SWITCH);
2822 usymtab_quietPlainExitScope ();
2828 updateNullState (sRef el, /*@notnull@*/ usymtab ttab,
2829 /*@notnull@*/ usymtab ftab, bool trueGuard)
2831 sRef base = sRef_getRootBase (el);
2832 int level = sRef_lexLevel (base);
2834 if (sRef_isCvar (base))
2836 usymId index = sRef_getScopeIndex (base);
2837 uentry ue = usymtab_getRefTab (ttab, level, index);
2839 if (!uentry_isLset (ue))
2841 sRef sr = uentry_getSref (ue);
2845 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2849 if (!guardSet_isGuarded (ttab->guards, el)
2850 && !sRef_isNotNull (sr))
2852 sRef_setDerivNullState (sr, el, NS_DEFNULL);
2860 ue = usymtab_getRefTab (ftab, level, index);
2862 if (!uentry_isLset (ue))
2864 sRef sr = uentry_getSref (ue);
2867 if (!trueGuard) /* yikes! forgot the ! */
2869 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2874 if (!guardSet_isGuarded (ftab->guards, el)
2875 && !sRef_isNotNull (sr))
2877 sRef_setDerivNullState (sr, el, NS_DEFNULL);
2889 usymtab_popBranches (exprNode pred, exprNode tbranch, exprNode fbranch,
2890 bool isOpt, clause cl)
2894 usymtab ftab = utab;
2895 usymtab ttab = utab->env;
2899 guardSet guards = exprNode_getGuards (pred);
2900 sRefSet tguards = guardSet_getTrueGuards (guards);
2901 sRefSet fguards = guardSet_getFalseGuards (guards);
2902 bool mustReturnT = exprNode_mustEscape (tbranch);
2903 bool mustReturnF = exprNode_mustEscape (fbranch);
2905 DPRINTF (("Pop branches: %s [mustreturn: %s/%s]", exprNode_unparse (pred),
2906 bool_unparse (mustReturnT),
2907 bool_unparse (mustReturnF)));
2909 if (exprNode_isDefined (fbranch))
2911 loc = exprNode_loc (fbranch);
2915 loc = exprNode_loc (tbranch);
2918 llassert (usymtab_isDefined (ttab));
2922 llassert (usymtab_isDefined (env));
2923 llassert (ftab->kind == US_FBRANCH);
2924 llassert (ttab->kind == US_TBRANCH);
2927 ** For each element that is true guarded (i.e., if (x != NULL))
2928 ** make x = null in false branch,
2929 ** and x = notnull in true branch.
2930 ** unless x was set locally in that branch.
2931 ** For each element that is false guarded (x == NULL)
2932 ** make x = null in true, notnull in false.
2934 ** For each element that is either guarded (pred(x))
2938 sRefSet_allElements (tguards, el)
2940 updateNullState (el, ttab, ftab, TRUE);
2941 } end_sRefSet_allElements;
2943 sRefSet_allElements (fguards, el)
2945 updateNullState (el, ttab, ftab, FALSE);
2946 } end_sRefSet_allElements;
2950 ** if an entry is in both true and false, merge the entries,
2951 ** then replace original with new state.
2953 ** if an entry is in one table, merge it with the original.
2956 DPRINTF (("ftab: %d", ftab->nentries));
2958 for (i = 0; i < ftab->nentries; i++)
2960 uentry fthis = ftab->entries[i];
2961 uentry old = usymtab_lookupAux (env, uentry_rawName (fthis));
2962 int tindex = usymtab_getIndex (ttab, uentry_rawName (fthis));
2964 DPRINTF (("Entry: %s / %s", uentry_unparseFull (fthis), uentry_unparseFull (old)));
2966 if (uentry_isUndefined (old))
2968 /* possible entry was added as an undefined id */
2969 DPRINTF (("Undefined! %s", uentry_rawName (fthis)));
2973 if (tindex != NOT_FOUND)
2975 uentry tthis = ttab->entries[tindex];
2977 /* note that is this is in a nested branch,
2978 it may create a "new" old entry. */
2984 uentry_mergeState (fthis, tthis, loc,
2985 mustReturnT, FALSE, FALSE, cl);
2989 uentry_mergeUses (fthis, tthis);
2992 uentry_setState (old, fthis);
2999 uentry_setState (old, tthis);
3000 uentry_mergeState (old, fthis, loc, mustReturnF,
3004 ttab->entries[tindex] = uentry_undefined;
3005 uentry_free (tthis);
3009 uentry_mergeState (old, fthis, loc, mustReturnF, TRUE, FALSE, cl);
3013 for (i = 0; i < ttab->nentries; i++)
3015 uentry current = ttab->entries[i];
3017 DPRINTF (("ttab: %s", uentry_unparseFull (current)));
3019 if (!uentry_isUndefined (current))
3021 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
3023 DPRINTF (("Old: %s", uentry_unparseFull (old)));
3025 if (uentry_isUndefined (old))
3027 llcontbug (message ("Undefined entry: %s", uentry_rawName (current)));
3033 uentry_mergeUses (current, old);
3034 uentry_setState (old, current);
3039 ** Assumes false branch is a fall-through if
3040 ** fbranch is not defined. This is true, unless
3041 ** where was some greivous error in processing
3042 ** the else branch of an if-then, in which case
3043 ** this is probably the right thing to do anyway.
3046 uentry_mergeState (old, current, loc, mustReturnT,
3050 DPRINTF (("==> %s", uentry_unparseFull (old)));
3055 ** Plain levelUnion doesn't work, since we need to use the sRef's in env->aliases
3056 ** if they are present.
3059 llassert (NOALIAS (env->aliases, ttab->aliases));
3060 llassert (NOALIAS (env->aliases, ftab->aliases));
3062 aliasTable_free (env->aliases);
3064 env->aliases = aliasTable_levelUnionNew (ttab->aliases,
3065 ftab->aliases, env->lexlevel);
3067 aliasTable_fixSrefs (env->aliases);
3069 DPRINTF (("Aliases: %s", aliasTable_unparse (env->aliases)));
3071 /* exit true and false scopes */
3072 usymtab_quietPlainExitScope ();
3073 usymtab_quietPlainExitScope ();
3077 utab->guards = guardSet_levelUnionFree
3079 guardSet_invert (exprNode_getGuards (pred)),
3085 utab->guards = guardSet_levelUnion (utab->guards,
3086 exprNode_getGuards (pred),
3090 DPRINTF (("Here."));
3093 static void usymtab_fixCases (void) /*@modifies utab@*/ {
3094 while (utab->kind == US_CBRANCH)
3096 usymtab_quietPlainExitScope ();
3099 llassert (utab->kind != US_CBRANCH);
3103 usymtab_altBranch (/*@only@*/ guardSet guards)
3107 usymtab parent = utab->env;
3109 t = usymtab_create (US_FBRANCH, utab, FALSE);
3112 ** If we are in a case, need to close it. The C syntax
3113 ** is very liberal, so this kludge is necessary.
3116 usymtab_fixCases ();
3118 DPRINTF (("Current kind: %s", usymtab_unparseStack ()));
3120 llassert (utab->kind == US_TBRANCH);
3121 llassert (parent != GLOBAL_ENV);
3123 guardSet_free (t->guards);
3126 aliasTable_free (t->aliases);
3127 t->aliases = aliasTable_copy (parent->aliases);
3133 usymtab_allDefined (void)
3134 /*@globals utab, globtab@*/
3138 llassert (utab == globtab);
3140 for (i = 0; i < utab->nentries; i++)
3142 uentry e = utab->entries[i];
3144 if (uentry_isPriv (e))
3146 ; /* no need to define it */
3150 if (context_getFlag (FLG_SPECUNDECL))
3152 fileloc sloc = uentry_whereSpecified (e);
3153 fileloc dloc = uentry_whereDeclared (e);
3155 if (fileloc_isDefined (sloc)
3156 && !uentry_isFakeTag (e)
3157 && !fileloc_isDefined (dloc))
3161 message ("%s %q specified but not declared",
3162 ekind_capName (uentry_getKind (e)),
3163 uentry_getName (e)),
3168 if (!uentry_isCodeDefined (e))
3170 fileloc dloc = uentry_whereDeclared (e);
3172 if (fileloc_isLib (dloc) || fileloc_isXHFile (dloc))
3176 else if (fileloc_isDefined (dloc))
3178 if (!uentry_isAnyTag (e))
3180 if (fileloc_isUser (dloc))
3184 message ("%s %q declared but not defined",
3185 ekind_capName (uentry_getKind (e)),
3186 uentry_getName (e)),
3193 fileloc sloc = uentry_whereSpecified (e);
3195 if (fileloc_isDefined (sloc)
3196 && !fileloc_isImport (sloc)
3197 && !fileloc_isLib (sloc)
3198 && !fileloc_isPreproc (sloc)
3199 && !uentry_isFakeTag (e))
3201 if (uentry_isVariable (e) || uentry_isFunction (e))
3205 message ("%s %q specified but not declared or defined",
3206 ekind_capName (uentry_getKind (e)),
3207 uentry_getName (e)),
3214 message ("%s %q specified but not defined",
3215 ekind_capName (uentry_getKind (e)),
3216 uentry_getName (e)),
3226 void usymtab_exportHeader (void)
3231 for (i = 0; i < utab->nentries; i++)
3233 uentry ce = utab->entries[i];
3235 if (!uentry_isDatatype (ce)
3236 && !uentry_isAnyTag (ce)
3237 && !uentry_isEitherConstant (ce) && !uentry_isStatic (ce)
3238 && !uentry_isExternal (ce)
3239 && !uentry_isForward (ce))
3241 fileloc fwhere = uentry_whereDeclared (ce);
3243 if (fileloc_isUndefined (fwhere)
3244 && uentry_isFunction (ce))
3246 fwhere = uentry_whereDefined (ce);
3249 if (fileloc_isDefined (fwhere)
3250 && !fileloc_isHeader (fwhere)
3251 && !fileloc_isXHFile (fwhere)
3252 && !(fileloc_isSpecialFile (fwhere)
3253 && !context_getFlag (FLG_UNUSEDSPECIAL)))
3255 if (uentry_isVariable (ce))
3258 (FLG_EXPORTHEADERVAR,
3259 message ("%s %q exported but not declared in header file",
3260 ekind_capName (uentry_getKind (ce)),
3261 uentry_getName (ce)),
3264 uentry_showDefSpecInfo (ce, fwhere);
3269 if (!uentry_isIter (ce)
3270 && !uentry_isEndIter (ce)
3271 && !uentry_isExpandedMacro (ce))
3273 if (uentry_isFunction (ce)
3274 && cstring_equalLit (uentry_rawName (ce), "main"))
3276 ; /* no error for main */
3282 message ("%s %q exported but not declared "
3284 ekind_capName (uentry_getKind (ce)),
3285 uentry_getName (ce)),
3288 uentry_showDefSpecInfo (ce, fwhere);
3298 void usymtab_exportLocal (void)
3303 for (i = 0; i < utab->nentries; i++)
3305 uentry ce = utab->entries[i];
3307 if (!uentry_isDatatype (ce) && !uentry_isAnyTag (ce)
3308 && !uentry_isEitherConstant (ce)
3309 && !uentry_isIter (ce)
3310 && !uentry_isEndIter (ce)
3311 && !uentry_isExpandedMacro (ce)
3312 && uentry_isUsed (ce))
3314 /* check static uses */
3315 filelocList fuses = uentry_getUses (ce);
3316 fileloc mod = uentry_whereDefined (ce);
3317 bool ok = filelocList_isEmpty (fuses);
3318 fileloc fwhere = uentry_whereDeclared (ce);
3320 if (fileloc_isSpecialFile (fwhere)
3321 && !context_getFlag (FLG_UNUSEDSPECIAL))
3323 ok = TRUE; /* no errors for special files */
3327 filelocList_elements (fuses, uloc)
3329 if (fileloc_isUndefined (uloc) || !fileloc_sameModule (uloc, mod))
3332 /*@innerbreak@*/ break;
3334 } end_filelocList_elements;
3341 message ("%s exported but not used outside %s: %q",
3342 ekind_capName (uentry_getKind (ce)),
3343 fileloc_getBase (mod),
3344 uentry_getName (ce)),
3347 uentry_showDefSpecInfo (ce, fwhere);
3355 usymtab_allUsed (void)
3359 bool isFileStatic = usymtab_inFileScope ();
3360 cstring last_file = cstring_undefined;
3362 for (i = 0; i < utab->nentries; i++)
3364 bool hasError = FALSE;
3365 uentry ce = utab->entries[i];
3366 fileloc fwhere = uentry_whereDeclared (ce);
3368 if (fileloc_isUndefined (fwhere))
3370 fwhere = uentry_whereDefined (ce);
3373 if (fileloc_isInvalid (fwhere)
3374 || fileloc_isLib (fwhere)
3375 || fileloc_isBuiltin (fwhere)
3376 || ((fileloc_isSpecialFile (fwhere)
3377 || fileloc_isSpecialFile (uentry_whereDefined (ce)))
3378 && !context_getFlag (FLG_UNUSEDSPECIAL)))
3382 else if (!uentry_wasUsed (ce) && !uentry_isAnyTag (ce))
3384 cstring fname = fileloc_filename (fwhere);
3386 if (cstring_isUndefined (last_file))
3390 else if (cstring_equal (fname, last_file))
3399 if (uentry_isParam (ce))
3401 if (context_inMacro ())
3403 sRef cref = uentry_getSref (ce);
3405 if (uentry_isYield (ce))
3407 ; /* no checks (for now) */
3409 else if (sRef_isSafe (cref))
3415 if (uentry_hasRealName (ce))
3418 optgenerror (FLG_MACROPARAMS,
3419 message ("Macro parameter %q not used",
3420 uentry_getName (ce)),
3427 if (cstring_equalFree (uentry_getName (ce),
3428 cstring_makeLiteral ("...")))
3434 hasError = optgenerror (FLG_PARAMUNUSED,
3435 message ("Parameter %q not used",
3436 uentry_getName (ce)),
3441 else if (uentry_isFunction (ce) || uentry_isIter (ce))
3443 if (fileloc_isUser (fwhere))
3445 hasError = optgenerror
3447 message ("%q %q declared but not used",
3449 (uentry_isIter (ce) ? "Iterator"
3450 : (isFileStatic ? "File static function" : "Function")),
3451 uentry_getName (ce)),
3455 else if (uentry_isEndIter (ce))
3457 ; /* no error (already reported for iter */
3459 else if (uentry_isEnumConstant (ce))
3461 if (fileloc_isUser (fwhere))
3463 hasError = optgenerror
3465 message ("Enum member %q not used",
3466 uentry_getName (ce)),
3470 else if (uentry_isConstant (ce))
3472 if (fileloc_isUser (fwhere))
3474 hasError = optgenerror
3476 message ("Constant %q declared but not used",
3477 uentry_getName (ce)),
3481 else if (uentry_isDatatype (ce))
3483 if (fileloc_isUser (fwhere))
3485 hasError = optgenerror
3487 message ("Type %q declared but not used",
3488 uentry_getName (ce)),
3492 else if (!uentry_isRefParam (ce) && !uentry_isExpandedMacro (ce))
3493 { /* errors for ref params will be reported in the next scope */
3494 llassertprint (uentry_isVar (ce),
3495 ("ce: %s", uentry_unparseFull (ce)));
3497 if (ctype_isFunction (uentry_getType (ce)))
3499 if (fileloc_isUser (fwhere))
3501 hasError = optgenerror
3503 message ("%q %q declared but not used",
3505 (isFileStatic ? "File static function"
3507 uentry_getName (ce)),
3513 if (fileloc_isUser (fwhere))
3517 hasError = optgenerror
3519 message ("%q %q declared but not used",
3521 (isFileStatic ? "File static variable"
3523 uentry_getName (ce)),
3533 else if ((uentry_isDatatype (ce) || uentry_isAnyTag (ce)))
3534 { /* check all fields */
3535 ctype ct = uentry_getRealType (ce);
3538 while (ctype_isAP (ct))
3540 ct = ctype_getBaseType (ct);
3543 if (ctype_isSU (ct))
3545 uentryList fields = ctype_getFields (ct);
3547 uentryList_elements (fields, field)
3549 if (!uentry_isUsed (field))
3551 if (uentry_hasName (ce))
3553 hasError |= optgenerror
3555 message ("Field %q of %s %q declared but not used",
3556 uentry_getName (field),
3557 cstring_makeLiteralTemp
3558 (ctype_isStruct (ct) ? "structure" : "union"),
3559 uentry_getName (ce)),
3560 uentry_whereEarliest (field));
3566 ** Can't report these errors for unnamed structs.
3567 ** No way to tell when there are multiple consistent
3568 ** unnamed structure types. (Could go through table
3569 ** and mark them all unused...)
3571 hasError |= optgenerror
3573 message ("Field %q of unnamed %s declared but not used",
3574 uentry_getName (field),
3575 cstring_makeLiteralTemp
3576 (ctype_isStruct (ct) ? "structure" : "union")),
3577 uentry_whereEarliest (field));
3582 uentry_setUsed (field, fileloc_undefined);
3584 } end_uentryList_elements;
3594 if (uentry_isParam (ce) && context_inMacro ())
3596 if (fileloc_isDefined (uentry_whereSpecified (ce)))
3598 uentry_showWhereSpecified (ce);
3603 uentry_showDefSpecInfo (ce, fwhere);
3606 uentry_setUsed (ce, fileloc_undefined);
3612 checkGlobalReturn (uentry glob, sRef orig)
3614 sRef sr = uentry_getSref (glob);
3616 DPRINTF (("Check global return: %s // orig: %s // sr: %s",
3617 uentry_unparseFull (glob),
3618 sRef_unparseFull (orig),
3619 sRef_unparseFull (sr)));
3621 DPRINTF (("Is killed: %s", bool_unparse (sRef_isKilledGlob (orig))));
3623 if (context_getFlag (FLG_GLOBSTATE))
3625 DPRINTF (("Is killed: %s", sRef_unparseFull (orig)));
3627 if (sRef_isKilledGlob (orig))
3629 if (sRef_isStateUndefined (sr)
3630 || sRef_isUnuseable (sr)
3631 || sRef_isStateUnknown (sr)
3632 || sRef_isDead (sr))
3638 ctype ct = ctype_realType (uentry_getType (glob));
3640 if (ctype_isVisiblySharable (ct))
3645 ("Killed global %q (type %s) not released before return",
3646 uentry_getName (glob),
3647 ctype_unparse (ct)),
3650 sRef_showStateInfo (sr);
3655 sRef_protectDerivs ();
3656 (void) checkGlobalDestroyed (sr, g_currentloc);
3657 sRef_clearProtectDerivs ();
3663 if (sRef_isStateUndefined (sr))
3665 if (optgenerror (FLG_GLOBSTATE,
3667 ("Function returns with global %q undefined",
3668 uentry_getName (glob)),
3671 sRef_showStateInfo (sr);
3676 if (sRef_isDead (sr))
3680 message ("Function returns with global %q "
3681 "referencing released storage",
3682 uentry_getName (glob)),
3685 sRef_showStateInfo (sr);
3686 sRef_setDefState (sr, SS_UNKNOWN, fileloc_undefined);
3690 if (ctype_isRealPointer (uentry_getType (glob))
3691 && sRef_possiblyNull (sr)
3692 && !uentry_possiblyNull (glob))
3696 message ("Function returns with non-null global %q "
3697 "referencing null storage",
3698 uentry_getName (glob)),
3701 sRef_showNullInfo (sr);
3706 checkGlobReturn (glob);
3714 ** remember: check alias globals
3717 void usymtab_checkFinalScope (bool isReturn)
3720 bool mustFree = context_getFlag (FLG_MUSTFREE);
3721 bool mustDefine = context_getFlag (FLG_MUSTDEFINE);
3722 /* bool mustNotAlias = context_getFlag (FLG_MUSTNOTALIAS); */
3723 sRefSet checked = sRefSet_new ();
3724 usymtab stab = utab;
3728 ** need to check all scopes out to function parameters.
3733 for (i = 0; i < stab->nentries; i++)
3735 uentry ce = stab->entries[i];
3736 sRef sr = uentry_getSref (ce);
3737 sRef rb = sRef_getRootBase (sr);
3741 ** Shouldn't check if shadow checked in deeper scope:
3746 uentry oue = usymtab_lookupQuietNoAlt (utab, uentry_observeRealName (ce));
3748 if (!uentry_sameObject (ce, oue))
3750 DPRINTF (("Skipping outer entry: %s / %s", uentry_unparseFull (ce),
3751 uentry_unparseFull (oue)));
3752 /*@i32 what if it is one an alternate branch? */
3753 /*@innercontinue@*/ continue;
3757 DPRINTF (("Here check final scope: %s", uentry_unparseFull (ce)));
3759 if (ctype_isFunction (uentry_getType (ce)))
3761 /*@innercontinue@*/ continue;
3764 if (uentry_isAnyParam (ce)
3765 || uentry_isRefParam (ce)
3766 || sRef_isFileOrGlobalScope (rb))
3768 /* Don't do the loseref check...but should check state! */
3770 else if (sRef_isDefinitelyNull (sr)
3771 || usymtab_isDefinitelyNull (sr))
3774 ** No state reference errors for definitely null references.
3779 DPRINTF (("Lose ref: %s / %s", uentry_unparse (ce),
3780 sRef_unparseFull (sr)));
3782 tvalues = sRef_getValueTable (sr);
3784 valueTable_elements (tvalues, fkey, fval) {
3785 metaStateInfo minfo;
3786 cstring msg = cstring_undefined;
3789 minfo = context_lookupMetaStateInfo (fkey);
3790 llassert (metaStateInfo_isDefined (minfo));
3792 if (stateValue_isError (fval))
3798 DPRINTF (("Check: %s / %s / %s", fkey,
3799 metaStateInfo_unparse (minfo),
3800 stateValue_unparse (fval)));
3802 minfo = context_lookupMetaStateInfo (fkey);
3804 nval = stateCombinationTable_lookupLoseReference
3805 (metaStateInfo_getTransferTable (minfo),
3806 stateValue_getValue (fval), &msg);
3808 if (cstring_isDefined (msg))
3810 /*@i32 print extra info for assignments@*/
3811 DPRINTF (("From: %s", sRef_unparseFull (sr)));
3812 DPRINTF (("Null? %s / %s",
3813 bool_unparse (sRef_isDefinitelyNull (sr)),
3814 bool_unparse (usymtab_isGuarded (sr))));
3819 ("%s loses reference %q in invalid state %q (%s)",
3820 cstring_makeLiteralTemp (isReturn ? "Return" : "Scope exit"),
3821 uentry_getName (ce),
3822 stateValue_unparseValue (fval, minfo),
3826 stateValue_show (fval, minfo);
3830 DPRINTF (("Suppressed transfer error: %s", msg));
3834 } end_valueTable_elements;
3839 DPRINTF (("Check entry: %s", uentry_unparseFull (ce)));
3841 if (!sRefSet_member (checked, sr) && !sRef_isFileOrGlobalScope (rb))
3843 if (ctype_isRealSU (uentry_getType (ce))
3844 && !uentry_isAnyParam (ce)
3845 && !uentry_isRefParam (ce)
3846 && !uentry_isStatic (ce)
3847 && !sRef_isDependent (sr)
3848 && !sRef_isOwned (sr))
3850 sRefSet als = usymtab_allAliases (sr);
3852 if (sRefSet_isEmpty (als))
3854 checkLocalDestroyed (sr, g_currentloc);
3858 /* aliased, no problem */ ;
3864 (!uentry_isStatic (ce)
3865 && ((sRef_isNewRef (sr))
3866 || (((sRef_isOnly (sr) || sRef_isFresh (sr)
3867 || sRef_isKeep (sr) || sRef_isOwned (sr))
3868 && !sRef_isDead (sr))
3869 && (!sRef_definitelyNull (sr))
3870 && (!usymtab_isDefinitelyNull (sr)))))
3872 bool hasError = TRUE;
3874 DPRINTF (("Checking: %s", sRef_unparseFull (sr)));
3877 ** If its a scope exit, check if there is an alias.
3878 ** If so, make it only. If not, there is an error.
3883 if (canLoseReference (sr, g_currentloc))
3885 DPRINTF (("Can lose!"));
3892 if (sRef_hasLastReference (sr))
3894 sRef ar = sRef_getAliasInfoRef (sr);
3899 ("Last reference %q to %s storage %qnot %q before %q",
3901 alkind_unparse (sRef_getAliasKind (sr)),
3902 sRef_unparseOpt (ar),
3903 cstring_makeLiteral (sRef_isKeep (sr)
3904 ? "transferred" : "released"),
3905 cstring_makeLiteral (isReturn
3906 ? "return" : "scope exit")),
3909 sRef_showRefLost (sr);
3912 else if (sRef_isNewRef (sr))
3917 ("%q %q not released before %q",
3919 (alkind_isKillRef (sRef_getOrigAliasKind (sr))
3920 ? "Kill reference parameter" : "New reference"),
3921 uentry_getName (ce),
3922 cstring_makeLiteral (isReturn
3923 ? "return" : "scope exit")),
3926 sRef_showAliasInfo (sr);
3931 if (ctype_isRealSU (sRef_getType (sr)))
3933 checkStructDestroyed (sr, g_currentloc);
3937 DPRINTF (("Here we are: %s", sRef_unparseFull (sr)));
3942 ("%s storage %q not %q before %q",
3943 alkind_capName (sRef_getAliasKind (sr)),
3944 uentry_getName (ce),
3945 cstring_makeLiteral (sRef_isKeep (sr)
3946 ? "transferred" : "released"),
3947 cstring_makeLiteral (isReturn
3948 ? "return" : "scope exit")),
3951 sRef_showAliasInfo (sr);
3952 DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
3963 else if (mustDefine && uentry_isOut (ce))
3965 if (!ynm_toBoolStrict (sRef_isReadable (sr)))
3969 message ("Out storage %q not defined before %q",
3970 uentry_getName (ce),
3972 (isReturn ? "return" : "scope exit")),
3975 /* uentry_showWhereDeclared (ce); */
3984 ** also check state is okay
3987 if (usymtab_lexicalLevel () > functionScope
3988 && uentry_isVariable (ce)
3989 && (sRef_isLocalVar (sr)
3990 && (sRef_isDependent (sr) || sRef_isLocalState (sr))))
3992 sRefSet ab = usymtab_aliasedBy (sr);
3994 /* should do something more efficient here */
3996 if (sRefSet_isEmpty (ab))
3998 /* and no local ref */
3999 DPRINTF (("Check lose ref: %s", uentry_unparseFull (ce)));
4014 checked = sRefSet_insert (checked, sr);
4018 llassert (usymtab_isDefined (stab->env));
4020 if (usymtab_isBranch (stab))
4022 stab = usymtab_dropEnv (stab);
4029 llassert (stab != usymtab_undefined);
4030 } while (isReturn && (stab->lexlevel >= paramsScope));
4032 sRefSet_free (checked);
4036 ** all globals are appropriately defined
4037 ** all parameters are appropriately defined
4038 ** special clauses are followed
4041 if (isReturn || (utab->lexlevel == paramsScope))
4043 uentry fcn = context_getHeader ();
4044 uentryList params = context_getParams ();
4045 globSet uglobs = context_getUsedGlobs ();
4046 globSet sglobs = context_getGlobs ();
4048 if (isReturn && context_maybeSet (FLG_GLOBALIAS))
4050 aliasTable_checkGlobs (utab->aliases);
4054 ** state clauses (ensures, defines, sets, allocates, releases)
4057 if (uentry_hasStateClauseList (fcn))
4059 stateClauseList clauses = uentry_getStateClauseList (fcn);
4061 stateClauseList_elements (clauses, cl)
4063 if (stateClause_isAfter (cl) && !stateClause_isGlobal (cl))
4065 if (stateClause_setsMetaState (cl))
4067 sRefSet rfs = stateClause_getRefs (cl);
4068 qual q = stateClause_getMetaQual (cl);
4069 annotationInfo ainfo = qual_getAnnotationInfo (q);
4070 metaStateInfo minfo = annotationInfo_getState (ainfo);
4071 cstring key = metaStateInfo_getName (minfo);
4072 int mvalue = annotationInfo_getValue (ainfo);
4074 DPRINTF (("Post meta state clause: %s", stateClause_unparse (cl)));
4076 sRefSet_elements (rfs, el)
4078 sRef base = sRef_getRootBase (el);
4080 if (sRef_isResult (base))
4083 ** This is checked for return transfers.
4087 else if (sRef_isParam (base) || sRef_isGlobalMarker (base))
4089 sRef sr = sRef_updateSref (base);
4090 sr = sRef_fixBase (el, sr);
4092 if (!sRef_checkMetaStateValue (sr, key, mvalue))
4097 ("Ensures clause not satisfied%q (state is %q): %q",
4098 sRef_isGlobalMarker (sr)
4100 : message (" by %q", sRef_unparse (sr)),
4101 stateValue_unparseValue (sRef_getMetaStateValue (sr, key),
4103 stateClause_unparse (cl)),
4106 sRef_showMetaStateInfo (sr, key);
4112 if (sRef_isMeaningful (el))
4117 } end_sRefSet_elements ;
4121 /* evs - 2000 07 10 - added this */
4122 sRefTest tst = stateClause_getPostTestFunction (cl);
4123 sRefSet rfs = stateClause_getRefs (cl);
4125 sRefSet_elements (rfs, el)
4127 sRef base = sRef_getRootBase (el);
4129 if (sRef_isResult (base))
4132 ** This is checked for return transfers.
4137 else if (sRef_isParam (base))
4139 sRef sr = sRef_updateSref (base);
4140 sr = sRef_fixBase (el, sr);
4142 if (tst != NULL && !tst (sr))
4145 (stateClause_postErrorCode (cl),
4146 message ("%s storage %qcorresponds to "
4147 "storage listed in %q clause",
4148 stateClause_postErrorString (cl, sr),
4149 sRef_unparseOpt (sr),
4150 stateClause_unparseKind (cl)),
4153 sRefShower ss = stateClause_getPostTestShower (cl);
4160 DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
4166 if (sRef_isMeaningful (el))
4171 } end_sRefSet_elements ;
4174 } end_stateClauseList_elements ;
4178 ** check parameters on return
4181 uentryList_elements (params, arg)
4183 if (!uentry_isElipsisMarker (arg))
4185 ctype rt = ctype_realType (uentry_getType (arg));
4187 if (ctype_isMutable (rt) || ctype_isSU (rt))
4189 uentry param = usymtab_lookupQuiet (utab, uentry_rawName (arg));
4190 DPRINTF (("Check param return: %s", uentry_unparseFull (param)));
4191 checkParamReturn (param);
4194 } end_uentryList_elements;
4196 DPRINTF (("Check global return: %s",
4197 globSet_unparse (sglobs)));
4199 globSet_allElements (sglobs, el)
4201 sRef orig = el; /*! sRef_updateSref (el); */ /*!!!*/
4202 uentry current = sRef_getUentry (el);
4204 DPRINTF (("Check global return: %s / %s", sRef_unparseFull (el),
4205 uentry_unparseFull (current)));
4207 if (uentry_isVariable (current) && !uentry_isRealFunction (current))
4209 checkGlobalReturn (current, orig);
4211 } end_globSet_allElements;
4213 globSet_allElements (uglobs, el)
4215 if (!globSet_member (sglobs, el))
4217 uentry current = sRef_getUentry (el);
4219 if (uentry_isVariable (current)
4220 && !uentry_isRealFunction (current))
4222 checkGlobalReturn (current, sRef_undefined);
4225 } end_globSet_allElements;
4230 usymtab_quietExitScope (fileloc loc)
4231 /*@globals utab, globtab, filetab; @*/
4234 usymtab t = utab->env;
4236 if (utab->reftable != NULL)
4240 for (i = 0; i < utab->nentries; i++)
4242 uentry current = utab->entries[i];
4243 uentry old = usymtab_lookupAux (t, uentry_rawName (current));
4245 uentry_mergeState (old, current, loc, FALSE, FALSE, FALSE, NOCLAUSE);
4249 llassert (t != NULL);
4251 if (t->lexlevel > paramsScope)
4253 t->guards = guardSet_levelUnion (t->guards, utab->guards, t->lexlevel);
4254 t->aliases = aliasTable_levelUnionSeq (t->aliases, utab->aliases,
4256 utab->aliases = aliasTable_undefined;
4259 t->mustBreak = utab->mustBreak;
4260 t->exitCode = utab->exitCode;
4262 usymtab_freeLevel (utab);
4268 ** Exit a scope with no checking, lose alias states.
4269 ** (When should this be used?)
4272 void usymtab_quietPlainExitScope (void)
4273 /*@globals utab, globtab, filetab@*/
4276 usymtab t = utab->env;
4278 llassert (t != NULL);
4279 llassert (NOALIAS (utab->aliases, t->aliases));
4280 usymtab_freeLevel (utab);
4284 void usymtab_exitScope (exprNode expr)
4285 /*@globals utab, filetab, globtab@*/
4286 /*@modifies utab, globtab@*/
4288 usymtab ctab = usymtab_undefined;
4289 usymtab lctab = usymtab_undefined;
4290 bool mustReturn = exprNode_mustEscape (expr);
4292 DPRINTF (("Exit scope"));
4294 if (utab->kind == US_CBRANCH)
4297 ** save the case branches, remove the first non-cbranch
4302 while (utab->kind == US_CBRANCH)
4306 llassert (utab != GLOBAL_ENV);
4310 if (utab->kind == US_TBRANCH || utab->kind == US_FBRANCH
4311 || utab->kind == US_CBRANCH || utab->kind == US_SWITCH) {
4313 if (context_inMacro ()) {
4314 /* evs 2000-07-25 */
4315 /* Unparseable macro may end inside nested scope. Deal with it. */
4317 llerror (FLG_SYNTAX,
4318 message ("Problem parsing macro body of %s (unbalanced scopes). "
4319 "Attempting to recover, recommend /*@notfunction@*/ before "
4320 "macro definition.",
4321 context_inFunctionName ()));
4323 while (utab->kind == US_TBRANCH
4324 || utab->kind == US_FBRANCH
4325 || utab->kind == US_CBRANCH
4326 || utab->kind == US_SWITCH)
4329 llassert (utab != GLOBAL_ENV);
4332 llcontbug (message ("exitScope: in branch: %q", usymtab_unparseStack ()));
4334 } /*@=branchstate@*/
4338 ** check all variables in scope were used
4342 ** bogus errors if this is the normal inside a switch,
4343 ** since cases have not been merged yet. Should probably
4344 ** still check this, but I'm too lazy at the moment...
4347 llassertfatal (utab->env != GLOBAL_ENV);
4349 if (utab->env->kind != US_SWITCH)
4355 ** check aliasing: all only params are released (dead)
4356 ** definition: all out params are defined, all modified params
4357 ** are completely defined
4359 ** NOTE: note for exiting paramsScope, since checkReturn should be
4363 if (!mustReturn && (usymtab_lexicalLevel () > functionScope))
4366 ** should only call this is end of scope is reachable...
4369 usymtab_checkFinalScope (FALSE);
4372 if (usymtab_lexicalLevel () == paramsScope && context_inFunctionLike ())
4375 ** leaving a function, need to fix up globals
4378 uentryList params = context_getParams ();
4379 globSet globs = context_getUsedGlobs ();
4382 uentryList_elements (params, ue)
4384 uentry_fixupSref (ue);
4385 } end_uentryList_elements;
4387 clearFunctionTypes ();
4390 globSet_allElements (globs, el)
4392 if (sRef_isCvar (el))
4395 int index = sRef_getScopeIndex (el);
4397 if (sRef_isFileStatic (el))
4399 llassert (usymtab_isDefined (filetab));
4400 current = usymtab_fetchIndex (filetab, index);
4404 current = usymtab_fetchIndex (globtab, index);
4407 if (uentry_isVariable (current))
4409 uentry_fixupSref (current);
4413 sRef_clearDerived (uentry_getSref (current));
4416 } end_globSet_allElements;
4419 usymtab_quietExitScope (exprNode_loc (expr));
4421 if (lctab != usymtab_undefined)
4423 /*@i@*/ lctab->env = utab;
4424 /*@i@*/ utab = ctab;
4425 /*@-branchstate@*/ } /*@=branchstate@*/
4431 ** yikes! don't let the '170 kids see this one...
4435 uentry_directParamNo (uentry ue)
4437 if (uentry_isVar (ue))
4439 sRef sr = uentry_getSref (ue);
4441 if (sRef_lexLevel (sr) == functionScope)
4446 llassert (sr->info != NULL);
4447 llassert (sr->info->cvar != NULL);
4448 index = sr->info->cvar->index;
4451 if (index < uentryList_size (context_getParams ()))
4460 /*@dependent@*/ /*@exposed@*/ uentry
4461 usymtab_getParam (int paramno)
4465 ** requires in a function context (checked)
4467 ** depends on no nested functions --- the function
4468 ** parameters are ALWAYS one scope inside the global scope
4469 ** and entered in order!
4473 if (!context_inFunctionLike ())
4474 llfatalbug (message ("usymtab_getParam: not in function context: %q",
4475 context_unparse ()));
4477 while (s->lexlevel > paramsScope)
4482 llassert (usymtab_isDefined (s));
4484 if (paramno >= s->nentries)
4487 ** Parse errors lead to this.
4490 uentry err = uentry_makeVariableLoc (cstring_makeLiteralTemp ("<error>"),
4493 uentry_markOwned (err);
4497 return (s->entries[paramno]);
4500 static /*@dependent@*/ /*@exposed@*/ uentry
4501 usymtab_getRefTab (/*@notnull@*/ usymtab u, int level, usymId index)
4505 ue = usymtab_getRefNoisy (u, level, index);
4507 if (uentry_isUndefined (ue))
4509 llbug (message ("usymtab_getRef: out of range: %d. level = %d",
4516 static /*@dependent@*/ /*@exposed@*/ usymtab
4517 usymtab_dropEnv (/*@notnull@*/ usymtab s)
4519 if (s->kind == US_CBRANCH)
4527 llassert (s != GLOBAL_ENV);
4528 } while (s->kind == US_CBRANCH);
4529 /* drop all cases (except in nested scopes */
4532 llassert (s != GLOBAL_ENV);
4535 if (s->kind == US_FBRANCH)
4537 s = s->env; /* skip the true branch */
4538 llassert (usymtab_isDefined (s));
4539 llassert (s->kind == US_TBRANCH);
4542 llassert (s != GLOBAL_ENV);
4548 /*@dependent@*/ /*@exposed@*/ uentry
4549 usymtab_getRefQuiet (int level, usymId index)
4555 llassert (s != NULL);
4556 llassert (index >= 0);
4558 if (level > s->lexlevel)
4560 return uentry_undefined;
4563 llassertprint (level <= s->lexlevel, ("level: %d / lexlevel: %d",
4564 level, s->lexlevel));
4566 while (s->lexlevel > level)
4568 if (usymtab_isBranch (s))
4570 int eindex = refTable_lookup (s, level, index);
4572 if (eindex != NOT_FOUND)
4574 return (s->entries[eindex]);
4578 s = usymtab_dropEnv (s);
4581 while (usymtab_isBranch (s) && s->lexlevel == level)
4583 int eindex = refTable_lookup (s, level, index);
4585 if (eindex != NOT_FOUND)
4587 return (s->entries[eindex]);
4590 s = usymtab_dropEnv (s);
4593 if (index >= s->nentries)
4595 return uentry_undefined;
4598 llassert (!uentry_isUndefined (s->entries[index]));
4600 return s->entries[index];
4603 static /*@dependent@*/ /*@exposed@*/ uentry
4604 usymtab_getRefNoisy (/*@notnull@*/ usymtab s, int level, usymId index)
4607 uentry ue = uentry_undefined;
4609 llassert (index >= 0);
4611 while (s->lexlevel > level)
4613 if (usymtab_isBranch (s))
4615 int eindex = refTable_lookup (s, level, index);
4617 if (eindex != NOT_FOUND)
4619 ue = s->entries[eindex];
4623 while (!usymtab_isBranch (otab))
4625 otab = usymtab_dropEnv (otab);
4626 llassert (otab != GLOBAL_ENV);
4629 if (refTable_lookup (otab, level, index) == NOT_FOUND)
4631 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4643 s = usymtab_dropEnv (s);
4646 llassert (usymtab_isDefined (s));
4648 while (usymtab_isBranch (s) && s->lexlevel == level)
4650 int eindex = refTable_lookup (s, level, index);
4653 if (eindex != NOT_FOUND)
4655 ue = s->entries[eindex];
4659 while (!usymtab_isBranch (otab))
4661 otab = usymtab_dropEnv (otab);
4662 llassert (otab != GLOBAL_ENV);
4665 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4675 s = usymtab_dropEnv (s);
4678 if (s->lexlevel == level && (index < s->nentries))
4680 ue = s->entries[index];
4682 if (uentry_isValid (ue))
4686 while (!usymtab_isBranch (otab))
4688 otab = usymtab_dropEnv (otab);
4690 if (otab == GLOBAL_ENV)
4696 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4707 if (index >= s->nentries)
4709 return uentry_undefined;
4712 llassert (!uentry_isUndefined (s->entries[index]));
4714 return s->entries[index];
4718 ** looking up entries
4720 ** If entry is inside a branch, then copy it, and put it into
4721 ** the branch table.
4725 int refTable_lookup (/*@notnull@*/ usymtab ut, int level, int index)
4727 refTable rt = ut->reftable;
4730 llassert (rt != NULL);
4732 for (i = 0; i < ut->nentries; i++)
4734 if (rt[i]->level == level && rt[i]->index == index)
4744 /*@only@*/ refentry refentry_create (int level, int index)
4746 refentry r = (refentry) dmalloc (sizeof (*r));
4754 static /*@dependent@*/ /*@exposed@*/ uentry
4755 usymtab_addRefEntry (/*@notnull@*/ usymtab s, cstring k)
4760 if (ut->reftable == NULL)
4762 DPRINTF (("Adding ref entry without reftable: %s", k));
4763 return uentry_undefined;
4766 llassert (ut->reftable != NULL);
4768 while (s != GLOBAL_ENV)
4770 eindex = usymtab_getIndex (s, k);
4772 if (eindex != NOT_FOUND)
4774 uentry current = s->entries[eindex];
4776 if (uentry_isVar (current) && !ctype_isFunction (uentry_getType (current)))
4780 DPRINTF (("Here: copying %s", uentry_unparse (current)));
4781 ue = uentry_copy (current);
4782 DPRINTF (("Here: copying %s", uentry_unparse (ue)));
4783 usymtab_addEntryQuiet (ut, ue);
4784 DPRINTF (("Okay..."));
4786 if (s->reftable != NULL)
4788 refentry ref = s->reftable[eindex];
4790 ut->reftable[ut->nentries - 1]
4791 = refentry_create (ref->level, ref->index);
4795 ut->reftable[ut->nentries - 1]
4796 = refentry_create (s->lexlevel, eindex);
4807 s = usymtab_dropEnv (s);
4810 return uentry_undefined;
4813 static uentry usymtab_lookupAux (usymtab s, cstring k)
4815 DPRINTF (("Lookup: %s", k));
4817 while (s != GLOBAL_ENV)
4819 int eindex = usymtab_getIndex (s, k);
4821 if (eindex != NOT_FOUND)
4823 uentry ret = s->entries[eindex];
4827 if (s->kind == US_TBRANCH
4828 || s->kind == US_FBRANCH
4829 || s->kind == US_CBRANCH)
4830 /* uentry_isGlobalVariable (ret) && os->lexlevel > fileScope) */
4833 DPRINTF (("Adding global ref entry: %s", k));
4834 ret = usymtab_addRefEntry (os, k);
4835 DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
4840 DPRINTF (("Found: %s", uentry_unparseFull (ret)));
4844 if (s->kind == US_TBRANCH || s->kind == US_FBRANCH
4845 || s->kind == US_CBRANCH)
4847 /* why isn't this os??? */
4848 uentry ret = usymtab_addRefEntry (s, k);
4849 DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
4856 return uentry_undefined;
4859 static /*@dependent@*/ /*@exposed@*/ uentry
4860 usymtab_lookupQuietAux (usymtab s, cstring k, bool noalt)
4864 while (s != GLOBAL_ENV)
4866 eindex = usymtab_getIndex (s, k);
4868 if (eindex != NOT_FOUND)
4870 uentry ret = s->entries[eindex];
4874 if (noalt && usymtab_isBranch (s))
4876 s = usymtab_dropEnv (s);
4884 return uentry_undefined;
4887 static /*@exposed@*/ /*@dependent@*/ uentry
4888 usymtab_lookupQuiet (usymtab s, cstring k)
4890 return usymtab_lookupQuietAux (s, k, FALSE);
4893 static /*@exposed@*/ /*@dependent@*/ uentry
4894 usymtab_lookupQuietNoAlt (usymtab s, cstring k)
4896 return usymtab_lookupQuietAux (s, k, TRUE);
4899 /*@dependent@*/ /*@observer@*/ uentry
4900 usymtab_lookupSafe (cstring k)
4903 DPRINTF (("Lookup safe: %s", k));
4904 return (usymtab_lookupAux (utab, k));
4908 usymtab_lookupExpose (cstring k)
4911 uentry ce = usymtab_lookupAux (utab, k);
4913 if (uentry_isUndefined (ce))
4915 llfatalbug (message ("usymtab_lookup: not found: *%s*", k));
4918 if (uentry_isPriv (ce))
4920 llfatalbug (message ("usymtab_lookup: private: *%s*", k));
4926 uentry usymtab_lookupExposeGlob (cstring k)
4928 return (usymtab_lookupGlobSafe (k));
4931 uentry usymtab_lookupGlob (cstring k)
4932 /*@globals globtab@*/
4934 uentry ce = usymtab_lookupAux (globtab, k);
4936 if (uentry_isUndefined (ce))
4937 llfatalbug (message ("usymtab_lookup: not found: %s", k));
4939 if (uentry_isPriv (ce))
4940 llfatalbug (message ("usymtab_lookup: private: %s", k));
4945 /*@observer@*/ uentry
4946 usymtab_lookupGlobSafe (cstring k)
4947 /*@globals globtab@*/
4949 uentry ce = usymtab_lookupAux (globtab, k);
4954 uentry usymtab_lookupEither (cstring k)
4957 uentry ce = usymtab_lookupSafe (k);
4959 if (uentry_isUndefined (ce))
4960 llfatalerror (message ("usymtab_lookup: not found: %s", k));
4967 usymtab_lookupType (cstring k)
4968 /*@globals globtab@*/
4970 usymId uid = usymtab_getTypeId (k);
4972 if (uid == USYMIDINVALID)
4974 llcontbug (message ("usymtab_lookupType: not found: %s", k));
4975 return ctype_unknown;
4978 return (uentry_getRealType (usymtab_getTypeEntry (uid)));
4983 usymtab_lookupAbstractType (cstring k) /*@globals globtab@*/
4985 usymId uid = usymtab_getTypeId (k);
4987 if (uid == USYMIDINVALID)
4989 llcontbug (message ("usymtab_lookupType: not found: %s", k));
4990 return ctype_unknown;
4993 return (uentry_getAbstractType (usymtab_getTypeEntry (uid)));
4997 ** if there is an unnamed lcl-specified struct tag matching
4998 ** the uentryList, return its datatype. Otherwise, returns
5003 usymtab_structFieldsType (uentryList f)
5004 /*@globals globtab@*/
5006 return (usymtab_suFieldsType (f, TRUE));
5010 usymtab_unionFieldsType (uentryList f)
5011 /*@globals globtab@*/
5013 return (usymtab_suFieldsType (f, FALSE));
5017 usymtab_suFieldsType (uentryList f, bool isStruct)
5018 /*@globals globtab@*/
5022 DPRINTF (("Fields: %s", uentryList_unparse (f)));
5024 if (fileloc_isSpec (g_currentloc))
5026 return (ctype_undefined);
5029 for (i = 0; i < globtab->nentries; i++)
5031 uentry current = globtab->entries[i];
5034 ? uentry_isStructTag (current) : uentry_isUnionTag (current)))
5036 if (isFakeTag (uentry_rawName (current)))
5038 ctype ct = uentry_getType (current);
5040 DPRINTF (("Check: %s", ctype_unparse (ct)));
5042 if ((isStruct ? ctype_isStruct (ct) : ctype_isUnion (ct))
5044 (uentry_isSpecified (current)
5045 && uentryList_equivFields (f, ctype_getFields (ct))))
5047 return uentry_getAbstractType (current);
5057 return ctype_undefined;
5061 usymtab_enumEnumNameListType (enumNameList f)
5062 /*@globals globtab@*/
5066 for (i = 0; i < globtab->nentries; i++)
5068 uentry current = globtab->entries[i];
5070 if (uentry_isEnumTag (current))
5072 if (isFakeTag (uentry_rawName (current)))
5074 ctype ct = uentry_getType (current);
5076 if (ctype_isEnum (ct) && (enumNameList_match (f, ctype_elist (ct))))
5078 return uentry_getType (current);
5084 return ctype_undefined;
5088 usymtab_exists (cstring k)
5091 uentry ce = usymtab_lookupSafe (k);
5092 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5096 usymtab_existsReal (cstring k)
5099 uentry ce = usymtab_lookupSafe (k);
5101 return (!(uentry_isUndefined (ce))
5102 && !(uentry_isPriv (ce))
5103 && !(uentry_isExpandedMacro (ce)));
5107 usymtab_existsGlob (cstring k)
5108 /*@globals globtab@*/
5110 uentry ce = usymtab_lookupAux (globtab, k);
5112 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5117 usymtab_existsEither (cstring k)
5120 uentry ce = usymtab_lookupAux (utab, k);
5122 return (uentry_isValid (ce));
5126 usymtab_existsGlobEither (cstring k)
5127 /*@globals globtab@*/
5129 uentry ce = usymtab_lookupAux (globtab, k);
5131 return (uentry_isValid (ce));
5136 usymtab_existsType (cstring k)
5137 /*@globals globtab@*/
5139 uentry ce = usymtab_lookupAux (globtab, k);
5141 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && uentry_isDatatype (ce));
5145 usymtab_existsTypeEither (cstring k)
5146 /*@globals globtab@*/
5149 ce = usymtab_lookupAux (globtab, k);
5150 return (uentry_isValid (ce) && uentry_isDatatype (ce));
5154 usymtab_existsStructTag (cstring k) /*@globals globtab@*/
5156 cstring sname = makeStruct (k);
5157 uentry ce = usymtab_lookupAux (globtab, sname);
5158 cstring_free (sname);
5159 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5163 usymtab_existsUnionTag (cstring k) /*@globals globtab@*/
5165 cstring uname = makeUnion (k);
5166 uentry ce = usymtab_lookupAux (globtab, uname);
5168 cstring_free (uname);
5170 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5174 usymtab_existsEnumTag (cstring k) /*@globals globtab@*/
5176 cstring ename = makeEnum (k);
5177 uentry ce = usymtab_lookupAux (globtab, ename);
5179 cstring_free (ename);
5180 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5184 bool usymtab_existsVar (cstring k)
5187 uentry ce = usymtab_lookupSafe (k);
5189 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && (uentry_isVar (ce)));
5198 refTable_free (/*@only@*/ /*@null@*/ refTable x, int nentries)
5204 for (i = 0; i < nentries; i++)
5214 usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab u)
5215 /*@globals globtab, utab, filetab@*/
5219 aliasTable_free (u->aliases);
5221 refTable_free (u->reftable, u->nentries);
5223 if (u == filetab || u == globtab)
5225 for (i = 0; i < u->nentries; i++)
5227 uentry_freeComplete (u->entries[i]);
5232 for (i = 0; i < u->nentries; i++)
5234 uentry_free (u->entries[i]);
5238 guardSet_free (u->guards);
5245 llassert (!cstringTable_isDefined (u->htable));
5253 usymtab_freeAux (/*@only@*/ usymtab u)
5254 /*@globals globtab, utab, filetab@*/
5257 while (u != GLOBAL_ENV)
5260 usymtab_freeLevel (u);
5267 void usymtab_free ()
5268 /*@globals killed utab, globtab, filetab@*/
5272 usymtab_freeAux (utab);
5275 static int usymtab_lexicalLevel (void) /*@globals utab@*/
5277 return (utab->lexlevel);
5280 bool usymtab_inGlobalScope () /*@globals utab, globtab@*/
5282 return (utab == globtab);
5285 bool usymtab_inFileScope () /*@globals utab@*/
5287 return (utab->lexlevel == fileScope);
5290 bool usymtab_inFunctionScope () /*@globals utab@*/
5292 return (utab->lexlevel == functionScope);
5297 usymtab_replaceEntry (uentry s)
5298 /*@globals utab, globtab@*/
5299 /*@modifies utab, s@*/
5301 usymtab_replaceEntryAux (utab, s);
5306 usymtab_matchForwardStruct (usymId u1, usymId u2)
5307 /*@globals globtab@*/
5309 uentry ue1 = usymtab_getTypeEntry (u1);
5310 uentry ue2 = usymtab_getTypeEntry (u2);
5312 if (uentry_isAnyTag (ue2))
5314 ctype reptype = uentry_getType (ue1);
5316 if (ctype_isPointer (reptype))
5318 ctype repbase = ctype_getBaseType (reptype);
5320 if (ctype_isUA (repbase))
5322 typeId rtuid = ctype_typeId (repbase);
5324 if (u2 == rtuid) return TRUE;
5326 if (usymId_isValid (rtuid))
5328 reptype = uentry_getType (usymtab_getTypeEntry (rtuid));
5330 return (ctype_isUA (reptype) && (u2 == (ctype_typeId (reptype))));
5339 void usymtab_addGuards (guardSet guards)
5342 utab->guards = guardSet_union (utab->guards, guards);
5345 static bool usymtab_isGuardedAux (sRef s)
5349 sRef base = sRef_getRootBase (s);
5350 int lowlevel = paramsScope;
5351 int baselevel = sRef_lexLevel (base);
5353 if (sRef_isCvar (base))
5355 lowlevel = baselevel;
5356 if (lowlevel < paramsScope) lowlevel = paramsScope;
5359 while (tab->lexlevel >= lowlevel)
5361 if (guardSet_isGuarded (tab->guards, s))
5364 if (!sRef_definitelyNull (s))
5366 sRef_setNotNull (s, fileloc_undefined);
5372 tab = usymtab_dropEnv (tab);
5378 void usymtab_unguard (sRef s) /*@modifies utab@*/
5381 sRef base = sRef_getRootBase (s);
5382 int lowlevel = paramsScope;
5383 int baselevel = sRef_lexLevel (base);
5385 if (sRef_isCvar (base))
5387 lowlevel = baselevel;
5388 if (lowlevel < paramsScope) lowlevel = paramsScope;
5391 while (tab->lexlevel >= lowlevel)
5393 if (guardSet_isGuarded (tab->guards, s))
5395 guardSet_delete (tab->guards, s);
5398 tab = usymtab_dropEnv (tab);
5402 bool usymtab_isGuarded (sRef s)
5405 return (sRef_aliasCompleteSimplePred (usymtab_isGuardedAux, s));
5408 bool usymtab_isDefinitelyNull (sRef s)
5410 return (sRef_aliasCheckSimplePred (usymtab_isDefinitelyNullAux, s));
5413 bool usymtab_isDefinitelyNullDeep (sRef s)
5415 return (sRef_deepPred (usymtab_isDefinitelyNull, s));
5418 static bool usymtab_isDefinitelyNullAux (sRef s)
5422 sRef base = sRef_getRootBase (s);
5423 int lowlevel = paramsScope;
5425 if (sRef_isCvar (base))
5427 lowlevel = sRef_lexLevel (base);
5428 if (lowlevel < paramsScope) lowlevel = paramsScope;
5431 while (tab->lexlevel >= lowlevel)
5433 if (guardSet_mustBeNull (tab->guards, s))
5438 while (tab->kind == US_CBRANCH)
5443 llassert (usymtab_isDefined (tab));
5445 if (tab->kind == US_FBRANCH)
5448 llassert (tab->kind == US_TBRANCH);
5458 usymtab_printGuards ()
5459 /*@globals utab, globtab@*/
5461 usymtab ttab = utab;
5463 while (ttab != globtab)
5465 llmsg (message ("Guards [%d]: %q", ttab->lexlevel,
5466 guardSet_unparse (ttab->guards)));
5472 usymtab_displayAllUses ()
5473 /*@globals utab, globtab@*/
5477 /* only in top scope */
5478 llassert (utab == globtab);
5480 /* need a copy, so order is not messed up by sort! */
5481 copy = usymtab_shallowCopy (globtab);
5483 qsort (copy->entries, (size_t)copy->nentries,
5484 sizeof (*copy->entries), (int (*)(const void *, const void *)) uentry_xcompareuses);
5486 usymtab_entries (copy, ue)
5488 if (uentry_isValid (ue))
5490 filelocList uses = uentry_getUses (ue);
5491 int size = filelocList_realSize (uses);
5493 if (fileloc_isDefined (uentry_whereDefined (ue))
5494 && !fileloc_isLib (uentry_whereDefined (ue))
5497 llmsg (message ("%q (%q), %d use%&:\n %q",
5498 uentry_getName (ue),
5499 fileloc_unparse (uentry_whereDefined (ue)),
5500 size, filelocList_unparseUses (uses)));
5503 } end_usymtab_entries;
5505 usymtab_shallowFree (copy);
5508 static /*@dependent@*/ /*@exposed@*/ usymtab
5509 usymtab_getFileTab ()
5510 /*@globals filetab@*/
5512 llassert (filetab != NULL);
5518 usymtab_unparseStack ()
5521 return (usymtab_unparseStackTab (utab));
5524 static /*@only@*/ cstring
5525 usymtab_unparseStackTab (usymtab t)
5527 bool firstOne = TRUE;
5528 cstring ret = cstring_makeLiteral ("[");
5530 while (t != GLOBAL_ENV)
5534 ret = message ("%q %q", ret, usymtab_typeName (t));
5539 ret = message ("%q, %q", ret, usymtab_typeName (t));
5544 ret = message ("%q ]", ret);
5548 static /*@only@*/ cstring
5549 usymtab_typeName (/*@notnull@*/ usymtab t)
5553 case US_GLOBAL: return cstring_makeLiteral ("global");
5554 case US_NORMAL: return cstring_makeLiteral ("normal");
5555 case US_TBRANCH: return cstring_makeLiteral ("true");
5556 case US_FBRANCH: return cstring_makeLiteral ("false");
5557 case US_CBRANCH: return cstring_makeLiteral ("case");
5558 case US_SWITCH: return cstring_makeLiteral ("switch");
5564 void usymtab_addMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5567 if (!sRef_similar (s, al))
5569 usymtab_addForceMustAlias (s, al);
5574 ** Same as usymtab_addMustAlias, except does not check sRef_isSimilar.
5577 void usymtab_addForceMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5580 if (sRef_isMeaningful (s)
5581 && sRef_isMeaningful (al)
5582 && !(sRef_isConst (s) || sRef_isConst (al))
5583 && !(sRef_isAddress (al) && sRef_isDirectParam (sRef_getBase (al))))
5585 utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
5586 DPRINTF (("Must alias: %s", aliasTable_unparse (utab->aliases)));
5589 ** for local variable, aliasing is symmetric
5592 if (sRef_isLocalVar (s) && sRef_isLocalVar (al))
5594 utab->aliases = aliasTable_addMustAlias (utab->aliases, al, s);
5603 void usymtab_clearAlias (sRef s)
5604 /*@modifies utab, s@*/
5607 aliasTable_clearAliases (utab->aliases, s);
5610 sRefSet usymtab_allAliases (sRef s)
5613 if (sRef_isMeaningful (s))
5617 ret = sRefSet_unionFree (aliasTable_aliasedBy (utab->aliases, s),
5618 aliasTable_canAlias (utab->aliases, s));
5623 DPRINTF (("NOT A MEANINGFUL SREF!"));
5624 return sRefSet_undefined;
5628 /*@only@*/ sRefSet usymtab_canAlias (sRef s)
5631 if (sRef_isMeaningful (s))
5633 sRefSet res = aliasTable_canAlias (utab->aliases, s);
5637 return sRefSet_undefined;
5640 /*@only@*/ sRefSet usymtab_aliasedBy (sRef s)
5643 return (aliasTable_aliasedBy (utab->aliases, s));
5646 /*@only@*/ cstring usymtab_unparseAliases ()
5649 return (aliasTable_unparse (utab->aliases));
5653 ** Debugging routines:
5654 ** okay to leak storage here, only for debugging
5660 usymtab_printOut (void)
5666 char *ind = mstring_copy (" ");
5668 fprintf (g_msgstream, "<<< [symbol table] >>>\n");
5670 while (s != GLOBAL_ENV && s->env != GLOBAL_ENV)
5672 cstring tname = usymtab_typeName (s);
5676 ind[depth * 3 + 1] = '\0';
5679 fprintf (g_msgstream, "level: %d (%s)\n", s->lexlevel,
5680 cstring_toCharsSafe (tname));
5682 cstring_free (tname);
5684 for (i = 0; i < s->nentries; i++)
5686 cstring us = uentry_unparseFull (s->entries[i]);
5687 fprintf (g_msgstream, "%s\n", cstring_toCharsSafe (us));
5691 if (s->reftable != NULL && s->nentries > 0)
5693 fprintf (g_msgstream, "\t<< Ref table >>\n");
5695 for (i = 0; i < s->nentries; i++)
5697 fprintf (g_msgstream, "\t%s %3d: %d, %d\n", ind, i,
5698 s->reftable[i]->level,
5699 s->reftable[i]->index);
5703 ind[depth * 3 + 1] = ' ';
5707 fprintf (g_msgstream, "<<< end usymtab >>>\n");
5713 usymtab_printTypes ()
5714 /*@globals globtab@*/
5716 usymtab_printAllAux (globtab);
5720 usymtab_printAll (void)
5723 usymtab_printAllAux (utab);
5727 usymtab_printAllAux (usymtab s)
5728 /*@modifies g_msgstream@*/
5732 char *ind = mstring_copy (" ");
5734 printf ("[[[ usymtab ]]]");
5736 while (s != GLOBAL_ENV)
5739 ind[depth * 3 + 1] = '\0';
5741 if (s->env == GLOBAL_ENV)
5745 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5746 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5747 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5751 for (i = looplow; i < s->nentries; i++)
5753 printf ("%s%3d. %s\n", ind, i,
5754 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5759 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5760 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5761 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5763 for (i = 0; i < s->nentries; i++)
5765 printf ("%s%3d %s\n", ind, i,
5766 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5770 ind[depth * 3 + 1] = ' ';
5774 printf ("----------\n");
5778 usymtab_printComplete ()
5783 char *ind = mstring_copy (" ");
5786 while (s != GLOBAL_ENV)
5790 ind[depth * 3 + 1] = '\0';
5793 if (s->env == GLOBAL_ENV)
5797 printf ("level: %d\n", s->lexlevel);
5801 for (i = looplow; i < s->nentries; i++)
5803 printf ("%s%3d %s\n", ind, i,
5804 cstring_toCharsSafe (uentry_unparse (s->entries[i])));
5809 printf ("level: %d\n", s->lexlevel);
5810 for (i = 0; i < s->nentries; i++)
5812 printf ("%s%3d %s\n", ind, i,
5813 cstring_toCharsSafe (uentry_unparse (s->entries[i])));
5817 ind[depth * 3 + 1] = ' ';
5822 printf ("----------\n");
5826 static /*@only@*/ cstring /*@unused@*/
5827 usymtab_unparseLocalAux (/*@notnull@*/ usymtab s)
5829 cstring c = message ("lexlevel: %d\n", s->lexlevel);
5832 for (i = 0; i < s->nentries; i++)
5834 c = message ("%q\n%q", c, uentry_unparseFull (s->entries[i]));
5837 c = message ("%q\n=========", c);
5841 static cstring /*@unused@*/ /*@only@*/
5842 usymtab_unparseLocalList (/*@notnull@*/ usymtab s)
5844 cstring c = message ("[%d/%s/%s] ", s->lexlevel,
5845 bool_unparse (s->mustBreak),
5846 exitkind_unparse (s->exitCode));
5849 for (i = 0; i < s->nentries; i++)
5851 sRef sr = uentry_getSref (s->entries[i]);
5855 c = message ("%q: %q [%b]", c, uentry_getName (s->entries[i]),
5856 sRef_isStateDefined (sr));
5860 c = message ("%q, %q [%b]", c, uentry_getName (s->entries[i]),
5861 sRef_isStateDefined (sr));
5870 usymtab_printLocal (void)
5876 printf ("lexlevel: %d\n", s->lexlevel);
5878 for (i = 0; i < s->nentries; i++)
5880 printf ("%s\n", cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5883 while (s->lexlevel > 1)
5888 llassert (usymtab_isDefined (s));
5890 printf ("Params:\n");
5892 for (i = 0; i < s->nentries; i++)
5894 printf ("%d: %s\n", i,
5895 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5900 static bool checkDistinctExternalName (uentry e)
5901 /*@globals globtab@*/
5902 /*@modifies *g_msgstream@*/
5904 int checklen = context_getValue (FLG_EXTERNALNAMELEN);
5905 bool ignorecase = context_getFlag (FLG_EXTERNALNAMECASEINSENSITIVE);
5906 bool gotone = FALSE;
5907 bool extras = FALSE;
5908 bool hasError = FALSE;
5909 cstring name = uentry_rawName (e);
5910 usymtab st = globtab;
5918 if (uentry_isAnyTag (e))
5920 checklen++; /* the tag marker doesn't count */
5924 usymtab_entries (st, oe)
5926 if (uentry_sameObject (oe, e))
5933 if (cstring_equalCaseInsensitive (uentry_rawName (oe), name))
5942 (FLG_DISTINCTEXTERNALNAMES,
5944 ("External identifier %q is not distinguishable from %q "
5945 "because alphabetical case is ignored",
5947 uentry_getName (oe)),
5948 uentry_whereLast (e)))
5950 uentry_showWhereAny (oe);
5951 uentry_setHasNameError (oe);
5960 if (cstring_equalLenCaseInsensitive (uentry_rawName (oe),
5969 if (cstring_equalLen (uentry_rawName (oe), name, checklen))
5972 (FLG_DISTINCTEXTERNALNAMES,
5975 ("External identifier %q is not distinguishable from %q "
5976 "in the first %d characters (%q)",
5978 uentry_getName (oe),
5980 cstring_clip (uentry_getName (e), checklen)),
5982 uentry_whereLast (e)))
5984 uentry_showWhereAny (oe);
5985 uentry_setHasNameError (oe);
5998 (FLG_DISTINCTEXTERNALNAMES,
6000 ("External identifier %q is not distinguishable from %q "
6001 "in the first %d characters because alphabetical case "
6004 uentry_getName (oe),
6006 uentry_whereLast (e)))
6008 uentry_showWhereAny (oe);
6009 uentry_setHasNameError (oe);
6015 else if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6024 (FLG_DISTINCTEXTERNALNAMES,
6027 ("External identifier %q is not distinguishable from %q "
6028 "in the first %d characters (%q)",
6030 uentry_getName (oe),
6032 cstring_clip (uentry_getName (e), checklen)),
6034 uentry_whereLast (e)))
6036 uentry_showWhereAny (oe);
6037 uentry_setHasNameError (oe);
6046 } end_usymtab_entries ;
6053 (cstring_makeLiteral ("One or more additional "
6054 "indistinguishable external "
6055 "names not reported"));
6061 static bool checkDistinctInternalName (uentry e)
6063 /*@modifies *g_msgstream@*/
6065 usymtab ttab = utab;
6066 cstring name = uentry_rawName (e);
6067 int numchars = context_getValue (FLG_INTERNALNAMELEN);
6068 bool caseinsensitive = context_getFlag (FLG_INTERNALNAMECASEINSENSITIVE);
6069 bool lookalike = context_getFlag (FLG_INTERNALNAMELOOKALIKE);
6071 if (uentry_isAnyTag (e) && (numchars != 0))
6073 numchars++; /* the tag marker doesn't count */
6076 while (usymtab_isDefined (ttab))
6078 usymtab_entries (ttab, oe)
6080 if (uentry_sameObject (oe, e))
6082 /*@innercontinue@*/ continue;
6085 switch (cstring_genericEqual
6086 (name, uentry_rawName (oe),
6087 numchars, caseinsensitive, lookalike))
6089 case CGE_DISTINCT: /* okay */
6093 if (cstring_equal (name, uentry_rawName (oe)))
6095 ; /* got a shadow error */
6100 (FLG_DISTINCTINTERNALNAMES,
6103 ("Internal identifier %q is not distinguishable from %q "
6104 "in the first %d characters (%q)",
6106 uentry_getName (oe),
6108 cstring_clip (uentry_getName (e), numchars)),
6110 uentry_whereLast (e)))
6112 uentry_showWhereAny (oe);
6113 uentry_setHasNameError (oe);
6121 || (cstring_length (name) <= numchars))
6124 (FLG_DISTINCTINTERNALNAMES,
6126 ("Internal identifier %q is not distinguishable from %q "
6127 "without case sensitivity",
6129 uentry_getName (oe)),
6130 uentry_whereLast (e)))
6132 uentry_showWhereAny (oe);
6133 uentry_setHasNameError (oe);
6140 (FLG_DISTINCTINTERNALNAMES,
6142 ("Internal identifier %q is not distinguishable from %q "
6143 "in the first %d characters without case sensitivity",
6145 uentry_getName (oe),
6147 uentry_whereLast (e)))
6149 uentry_showWhereAny (oe);
6150 uentry_setHasNameError (oe);
6158 || (cstring_length (name) <= numchars))
6161 (FLG_DISTINCTINTERNALNAMES,
6163 ("Internal identifier %q is not distinguishable from %q "
6164 "except by lookalike characters",
6166 uentry_getName (oe)),
6167 uentry_whereLast (e)))
6169 uentry_showWhereAny (oe);
6170 uentry_setHasNameError (oe);
6177 (FLG_DISTINCTINTERNALNAMES,
6179 ("Internal identifier %q is not distinguishable from %q "
6180 "in the first %d characters except by lookalike characters",
6182 uentry_getName (oe),
6184 uentry_whereLast (e)))
6186 uentry_showWhereAny (oe);
6187 uentry_setHasNameError (oe);
6192 } end_usymtab_entries ;
6200 void usymtab_checkDistinctName (uentry e, int scope)
6201 /*@globals utab, globtab@*/
6203 bool hasError = FALSE;
6204 fileloc where = uentry_whereLast (e);
6206 if (!fileloc_isPreproc (where) && !fileloc_isBuiltin (where))
6208 if (scope == globScope)
6210 if (context_getFlag (FLG_DISTINCTEXTERNALNAMES))
6212 hasError = checkDistinctExternalName (e);
6216 if (!hasError && context_getFlag (FLG_DISTINCTINTERNALNAMES))
6218 hasError = checkDistinctInternalName (e);
6224 uentry_setHasNameError (e);
6228 /*@exposed@*/ sRef usymtab_lookupGlobalMarker (void) /*@globals utab@*/
6232 ue = usymtab_lookupAux (utab, GLOBAL_MARKER_NAME);
6233 llassert (uentry_isValid (ue));
6235 return uentry_getSref (ue);