X-Git-Url: http://andersk.mit.edu/gitweb/splint.git/blobdiff_plain/885824d34f6f6626fde2fb041801408cbaf1f6f1..3dabb0778770a6ee8a2af1a104325e2651933ce1:/src/usymtab.c diff --git a/src/usymtab.c b/src/usymtab.c index 99c2f91..cf207a3 100644 --- a/src/usymtab.c +++ b/src/usymtab.c @@ -1,6 +1,6 @@ /* -** LCLint - annotation-assisted static program checker -** Copyright (C) 1994-2000 University of Virginia, +** Splint - annotation-assisted static program checker +** Copyright (C) 1994-2002 University of Virginia, ** Massachusetts Institute of Technology ** ** This program is free software; you can redistribute it and/or modify it @@ -17,9 +17,9 @@ ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, ** MA 02111-1307, USA. ** -** For information on lclint: lclint-request@cs.virginia.edu -** To report a bug: lclint-bug@cs.virginia.edu -** For more information: http://lclint.cs.virginia.edu +** For information on splint: info@splint.org +** To report a bug: splint-bug@splint.org +** For more information: http://www.splint.org */ /* ** usymtab @@ -46,11 +46,17 @@ ** weird C syntax. */ -# include "lclintMacros.nf" +# include "splintMacros.nf" # include "basic.h" # include "structNames.h" # include "exprChecks.h" -# include "aliasChecks.h" +# include "transferChecks.h" + +/* Needed to install macros when loading libraries */ + +# include "cpplib.h" +# include "cpperror.h" +# include "cpphash.h" /* ** Keep track of type definitions inside a function. @@ -61,7 +67,7 @@ static uentryList functypes = uentryList_undefined; static bool dbgfree = FALSE; static bool dbgload = TRUE; -/*@access ekind usymId@*/ +/*@access ekind@*/ /* ** Hack to prevent shadow errors from appearing when function parameters @@ -95,22 +101,36 @@ static /*@checkedstrict@*/ /*@dependent@*/ usymtab filetab; static /*@checkedstrict@*/ /*@owned@*/ usymtab oldtab; static int usymtab_lexicalLevel (void) /*@globals utab@*/ ; -static bool usymtab_isProbableNullAltBranch (sRef p_s) /*@globals utab@*/ ; +static bool usymtab_isAltDefinitelyNull (sRef p_s) /*@globals utab@*/ ; static void refTable_free (/*@only@*/ /*@null@*/ refTable p_x, int p_nentries); static ctype usymtab_suFieldsType (uentryList p_f, bool p_isStruct) /*@globals globtab@*/ ; +static void usymtab_freeAux (/*@only@*/ usymtab p_u) + /*@globals globtab, utab, filetab@*/ + /*@modifies p_u@*/ ; + +extern int usymtab_getCurrentDepth (void) /*@globals utab@*/ +{ + return utab->lexlevel; +} + static void usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab p_u) /*@globals globtab, utab, filetab@*/ /*@modifies p_u@*/ ; -static bool usymtab_isProbableNullAux (sRef p_s) /*@globals utab@*/ ; +static bool usymtab_isDefinitelyNullAux (sRef p_s) /*@globals utab@*/ ; static /*@only@*/ cstring usymtab_unparseStackTab (usymtab p_t); static /*@exposed@*/ /*@dependent@*/ uentry usymtab_getRefTab (/*@notnull@*/ usymtab p_u, int p_level, usymId p_index); + +# ifdef S_SPLINT_S +/* These are not used anymore... */ static /*@unused@*/ /*@only@*/ cstring usymtab_unparseLocalAux (/*@notnull@*/ usymtab p_s); static /*@unused@*/ /*@only@*/ cstring usymtab_unparseLocalList (/*@notnull@*/ usymtab p_s); +# endif + static /*@only@*/ cstring usymtab_typeName (/*@notnull@*/ usymtab p_t); static void usymtab_handleParams (void) /*@globals utab, globtab, filetab@*/ @@ -123,9 +143,16 @@ static /*@exposed@*/ /*@dependent@*/ usymtab static /*@exposed@*/ /*@dependent@*/ uentry usymtab_getRefNoisy (/*@notnull@*/ usymtab p_s, int p_level, usymId p_index); +static /*@exposed@*/ /*@dependent@*/ uentry + usymtab_lookupQuietAux (usymtab p_s, cstring p_k, bool p_noalt); + static /*@exposed@*/ /*@dependent@*/ uentry usymtab_lookupQuiet (usymtab p_s, cstring p_k); -static void usymtab_printAllAux (usymtab p_s) /*@modifies g_msgstream@*/ ; + +static /*@exposed@*/ /*@dependent@*/ uentry + usymtab_lookupQuietNoAlt (usymtab p_s, cstring p_k); + +static void usymtab_printAllAux (usymtab p_s) /*@modifies g_warningstream@*/ ; static int usymtab_getIndex (/*@notnull@*/ usymtab p_s, cstring p_k); static /*@exposed@*/ uentry usymtab_fetchIndex (/*@notnull@*/ usymtab p_s, int p_i); static /*@exposed@*/ uentry @@ -138,9 +165,9 @@ static bool usymtab_mustEscape (usymtab p_s); static void recordFunctionType (uentry ue) { - llassert (uentry_isDatatype (ue) || uentry_isAnyTag (ue) + llassert (uentry_isDatatype (ue) || uentry_isAnyTag (ue) || uentry_isEnumConstant (ue)); - + DPRINTF (("Function type: %s", uentry_unparseFull (ue))); /*@-temptrans@*/ functypes = uentryList_add (functypes, ue); /*@=temptrans@*/ @@ -153,9 +180,9 @@ static void clearFunctionTypes (void) { if (cstring_isDefined (uentry_rawName (el))) { - if (globtab->htable != NULL) + if (cstringTable_isDefined (globtab->htable)) { - hashTable_remove (globtab->htable, uentry_rawName (el)); + cstringTable_remove (globtab->htable, uentry_rawName (el)); } uentry_setName (el, cstring_undefined); @@ -170,7 +197,7 @@ static void clearFunctionTypes (void) uentryList_clear (functypes); } -static /*@falsenull@*/ bool usymtab_isBranch (usymtab u) +static /*@falsewhennull@*/ bool usymtab_isBranch (usymtab u) { return (usymtab_isDefined (u) && (u->kind == US_TBRANCH || u->kind == US_FBRANCH @@ -209,12 +236,12 @@ void usymtab_setExitCode (exitkind ex) } } -bool usymtab_isAltProbablyDeepNull (sRef s) +bool usymtab_isAltDefinitelyNullDeep (sRef s) { - return (sRef_deepPred (usymtab_isProbableNullAltBranch, s)); + return (sRef_deepPred (usymtab_isAltDefinitelyNull, s)); } -static bool usymtab_isProbableNullAltBranch (sRef s) +static bool usymtab_isAltDefinitelyNull (sRef s) /*@globals utab@*/ { guardSet t; @@ -230,7 +257,7 @@ static bool usymtab_isProbableNullAltBranch (sRef s) /*@=mods@*/ llassert (usymtab_isDefined (utab)); - res = usymtab_isProbableNull (s); + res = usymtab_isDefinitelyNull (s); /* ** This reports a spurious error. It is okay, because of @@ -255,22 +282,27 @@ static /*@notnull@*/ /*@special@*/ usymtab t->nentries = 0; t->nspace = CBASESIZE; t->entries = (uentry *) dmalloc (sizeof (*t->entries) * CBASESIZE); + + /* We only use a reftable for branch-level symbol tables. + */ + t->reftable = (nextlevel ? NULL : (refentry *) dmalloc (sizeof (*t->reftable) * CBASESIZE)); t->kind = kind; t->lexlevel = (env == GLOBAL_ENV ? 0 : env->lexlevel) + (nextlevel ? 1 : 0); - + t->env = env; t->htable = NULL; t->guards = guardSet_undefined; t->aliases = aliasTable_undefined; - t->mustBreak = FALSE; + t->mustBreak = FALSE; t->exitCode = XK_NEVERESCAPE; + DPRINTF (("Create usymtab [%p]", t)); return t; } @@ -288,9 +320,9 @@ static /*@only@*/ /*@notnull@*/ usymtab u->entries = (uentry *) dmalloc (sizeof (*u->entries) * CGLOBBASESIZE); u->env = GLOBAL_ENV; u->lexlevel = 0; - u->htable = hashTable_create (CGLOBHASHSIZE); + u->htable = cstringTable_create (CGLOBHASHSIZE); u->reftable = NULL; - + u->guards = guardSet_new (); u->aliases = aliasTable_new (); @@ -312,6 +344,28 @@ usymtab_initMod (void) oldtab = usymtab_undefined; } +void +usymtab_destroyMod (void) /*@modifies utab, globtab, filetab@*/ /*@globals killed utab@*/ +{ + DPRINTF (("Destroy usymtab [%p]: %d", utab, utab->nentries)); + usymtab_freeAux (utab); + utab = usymtab_undefined; + /*@-globstate@*/ +} /*@=globstate@*/ + +void +usymtab_initGlobalMarker () /*@globals globtab@*/ +{ + if (uentry_isValid (usymtab_lookupAux (globtab, GLOBAL_MARKER_NAME))) + { + ; /* Already entered from load table. */ + } + else + { + usymtab_addGlobalEntry (uentry_makeGlobalMarker ()); + } +} + /* ** utab should be empty? (requires?) ** @@ -322,37 +376,31 @@ usymtab_initMod (void) void usymtab_initBool () { + DPRINTF (("Init bool!")); + if (context_getFlag (FLG_NOLIB)) { ctype boolt = ctype_bool; + /* evs 2000-07-24: bool is now treated as abstract (always) */ + + uentry boolentry = uentry_makeBoolDatatype (YES); + usymtab_supGlobalEntry (boolentry); + context_addBoolAccess (); - if (context_getFlag (FLG_ABSTRACTBOOL)) - { - uentry boolentry = uentry_makeBoolDatatype (YES); - - usymtab_supGlobalEntry (boolentry); - context_addBoolAccess (); - } - else - { - uentry boolentry = uentry_makeBoolDatatype (NO); - - usymtab_supGlobalEntry (boolentry); - } - /* ** We supply values 0 and 1 for the constants, so things like ** while (TRUE) can be interpreted correctly. */ usymtab_supGlobalEntry - (uentry_makeConstantAux (context_getFalseName (), boolt, - fileloc_getBuiltin (), FALSE, - multiVal_makeInt (0))); + (uentry_makeConstantValue (context_getFalseName (), boolt, + fileloc_getBuiltin (), FALSE, + multiVal_makeInt (0))); + usymtab_supGlobalEntry - (uentry_makeConstantAux (context_getTrueName (), boolt, - fileloc_getBuiltin (), FALSE, - multiVal_makeInt (1))); + (uentry_makeConstantValue (context_getTrueName (), boolt, + fileloc_getBuiltin (), FALSE, + multiVal_makeInt (1))); } } @@ -449,9 +497,9 @@ usymtab_addEntryQuiet (/*@notnull@*/ usymtab s, /*@keep@*/ uentry e) } # endif - if (s->htable != NULL) + if (cstringTable_isDefined (s->htable)) { - hashTable_insert (s->htable, uentry_rawName (e), s->nentries); + cstringTable_insert (s->htable, cstring_copy (uentry_rawName (e)), s->nentries); } s->nentries++; @@ -482,7 +530,8 @@ usymtab_addEntryBase (/*@notnull@*/ usymtab s, /*@only@*/ uentry e) if (uentry_isVar (e)) { uentry_setSref (e, sRef_makeCvar (globScope, thisentry, - uentry_getType (e))); + uentry_getType (e), + stateInfo_makeLoc (uentry_whereLast (e)))); } usymtab_addEntryQuiet (s, e); @@ -490,6 +539,45 @@ usymtab_addEntryBase (/*@notnull@*/ usymtab s, /*@only@*/ uentry e) } } + +static /*@observer@*/ uentry /*@alt void@*/ +usymtab_addEntryAlways (/*@notnull@*/ usymtab s, /*@only@*/ uentry e) +{ + /* + ** In theory, we shouldn't need this test because it this is + ** only called when a library is being read, and it shouldn't + ** ever have a duplicate entry. In practice, its safer to + ** leave it in, though. + */ + + uentry old; + int thisentry = s->nentries; + + if (uentry_isValid (old = usymtab_lookupQuiet (s, uentry_rawName (e)))) + { + llcontbug + (message ("Duplicate entry in load library: %s. " + "Old entry: %q. New entry: %q", + uentry_rawName (e), + uentry_unparseFull (old), + uentry_unparseFull (e))); + + uentry_setName (e, message ("__x_%s", uentry_rawName (e))); + /* This shouldn't happen...unless the library is bad! */ + } + + + if (uentry_isVar (e) && !uentry_isGlobalMarker (e)) + { + uentry_setSref (e, sRef_makeCvar (globScope, thisentry, + uentry_getType (e), + stateInfo_makeLoc (uentry_whereLast (e)))); + } + + usymtab_addEntryQuiet (s, e); + return e; +} + static usymId usymtab_addEntryAux (/*@notnull@*/ usymtab st, /*@keep@*/ uentry e, bool isSref) /*@globals globtab@*/ @@ -519,12 +607,12 @@ usymtab_addEntryAux (/*@notnull@*/ usymtab st, /*@keep@*/ uentry e, bool isSref) if (uentry_isFunction (e) && ctype_isFunction (ct)) { - ct = ctype_returnValue (ct); + ct = ctype_getReturnType (ct); } if (uentry_isStatic (e)) { - sRef sr = sRef_makeCvar (st->lexlevel, thisentry, ct); + sRef sr = sRef_makeCvar (st->lexlevel, thisentry, ct, stateInfo_makeLoc (uentry_whereLast (e))); if (sRef_isStack (sr) || sRef_isLocalState (sr)) { @@ -536,10 +624,9 @@ usymtab_addEntryAux (/*@notnull@*/ usymtab st, /*@keep@*/ uentry e, bool isSref) } else { - uentry_setSref (e, sRef_makeCvar (st->lexlevel, thisentry, ct)); + uentry_setSref (e, sRef_makeCvar (st->lexlevel, thisentry, ct, stateInfo_makeLoc (uentry_whereLast (e)))); } - - } + } if (uentry_isDatatype (e)) { @@ -578,10 +665,10 @@ usymtab_addEntryAux (/*@notnull@*/ usymtab st, /*@keep@*/ uentry e, bool isSref) exprChecks_checkExport (e); } - uentry_checkName (e); usymtab_addEntryQuiet (st, e); + DPRINTF (("Adding entry: [%p] %s", e, uentry_unparseFull (e))); return (thisentry); } @@ -589,8 +676,7 @@ usymId usymtab_addEntry (uentry e) /*@globals utab, globtab@*/ /*@modifies utab, e@*/ -{ - +{ llassertprint (!usymtab_exists (uentry_rawName (e)), ("Entry already exists: %s", uentry_unparse (e))); @@ -625,7 +711,7 @@ usymtab_supEntryAux (/*@notnull@*/ usymtab st, int eindex; DPRINTF (("Sup entry aux: %s", uentry_unparseFull (e))); - + /* static tags in global scope */ if (st->lexlevel == fileScope && (!(uentry_isStatic (e)) || uentry_isAnyTag (e))) @@ -655,10 +741,10 @@ usymtab_supEntryAux (/*@notnull@*/ usymtab st, st->entries[eindex] = st->entries[st->nentries - 1]; } - if (st->htable != NULL) + if (cstringTable_isDefined (st->htable)) { - hashTable_replaceKey (st->htable, uentry_rawName (ce), - uentry_rawName (e)); + cstringTable_replaceKey (st->htable, uentry_rawName (ce), + cstring_copy (uentry_rawName (e))); } uentry_free (ce); @@ -670,7 +756,11 @@ usymtab_supEntryAux (/*@notnull@*/ usymtab st, if (uentry_isStatic (e)) { if (uentry_isFunction (e)) { - /* Static function declarations are at the file level, even if they are in a deeped scope. */ + /* + ** Static function declarations are at the file level, + ** even if they are in a deeper scope. + */ + st = usymtab_getFileTab (); staticEntry = TRUE; } else { @@ -683,14 +773,12 @@ usymtab_supEntryAux (/*@notnull@*/ usymtab st, } } - DPRINTF (("Using symtab: %s", usymtab_unparseLocalAux (st))); - eindex = usymtab_getIndex (st, ename); if (eindex != NOT_FOUND) { uentry ce = st->entries[eindex]; - + DPRINTF (("Found entry: %s", uentry_unparse (ce))); if (uentry_isPriv (ce) @@ -708,6 +796,8 @@ usymtab_supEntryAux (/*@notnull@*/ usymtab st, llassert ((st->lexlevel > fileScope || !sRef_modInFunction ())); + DPRINTF (("Overloading!")); + st->entries[eindex] = e; if (uentry_isDatatype (e)) @@ -720,10 +810,10 @@ usymtab_supEntryAux (/*@notnull@*/ usymtab st, exprChecks_checkExport (e); } - if (st->htable != NULL) + if (cstringTable_isDefined (st->htable)) { - hashTable_replaceKey (st->htable, uentry_rawName (ce), - uentry_rawName (e)); + cstringTable_replaceKey (st->htable, uentry_rawName (ce), + cstring_copy (uentry_rawName (e))); } uentry_free (ce); @@ -733,14 +823,15 @@ usymtab_supEntryAux (/*@notnull@*/ usymtab st, { if (uentry_isSpecified (e)) { + DPRINTF (("Here we are: %s", uentry_unparseFull (e))); + if (fileloc_isImport (uentry_whereSpecified (ce))) - { - - if (st->htable != NULL) + { + if (cstringTable_isDefined (st->htable)) { - hashTable_replaceKey (st->htable, - uentry_rawName (ce), - uentry_rawName (e)); + cstringTable_replaceKey (st->htable, + uentry_rawName (ce), + cstring_copy (uentry_rawName (e))); } uentry_free (ce); @@ -757,18 +848,21 @@ usymtab_supEntryAux (/*@notnull@*/ usymtab st, } else { - /* respecification errors already reported */ - + /* Respecification errors already reported */ + DPRINTF (("Respecification: %s / %s", + fileloc_unparse (uentry_whereSpecified (e)), + bool_unparse (fileloc_isSpec (uentry_whereSpecified (e))))); + if (uentry_isDatatype (e)) { uentry_setDatatype (e, eindex); } - if (st->htable != NULL) + if (cstringTable_isDefined (st->htable)) { - hashTable_replaceKey (st->htable, - uentry_rawName (ce), - uentry_rawName (e)); + cstringTable_replaceKey (st->htable, + uentry_rawName (ce), + cstring_copy (uentry_rawName (e))); } llassert ((st->lexlevel > fileScope || !sRef_modInFunction ())); @@ -780,15 +874,28 @@ usymtab_supEntryAux (/*@notnull@*/ usymtab st, } else /* e not specified */ { + DPRINTF (("Merging...")); + if (uentry_isDeclared (ce)) { - llassert ((st->lexlevel > fileScope || !sRef_modInFunction ())); + /* evans 2001-08-26 + No - this can happen for internal typedefs + llassert ((st->lexlevel > fileScope || !sRef_modInFunction ())); + */ + + DPRINTF (("Merge defn")); uentry_mergeDefinition (ce, e); } else { - llassert ((st->lexlevel > fileScope || !sRef_modInFunction ())); + /* evans 2001-08-26 + No - this can happen for internal typedefs + llassert ((st->lexlevel > fileScope || !sRef_modInFunction ())); + */ + + DPRINTF (("Merge entries...")); uentry_mergeEntries (ce, e); + DPRINTF (("After: %s", uentry_unparseFull (ce))); } } } @@ -797,7 +904,8 @@ usymtab_supEntryAux (/*@notnull@*/ usymtab st, if (!(st->lexlevel > fileScope || !sRef_modInFunction ())) { if (uentry_isDatatype (e) || uentry_isAnyTag (e) - || uentry_isEnumConstant (e)) + || uentry_isEnumConstant (e) + || uentry_isStatic (e)) /* bug fix from Brian St. Pierre */ { ; /* ** Not a bug. Code like, @@ -820,6 +928,7 @@ usymtab_supEntryAux (/*@notnull@*/ usymtab st, } } + DPRINTF (("Merge..")); uentry_mergeDefinition (ce, e); } @@ -829,11 +938,11 @@ usymtab_supEntryAux (/*@notnull@*/ usymtab st, if (uentry_isFunction (ce) && ctype_isFunction (ct)) { - ct = ctype_returnValue (ct); + ct = ctype_getReturnType (ct); } - uentry_setSref (ce, sRef_makeCvar (st->lexlevel, eindex, ct)); - } + uentry_setSref (ce, sRef_makeCvar (st->lexlevel, eindex, ct, stateInfo_makeLoc (uentry_whereLast (ce)))); + } } else /* no previous entry */ { @@ -867,6 +976,9 @@ usymtab_supEntryAux (/*@notnull@*/ usymtab st, outer = usymtab_lookupQuiet (st->env, ename); + DPRINTF (("New : [%p] %s", e, uentry_unparseFull (e))); + DPRINTF (("Outer: [%p] %s", outer, uentry_unparseFull (outer))); + /* ** no previous definition, add the new one */ @@ -875,7 +987,9 @@ usymtab_supEntryAux (/*@notnull@*/ usymtab st, && uentry_isValid (outer) && !(uentry_isYield (e) || uentry_isYield (outer)) && fileloc_isDefined (uentry_whereLast (e)) - && fileloc_isDefined (uentry_whereLast (outer))) + && !fileloc_isXHFile (uentry_whereLast (e)) + && fileloc_isDefined (uentry_whereLast (outer)) + && !fileloc_isXHFile (uentry_whereLast (outer))) { if (!uentry_sameKind (outer, e)) { @@ -918,7 +1032,6 @@ usymtab_supEntryAux (/*@notnull@*/ usymtab st, return (staticEntry ? USYMIDINVALID : eindex); } -# ifndef NOLCL static void usymtab_replaceEntryAux (/*@notnull@*/ usymtab st, /*@only@*/ uentry e) /*@globals globtab@*/ /*@modifies st, e@*/ @@ -933,9 +1046,10 @@ usymtab_replaceEntryAux (/*@notnull@*/ usymtab st, /*@only@*/ uentry e) { uentry ce = st->entries[eindex]; - if (st->htable != NULL) + if (cstringTable_isDefined (st->htable)) { - hashTable_replaceKey (st->htable, uentry_rawName (ce), uentry_rawName (e)); + cstringTable_replaceKey (st->htable, uentry_rawName (ce), + cstring_copy (uentry_rawName (e))); } uentry_free (ce); @@ -946,7 +1060,6 @@ usymtab_replaceEntryAux (/*@notnull@*/ usymtab st, /*@only@*/ uentry e) eindex = usymtab_addEntryAux (st, e, FALSE); } } -# endif /*@=deparrays@*/ @@ -971,7 +1084,6 @@ static /*@exposed@*/ uentry bool stat = (tab == globtab) && uentry_isStatic (e); uentry ret; - (void) usymtab_supEntryAux (tab, e, isref); if (stat) @@ -1017,6 +1129,12 @@ static /*@exposed@*/ uentry ret = usymtab_supEntryReturnAux (globtab, e, FALSE); + /* + ** We need to keep track of internal function declarations, so + ** we can remove them from the symbol table after exiting this + ** function. This is a bit bogus, of course. + */ + if (sRef_modInFunction ()) { recordFunctionType (ret); @@ -1059,15 +1177,69 @@ usymtab_supReturnTypeEntry (/*@only@*/ uentry e) { usymId uid; + DPRINTF (("Abstract? %s", uentry_unparseFull (e))); + if (uentry_isAbstractDatatype (e)) { - uid = usymtab_supAbstractTypeEntry (e, FALSE); + uid = usymtab_supAbstractTypeEntry (e, FALSE); } - else + else if (uentry_isMaybeAbstract (e) && context_getFlag (FLG_IMPABSTRACT)) { - uid = usymtab_supEntryAux (globtab, e, FALSE); + bool maybeabs = TRUE; + cstring sname = uentry_getName (e); + uentry ue = usymtab_lookupGlobSafe (sname); + cstring_free (sname); + + if (uentry_isValid (ue)) + { + DPRINTF (("Lookup: %s", uentry_unparseFull (ue))); + + if (uentry_isDatatype (ue)) + { + if (uentry_isMaybeAbstract (ue)) + { + ; + } + else + { + maybeabs = FALSE; + } + } + else + { + DPRINTF (("Not datatype!")); + } + } + + if (maybeabs) + { + uentry ux; + uid = usymtab_supAbstractTypeEntry (e, FALSE); + ux = usymtab_getTypeEntry (uid); + uentry_setAbstract (ux); + } + else + { + uid = usymtab_supEntryAux (globtab, e, FALSE); + e = usymtab_getTypeEntry (uid); + + if (uentry_isMaybeAbstract (e)) + { + uentry_setConcrete (e); + } + } } + else + { + uid = usymtab_supEntryAux (globtab, e, FALSE); + e = usymtab_getTypeEntry (uid); + if (uentry_isMaybeAbstract (e)) + { + uentry_setConcrete (e); + } + } + if (sRef_modInFunction ()) { recordFunctionType (globtab->entries[uid]); @@ -1082,17 +1254,17 @@ usymtab_supAbstractTypeEntry (/*@only@*/ uentry e, bool dodef) /*@modifies globtab, e@*/ { usymId uid; + uentry ue; uid = usymtab_supEntryAux (globtab, e, FALSE); + ue = usymtab_getTypeEntry (uid); if (dodef) { - uentry ue = usymtab_getTypeEntry (uid); - uentry_setDatatype (ue, uid); } - if (context_getFlag (FLG_ACCESSMODULE)) + if (context_getFlag (FLG_ACCESSMODULE)) /* was accessfile */ { context_addFileAccessType (uid); } @@ -1105,7 +1277,6 @@ usymtab_supAbstractTypeEntry (/*@only@*/ uentry e, bool dodef) return (uid); } -# ifndef NOLCL usymId usymtab_supExposedTypeEntry (/*@only@*/ uentry e, bool dodef) /*@globals globtab, filetab@*/ @@ -1129,7 +1300,6 @@ usymtab_supExposedTypeEntry (/*@only@*/ uentry e, bool dodef) return (uid); } -# endif ctype usymtab_supForwardTypeEntry (/*@only@*/ uentry e) @@ -1155,7 +1325,6 @@ void /*@modifies utab, globtab, e@*/ { sRef old = uentry_getSref (e); - if (sRef_isType (old)) { @@ -1222,10 +1391,11 @@ usymtab_getIndex (/*@notnull@*/ usymtab s, cstring k) { int i; - if (s->htable != NULL) - { - i = hashTable_lookup (s->htable, k); + DPRINTF (("Lookup %s", k)); + if (cstringTable_isDefined (s->htable)) + { + i = cstringTable_lookup (s->htable, k); return i; } else @@ -1234,6 +1404,8 @@ usymtab_getIndex (/*@notnull@*/ usymtab s, cstring k) { uentry current = s->entries[i]; + DPRINTF (("Check %d: %s", i, uentry_rawName (current))); + if (!uentry_isUndefined (current) && cstring_equal (uentry_rawName (current), k)) { @@ -1258,7 +1430,10 @@ usymtab_getTypeId (cstring k) /*@globals globtab@*/ usymId uid = usymtab_getIndex (globtab, k); if (uid == NOT_FOUND) return USYMIDINVALID; - if (!(uentry_isDatatype (usymtab_getTypeEntry (uid)))) return USYMIDINVALID; + + if (!(uentry_isDatatype (usymtab_getTypeEntry (uid)))) { + return USYMIDINVALID; + } return uid; } @@ -1268,7 +1443,8 @@ usymtab_lookupStructTag (cstring k) { cstring sname = makeStruct (k); uentry ue = usymtab_lookupGlob (sname); - cstring_free (sname); + + cstring_free (sname); return (ue); } @@ -1365,8 +1541,7 @@ usymtab_getEntryAux (/*@notnull@*/ usymtab s, usymId uid) } else { - llassert (uid >= 0 && uid < globtab->nentries); - + llassert (uid >= 0 && uid < globtab->nentries); return (globtab->entries[uid]); } } @@ -1420,23 +1595,25 @@ usymtab_getTypeEntryName (usymId uid) return (uentry_getName (ue)); } -static void +# if 0 +/*@unused@*/ static void usymtab_rehash (/*@notnull@*/ usymtab s) { int i; - if (s->htable != NULL) + if (cstringTable_isDefined (s->htable)) { - hashTable_free (s->htable); + cstringTable_free (s->htable); } - s->htable = hashTable_create (LLHASHSIZE); + s->htable = cstringTable_create (LLAHSHSIZE); for (i = 0; i < s->nentries; i++) { - hashTable_insert (s->htable, uentry_rawName (s->entries[i]), i); + cstringTable_insert (s->htable, cstring_copy (uentry_rawName (s->entries[i])), i); } } +# endif /* ** superficial copy of usymtab @@ -1488,6 +1665,10 @@ usymId name = uentry_rawName (ue); ret = usymtab_getIndex (utab, name); + llassert (ret == uid); /*! for now, no rehash! */ + DPRINTF (("Convert: %s [%d] -> %s [%d]", + uentry_unparse (ue), uid, + uentry_unparse (utab->entries[ret]), ret)); llassertprint (ret != USYMIDINVALID, ("convertId: return is invalid")); @@ -1500,25 +1681,36 @@ usymtab_prepareDump (void) /*@modifies oldtab, utab@*/ { llassert (usymtab_inGlobalScope ()); - llassert (oldtab == usymtab_undefined); + /* + DPRINTF (("Preparing to dump:")); + usymtab_printAll (); + */ + oldtab = usymtab_shallowCopy (utab); /* - alpha compare - make sure order is same on different platforms - error messages appear in same order + ** alpha compare - make sure order is same on different platforms + ** error messages appear in same order */ + /* qsort (utab->entries, (size_t)utab->nentries, - sizeof (*utab->entries), (int (*)(const void *, const void *)) uentry_xcomparealpha); - + sizeof (*utab->entries), + (int (*)(const void *, const void *)) uentry_xcomparealpha); + usymtab_rehash (utab); + */ + + /* + DPRINTF (("After rehash:")); + usymtab_printAll (); + */ } -void - usymtab_dump (FILE *fout) - /*@globals utab, oldtab@*/ +void usymtab_dump (FILE *fout) + /*@globals utab, oldtab@*/ { int i; bool neednl = FALSE; @@ -1537,61 +1729,143 @@ void uentry thisentry = utab->entries[i]; ekind thisekind = uentry_getKind (thisentry); - - if (uentry_hasRealName (thisentry)) { - if (thisekind != lastekind) - { - if (neednl) - { - check (fputc ('\n', fout) == (int) '\n'); - } - - neednl = FALSE; - lastentry = uentry_undefined; - fprintf (fout, "*%d (%s)\n", ekind_toInt (thisekind), - cstring_toCharsSafe (ekind_capName (thisekind))); - lastekind = thisekind; - linelen = 0; - } - - if (uentry_isInvalid (lastentry) || !uentry_equiv (lastentry, thisentry) - || (linelen > (MAX_DUMP_LINE_LENGTH - (2 * MAX_NAME_LENGTH)))) - { - cstring cdump = uentry_dump (thisentry); - - lastentry = thisentry; - if (neednl) - { - check (fputc ('\n', fout) == (int) '\n'); - linelen = 0; - } - - linelen += cstring_length (cdump); - - /* no new line here! */ - if (cstring_length (cdump) > 0) - { - check (fputs (cstring_toCharsSafe (cdump), fout) != EOF); - } - - cstring_free (cdump); - neednl = TRUE; - } - else - { - cstring cdump = uentry_rawName (thisentry); - linelen += cstring_length (cdump); - fprintf (fout, "#%s", cstring_toCharsSafe (cdump)); - } - } + if (!uentry_hasRealName (thisentry)) + { + llassert (uentry_isGlobalMarker (thisentry)); + + if (neednl) + { + check (fputc ('\n', fout) == (int) '\n'); + } + + fprintf (fout, "*%d (GlobalMarker)\n", KGLOBALMARKER); + lastekind = KINVALID; + linelen = 0; + neednl = FALSE; + } + else + { + if (thisekind != lastekind) + { + if (neednl) + { + check (fputc ('\n', fout) == (int) '\n'); + } + + neednl = FALSE; + lastentry = uentry_undefined; + fprintf (fout, "*%d (%s)\n", ekind_toInt (thisekind), + cstring_toCharsSafe (ekind_capName (thisekind))); + lastekind = thisekind; + linelen = 0; + } + + /* + ** evans - 2001-02-18 - added the - 48 fudge factor... + ** extra characters dumped, but I haven't counded them carefully... + */ + + if (uentry_isInvalid (lastentry) || !uentry_equiv (lastentry, thisentry) + || (linelen > (MAX_DUMP_LINE_LENGTH - (2 * MAX_NAME_LENGTH) - 48))) + { + cstring cdump; + + DPRINTF (("Dumping entry: %d", i)); + cdump = message ("^%d %q", i, uentry_dump (thisentry)); + /* was: cdump = uentry_dump (thisentry)); */ + + lastentry = thisentry; + if (neednl) + { + check (fputc ('\n', fout) == (int) '\n'); + linelen = 0; + } + + linelen += cstring_length (cdump); + + /* no new line here! */ + if (cstring_length (cdump) > 0) + { + check (fputs (cstring_toCharsSafe (cdump), fout) != EOF); + } + + cstring_free (cdump); + neednl = TRUE; + } + else + { + cstring cdump = uentry_rawName (thisentry); + DPRINTF (("Raw name: %s", cdump)); + linelen += (cstring_length (cdump) + 1); + fprintf (fout, "#%s", cstring_toCharsSafe (cdump)); + } + } } if (neednl) { check (fputc ('\n', fout) == (int) '\n'); } + + lastekind = KINVALID; + + fprintf(fout, ";; Library constraints\n"); + + /*drl July 27 added this so that libraries without + buffer constraints would be handled correctly. + I'm trying to do this without breaking older libraries. + + Splint should still be able to handle libraries without this message. + */ + + + fprintf(fout, "start_Buffer_Constraints\n"); + + for (i = 0; i < utab->nentries; i++) + { + uentry thisentry = utab->entries[i]; + + if (uentry_isFunction (thisentry) ) + { + constraintList preconditions; + constraintList postconditions; + + preconditions = uentry_getFcnPreconditions (thisentry); + postconditions = uentry_getFcnPostconditions (thisentry); + + if ( constraintList_isDefined(preconditions) || + constraintList_isDefined(postconditions) ) + { + fprintf(fout,"%s\n", cstring_toCharsSafe (uentry_rawName(thisentry) ) ); + if (constraintList_isDefined(preconditions) ) + { + fprintf(fout,"pre:\n"); + constraintList_dump(preconditions, fout); + fprintf (fout, ";; end precondition constraints\n" ); + constraintList_free(preconditions); + } + else + { + fprintf(fout,"pre:EMPTY\n"); + } + if (constraintList_isDefined(postconditions) ) + { + fprintf(fout,"post:\n"); + constraintList_dump(postconditions, fout); + fprintf (fout, ";; end precondition constraints\n" ); + constraintList_free(postconditions); + } + else + { + fprintf(fout,"post:EMPTY\n"); + } + } + + } + } } + void usymtab_load (FILE *f) /*@globals utab, globtab@*/ /*@modifies utab, *f@*/ @@ -1608,37 +1882,92 @@ void usymtab_load (FILE *f) llassert (utab == globtab); llassert (utab->nentries == 0); - while (fgets (s, MAX_DUMP_LINE_LENGTH, f) != NULL + while (((s = reader_readLine (f, s, MAX_DUMP_LINE_LENGTH)) != NULL) && *s == ';') { - ; /* ignore ;-comments */ + /* ignore ; comments */ ; } - + while (s != NULL && *s != ';') { - + int index; + if (*s == '*') { + int ek; s++; - kind = ekind_fromInt (getInt (&s)); + ek = reader_getInt (&s); - goto nextiter; + if (ek == KGLOBALMARKER) + { + uentry lue = uentry_makeGlobalMarker (); + DPRINTF (("Adding global marker: %s", uentry_unparseFull (lue))); + usymtab_addEntryAlways (utab, lue); + kind = KINVALID; + goto nextiter; + } + else + { + kind = ekind_fromInt (ek); + goto nextiter; + } } if (*s == '$') { llfatalerror (cstring_makeLiteral - ("Library is in obsolete format. Use lclint +whichlib " + ("Library is in obsolete format. Use splint +whichlib " "to see which library is being loaded.")); } + if (reader_optCheckChar (&s, '^')) + { + index = reader_getInt (&s); + } + else + { + index = -1; + } + + llassert (kind != KINVALID); ue = uentry_undump (kind, loc, &s); - DPRINTF (("Load: %s", uentry_unparseFull (ue))); + + llassert (utab->nentries == index || index == -1); if (uentry_isValid (ue)) { - ue = usymtab_addEntryBase (utab, ue); + int lastindex = utab->nentries; + ue = usymtab_addEntryAlways (utab, ue); + + +# if 0 + if (uentry_isConstant (ue)) /*@i23! isPreProcessorMacro */ + { + cstring uname = uentry_getName (ue); + + /* Also check its a macro... */ + DPRINTF (("Installing: %s", uname)); + + cpphash_installMacro + (mstring_copy (cstring_toCharsSafe (uname)), + cstring_length (uname), + cpplib_createDefinition (message ("%s 255", uname), + loc, + FALSE, FALSE).defn, + cpphash_hashCode (cstring_toCharsSafe (uname), + cstring_length (uname), + CPP_HASHSIZE)); + + DPRINTF (("After install: %s", uname)); + } +# endif + + if (utab->nentries != lastindex + 1) + { + DPRINTF (("No add: %s", uentry_unparseFull (ue))); + BADBRANCH; + } /*@-branchstate@*/ } /*@=branchstate@*/ @@ -1649,27 +1978,107 @@ void usymtab_load (FILE *f) while (*(s++) == '#') { - cstring name = cstring_fromCharsO (getWord (&s)); - uentry nue = uentry_nameCopy (name, ue); - - DPRINTF (("Name copy: %s", uentry_unparseFull (nue))); - usymtab_addEntryBase (utab, nue); + cstring name = cstring_fromCharsO (reader_getWord (&s)); + uentry nue = uentry_nameCopy (name, ue); + /* + DPRINTF (("Name copy: %s", uentry_unparseFull (nue))); + BADBRANCH; + */ + + usymtab_addEntryAlways (utab, nue); + } + + while ((c = *s) != '\0' && (c !='\n')) + { + if (c != ' ' || c != '\t') + { + llbuglit ("Junk in load file"); + } + + s++; + } + + nextiter: + { + s = reader_readLine (f, os, MAX_DUMP_LINE_LENGTH); + } + } + + /*DRL added 6/21/01 + to handle reading of buffer overflow related constraints + */ + while (fgets (s, MAX_DUMP_LINE_LENGTH, f) != NULL + && *s == ';') + { + ; /* ignore ;-comments */ + } + + /*drl July 27 added this so that libraries without + buffer constraints would be handled correctly. + I'm trying to do this without breaking older libraries*/ + + /*check for "optional" start buffer constraints message*/ + + if (mstring_equalPrefix (s, "start_Buffer_Constraints")) + { + (void) fgets (s, MAX_DUMP_LINE_LENGTH, f); + } + + while (s != NULL && *s != ';') + { + constraintList preconditions; + constraintList postconditions; + + cstring name = cstring_fromChars(reader_getWord(&s) ); + cstring temp; + ue = usymtab_lookup ( name ); + + cstring_free(name); + + preconditions = constraintList_undefined; + postconditions = constraintList_undefined; + + if (!uentry_isValid(ue) ) + { + llfatalbug ((message("Invalid uentry for %s library file may be corrupted", cstring_fromChars(s) ) )); } + s = fgets (os, MAX_DUMP_LINE_LENGTH, f); - while ((c = *s) != '\0' && (c !='\n')) + temp = cstring_fromChars (reader_getWord(&s) ); + + if (cstring_compareLit (temp,"pre:") == 0 ) { - if (c != ' ' || c != '\t') - { - llbuglit ("Junk in load file"); - } + preconditions = constraintList_undump (f); + } + else + { + if (cstring_compareLit (temp,"pre:EMPTY") != 0 ) + llfatalbug ((message("Error reading library file pre:EMPTY expected but got %s", temp ) )); + } + + cstring_free(temp); + + s = fgets (os, MAX_DUMP_LINE_LENGTH, f); - s++; + temp = cstring_fromChars(reader_getWord(&s) ); + if (cstring_compareLit (temp, "post:") == 0 ) + { + postconditions = constraintList_undump (f); + } + else + { + if (cstring_compareLit (temp, "post:EMPTY") != 0 ) + llfatalbug ((message("Error reading library file post:EMPTY expected but got %s", temp ) )); } + + cstring_free (temp); - nextiter: + uentry_setPreconditions (ue, functionConstraint_createBufferConstraint (preconditions)); + uentry_setPostconditions (ue, functionConstraint_createBufferConstraint (postconditions)); + s = fgets (os, MAX_DUMP_LINE_LENGTH, f); } - + dbgload = FALSE; sfree (os); } @@ -1692,8 +2101,8 @@ usymtab_enterFile () { if (sRef_hasDerived (uentry_getSref (ue))) { - fprintf (g_msgstream, "Derived Global: %s\n", uentry_unparse (ue)); - fprintf (g_msgstream, "sRef: %s\n", sRef_unparseFull (ue->sref)); + fprintf (g_warningstream, "Derived Global: %s\n", uentry_unparse (ue)); + fprintf (g_warningstream, "sRef: %s\n", sRef_unparseFull (ue->sref)); } } end_usymtab_entries ; @@ -1750,7 +2159,6 @@ usymtab_handleParams (void) usymtab ptab = utab->env; uentry fcn = context_getHeader (); - usymtab_entries (ptab, param) { uentry ue; @@ -1759,147 +2167,192 @@ usymtab_handleParams (void) { sRef uref; sRef pref = uentry_getSref (param); - - llassertprint (uentry_isAnyParam (param), - ("not param: %s", - uentry_unparseFull (param))); - - - ue = uentry_makeVariable (fixParamName (uentry_rawName (param)), - uentry_getType (param), - fileloc_copy (uentry_whereDeclared (param)), - FALSE); - uentry_copyState (ue, param); - uentry_setRefParam (ue); + /* Could be a global. */ - ue = usymtab_supEntrySrefReturn (ue); - - /* must be after supercede! */ - - if (!sRef_stateKnown (pref)) - { - uentry_setDefState (ue, SS_DEFINED); - uentry_setDefState (param, SS_DEFINED); - } - else - { - if (sRef_isStateSpecial (pref)) + if (uentry_isAnyParam (param)) + { + ue = uentry_makeVariable (fixParamName (uentry_rawName (param)), + uentry_getType (param), + fileloc_copy (uentry_whereDeclared (param)), + FALSE); + + uentry_copyState (ue, param); + uentry_setRefParam (ue); + + ue = usymtab_supEntrySrefReturn (ue); + + /* must be after supercede! */ + + if (!sRef_stateKnown (pref)) { - uentry_setDefState (ue, SS_ALLOCATED); + uentry_setDefState (ue, SS_DEFINED); + uentry_setDefState (param, SS_DEFINED); } else { - uentry_setDefState (ue, sRef_getDefState (pref)); - } - } - - uref = uentry_getSref (ue); - - if (sRef_isStack (uref)) - { - alkind pkind = sRef_getAliasKind (pref); - - if (alkind_isKnown (pkind) && !alkind_isLocal (pkind) - && !alkind_isStack (pkind)) - { - sRef_setAliasKind (uref, pkind, fileloc_undefined); - sRef_setOrigAliasKind (uref, pkind); + if (sRef_isStateSpecial (pref)) + { + uentry_setDefState (ue, SS_SPECIAL); /* ALLOCATED); */ + /* evans 2002-01-01: should be unnecessary, the pre clauses + ** set the state if necessary. + */ + } + else + { + uentry_setDefState (ue, sRef_getDefState (pref)); + } } - else + + uref = uentry_getSref (ue); + + if (sRef_isStack (uref)) { - sRef_setAliasKind (uref, AK_IMPTEMP, fileloc_undefined); - sRef_setOrigAliasKind (uref, AK_IMPTEMP); - - if (uentry_isOut (param)) + alkind pkind = sRef_getAliasKind (pref); + + if (alkind_isKnown (pkind) && !alkind_isLocal (pkind) + && !alkind_isStack (pkind)) { - ; + sRef_setAliasKind (uref, pkind, fileloc_undefined); + sRef_setOrigAliasKind (uref, pkind); } else { - sRef_setDefined (uref, fileloc_undefined); + sRef_setAliasKind (uref, AK_IMPTEMP, fileloc_undefined); + sRef_setOrigAliasKind (uref, AK_IMPTEMP); + + if (uentry_isOut (param)) + { + ; + } + else + { + sRef_setDefined (uref, fileloc_undefined); + } } + } + + usymtab_addMustAlias (uref, pref); + + if (!(uentry_isOnly (param) || uentry_isUnique (param))) + { + /* + ** This is needed for detecting possibly aliased parameters. + */ - } - - usymtab_addMustAlias (uref, pref); - - if (!(uentry_isOnly (param) || uentry_isUnique (param))) - { - sRef s = sRef_makeExternal (uref); - - usymtab_addMustAlias (uref, s); - } - - if (sRef_isKillRef (pref)) - { - sRef_setAliasKind (uref, AK_NEWREF, fileloc_undefined); - sRef_setOrigAliasKind (uref, AK_KILLREF); - } - else if (sRef_isRefCounted (uref)) - { - sRef_setOrigAliasKind (uref, AK_REFCOUNTED); + sRef s = sRef_makeExternal (uref); + usymtab_addMustAlias (uref, s); + } + + if (sRef_isKillRef (pref)) + { + sRef_setAliasKind (uref, AK_NEWREF, fileloc_undefined); + sRef_setOrigAliasKind (uref, AK_KILLREF); + } + else if (sRef_isRefCounted (uref)) + { + sRef_setOrigAliasKind (uref, AK_REFCOUNTED); + } + else + { + /* was AK_UNIQUE */ + sRef_setOrigAliasKind (uref, AK_LOCAL); + } } else { - /* was AK_UNIQUE */ - sRef_setOrigAliasKind (uref, AK_LOCAL); } } - else - { - } } end_usymtab_entries; - - - if (uentry_hasSpecialClauses (fcn)) + + + if (uentry_hasStateClauseList (fcn)) { - specialClauses clauses = uentry_getSpecialClauses (fcn); - - specialClauses_preElements (clauses, cl) + stateClauseList clauses = uentry_getStateClauseList (fcn); + + stateClauseList_preElements (clauses, cl) { - sRefSet refs = specialClause_getRefs (cl); - sRefMod modf = specialClause_getEntryFunction (cl); - + fileloc loc = stateClause_loc (cl); + sRefSet osrs = sRefSet_undefined; + sRefSet srs; + + if (stateClause_isGlobal (cl)) + { + DPRINTF (("Global Marker: %s", + sRef_unparseFull (usymtab_lookupGlobalMarker ()))); + llassert (sRef_isGlobalMarker (usymtab_lookupGlobalMarker ())); + srs = sRefSet_single (usymtab_lookupGlobalMarker ()); + osrs = srs; + } + else + { + srs = stateClause_getRefs (cl); + } - sRefSet_elements (refs, el) + sRefSet_elements (srs, el) { sRef base = sRef_getRootBase (el); - + sRef sb = sRef_updateSref (el); + if (sRef_isResult (base)) { ; /* nothing to do before */ } - else if (sRef_isParam (base)) + else if (sRef_isParam (base) || sRef_isGlobalMarker (base)) { - if (modf != NULL) + if (stateClause_setsMetaState (cl)) { - sRef sb = sRef_updateSref (el); - sRefSet aliases = usymtab_allAliases (sb); + /* copied from exprNode.c:3040 */ + qual ql = stateClause_getMetaQual (cl); + annotationInfo ainfo = qual_getAnnotationInfo (ql); + metaStateInfo minfo = annotationInfo_getState (ainfo); + cstring key = metaStateInfo_getName (minfo); + int mvalue = annotationInfo_getValue (ainfo); - modf (sb, fileloc_undefined); - - sRefSet_elements (aliases, sr) + DPRINTF (("Sets meta state! %s", stateClause_unparse (cl))); + + if (sRef_isResult (base)) { - modf (sr, fileloc_undefined); - } end_sRefSet_elements ; - - sRefSet_free (aliases); + BADBRANCH; + } + else + { + sRef_setMetaStateValueComplete (sb, key, mvalue, loc); + } + } + else + { + sRefMod modf = stateClause_getEntryFunction (cl); + + if (modf != NULL) + { + sRefSet aliases = usymtab_allAliases (sb); + + modf (sb, loc); + + sRefSet_elements (aliases, sr) + { + modf (sr, loc); + } end_sRefSet_elements ; + + sRefSet_free (aliases); + } } } else { if (sRef_isValid (base)) { + DPRINTF (("Base: %s", sRef_unparseFull (base))); BADBRANCH; } } } end_sRefSet_elements ; - } end_specialClauses_preElements ; + } end_stateClauseList_preElements ; } - } - +} + void usymtab_enterFunctionScope (uentry fcn) /*@globals utab, filetab, globtab@*/ @@ -1907,11 +2360,13 @@ usymtab_enterFunctionScope (uentry fcn) { usymtab t = usymtab_create (US_NORMAL, utab, TRUE); + DPRINTF (("Enter function: %s", uentry_unparse (fcn))); + if (utab->lexlevel != fileScope) { if (utab->lexlevel > fileScope) { - llparseerror (cstring_makeLiteral ("New function scope inside function.")); + llparseerror (cstring_makeLiteral ("New function scope inside function")); while (utab->lexlevel > fileScope) { @@ -1926,15 +2381,22 @@ usymtab_enterFunctionScope (uentry fcn) } /*@-branchstate@*/ } /*@=branchstate@*/ + utab = t; + + DPRINTF (("Globs: %s", globSet_unparse (uentry_getGlobs (fcn)))); + globSet_allElements (uentry_getGlobs (fcn), el) { + DPRINTF (("Here we go: %s", sRef_unparseFull (el))); if (sRef_isUndefGlob (el)) { int index = sRef_getScopeIndex (el); sRef sr = sRef_updateSref (el); fileloc loc = uentry_whereEarliest (fcn); - + + DPRINTF (("update: %s", sRef_unparseFull (sr))); + DPRINTF (("Undef!")); if (sRef_isFileStatic (el)) { ctype ct = sRef_getType (el); @@ -1984,11 +2446,22 @@ usymtab_enterFunctionScope (uentry fcn) } else { - /* defined */ ; + /* + sRef sr = sRef_updateSref (el); + fileloc loc = uentry_whereEarliest (fcn); + + sRef_setDefined (sr, loc); + */ + + /* defined */ + /* shouldn't need to do anything! */ } } end_globSet_allElements; - utab = t; + DPRINTF (("Globs after: %s", globSet_unparse (uentry_getGlobs (fcn)))); +# ifdef DEBUGSPLINT + usymtab_checkAllValid (); +# endif } static void @@ -2006,7 +2479,7 @@ usymtab_switchBranch (/*@unused@*/ exprNode s) usymtab t = usymtab_create (US_SWITCH, utab, FALSE); t->aliases = aliasTable_copy (utab->aliases); - utab = t; + utab = t; } void @@ -2025,11 +2498,11 @@ usymtab_trueBranch (/*@only@*/ guardSet guards) guardSet_free (t->guards); t->guards = guards; - - aliasTable_free (t->aliases); + + aliasTable_free (t->aliases); t->aliases = aliasTable_copy (utab->aliases); - utab = t; + utab = t; } /* @@ -2040,7 +2513,7 @@ usymtab_trueBranch (/*@only@*/ guardSet guards) */ void -usymtab_popTrueBranch (exprNode pred, exprNode expr, clause cl) +usymtab_popTrueBranch (exprNode pred, exprNode expr, clause cl) /*@modifies utab@*/ { /* ** add a false branch @@ -2048,8 +2521,17 @@ usymtab_popTrueBranch (exprNode pred, exprNode expr, clause cl) ** it is better to only maintain one version of the code) */ - usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred))); - usymtab_popBranches (pred, expr, exprNode_undefined, TRUE, cl); + if (utab->kind != US_TBRANCH + && context_inIterDef ()) + { + usymtab_exitScope (expr); + } + else + { + DPRINTF (("pop true branch..")); + usymtab_altBranch (guardSet_invert (exprNode_getGuards (pred))); + usymtab_popBranches (pred, expr, exprNode_undefined, TRUE, cl); + } } void @@ -2140,6 +2622,8 @@ usymtab_newCase (/*@unused@*/ exprNode pred, exprNode last) bool mustReturn = usymtab_mustEscape (utab); usymtab stab = utab; + DPRINTF (("New case!")); + /* ** Find last case (or outer switch) */ @@ -2149,9 +2633,7 @@ usymtab_newCase (/*@unused@*/ exprNode pred, exprNode last) stab = stab->env; llassert (stab != GLOBAL_ENV); } - - /* ??? */ - + while (stab->kind == US_CBRANCH) { stab = stab->env; @@ -2217,7 +2699,7 @@ usymtab_popAndBranch (exprNode pred, /*@unused@*/ exprNode expr) usymtab otab= utab; int i = 0; - llassert (utab->kind == US_TBRANCH); + llassert (utab->kind == US_TBRANCH); /* ** merge each entry in table with its original @@ -2441,9 +2923,7 @@ updateNullState (sRef el, /*@notnull@*/ usymtab ttab, /*@notnull@*/ usymtab ftab, bool trueGuard) { sRef base = sRef_getRootBase (el); - int level = sRef_lexLevel (base); - - + int level = sRef_lexLevel (base); if (sRef_isCvar (base)) { @@ -2463,13 +2943,17 @@ updateNullState (sRef el, /*@notnull@*/ usymtab ttab, if (!guardSet_isGuarded (ttab->guards, el) && !sRef_isNotNull (sr)) { + DPRINTF (("Here! %s / %s", + sRef_unparseFull (sr), + sRef_unparseFull (el))); sRef_setDerivNullState (sr, el, NS_DEFNULL); - } + } } } else { - } + ; + } ue = usymtab_getRefTab (ftab, level, index); @@ -2477,7 +2961,6 @@ updateNullState (sRef el, /*@notnull@*/ usymtab ttab, { sRef sr = uentry_getSref (ue); - if (!trueGuard) /* yikes! forgot the ! */ { sRef_setDerivNullState (sr, el, NS_NOTNULL); @@ -2489,16 +2972,15 @@ updateNullState (sRef el, /*@notnull@*/ usymtab ttab, && !sRef_isNotNull (sr)) { sRef_setDerivNullState (sr, el, NS_DEFNULL); - } + } } } else { - } - - } - - } + ; + } + } +} void usymtab_popBranches (exprNode pred, exprNode tbranch, exprNode fbranch, @@ -2516,7 +2998,11 @@ usymtab_popBranches (exprNode pred, exprNode tbranch, exprNode fbranch, sRefSet fguards = guardSet_getFalseGuards (guards); bool mustReturnT = exprNode_mustEscape (tbranch); bool mustReturnF = exprNode_mustEscape (fbranch); - + + DPRINTF (("Pop branches: %s [mustreturn: %s/%s]", exprNode_unparse (pred), + bool_unparse (mustReturnT), + bool_unparse (mustReturnF))); + if (exprNode_isDefined (fbranch)) { loc = exprNode_loc (fbranch); @@ -2563,23 +3049,28 @@ usymtab_popBranches (exprNode pred, exprNode tbranch, exprNode fbranch, ** ** if an entry is in one table, merge it with the original. */ - + + DPRINTF (("ftab: %d", ftab->nentries)); + for (i = 0; i < ftab->nentries; i++) { uentry fthis = ftab->entries[i]; uentry old = usymtab_lookupAux (env, uentry_rawName (fthis)); int tindex = usymtab_getIndex (ttab, uentry_rawName (fthis)); + DPRINTF (("Entry: %s / %s", uentry_unparseFull (fthis), uentry_unparseFull (old))); + if (uentry_isUndefined (old)) { /* possible entry was added as an undefined id */ + DPRINTF (("Undefined! %s", uentry_rawName (fthis))); continue; } if (tindex != NOT_FOUND) { uentry tthis = ttab->entries[tindex]; - + /* note that is this is in a nested branch, it may create a "new" old entry. */ @@ -2587,7 +3078,6 @@ usymtab_popBranches (exprNode pred, exprNode tbranch, exprNode fbranch, { if (!mustReturnT) { - uentry_mergeState (fthis, tthis, loc, mustReturnT, FALSE, FALSE, cl); } @@ -2621,12 +3111,20 @@ usymtab_popBranches (exprNode pred, exprNode tbranch, exprNode fbranch, { uentry current = ttab->entries[i]; + DPRINTF (("ttab: %s", uentry_unparseFull (current))); + if (!uentry_isUndefined (current)) { uentry old = usymtab_lookupAux (env, uentry_rawName (current)); - llassertprint (!uentry_isUndefined (old), ("name: <%s>", - uentry_rawName (current))); + DPRINTF (("Old: %s", uentry_unparseFull (old))); + + if (uentry_isUndefined (old)) + { + llcontbug (message ("Undefined entry: %s", uentry_rawName (current))); + continue; + } + if (mustReturnF) { uentry_mergeUses (current, old); @@ -2635,7 +3133,7 @@ usymtab_popBranches (exprNode pred, exprNode tbranch, exprNode fbranch, else { /* - ** assumes false branch is a fall-through if + ** Assumes false branch is a fall-through if ** fbranch is not defined. This is true, unless ** where was some greivous error in processing ** the else branch of an if-then, in which case @@ -2645,9 +3143,10 @@ usymtab_popBranches (exprNode pred, exprNode tbranch, exprNode fbranch, uentry_mergeState (old, current, loc, mustReturnT, FALSE, isOpt, cl); } + + DPRINTF (("==> %s", uentry_unparseFull (old))); } } - /* ** Plain levelUnion doesn't work, since we need to use the sRef's in env->aliases @@ -2663,6 +3162,8 @@ usymtab_popBranches (exprNode pred, exprNode tbranch, exprNode fbranch, ftab->aliases, env->lexlevel); aliasTable_fixSrefs (env->aliases); + + DPRINTF (("Aliases: %s", aliasTable_unparse (env->aliases))); /* exit true and false scopes */ usymtab_quietPlainExitScope (); @@ -2699,9 +3200,11 @@ void usymtab_altBranch (/*@only@*/ guardSet guards) /*@modifies utab@*/ { - usymtab t = usymtab_create (US_FBRANCH, utab, FALSE); + usymtab t; usymtab parent = utab->env; + t = usymtab_create (US_FBRANCH, utab, FALSE); + /* ** If we are in a case, need to close it. The C syntax ** is very liberal, so this kludge is necessary. @@ -2710,15 +3213,16 @@ usymtab_altBranch (/*@only@*/ guardSet guards) usymtab_fixCases (); DPRINTF (("Current kind: %s", usymtab_unparseStack ())); + llassert (utab->kind == US_TBRANCH); llassert (parent != GLOBAL_ENV); - + guardSet_free (t->guards); t->guards = guards; - + aliasTable_free (t->aliases); t->aliases = aliasTable_copy (parent->aliases); - + utab = t; } @@ -2762,7 +3266,7 @@ usymtab_allDefined (void) { fileloc dloc = uentry_whereDeclared (e); - if (fileloc_isLib (dloc)) + if (fileloc_isLib (dloc) || fileloc_isXHFile (dloc)) { ; } @@ -2778,6 +3282,7 @@ usymtab_allDefined (void) ekind_capName (uentry_getKind (e)), uentry_getName (e)), dloc); + DPRINTF (("decl: %s", uentry_unparseFull (e))); } } } @@ -2841,6 +3346,7 @@ void usymtab_exportHeader (void) if (fileloc_isDefined (fwhere) && !fileloc_isHeader (fwhere) + && !fileloc_isXHFile (fwhere) && !(fileloc_isSpecialFile (fwhere) && !context_getFlag (FLG_UNUSEDSPECIAL))) { @@ -2891,12 +3397,10 @@ void usymtab_exportLocal (void) /*@globals utab@*/ { int i; - for (i = 0; i < utab->nentries; i++) { uentry ce = utab->entries[i]; - if (!uentry_isDatatype (ce) && !uentry_isAnyTag (ce) && !uentry_isEitherConstant (ce) @@ -3124,7 +3628,7 @@ usymtab_allUsed (void) ; /* no errors */ } } /* unused */ - else if (uentry_isDatatype (ce) || uentry_isAnyTag (ce)) + else if ((uentry_isDatatype (ce) || uentry_isAnyTag (ce))) { /* check all fields */ ctype ct = uentry_getRealType (ce); @@ -3134,7 +3638,6 @@ usymtab_allUsed (void) ct = ctype_getBaseType (ct); } - if (ctype_isSU (ct)) { uentryList fields = ctype_getFields (ct); @@ -3156,6 +3659,13 @@ usymtab_allUsed (void) } else { + /* + ** evans 2001-06-08 + ** Can't report these errors for unnamed structs. + ** No way to tell when there are multiple consistent + ** unnamed structure types. (Could go through table + ** and mark them all unused...) + hasError |= optgenerror (FLG_FIELDUNUSED, message ("Field %q of unnamed %s declared but not used", @@ -3163,6 +3673,8 @@ usymtab_allUsed (void) cstring_makeLiteralTemp (ctype_isStruct (ct) ? "structure" : "union")), uentry_whereEarliest (field)); + + */ } uentry_setUsed (field, fileloc_undefined); @@ -3199,9 +3711,17 @@ checkGlobalReturn (uentry glob, sRef orig) { sRef sr = uentry_getSref (glob); - + DPRINTF (("Check global return: %s / orig: %s / sr: %s", + uentry_unparseFull (glob), + sRef_unparseFull (orig), + sRef_unparseFull (sr))); + + DPRINTF (("Is killed: %s", bool_unparse (sRef_isKilledGlob (orig)))); + if (context_getFlag (FLG_GLOBSTATE)) { + DPRINTF (("Is killed: %s", sRef_unparseFull (orig))); + if (sRef_isKilledGlob (orig)) { if (sRef_isStateUndefined (sr) @@ -3214,23 +3734,26 @@ checkGlobalReturn (uentry glob, sRef orig) else { ctype ct = ctype_realType (uentry_getType (glob)); + + DPRINTF (("Check global destroyed: %s", uentry_unparseFull (glob))); if (ctype_isVisiblySharable (ct)) { if (optgenerror (FLG_GLOBSTATE, message - ("Killed global %q not released before return", - uentry_getName (glob)), + ("Killed global %q (type %s) not released before return", + uentry_getName (glob), + ctype_unparse (ct)), g_currentloc)) { sRef_showStateInfo (sr); - } + } } else { - sRef_protectDerivs (); - (void) checkGlobalDestroyed (sr, g_currentloc); + sRef_protectDerivs (); + (void) transferChecks_globalDestroyed (sr, g_currentloc); sRef_clearProtectDerivs (); } } @@ -3250,22 +3773,32 @@ checkGlobalReturn (uentry glob, sRef orig) } else { - if (sRef_isDead (sr)) + if (sRef_isDead (sr) || sRef_isKept (sr)) { if (optgenerror (FLG_GLOBSTATE, message ("Function returns with global %q " - "referencing released storage", - uentry_getName (glob)), + "referencing %s storage", + uentry_getName (glob), + cstring_makeLiteralTemp (sRef_isDead (sr) ? "released" : "kept")), g_currentloc)) { - sRef_showStateInfo (sr); + if (sRef_isKept (sr)) + { + sRef_showAliasInfo (sr); + } + else + { + sRef_showStateInfo (sr); + } + sRef_setDefState (sr, SS_UNKNOWN, fileloc_undefined); } } - if (ctype_isRealPointer (uentry_getType (glob)) && - sRef_possiblyNull (sr) && !uentry_possiblyNull (glob)) + if (ctype_isRealPointer (uentry_getType (glob)) + && sRef_possiblyNull (sr) + && !uentry_possiblyNull (glob)) { if (optgenerror (FLG_GLOBSTATE, @@ -3279,7 +3812,8 @@ checkGlobalReturn (uentry glob, sRef orig) } else { - checkGlobReturn (glob); + DPRINTF (("Check transfer: %s", uentry_unparseFull (glob))); + transferChecks_globalReturn (glob); } } } @@ -3293,7 +3827,7 @@ checkGlobalReturn (uentry glob, sRef orig) void usymtab_checkFinalScope (bool isReturn) /*@globals utab@*/ { - bool mustFree = context_getFlag (FLG_MUSTFREE); + bool mustFree = context_getFlag (FLG_MUSTFREEONLY) || context_getFlag (FLG_MUSTFREEFRESH); /*@i423 remove this mustFree */ bool mustDefine = context_getFlag (FLG_MUSTDEFINE); /* bool mustNotAlias = context_getFlag (FLG_MUSTNOTALIAS); */ sRefSet checked = sRefSet_new (); @@ -3311,17 +3845,116 @@ void usymtab_checkFinalScope (bool isReturn) uentry ce = stab->entries[i]; sRef sr = uentry_getSref (ce); sRef rb = sRef_getRootBase (sr); + valueTable tvalues; + + /* + ** Shouldn't check if shadow checked in deeper scope: + */ + + if (stab != utab) + { + uentry oue = usymtab_lookupQuietNoAlt (utab, uentry_observeRealName (ce)); + if (!uentry_sameObject (ce, oue)) + { + DPRINTF (("Skipping outer entry: %s / %s", uentry_unparseFull (ce), + uentry_unparseFull (oue))); + /*@i32 what if it is one an alternate branch? */ + /*@innercontinue@*/ continue; + } + } + + DPRINTF (("Here check final scope: %s", uentry_unparseFull (ce))); + if (ctype_isFunction (uentry_getType (ce))) { /*@innercontinue@*/ continue; } - if (mustFree) + if (uentry_isAnyParam (ce) + || uentry_isRefParam (ce) + || sRef_isFileOrGlobalScope (rb)) + { + /* Don't do the loseref check...but should check state! */ + DPRINTF (("Skipping check 1")); + } + else if (sRef_isDefinitelyNull (sr) + || usymtab_isDefinitelyNull (sr)) + { + /* + ** No state reference errors for definitely null references. + */ + + DPRINTF (("Skipping check 2")); + } + else { - DPRINTF (("Check entry: %s", uentry_unparseFull (ce))); + DPRINTF (("Lose ref: %s / %s", uentry_unparse (ce), + sRef_unparseFull (sr))); + + tvalues = sRef_getValueTable (sr); + + valueTable_elements (tvalues, fkey, fval) { + metaStateInfo minfo; + cstring msg = cstring_undefined; + int nval; + + minfo = context_lookupMetaStateInfo (fkey); + llassert (metaStateInfo_isDefined (minfo)); + + if (stateValue_isError (fval) + || sRef_isStateUndefined (sr)) /* No errors for undefined state */ + { + DPRINTF (("Skipping check 3")); + } + else + { + DPRINTF (("Check: %s / %s / %s", fkey, + metaStateInfo_unparse (minfo), + stateValue_unparse (fval))); + + minfo = context_lookupMetaStateInfo (fkey); + + nval = stateCombinationTable_lookupLoseReference + (metaStateInfo_getTransferTable (minfo), + stateValue_getValue (fval), &msg); + + if (cstring_isDefined (msg)) + { + /*@i32 print extra info for assignments@*/ + DPRINTF (("From: %s", sRef_unparseFull (sr))); + DPRINTF (("Null? %s / %s", + bool_unparse (sRef_isDefinitelyNull (sr)), + bool_unparse (usymtab_isGuarded (sr)))); + + if (optgenerror + (FLG_STATETRANSFER, + message + ("%s loses reference %q in invalid state %q (%s)", + cstring_makeLiteralTemp (isReturn ? "Return" : "Scope exit"), + uentry_getName (ce), + stateValue_unparseValue (fval, minfo), + msg), + g_currentloc)) + { + stateValue_show (fval, minfo); + } + else + { + DPRINTF (("Suppressed transfer error: %s", msg)); + } + } + } + } end_valueTable_elements; + } + + DPRINTF (("Here 1")); - if (!sRefSet_member (checked, sr) && !sRef_isGlobal (rb)) + if (mustFree) + { + DPRINTF (("Check mustfree entry: %s", uentry_unparseFull (ce))); + + if (!sRefSet_member (checked, sr) && !sRef_isFileOrGlobalScope (rb)) { if (ctype_isRealSU (uentry_getType (ce)) && !uentry_isAnyParam (ce) @@ -3331,11 +3964,10 @@ void usymtab_checkFinalScope (bool isReturn) && !sRef_isOwned (sr)) { sRefSet als = usymtab_allAliases (sr); - if (sRefSet_isEmpty (als)) { - checkLocalDestroyed (sr, g_currentloc); + transferChecks_localDestroyed (sr, g_currentloc); } else { @@ -3351,10 +3983,12 @@ void usymtab_checkFinalScope (bool isReturn) || sRef_isKeep (sr) || sRef_isOwned (sr)) && !sRef_isDead (sr)) && (!sRef_definitelyNull (sr)) - && (!usymtab_isProbableNull (sr))))) + && (!usymtab_isDefinitelyNull (sr))))) { bool hasError = TRUE; + DPRINTF (("Checking: %s", sRef_unparseFull (sr))); + /* ** If its a scope exit, check if there is an alias. ** If so, make it only. If not, there is an error. @@ -3362,8 +3996,9 @@ void usymtab_checkFinalScope (bool isReturn) if (!isReturn) { - if (canLoseReference (sr, g_currentloc)) + if (transferChecks_canLoseReference (sr, g_currentloc)) { + DPRINTF (("Can lose!")); hasError = FALSE; } } @@ -3375,7 +4010,7 @@ void usymtab_checkFinalScope (bool isReturn) sRef ar = sRef_getAliasInfoRef (sr); if (optgenerror - (FLG_MUSTFREE, + (sRef_isFresh (ar) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY, message ("Last reference %q to %s storage %qnot %q before %q", sRef_unparse (sr), @@ -3393,7 +4028,7 @@ void usymtab_checkFinalScope (bool isReturn) else if (sRef_isNewRef (sr)) { if (optgenerror - (FLG_MUSTFREE, + (sRef_isFresh (sr) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY, message ("%q %q not released before %q", cstring_makeLiteral @@ -3411,12 +4046,14 @@ void usymtab_checkFinalScope (bool isReturn) { if (ctype_isRealSU (sRef_getType (sr))) { - checkStructDestroyed (sr, g_currentloc); + transferChecks_structDestroyed (sr, g_currentloc); } else { + DPRINTF (("Here we are: %s", sRef_unparseFull (sr))); + if (optgenerror - (FLG_MUSTFREE, + (sRef_isFresh (sr) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY, message ("%s storage %q not %q before %q", alkind_capName (sRef_getAliasKind (sr)), @@ -3428,6 +4065,7 @@ void usymtab_checkFinalScope (bool isReturn) g_currentloc)) { sRef_showAliasInfo (sr); + DPRINTF (("Storage: %s", sRef_unparseFull (sr))); } } } @@ -3438,59 +4076,59 @@ void usymtab_checkFinalScope (bool isReturn) ; } } - else if (mustDefine && uentry_isOut (ce)) - { - if (!ynm_toBoolStrict (sRef_isReadable (sr))) - { - voptgenerror - (FLG_MUSTDEFINE, - message ("Out storage %q not defined before %q", - uentry_getName (ce), - cstring_makeLiteral - (isReturn ? "return" : "scope exit")), - g_currentloc); - - /* uentry_showWhereDeclared (ce); */ - } - } - else + } + + if (mustDefine && uentry_isOut (ce)) + { + /* No error if its dead (either only or error already reported */ + if (!sRef_isReallyDefined (sr) && !sRef_isDead (sr)) { - ; + voptgenerror + (FLG_MUSTDEFINE, + message ("Out storage %q not defined before %q", + uentry_getName (ce), + cstring_makeLiteral + (isReturn ? "return" : "scope exit")), + g_currentloc); + + DPRINTF (("sr: %s", sRef_unparseFull (sr))); } + } + + /* + ** also check state is okay + */ + + if (usymtab_lexicalLevel () > functionScope + && uentry_isVariable (ce) + && (sRef_isLocalVar (sr) + && (sRef_isDependent (sr) || sRef_isLocalState (sr)))) + { + sRefSet ab = usymtab_aliasedBy (sr); - /* - ** also check state is okay - */ - - if (usymtab_lexicalLevel () > functionScope - && uentry_isVariable (ce) - && (sRef_isLocalVar (sr) - && (sRef_isDependent (sr) || sRef_isLocalState (sr)))) + /* should do something more efficient here */ + + if (sRefSet_isEmpty (ab)) { - sRefSet ab = usymtab_aliasedBy (sr); - - /* should do something more efficient here */ - - if (sRefSet_isEmpty (ab)) - { - /* and no local ref */ - checkLoseRef (ce); - } - else - { - ; - } - - sRefSet_free (ab); + /* and no local ref */ + DPRINTF (("Check lose ref: %s", uentry_unparseFull (ce))); + transferChecks_loseReference (ce); } - else + else { ; } - checked = sRefSet_insert (checked, sr); + sRefSet_free (ab); + } + else + { + ; } + + checked = sRefSet_insert (checked, sr); } + llassert (usymtab_isDefined (stab->env)); if (usymtab_isBranch (stab)) @@ -3501,12 +4139,12 @@ void usymtab_checkFinalScope (bool isReturn) { stab = stab->env; } - + llassert (stab != usymtab_undefined); } while (isReturn && (stab->lexlevel >= paramsScope)); - - sRefSet_free (checked); - + + sRefSet_free (checked); + /* ** for returns: ** all globals are appropriately defined @@ -3520,7 +4158,6 @@ void usymtab_checkFinalScope (bool isReturn) uentryList params = context_getParams (); globSet uglobs = context_getUsedGlobs (); globSet sglobs = context_getGlobs (); - if (isReturn && context_maybeSet (FLG_GLOBALIAS)) { @@ -3528,68 +4165,129 @@ void usymtab_checkFinalScope (bool isReturn) } /* - ** special clauses (defines, sets, allocates, releases) + ** state clauses (ensures, defines, sets, allocates, releases) */ - - if (uentry_hasSpecialClauses (fcn)) + + if (uentry_hasStateClauseList (fcn)) { - specialClauses clauses = uentry_getSpecialClauses (fcn); + stateClauseList clauses = uentry_getStateClauseList (fcn); - specialClauses_elements (clauses, cl) + stateClauseList_elements (clauses, cl) { - sRefTest tst = specialClause_getPostTestFunction (cl); - sRefSet rfs = specialClause_getRefs (cl); - - - sRefSet_elements (rfs, el) - { - sRef base = sRef_getRootBase (el); - - if (sRef_isResult (base)) - { - ; - } - else if (sRef_isParam (base)) + if (stateClause_isAfter (cl) && !stateClause_isGlobal (cl)) + { + if (stateClause_setsMetaState (cl)) { - sRef sr = sRef_updateSref (base); + sRefSet rfs = stateClause_getRefs (cl); + qual q = stateClause_getMetaQual (cl); + annotationInfo ainfo = qual_getAnnotationInfo (q); + metaStateInfo minfo = annotationInfo_getState (ainfo); + cstring key = metaStateInfo_getName (minfo); + int mvalue = annotationInfo_getValue (ainfo); - sr = sRef_fixBase (el, sr); + DPRINTF (("Post meta state clause: %s", stateClause_unparse (cl))); - - if (tst != NULL && !tst (sr)) + sRefSet_elements (rfs, el) { - if (optgenerror - (specialClause_postErrorCode (cl), - message ("%s storage %qcorresponds to " - "storage listed in %q clause", - specialClause_postErrorString (cl, sr), - sRef_unparseOpt (sr), - specialClause_unparseKind (cl)), - g_currentloc)) + sRef base = sRef_getRootBase (el); + + if (sRef_isResult (base)) { - sRefShower ss = specialClause_getPostTestShower (cl); - - if (ss != NULL) + /* + ** This is checked for return transfers. + */ + ; + } + else if (sRef_isParam (base) || sRef_isGlobalMarker (base)) + { + sRef sr = sRef_updateSref (base); + sr = sRef_fixBase (el, sr); + + if (!sRef_checkMetaStateValue (sr, key, mvalue)) { - ss (sr); + if (optgenerror + (FLG_STATETRANSFER, + message + ("Ensures clause not satisfied%q (state is %q): %q", + sRef_isGlobalMarker (sr) + ? message ("") + : message (" by %q", sRef_unparse (sr)), + stateValue_unparseValue (sRef_getMetaStateValue (sr, key), + minfo), + stateClause_unparse (cl)), + g_currentloc)) + { + sRef_showMetaStateInfo (sr, key); + } } } - - } + else + { + if (sRef_isMeaningful (el)) + { + BADBRANCH; + } + } + } end_sRefSet_elements ; } else { - if (sRef_isMeaningful (el)) + /* evs - 2000 07 10 - added this */ + sRefTest tst = stateClause_getPostTestFunction (cl); + sRefSet rfs = stateClause_getRefs (cl); + + sRefSet_elements (rfs, el) { - BADBRANCH; - } - } - } end_sRefSet_elements ; + sRef base = sRef_getRootBase (el); + + if (sRef_isResult (base)) + { + /* + ** This is checked for return transfers. + */ - } end_specialClauses_elements ; + ; + } + else if (sRef_isParam (base)) + { + sRef sr = sRef_updateSref (base); + sr = sRef_fixBase (el, sr); + + if (tst != NULL && !tst (sr)) + { + if (optgenerror + (stateClause_postErrorCode (cl), + message ("%s storage %qcorresponds to " + "storage listed in %q clause", + stateClause_postErrorString (cl, sr), + sRef_unparseOpt (sr), + stateClause_unparseKind (cl)), + g_currentloc)) + { + sRefShower ss = stateClause_getPostTestShower (cl); + + if (ss != NULL) + { + ss (sr); + } + + DPRINTF (("Storage: %s", sRef_unparseFull (sr))); + } + } + } + else + { + if (sRef_isMeaningful (el)) + { + BADBRANCH; + } + } + } end_sRefSet_elements ; + } + } + } end_stateClauseList_elements ; } - - + /* ** check parameters on return */ @@ -3603,18 +4301,26 @@ void usymtab_checkFinalScope (bool isReturn) if (ctype_isMutable (rt) || ctype_isSU (rt)) { uentry param = usymtab_lookupQuiet (utab, uentry_rawName (arg)); - checkParamReturn (param); + DPRINTF (("Check param return: %s", uentry_unparseFull (param))); + transferChecks_paramReturn (param); } } } end_uentryList_elements; + DPRINTF (("Check global return: %s", + globSet_unparse (sglobs))); + globSet_allElements (sglobs, el) { + sRef orig = el; /*! sRef_updateSref (el); */ /*!!!*/ uentry current = sRef_getUentry (el); + DPRINTF (("Check global return: %s / %s", sRef_unparseFull (el), + uentry_unparseFull (current))); + if (uentry_isVariable (current) && !uentry_isRealFunction (current)) { - checkGlobalReturn (current, el); + checkGlobalReturn (current, orig); } } end_globSet_allElements; @@ -3624,7 +4330,6 @@ void usymtab_checkFinalScope (bool isReturn) { uentry current = sRef_getUentry (el); - if (uentry_isVariable (current) && !uentry_isRealFunction (current)) { @@ -3632,9 +4337,8 @@ void usymtab_checkFinalScope (bool isReturn) } } } end_globSet_allElements; - } - - } + } +} void usymtab_quietExitScope (fileloc loc) @@ -3643,6 +4347,8 @@ usymtab_quietExitScope (fileloc loc) { usymtab t = utab->env; + DPRINTF (("Quiet exit scope [%p]", utab)); + if (utab->reftable != NULL) { int i; @@ -3669,9 +4375,14 @@ usymtab_quietExitScope (fileloc loc) t->mustBreak = utab->mustBreak; t->exitCode = utab->exitCode; + DPRINTF (("Free level [%p]", utab)); usymtab_freeLevel (utab); utab = t; + +# ifdef DEBUGSPLINT + usymtab_checkAllValid (); +# endif } /* @@ -3698,7 +4409,9 @@ void usymtab_exitScope (exprNode expr) usymtab ctab = usymtab_undefined; usymtab lctab = usymtab_undefined; bool mustReturn = exprNode_mustEscape (expr); - + + DPRINTF (("Exit scope [%p]", utab)); + if (utab->kind == US_CBRANCH) { /* @@ -3715,10 +4428,35 @@ void usymtab_exitScope (exprNode expr) } } - llassertprint (utab->kind != US_TBRANCH && utab->kind != US_FBRANCH - && utab->kind != US_CBRANCH && utab->kind != US_SWITCH, - ("exitScope: in branch: %s", usymtab_unparseStack())); - + if (utab->kind == US_TBRANCH || utab->kind == US_FBRANCH + || utab->kind == US_CBRANCH || utab->kind == US_SWITCH) + { + if (context_inMacro ()) + { + /* evs 2000-07-25 */ + /* Unparseable macro may end inside nested scope. Deal with it. */ + + llerror (FLG_SYNTAX, + message ("Problem parsing macro body of %s (unbalanced scopes). " + "Attempting to recover, recommend /*@notfunction@*/ before " + "macro definition.", + context_inFunctionName ())); + + while (utab->kind == US_TBRANCH + || utab->kind == US_FBRANCH + || utab->kind == US_CBRANCH + || utab->kind == US_SWITCH) + { + utab = utab->env; + llassert (utab != GLOBAL_ENV); + } + } else + { + llcontbug (message ("exitScope: in branch: %q", usymtab_unparseStack ())); + /*@-branchstate@*/ + } /*@=branchstate@*/ + } + /* ** check all variables in scope were used */ @@ -3744,7 +4482,7 @@ void usymtab_exitScope (exprNode expr) ** NOTE: note for exiting paramsScope, since checkReturn should be ** called first. */ - + if (!mustReturn && (usymtab_lexicalLevel () > functionScope)) { /* @@ -3763,7 +4501,6 @@ void usymtab_exitScope (exprNode expr) uentryList params = context_getParams (); globSet globs = context_getUsedGlobs (); - uentryList_elements (params, ue) { uentry_fixupSref (ue); @@ -3771,9 +4508,12 @@ void usymtab_exitScope (exprNode expr) clearFunctionTypes (); - + DPRINTF (("Fixing up globals: %s", globSet_unparse (globs))); + globSet_allElements (globs, el) { + DPRINTF (("Fix: %s", sRef_unparseDebug (el))); + if (sRef_isCvar (el)) { uentry current; @@ -3791,13 +4531,17 @@ void usymtab_exitScope (exprNode expr) if (uentry_isVariable (current)) { + DPRINTF (("Fixup: %s", uentry_unparse (current))); uentry_fixupSref (current); } else { + DPRINTF (("Clear: %s", uentry_getSref (current))); sRef_clearDerived (uentry_getSref (current)); } } + + sRef_clearDerived (el); /* evans 2002-03-14 - this is the likely source of many crashes! */ } end_globSet_allElements; } @@ -3808,8 +4552,13 @@ void usymtab_exitScope (exprNode expr) /*@i@*/ lctab->env = utab; /*@i@*/ utab = ctab; /*@-branchstate@*/ } /*@=branchstate@*/ -/*@-globstate@*/ -} + /*@-globstate@*/ + + +# ifdef DEBUGSPLINT + usymtab_checkAllValid (); +# endif +/*@i523@*/ } /*@=globstate@*/ /* @@ -3825,9 +4574,7 @@ uentry_directParamNo (uentry ue) if (sRef_lexLevel (sr) == functionScope) { - /*@access sRef@*/ /*@-null@*/ - int index = sr->info->cvar->index; - /*@noaccess sRef@*/ /*@=null@*/ + int index = sRef_getScopeIndex (sr); if (index < uentryList_size (context_getParams ())) { @@ -3883,16 +4630,13 @@ usymtab_getRefTab (/*@notnull@*/ usymtab u, int level, usymId index) { uentry ue; - ue = usymtab_getRefNoisy (u, level, index); - if (uentry_isUndefined (ue)) { llbug (message ("usymtab_getRef: out of range: %d. level = %d", index, level)); } - return ue; } @@ -3940,8 +4684,7 @@ static /*@dependent@*/ /*@exposed@*/ usymtab llassert (index >= 0); if (level > s->lexlevel) - { - + { return uentry_undefined; } @@ -3990,14 +4733,11 @@ usymtab_getRefNoisy (/*@notnull@*/ usymtab s, int level, usymId index) { usymtab otab = s; uentry ue = uentry_undefined; - llassert (index >= 0); - while (s->lexlevel > level) { - if (usymtab_isBranch (s)) { int eindex = refTable_lookup (s, level, index); @@ -4085,9 +4825,9 @@ usymtab_getRefNoisy (/*@notnull@*/ usymtab s, int level, usymId index) } else { - } + } } - + return ue; } @@ -4117,16 +4857,15 @@ int refTable_lookup (/*@notnull@*/ usymtab ut, int level, int index) llassert (rt != NULL); - for (i = 0; i < ut->nentries; i++) { if (rt[i]->level == level && rt[i]->index == index) { - return i; + return i; } } - - return NOT_FOUND; + + return NOT_FOUND; } static @@ -4146,8 +4885,14 @@ usymtab_addRefEntry (/*@notnull@*/ usymtab s, cstring k) int eindex; usymtab ut = s; - llassert (ut->reftable != NULL); + if (ut->reftable == NULL) + { + DPRINTF (("Adding ref entry without reftable: %s", k)); + return uentry_undefined; + } + llassert (ut->reftable != NULL); + while (s != GLOBAL_ENV) { eindex = usymtab_getIndex (s, k); @@ -4160,18 +4905,23 @@ usymtab_addRefEntry (/*@notnull@*/ usymtab s, cstring k) { uentry ue; - DPRINTF (("Here: copying %s", uentry_unparseFull (current))); - - ue = uentry_copy (current); - - DPRINTF (("Here: copying %s", uentry_unparseFull (ue))); + DPRINTF (("Here: copying %s", uentry_unparse (current))); + if (uentry_isNonLocal (current)) + { + ue = uentry_copy (current); + } + else + { + ue = uentry_copyNoSave (current); + } + DPRINTF (("Here: copying %s", uentry_unparse (ue))); usymtab_addEntryQuiet (ut, ue); - + DPRINTF (("Okay...")); + if (s->reftable != NULL) { refentry ref = s->reftable[eindex]; - ut->reftable[ut->nentries - 1] = refentry_create (ref->level, ref->index); @@ -4207,16 +4957,32 @@ static uentry usymtab_lookupAux (usymtab s, cstring k) if (eindex != NOT_FOUND) { uentry ret = s->entries[eindex]; +# if 0 + + if (s->kind == US_TBRANCH + || s->kind == US_FBRANCH + || s->kind == US_CBRANCH) + /* uentry_isGlobalVariable (ret) && os->lexlevel > fileScope) */ + { + uentry ret; + DPRINTF (("Adding global ref entry: %s", k)); + ret = usymtab_addRefEntry (os, k); + DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret))); + return ret; + } + +# endif DPRINTF (("Found: %s", uentry_unparseFull (ret))); return (ret); } - + if (s->kind == US_TBRANCH || s->kind == US_FBRANCH || s->kind == US_CBRANCH) { + /* why isn't this os??? */ uentry ret = usymtab_addRefEntry (s, k); - DPRINTF (("Ref entry: %s", uentry_unparseFull (ret))); + DPRINTF (("Adding ref entry: %s", uentry_unparseFull (ret))); return ret; } @@ -4227,7 +4993,7 @@ static uentry usymtab_lookupAux (usymtab s, cstring k) } static /*@dependent@*/ /*@exposed@*/ uentry -usymtab_lookupQuiet (usymtab s, cstring k) +usymtab_lookupQuietAux (usymtab s, cstring k, bool noalt) { int eindex; @@ -4241,12 +5007,32 @@ usymtab_lookupQuiet (usymtab s, cstring k) return (ret); } - s = s->env; + if (noalt && usymtab_isBranch (s)) + { + s = usymtab_dropEnv (s); + } + else + { + llassert (s != NULL); /*@i523 should not need this? */ + s = s->env; + } } return uentry_undefined; } +static /*@exposed@*/ /*@dependent@*/ uentry +usymtab_lookupQuiet (usymtab s, cstring k) +{ + return usymtab_lookupQuietAux (s, k, FALSE); +} + +static /*@exposed@*/ /*@dependent@*/ uentry +usymtab_lookupQuietNoAlt (usymtab s, cstring k) +{ + return usymtab_lookupQuietAux (s, k, TRUE); +} + /*@dependent@*/ /*@observer@*/ uentry usymtab_lookupSafe (cstring k) /*@globals utab@*/ @@ -4290,6 +5076,7 @@ uentry usymtab_lookupGlob (cstring k) if (uentry_isPriv (ce)) llfatalbug (message ("usymtab_lookup: private: %s", k)); + DPRINTF (("Lookup global: %s", uentry_unparseFull (ce))); return ce; } @@ -4298,7 +5085,7 @@ uentry usymtab_lookupGlob (cstring k) /*@globals globtab@*/ { uentry ce = usymtab_lookupAux (globtab, k); - + DPRINTF (("Lookup global: %s", uentry_unparseFull (ce))); return ce; } @@ -4310,10 +5097,10 @@ uentry usymtab_lookupEither (cstring k) if (uentry_isUndefined (ce)) llfatalerror (message ("usymtab_lookup: not found: %s", k)); + DPRINTF (("Lookup either: %s", uentry_unparseFull (ce))); return ce; } -# ifndef NOLCL ctype usymtab_lookupType (cstring k) /*@globals globtab@*/ @@ -4328,7 +5115,6 @@ usymtab_lookupType (cstring k) return (uentry_getRealType (usymtab_getTypeEntry (uid))); } -# endif ctype usymtab_lookupAbstractType (cstring k) /*@globals globtab@*/ @@ -4370,7 +5156,12 @@ usymtab_suFieldsType (uentryList f, bool isStruct) { int i; - if (fileloc_isSpec (g_currentloc)) return (ctype_undefined); + DPRINTF (("Fields: %s", uentryList_unparse (f))); + + if (fileloc_isSpec (g_currentloc)) + { + return (ctype_undefined); + } for (i = 0; i < globtab->nentries; i++) { @@ -4382,11 +5173,19 @@ usymtab_suFieldsType (uentryList f, bool isStruct) if (isFakeTag (uentry_rawName (current))) { ctype ct = uentry_getType (current); + + DPRINTF (("Check: %s", ctype_unparse (ct))); if ((isStruct ? ctype_isStruct (ct) : ctype_isUnion (ct)) - && (uentryList_matchFields (f, ctype_getFields (ct)))) + && + (uentry_isSpecified (current) + && uentryList_equivFields (f, ctype_getFields (ct)))) { - return uentry_getAbstractType (current); + return uentry_getAbstractType (current); + } + else + { + ; } } } @@ -4427,7 +5226,6 @@ usymtab_exists (cstring k) /*@globals utab@*/ { uentry ce = usymtab_lookupSafe (k); - return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce))); } @@ -4451,7 +5249,6 @@ bool return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce))); } -# ifndef NOLCL bool usymtab_existsEither (cstring k) /*@globals utab@*/ @@ -4469,7 +5266,6 @@ bool return (uentry_isValid (ce)); } -# endif bool usymtab_existsType (cstring k) @@ -4484,9 +5280,9 @@ bool usymtab_existsTypeEither (cstring k) /*@globals globtab@*/ { - uentry ce = usymtab_lookupAux (globtab, k); - - return (uentry_isValid (ce) && uentry_isDatatype (ce)); + uentry ce; + ce = usymtab_lookupAux (globtab, k); + return (uentry_isValid (ce) && uentry_isDatatype (ce)); } bool @@ -4494,10 +5290,7 @@ usymtab_existsStructTag (cstring k) /*@globals globtab@*/ { cstring sname = makeStruct (k); uentry ce = usymtab_lookupAux (globtab, sname); - - cstring_free (sname); - - + cstring_free (sname); return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce))); } @@ -4522,7 +5315,6 @@ usymtab_existsEnumTag (cstring k) /*@globals globtab@*/ return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce))); } -# ifndef NOLCL bool usymtab_existsVar (cstring k) /*@globals utab@*/ { @@ -4530,7 +5322,6 @@ bool usymtab_existsVar (cstring k) return (!(uentry_isUndefined (ce)) && !(uentry_isPriv (ce)) && (uentry_isVar (ce))); } -# endif /* ** destructors @@ -4558,6 +5349,7 @@ usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab u) { int i; + DPRINTF (("Free level [%p]", u)); aliasTable_free (u->aliases); refTable_free (u->reftable, u->nentries); @@ -4566,7 +5358,10 @@ usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab u) { for (i = 0; i < u->nentries; i++) { + DPRINTF (("Free complete: %d", i)); + DPRINTF (("Uentry: %s", uentry_unparse (u->entries[i]))); uentry_freeComplete (u->entries[i]); + u->entries[i] = uentry_undefined; } } else @@ -4574,6 +5369,7 @@ usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab u) for (i = 0; i < u->nentries; i++) { uentry_free (u->entries[i]); + u->entries[i] = uentry_undefined; } } @@ -4584,12 +5380,12 @@ usymtab_freeLevel (/*@notnull@*/ /*@only@*/ usymtab u) && u != utab && u != filetab) { - llassert (u->htable == NULL); - sfree (u); + llassert (!cstringTable_isDefined (u->htable)); } -/*@-mustfree@*/ -} /*@=mustfree@*/ + sfree (u); /* evans 2002-07-12: was inside if */ + /*:!!mustfree@*/ +} /*!@=mustfree@*/ static void usymtab_freeAux (/*@only@*/ usymtab u) @@ -4612,7 +5408,8 @@ void usymtab_free () { dbgfree = TRUE; usymtab_freeAux (utab); -} + utab = usymtab_undefined; +/*@i523@*/ } static int usymtab_lexicalLevel (void) /*@globals utab@*/ { @@ -4634,7 +5431,6 @@ bool usymtab_inFunctionScope () /*@globals utab@*/ return (utab->lexlevel == functionScope); } -# ifndef NOLCL void usymtab_replaceEntry (uentry s) /*@globals utab, globtab@*/ @@ -4642,7 +5438,6 @@ usymtab_replaceEntry (uentry s) { usymtab_replaceEntryAux (utab, s); } -# endif bool usymtab_matchForwardStruct (usymId u1, usymId u2) @@ -4700,6 +5495,10 @@ static bool usymtab_isGuardedAux (sRef s) while (tab->lexlevel >= lowlevel) { + DPRINTF (("Is guarded? [%s] %s", + guardSet_unparse (tab->guards), + sRef_unparseFull (s))); + if (guardSet_isGuarded (tab->guards, s)) { /* @@ -4743,21 +5542,21 @@ void usymtab_unguard (sRef s) /*@modifies utab@*/ bool usymtab_isGuarded (sRef s) { - + DPRINTF (("Is guarded? %s", sRef_unparseFull (s))); return (sRef_aliasCompleteSimplePred (usymtab_isGuardedAux, s)); } -bool usymtab_isProbableNull (sRef s) +bool usymtab_isDefinitelyNull (sRef s) { - return (sRef_aliasCheckSimplePred (usymtab_isProbableNullAux, s)); + return (sRef_aliasCheckSimplePred (usymtab_isDefinitelyNullAux, s)); } -bool usymtab_isProbableDeepNull (sRef s) +bool usymtab_isDefinitelyNullDeep (sRef s) { - return (sRef_deepPred (usymtab_isProbableNull, s)); + return (sRef_deepPred (usymtab_isDefinitelyNull, s)); } -static bool usymtab_isProbableNullAux (sRef s) +static bool usymtab_isDefinitelyNullAux (sRef s) /*@globals utab@*/ { usymtab tab = utab; @@ -4772,7 +5571,7 @@ static bool usymtab_isProbableNullAux (sRef s) while (tab->lexlevel >= lowlevel) { - if (guardSet_isProbableNull (tab->guards, s)) + if (guardSet_mustBeNull (tab->guards, s)) { return TRUE; } @@ -4827,7 +5626,7 @@ usymtab_displayAllUses () usymtab_entries (copy, ue) { - if (uentry_isValid (ue)) + if (uentry_isValid (ue) && !uentry_isGlobalMarker (ue)) { filelocList uses = uentry_getUses (ue); int size = filelocList_realSize (uses); @@ -4836,7 +5635,7 @@ usymtab_displayAllUses () && !fileloc_isLib (uentry_whereDefined (ue)) && (size > 0)) { - llmsg (message ("%q (%q), %d use%p:\n %q", + llmsg (message ("%q (%q), %d use%&:\n %q", uentry_getName (ue), fileloc_unparse (uentry_whereDefined (ue)), size, filelocList_unparseUses (uses))); @@ -4903,29 +5702,12 @@ usymtab_typeName (/*@notnull@*/ usymtab t) BADEXIT; } -void usymtab_addMustAlias (sRef s, sRef al) +void usymtab_addMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al) /*@modifies utab@*/ { - if (sRef_isMeaningful (s) && sRef_isMeaningful (al) - && !(sRef_isConst (s) || sRef_isConst (al)) - && !(sRef_isAddress (al) && sRef_isDirectParam (sRef_getBase (al))) - && !(sRef_similar (s, al))) - { - utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al); - DPRINTF (("Must alias: %s", aliasTable_unparse (utab->aliases))); - - /* - ** for local variable, aliasing is symmetric - */ - - if (sRef_isLocalVar (s) && sRef_isLocalVar (al)) - { - utab->aliases = aliasTable_addMustAlias (utab->aliases, al, s); - } - } - else + if (!sRef_similar (s, al)) { - ; + usymtab_addForceMustAlias (s, al); } } @@ -4933,9 +5715,10 @@ void usymtab_addMustAlias (sRef s, sRef al) ** Same as usymtab_addMustAlias, except does not check sRef_isSimilar. */ -void usymtab_addForceMustAlias (sRef s, sRef al) +void usymtab_addForceMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al) /*@modifies utab@*/ { + /* evans 2002-03-3: was sRef_isMeaningful -- but we need to keep aliases for new storage also! */ if (sRef_isMeaningful (s) && sRef_isMeaningful (al) && !(sRef_isConst (s) || sRef_isConst (al)) @@ -4955,10 +5738,17 @@ void usymtab_addForceMustAlias (sRef s, sRef al) } else { - ; + DPRINTF (("Not aliasing! %s / %s", sRef_unparseFull (s), sRef_unparseFull (al))); + DPRINTF (("meaningful: %d %d", sRef_isMeaningful (s), sRef_isMeaningful (al))); } } +void usymtab_addReallyForceMustAlias (/*@exposed@*/ sRef s, /*@exposed@*/ sRef al) + /*@modifies utab@*/ +{ + utab->aliases = aliasTable_addMustAlias (utab->aliases, s, al); +} + void usymtab_clearAlias (sRef s) /*@modifies utab, s@*/ { @@ -4969,36 +5759,35 @@ void usymtab_clearAlias (sRef s) sRefSet usymtab_allAliases (sRef s) /*@globals utab@*/ { - if (sRef_isMeaningful (s)) + if (sRef_isSomewhatMeaningful (s)) { sRefSet ret; - ret = sRefSet_unionFree (aliasTable_aliasedBy (utab->aliases, s), aliasTable_canAlias (utab->aliases, s)); - return (ret); + return (ret); } else { + DPRINTF (("NOT A MEANINGFUL SREF!")); return sRefSet_undefined; } } /*@only@*/ sRefSet usymtab_canAlias (sRef s) - /*@globals utab@*/ + /*@globals utab@*/ { - if (sRef_isMeaningful (s)) + if (sRef_isSomewhatMeaningful (s)) { sRefSet res = aliasTable_canAlias (utab->aliases, s); - return res; } - + return sRefSet_undefined; } /*@only@*/ sRefSet usymtab_aliasedBy (sRef s) - /*@globals utab@*/ + /*@globals utab@*/ { return (aliasTable_aliasedBy (utab->aliases, s)); } @@ -5025,7 +5814,7 @@ usymtab_printOut (void) int depth = 0; char *ind = mstring_copy (" "); - fprintf (g_msgstream, "<<< [symbol table] >>>\n"); + fprintf (g_warningstream, "<<< [symbol table] >>>\n"); while (s != GLOBAL_ENV && s->env != GLOBAL_ENV) { @@ -5036,7 +5825,7 @@ usymtab_printOut (void) ind[depth * 3 + 1] = '\0'; } - fprintf (g_msgstream, "level: %d (%s)\n", s->lexlevel, + fprintf (g_warningstream, "level: %d (%s)\n", s->lexlevel, cstring_toCharsSafe (tname)); cstring_free (tname); @@ -5044,17 +5833,17 @@ usymtab_printOut (void) for (i = 0; i < s->nentries; i++) { cstring us = uentry_unparseFull (s->entries[i]); - fprintf (g_msgstream, "%s\n", cstring_toCharsSafe (us)); + fprintf (g_warningstream, "%s\n", cstring_toCharsSafe (us)); cstring_free (us); } if (s->reftable != NULL && s->nentries > 0) { - fprintf (g_msgstream, "\t<< Ref table >>\n"); + fprintf (g_warningstream, "\t<< Ref table >>\n"); for (i = 0; i < s->nentries; i++) { - fprintf (g_msgstream, "\t%s %3d: %d, %d\n", ind, i, + fprintf (g_warningstream, "\t%s %3d: %d, %d\n", ind, i, s->reftable[i]->level, s->reftable[i]->index); } @@ -5064,7 +5853,7 @@ usymtab_printOut (void) depth++; s = s->env; } - fprintf (g_msgstream, "<<< end usymtab >>>\n"); + fprintf (g_warningstream, "<<< end usymtab >>>\n"); mstring_free (ind); return; } @@ -5085,7 +5874,7 @@ usymtab_printAll (void) static void usymtab_printAllAux (usymtab s) - /*@modifies g_msgstream@*/ + /*@modifies g_warningstream@*/ { int i; int depth = 0; @@ -5161,7 +5950,7 @@ usymtab_printComplete () for (i = looplow; i < s->nentries; i++) { printf ("%s%3d %s\n", ind, i, - cstring_toCharsSafe (uentry_unparse (s->entries[i]))); + cstring_toCharsSafe (uentry_unparseFull (s->entries[i]))); } } else @@ -5170,7 +5959,7 @@ usymtab_printComplete () for (i = 0; i < s->nentries; i++) { printf ("%s%3d %s\n", ind, i, - cstring_toCharsSafe (uentry_unparse (s->entries[i]))); + cstring_toCharsSafe (uentry_unparseFull (s->entries[i]))); } } @@ -5183,6 +5972,7 @@ usymtab_printComplete () mstring_free (ind); } +# ifdef S_SPLINT_S static /*@only@*/ cstring /*@unused@*/ usymtab_unparseLocalAux (/*@notnull@*/ usymtab s) { @@ -5225,6 +6015,7 @@ usymtab_unparseLocalList (/*@notnull@*/ usymtab s) return (c); } +# endif void usymtab_printLocal (void) @@ -5259,9 +6050,9 @@ usymtab_printLocal (void) static bool checkDistinctExternalName (uentry e) /*@globals globtab@*/ - /*@modifies *g_msgstream@*/ + /*@modifies *g_warningstream@*/ { - int checklen = context_getValue (FLG_EXTERNALNAMELEN); + size_t checklen = size_fromInt (context_getValue (FLG_EXTERNALNAMELEN)); bool ignorecase = context_getFlag (FLG_EXTERNALNAMECASEINSENSITIVE); bool gotone = FALSE; bool extras = FALSE; @@ -5336,7 +6127,7 @@ static bool checkDistinctExternalName (uentry e) "in the first %d characters (%q)", uentry_getName (e), uentry_getName (oe), - checklen, + size_toInt (checklen), cstring_clip (uentry_getName (e), checklen)), /*@=sefparams@*/ uentry_whereLast (e))) @@ -5362,7 +6153,7 @@ static bool checkDistinctExternalName (uentry e) "is ignored", uentry_getName (e), uentry_getName (oe), - checklen), + size_toInt (checklen)), uentry_whereLast (e))) { uentry_showWhereAny (oe); @@ -5388,7 +6179,7 @@ static bool checkDistinctExternalName (uentry e) "in the first %d characters (%q)", uentry_getName (e), uentry_getName (oe), - checklen, + size_toInt (checklen), cstring_clip (uentry_getName (e), checklen)), /*@=sefparams@*/ uentry_whereLast (e))) @@ -5420,11 +6211,11 @@ static bool checkDistinctExternalName (uentry e) static bool checkDistinctInternalName (uentry e) /*@globals utab@*/ - /*@modifies *g_msgstream@*/ + /*@modifies *g_warningstream@*/ { usymtab ttab = utab; cstring name = uentry_rawName (e); - int numchars = context_getValue (FLG_INTERNALNAMELEN); + size_t numchars = size_fromInt (context_getValue (FLG_INTERNALNAMELEN)); bool caseinsensitive = context_getFlag (FLG_INTERNALNAMECASEINSENSITIVE); bool lookalike = context_getFlag (FLG_INTERNALNAMELOOKALIKE); @@ -5464,7 +6255,7 @@ static bool checkDistinctInternalName (uentry e) "in the first %d characters (%q)", uentry_getName (e), uentry_getName (oe), - numchars, + size_toInt (numchars), cstring_clip (uentry_getName (e), numchars)), /*@=sefparams@*/ uentry_whereLast (e))) @@ -5477,8 +6268,7 @@ static bool checkDistinctInternalName (uentry e) /*@switchbreak@*/ break; case CGE_CASE: - if (numchars == 0 - || (cstring_length (name) <= numchars)) + if (numchars == 0 || (cstring_length (name) <= numchars)) { if (optgenerror (FLG_DISTINCTINTERNALNAMES, @@ -5503,7 +6293,7 @@ static bool checkDistinctInternalName (uentry e) "in the first %d characters without case sensitivity", uentry_getName (e), uentry_getName (oe), - numchars), + size_toInt (numchars)), uentry_whereLast (e))) { uentry_showWhereAny (oe); @@ -5540,7 +6330,7 @@ static bool checkDistinctInternalName (uentry e) "in the first %d characters except by lookalike characters", uentry_getName (e), uentry_getName (oe), - numchars), + size_toInt (numchars)), uentry_whereLast (e))) { uentry_showWhereAny (oe); @@ -5581,7 +6371,50 @@ void usymtab_checkDistinctName (uentry e, int scope) if (hasError) { - uentry_setHasNameError (e); + uentry_setHasNameError (e); } } +/*@exposed@*/ sRef usymtab_lookupGlobalMarker (void) /*@globals utab@*/ +{ + uentry ue; + + ue = usymtab_lookupAux (utab, GLOBAL_MARKER_NAME); + llassert (uentry_isValid (ue)); + + return uentry_getSref (ue); +} + + +# ifdef DEBUGSPLINT +/* +** For debugging only +*/ + +void +usymtab_checkAllValid () /*@globals utab@*/ +{ + usymtab tab = utab; + + while (tab != GLOBAL_ENV) + { + int i; + + for (i = 0; i < utab->nentries; i++) + { + uentry e = utab->entries[i]; + + uentry_checkValid (e); + } + + aliasTable_checkValid (tab->aliases); + tab = tab->env; + } +} +# endif + + + + + +