Handle possible null character inside string literal
[splint-patched.git] / src / usymtab.c
blob6ce4f694882f3bce89770a4806755b1a517b0bdd
1 /*
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 University of Virginia,
4 ** Massachusetts Institute of Technology
5 **
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.
10 **
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.
15 **
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
20 ** For information on splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
25 ** usymtab
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
46 ** weird C syntax.
49 # include "splintMacros.nf"
50 # include "basic.h"
51 # include "structNames.h"
52 # include "exprChecks.h"
53 # include "transferChecks.h"
55 #if 0
56 /* Needed to install macros when loading libraries */
58 # include "cpplib.h"
59 # include "cpperror.h"
60 # include "cpphash.h"
61 #endif
64 ** Keep track of type definitions inside a function.
67 static uentryList functypes = uentryList_undefined;
69 static bool dbgfree = FALSE;
70 static bool dbgload = TRUE;
72 /*@access ekind@*/
75 ** Hack to prevent shadow errors from appearing when function parameters
76 ** are entered into a new scope.
79 static bool noshadowerror = FALSE;
82 ** Constraint: static variables can live in 1 or > 2.
84 ** except for tags. All tags must be at the global level.
85 ** Static tags are handled in a kludgey way.
89 ** utab is the universal symbol table
90 ** globtab is the global environment of utab
91 ** oldtab is needed for conversions in dumping (after sorting the table)
93 ** there can be only one usymtab!
96 static /*@checkedstrict@*/ /*@owned@*/ /*@notnull@*/ usymtab utab;
98 /* Reachable environments from from utab */
99 static /*@checkedstrict@*/ /*@notnull@*/ /*@dependent@*/ usymtab globtab;
100 static /*@checkedstrict@*/ /*@dependent@*/ usymtab filetab;
102 /* Used for sorting for dumpage. */
103 static /*@checkedstrict@*/ /*@owned@*/ usymtab oldtab;
105 static int usymtab_lexicalLevel (void) /*@globals utab@*/ ;
106 static bool usymtab_isAltDefinitelyNull (sRef p_s) /*@globals utab@*/ ;
107 static void refTable_free (/*@only@*/ /*@null@*/ refTable p_x, int p_nentries);
108 static ctype usymtab_suFieldsType (uentryList p_f, bool p_isStruct) /*@globals globtab@*/ ;
110 static void usymtab_freeAux (/*@only@*/ usymtab p_u)
111 /*@globals globtab, utab, filetab@*/
112 /*@modifies p_u@*/ ;
114 # if 0
115 extern int usymtab_getCurrentDepth (void) /*@globals utab@*/
117 return utab->lexlevel;
119 # endif
121 static void
122 usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab p_u)
123 /*@globals globtab, utab, filetab@*/ /*@modifies p_u@*/ ;
125 static bool usymtab_isDefinitelyNullAux (sRef p_s) /*@globals utab@*/ ;
126 static /*@only@*/ cstring usymtab_unparseStackTab (usymtab p_t);
127 static /*@exposed@*/ /*@dependent@*/ uentry
128 usymtab_getRefTab (/*@notnull@*/ usymtab p_u, int p_level, usymId p_index);
130 # ifdef S_SPLINT_S
131 /* These are not used anymore... */
132 static /*@unused@*/ /*@only@*/ cstring
133 usymtab_unparseLocalAux (/*@notnull@*/ usymtab p_s);
134 static /*@unused@*/ /*@only@*/ cstring
135 usymtab_unparseLocalList (/*@notnull@*/ usymtab p_s);
136 # endif
138 static /*@only@*/ cstring usymtab_typeName (/*@notnull@*/ usymtab p_t);
139 static void usymtab_handleParams (void)
140 /*@globals utab, globtab, filetab@*/
141 /*@modifies utab@*/ ;
143 static /*@exposed@*/ /*@dependent@*/ uentry
144 usymtab_addRefEntry (/*@notnull@*/ usymtab p_s, cstring p_k);
145 static /*@exposed@*/ /*@dependent@*/ usymtab
146 usymtab_dropEnv (/*@notnull@*/ usymtab p_s);
147 static /*@exposed@*/ /*@dependent@*/ uentry
148 usymtab_getRefNoisy (/*@notnull@*/ usymtab p_s, int p_level, usymId p_index);
150 static /*@exposed@*/ /*@dependent@*/ uentry
151 usymtab_lookupQuietAux (usymtab p_s, cstring p_k, bool p_noalt);
153 static /*@exposed@*/ /*@dependent@*/ uentry
154 usymtab_lookupQuiet (usymtab p_s, cstring p_k);
156 static /*@exposed@*/ /*@dependent@*/ uentry
157 usymtab_lookupQuietNoAlt (usymtab p_s, cstring p_k);
159 static void usymtab_printAllAux (usymtab p_s) /*@modifies g_warningstream@*/ ;
161 /*@function bool usymtab_indexFound (usymId) @*/
162 # define usymtab_indexFound(u) ((u) != usymId_notfound)
164 static usymId usymtab_getIndex (/*@notnull@*/ usymtab p_s, cstring p_k);
165 static /*@exposed@*/ uentry usymtab_fetchIndex (/*@notnull@*/ usymtab p_s, usymId p_ui);
166 static /*@exposed@*/ uentry usymtab_lookupAux (usymtab p_s, cstring p_k);
168 static /*@exposed@*/ /*@dependent@*/ /*@notnull@*/
169 usymtab usymtab_getFileTab (void) /*@globals filetab@*/ ;
171 static int refTable_lookup (/*@notnull@*/ usymtab p_ut, int p_level, usymId p_index);
172 static bool usymtab_mustBreak (usymtab p_s);
173 static bool usymtab_mustEscape (usymtab p_s);
175 static void recordFunctionType (uentry ue)
177 llassert (uentry_isDatatype (ue) || uentry_isAnyTag (ue)
178 || uentry_isEnumConstant (ue));
179 DPRINTF (("Function type: %s", uentry_unparseFull (ue)));
180 /*@-temptrans@*/
181 functypes = uentryList_add (functypes, ue);
182 /*@=temptrans@*/
185 static void clearFunctionTypes (void)
186 /*@modifies globtab@*/
188 uentryList_elements (functypes, el)
190 if (cstring_isDefined (uentry_rawName (el)))
192 if (cstringTable_isDefined (globtab->htable))
194 cstringTable_remove (globtab->htable, uentry_rawName (el));
197 uentry_setName (el, cstring_undefined);
200 /*@access uentry@*/
201 llassert (uentry_isValid (el));
202 el->sref = sRef_undefined;
203 /*@noaccess uentry@*/
204 } end_uentryList_elements ;
206 uentryList_clear (functypes);
209 static /*@falsewhennull@*/ bool usymtab_isBranch (usymtab u)
211 return (usymtab_isDefined (u) &&
212 (u->kind == US_TBRANCH || u->kind == US_FBRANCH
213 || u->kind == US_CBRANCH || u->kind == US_SWITCH));
216 static bool usymtab_mustBreak (usymtab s)
218 llassert (s != GLOBAL_ENV);
219 return (s->mustBreak);
222 static bool usymtab_mustEscape (usymtab s)
224 llassert (s != GLOBAL_ENV);
225 return (exitkind_mustEscape (s->exitCode));
228 void usymtab_setMustBreak (void)
229 /*@modifies utab@*/
231 llassert (utab != GLOBAL_ENV);
232 utab->mustBreak = TRUE;
235 void usymtab_setExitCode (exitkind ex)
236 /*@modifies utab@*/
238 llassert (utab != GLOBAL_ENV);
240 utab->exitCode = ex;
242 if (exitkind_mustEscape (ex))
244 utab->mustBreak = TRUE;
248 bool usymtab_isAltDefinitelyNullDeep (sRef s)
250 return (sRef_deepPred (usymtab_isAltDefinitelyNull, s));
253 static bool usymtab_isAltDefinitelyNull (sRef s)
254 /*@globals utab@*/
256 guardSet t;
257 bool res;
259 t = utab->guards;
261 llassert (utab->env != NULL);
263 /*@-mods@*/ /* These modifications are cancelled. */
264 utab->guards = utab->env->guards;
265 utab->env->guards = t;
266 /*@=mods@*/
268 llassert (usymtab_isDefined (utab));
269 res = usymtab_isDefinitelyNull (s);
272 ** This reports a spurious error. It is okay, because of
273 ** the nesting relationship of usymtab environments.
276 /*@-mods@*/ /* Cancelling modifications. */
277 /*@i1@*/ utab->env->guards = utab->guards;
278 /*@i1@*/ utab->guards = t;
279 /*@=mods@*/
281 return res;
284 static /*@notnull@*/ /*@special@*/ usymtab
285 usymtab_create (uskind kind, /*@keep@*/ usymtab env, bool nextlevel)
286 /*@defines result@*/
287 /*@post:isnull result->htable, result->guards, result->aliases@*/
289 usymtab t = (usymtab) dmalloc (sizeof (*t));
291 t->nentries = 0;
292 t->nspace = CBASESIZE;
293 t->entries = (uentry *) dmalloc (sizeof (*t->entries) * CBASESIZE);
295 /* We only use a reftable for branch-level symbol tables. */
297 t->reftable = (nextlevel
298 ? NULL
299 : (refentry *) dmalloc (sizeof (*t->reftable) * CBASESIZE));
301 t->kind = kind;
302 t->lexlevel = (env == GLOBAL_ENV ? 0 : env->lexlevel) + (nextlevel ? 1 : 0);
304 t->env = env;
305 t->htable = NULL;
307 t->guards = guardSet_undefined;
308 t->aliases = aliasTable_undefined;
310 t->mustBreak = FALSE;
311 t->exitCode = XK_NEVERESCAPE;
313 DPRINTF (("Create usymtab [%p]", t));
314 return t;
318 ** constructors
321 static /*@only@*/ /*@notnull@*/ usymtab
322 usymtab_createRoot (void) /*@modifies nothing@*/
324 usymtab u = (usymtab) dmalloc (sizeof (*u));
326 u->nentries = 0;
327 u->nspace = CGLOBBASESIZE;
328 u->entries = (uentry *) dmalloc (sizeof (*u->entries) * CGLOBBASESIZE);
329 u->env = GLOBAL_ENV;
330 u->lexlevel = 0;
331 u->htable = cstringTable_create (CGLOBHASHSIZE);
332 u->reftable = NULL;
334 u->guards = guardSet_new ();
335 u->aliases = aliasTable_new ();
337 u->mustBreak = FALSE;
338 u->exitCode = XK_NEVERESCAPE;
339 u->kind = US_NORMAL;
341 return (u);
344 void
345 usymtab_initMod (void)
346 /*@globals undef utab, undef oldtab, undef globtab, undef filetab @*/
347 /*@modifies utab, globtab, filetab, oldtab @*/
349 utab = usymtab_createRoot ();
350 globtab = utab;
351 filetab = usymtab_undefined;
352 oldtab = usymtab_undefined;
355 void
356 usymtab_destroyMod (void)
357 /*@modifies utab, globtab, filetab@*/
358 /*@globals killed utab@*/
360 DPRINTF (("Destroy usymtab [%p]: %d", utab, utab->nentries));
361 #if 0
362 dbgfree = TRUE;
363 #endif
364 usymtab_freeAux (utab);
365 utab = usymtab_undefined;
366 /*@-globstate@*/
367 } /*@=globstate@*/ /* Splint cannot tell that utab is killed */
369 void
370 usymtab_initGlobalMarker (void) /*@globals globtab@*/
372 if (uentry_isValid (usymtab_lookupAux (globtab, GLOBAL_MARKER_NAME)))
374 ; /* Already entered from load table. */
376 else
378 usymtab_addGlobalEntry (uentry_makeGlobalMarker ());
383 ** utab should be empty? (requires?)
385 ** Adds bool types to symbol table (these are built in for now)
386 ** Only do this is there is no library!
389 void
390 usymtab_initBool (void)
392 DPRINTF (("Init bool!"));
394 if (context_getFlag (FLG_NOLIB))
396 ctype boolt = ctype_bool;
397 /* evs 2000-07-24: bool is now treated as abstract (always) */
399 uentry boolentry = uentry_makeBoolDatatype (qual_createAbstract ());
400 usymtab_supGlobalEntry (boolentry);
401 context_addBoolAccess ();
404 ** We supply values 0 and 1 for the constants, so things like
405 ** while (TRUE) can be interpreted correctly.
408 usymtab_supGlobalEntry
409 (uentry_makeConstantValue (context_getFalseName (), boolt,
410 fileloc_getBuiltin (), FALSE,
411 multiVal_makeInt (0)));
413 usymtab_supGlobalEntry
414 (uentry_makeConstantValue (context_getTrueName (), boolt,
415 fileloc_getBuiltin (), FALSE,
416 multiVal_makeInt (1)));
421 ** mutators
424 static void
425 usymtab_grow (/*@notnull@*/ usymtab s)
427 int i;
428 o_uentry *oldsyms = s->entries;
430 s->nspace = CBASESIZE;
431 s->entries = (uentry *) dmalloc (sizeof (*s->entries)
432 * (s->nentries + s->nspace));
434 for (i = 0; i < s->nentries; i++)
436 s->entries[i] = oldsyms[i];
439 sfree (oldsyms);
441 if (s->reftable != NULL)
443 refTable oldRefs = s->reftable;
445 s->reftable = (refentry *) dmalloc (sizeof (*s->reftable)
446 * (s->nentries + CBASESIZE + 1));
448 for (i = 0; i < s->nentries; i++)
450 s->reftable[i] = oldRefs[i];
453 /*@-compdestroy@*/
454 sfree (oldRefs);
455 /*@=compdestroy@*/
460 static void
461 usymtab_addEntryQuiet (/*@notnull@*/ usymtab s, /*@keep@*/ uentry e)
463 if (!(s->lexlevel > fileScope || !sRef_modInFunction ()))
465 if (uentry_isDatatype (e)
466 || uentry_isFunction (e)
467 || uentry_isAnyTag (e)
468 || uentry_isEnumConstant (e)
469 || context_inMacro ())
472 ** Not a bug. Code like,
473 ** int f (void) { typedef int tint; ... }
474 ** is legal.
477 /* was nothing here! */
478 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
480 else
482 llparseerror
483 (cstring_makeLiteral ("Declaration outside function scope"));
485 llcontbug (message ("%s: inconsistent state (lexlevel = %d, "
486 "modFunction = %s) adding: %q", cstring_fromChars (__func__),
487 s->lexlevel, bool_unparse (sRef_modInFunction ()),
488 uentry_unparse (e)));
489 sRef_setGlobalScope ();
490 /* make sure the sRef is not bashed! */
491 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
495 if (s->nspace <= 0)
497 usymtab_grow (s);
500 s->nspace--;
501 s->entries[s->nentries] = e;
503 # ifdef DOANNOTS
504 if (s == globtab || s == filetab)
506 if (!fileloc_isLib (g_currentloc))
508 uentry_tallyAnnots (e, AN_UNKNOWN);
511 # endif
513 if (cstringTable_isDefined (s->htable))
515 cstringTable_insert (s->htable, cstring_copy (uentry_rawName (e)), s->nentries);
518 s->nentries++;
521 static /*@observer@*/ uentry /*@alt void@*/
522 usymtab_addEntryBase (/*@notnull@*/ usymtab s, /*@only@*/ uentry e)
525 ** In theory, we shouldn't need this test because it this is
526 ** only called when a library is being read, and it shouldn't
527 ** ever have a duplicate entry. In practice, its safer to
528 ** leave it in, though.
531 uentry old;
533 if (uentry_isValid (old = usymtab_lookupQuiet (s, uentry_rawName (e))))
535 DPRINTF (("Duplicate entry: %s", uentry_unparse (e)));
536 uentry_free (e); /* duplicate */
537 return old;
539 else
541 usymId thisentry = usymId_fromInt (s->nentries);
543 if (uentry_isVar (e))
545 uentry_setSref
546 (e, sRef_makeCvar (globScope, thisentry,
547 uentry_getType (e),
548 stateInfo_makeLoc (uentry_whereLast (e), SA_DECLARED)));
551 usymtab_addEntryQuiet (s, e);
552 return e;
557 static /*@observer@*/ uentry /*@alt void@*/
558 usymtab_addEntryAlways (/*@notnull@*/ usymtab s, /*@only@*/ uentry e)
561 ** In theory, we shouldn't need this test because it this is
562 ** only called when a library is being read, and it shouldn't
563 ** ever have a duplicate entry. In practice, its safer to
564 ** leave it in, though.
567 uentry old;
568 usymId thisentry = usymId_fromInt (s->nentries);
570 if (uentry_isValid (old = usymtab_lookupQuiet (s, uentry_rawName (e))))
572 llcontbug
573 (message ("Duplicate entry in load library: %s. "
574 "Old entry: %q. New entry: %q",
575 uentry_rawName (e),
576 uentry_unparseFull (old),
577 uentry_unparseFull (e)));
579 uentry_setName (e, message ("__x_%s", uentry_rawName (e)));
580 /* This shouldn't happen...unless the library is bad! */
584 if (uentry_isVar (e) && !uentry_isGlobalMarker (e))
586 uentry_setSref
587 (e, sRef_makeCvar (globScope, thisentry,
588 uentry_getType (e),
589 stateInfo_makeLoc (uentry_whereLast (e), SA_DECLARED)));
592 usymtab_addEntryQuiet (s, e);
593 return e;
596 static usymId
597 usymtab_addEntryAux (/*@notnull@*/ usymtab st, /*@keep@*/ uentry e, bool isSref)
598 /*@globals globtab@*/
599 /*@modifies st, e@*/
601 usymId thisentry = usymId_fromInt (st->nentries);
603 llassert (!uentry_isElipsisMarker (e));
606 ** not true for tags
607 ** llassert (usymtab_lookupSafe (uentry_rawName (e)) == uentry_undefined);
610 llassertprint (uentry_isAnyTag (e) ? st == globtab : TRUE,
611 ("non-global tag: %s / %d", uentry_unparseFull (e), st->lexlevel));
613 if (st->lexlevel == fileScope
614 && (!(uentry_isStatic (e)) || uentry_isAnyTag (e)))
616 st = globtab;
619 if (st->kind == US_CBRANCH)
621 /* variables in a case branch (and not in a block inside the case branch)
622 * must be added in the environment incapsulating the case branch. */
623 st = usymtab_dropEnv (st);
626 if (isSref)
628 ctype ct = uentry_getType (e);
630 if (uentry_isFunction (e) && ctype_isFunction (ct))
632 ct = ctype_getReturnType (ct);
635 if (uentry_isStatic (e))
637 sRef sr = sRef_makeCvar (st->lexlevel, thisentry, ct,
638 stateInfo_makeLoc (uentry_whereLast (e), SA_DECLARED));
640 if (sRef_isStack (sr) || sRef_isLocalState (sr))
642 sRef_setAliasKind (sr, AK_STATIC, uentry_whereLast (e));
643 sRef_setDefined (sr, uentry_whereLast (e));
646 uentry_setSref (e, sr);
648 else
650 uentry_setSref
651 (e, sRef_makeCvar (st->lexlevel, thisentry, ct,
652 stateInfo_makeLoc (uentry_whereLast (e), SA_DECLARED)));
656 if (uentry_isDatatype (e))
658 uentry_setDatatype (e, typeId_fromUsymId (thisentry));
661 if (uentry_isFunction (e))
663 ctype ct = uentry_getType (e);
665 if (ctype_isFunction (ct)
666 && uentryList_isMissingParams (ctype_argsFunction (ct)))
668 if (uentry_isDeclared (e))
670 voptgenerror
671 (FLG_NOPARAMS,
672 message ("Function %q declared without parameter list",
673 uentry_getName (e)),
674 uentry_whereDeclared (e));
676 else
678 voptgenerror
679 (FLG_NOPARAMS,
680 message ("Function %q specified without parameter list",
681 uentry_getName (e)),
682 uentry_whereSpecified (e));
687 if (st == globtab && !uentry_isSpecified (e))
689 exprChecks_checkExport (e);
692 uentry_checkName (e);
694 usymtab_addEntryQuiet (st, e);
695 DPRINTF (("Adding entry: [%p] %s", e, uentry_unparseFull (e)));
696 return (thisentry);
699 usymId
700 usymtab_addEntry (uentry e)
701 /*@globals utab, globtab@*/
702 /*@modifies utab, e@*/
704 llassertprint (!usymtab_exists (uentry_rawName (e)),
705 ("Entry already exists: %s", uentry_unparse (e)));
707 return usymtab_addEntryAux (utab, e, FALSE);
710 void
711 usymtab_addGlobalEntry (uentry e)
712 /*@modifies globtab, e@*/
714 DPRINTF (("Add global: %s / %s", uentry_unparse (e), bool_unparse (uentry_isForward (e))));
716 (void) usymtab_addEntryAux (globtab, e, FALSE);
720 ** supercede and replace entry use elements of entries array, and
721 ** assign an element to a new value, and then free the old value.
722 ** Need -deparrays to avoid errors for this.
725 /*@-deparrays@*/
727 static usymId
728 usymtab_supEntryAux (/*@notnull@*/ usymtab st,
729 /*@only@*/ uentry e, bool isSref)
730 /*@globals globtab, filetab@*/
731 /*@modifies st, globtab, e@*/
733 cstring ename = uentry_rawName (e);
734 bool staticEntry = FALSE;
735 usymId eindex;
737 DPRINTF (("Sup entry aux: %s", uentry_unparseFull (e)));
739 /* static tags in global scope */
740 if (st->lexlevel == fileScope
741 && (!(uentry_isStatic (e)) || uentry_isAnyTag (e)))
743 eindex = usymtab_getIndex (st, ename);
745 if (usymtab_indexFound (eindex))
747 uentry ce = st->entries[eindex];
749 if (optgenerror
750 (FLG_SHADOW,
751 message ("%s %q shadows static declaration",
752 ekind_capName (uentry_getKind (e)),
753 uentry_getName (e)),
754 uentry_whereDeclared (e)))
756 uentry_showWhereLast (ce);
759 if (eindex == usymId_fromInt (st->nentries - 1))
763 else
765 st->entries[eindex] = st->entries[st->nentries - 1];
768 if (cstringTable_isDefined (st->htable))
770 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
771 cstring_copy (uentry_rawName (e)));
774 uentry_free (ce);
775 st->nentries--;
778 st = globtab;
781 if (uentry_isStatic (e)) {
782 if (uentry_isFunction (e)) {
784 ** Static function declarations are at the file level,
785 ** even if they are in a deeper scope.
788 st = usymtab_getFileTab ();
789 staticEntry = TRUE;
790 } else {
791 if (!uentry_isAnyTag (e) && st == globtab)
793 st = usymtab_getFileTab ();
794 staticEntry = TRUE;
795 DPRINTF (("Static entry!"));
800 eindex = usymtab_getIndex (st, ename);
802 if (usymtab_indexFound (eindex))
804 uentry ce = st->entries[eindex];
806 DPRINTF (("Found entry: %s", uentry_unparse (ce)));
808 if (uentry_isPriv (ce)
809 /* || (fileloc_isImport (uentry_whereSpecified (ce))) */
810 || (uentry_isStatic (ce)
811 && uentry_isAnyTag (ce)
812 && (uentry_isDeclared (ce)
813 && !fileloc_sameFile (uentry_whereDefined (ce),
814 uentry_whereDefined (e)))))
817 ** overload entry
818 ** if overloading import should do some checks!
821 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
823 DPRINTF (("Overloading!"));
825 st->entries[eindex] = e;
827 if (uentry_isDatatype (e))
829 uentry_setDatatype (e, typeId_fromUsymId (eindex));
832 if (st == globtab && !uentry_isSpecified (e))
834 exprChecks_checkExport (e);
837 if (cstringTable_isDefined (st->htable))
839 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
840 cstring_copy (uentry_rawName (e)));
843 uentry_free (ce);
844 ce = e;
846 else if (uentry_isSpecified (ce))
848 if (uentry_isSpecified (e))
850 DPRINTF (("Here we are: %s", uentry_unparseFull (e)));
852 if (fileloc_isImport (uentry_whereSpecified (ce)))
854 if (cstringTable_isDefined (st->htable))
856 cstringTable_replaceKey (st->htable,
857 uentry_rawName (ce),
858 cstring_copy (uentry_rawName (e)));
861 uentry_free (ce);
862 st->entries[eindex] = e;
863 ce = e;
865 if (uentry_isDatatype (e)) uentry_setDatatype (e, typeId_fromUsymId (eindex));
867 else
869 if (fileloc_isImport (uentry_whereSpecified (e)))
871 uentry_free (e);
873 else
875 /* Respecification errors already reported */
876 DPRINTF (("Respecification: %s / %s",
877 fileloc_unparse (uentry_whereSpecified (e)),
878 bool_unparse (fileloc_isSpec (uentry_whereSpecified (e)))));
880 if (uentry_isDatatype (e))
882 uentry_setDatatype (e, typeId_fromUsymId (eindex));
885 if (cstringTable_isDefined (st->htable))
887 cstringTable_replaceKey (st->htable,
888 uentry_rawName (ce),
889 cstring_copy (uentry_rawName (e)));
892 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
893 uentry_free (ce);
894 st->entries[eindex] = e;
895 ce = e;
899 else /* e not specified */
901 DPRINTF (("Merging..."));
903 if (uentry_isDeclared (ce))
905 /* evans 2001-08-26
906 No - this can happen for internal typedefs
907 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
910 DPRINTF (("Merge defn"));
911 uentry_mergeDefinition (ce, e);
913 else
915 /* evans 2001-08-26
916 No - this can happen for internal typedefs
917 llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
920 DPRINTF (("Merge entries..."));
921 uentry_mergeEntries (ce, e);
922 DPRINTF (("After: %s", uentry_unparseFull (ce)));
926 else /* ce not specified */
928 if (!(st->lexlevel > fileScope || !sRef_modInFunction ()))
930 if (uentry_isDatatype (e) || uentry_isAnyTag (e)
931 || uentry_isEnumConstant (e)
932 || uentry_isStatic (e)) /* bug fix from Brian St. Pierre */
934 ; /*
935 ** Not a bug. Code like,
936 ** int f (void) { typedef int tint; ... }
937 ** is legal.
940 else
942 llcontbug (message ("%s: inconsistent state (lexlevel = %d,"
943 " modFunction = %s) adding: %q", cstring_fromChars (__func__),
944 st->lexlevel, bool_unparse (sRef_modInFunction ()),
945 uentry_unparse (e)));
947 if (sRef_modInFunction ())
949 /* make sure the sRef is not bashed! */
950 /*@i@*/ e->sref = sRef_saveCopy (e->sref);
955 DPRINTF (("Merge.."));
956 uentry_mergeDefinition (ce, e);
959 if (isSref)
961 ctype ct = uentry_getType (ce);
963 if (uentry_isFunction (ce) && ctype_isFunction (ct))
965 ct = ctype_getReturnType (ct);
968 uentry_setSref
969 (ce, sRef_makeCvar (st->lexlevel, eindex, ct,
970 stateInfo_makeLoc (uentry_whereLast (ce), SA_DECLARED)));
973 else /* no previous entry */
975 uentry outer;
977 if (st->lexlevel == globScope
978 && !uentry_isStatic (e)
979 && !uentry_isExtern (e)
980 && usymtab_isDefined (filetab))
983 ** check if there is a static entry: (i.e.,
985 ** static int f ();
986 ** ...
987 ** int f ();
990 eindex = usymtab_getIndex (filetab, ename);
992 if (usymtab_indexFound (eindex))
994 uentry ce = filetab->entries[eindex];
996 uentry_setStatic (e);
997 uentry_mergeDefinition (ce, e);
998 staticEntry = TRUE;
999 goto exitPoint;
1003 outer = usymtab_lookupQuiet (st->env, ename);
1005 DPRINTF (("New : [%p] %s", e, uentry_unparseFull (e)));
1006 DPRINTF (("Outer: [%p] %s", outer, uentry_unparseFull (outer)));
1009 ** no previous definition, add the new one
1012 if (!noshadowerror
1013 && uentry_isValid (outer)
1014 && !(uentry_isYield (e) || uentry_isYield (outer))
1015 && fileloc_isDefined (uentry_whereLast (e))
1016 && !fileloc_isXHFile (uentry_whereLast (e))
1017 && fileloc_isDefined (uentry_whereLast (outer))
1018 && !fileloc_isXHFile (uentry_whereLast (outer)))
1020 if (!uentry_sameKind (outer, e))
1022 ; /* no error */
1024 else
1026 if (ctype_isUnknown (uentry_getType (outer))
1027 || uentry_isForward (outer))
1031 else
1033 if (optgenerror
1034 (FLG_SHADOW,
1035 message ("%s %q shadows outer declaration",
1036 ekind_capName (uentry_getKind (e)),
1037 uentry_getName (e)),
1038 uentry_whereLast (e)))
1040 uentry_showWhereLast (outer);
1046 if (st == globtab && context_getFlag (FLG_NEWDECL))
1048 voptgenerror
1049 (FLG_NEWDECL,
1050 message ("New declaration: %q", uentry_getName (e)),
1051 uentry_whereLast (e));
1054 eindex = usymtab_addEntryAux (st, e, isSref);
1057 exitPoint:
1058 return (staticEntry ? usymId_invalid : eindex);
1061 static void
1062 usymtab_replaceEntryAux (/*@notnull@*/ usymtab st, /*@only@*/ uentry e)
1063 /*@globals globtab@*/ /*@modifies st, e@*/
1065 cstring ename = uentry_rawName (e);
1066 usymId eindex;
1068 /* static tags in global scope */
1069 eindex = usymtab_getIndex (st, ename);
1071 if (usymtab_indexFound (eindex))
1073 uentry ce = st->entries[eindex];
1075 if (cstringTable_isDefined (st->htable))
1077 cstringTable_replaceKey (st->htable, uentry_rawName (ce),
1078 cstring_copy (uentry_rawName (e)));
1081 uentry_free (ce);
1082 st->entries[eindex] = e;
1084 else
1086 eindex = usymtab_addEntryAux (st, e, FALSE);
1090 /*@=deparrays@*/
1092 void usymtab_supEntry (uentry e)
1093 /*@globals utab, filetab, globtab@*/
1094 /*@modifies utab, globtab, e@*/
1096 (void) usymtab_supEntryAux (utab, e, FALSE);
1100 ** this should be lots more efficient!
1103 static /*@exposed@*/ uentry
1104 usymtab_supEntryReturnAux (/*@notnull@*/ usymtab tab,
1105 /*@only@*/ uentry e, bool isref)
1106 /*@globals globtab, filetab@*/
1107 /*@modifies tab, globtab, e@*/
1109 cstring rawName = cstring_copy (uentry_rawName (e));
1110 bool stat = (tab == globtab) && uentry_isStatic (e);
1111 uentry ret;
1113 (void) usymtab_supEntryAux (tab, e, isref);
1115 if (stat)
1117 ret = usymtab_lookupAux (filetab, rawName);
1119 else
1121 ret = usymtab_lookupAux (tab, rawName);
1123 if (uentry_isInvalid (ret) && usymtab_isDefined (filetab))
1125 ret = usymtab_lookupAux (filetab, rawName);
1129 cstring_free (rawName);
1130 return ret;
1133 /*@dependent@*/ /*@exposed@*/ uentry
1134 usymtab_supEntryReturn (/*@only@*/ uentry e)
1135 /*@globals utab, filetab, globtab@*/
1136 /*@modifies utab, globtab, e@*/
1138 return (usymtab_supEntryReturnAux (utab, e, FALSE));
1141 /*@dependent@*/ /*@exposed@*/ uentry
1142 usymtab_supEntrySrefReturn (/*@only@*/ uentry e)
1143 /*@globals utab, globtab, filetab@*/
1144 /*@modifies utab, globtab, e@*/
1146 return (usymtab_supEntryReturnAux (utab, e, TRUE));
1149 /*@dependent@*/ /*@exposed@*/ uentry
1150 usymtab_supGlobalEntryReturn (uentry e)
1151 /*@globals globtab, filetab@*/
1152 /*@modifies globtab, e@*/
1154 uentry ret;
1156 ret = usymtab_supEntryReturnAux (globtab, e, FALSE);
1159 ** We need to keep track of internal function declarations, so
1160 ** we can remove them from the symbol table after exiting this
1161 ** function. This is a bit bogus, of course.
1164 if (sRef_modInFunction ())
1166 recordFunctionType (ret);
1169 return (ret);
1172 ctype
1173 usymtab_supTypeEntry (/*@only@*/ uentry e)
1174 /*@globals globtab, filetab@*/
1175 /*@modifies globtab, e@*/
1177 usymId uid;
1178 ctype ret;
1180 if (uentry_isAbstractDatatype (e))
1182 typeId tid = usymtab_supAbstractTypeEntry (e, FALSE);
1183 ret = ctype_createAbstract (tid);
1184 uid = typeId_toUsymId (tid);
1186 else
1188 uid = usymtab_supEntryAux (globtab, e, FALSE);
1189 ret = ctype_createUser (typeId_fromUsymId (uid));
1192 if (sRef_modInFunction ())
1194 recordFunctionType (globtab->entries[uid]);
1197 return ret;
1200 uentry
1201 usymtab_supReturnTypeEntry (/*@only@*/ uentry e)
1202 /*@globals globtab, filetab@*/
1203 /*@modifies globtab@*/
1205 usymId uid;
1207 DPRINTF (("Abstract? %s", uentry_unparseFull (e)));
1209 if (uentry_isAbstractDatatype (e))
1211 uid = typeId_toUsymId (usymtab_supAbstractTypeEntry (e, FALSE));
1213 else if (uentry_isMaybeAbstract (e) && context_getFlag (FLG_IMPABSTRACT))
1215 bool maybeabs = TRUE;
1216 cstring sname = uentry_getName (e);
1217 uentry ue = usymtab_lookupGlobSafe (sname);
1218 cstring_free (sname);
1220 if (uentry_isValid (ue))
1222 DPRINTF (("Lookup: %s", uentry_unparseFull (ue)));
1224 if (uentry_isDatatype (ue))
1226 if (uentry_isMaybeAbstract (ue))
1230 else
1232 maybeabs = FALSE;
1235 else
1237 DPRINTF (("Not datatype!"));
1241 if (maybeabs)
1243 uentry ux;
1244 typeId tid = usymtab_supAbstractTypeEntry (e, FALSE);
1245 ux = usymtab_getTypeEntry (tid);
1246 uentry_setAbstract (ux);
1247 uid = typeId_toUsymId (tid);
1249 else
1251 uid = usymtab_supEntryAux (globtab, e, FALSE);
1252 e = usymtab_getTypeEntry (typeId_fromUsymId (uid));
1254 if (uentry_isMaybeAbstract (e))
1256 uentry_setConcrete (e);
1260 else
1262 uid = usymtab_supEntryAux (globtab, e, FALSE);
1263 e = usymtab_getTypeEntry (typeId_fromUsymId (uid));
1265 /*? evans 2002-12-16 removed this? it doesn't make sense
1266 if (uentry_isMaybeAbstract (e))
1268 uentry_setConcrete (e);
1273 if (sRef_modInFunction ())
1275 recordFunctionType (globtab->entries[uid]);
1278 return (globtab->entries[uid]);
1281 typeId
1282 usymtab_supAbstractTypeEntry (/*@only@*/ uentry e, bool dodef)
1283 /*@globals globtab, filetab@*/
1284 /*@modifies globtab, e@*/
1286 typeId uid;
1287 uentry ue;
1289 uid = typeId_fromUsymId (usymtab_supEntryAux (globtab, e, FALSE));
1290 ue = usymtab_getTypeEntry (uid);
1292 if (dodef)
1294 uentry_setDatatype (ue, uid);
1297 if (context_getFlag (FLG_ACCESSMODULE)) /* was accessfile */
1299 context_addFileAccessType (uid);
1302 if (sRef_modInFunction ())
1304 recordFunctionType (globtab->entries[uid]);
1307 return (uid);
1310 typeId
1311 usymtab_supExposedTypeEntry (/*@only@*/ uentry e, bool dodef)
1312 /*@globals globtab, filetab@*/
1313 /*@modifies globtab, e@*/
1315 typeId uid;
1317 uid = typeId_fromUsymId (usymtab_supEntryAux (globtab, e, FALSE));
1319 if (dodef)
1321 uentry ue = usymtab_getTypeEntry (uid);
1323 uentry_setDatatype (ue, uid);
1326 if (sRef_modInFunction ())
1328 recordFunctionType (globtab->entries[uid]);
1331 return uid;
1334 ctype
1335 usymtab_supForwardTypeEntry (/*@only@*/ uentry e)
1336 /*@globals globtab, filetab@*/
1337 /*@modifies globtab, e@*/
1339 typeId uid = typeId_fromUsymId (usymtab_supEntryAux (globtab, e, FALSE));
1340 uentry ue = usymtab_getTypeEntry (uid);
1342 uentry_setDatatype (ue, uid);
1344 if (sRef_modInFunction ())
1346 recordFunctionType (globtab->entries[uid]);
1349 return (uentry_getAbstractType (ue));
1352 void
1353 usymtab_supEntrySref (uentry e)
1354 /*@globals utab, globtab, filetab@*/
1355 /*@modifies utab, globtab, e@*/
1357 sRef old = uentry_getSref (e);
1359 if (sRef_isType (old))
1361 uentry ue = usymtab_supEntryReturnAux (utab, e, TRUE);
1363 /*@access uentry@*/
1364 if (uentry_isValid (ue))
1366 sRef uref = uentry_getSref (ue);
1368 sRef_mergeStateQuiet (uref, old);
1369 sRef_clearDerived (uref);
1371 /*@noaccess uentry@*/
1373 else if (sRef_isKnown (old))
1375 usymtab_supEntry (e);
1377 else
1379 (void) usymtab_supEntryAux (utab, e, TRUE);
1383 void usymtab_supGlobalEntry (/*@only@*/ uentry e)
1384 /*@globals globtab, filetab@*/
1385 /*@modifies globtab, filetab, e@*/
1387 usymId uid;
1389 DPRINTF (("Sup global entry: %s", uentry_unparse (e)));
1391 uid = usymtab_supEntryAux (globtab, e, FALSE);
1393 if (sRef_modInFunction ())
1395 recordFunctionType (globtab->entries[uid]);
1399 uentry
1400 usymtab_supReturnFileEntry (/*@only@*/ uentry e)
1401 /*@globals filetab, globtab@*/
1402 /*@modifies filetab, globtab, e@*/
1404 llassert (filetab != usymtab_undefined);
1405 DPRINTF (("File entry: %s", uentry_unparse (e)));
1406 return (usymtab_supEntryReturnAux (filetab, e, FALSE));
1410 ** observers
1413 bool
1414 usymtab_inDeepScope (void) /*@globals utab@*/
1416 return (utab->lexlevel > paramsScope);
1419 static usymId
1420 usymtab_getIndex (/*@notnull@*/ usymtab s, cstring k)
1422 int i;
1424 DPRINTF (("Lookup %s", k));
1426 if (cstringTable_isDefined (s->htable))
1428 i = cstringTable_lookup (s->htable, k);
1429 return usymId_fromInt (i);
1431 else
1433 for (i = 0; i < s->nentries; i++)
1435 uentry current = s->entries[i];
1437 DPRINTF (("Check %d: %s", i, uentry_rawName (current)));
1439 if (!uentry_isUndefined (current)
1440 && cstring_equal (uentry_rawName (current), k))
1442 return usymId_fromInt (i);
1446 return usymId_notfound;
1450 static uentry
1451 usymtab_fetchIndex (/*@notnull@*/ usymtab s, usymId ui)
1453 int i = usymId_toInt (ui);
1454 llassert (i >= 0 && i < s->nentries);
1455 return (s->entries[i]);
1458 typeId
1459 usymtab_getTypeId (cstring k) /*@globals globtab@*/
1461 usymId uid = usymtab_getIndex (globtab, k);
1463 if (!usymtab_indexFound (uid)
1464 || !(uentry_isDatatype (usymtab_getTypeEntry (typeId_fromUsymId (uid)))))
1467 return typeId_invalid;
1469 else
1471 return typeId_fromUsymId (uid);
1475 /*@dependent@*/ uentry
1476 usymtab_lookupStructTag (cstring k)
1478 cstring sname = makeStruct (k);
1479 uentry ue = usymtab_lookupGlob (sname);
1481 cstring_free (sname);
1482 return (ue);
1485 /*@dependent@*/ uentry
1486 usymtab_lookupUnionTag (cstring k)
1488 cstring uname = makeUnion (k);
1489 uentry res = usymtab_lookupGlob (uname);
1491 cstring_free (uname);
1492 return res;
1495 /*@dependent@*/ uentry
1496 usymtab_lookupEnumTag (cstring k)
1498 cstring ename = makeEnum (k);
1499 uentry res = usymtab_lookupGlob (ename);
1501 cstring_free (ename);
1502 return res;
1505 usymId
1506 usymtab_getId (cstring k) /*@globals globtab@*/
1508 usymId uid = usymtab_getIndex (globtab, k);
1509 uentry ue;
1511 if (!usymtab_indexFound (uid))
1513 return usymId_invalid;
1516 ue = usymtab_getGlobalEntry (uid);
1518 if (uentry_isPriv (ue))
1520 return usymId_invalid;
1523 return uid;
1526 static /*@exposed@*/ uentry
1527 usymtab_getEntryAux (/*@notnull@*/ usymtab s, usymId uid)
1529 llassert (uid != usymId_invalid);
1531 if (uid < 0 || uid >= usymId_fromInt (s->nentries))
1533 llcontbug (message ("%s: out of range: level = %d [%d]",
1534 cstring_fromChars (__func__), s->lexlevel, uid));
1535 return uentry_undefined;
1538 llassertprint (uentry_isValid (s->entries[uid]),
1539 ("entry undefined: %d", uid));
1541 return s->entries[uid];
1544 /*@dependent@*/ /*@observer@*/ uentry
1545 usymtab_getGlobalEntry (usymId uid)
1546 /*@globals utab, globtab@*/
1548 if (dbgfree) return (uentry_undefined);
1550 if (utab->lexlevel > paramsScope)
1552 /* need to do this the awkward way, since it could be in conditional scope */
1553 return (usymtab_lookupSafe (uentry_rawName (globtab->entries[uid])));
1555 else
1557 return (globtab->entries[uid]);
1561 /*@dependent@*/ /*@exposed@*/ uentry usymtab_getTypeEntry (typeId uid)
1562 /*@globals globtab@*/
1564 if (dbgload)
1566 if (uid >= 0 && uid < typeId_fromInt (globtab->nentries))
1568 return (globtab->entries[uid]);
1570 else
1572 return (uentry_undefined);
1575 else
1577 llassert (uid >= 0 && uid < typeId_fromInt (globtab->nentries));
1578 return (globtab->entries[uid]);
1583 ** in load files
1586 /*@dependent@*/ /*@exposed@*/ uentry usymtab_getTypeEntrySafe (typeId uid)
1587 /*@globals globtab@*/
1589 if (uid < 0 || uid >= typeId_fromInt (globtab->nentries))
1591 return uentry_undefined;
1594 return (globtab->entries[uid]);
1597 bool usymtab_isBoolType (typeId uid)
1598 /*@globals globtab@*/
1600 llassert (uid >= 0 && uid < typeId_fromInt (globtab->nentries));
1602 return (cstring_equal (uentry_rawName (globtab->entries[uid]),
1603 context_getBoolName ()));
1606 cstring usymtab_getTypeEntryName (typeId uid)
1607 /*@globals globtab@*/
1609 uentry ue;
1611 if (dbgfree)
1613 return (cstring_makeLiteral ("<freetype>"));
1616 ue = usymtab_getTypeEntry (uid);
1618 if (dbgload && !uentry_isValid (ue))
1620 return (message ("<missing type: %d>", uid));
1623 llassertprint (uentry_isValid (ue), ("type undefined: %d", uid));
1625 return (uentry_getName (ue));
1628 # if 0
1629 /*@unused@*/ static void
1630 usymtab_rehash (/*@notnull@*/ usymtab s)
1632 int i;
1634 if (cstringTable_isDefined (s->htable))
1636 cstringTable_free (s->htable);
1639 s->htable = cstringTable_create (LLAHSHSIZE);
1641 for (i = 0; i < s->nentries; i++)
1643 cstringTable_insert (s->htable, cstring_copy (uentry_rawName (s->entries[i])), i);
1646 # endif
1649 ** superficial copy of usymtab
1651 ** DO copy spec entries
1654 static /*@only@*/ /*@notnull@*/ usymtab
1655 usymtab_shallowCopy (/*@notnull@*/ usymtab s) /*@*/
1657 usymtab copytab = usymtab_createRoot ();
1658 int i;
1660 for (i = 0; i < s->nentries; i++)
1662 usymtab_addEntryBase (copytab, s->entries[i]);
1665 return copytab;
1668 static void
1669 usymtab_shallowFree (/*@only@*/ /*@notnull@*/ usymtab s)
1671 aliasTable_free (s->aliases);
1672 refTable_free (s->reftable, s->nentries);
1673 sfree (s->entries);
1674 /*@-compdestroy@*/ sfree (s); /*@=compdestroy@*/
1677 usymId usymtab_convertTypeId (typeId uid)
1679 return usymtab_convertId (typeId_toUsymId (uid));
1683 ** usymtab_convertId: converts usymId from old table to sorted one
1686 usymId usymtab_convertId (usymId uid)
1687 /*@globals oldtab, utab@*/
1689 uentry ue;
1690 usymId ret;
1691 cstring name;
1693 llassert (usymtab_isDefined (oldtab));
1695 ue = usymtab_getEntryAux (oldtab, uid);
1697 llassertprint (uentry_isValid (ue), ("convertId: undefined: %d", uid));
1699 name = uentry_rawName (ue);
1701 ret = usymtab_getIndex (utab, name);
1702 llassert (ret == uid); /*! for now, no rehash! */
1703 DPRINTF (("Convert: %s [%d] -> %s [%d]",
1704 uentry_unparse (ue), uid,
1705 uentry_unparse (utab->entries[ret]), ret));
1707 llassertprint (ret != usymId_invalid, ("convertId: return is invalid"));
1709 return (ret);
1712 void
1713 usymtab_prepareDump (void)
1714 /*@globals oldtab, utab@*/
1715 /*@modifies oldtab, utab@*/
1717 llassert (usymtab_inGlobalScope ());
1718 llassert (oldtab == usymtab_undefined);
1721 DPRINTF (("Preparing to dump:"));
1722 usymtab_printAll ();
1725 oldtab = usymtab_shallowCopy (utab);
1727 # if 0
1729 ** alpha compare - make sure order is same on different platforms
1730 ** error messages appear in same order
1733 qsort (utab->entries, (size_t)utab->nentries,
1734 sizeof (*utab->entries),
1735 (int (*)(const void *, const void *)) uentry_xcomparealpha);
1737 usymtab_rehash (utab);
1738 # endif
1741 DPRINTF (("After rehash:"));
1742 usymtab_printAll ();
1746 void usymtab_dump (FILE *fout)
1747 /*@globals utab, oldtab@*/
1749 int i;
1750 bool neednl = FALSE;
1751 uentry lastentry = uentry_undefined;
1752 ekind lastekind = KINVALID;
1753 int linelen = 0;
1756 ** must call prepareDump first
1759 llassert (oldtab != usymtab_undefined);
1761 for (i = 0; i < utab->nentries; i++)
1763 uentry thisentry = utab->entries[i];
1764 ekind thisekind = uentry_getKind (thisentry);
1766 if (!uentry_hasRealName (thisentry))
1768 llassert (uentry_isGlobalMarker (thisentry));
1770 if (neednl)
1772 check (fputc ('\n', fout) == (int) '\n');
1775 fprintf (fout, "*%d (GlobalMarker)\n", KGLOBALMARKER);
1776 lastekind = KINVALID;
1777 linelen = 0;
1778 neednl = FALSE;
1780 else
1782 if (thisekind != lastekind)
1784 if (neednl)
1786 check (fputc ('\n', fout) == (int) '\n');
1789 neednl = FALSE;
1790 lastentry = uentry_undefined;
1791 fprintf (fout, "*%d (%s)\n", ekind_toInt (thisekind),
1792 cstring_toCharsSafe (ekind_capName (thisekind)));
1793 lastekind = thisekind;
1794 linelen = 0;
1798 ** evans - 2001-02-18 - added the - 48 fudge factor...
1799 ** extra characters dumped, but I haven't counded them carefully...
1802 if (uentry_isInvalid (lastentry) || !uentry_equiv (lastentry, thisentry)
1803 || (linelen > (MAX_DUMP_LINE_LENGTH - (2 * MAX_NAME_LENGTH) - 48)))
1805 cstring cdump;
1807 DPRINTF (("Dumping entry: %d", i));
1808 cdump = message ("^%d %q", i, uentry_dump (thisentry));
1809 /* was: cdump = uentry_dump (thisentry)); */
1811 lastentry = thisentry;
1812 if (neednl)
1814 check (fputc ('\n', fout) == (int) '\n');
1815 linelen = 0;
1818 linelen += cstring_length (cdump);
1820 /* no new line here! */
1821 if (cstring_length (cdump) > 0)
1823 check (fputs (cstring_toCharsSafe (cdump), fout) != EOF);
1826 cstring_free (cdump);
1827 neednl = TRUE;
1829 else
1831 cstring cdump = uentry_rawName (thisentry);
1832 DPRINTF (("Raw name: %s", cdump));
1833 linelen += (cstring_length (cdump) + 1);
1834 fprintf (fout, "#%s", cstring_toCharsSafe (cdump));
1839 if (neednl)
1841 check (fputc ('\n', fout) == (int) '\n');
1844 lastekind = KINVALID;
1846 fprintf(fout, ";; Library constraints\n");
1848 /*drl July 27 added this so that libraries without
1849 buffer constraints would be handled correctly.
1850 I'm trying to do this without breaking older libraries.
1852 Splint should still be able to handle libraries without this message.
1856 fprintf(fout, "start_Buffer_Constraints\n");
1858 for (i = 0; i < utab->nentries; i++)
1860 uentry thisentry = utab->entries[i];
1862 if (uentry_isFunction (thisentry) )
1864 constraintList preconditions;
1865 constraintList postconditions;
1867 preconditions = uentry_getFcnPreconditions (thisentry);
1868 postconditions = uentry_getFcnPostconditions (thisentry);
1870 if ( constraintList_isDefined(preconditions) ||
1871 constraintList_isDefined(postconditions) )
1873 fprintf(fout,"%s\n", cstring_toCharsSafe (uentry_rawName(thisentry) ) );
1874 if (constraintList_isDefined(preconditions) )
1876 fprintf(fout,"pre:\n");
1877 constraintList_dump(preconditions, fout);
1878 fprintf (fout, ";; end precondition constraints\n" );
1879 constraintList_free(preconditions);
1881 else
1883 fprintf(fout,"pre:EMPTY\n");
1885 if (constraintList_isDefined(postconditions) )
1887 fprintf(fout,"post:\n");
1888 constraintList_dump(postconditions, fout);
1889 fprintf (fout, ";; end precondition constraints\n" );
1890 constraintList_free(postconditions);
1892 else
1894 fprintf(fout,"post:EMPTY\n");
1903 void usymtab_load (FILE *f)
1904 /*@globals utab, globtab@*/
1905 /*@modifies utab, *f@*/
1907 char *s = mstring_create (MAX_DUMP_LINE_LENGTH);
1908 char *os = s;
1909 ekind kind = KINVALID;
1910 fileloc loc = g_currentloc;
1911 char c;
1912 uentry ue;
1914 dbgload = TRUE;
1916 llassert (utab == globtab);
1917 llassert (utab->nentries == 0);
1919 while (((s = reader_readLine (f, s, MAX_DUMP_LINE_LENGTH)) != NULL)
1920 && *s == ';')
1922 /* ignore ; comments */ ;
1925 while (s != NULL && *s != ';')
1927 int index;
1929 if (*s == '*')
1931 int ek;
1932 s++;
1933 ek = reader_getInt (&s);
1935 if (ek == KGLOBALMARKER)
1937 uentry lue = uentry_makeGlobalMarker ();
1938 DPRINTF (("Adding global marker: %s", uentry_unparseFull (lue)));
1939 usymtab_addEntryAlways (utab, lue);
1940 kind = KINVALID;
1941 goto nextiter;
1943 else
1945 kind = ekind_fromInt (ek);
1946 goto nextiter;
1950 if (*s == '$')
1952 llfatalerror
1953 (cstring_makeLiteral
1954 ("Library is in obsolete format. Use splint +whichlib "
1955 "to see which library is being loaded."));
1958 if (reader_optCheckChar (&s, '^'))
1960 index = reader_getInt (&s);
1962 else
1964 index = -1;
1967 llassert (kind != KINVALID);
1968 ue = uentry_undump (kind, loc, &s);
1970 llassert (utab->nentries == index || index == -1);
1972 if (uentry_isValid (ue))
1974 int lastindex = utab->nentries;
1975 ue = usymtab_addEntryAlways (utab, ue);
1978 # if 0
1979 if (uentry_isConstant (ue)) /*@i23! isPreProcessorMacro */
1981 cstring uname = uentry_getName (ue);
1983 /* Also check its a macro... */
1984 DPRINTF (("Installing: %s", uname));
1986 cpphash_installMacro
1987 (mstring_copy (cstring_toCharsSafe (uname)),
1988 cstring_length (uname),
1989 cpplib_createDefinition (message ("%s 255", uname),
1990 loc,
1991 FALSE, FALSE).defn,
1992 cpphash_hashCode (cstring_toCharsSafe (uname),
1993 cstring_length (uname),
1994 CPP_HASHSIZE));
1996 DPRINTF (("After install: %s", uname));
1998 # endif
2000 if (utab->nentries != lastindex + 1)
2002 DPRINTF (("No add: %s", uentry_unparseFull (ue)));
2003 BADBRANCH;
2005 /*@-branchstate@*/
2007 /*@=branchstate@*/
2010 ** now, any other names are the same uentry
2013 while (*(s++) == '#')
2015 cstring name = cstring_fromCharsO (reader_getWord (&s));
2016 uentry nue = uentry_nameCopy (name, ue);
2018 DPRINTF (("Name copy: %s", uentry_unparseFull (nue)));
2019 BADBRANCH;
2022 usymtab_addEntryAlways (utab, nue);
2025 while ((c = *s) != '\0' && (c !='\n'))
2027 if (!(c == ' ' || c == '\t'))
2029 llbuglit ("Junk in load file");
2032 s++;
2035 nextiter:
2037 s = reader_readLine (f, os, MAX_DUMP_LINE_LENGTH);
2041 /*DRL added 6/21/01
2042 to handle reading of buffer overflow related constraints
2044 while (fgets (s, MAX_DUMP_LINE_LENGTH, f) != NULL
2045 && *s == ';')
2047 ; /* ignore ;-comments */
2050 /*drl July 27 added this so that libraries without
2051 buffer constraints would be handled correctly.
2052 I'm trying to do this without breaking older libraries*/
2054 /*check for "optional" start buffer constraints message*/
2056 if (mstring_equalPrefix (s, "start_Buffer_Constraints"))
2058 (void) fgets (s, MAX_DUMP_LINE_LENGTH, f);
2061 while (s != NULL && *s != ';')
2063 constraintList preconditions;
2064 constraintList postconditions;
2065 cstring name = cstring_fromChars (reader_getWord (&s));
2066 cstring temp;
2068 ue = usymtab_lookup (name);
2069 cstring_free (name);
2071 preconditions = constraintList_undefined;
2072 postconditions = constraintList_undefined;
2074 if (!uentry_isValid(ue) )
2076 llfatalbug ((message("Invalid uentry for %s library file may be corrupted", cstring_fromChars(s) ) ));
2078 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2080 temp = cstring_fromChars (reader_getWord(&s) );
2082 if (cstring_compareLit (temp,"pre:") == 0 )
2084 preconditions = constraintList_undump (f);
2086 else
2088 if (cstring_compareLit (temp,"pre:EMPTY") != 0 )
2089 llfatalbug ((message("Error reading library file pre:EMPTY expected but got %s", temp ) ));
2092 cstring_free(temp);
2094 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2096 temp = cstring_fromChars(reader_getWord(&s) );
2097 if (cstring_compareLit (temp, "post:") == 0 )
2099 postconditions = constraintList_undump (f);
2101 else
2103 if (cstring_compareLit (temp, "post:EMPTY") != 0 )
2104 llfatalbug ((message("Error reading library file post:EMPTY expected but got %s", temp ) ));
2107 cstring_free (temp);
2109 uentry_setPreconditions (ue, functionConstraint_createBufferConstraint (preconditions));
2110 uentry_setPostconditions (ue, functionConstraint_createBufferConstraint (postconditions));
2112 s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
2115 dbgload = FALSE;
2116 sfree (os);
2120 ** file scope for static variables
2123 void
2124 usymtab_enterFile (void)
2125 /*@globals utab, globtab, filetab@*/
2126 /*@modifies filetab@*/
2128 llassert (utab == globtab);
2130 # if 0
2131 /* check globals */
2133 usymtab_entries (globtab, ue)
2135 if (sRef_hasDerived (uentry_getSref (ue)))
2137 fprintf (g_warningstream, "Derived Global: %s\n", uentry_unparse (ue));
2138 fprintf (g_warningstream, "sRef: %s\n", sRef_unparseFull (ue->sref));
2140 } end_usymtab_entries ;
2142 # endif
2144 usymtab_enterScope ();
2145 filetab = utab;
2148 void
2149 usymtab_exitFile (void)
2150 /*@globals utab, filetab@*/
2151 /*@modifies filetab, utab@*/
2154 llassert (utab->lexlevel == 1);
2156 usymtab_exitScope (exprNode_undefined);
2157 filetab = NULL;
2160 void
2161 usymtab_enterScope (void)
2162 /*@globals utab, globtab, filetab@*/
2163 /*@modifies utab@*/
2165 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
2167 /* unconditional scope: optimize to avoid copy */
2168 t->aliases = aliasTable_copy (utab->aliases);
2169 utab = t;
2171 llassert (usymtab_isDefined (t->env));
2173 if (t->env->lexlevel == paramsScope && context_inFunctionLike ())
2175 noshadowerror = TRUE;
2176 usymtab_handleParams ();
2177 noshadowerror = FALSE;
2182 ** setup external references:
2183 ** o only, unique params alias external args
2184 ** o other params may alias anything of their type
2187 static void
2188 usymtab_handleParams (void)
2189 /*@globals utab, globtab, filetab@*/
2190 /*@modifies utab, globtab@*/
2192 usymtab ptab = utab->env;
2193 uentry fcn = context_getHeader ();
2195 usymtab_entries (ptab, param)
2197 uentry ue;
2199 if (!uentry_isYield (param))
2201 sRef uref;
2202 sRef pref = uentry_getSref (param);
2204 /* Could be a global. */
2206 if (uentry_isAnyParam (param))
2208 ue = uentry_makeVariable (fixParamName (uentry_rawName (param)),
2209 uentry_getType (param),
2210 fileloc_copy (uentry_whereDeclared (param)),
2211 FALSE);
2213 uentry_copyState (ue, param);
2214 uentry_setRefParam (ue);
2216 ue = usymtab_supEntrySrefReturn (ue);
2218 /* must be after supercede! */
2220 if (!sRef_stateKnown (pref))
2222 uentry_setDefState (ue, SS_DEFINED);
2223 uentry_setDefState (param, SS_DEFINED);
2225 else
2227 if (sRef_isStateSpecial (pref))
2229 uentry_setDefState (ue, SS_SPECIAL); /* ALLOCATED); */
2230 /* evans 2002-01-01: should be unnecessary, the pre clauses
2231 ** set the state if necessary.
2234 else
2236 uentry_setDefState (ue, sRef_getDefState (pref));
2240 uref = uentry_getSref (ue);
2242 if (sRef_isStack (uref))
2244 alkind pkind = sRef_getAliasKind (pref);
2246 if (alkind_isKnown (pkind) && !alkind_isLocal (pkind)
2247 && !alkind_isStack (pkind))
2249 sRef_setAliasKind (uref, pkind, fileloc_undefined);
2250 sRef_setOrigAliasKind (uref, pkind);
2252 else
2254 sRef_setAliasKind (uref, AK_IMPTEMP, fileloc_undefined);
2255 sRef_setOrigAliasKind (uref, AK_IMPTEMP);
2257 if (uentry_isOut (param))
2261 else
2263 sRef_setDefined (uref, fileloc_undefined);
2269 usymtab_addMustAlias (uref, pref);
2271 if (!(uentry_isOnly (param) || uentry_isUnique (param)))
2274 ** This is needed for detecting possibly aliased parameters.
2277 sRef s = sRef_makeExternal (uref);
2278 usymtab_addMustAlias (uref, s);
2281 if (sRef_isKillRef (pref))
2283 sRef_setAliasKind (uref, AK_NEWREF, fileloc_undefined);
2284 sRef_setOrigAliasKind (uref, AK_KILLREF);
2286 else if (sRef_isRefCounted (uref))
2288 sRef_setOrigAliasKind (uref, AK_REFCOUNTED);
2290 else
2292 /* was AK_UNIQUE */
2293 sRef_setOrigAliasKind (uref, AK_LOCAL);
2296 else
2300 } end_usymtab_entries;
2303 if (uentry_hasStateClauseList (fcn))
2305 stateClauseList clauses = uentry_getStateClauseList (fcn);
2307 stateClauseList_preElements (clauses, cl)
2309 fileloc loc = stateClause_loc (cl);
2310 sRefSet srs;
2312 if (stateClause_isGlobal (cl))
2314 DPRINTF (("Global Marker: %s",
2315 sRef_unparseFull (usymtab_lookupGlobalMarker ())));
2316 llassert (sRef_isGlobalMarker (usymtab_lookupGlobalMarker ()));
2317 srs = sRefSet_single (usymtab_lookupGlobalMarker ());
2319 else
2321 srs = stateClause_getRefs (cl);
2324 sRefSet_elements (srs, el)
2326 sRef base = sRef_getRootBase (el);
2327 sRef sb = sRef_updateSref (el);
2329 if (sRef_isResult (base))
2331 ; /* nothing to do before */
2333 else if (sRef_isParam (base) || sRef_isGlobalMarker (base))
2335 if (stateClause_setsMetaState (cl))
2337 /* copied from exprNode.c:3040 */
2338 qual ql = stateClause_getMetaQual (cl);
2339 annotationInfo ainfo = qual_getAnnotationInfo (ql);
2340 metaStateInfo minfo = annotationInfo_getState (ainfo);
2341 cstring key = metaStateInfo_getName (minfo);
2342 int mvalue = annotationInfo_getValue (ainfo);
2344 DPRINTF (("Sets meta state! %s", stateClause_unparse (cl)));
2346 if (sRef_isResult (base))
2348 BADBRANCH;
2350 else
2352 sRef_setMetaStateValueComplete (sb, key, mvalue, loc);
2355 else
2357 sRefMod modf = stateClause_getEntryFunction (cl);
2359 if (modf != NULL)
2361 sRefSet aliases = usymtab_allAliases (sb);
2363 modf (sb, loc);
2365 sRefSet_elements (aliases, sr)
2367 modf (sr, loc);
2368 } end_sRefSet_elements ;
2370 sRefSet_free (aliases);
2374 else
2376 if (sRef_isValid (base))
2378 DPRINTF (("Base: %s", sRef_unparseFull (base)));
2379 BADBRANCH;
2382 } end_sRefSet_elements ;
2383 } end_stateClauseList_preElements ;
2387 void
2388 usymtab_enterFunctionScope (uentry fcn)
2389 /*@globals utab, filetab, globtab@*/
2390 /*@modifies utab@*/
2392 usymtab t = usymtab_create (US_NORMAL, utab, TRUE);
2394 DPRINTF (("Enter function: %s", uentry_unparse (fcn)));
2396 if (utab->lexlevel != fileScope)
2398 if (utab->lexlevel > fileScope)
2400 llparseerror (cstring_makeLiteral ("New function scope inside function"));
2402 while (utab->lexlevel > fileScope)
2404 /*@i@*/ utab = usymtab_dropEnv (utab);
2405 /*@-branchstate@*/
2407 /*@=branchstate@*/
2409 else
2411 llfatalbug (cstring_makeLiteral ("New function not inside file."));
2413 /*@-branchstate@*/ } /*@=branchstate@*/
2415 utab = t;
2417 DPRINTF (("Globs: %s", globSet_unparse (uentry_getGlobs (fcn))));
2419 globSet_allElements (uentry_getGlobs (fcn), el)
2421 DPRINTF (("Here we go: %s", sRef_unparseFull (el)));
2423 if (sRef_isUndefGlob (el))
2425 usymId index = sRef_getScopeIndex (el);
2426 sRef sr = sRef_updateSref (el);
2427 fileloc loc = uentry_whereEarliest (fcn);
2429 DPRINTF (("update: %s", sRef_unparseFull (sr)));
2430 DPRINTF (("Undef!"));
2431 if (sRef_isFileStatic (el))
2433 ctype ct = sRef_getType (el);
2435 if (ctype_isRealArray (ct) || ctype_isRealSU (ct))
2437 sRef_setAllocated (sr, loc);
2439 else
2441 sRef_setUndefined (sr, loc);
2444 else
2446 uentry ue = globtab->entries[index];
2447 ctype ct = uentry_getType (ue);
2449 if (ctype_isArray (ct) || ctype_isSU (ct))
2451 sRef_setAllocated (sr, loc);
2453 else
2455 sRef_setUndefined (sr, loc);
2459 else if (sRef_isAllocated (el))
2461 sRef sr = sRef_updateSref (el);
2462 fileloc loc = uentry_whereEarliest (fcn);
2464 sRef_setAllocated (sr, loc);
2466 else if (sRef_isPartial (el))
2468 sRef sr = sRef_updateSref (el);
2469 fileloc loc = uentry_whereEarliest (fcn);
2471 sRef_setPartial (sr, loc);
2473 else
2476 sRef sr = sRef_updateSref (el);
2477 fileloc loc = uentry_whereEarliest (fcn);
2479 sRef_setDefined (sr, loc);
2482 /* defined */
2483 /* shouldn't need to do anything! */
2485 } end_globSet_allElements;
2487 DPRINTF (("Globs after: %s", globSet_unparse (uentry_getGlobs (fcn))));
2488 # ifdef DEBUGSPLINT
2489 usymtab_checkAllValid ();
2490 # endif
2493 static void
2494 usymtab_caseBranch (void)
2495 /*@modifies utab@*/
2497 usymtab t = usymtab_create (US_CBRANCH, utab, FALSE);
2498 utab = t;
2501 void
2502 usymtab_switchBranch (/*@unused@*/ exprNode s)
2503 /*@modifies utab@*/
2505 usymtab t = usymtab_create (US_SWITCH, utab, FALSE);
2507 t->aliases = aliasTable_copy (utab->aliases);
2508 utab = t;
2511 void
2512 usymtab_trueBranch (/*@only@*/ guardSet guards)
2513 /*@modifies utab@*/
2515 usymtab t = usymtab_create (US_TBRANCH, utab, FALSE);
2518 ** not true! (could be in a macro)
2520 ** llassertprint (utab->lexlevel > paramsScope,
2521 ** ("not in scope: %s", usymtab_unparseLocal ()));
2525 guardSet_free (t->guards);
2526 t->guards = guards;
2528 aliasTable_free (t->aliases);
2529 t->aliases = aliasTable_copy (utab->aliases);
2531 utab = t;
2535 ** consider,
2537 ** { int a; if (...) a = 3; < a may be undefined here!
2541 void
2542 usymtab_popTrueBranch (exprNode pred, exprNode expr, clause cl) /*@modifies utab@*/
2545 ** add a false branch
2546 ** (could be done more efficiently as a special case, but
2547 ** it is better to only maintain one version of the code)
2550 if (utab->kind != US_TBRANCH
2551 && context_inIterDef ())
2553 usymtab_exitScope (expr);
2555 else
2557 DPRINTF (("pop true branch.."));
2558 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2559 usymtab_popBranches (pred, expr, exprNode_undefined, TRUE, cl);
2563 void
2564 usymtab_popCaseBranch (void) /*@modifies utab@*/
2566 llassert (utab->kind == US_CBRANCH);
2567 usymtab_quietPlainExitScope ();
2570 void
2571 usymtab_popTrueExecBranch (exprNode pred, exprNode expr, clause cl)
2574 ** add a false branch that must return --- that is,
2575 ** the true branch is always executed!
2578 usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred)));
2579 usymtab_popBranches (pred, expr, exprNode_makeMustExit (), FALSE, cl);
2582 void
2583 usymtab_popOrBranch (exprNode pred, exprNode expr)
2584 /*@modifies utab@*/
2586 bool mustReturn;
2587 usymtab env = utab->env;
2588 usymtab otab = utab;
2589 int i = 0;
2591 llassert (env != NULL);
2593 if (exprNode_isError (expr))
2595 mustReturn = FALSE;
2597 else
2599 mustReturn = exprNode_mustEscape (expr);
2603 llassert (utab->kind == US_TBRANCH);
2606 ** merge each entry in table with its original
2607 ** unless execution cannot continue after this branch
2610 for (i = 0; i < utab->nentries; i++)
2612 uentry current = utab->entries[i];
2613 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2615 uentry_mergeState (old, current, exprNode_loc (expr),
2616 mustReturn, FALSE, TRUE, ORCLAUSE);
2620 if (mustReturn)
2622 env->guards = guardSet_levelUnionFree (env->guards,
2623 guardSet_invert (exprNode_getGuards (pred)),
2624 env->lexlevel);
2626 else
2628 env->aliases = aliasTable_levelUnion (env->aliases, otab->aliases, env->lexlevel);
2631 /* env is now utab */
2632 usymtab_quietPlainExitScope ();
2636 ** case syntax in C is very unrestricted. This is unfortunate.
2638 ** A switch case is ended either by a new case or default, or
2639 ** a close } that may close the switch or some other control
2640 ** structure.
2643 bool
2644 usymtab_newCase (/*@unused@*/ exprNode pred, exprNode last)
2645 /*@modifies utab@*/
2647 bool mustBreak = usymtab_mustBreak (utab);
2648 bool mustReturn = usymtab_mustEscape (utab);
2649 usymtab stab = utab;
2651 DPRINTF (("New case!"));
2654 ** Find last case (or outer switch)
2657 while (stab->kind != US_CBRANCH && stab->kind != US_SWITCH)
2659 stab = stab->env;
2660 llassert (stab != GLOBAL_ENV);
2663 while (stab->kind == US_CBRANCH)
2665 stab = stab->env;
2666 llassert (stab != GLOBAL_ENV);
2670 ** if its a fall through case, merge in outside entries and last case.
2672 ** e.g.,
2673 ** ...
2674 ** switch
2675 ** case 1: x = 3; <fall through>
2676 ** case 2: << x may not be defined
2680 if (!mustBreak && !mustReturn && utab->kind == US_CBRANCH)
2682 llassert (stab->kind == US_SWITCH || stab->kind == US_NORMAL);
2684 usymtab_entries (utab, ue) /* but, keep track of used variables */
2686 uentry old = usymtab_lookupAux (stab, uentry_rawName (ue));
2688 llassert (uentry_isValid (old));
2690 /* modifies ue, not old */
2692 uentry_mergeState (ue, old, exprNode_loc (last),
2693 FALSE, FALSE, TRUE, CASECLAUSE);
2694 } end_usymtab_entries;
2696 utab->aliases = aliasTable_levelUnion (utab->aliases,
2697 stab->aliases, utab->lexlevel);
2700 ** No need for a new branch.
2703 return FALSE;
2705 else
2707 usymtab_caseBranch ();
2708 /*@-mustfree@*/ /*< utab->aliases >*/
2709 utab->aliases = aliasTable_copy (stab->aliases);
2710 /*@=mustfree@*/
2712 return TRUE;
2717 ** for && (both pred and expr are executed)
2720 void
2721 usymtab_popAndBranch (exprNode pred, /*@unused@*/ exprNode expr)
2722 /*@modifies utab@*/
2724 usymtab env = utab->env;
2725 usymtab otab= utab;
2726 int i = 0;
2728 llassert (utab->kind == US_TBRANCH);
2731 ** merge each entry in table with its original
2732 ** unless execution cannot continue after this branch
2735 for (i = 0; i < utab->nentries; i++)
2737 uentry current = utab->entries[i];
2738 sRef tref = uentry_getSref (current);
2739 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
2740 sRef oref = uentry_getSref (old);
2742 /* note that is current is in a nested branch,
2743 it may create a "new" old entry. */
2745 llassert (uentry_isValid (old));
2746 uentry_mergeState (old, current, exprNode_loc (expr),
2747 FALSE, FALSE, TRUE, ANDCLAUSE);
2750 ** if is it defined by the second clause, then it should be defined.
2753 if (sRef_isAnyDefined (tref)
2754 && (sRef_isAllocated (oref) || sRef_isStateUndefined (oref)))
2756 sRef_setDefined (oref, g_currentloc);
2760 DPRINTF (("Popping and: %s / %s",
2761 guardSet_unparse (utab->guards),
2762 guardSet_unparse (exprNode_getGuards (pred))));
2764 utab->guards = guardSet_levelUnionFree (utab->guards,
2765 guardSet_invert (exprNode_getGuards (pred)),
2766 utab->lexlevel);
2767 utab->aliases = aliasTable_levelUnion (utab->aliases, otab->aliases, utab->lexlevel);
2769 usymtab_quietPlainExitScope ();
2774 ** Stack should be [ US_CBRANCH+ US_SWITCH ]
2775 ** Only branches which do not return (except possibly the last branch) are included.
2777 ** Conditionally merge state from all CBRANCHes.
2779 ** If allpaths is TRUE, then all possible executions go through some switch
2780 ** case, and the original scope is not merged.
2783 void
2784 usymtab_exitSwitch (/*@unused@*/ exprNode sw, bool allpaths)
2785 /*@modifies utab@*/
2787 usymtab ttab = utab;
2788 usymtab stab = ttab;
2789 usymtab ltab = ttab;
2790 bool lastMustReturn = usymtab_mustEscape (utab);
2791 int i;
2794 while (stab->kind == US_CBRANCH)
2796 stab = stab->env;
2797 llassert (stab != GLOBAL_ENV);
2800 while (stab->kind == US_NORMAL)
2802 stab = stab->env;
2803 llassert (stab != GLOBAL_ENV);
2806 llassert (stab->kind == US_SWITCH);
2808 /* go to the scope outside the switch (US_SWITCH is just a marker! */
2809 stab = stab->env;
2810 llassert (stab != GLOBAL_ENV);
2813 ttab = ttab->env;
2814 llassert (usymtab_isDefined (ttab));
2816 if (ttab->kind == US_CBRANCH)
2818 /* was quietPlainExitScope --- but, can't free it yet! */
2819 utab = utab->env;
2820 llassert (utab != GLOBAL_ENV);
2822 while (ttab->kind == US_CBRANCH)
2825 ** (from popTrueBranch)
2828 bool mustReturn = usymtab_mustEscape (ttab);
2829 bool mustBreak = usymtab_mustBreak (ttab);
2831 usymtab_entries (ttab, current)
2833 uentry old = /*@-compmempass@*/ usymtab_lookupAux (ltab, uentry_rawName (current));
2834 /*@=compmempass@*/
2837 ** note that is this is in a nested branch,
2838 ** it may create a "new" old entry.
2841 if (uentry_isValid (old))
2843 if (lastMustReturn)
2845 uentry_mergeUses (current, old);
2846 uentry_setState (old, current);
2848 else
2850 uentry_mergeState (old, current, exprNode_loc (sw),
2851 mustReturn, FALSE, TRUE, SWITCHCLAUSE);
2854 else
2858 } end_usymtab_entries;
2861 ** if entry is not in symbol table for this case, merge with pre-switch
2862 ** table
2865 if (!mustReturn && !mustBreak)
2867 usymtab_entries (stab, current)
2869 if (!usymtab_indexFound (usymtab_getIndex (ttab, uentry_rawName (current))))
2871 uentry old = /*@-compmempass@*/
2872 usymtab_lookupAux (ltab, uentry_rawName (current));
2873 /*@=compmempass@*/
2875 llassert (uentry_isValid (old));
2876 uentry_mergeState (old, current, exprNode_loc (sw),
2877 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2879 } end_usymtab_entries;
2882 ltab->env = ttab->env;
2883 ttab = ltab->env;
2886 ** Suprious error, becuase of environments.
2889 /*@i1@*/ utab = ltab;
2891 lastMustReturn = FALSE;
2892 /*@-branchstate@*/
2895 /*@=branchstate@*/
2898 ** now, there is one US_CBRANCH. Merge this with the stab.
2902 for (i = 0; i < ltab->nentries; i++)
2904 uentry current = ltab->entries[i];
2905 uentry old = usymtab_lookupAux (stab, uentry_rawName (current));
2907 /* note that is this is in a nested branch,
2908 it may create a "new" old entry. */
2911 if (uentry_isValid (old))
2913 if (allpaths)
2915 uentry_mergeUses (current, old);
2916 uentry_setState (old, current);
2918 else
2920 uentry_mergeState (old, current, exprNode_loc (sw),
2921 FALSE, FALSE, TRUE, SWITCHCLAUSE);
2924 else
2930 ** exit the switch
2935 ** switch may or may not be followed by a new scope
2938 if (utab->kind == US_SWITCH)
2940 usymtab_quietPlainExitScope ();
2942 else
2944 usymtab_quietPlainExitScope ();
2945 llassert (utab->kind == US_SWITCH);
2946 usymtab_quietPlainExitScope ();
2951 static void
2952 updateNullState (sRef el, /*@notnull@*/ usymtab ttab,
2953 /*@notnull@*/ usymtab ftab, bool trueGuard)
2955 sRef base = sRef_getRootBase (el);
2956 int level = sRef_lexLevel (base);
2958 if (sRef_isCvar (base))
2960 usymId index = sRef_getScopeIndex (base);
2961 uentry ue = usymtab_getRefTab (ttab, level, index);
2963 if (!uentry_isLset (ue))
2965 sRef sr = uentry_getSref (ue);
2967 if (trueGuard)
2969 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2971 else
2973 if (!guardSet_isGuarded (ttab->guards, el)
2974 && !sRef_isNotNull (sr))
2976 DPRINTF (("Here! %s / %s",
2977 sRef_unparseFull (sr),
2978 sRef_unparseFull (el)));
2979 sRef_setDerivNullState (sr, el, NS_DEFNULL);
2983 else
2988 ue = usymtab_getRefTab (ftab, level, index);
2990 if (!uentry_isLset (ue))
2992 sRef sr = uentry_getSref (ue);
2994 if (!trueGuard) /* yikes! forgot the ! */
2996 sRef_setDerivNullState (sr, el, NS_NOTNULL);
2998 else
3001 if (!guardSet_isGuarded (ftab->guards, el)
3002 && !sRef_isNotNull (sr))
3004 sRef_setDerivNullState (sr, el, NS_DEFNULL);
3008 else
3015 void
3016 usymtab_popBranches (exprNode pred, exprNode tbranch, exprNode fbranch,
3017 bool isOpt, clause cl)
3018 /*@modifies utab@*/
3020 int i = 0;
3021 usymtab ftab = utab;
3022 usymtab ttab = utab->env;
3024 fileloc loc;
3025 usymtab env;
3026 guardSet guards = exprNode_getGuards (pred);
3027 sRefSet tguards = guardSet_getTrueGuards (guards);
3028 sRefSet fguards = guardSet_getFalseGuards (guards);
3029 bool mustReturnT = exprNode_mustEscape (tbranch);
3030 bool mustReturnF = exprNode_mustEscape (fbranch);
3032 DPRINTF (("Pop branches: %s [mustreturn: %s/%s]", exprNode_unparse (pred),
3033 bool_unparse (mustReturnT),
3034 bool_unparse (mustReturnF)));
3036 if (exprNode_isDefined (fbranch))
3038 loc = exprNode_loc (fbranch);
3040 else
3042 loc = exprNode_loc (tbranch);
3045 llassert (usymtab_isDefined (ttab));
3047 env = ttab->env;
3049 llassert (usymtab_isDefined (env));
3050 llassert (ftab->kind == US_FBRANCH);
3051 llassert (ttab->kind == US_TBRANCH);
3054 ** For each element that is true guarded (i.e., if (x != NULL))
3055 ** make x = null in false branch,
3056 ** and x = notnull in true branch.
3057 ** unless x was set locally in that branch.
3058 ** For each element that is false guarded (x == NULL)
3059 ** make x = null in true, notnull in false.
3061 ** For each element that is either guarded (pred(x))
3065 sRefSet_allElements (tguards, el)
3067 updateNullState (el, ttab, ftab, TRUE);
3068 } end_sRefSet_allElements;
3070 sRefSet_allElements (fguards, el)
3072 updateNullState (el, ttab, ftab, FALSE);
3073 } end_sRefSet_allElements;
3077 ** if an entry is in both true and false, merge the entries,
3078 ** then replace original with new state.
3080 ** if an entry is in one table, merge it with the original.
3083 DPRINTF (("ftab: %d", ftab->nentries));
3085 for (i = 0; i < ftab->nentries; i++)
3087 uentry fthis = ftab->entries[i];
3088 uentry old = usymtab_lookupAux (env, uentry_rawName (fthis));
3089 usymId tindex = usymtab_getIndex (ttab, uentry_rawName (fthis));
3091 DPRINTF (("Entry: %s / %s", uentry_unparseFull (fthis), uentry_unparseFull (old)));
3093 if (uentry_isUndefined (old))
3095 /* possible entry was added as an undefined id */
3096 DPRINTF (("Undefined! %s", uentry_rawName (fthis)));
3097 continue;
3100 if (usymtab_indexFound (tindex))
3102 uentry tthis = ttab->entries[tindex];
3104 /* note that is this is in a nested branch,
3105 it may create a "new" old entry. */
3107 if (!mustReturnF)
3109 if (!mustReturnT)
3111 uentry_mergeState (fthis, tthis, loc,
3112 mustReturnT, FALSE, FALSE, cl);
3114 else
3116 uentry_mergeUses (fthis, tthis);
3119 uentry_setState (old, fthis);
3121 /*@-mustfree@*/
3123 /*@=mustfree@*/
3124 else
3126 uentry_setState (old, tthis);
3127 uentry_mergeState (old, fthis, loc, mustReturnF,
3128 TRUE, FALSE, cl);
3131 ttab->entries[tindex] = uentry_undefined;
3132 uentry_free (tthis);
3134 else
3136 uentry_mergeState (old, fthis, loc, mustReturnF, TRUE, FALSE, cl);
3140 for (i = 0; i < ttab->nentries; i++)
3142 uentry current = ttab->entries[i];
3144 DPRINTF (("ttab: %s", uentry_unparseFull (current)));
3146 if (!uentry_isUndefined (current))
3148 uentry old = usymtab_lookupAux (env, uentry_rawName (current));
3150 DPRINTF (("Old: %s", uentry_unparseFull (old)));
3152 if (uentry_isUndefined (old))
3154 llcontbug (message ("Undefined entry: %s", uentry_rawName (current)));
3155 continue;
3158 if (mustReturnF)
3160 uentry_mergeUses (current, old);
3161 uentry_setState (old, current);
3163 else
3166 ** Assumes false branch is a fall-through if
3167 ** fbranch is not defined. This is true, unless
3168 ** where was some greivous error in processing
3169 ** the else branch of an if-then, in which case
3170 ** this is probably the right thing to do anyway.
3173 uentry_mergeState (old, current, loc, mustReturnT,
3174 FALSE, isOpt, cl);
3177 DPRINTF (("==> %s", uentry_unparseFull (old)));
3182 ** Plain levelUnion doesn't work, since we need to use the sRef's in env->aliases
3183 ** if they are present.
3186 llassert (NOALIAS (env->aliases, ttab->aliases));
3187 llassert (NOALIAS (env->aliases, ftab->aliases));
3189 aliasTable_free (env->aliases);
3191 env->aliases = aliasTable_levelUnionNew (ttab->aliases,
3192 ftab->aliases, env->lexlevel);
3194 aliasTable_fixSrefs (env->aliases);
3196 DPRINTF (("Aliases: %s", aliasTable_unparse (env->aliases)));
3198 /* exit true and false scopes */
3199 usymtab_quietPlainExitScope ();
3200 usymtab_quietPlainExitScope ();
3202 if (mustReturnT)
3204 utab->guards = guardSet_levelUnionFree
3205 (utab->guards,
3206 guardSet_invert (exprNode_getGuards (pred)),
3207 utab->lexlevel);
3210 if (mustReturnF)
3212 utab->guards = guardSet_levelUnion (utab->guards,
3213 exprNode_getGuards (pred),
3214 utab->lexlevel);
3217 DPRINTF (("Here."));
3220 static void usymtab_fixCases (void) /*@modifies utab@*/ {
3221 while (utab->kind == US_CBRANCH)
3223 usymtab_quietPlainExitScope ();
3226 llassert (utab->kind != US_CBRANCH);
3229 void
3230 usymtab_altBranch (/*@only@*/ guardSet guards)
3231 /*@modifies utab@*/
3233 usymtab t;
3234 usymtab parent = utab->env;
3236 t = usymtab_create (US_FBRANCH, utab, FALSE);
3239 ** If we are in a case, need to close it. The C syntax
3240 ** is very liberal, so this kludge is necessary.
3243 usymtab_fixCases ();
3245 DPRINTF (("Current kind: %s", usymtab_unparseStack ()));
3247 llassert (utab->kind == US_TBRANCH);
3248 llassert (parent != GLOBAL_ENV);
3250 guardSet_free (t->guards);
3251 t->guards = guards;
3253 aliasTable_free (t->aliases);
3254 t->aliases = aliasTable_copy (parent->aliases);
3256 utab = t;
3259 void
3260 usymtab_allDefined (void)
3261 /*@globals utab, globtab@*/
3263 int i;
3265 llassert (utab == globtab);
3267 for (i = 0; i < utab->nentries; i++)
3269 uentry e = utab->entries[i];
3271 if (uentry_isPriv (e))
3273 ; /* no need to define it */
3275 else
3277 if (context_getFlag (FLG_SPECUNDECL))
3279 fileloc sloc = uentry_whereSpecified (e);
3280 fileloc dloc = uentry_whereDeclared (e);
3282 if (fileloc_isDefined (sloc)
3283 && !uentry_isFakeTag (e)
3284 && !fileloc_isDefined (dloc))
3286 voptgenerror
3287 (FLG_SPECUNDECL,
3288 message ("%s %q specified but not declared",
3289 ekind_capName (uentry_getKind (e)),
3290 uentry_getName (e)),
3291 sloc);
3295 if (!uentry_isCodeDefined (e))
3297 fileloc dloc = uentry_whereDeclared (e);
3299 if (fileloc_isLib (dloc) || fileloc_isXHFile (dloc))
3303 else if (fileloc_isDefined (dloc))
3305 if (!uentry_isAnyTag (e))
3307 if (fileloc_isUser (dloc))
3309 voptgenerror
3310 (FLG_DECLUNDEF,
3311 message ("%s %q declared but not defined",
3312 ekind_capName (uentry_getKind (e)),
3313 uentry_getName (e)),
3314 dloc);
3315 DPRINTF (("decl: %s", uentry_unparseFull (e)));
3319 else
3321 fileloc sloc = uentry_whereSpecified (e);
3323 if (fileloc_isDefined (sloc)
3324 && !fileloc_isImport (sloc)
3325 && !fileloc_isLib (sloc)
3326 && !fileloc_isPreproc (sloc)
3327 && !uentry_isFakeTag (e))
3329 if (uentry_isVariable (e) || uentry_isFunction (e))
3331 voptgenerror
3332 (FLG_SPECUNDEF,
3333 message ("%s %q specified but not declared or defined",
3334 ekind_capName (uentry_getKind (e)),
3335 uentry_getName (e)),
3336 sloc);
3338 else
3340 voptgenerror
3341 (FLG_SPECUNDEF,
3342 message ("%s %q specified but not defined",
3343 ekind_capName (uentry_getKind (e)),
3344 uentry_getName (e)),
3345 sloc);
3354 void usymtab_exportHeader (void)
3355 /*@globals utab@*/
3357 int i;
3359 for (i = 0; i < utab->nentries; i++)
3361 uentry ce = utab->entries[i];
3363 if (!uentry_isDatatype (ce)
3364 && !uentry_isAnyTag (ce)
3365 && !uentry_isEitherConstant (ce) && !uentry_isStatic (ce)
3366 && !uentry_isExternal (ce)
3367 && !uentry_isForward (ce))
3369 fileloc fwhere = uentry_whereDeclared (ce);
3371 if (fileloc_isUndefined (fwhere)
3372 && uentry_isFunction (ce))
3374 fwhere = uentry_whereDefined (ce);
3377 if (fileloc_isDefined (fwhere)
3378 && !fileloc_isHeader (fwhere)
3379 && !fileloc_isXHFile (fwhere)
3380 && !(fileloc_isSpecialFile (fwhere)
3381 && !context_getFlag (FLG_UNUSEDSPECIAL)))
3383 if (uentry_isVariable (ce))
3385 if (optgenerror
3386 (FLG_EXPORTHEADERVAR,
3387 message ("%s %q exported but not declared in header file",
3388 ekind_capName (uentry_getKind (ce)),
3389 uentry_getName (ce)),
3390 fwhere))
3392 uentry_showDefSpecInfo (ce, fwhere);
3395 else
3397 if (!uentry_isIter (ce)
3398 && !uentry_isEndIter (ce)
3399 && !uentry_isExpandedMacro (ce))
3401 if (uentry_isFunction (ce)
3402 && cstring_equalLit (uentry_rawName (ce), "main"))
3404 ; /* no error for main */
3406 else
3408 if (optgenerror
3409 (FLG_EXPORTHEADER,
3410 message ("%s %q exported but not declared "
3411 "in header file",
3412 ekind_capName (uentry_getKind (ce)),
3413 uentry_getName (ce)),
3414 fwhere))
3416 uentry_showDefSpecInfo (ce, fwhere);
3426 void usymtab_exportLocal (void)
3427 /*@globals utab@*/
3429 int i;
3431 for (i = 0; i < utab->nentries; i++)
3433 uentry ce = utab->entries[i];
3435 if (!uentry_isDatatype (ce) && !uentry_isAnyTag (ce)
3436 && !uentry_isEitherConstant (ce)
3437 && !uentry_isIter (ce)
3438 && !uentry_isEndIter (ce)
3439 && !uentry_isExpandedMacro (ce)
3440 && uentry_isUsed (ce))
3442 /* check static uses */
3443 filelocList fuses = uentry_getUses (ce);
3444 fileloc mod = uentry_whereDefined (ce);
3445 bool ok = filelocList_isEmpty (fuses);
3446 fileloc fwhere = uentry_whereDeclared (ce);
3448 if (fileloc_isSpecialFile (fwhere)
3449 && !context_getFlag (FLG_UNUSEDSPECIAL))
3451 ok = TRUE; /* no errors for special files */
3453 else
3455 filelocList_elements (fuses, uloc)
3457 if (fileloc_isUndefined (uloc) || !fileloc_sameModule (uloc, mod))
3459 ok = TRUE;
3460 /*@innerbreak@*/ break;
3462 } end_filelocList_elements;
3465 if (!ok)
3467 if (optgenerror
3468 (FLG_EXPORTLOCAL,
3469 message ("%s exported but not used outside %s: %q",
3470 ekind_capName (uentry_getKind (ce)),
3471 fileloc_getBase (mod),
3472 uentry_getName (ce)),
3473 fwhere))
3475 uentry_showDefSpecInfo (ce, fwhere);
3482 void
3483 usymtab_allUsed (void)
3484 /*@globals utab@*/
3486 int i;
3487 bool isFileStatic = usymtab_inFileScope ();
3488 cstring last_file = cstring_undefined;
3490 for (i = 0; i < utab->nentries; i++)
3492 bool hasError = FALSE;
3493 uentry ce = utab->entries[i];
3494 fileloc fwhere = uentry_whereDeclared (ce);
3496 if (fileloc_isUndefined (fwhere))
3498 fwhere = uentry_whereDefined (ce);
3501 if (fileloc_isInvalid (fwhere)
3502 || fileloc_isLib (fwhere)
3503 || fileloc_isBuiltin (fwhere)
3504 || ((fileloc_isSpecialFile (fwhere)
3505 || fileloc_isSpecialFile (uentry_whereDefined (ce)))
3506 && !context_getFlag (FLG_UNUSEDSPECIAL)))
3510 else if (!uentry_wasUsed (ce) && !uentry_isAnyTag (ce))
3512 cstring fname = fileloc_filename (fwhere);
3514 if (cstring_isUndefined (last_file))
3516 last_file = fname;
3518 else if (cstring_equal (fname, last_file))
3521 else
3523 cleanupMessages ();
3524 last_file = fname;
3527 if (uentry_isParam (ce))
3529 if (context_inMacro ())
3531 sRef cref = uentry_getSref (ce);
3533 if (uentry_isYield (ce))
3535 ; /* no checks (for now) */
3537 else if (sRef_isSafe (cref))
3539 ; /* no error */
3541 else
3543 if (uentry_hasRealName (ce))
3545 hasError =
3546 optgenerror (FLG_MACROPARAMS,
3547 message ("Macro parameter %q not used",
3548 uentry_getName (ce)),
3549 fwhere);
3553 else
3555 if (cstring_equalFree (uentry_getName (ce),
3556 cstring_makeLiteral ("...")))
3560 else
3562 hasError = optgenerror (FLG_PARAMUNUSED,
3563 message ("Parameter %q not used",
3564 uentry_getName (ce)),
3565 fwhere);
3568 } /* isParam */
3569 else if (uentry_isFunction (ce) || uentry_isIter (ce))
3571 if (fileloc_isUser (fwhere))
3573 hasError = optgenerror
3574 (FLG_FUNCUNUSED,
3575 message ("%q %q declared but not used",
3576 cstring_makeLiteral
3577 (uentry_isIter (ce) ? "Iterator"
3578 : (isFileStatic ? "File static function" : "Function")),
3579 uentry_getName (ce)),
3580 fwhere);
3583 else if (uentry_isEndIter (ce))
3585 ; /* no error (already reported for iter */
3587 else if (uentry_isEnumConstant (ce))
3589 if (fileloc_isUser (fwhere))
3591 hasError = optgenerror
3592 (FLG_ENUMMEMUNUSED,
3593 message ("Enum member %q not used",
3594 uentry_getName (ce)),
3595 fwhere);
3598 else if (uentry_isConstant (ce))
3600 if (fileloc_isUser (fwhere))
3602 hasError = optgenerror
3603 (FLG_CONSTUNUSED,
3604 message ("Constant %q declared but not used",
3605 uentry_getName (ce)),
3606 fwhere);
3609 else if (uentry_isDatatype (ce))
3611 if (fileloc_isUser (fwhere))
3613 hasError = optgenerror
3614 (FLG_TYPEUNUSED,
3615 message ("Type %q declared but not used",
3616 uentry_getName (ce)),
3617 fwhere);
3620 else if (!uentry_isRefParam (ce) && !uentry_isExpandedMacro (ce))
3621 { /* errors for ref params will be reported in the next scope */
3622 llassertprint (uentry_isVar (ce),
3623 ("ce: %s", uentry_unparseFull (ce)));
3625 if (ctype_isFunction (uentry_getType (ce)))
3627 if (fileloc_isUser (fwhere))
3629 hasError = optgenerror
3630 (FLG_FUNCUNUSED,
3631 message ("%q %q declared but not used",
3632 cstring_makeLiteral
3633 (isFileStatic ? "File static function"
3634 : "Function"),
3635 uentry_getName (ce)),
3636 fwhere);
3639 else
3641 if (fileloc_isUser (fwhere))
3645 hasError = optgenerror
3646 (FLG_VARUNUSED,
3647 message ("%q %q declared but not used",
3648 cstring_makeLiteral
3649 (isFileStatic ? "File static variable"
3650 : "Variable"),
3651 uentry_getName (ce)),
3652 fwhere);
3656 else
3658 ; /* no errors */
3660 } /* unused */
3661 else if ((uentry_isDatatype (ce) || uentry_isAnyTag (ce)))
3662 { /* check all fields */
3663 ctype ct = uentry_getRealType (ce);
3666 while (ctype_isAP (ct))
3668 ct = ctype_getBaseType (ct);
3671 if (ctype_isSU (ct))
3673 uentryList fields = ctype_getFields (ct);
3675 uentryList_elements (fields, field)
3677 if (!uentry_isUsed (field))
3679 if (uentry_hasName (ce))
3681 hasError |= optgenerror
3682 (FLG_FIELDUNUSED,
3683 message ("Field %q of %s %q declared but not used",
3684 uentry_getName (field),
3685 cstring_makeLiteralTemp
3686 (ctype_isStruct (ct) ? "structure" : "union"),
3687 uentry_getName (ce)),
3688 uentry_whereEarliest (field));
3690 else
3693 ** evans 2001-06-08
3694 ** Can't report these errors for unnamed structs.
3695 ** No way to tell when there are multiple consistent
3696 ** unnamed structure types. (Could go through table
3697 ** and mark them all unused...)
3699 hasError |= optgenerror
3700 (FLG_FIELDUNUSED,
3701 message ("Field %q of unnamed %s declared but not used",
3702 uentry_getName (field),
3703 cstring_makeLiteralTemp
3704 (ctype_isStruct (ct) ? "structure" : "union")),
3705 uentry_whereEarliest (field));
3710 uentry_setUsed (field, fileloc_undefined);
3712 } end_uentryList_elements;
3715 else
3717 ; /* no errors */
3720 if (hasError)
3722 if (uentry_isParam (ce) && context_inMacro ())
3724 if (fileloc_isDefined (uentry_whereSpecified (ce)))
3726 uentry_showWhereSpecified (ce);
3729 else
3731 uentry_showDefSpecInfo (ce, fwhere);
3734 uentry_setUsed (ce, fileloc_undefined);
3739 static void
3740 checkGlobalReturn (uentry glob, sRef orig)
3742 sRef sr = uentry_getSref (glob);
3744 DPRINTF (("Check global return: %s / orig: %s / sr: %s",
3745 uentry_unparseFull (glob),
3746 sRef_unparseFull (orig),
3747 sRef_unparseFull (sr)));
3749 DPRINTF (("Is killed: %s", bool_unparse (sRef_isKilledGlob (orig))));
3751 if (context_getFlag (FLG_GLOBSTATE))
3753 DPRINTF (("Is killed: %s", sRef_unparseFull (orig)));
3755 if (sRef_isKilledGlob (orig))
3757 if (sRef_isStateUndefined (sr)
3758 || sRef_isUnuseable (sr)
3759 || sRef_isStateUnknown (sr)
3760 || sRef_isDead (sr))
3764 else
3766 ctype ct = ctype_realType (uentry_getType (glob));
3768 DPRINTF (("Check global destroyed: %s", uentry_unparseFull (glob)));
3770 if (ctype_isVisiblySharable (ct))
3772 if (optgenerror
3773 (FLG_GLOBSTATE,
3774 message
3775 ("Killed global %q (type %s) not released before return",
3776 uentry_getName (glob),
3777 ctype_unparse (ct)),
3778 g_currentloc))
3780 sRef_showStateInfo (sr);
3783 else
3785 sRef_protectDerivs ();
3786 (void) transferChecks_globalDestroyed (sr, g_currentloc);
3787 sRef_clearProtectDerivs ();
3791 else
3793 if (sRef_isStateUndefined (sr))
3795 if (optgenerror (FLG_GLOBSTATE,
3796 message
3797 ("Function returns with global %q undefined",
3798 uentry_getName (glob)),
3799 g_currentloc))
3801 sRef_showStateInfo (sr);
3804 else
3806 if (sRef_isDead (sr) || sRef_isKept (sr))
3808 if (optgenerror
3809 (FLG_GLOBSTATE,
3810 message ("Function returns with global %q "
3811 "referencing %s storage",
3812 uentry_getName (glob),
3813 cstring_makeLiteralTemp (sRef_isDead (sr) ? "released" : "kept")),
3814 g_currentloc))
3816 if (sRef_isKept (sr))
3818 sRef_showAliasInfo (sr);
3820 else
3822 sRef_showStateInfo (sr);
3825 sRef_setDefState (sr, SS_UNKNOWN, fileloc_undefined);
3829 DPRINTF (("Here: %s / %s",
3830 uentry_unparseFull (glob),
3831 sRef_unparseFull (sr)));
3833 if (ctype_isRealPointer (uentry_getType (glob))
3834 && sRef_possiblyNull (sr)
3835 && !uentry_possiblyNull (glob))
3837 if (optgenerror
3838 (FLG_GLOBSTATE,
3839 message ("Function returns with non-null global %q "
3840 "referencing null storage",
3841 uentry_getName (glob)),
3842 g_currentloc))
3844 sRef_showNullInfo (sr);
3847 else
3849 DPRINTF (("Check transfer: %s", uentry_unparseFull (glob)));
3850 transferChecks_globalReturn (glob);
3858 ** remember: check alias globals
3861 void usymtab_checkFinalScope (bool isReturn)
3862 /*@globals utab@*/
3864 bool mustDefine = context_getFlag (FLG_MUSTDEFINE);
3865 sRefSet checked = sRefSet_new ();
3866 usymtab stab = utab;
3867 int i;
3870 ** need to check all scopes out to function parameters.
3875 for (i = 0; i < stab->nentries; i++)
3877 uentry ce = stab->entries[i];
3878 sRef sr = uentry_getSref (ce);
3879 sRef rb = sRef_getRootBase (sr);
3880 valueTable tvalues;
3883 ** Shouldn't check if shadow checked in deeper scope:
3886 if (stab != utab)
3888 uentry oue = usymtab_lookupQuietNoAlt (utab, uentry_observeRealName (ce));
3890 if (!uentry_sameObject (ce, oue))
3892 /* what if it is one an alternate branch? */
3893 /*@innercontinue@*/ continue;
3897 DPRINTF (("Here check final scope: %s", uentry_unparseFull (ce)));
3899 if (ctype_isFunction (uentry_getType (ce)))
3901 /*@innercontinue@*/ continue;
3904 if (uentry_isAnyParam (ce)
3905 || uentry_isRefParam (ce)
3906 || sRef_isFileOrGlobalScope (rb))
3908 /* Don't do the loseref check...but should check state! */
3909 DPRINTF (("Skipping check 1"));
3911 else if (sRef_isDefinitelyNull (sr)
3912 || usymtab_isDefinitelyNull (sr))
3915 ** No state reference errors for definitely null references.
3918 DPRINTF (("Skipping check 2"));
3920 else
3922 DPRINTF (("Lose ref: %s / %s", uentry_unparse (ce),
3923 sRef_unparseFull (sr)));
3925 tvalues = sRef_getValueTable (sr);
3927 valueTable_elements (tvalues, fkey, fval) {
3928 metaStateInfo minfo;
3929 cstring msg = cstring_undefined;
3931 minfo = context_lookupMetaStateInfo (fkey);
3932 llassert (metaStateInfo_isDefined (minfo));
3934 if (stateValue_isError (fval)
3935 || sRef_isStateUndefined (sr)) /* No errors for undefined state */
3937 DPRINTF (("Skipping check 3"));
3939 else
3941 DPRINTF (("Check: %s / %s / %s", fkey,
3942 metaStateInfo_unparse (minfo),
3943 stateValue_unparse (fval)));
3945 minfo = context_lookupMetaStateInfo (fkey);
3948 stateCombinationTable sctable;
3950 sctable = metaStateInfo_getTransferTable (minfo);
3951 (void) stateCombinationTable_lookup (sctable,
3952 stateValue_getValue (fval), sctable->size, &msg);
3955 if (cstring_isDefined (msg))
3957 if (optgenerror
3958 (FLG_STATETRANSFER,
3959 message
3960 ("%s loses reference %q in invalid state %q (%s)",
3961 cstring_makeLiteralTemp (isReturn ? "Return" : "Scope exit"),
3962 uentry_getName (ce),
3963 stateValue_unparseValue (fval, minfo),
3964 msg),
3965 g_currentloc))
3967 stateValue_show (fval, minfo);
3969 else
3971 DPRINTF (("Suppressed transfer error: %s", msg));
3975 } end_valueTable_elements;
3978 DPRINTF (("Check mustfree entry: %s", uentry_unparseFull (ce)));
3980 if (!sRefSet_member (checked, sr) && !sRef_isFileOrGlobalScope (rb))
3982 if (ctype_isRealSU (uentry_getType (ce))
3983 && !uentry_isAnyParam (ce)
3984 && !uentry_isRefParam (ce)
3985 && !uentry_isStatic (ce)
3986 && !sRef_isDependent (sr)
3987 && !sRef_isOwned (sr))
3989 sRefSet als = usymtab_allAliases (sr);
3991 if (sRefSet_isEmpty (als))
3993 transferChecks_localDestroyed (sr, g_currentloc);
3995 else
3997 /* aliased, no problem */ ;
4000 sRefSet_free (als);
4002 else if
4003 (!uentry_isStatic (ce)
4004 && ((sRef_isNewRef (sr))
4005 || (((sRef_isOnly (sr) || sRef_isFresh (sr)
4006 || sRef_isKeep (sr) || sRef_isOwned (sr))
4007 && !sRef_isDead (sr))
4008 && (!sRef_definitelyNull (sr))
4009 && (!usymtab_isDefinitelyNull (sr)))))
4011 bool hasError = TRUE;
4013 DPRINTF (("Checking: %s", sRef_unparseFull (sr)));
4016 ** If its a scope exit, check if there is an alias.
4017 ** If so, make it only. If not, there is an error.
4020 if (!isReturn)
4022 if (transferChecks_canLoseReference (sr, g_currentloc))
4024 DPRINTF (("Can lose!"));
4025 hasError = FALSE;
4029 if (hasError)
4031 if (sRef_hasLastReference (sr))
4033 sRef ar = sRef_getAliasInfoRef (sr);
4035 if (optgenerror
4036 (sRef_isFresh (ar) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4037 message
4038 ("Last reference %q to %s storage %qnot %q before %q",
4039 sRef_unparse (sr),
4040 alkind_unparse (sRef_getAliasKind (sr)),
4041 sRef_unparseOpt (ar),
4042 cstring_makeLiteral (sRef_isKeep (sr)
4043 ? "transferred" : "released"),
4044 cstring_makeLiteral (isReturn
4045 ? "return" : "scope exit")),
4046 g_currentloc))
4048 sRef_showRefLost (sr);
4051 else if (sRef_isNewRef (sr))
4053 if (optgenerror
4054 (sRef_isFresh (sr) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4055 message
4056 ("%q %q not released before %q",
4057 cstring_makeLiteral
4058 (alkind_isKillRef (sRef_getOrigAliasKind (sr))
4059 ? "Kill reference parameter" : "New reference"),
4060 uentry_getName (ce),
4061 cstring_makeLiteral (isReturn
4062 ? "return" : "scope exit")),
4063 g_currentloc))
4065 sRef_showAliasInfo (sr);
4068 else
4070 if (ctype_isRealSU (sRef_getType (sr)))
4072 transferChecks_structDestroyed (sr, g_currentloc);
4074 else
4076 if (optgenerror
4077 (sRef_isFresh (sr) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
4078 message
4079 ("%s storage %q not %q before %q",
4080 alkind_capName (sRef_getAliasKind (sr)),
4081 uentry_getName (ce),
4082 cstring_makeLiteral (sRef_isKeep (sr)
4083 ? "transferred" : "released"),
4084 cstring_makeLiteral (isReturn
4085 ? "return" : "scope exit")),
4086 g_currentloc))
4088 sRef_showAliasInfo (sr);
4089 DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
4095 else
4101 if (mustDefine && uentry_isOut (ce))
4103 /* No error if its dead (either only or error already reported */
4104 if (!sRef_isReallyDefined (sr) && !sRef_isDead (sr))
4106 voptgenerror
4107 (FLG_MUSTDEFINE,
4108 message ("Out storage %q not defined before %q",
4109 uentry_getName (ce),
4110 cstring_makeLiteral
4111 (isReturn ? "return" : "scope exit")),
4112 g_currentloc);
4114 DPRINTF (("sr: %s", sRef_unparseFull (sr)));
4119 ** also check state is okay
4122 if (usymtab_lexicalLevel () > functionScope
4123 && uentry_isVariable (ce)
4124 && (sRef_isLocalVar (sr)
4125 && (sRef_isDependent (sr) || sRef_isLocalState (sr))))
4127 sRefSet ab = usymtab_aliasedBy (sr);
4129 /* should do something more efficient here */
4131 if (sRefSet_isEmpty (ab))
4133 /* and no local ref */
4134 DPRINTF (("Check lose ref: %s", uentry_unparseFull (ce)));
4135 transferChecks_loseReference (ce);
4137 else
4142 sRefSet_free (ab);
4144 else
4149 checked = sRefSet_insert (checked, sr);
4152 llassert (usymtab_isDefined (stab->env));
4154 if (usymtab_isBranch (stab))
4156 stab = usymtab_dropEnv (stab);
4158 else
4160 stab = stab->env;
4163 llassert (stab != usymtab_undefined);
4164 } while (isReturn && (stab->lexlevel >= paramsScope));
4166 sRefSet_free (checked);
4169 ** for returns:
4170 ** all globals are appropriately defined
4171 ** all parameters are appropriately defined
4172 ** special clauses are followed
4175 if (isReturn || (utab->lexlevel == paramsScope))
4177 uentry fcn = context_getHeader ();
4178 uentryList params = context_getParams ();
4179 globSet uglobs = context_getUsedGlobs ();
4180 globSet sglobs = context_getGlobs ();
4182 if (isReturn && context_maybeSet (FLG_GLOBALIAS))
4184 aliasTable_checkGlobs (utab->aliases);
4188 ** state clauses (ensures, defines, sets, allocates, releases)
4191 if (uentry_hasStateClauseList (fcn))
4193 stateClauseList clauses = uentry_getStateClauseList (fcn);
4195 stateClauseList_elements (clauses, cl)
4197 if (stateClause_isAfter (cl) && !stateClause_isGlobal (cl))
4199 if (stateClause_setsMetaState (cl))
4201 sRefSet rfs = stateClause_getRefs (cl);
4202 qual q = stateClause_getMetaQual (cl);
4203 annotationInfo ainfo = qual_getAnnotationInfo (q);
4204 metaStateInfo minfo = annotationInfo_getState (ainfo);
4205 cstring key = metaStateInfo_getName (minfo);
4206 int mvalue = annotationInfo_getValue (ainfo);
4208 DPRINTF (("Post meta state clause: %s", stateClause_unparse (cl)));
4210 sRefSet_elements (rfs, el)
4212 sRef base = sRef_getRootBase (el);
4214 if (sRef_isResult (base))
4217 ** This is checked for return transfers.
4221 else if (sRef_isParam (base) || sRef_isGlobalMarker (base))
4223 sRef sr = sRef_updateSref (base);
4224 sr = sRef_fixBase (el, sr);
4226 if (!sRef_checkMetaStateValue (sr, key, mvalue))
4228 if (optgenerror
4229 (FLG_STATETRANSFER,
4230 message
4231 ("Ensures clause not satisfied%q (state is %q): %q",
4232 sRef_isGlobalMarker (sr)
4233 ? message ("")
4234 : message (" by %q", sRef_unparse (sr)),
4235 stateValue_unparseValue (sRef_getMetaStateValue (sr, key),
4236 minfo),
4237 stateClause_unparse (cl)),
4238 g_currentloc))
4240 sRef_showMetaStateInfo (sr, key);
4244 else
4246 if (sRef_isMeaningful (el))
4248 BADBRANCH;
4251 } end_sRefSet_elements ;
4253 else
4255 /* evs - 2000 07 10 - added this */
4256 sRefTest tst = stateClause_getPostTestFunction (cl);
4257 sRefSet rfs = stateClause_getRefs (cl);
4259 sRefSet_elements (rfs, el)
4261 sRef base = sRef_getRootBase (el);
4263 if (sRef_isResult (base))
4266 ** This is checked for return transfers.
4271 else if (sRef_isParam (base))
4273 sRef sr = sRef_updateSref (base);
4274 sr = sRef_fixBase (el, sr);
4276 if (tst != NULL && !tst (sr))
4278 if (optgenerror
4279 (stateClause_postErrorCode (cl),
4280 message ("%s storage %qcorresponds to "
4281 "storage listed in %q clause",
4282 stateClause_postErrorString (cl, sr),
4283 sRef_unparseOpt (sr),
4284 stateClause_unparseKind (cl)),
4285 g_currentloc))
4287 sRefShower ss = stateClause_getPostTestShower (cl);
4289 if (ss != NULL)
4291 ss (sr);
4294 DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
4298 else
4300 if (sRef_isMeaningful (el))
4302 BADBRANCH;
4305 } end_sRefSet_elements ;
4308 } end_stateClauseList_elements ;
4312 ** check parameters on return
4315 uentryList_elements (params, arg)
4317 if (!uentry_isElipsisMarker (arg))
4319 ctype rt = ctype_realType (uentry_getType (arg));
4321 if (ctype_isMutable (rt) || ctype_isSU (rt))
4323 uentry param = usymtab_lookupQuiet (utab, uentry_rawName (arg));
4324 DPRINTF (("Check param return: %s", uentry_unparseFull (param)));
4325 transferChecks_paramReturn (param);
4328 } end_uentryList_elements;
4330 DPRINTF (("Check global return: %s",
4331 globSet_unparse (sglobs)));
4333 globSet_allElements (sglobs, el)
4335 sRef orig = el; /*! sRef_updateSref (el); */ /*!!!*/
4336 uentry current = sRef_getUentry (el);
4338 DPRINTF (("Check global return: %s / %s", sRef_unparseFull (el),
4339 uentry_unparseFull (current)));
4341 if (uentry_isVariable (current) && !uentry_isRealFunction (current))
4343 checkGlobalReturn (current, orig);
4345 } end_globSet_allElements;
4347 globSet_allElements (uglobs, el)
4349 if (!globSet_member (sglobs, el))
4351 uentry current = sRef_getUentry (el);
4353 if (uentry_isVariable (current)
4354 && !uentry_isRealFunction (current))
4356 checkGlobalReturn (current, sRef_undefined);
4359 } end_globSet_allElements;
4363 void
4364 usymtab_quietExitScope (fileloc loc)
4365 /*@globals utab, globtab, filetab; @*/
4366 /*@modifies utab@*/
4368 usymtab t = utab->env;
4370 DPRINTF (("Quiet exit scope [%p]", utab));
4372 if (utab->reftable != NULL)
4374 int i;
4376 for (i = 0; i < utab->nentries; i++)
4378 uentry current = utab->entries[i];
4379 uentry old = usymtab_lookupAux (t, uentry_rawName (current));
4381 uentry_mergeState (old, current, loc, FALSE, FALSE, FALSE, NOCLAUSE);
4385 llassert (t != NULL);
4387 if (t->lexlevel > paramsScope)
4389 t->guards = guardSet_levelUnion (t->guards, utab->guards, t->lexlevel);
4390 t->aliases = aliasTable_levelUnionSeq (t->aliases, utab->aliases,
4391 t->lexlevel);
4392 utab->aliases = aliasTable_undefined;
4395 t->mustBreak = utab->mustBreak;
4396 t->exitCode = utab->exitCode;
4398 DPRINTF (("Free level [%p]", utab));
4399 usymtab_freeLevel (utab);
4401 utab = t;
4403 # ifdef DEBUGSPLINT
4404 usymtab_checkAllValid ();
4405 # endif
4409 ** Exit a scope with no checking, lose alias states.
4410 ** (When should this be used?)
4413 void usymtab_quietPlainExitScope (void)
4414 /*@globals utab, globtab, filetab@*/
4415 /*@modifies utab@*/
4417 usymtab t = utab->env;
4419 llassert (t != NULL);
4420 llassert (NOALIAS (utab->aliases, t->aliases));
4421 usymtab_freeLevel (utab);
4422 utab = t;
4425 void usymtab_exitScope (exprNode expr)
4426 /*@globals utab, filetab, globtab@*/
4427 /*@modifies utab, globtab@*/
4429 usymtab ctab = usymtab_undefined;
4430 usymtab lctab = usymtab_undefined;
4431 bool mustReturn = exprNode_mustEscape (expr);
4433 DPRINTF (("Exit scope [%p]", utab));
4435 if (utab->kind == US_CBRANCH)
4438 ** save the case branches, remove the first non-cbranch
4441 ctab = utab;
4443 while (utab->kind == US_CBRANCH)
4445 lctab = utab;
4446 utab = utab->env;
4447 llassert (utab != GLOBAL_ENV);
4451 if (usymtab_isBranch (utab))
4453 if (context_inMacro ())
4455 /* evs 2000-07-25 */
4456 /* Unparseable macro may end inside nested scope. Deal with it. */
4458 llerror (FLG_SYNTAX,
4459 message ("Problem parsing macro body of %s (unbalanced scopes). "
4460 "Attempting to recover, recommend /*@notfunction@*/ before "
4461 "macro definition.",
4462 context_inFunctionName ()));
4464 while (usymtab_isBranch (utab))
4466 utab = utab->env;
4467 llassert (utab != GLOBAL_ENV);
4469 } else
4471 llcontbug (message ("%s: in branch: %q",
4472 cstring_fromChars (__func__), usymtab_unparseStack ()));
4473 /*@-branchstate@*/
4474 } /*@=branchstate@*/
4478 ** check all variables in scope were used
4482 ** bogus errors if this is the normal inside a switch,
4483 ** since cases have not been merged yet. Should probably
4484 ** still check this, but I'm too lazy at the moment...
4487 llassertfatal (utab->env != GLOBAL_ENV);
4489 if (utab->env->kind != US_SWITCH)
4491 usymtab_allUsed ();
4495 ** check aliasing: all only params are released (dead)
4496 ** definition: all out params are defined, all modified params
4497 ** are completely defined
4499 ** NOTE: note for exiting paramsScope, since checkReturn should be
4500 ** called first.
4503 if (!mustReturn && (usymtab_lexicalLevel () > functionScope))
4506 ** should only call this is end of scope is reachable...
4509 usymtab_checkFinalScope (FALSE);
4512 if (usymtab_lexicalLevel () == paramsScope && context_inFunctionLike ())
4515 ** leaving a function, need to fix up globals
4518 uentryList params = context_getParams ();
4519 globSet globs = context_getUsedGlobs ();
4521 uentryList_elements (params, ue)
4523 uentry_fixupSref (ue);
4524 } end_uentryList_elements;
4526 clearFunctionTypes ();
4528 DPRINTF (("Fixing up globals: %s", globSet_unparse (globs)));
4530 globSet_allElements (globs, el)
4532 DPRINTF (("Fix: %s", sRef_unparseDebug (el)));
4534 if (sRef_isCvar (el))
4536 uentry current;
4537 usymId index = sRef_getScopeIndex (el);
4539 if (sRef_isFileStatic (el))
4541 llassert (usymtab_isDefined (filetab));
4542 current = usymtab_fetchIndex (filetab, index);
4544 else
4546 current = usymtab_fetchIndex (globtab, index);
4549 if (uentry_isVariable (current))
4551 DPRINTF (("Fixup: %s", uentry_unparse (current)));
4552 uentry_fixupSref (current);
4554 else
4556 DPRINTF (("Clear: %s", uentry_getSref (current)));
4557 sRef_clearDerived (uentry_getSref (current));
4561 sRef_clearDerived (el); /* evans 2002-03-14 - this is the likely source of many crashes! */
4562 } end_globSet_allElements;
4565 usymtab_quietExitScope (exprNode_loc (expr));
4567 if (lctab != usymtab_undefined)
4569 /*@i@*/ lctab->env = utab;
4570 /*@i@*/ utab = ctab;
4571 /*@-branchstate@*/ } /*@=branchstate@*/
4572 /*@-globstate@*/
4575 # ifdef DEBUGSPLINT
4576 usymtab_checkAllValid ();
4577 # endif
4579 /*@=globstate@*/
4582 ** yikes! don't let the '170 kids see this one...
4585 usymId
4586 usymtab_directParamNo (uentry ue)
4588 if (uentry_isVar (ue))
4590 sRef sr = uentry_getSref (ue);
4592 if (sRef_lexLevel (sr) == functionScope)
4594 usymId index = sRef_getScopeIndex (sr);
4596 if (index < usymId_fromInt (uentryList_size (context_getParams ())))
4598 return index;
4602 return usymId_invalid;
4605 /*@dependent@*/ /*@exposed@*/ uentry
4606 usymtab_getParam (int paramno)
4607 /*@globals utab@*/
4610 ** requires in a function context (checked)
4612 ** depends on no nested functions --- the function
4613 ** parameters are ALWAYS one scope inside the global scope
4614 ** and entered in order!
4616 usymtab s = utab;
4618 if (!context_inFunctionLike ())
4619 llfatalbug (message ("%s: not in function context: %q",
4620 cstring_fromChars (__func__), context_unparse ()));
4622 while (s->lexlevel > paramsScope)
4624 s = s->env;
4627 llassert (usymtab_isDefined (s));
4629 if (paramno >= s->nentries)
4632 ** Parse errors lead to this.
4635 uentry err = uentry_makeVariableLoc (cstring_makeLiteralTemp ("<error>"),
4636 ctype_unknown);
4638 uentry_markOwned (err);
4639 return (err);
4642 return (s->entries[paramno]);
4645 static /*@dependent@*/ /*@exposed@*/ uentry
4646 usymtab_getRefTab (/*@notnull@*/ usymtab u, int level, usymId index)
4648 uentry ue;
4650 ue = usymtab_getRefNoisy (u, level, index);
4652 if (uentry_isUndefined (ue))
4654 llbug (message ("%s: out of range: %d. level = %d",
4655 cstring_fromChars (__func__), index, level));
4658 return ue;
4661 static /*@dependent@*/ /*@exposed@*/ usymtab
4662 usymtab_dropEnv (/*@notnull@*/ usymtab s)
4664 if (s->kind == US_CBRANCH)
4666 /* drop all cases (except in nested scopes) */
4669 s = s->env;
4670 llassert (s != GLOBAL_ENV);
4671 } while (s->kind == US_CBRANCH);
4673 else if (s->kind == US_FBRANCH)
4675 /* skip the true branch */
4676 s = s->env;
4677 llassert (s != GLOBAL_ENV);
4678 llassert (s->kind == US_TBRANCH);
4680 s = s->env;
4682 else
4684 llassert (s != GLOBAL_ENV);
4685 s = s->env;
4688 return s;
4691 /*@dependent@*/ /*@exposed@*/ uentry
4692 usymtab_getRefQuiet (int level, usymId index)
4693 /*@globals utab@*/
4695 usymtab s = utab;
4698 llassert (s != NULL);
4699 llassert (index >= 0);
4701 if (level > s->lexlevel)
4703 return uentry_undefined;
4706 llassertprint (level <= s->lexlevel, ("level: %d / lexlevel: %d",
4707 level, s->lexlevel));
4709 while (s->lexlevel > level)
4711 if (usymtab_isBranch (s))
4713 int eindex = refTable_lookup (s, level, index);
4715 if (eindex != NOT_FOUND)
4717 return (s->entries[eindex]);
4721 s = usymtab_dropEnv (s);
4724 while (usymtab_isBranch (s) && s->lexlevel == level)
4726 int eindex = refTable_lookup (s, level, index);
4728 if (eindex != NOT_FOUND)
4730 return (s->entries[eindex]);
4733 s = usymtab_dropEnv (s);
4736 if (index >= usymId_fromInt (s->nentries))
4738 return uentry_undefined;
4741 llassert (!uentry_isUndefined (s->entries[index]));
4743 return s->entries[index];
4746 static /*@dependent@*/ /*@exposed@*/ uentry
4747 usymtab_getRefNoisy (/*@notnull@*/ usymtab s, int level, usymId index)
4749 usymtab otab = s;
4750 uentry ue = uentry_undefined;
4752 llassert (index >= 0);
4754 while (s->lexlevel > level)
4756 if (usymtab_isBranch (s))
4758 int eindex = refTable_lookup (s, level, index);
4760 if (eindex != NOT_FOUND)
4762 ue = s->entries[eindex];
4764 if (s != otab)
4766 while (!usymtab_isBranch (otab))
4768 otab = usymtab_dropEnv (otab);
4769 llassert (otab != GLOBAL_ENV);
4772 if (refTable_lookup (otab, level, index) == NOT_FOUND)
4774 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4776 else
4782 return ue;
4786 s = usymtab_dropEnv (s);
4789 llassert (usymtab_isDefined (s));
4791 while (usymtab_isBranch (s) && s->lexlevel == level)
4793 int eindex = refTable_lookup (s, level, index);
4795 if (eindex != NOT_FOUND)
4797 ue = s->entries[eindex];
4799 if (s != otab)
4801 while (!usymtab_isBranch (otab))
4803 otab = usymtab_dropEnv (otab);
4804 llassert (otab != GLOBAL_ENV);
4807 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4809 else
4814 return ue;
4817 s = usymtab_dropEnv (s);
4820 if (s->lexlevel == level && (index < usymId_fromInt (s->nentries)))
4822 ue = s->entries[index];
4824 if (uentry_isValid (ue))
4826 if (s != otab)
4828 while (!usymtab_isBranch (otab))
4830 otab = usymtab_dropEnv (otab);
4832 if (otab == GLOBAL_ENV)
4834 return ue;
4838 ue = usymtab_addRefEntry (otab, uentry_rawName (ue));
4840 else
4845 return ue;
4849 if (index >= usymId_fromInt (s->nentries))
4851 return uentry_undefined;
4854 llassert (!uentry_isUndefined (s->entries[index]));
4856 return s->entries[index];
4860 ** looking up entries
4862 ** If entry is inside a branch, then copy it, and put it into
4863 ** the branch table.
4866 static
4867 int refTable_lookup (/*@notnull@*/ usymtab ut, int level, usymId index)
4869 refTable rt = ut->reftable;
4870 int i;
4872 llassertfatal (rt != NULL);
4874 for (i = 0; i < ut->nentries; i++)
4876 llassertfatal (rt[i] != NULL);
4877 if (rt[i]->level == level && rt[i]->index == usymId_toInt (index))
4879 return i;
4883 return NOT_FOUND;
4886 static
4887 /*@only@*/ refentry refentry_create (int level, int index)
4889 refentry r = (refentry) dmalloc (sizeof (*r));
4891 r->level = level;
4892 r->index = index;
4894 return r;
4897 static /*@dependent@*/ /*@exposed@*/ uentry
4898 usymtab_addRefEntry (/*@notnull@*/ usymtab s, cstring k)
4900 usymtab ut = s;
4902 if (ut->reftable == NULL)
4904 DPRINTF (("Adding ref entry without reftable: %s", k));
4905 return uentry_undefined;
4908 llassert (ut->reftable != NULL);
4910 while (s != GLOBAL_ENV)
4912 usymId eindex = usymtab_getIndex (s, k);
4914 if (usymtab_indexFound (eindex))
4916 uentry current = s->entries[eindex];
4918 if (uentry_isVar (current) && !ctype_isFunction (uentry_getType (current)))
4920 uentry ue;
4922 DPRINTF (("Here: copying %s", uentry_unparse (current)));
4923 if (uentry_isNonLocal (current))
4925 ue = uentry_copy (current);
4927 else
4929 ue = uentry_copyNoSave (current);
4932 DPRINTF (("Here: copying %s", uentry_unparse (ue)));
4933 usymtab_addEntryQuiet (ut, ue);
4934 DPRINTF (("Okay..."));
4936 if (s->reftable != NULL)
4938 refentry ref = s->reftable[eindex];
4940 ut->reftable[ut->nentries - 1]
4941 = refentry_create (ref->level, ref->index);
4943 else
4945 ut->reftable[ut->nentries - 1]
4946 = refentry_create (s->lexlevel, usymId_toInt (eindex));
4949 return (ue);
4951 else
4953 return (current);
4957 s = usymtab_dropEnv (s);
4960 return uentry_undefined;
4963 static uentry usymtab_lookupAux (usymtab s, cstring k)
4965 DPRINTF (("Lookup: %s", k));
4967 while (s != GLOBAL_ENV)
4969 usymId eindex = usymtab_getIndex (s, k);
4971 if (usymtab_indexFound (eindex))
4973 uentry ret = s->entries[eindex];
4974 DPRINTF (("Found: %s", uentry_unparseFull (ret)));
4975 return (ret);
4978 if (s->kind == US_TBRANCH ||
4979 s->kind == US_FBRANCH ||
4980 s->kind == US_CBRANCH) /* all branches except US_SWITCH */
4982 uentry ret = usymtab_addRefEntry (s, k);
4983 DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret)));
4984 return ret;
4987 s = s->env;
4990 return uentry_undefined;
4993 static /*@dependent@*/ /*@exposed@*/ uentry
4994 usymtab_lookupQuietAux (usymtab s, cstring k, bool noalt)
4996 while (s != GLOBAL_ENV)
4998 usymId eindex = usymtab_getIndex (s, k);
5000 if (usymtab_indexFound (eindex))
5002 uentry ret = s->entries[eindex];
5003 return (ret);
5006 if (noalt && usymtab_isBranch (s))
5008 s = usymtab_dropEnv (s);
5010 else
5012 llassert (s != NULL);
5013 s = s->env;
5017 return uentry_undefined;
5020 static /*@exposed@*/ /*@dependent@*/ uentry
5021 usymtab_lookupQuiet (usymtab s, cstring k)
5023 return usymtab_lookupQuietAux (s, k, FALSE);
5026 static /*@exposed@*/ /*@dependent@*/ uentry
5027 usymtab_lookupQuietNoAlt (usymtab s, cstring k)
5029 return usymtab_lookupQuietAux (s, k, TRUE);
5032 /*@dependent@*/ /*@observer@*/ uentry
5033 usymtab_lookupSafe (cstring k)
5034 /*@globals utab@*/
5036 DPRINTF (("Lookup safe: %s", k));
5037 return (usymtab_lookupAux (utab, k));
5040 /*@dependent@*/ /*@observer@*/ uentry
5041 usymtab_lookupSafeScope (cstring k, int lexlevel)
5042 /*@globals utab@*/
5045 ** This is necessary to deal with shadowed variables that are referenced
5046 ** through aliases inside the shadowed scope. It would be better if
5047 ** lookup could take an sRef as a parameter.
5050 usymtab tab = utab;
5052 while (tab != GLOBAL_ENV && tab->lexlevel > lexlevel) {
5053 uentry ret = usymtab_lookupAux (tab, k);
5055 if (uentry_isValid (ret)) {
5056 sRef sr = uentry_getSref (ret);
5058 if (sRef_isCvar (sr) && sRef_lexLevel (sr) > lexlevel) {
5059 tab = usymtab_dropEnv (tab);
5060 } else {
5061 return ret;
5066 return uentry_undefined;
5069 uentry
5070 usymtab_lookupExpose (cstring k)
5071 /*@globals utab@*/
5073 uentry ce = usymtab_lookupAux (utab, k);
5075 if (uentry_isUndefined (ce))
5077 llfatalbug (message ("%s: not found: *%s*", cstring_fromChars (__func__), k));
5080 if (uentry_isPriv (ce))
5082 llfatalbug (message ("%s: private: *%s*", cstring_fromChars (__func__), k));
5085 return ce;
5088 uentry usymtab_lookupExposeGlob (cstring k)
5090 return (usymtab_lookupGlobSafe (k));
5093 uentry usymtab_lookupGlob (cstring k)
5094 /*@globals globtab@*/
5096 uentry ce = usymtab_lookupAux (globtab, k);
5098 if (uentry_isUndefined (ce))
5099 llfatalbug (message ("%s: not found: %s", cstring_fromChars (__func__), k));
5101 if (uentry_isPriv (ce))
5102 llfatalbug (message ("%s: private: %s", cstring_fromChars (__func__), k));
5104 DPRINTF (("Lookup global: %s", uentry_unparseFull (ce)));
5105 return ce;
5108 /*@observer@*/ uentry
5109 usymtab_lookupGlobSafe (cstring k)
5110 /*@globals globtab@*/
5112 uentry ce = usymtab_lookupAux (globtab, k);
5113 DPRINTF (("Lookup global: %s", uentry_unparseFull (ce)));
5114 return ce;
5117 uentry usymtab_lookupEither (cstring k)
5118 /*@globals utab@*/
5120 uentry ce = usymtab_lookupSafe (k);
5122 if (uentry_isUndefined (ce))
5123 llfatalerror (message ("%s: not found: %s", cstring_fromChars (__func__), k));
5125 DPRINTF (("Lookup either: %s", uentry_unparseFull (ce)));
5126 return ce;
5129 ctype
5130 usymtab_lookupType (cstring k)
5131 /*@globals globtab@*/
5133 typeId uid = usymtab_getTypeId (k);
5135 if (typeId_isInvalid (uid))
5137 llcontbug (message ("%s: not found: %s", cstring_fromChars (__func__), k));
5138 return ctype_unknown;
5141 return (uentry_getRealType (usymtab_getTypeEntry (uid)));
5144 ctype
5145 usymtab_lookupAbstractType (cstring k) /*@globals globtab@*/
5147 typeId uid = usymtab_getTypeId (k);
5149 if (typeId_isInvalid (uid))
5151 llcontbug (message ("%s: not found: %s", cstring_fromChars (__func__), k));
5152 return ctype_unknown;
5155 return (uentry_getAbstractType (usymtab_getTypeEntry (uid)));
5159 ** if there is an unnamed lcl-specified struct tag matching
5160 ** the uentryList, return its datatype. Otherwise, returns
5161 ** ctype_undefined.
5164 ctype
5165 usymtab_structFieldsType (uentryList f)
5166 /*@globals globtab@*/
5168 return (usymtab_suFieldsType (f, TRUE));
5171 ctype
5172 usymtab_unionFieldsType (uentryList f)
5173 /*@globals globtab@*/
5175 return (usymtab_suFieldsType (f, FALSE));
5178 static ctype
5179 usymtab_suFieldsType (uentryList f, bool isStruct)
5180 /*@globals globtab@*/
5182 int i;
5184 DPRINTF (("Fields: %s", uentryList_unparse (f)));
5186 if (fileloc_isSpec (g_currentloc))
5188 return (ctype_undefined);
5191 for (i = 0; i < globtab->nentries; i++)
5193 uentry current = globtab->entries[i];
5195 if ((isStruct
5196 ? uentry_isStructTag (current) : uentry_isUnionTag (current)))
5198 if (isFakeTag (uentry_rawName (current)))
5200 ctype ct = uentry_getType (current);
5202 DPRINTF (("Check: %s", ctype_unparse (ct)));
5204 if ((isStruct ? ctype_isStruct (ct) : ctype_isUnion (ct))
5206 (uentry_isSpecified (current)
5207 && uentryList_equivFields (f, ctype_getFields (ct))))
5209 return uentry_getAbstractType (current);
5211 else
5219 return ctype_undefined;
5222 ctype
5223 usymtab_enumEnumNameListType (enumNameList f)
5224 /*@globals globtab@*/
5226 int i;
5228 for (i = 0; i < globtab->nentries; i++)
5230 uentry current = globtab->entries[i];
5232 if (uentry_isEnumTag (current))
5234 if (isFakeTag (uentry_rawName (current)))
5236 ctype ct = uentry_getType (current);
5238 if (ctype_isEnum (ct) && (enumNameList_match (f, ctype_elist (ct))))
5240 return uentry_getType (current);
5246 return ctype_undefined;
5249 bool
5250 usymtab_exists (cstring k)
5251 /*@globals utab@*/
5253 uentry ce = usymtab_lookupSafe (k);
5254 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5257 bool
5258 usymtab_existsReal (cstring k)
5259 /*@globals utab@*/
5261 uentry ce = usymtab_lookupSafe (k);
5263 return (!(uentry_isUndefined (ce))
5264 && !(uentry_isPriv (ce))
5265 && !(uentry_isExpandedMacro (ce)));
5268 bool
5269 usymtab_existsGlob (cstring k)
5270 /*@globals globtab@*/
5272 uentry ce = usymtab_lookupAux (globtab, k);
5274 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5277 bool
5278 usymtab_existsEither (cstring k)
5279 /*@globals utab@*/
5281 uentry ce = usymtab_lookupAux (utab, k);
5283 return (uentry_isValid (ce));
5286 bool
5287 usymtab_existsGlobEither (cstring k)
5288 /*@globals globtab@*/
5290 uentry ce = usymtab_lookupAux (globtab, k);
5292 return (uentry_isValid (ce));
5295 bool
5296 usymtab_existsType (cstring k)
5297 /*@globals globtab@*/
5299 uentry ce = usymtab_lookupAux (globtab, k);
5301 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && uentry_isDatatype (ce));
5304 bool
5305 usymtab_existsTypeEither (cstring k)
5306 /*@globals globtab@*/
5308 uentry ce;
5309 ce = usymtab_lookupAux (globtab, k);
5310 return (uentry_isValid (ce) && uentry_isDatatype (ce));
5313 bool
5314 usymtab_existsStructTag (cstring k) /*@globals globtab@*/
5316 cstring sname = makeStruct (k);
5317 uentry ce = usymtab_lookupAux (globtab, sname);
5318 cstring_free (sname);
5319 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5322 bool
5323 usymtab_existsUnionTag (cstring k) /*@globals globtab@*/
5325 cstring uname = makeUnion (k);
5326 uentry ce = usymtab_lookupAux (globtab, uname);
5328 cstring_free (uname);
5330 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5333 bool
5334 usymtab_existsEnumTag (cstring k) /*@globals globtab@*/
5336 cstring ename = makeEnum (k);
5337 uentry ce = usymtab_lookupAux (globtab, ename);
5339 cstring_free (ename);
5340 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)));
5343 bool usymtab_existsVar (cstring k)
5344 /*@globals utab@*/
5346 uentry ce = usymtab_lookupSafe (k);
5348 return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && (uentry_isVar (ce)));
5352 ** destructors
5355 static void
5356 refTable_free (/*@only@*/ /*@null@*/ refTable x, int nentries)
5358 if (x != NULL)
5360 int i;
5362 for (i = 0; i < nentries; i++)
5364 sfree (x[i]);
5367 sfree (x);
5371 static void
5372 usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab u)
5373 /*@globals globtab, utab, filetab@*/
5375 int i;
5377 DPRINTF (("Free level [%p]", u));
5378 aliasTable_free (u->aliases);
5380 refTable_free (u->reftable, u->nentries);
5382 if (u == filetab || u == globtab)
5384 for (i = 0; i < u->nentries; i++)
5386 DPRINTF (("Free complete: %d", i));
5387 DPRINTF (("Uentry: %s", uentry_unparse (u->entries[i])));
5388 uentry_freeComplete (u->entries[i]);
5389 u->entries[i] = uentry_undefined;
5392 else
5394 for (i = 0; i < u->nentries; i++)
5396 uentry_free (u->entries[i]);
5397 u->entries[i] = uentry_undefined;
5401 guardSet_free (u->guards);
5402 sfree (u->entries);
5404 if (u != globtab
5405 && u != utab
5406 && u != filetab)
5408 llassert (!cstringTable_isDefined (u->htable));
5411 sfree (u); /* evans 2002-07-12: was inside if */
5414 static void
5415 usymtab_freeAux (/*@only@*/ usymtab u)
5416 /*@globals globtab, utab, filetab@*/
5417 /*@modifies u@*/
5419 while (u != GLOBAL_ENV)
5421 usymtab t = u->env;
5422 usymtab_freeLevel (u);
5423 u = t;
5424 /*@-branchstate@*/
5426 /*@=branchstate@*/
5429 static int usymtab_lexicalLevel (void) /*@globals utab@*/
5431 return (utab->lexlevel);
5434 bool usymtab_inGlobalScope (void) /*@globals utab, globtab@*/
5436 return (utab == globtab);
5439 bool usymtab_inFileScope (void) /*@globals utab@*/
5441 return (utab->lexlevel == fileScope);
5444 bool usymtab_inFunctionScope (void) /*@globals utab@*/
5446 return (utab->lexlevel == functionScope);
5449 void
5450 usymtab_replaceEntry (uentry s)
5451 /*@globals utab, globtab@*/
5452 /*@modifies utab, s@*/
5454 usymtab_replaceEntryAux (utab, s);
5457 bool
5458 usymtab_matchForwardStruct (typeId u1, typeId u2)
5459 /*@globals globtab@*/
5461 uentry ue1 = usymtab_getTypeEntry (u1);
5462 uentry ue2 = usymtab_getTypeEntry (u2);
5464 if (uentry_isAnyTag (ue2))
5466 ctype reptype = uentry_getType (ue1);
5468 if (ctype_isPointer (reptype))
5470 ctype repbase = ctype_getBaseType (reptype);
5472 if (ctype_isUA (repbase))
5474 typeId rtuid = ctype_typeId (repbase);
5476 if (u2 == rtuid) return TRUE;
5478 if (typeId_isValid (rtuid))
5480 reptype = uentry_getType (usymtab_getTypeEntry (rtuid));
5481 return (ctype_isUA (reptype) && (u2 == (ctype_typeId (reptype))));
5487 return FALSE;
5490 void usymtab_addGuards (guardSet guards)
5491 /*@modifies utab@*/
5493 utab->guards = guardSet_union (utab->guards, guards);
5496 static bool usymtab_isGuardedAux (sRef s)
5497 /*@globals utab@*/
5499 usymtab tab = utab;
5500 sRef base = sRef_getRootBase (s);
5501 int lowlevel = paramsScope;
5502 int baselevel = sRef_lexLevel (base);
5504 if (sRef_isCvar (base))
5506 lowlevel = baselevel;
5507 if (lowlevel < paramsScope) lowlevel = paramsScope;
5510 while (tab->lexlevel >= lowlevel)
5512 DPRINTF (("Is guarded? [%s] %s",
5513 guardSet_unparse (tab->guards),
5514 sRef_unparseFull (s)));
5516 if (guardSet_isGuarded (tab->guards, s))
5519 if (!sRef_definitelyNull (s))
5521 sRef_setNotNull (s, fileloc_undefined);
5524 return TRUE;
5527 tab = usymtab_dropEnv (tab);
5530 return FALSE;
5533 void usymtab_unguard (sRef s) /*@modifies utab@*/
5535 usymtab tab = utab;
5536 sRef base = sRef_getRootBase (s);
5537 int lowlevel = paramsScope;
5538 int baselevel = sRef_lexLevel (base);
5540 if (sRef_isCvar (base))
5542 lowlevel = baselevel;
5543 if (lowlevel < paramsScope) lowlevel = paramsScope;
5546 while (tab->lexlevel >= lowlevel)
5548 if (guardSet_isGuarded (tab->guards, s))
5550 guardSet_delete (tab->guards, s);
5553 tab = usymtab_dropEnv (tab);
5557 bool usymtab_isGuarded (sRef s)
5559 DPRINTF (("Is guarded? %s", sRef_unparseFull (s)));
5560 return (sRef_aliasCompleteSimplePred (usymtab_isGuardedAux, s));
5563 bool usymtab_isDefinitelyNull (sRef s)
5565 return (sRef_aliasCheckSimplePred (usymtab_isDefinitelyNullAux, s));
5568 bool usymtab_isDefinitelyNullDeep (sRef s)
5570 return (sRef_deepPred (usymtab_isDefinitelyNull, s));
5573 static bool usymtab_isDefinitelyNullAux (sRef s)
5574 /*@globals utab@*/
5576 usymtab tab = utab;
5577 sRef base = sRef_getRootBase (s);
5578 int lowlevel = paramsScope;
5580 if (sRef_isCvar (base))
5582 lowlevel = sRef_lexLevel (base);
5583 if (lowlevel < paramsScope) lowlevel = paramsScope;
5586 while (tab->lexlevel >= lowlevel)
5588 if (guardSet_mustBeNull (tab->guards, s))
5590 return TRUE;
5593 while (tab->kind == US_CBRANCH)
5595 tab = tab->env;
5598 llassert (usymtab_isDefined (tab));
5600 if (tab->kind == US_FBRANCH)
5602 tab = tab->env;
5603 llassert (tab->kind == US_TBRANCH);
5606 tab = tab->env;
5609 return FALSE;
5612 void
5613 usymtab_printGuards (void)
5614 /*@globals utab, globtab@*/
5616 usymtab ttab = utab;
5618 while (ttab != globtab)
5620 llmsg (message ("Guards [%d]: %q", ttab->lexlevel,
5621 guardSet_unparse (ttab->guards)));
5622 ttab = ttab->env;
5626 void
5627 usymtab_displayAllUses (void)
5628 /*@globals utab, globtab@*/
5630 usymtab copy;
5632 /* only in top scope */
5633 llassert (utab == globtab);
5635 /* need a copy, so order is not messed up by sort! */
5636 copy = usymtab_shallowCopy (globtab);
5638 qsort (copy->entries, (size_t)copy->nentries,
5639 sizeof (*copy->entries), (int (*)(const void *, const void *)) uentry_xcompareuses);
5641 usymtab_entries (copy, ue)
5643 if (uentry_isValid (ue) && !uentry_isGlobalMarker (ue))
5645 filelocList uses = uentry_getUses (ue);
5646 int size = filelocList_realSize (uses);
5648 if (fileloc_isDefined (uentry_whereDefined (ue))
5649 && !fileloc_isLib (uentry_whereDefined (ue))
5650 && (size > 0))
5652 llmsg (message ("%q (%q), %d use%&:\n %q",
5653 uentry_getName (ue),
5654 fileloc_unparse (uentry_whereDefined (ue)),
5655 size, filelocList_unparseUses (uses)));
5658 } end_usymtab_entries;
5660 usymtab_shallowFree (copy);
5663 static /*@dependent@*/ /*@exposed@*/ usymtab
5664 usymtab_getFileTab (void)
5665 /*@globals filetab@*/
5667 llassert (filetab != NULL);
5669 return filetab;
5672 /*@only@*/ cstring
5673 usymtab_unparseStack (void)
5674 /*@globals utab@*/
5676 return (usymtab_unparseStackTab (utab));
5679 static /*@only@*/ cstring
5680 usymtab_unparseStackTab (usymtab t)
5682 bool firstOne = TRUE;
5683 cstring ret = cstring_makeLiteral ("[");
5685 while (t != GLOBAL_ENV)
5687 if (firstOne)
5689 ret = message ("%q %q", ret, usymtab_typeName (t));
5690 firstOne = FALSE;
5692 else
5694 ret = message ("%q, %q", ret, usymtab_typeName (t));
5696 t = t->env;
5699 ret = message ("%q ]", ret);
5700 return ret;
5703 static /*@only@*/ cstring
5704 usymtab_typeName (/*@notnull@*/ usymtab t)
5706 switch (t->kind)
5708 case US_GLOBAL: return cstring_makeLiteral ("global");
5709 case US_NORMAL: return cstring_makeLiteral ("normal");
5710 case US_TBRANCH: return cstring_makeLiteral ("true");
5711 case US_FBRANCH: return cstring_makeLiteral ("false");
5712 case US_CBRANCH: return cstring_makeLiteral ("case");
5713 case US_SWITCH: return cstring_makeLiteral ("switch");
5716 BADEXIT;
5719 void usymtab_addMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5720 /*@modifies utab@*/
5722 if (!sRef_similar (s, al))
5724 usymtab_addForceMustAlias (s, al);
5729 ** Same as usymtab_addMustAlias, except does not check sRef_isSimilar.
5732 void usymtab_addForceMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5733 /*@modifies utab@*/
5735 /* evans 2002-03-3: was sRef_isMeaningful -- but we need to keep aliases for new storage also! */
5736 if (sRef_isMeaningful (s)
5737 && sRef_isMeaningful (al)
5738 && !(sRef_isConst (s) || sRef_isConst (al))
5739 && !(sRef_isAddress (al) && sRef_isDirectParam (sRef_getBase (al))))
5741 utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
5742 DPRINTF (("Must alias: %s", aliasTable_unparse (utab->aliases)));
5745 ** for local variable, aliasing is symmetric
5748 if (sRef_isLocalVar (s) && sRef_isLocalVar (al))
5750 utab->aliases = aliasTable_addMustAlias (utab->aliases, al, s);
5753 else
5755 DPRINTF (("Not aliasing! %s / %s", sRef_unparseFull (s), sRef_unparseFull (al)));
5756 DPRINTF (("meaningful: %d %d", sRef_isMeaningful (s), sRef_isMeaningful (al)));
5760 # ifdef DEADCODE
5761 void usymtab_addReallyForceMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al)
5762 /*@modifies utab@*/
5764 utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al);
5766 # endif /* DEADCODE */
5768 void usymtab_clearAlias (sRef s)
5769 /*@modifies utab, s@*/
5772 aliasTable_clearAliases (utab->aliases, s);
5775 sRefSet usymtab_allAliases (sRef s)
5776 /*@globals utab@*/
5778 if (sRef_isSomewhatMeaningful (s))
5780 sRefSet ret;
5782 ret = sRefSet_unionFree (aliasTable_aliasedBy (utab->aliases, s),
5783 aliasTable_canAlias (utab->aliases, s));
5784 return (ret);
5786 else
5788 DPRINTF (("NOT A MEANINGFUL SREF!"));
5789 return sRefSet_undefined;
5793 /*@only@*/ sRefSet usymtab_canAlias (sRef s)
5794 /*@globals utab@*/
5796 if (sRef_isSomewhatMeaningful (s))
5798 sRefSet res = aliasTable_canAlias (utab->aliases, s);
5799 return res;
5802 return sRefSet_undefined;
5805 /*@only@*/ sRefSet usymtab_aliasedBy (sRef s)
5806 /*@globals utab@*/
5808 return (aliasTable_aliasedBy (utab->aliases, s));
5811 /*@only@*/ cstring usymtab_unparseAliases (void)
5812 /*@globals utab@*/
5814 return (aliasTable_unparse (utab->aliases));
5818 ** Debugging routines:
5819 ** okay to leak storage here, only for debugging
5822 /*@-mustfree@*/
5824 void
5825 usymtab_printOut (void)
5826 /*@globals utab@*/
5828 int i;
5829 usymtab s = utab;
5830 int depth = 0;
5831 char *ind = mstring_copy (" ");
5833 fprintf (g_warningstream, "<<< [symbol table] >>>\n");
5835 while (s != GLOBAL_ENV && s->env != GLOBAL_ENV)
5837 cstring tname = usymtab_typeName (s);
5839 if (depth < 5)
5841 ind[depth * 3 + 1] = '\0';
5844 fprintf (g_warningstream, "level: %d (%s)\n", s->lexlevel,
5845 cstring_toCharsSafe (tname));
5847 cstring_free (tname);
5849 for (i = 0; i < s->nentries; i++)
5851 cstring us = uentry_unparseFull (s->entries[i]);
5852 fprintf (g_warningstream, "%s\n", cstring_toCharsSafe (us));
5853 cstring_free (us);
5856 if (s->reftable != NULL && s->nentries > 0)
5858 fprintf (g_warningstream, "\t<< Ref table >>\n");
5860 for (i = 0; i < s->nentries; i++)
5862 fprintf (g_warningstream, "\t%s %3d: %d, %d\n", ind, i,
5863 s->reftable[i]->level,
5864 s->reftable[i]->index);
5868 ind[depth * 3 + 1] = ' ';
5869 depth++;
5870 s = s->env;
5872 fprintf (g_warningstream, "<<< end usymtab >>>\n");
5873 mstring_free (ind);
5874 return;
5877 void
5878 usymtab_printTypes (void)
5879 /*@globals globtab@*/
5881 usymtab_printAllAux (globtab);
5884 void
5885 usymtab_printAll (void)
5886 /*@globals utab@*/
5888 usymtab_printAllAux (utab);
5891 static void
5892 usymtab_printAllAux (usymtab s)
5893 /*@modifies g_warningstream@*/
5895 int i;
5896 int depth = 0;
5897 char *ind = mstring_copy (" ");
5899 printf ("[[[ usymtab ]]]");
5901 while (s != GLOBAL_ENV)
5903 if (depth < 5)
5904 ind[depth * 3 + 1] = '\0';
5906 if (s->env == GLOBAL_ENV)
5908 int looplow;
5910 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5911 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5912 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5914 looplow = 0;
5916 for (i = looplow; i < s->nentries; i++)
5918 printf ("%s%3d. %s\n", ind, i,
5919 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5922 else
5924 printf ("level: %d / break: %s / exit: %s\n", s->lexlevel,
5925 cstring_toCharsSafe (bool_unparse (s->mustBreak)),
5926 cstring_toCharsSafe (exitkind_unparse (s->exitCode)));
5928 for (i = 0; i < s->nentries; i++)
5930 printf ("%s%3d %s\n", ind, i,
5931 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5935 ind[depth * 3 + 1] = ' ';
5936 depth++;
5937 s = s->env;
5939 printf ("----------\n");
5942 void
5943 usymtab_printComplete (void)
5944 /*@globals utab@*/
5946 int i;
5947 int depth = 0;
5948 char *ind = mstring_copy (" ");
5949 usymtab s = utab;
5951 while (s != GLOBAL_ENV)
5953 if (depth < 5)
5955 ind[depth * 3 + 1] = '\0';
5958 if (s->env == GLOBAL_ENV)
5960 int looplow;
5962 printf ("level: %d\n", s->lexlevel);
5964 looplow = 0;
5966 for (i = looplow; i < s->nentries; i++)
5968 printf ("%s%3d %s\n", ind, i,
5969 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5972 else
5974 printf ("level: %d\n", s->lexlevel);
5975 for (i = 0; i < s->nentries; i++)
5977 printf ("%s%3d %s\n", ind, i,
5978 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
5982 ind[depth * 3 + 1] = ' ';
5983 depth++;
5984 s = s->env;
5987 printf ("----------\n");
5988 mstring_free (ind);
5991 # ifdef S_SPLINT_S
5992 static /*@only@*/ cstring /*@unused@*/
5993 usymtab_unparseLocalAux (/*@notnull@*/ usymtab s)
5995 cstring c = message ("lexlevel: %d\n", s->lexlevel);
5996 int i;
5998 for (i = 0; i < s->nentries; i++)
6000 c = message ("%q\n%q", c, uentry_unparseFull (s->entries[i]));
6003 c = message ("%q\n=========", c);
6004 return (c);
6007 static cstring /*@unused@*/ /*@only@*/
6008 usymtab_unparseLocalList (/*@notnull@*/ usymtab s)
6010 cstring c = message ("[%d/%s/%s] ", s->lexlevel,
6011 bool_unparse (s->mustBreak),
6012 exitkind_unparse (s->exitCode));
6013 int i;
6015 for (i = 0; i < s->nentries; i++)
6017 sRef sr = uentry_getSref (s->entries[i]);
6019 if (i == 0)
6021 c = message ("%q: %q [%b]", c, uentry_getName (s->entries[i]),
6022 sRef_isStateDefined (sr));
6024 else
6026 c = message ("%q, %q [%b]", c, uentry_getName (s->entries[i]),
6027 sRef_isStateDefined (sr));
6032 return (c);
6034 # endif
6036 void
6037 usymtab_printLocal (void)
6038 /*@globals utab@*/
6040 int i;
6041 usymtab s = utab;
6043 printf ("lexlevel: %d\n", s->lexlevel);
6045 for (i = 0; i < s->nentries; i++)
6047 printf ("%s\n", cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
6050 while (s->lexlevel > 1)
6052 s = s->env;
6055 llassert (usymtab_isDefined (s));
6057 printf ("Params:\n");
6059 for (i = 0; i < s->nentries; i++)
6061 printf ("%d: %s\n", i,
6062 cstring_toCharsSafe (uentry_unparseFull (s->entries[i])));
6065 /*@=mustfree@*/
6067 static bool checkDistinctExternalName (uentry e)
6068 /*@globals globtab@*/
6069 /*@modifies *g_warningstream@*/
6071 size_t checklen = size_fromInt (context_getValue (FLG_EXTERNALNAMELEN));
6072 bool ignorecase = context_getFlag (FLG_EXTERNALNAMECASEINSENSITIVE);
6073 bool gotone = FALSE;
6074 bool extras = FALSE;
6075 bool hasError = FALSE;
6076 cstring name = uentry_rawName (e);
6077 usymtab st = globtab;
6079 if (checklen == 0)
6083 else
6085 if (uentry_isAnyTag (e))
6087 checklen++; /* the tag marker doesn't count */
6091 usymtab_entries (st, oe)
6093 if (uentry_sameObject (oe, e))
6095 continue;
6098 if (checklen == 0)
6100 if (cstring_equalCaseInsensitive (uentry_rawName (oe), name))
6102 if (gotone)
6104 extras = TRUE;
6105 break;
6108 if (optgenerror
6109 (FLG_DISTINCTEXTERNALNAMES,
6110 message
6111 ("External identifier %q is not distinguishable from %q "
6112 "because alphabetical case is ignored",
6113 uentry_getName (e),
6114 uentry_getName (oe)),
6115 uentry_whereLast (e)))
6117 uentry_showWhereAny (oe);
6118 uentry_setHasNameError (oe);
6119 gotone = TRUE;
6123 else
6125 if (ignorecase)
6127 if (cstring_equalLenCaseInsensitive (uentry_rawName (oe),
6128 name, checklen))
6130 if (gotone)
6132 extras = TRUE;
6133 break;
6136 if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6138 if (optgenerror
6139 (FLG_DISTINCTEXTERNALNAMES,
6140 /*@-sefparams@*/
6141 message
6142 ("External identifier %q is not distinguishable from %q "
6143 "in the first %d characters (%q)",
6144 uentry_getName (e),
6145 uentry_getName (oe),
6146 size_toInt (checklen),
6147 cstring_clip (uentry_getName (e), checklen)),
6148 /*@=sefparams@*/
6149 uentry_whereLast (e)))
6151 uentry_showWhereAny (oe);
6152 uentry_setHasNameError (oe);
6153 gotone = TRUE;
6156 else
6158 if (gotone)
6160 extras = TRUE;
6161 break;
6164 if (optgenerror
6165 (FLG_DISTINCTEXTERNALNAMES,
6166 message
6167 ("External identifier %q is not distinguishable from %q "
6168 "in the first %d characters because alphabetical case "
6169 "is ignored",
6170 uentry_getName (e),
6171 uentry_getName (oe),
6172 size_toInt (checklen)),
6173 uentry_whereLast (e)))
6175 uentry_showWhereAny (oe);
6176 uentry_setHasNameError (oe);
6177 gotone = TRUE;
6182 else if (cstring_equalLen (uentry_rawName (oe), name, checklen))
6184 if (gotone)
6186 extras = TRUE;
6187 break;
6190 if (optgenerror
6191 (FLG_DISTINCTEXTERNALNAMES,
6192 /*@-sefparams@*/
6193 message
6194 ("External identifier %q is not distinguishable from %q "
6195 "in the first %d characters (%q)",
6196 uentry_getName (e),
6197 uentry_getName (oe),
6198 size_toInt (checklen),
6199 cstring_clip (uentry_getName (e), checklen)),
6200 /*@=sefparams@*/
6201 uentry_whereLast (e)))
6203 uentry_showWhereAny (oe);
6204 uentry_setHasNameError (oe);
6205 gotone = TRUE;
6208 else
6210 ; /* okay */
6213 } end_usymtab_entries ;
6215 hasError = gotone;
6217 if (extras)
6219 llgenindentmsgnoloc
6220 (cstring_makeLiteral ("One or more additional "
6221 "indistinguishable external "
6222 "names not reported"));
6225 return hasError;
6228 static bool checkDistinctInternalName (uentry e)
6229 /*@globals utab@*/
6230 /*@modifies *g_warningstream@*/
6232 usymtab ttab = utab;
6233 cstring name = uentry_rawName (e);
6234 size_t numchars = size_fromInt (context_getValue (FLG_INTERNALNAMELEN));
6235 bool caseinsensitive = context_getFlag (FLG_INTERNALNAMECASEINSENSITIVE);
6236 bool lookalike = context_getFlag (FLG_INTERNALNAMELOOKALIKE);
6238 if (uentry_isAnyTag (e) && (numchars != 0))
6240 numchars++; /* the tag marker doesn't count */
6243 while (usymtab_isDefined (ttab))
6245 usymtab_entries (ttab, oe)
6247 if (uentry_sameObject (oe, e))
6249 /*@innercontinue@*/ continue;
6252 switch (cstring_genericEqual
6253 (name, uentry_rawName (oe),
6254 numchars, caseinsensitive, lookalike))
6256 case CGE_DISTINCT: /* okay */
6257 /*@switchbreak@*/
6258 break;
6259 case CGE_SAME:
6260 if (cstring_equal (name, uentry_rawName (oe)))
6262 ; /* got a shadow error */
6264 else
6266 if (optgenerror
6267 (FLG_DISTINCTINTERNALNAMES,
6268 /*@-sefparams@*/
6269 message
6270 ("Internal identifier %q is not distinguishable from %q "
6271 "in the first %d characters (%q)",
6272 uentry_getName (e),
6273 uentry_getName (oe),
6274 size_toInt (numchars),
6275 cstring_clip (uentry_getName (e), numchars)),
6276 /*@=sefparams@*/
6277 uentry_whereLast (e)))
6279 uentry_showWhereAny (oe);
6280 uentry_setHasNameError (oe);
6281 return TRUE;
6284 /*@switchbreak@*/
6285 break;
6286 case CGE_CASE:
6287 if (numchars == 0 || (cstring_length (name) <= numchars))
6289 if (optgenerror
6290 (FLG_DISTINCTINTERNALNAMES,
6291 message
6292 ("Internal identifier %q is not distinguishable from %q "
6293 "without case sensitivity",
6294 uentry_getName (e),
6295 uentry_getName (oe)),
6296 uentry_whereLast (e)))
6298 uentry_showWhereAny (oe);
6299 uentry_setHasNameError (oe);
6300 return TRUE;
6303 else
6305 if (optgenerror
6306 (FLG_DISTINCTINTERNALNAMES,
6307 message
6308 ("Internal identifier %q is not distinguishable from %q "
6309 "in the first %d characters without case sensitivity",
6310 uentry_getName (e),
6311 uentry_getName (oe),
6312 size_toInt (numchars)),
6313 uentry_whereLast (e)))
6315 uentry_showWhereAny (oe);
6316 uentry_setHasNameError (oe);
6317 return TRUE;
6320 /*@switchbreak@*/
6321 break;
6322 case CGE_LOOKALIKE:
6323 if (numchars == 0
6324 || (cstring_length (name) <= numchars))
6326 if (optgenerror
6327 (FLG_DISTINCTINTERNALNAMES,
6328 message
6329 ("Internal identifier %q is not distinguishable from %q "
6330 "except by lookalike characters",
6331 uentry_getName (e),
6332 uentry_getName (oe)),
6333 uentry_whereLast (e)))
6335 uentry_showWhereAny (oe);
6336 uentry_setHasNameError (oe);
6337 return TRUE;
6340 else
6342 if (optgenerror
6343 (FLG_DISTINCTINTERNALNAMES,
6344 message
6345 ("Internal identifier %q is not distinguishable from %q "
6346 "in the first %d characters except by lookalike characters",
6347 uentry_getName (e),
6348 uentry_getName (oe),
6349 size_toInt (numchars)),
6350 uentry_whereLast (e)))
6352 uentry_showWhereAny (oe);
6353 uentry_setHasNameError (oe);
6354 return TRUE;
6358 } end_usymtab_entries ;
6360 ttab = ttab->env;
6363 return FALSE;
6366 void usymtab_checkDistinctName (uentry e, int scope)
6367 /*@globals utab, globtab@*/
6369 bool hasError = FALSE;
6370 fileloc where = uentry_whereLast (e);
6372 if (!fileloc_isPreproc (where) && !fileloc_isBuiltin (where))
6374 if (scope == globScope)
6376 if (context_getFlag (FLG_DISTINCTEXTERNALNAMES))
6378 hasError = checkDistinctExternalName (e);
6382 if (!hasError && context_getFlag (FLG_DISTINCTINTERNALNAMES))
6384 hasError = checkDistinctInternalName (e);
6388 if (hasError)
6390 uentry_setHasNameError (e);
6394 /*@exposed@*/ sRef usymtab_lookupGlobalMarker (void) /*@globals utab@*/
6396 uentry ue;
6398 ue = usymtab_lookupAux (utab, GLOBAL_MARKER_NAME);
6399 llassert (uentry_isValid (ue));
6401 return uentry_getSref (ue);
6405 # ifdef DEBUGSPLINT
6407 ** For debugging only
6410 void
6411 usymtab_checkAllValid () /*@globals utab@*/
6413 usymtab tab = utab;
6415 while (tab != GLOBAL_ENV)
6417 int i;
6419 for (i = 0; i < utab->nentries; i++)
6421 uentry e = utab->entries[i];
6423 uentry_checkValid (e);
6426 aliasTable_checkValid (tab->aliases);
6427 tab = tab->env;
6430 # endif