X-Git-Url: http://andersk.mit.edu/gitweb/splint.git/blobdiff_plain/ef2aa32aebac950c1784a2dd25f0fa299b8840da..2e4caa51b7f68083f8e80e59475eb5d045ffd91e:/src/uentry.c diff --git a/src/uentry.c b/src/uentry.c index 5da16f3..0f5fb17 100644 --- a/src/uentry.c +++ b/src/uentry.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-2003 University of Virginia, ** Massachusetts Institute of Technology ** ** This program is free software; you can redistribute it and/or modify it @@ -17,21 +17,19 @@ ** 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 */ /* ** uentry.c */ -# include "lclintMacros.nf" +# include "splintMacros.nf" # include "basic.h" # include "structNames.h" # include "nameChecks.h" -/*@i223*/ -/*@-type*/ static /*@dependent@*/ uentry posRedeclared = uentry_undefined; static /*@only@*/ fileloc posLoc = fileloc_undefined; static int nuentries = 0; @@ -45,6 +43,14 @@ static bool uentry_isReallySpecified (uentry p_e) /*@*/ ; static void uentry_checkIterArgs (uentry p_ue); static cstring uentry_dumpAux (uentry p_v, bool p_isParam); +static void uentry_showWhereLastKind (uentry p_spec) /*@modifies g_warningstream@*/ ; + +static void uentry_combineModifies (uentry p_ue, /*@owned@*/ sRefSet p_sr) + /*@modifies p_ue@*/ ; + +static void uentry_addStateClause (uentry p_ue, /*@only@*/ stateClause p_sc) + /*@modifies p_ue@*/ ; + /*@access ekind@*/ static void checkAliasState (/*@notnull@*/ uentry p_old, /*@notnull@*/ uentry p_unew, @@ -60,10 +66,8 @@ static void checkVarConformance (/*@notnull@*/ uentry p_old, bool p_mustConform, bool p_completeConform) /*@modifies p_old, p_unew@*/; -# ifndef NOLCL static void uentry_setHasMods (uentry p_ue) /*@modifies p_ue@*/; static void uentry_setHasGlobs (uentry p_ue) /*@modifies p_ue@*/; -# endif static void uentry_reallyFree (/*@notnull@*/ /*@only@*/ uentry p_e); @@ -80,15 +84,31 @@ static void paramTypeError (/*@notnull@*/ uentry p_old, /*@notnull@*/ uentry p_oldCurrent, ctype p_oldType, /*@notnull@*/ uentry p_unew, /*@notnull@*/ uentry p_newCurrent, - ctype p_newType, int p_paramno) /*@modifies g_msgstream@*/ ; + ctype p_newType, int p_paramno) /*@modifies g_warningstream@*/ ; static /*@only@*/ /*@notnull@*/ uentry uentry_makeVariableAux (cstring p_n, ctype p_t, /*@keep@*/ fileloc p_f, /*@exposed@*/ sRef p_s, bool p_priv, vkind p_kind); +static /*@only@*/ /*@notnull@*/ uentry + uentry_makeConstantAux (cstring p_n, ctype p_t, + /*@keep@*/ fileloc p_f, bool p_priv, bool p_macro, + /*@only@*/ multiVal p_m) /*@*/ ; + +static void uentry_convertVarFunction (uentry ue) /*@modifies ue@*/ +{ + if (uentry_isVariable (ue) + && (ctype_isFunction (ctype_realType (uentry_getType (ue))) + || ctype_isUnknown (uentry_getType (ue)))) + { + uentry_makeVarFunction (ue); + } +} + static /*@out@*/ /*@notnull@*/ uentry uentry_alloc (void) /*@*/ { uentry ue = (uentry) dmalloc (sizeof (*ue)); + ue->warn = warnClause_undefined; /*@i32@*/ nuentries++; totuentries++; @@ -96,11 +116,13 @@ static /*@out@*/ /*@notnull@*/ uentry uentry_alloc (void) /*@*/ } static cstring uentry_getOptName (uentry p_e) /*@*/ ; -static void uentry_copyInto (/*@out@*/ /*@unique@*/ uentry p_unew, uentry p_old); +static void uentry_updateInto (/*@unique@*/ uentry p_unew, uentry p_old) /*@modifies p_unew, p_old@*/ ; + static void uentry_setNullState (/*@notnull@*/ uentry p_ue, nstate p_ns); static void uentry_setAliasKind (/*@notnull@*/ uentry p_ue, alkind p_ak); static /*@only@*/ /*@null@*/ uinfo uinfo_copy (uinfo p_u, ekind p_kind); static void uinfo_free (/*@only@*/ uinfo p_u, ekind p_kind); +static void ucinfo_free (/*@only@*/ ucinfo p_u); static void uvinfo_free (/*@only@*/ uvinfo p_u); # ifdef DOANNOTS @@ -288,8 +310,7 @@ void printAnnots () } printf ("\n"); - printf ("Total Annotations: %d (%d decls, %d sharable, %d indirect)\n", alltotals, totdecls, totshdecls, totidecls); -} + printf ("Total Annotations: %d (%d decls, %d sharable, %d indirect)\n", alltotals, totdecls, totshdecls, totidecls); } extern void uentry_tallyAnnots (uentry u, ancontext kind) { @@ -298,7 +319,6 @@ extern void uentry_tallyAnnots (uentry u, ancontext kind) nstate ns = sRef_getNullState (u->sref); sstate ss = sRef_getDefState (u->sref); bool recordUnknown = FALSE; - if (kind == AN_UNKNOWN) { @@ -333,7 +353,7 @@ extern void uentry_tallyAnnots (uentry u, ancontext kind) if (ctype_isFunction (u->utype) && !hasRet - && ctype_isVisiblySharable (ctype_realType (ctype_returnValue (u->utype)))) + && ctype_isVisiblySharable (ctype_realType (ctype_getReturnType (u->utype)))) { recordUnknown = TRUE; } @@ -398,15 +418,6 @@ extern void uentry_tallyAnnots (uentry u, ancontext kind) } } - - - - - - - - - switch (ss) { case SS_ALLOCATED: tallyAnnot (kind, QU_OUT); break; @@ -426,7 +437,7 @@ extern void uentry_tallyAnnots (uentry u, ancontext kind) case AK_UNKNOWN: if (ctype_isRefCounted (ctype_realType (u->utype)) || (ctype_isFunction (u->utype) && - ctype_isRefCounted (ctype_realType (ctype_returnValue (u->utype))))) + ctype_isRefCounted (ctype_realType (ctype_getReturnType (u->utype))))) { ; } @@ -558,99 +569,72 @@ static /*@observer@*/ cstring uentry_reDefDecl (uentry old, uentry unew) /*@*/ } } - -/*drl7x*/ -constraintList uentry_getFcnPreconditions (uentry ue) +static constraintList uentry_getFunctionConditions (uentry ue, bool isPost) { if (uentry_isValid (ue)) { + functionConstraint constraint; + + DPRINTF((message ("called uentry_getFcnPostconditions on %s", + uentry_unparse (ue) ) ) ); + + if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue))) { - if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue))) + DPRINTF((message ("called uentry_getFunctionConditions on nonfunction %s", + uentry_unparse (ue) ) ) ); + if (!uentry_isFunction (ue) ) { - uentry_makeVarFunction (ue); + DPRINTF((message ("called uentry_getFunctionConditions on nonfunction %s", + uentry_unparse (ue) ) )); + return constraintList_undefined; } - - //llassert (uentry_isFunction (ue)); - //llassert ((ue->info->fcn->preconditions)); - //llassert ((ue->info->fcn->preconditions)); - if (!uentry_isFunction (ue)) - { - TPRINTF ( (message ("called uentry_getFcnPreconditions on nonfunction %s", - uentry_unparse (ue) ) ) ); - if (!uentry_isSpecified (ue) ) - { - TPRINTF((message ("called uentry_getFcnPreconditions on nonfunction %s", - uentry_unparse (ue) ) )); - return constraintList_undefined; - } + + return constraintList_undefined; + } + + if (!uentry_isFunction(ue)) + { + + DPRINTF((message ("called uentry_getFunctionConditions on non function %s", + uentry_unparse (ue) ) ) ); + return constraintList_undefined; + + } - return constraintList_undefined; - } + llassert (uentry_isFunction (ue)); - if (ue->info->fcn->preconditions) - { - return constraintList_copy (ue->info->fcn->preconditions); - } - else - { - return NULL; - } + if (isPost) + { + constraint = ue->info->fcn->postconditions; } - + else + { + constraint = ue->info->fcn->preconditions; + } + + return functionConstraint_getBufferConstraints (constraint); } return constraintList_undefined; } +/*drl7x*/ +/*@only@*/ constraintList uentry_getFcnPreconditions (uentry ue) +{ + return uentry_getFunctionConditions (ue, FALSE); +} /*drl 12/28/2000 */ + constraintList uentry_getFcnPostconditions (uentry ue) { - if (uentry_isValid (ue)) - { - { - if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue))) - { - uentry_makeVarFunction (ue); - } - - //llassert (uentry_isFunction (ue)); - //llassert ((ue->info->fcn->preconditions)); - /* if (!uentry_isSpecified (ue) ) - { - TPRINTF((message ("called uentry_getFcnPostconditions on nonfunction %s", - uentry_unparse (ue) ) )); - // return constraintList_undefined; - }*/ - - if (!uentry_isFunction (ue)) - { - /*llcontbug*/ TPRINTF( (message ("called uentry_getFcnPostconditions on nonfunction %s", - uentry_unparse (ue) ) ) ); - return constraintList_undefined; - } - - if (ue->info->fcn->postconditions) - { - return constraintList_copy (ue->info->fcn->postconditions); - } - else - { - return NULL; - } - } - - } - - return constraintList_undefined; - + return uentry_getFunctionConditions (ue, TRUE); } - static /*@only@*/ fileloc setLocation (void) { fileloc fl = context_getSaveLocation (); @@ -665,6 +649,12 @@ static /*@only@*/ fileloc setLocation (void) } } +static void uentry_setConstantValue (uentry ue, /*@only@*/ multiVal val) +{ + llassert (uentry_isEitherConstant (ue)); + sRef_setValue (ue->sref, val); +} + /*@notnull@*/ uentry uentry_makeEnumConstant (cstring n, ctype t) { fileloc loc = setLocation (); @@ -695,7 +685,6 @@ static /*@only@*/ fileloc setLocation (void) return ue; } -# ifndef NOLCL /*@notnull@*/ uentry uentry_makeSpecEnumConstant (cstring n, ctype t, fileloc loc) { uentry ue = uentry_makeConstant (n, t, loc); @@ -703,29 +692,32 @@ static /*@only@*/ fileloc setLocation (void) ue->ukind = KENUMCONST; return ue; } -# endif /*@notnull@*/ uentry uentry_makeVariableLoc (cstring n, ctype t) { return uentry_makeVariable (n, t, setLocation (), FALSE); } -# ifndef NOLCL +bool uentry_isUnnamedVariable (uentry ue) +{ + return uentry_isVariable (ue) && cstring_isUndefined (ue->uname); +} + /*@notnull@*/ /*@only@*/ uentry uentry_makeUnnamedVariable (ctype t) { return uentry_makeVariable (cstring_undefined, t, setLocation (), FALSE); } -# endif /*@notnull@*/ uentry uentry_makeIdDatatype (idDecl id) { ctype ct = idDecl_getCtype (id); uentry ue = uentry_makeDatatype (idDecl_observeId (id), ct, - MAYBE, MAYBE, setLocation ()); + MAYBE, qual_createUnknown (), + setLocation ()); uentry_reflectQualifiers (ue, idDecl_getQuals (id)); - if (!ynm_isOn (ue->info->datatype->abs)) + if (!qual_isEitherAbstract (ue->info->datatype->abs)) { if (ctype_isUnknown (ct)) { @@ -749,9 +741,12 @@ void uentry_checkParams (uentry ue) if (uentry_isRealFunction (ue)) { uentryList params = uentry_getParams (ue); + int paramno = 0; uentryList_elements (params, current) { + paramno++; + if (uentry_isValid (current)) { ctype ct = current->utype; @@ -765,24 +760,48 @@ void uentry_checkParams (uentry ue) } else { - voptgenerror - (FLG_FIXEDFORMALARRAY, - message ("Function parameter %q declared as " - "manifest array (size constant is meaningless)", - uentry_getName (current)), - uentry_whereDeclared (current)); + if (uentry_hasName (current)) + { + voptgenerror + (FLG_FIXEDFORMALARRAY, + message ("Function parameter %q declared as " + "manifest array (size constant is meaningless)", + uentry_getName (current)), + uentry_whereDeclared (current)); + } + else + { + voptgenerror + (FLG_FIXEDFORMALARRAY, + message ("Unnamed function parameter %d declared as " + "manifest array (size constant is meaningless)", + paramno), + uentry_whereDeclared (current)); + } } } else { if (ctype_isArray (ct)) { - voptgenerror - (FLG_FORMALARRAY, - message ("Function parameter %q declared as " - "array (treated as pointer)", - uentry_getName (current)), - uentry_whereDeclared (current)); + if (uentry_hasName (current)) + { + voptgenerror + (FLG_FORMALARRAY, + message ("Function parameter %q declared as " + "array (treated as pointer)", + uentry_getName (current)), + uentry_whereDeclared (current)); + } + else + { + voptgenerror + (FLG_FORMALARRAY, + message ("Unnamed function parameter %d declared as " + "array (treated as pointer)", + paramno), + uentry_whereDeclared (current)); + } } } @@ -856,24 +875,38 @@ static void reflectImplicitFunctionQualifiers (/*@notnull@*/ uentry ue, bool spe if (exkind_isKnown (ek)) { + DPRINTF (("Setting imp dependent: %s", + uentry_unparseFull (ue))); sRef_setAliasKind (ue->sref, AK_IMPDEPENDENT, fileloc_undefined); } else { if (context_getFlag (spec ? FLG_SPECRETIMPONLY : FLG_RETIMPONLY)) { + /* evans 2000-12-22 removed ctype_realType so it will + not apply to immutable abstract types. */ + if (ctype_isVisiblySharable - (ctype_realType (ctype_returnValue (ue->utype)))) + (ctype_realType (ctype_getReturnType (ue->utype)))) { if (uentryList_hasReturned (uentry_getParams (ue))) { ; } - else + else { - sRef_setAliasKind (ue->sref, AK_IMPONLY, - fileloc_undefined); - } + if (ctype_isImmutableAbstract (ctype_getReturnType (ue->utype))) + { + ; /* Immutable objects are not shared. */ + } + else + { + sRef_setAliasKind (ue->sref, AK_IMPONLY, + fileloc_undefined); + DPRINTF (("Ret imp only: %s", + ctype_unparse (ctype_getReturnType (ue->utype)))); + } + } } } } @@ -885,16 +918,21 @@ static /*@notnull@*/ uentry uentry_makeFunctionAux (cstring n, ctype t, typeIdSet access, /*@only@*/ globSet globs, - /*@only@*/ sRefSet mods, + /*@only@*/ sRefSet mods, + /*@only@*/ warnClause warn, /*@keep@*/ fileloc f, bool priv, /*@unused@*/ bool isForward) { uentry e = uentry_alloc (); ctype ret; + llassert (warnClause_isUndefined (warn)); /*@i325 remove parameter! */ + + DPRINTF (("Make function: %s", n)); + if (ctype_isFunction (t)) { - ret = ctype_returnValue (t); + ret = ctype_getReturnType (t); } else { @@ -923,7 +961,9 @@ uentry_makeFunctionAux (cstring n, ctype t, e->utype = t; e->storageclass = SCNONE; - e->sref = sRef_makeType (ret); + e->sref = sRef_makeResult (ret); /* evans 2001-07-19 - was sRef_makeType */ + + DPRINTF (("Result: %s", sRef_unparseFull (e->sref))); if (ctype_isUA (ret)) { @@ -936,6 +976,8 @@ uentry_makeFunctionAux (cstring n, ctype t, e->isPrivate = priv; e->hasNameError = FALSE; + e->warn = warn; + e->info = (uinfo) dmalloc (sizeof (*e->info)); e->info->fcn = (ufinfo) dmalloc (sizeof (*e->info->fcn)); @@ -943,7 +985,7 @@ uentry_makeFunctionAux (cstring n, ctype t, e->info->fcn->hasGlobs = globSet_isDefined (globs); e->info->fcn->exitCode = XK_UNKNOWN; - e->info->fcn->nullPred = QU_UNKNOWN; + e->info->fcn->nullPred = qual_createUnknown (); e->info->fcn->specialCode = SPC_NONE; e->info->fcn->access = access; @@ -970,16 +1012,198 @@ uentry_makeFunctionAux (cstring n, ctype t, return (e); } +static void uentry_reflectClauses (uentry ue, functionClauseList clauses) +{ + functionClauseList_elements (clauses, el) + { + DPRINTF (("Reflect clause: %s on %s", + functionClause_unparse (el), uentry_getName (ue))); + + if (functionClause_isNoMods (el)) + { + modifiesClause mel = functionClause_getModifies (el); + + if (uentry_hasGlobs (ue)) + { + voptgenerror + (FLG_SYNTAX, + message + ("No globals and modifies inconsistent to globals clause for %q: %q", + uentry_getName (ue), + globSet_unparse (uentry_getGlobs (ue))), + modifiesClause_getLoc (mel)); + + } + + if (uentry_hasMods (ue)) + { + voptgenerror + (FLG_SYNTAX, + message + ("No globals and modifies inconsistent to modifies clause for %q: %q", + uentry_getName (ue), + sRefSet_unparse (uentry_getMods (ue))), + modifiesClause_getLoc (mel)); + } + + uentry_setGlobals (ue, globSet_undefined); + uentry_setModifies (ue, sRefSet_undefined); + } + else if (functionClause_isGlobals (el)) + { + globalsClause glc = functionClause_getGlobals (el); + + DPRINTF (("Globals: %s / %s", uentry_unparse (ue), + globalsClause_unparse (glc))); + + if (uentry_hasGlobs (ue)) + { + vgenhinterror + (FLG_SYNTAX, + message + ("Multiple globals clauses for %q: %q", + uentry_getName (ue), + globalsClause_unparse (glc)), + cstring_makeLiteral ("Only one globals clause may be used. The second globals clause is ignored."), + globalsClause_getLoc (glc)); + + /* + uentry_setGlobals (ue, globalsClause_takeGlobs (glc)); + */ + } + else + { + DPRINTF (("Taking globs: %s", globalsClause_unparse (glc))); + uentry_setGlobals (ue, globalsClause_takeGlobs (glc)); + DPRINTF (("Taking globs after: %s", globalsClause_unparse (glc))); + } + } + else if (functionClause_isModifies (el)) + { + modifiesClause mlc = functionClause_getModifies (el); + + DPRINTF (("Has modifies: %s", uentry_unparseFull (ue))); + + if (uentry_hasMods (ue)) + { + /* + ** Not an error: + + if (optgenerror + (FLG_SYNTAX, + message + ("Multiple modifies clauses for %s: %s", + uentry_getName (ue), + modifiesClause_unparse (mlc)), + modifiesClause_getLoc (mlc))) + { + llhint (message ("Previous modifies clause: ", + sRefSet_unparse (uentry_getMods (ue)))); + } + + ** + */ + + uentry_combineModifies (ue, modifiesClause_takeMods (mlc)); /*@i32@*/ + } + else + { + uentry_setModifies (ue, modifiesClause_takeMods (mlc)); + } + } + else if (functionClause_isEnsures (el)) + { + functionConstraint cl = functionClause_takeEnsures (el); + DPRINTF (("Setting post: %s / %s", + uentry_unparse (ue), functionConstraint_unparse (cl))); + uentry_setPostconditions (ue, cl); + } + else if (functionClause_isRequires (el)) + { + functionConstraint cl = functionClause_takeRequires (el); + uentry_setPreconditions (ue, cl); + } + else if (functionClause_isState (el)) + { + stateClause sc = functionClause_takeState (el); + + if (stateClause_isBefore (sc) && stateClause_setsMetaState (sc)) + { + sRefSet rfs = stateClause_getRefs (sc); + + sRefSet_elements (rfs, s) + { + if (sRef_isParam (s)) + { + /* + ** Can't use requires on parameters + */ + + voptgenerror + (FLG_ANNOTATIONERROR, + message ("Requires clauses for %q concerns parameters %q should be " + "a parameter annotation instead: %q", + uentry_unparse (ue), + sRef_unparse (s), + stateClause_unparse (sc)), + stateClause_loc (sc)); + } + } end_sRefSet_elements ; + } + + DPRINTF (("State clause: %s", stateClause_unparse (sc))); + uentry_addStateClause (ue, sc); + } + else if (functionClause_isWarn (el)) + { + warnClause wc = functionClause_takeWarn (el); + uentry_addWarning (ue, wc); + } + else + { + DPRINTF (("Unhandled clause: %s", functionClause_unparse (el))); + } + } end_functionClauseList_elements ; + + DPRINTF (("Checking all: %s", sRef_unparseFull (ue->sref))); + stateClauseList_checkAll (ue); +} + /*@notnull@*/ uentry uentry_makeIdFunction (idDecl id) { + bool leaveFunc = FALSE; uentry ue = uentry_makeFunction (idDecl_observeId (id), idDecl_getCtype (id), typeId_invalid, globSet_undefined, - sRefSet_undefined, + sRefSet_undefined, warnClause_undefined, setLocation ()); - + + DPRINTF (("Id function: %s", sRef_unparseFull (ue->sref))); + + /* + ** This makes parameters names print out correctly. + ** (But we might be a local variable declaration for a function type...) + */ + + if (context_inFunctionLike ()) + { + DPRINTF (("Header: %s / %s", + uentry_unparse (context_getHeader ()), + idDecl_unparse (id))); + } + else + { + context_enterFunctionDeclaration (ue); + leaveFunc = TRUE; + } + + DPRINTF (("Id function: %s", sRef_unparseFull (ue->sref))); uentry_reflectQualifiers (ue, idDecl_getQuals (id)); + DPRINTF (("Id function: %s", sRef_unparseFull (ue->sref))); reflectImplicitFunctionQualifiers (ue, FALSE); + DPRINTF (("Id function: %s", sRef_unparseFull (ue->sref))); + uentry_reflectClauses (ue, idDecl_getClauses (id)); + DPRINTF (("Id function: %s", sRef_unparseFull (ue->sref))); if (!uentry_isStatic (ue) && cstring_equalLit (ue->uname, "main")) @@ -990,7 +1214,7 @@ uentry_makeFunctionAux (cstring n, ctype t, llassert (ctype_isFunction (typ)); - retval = ctype_returnValue (typ); + retval = ctype_getReturnType (typ); if (!ctype_isInt (retval)) { @@ -1014,7 +1238,7 @@ uentry_makeFunctionAux (cstring n, ctype t, { voptgenerror (FLG_MAINTYPE, - message ("Function main declared with %d arg%p, " + message ("Function main declared with %d arg%&, " "should have 2 (int argc, char *argv[])", uentryList_size (args)), uentry_whereLast (ue)); @@ -1056,6 +1280,11 @@ uentry_makeFunctionAux (cstring n, ctype t, } } + if (leaveFunc) + { + context_exitFunctionDeclaration (); + } + return ue; } @@ -1070,6 +1299,7 @@ static void uentry_implicitParamAnnots (/*@notnull@*/ uentry e) if (exkind_isKnown (ek)) { + DPRINTF (("imp dep: %s", uentry_unparseFull (e))); sRef_setAliasKind (e->sref, AK_IMPDEPENDENT, fileloc_undefined); sRef_setOrigAliasKind (e->sref, AK_IMPDEPENDENT); } @@ -1082,24 +1312,31 @@ static void uentry_implicitParamAnnots (/*@notnull@*/ uentry e) } static /*@only@*/ /*@notnull@*/ uentry -uentry_makeVariableParamAux (cstring n, ctype t, sRef s, sstate defstate) +uentry_makeVariableParamAux (cstring n, ctype t, /*@dependent@*/ sRef s, + /*@only@*/ fileloc loc, sstate defstate) /*@i32 exposed*/ { cstring pname = makeParam (n); - uentry e = uentry_makeVariableAux (pname, t, setLocation (), s, FALSE, VKPARAM); + uentry e; + + DPRINTF (("Sref: %s", sRef_unparseFull (s))); + e = uentry_makeVariableAux (pname, t, loc, s, FALSE, VKPARAM); cstring_free (pname); + DPRINTF (("Param: %s", uentry_unparseFull (e))); uentry_implicitParamAnnots (e); + DPRINTF (("Param: %s", uentry_unparseFull (e))); if (!sRef_isAllocated (e->sref) && !sRef_isPartial (e->sref)) { + DPRINTF (("Param: %s", uentry_unparseFull (e))); sRef_setDefState (e->sref, defstate, uentry_whereDeclared (e)); e->info->var->defstate = defstate; } + DPRINTF (("Param: %s", uentry_unparseFull (e))); return (e); } -# ifndef NOLCL void uentry_setRefCounted (uentry e) { @@ -1109,7 +1346,6 @@ uentry_setRefCounted (uentry e) sRef_storeState (e->sref); } } -# endif void uentry_setStatic (uentry c) @@ -1180,7 +1416,7 @@ void checkGlobalsModifies (/*@notnull@*/ uentry ue, sRefSet sr) { sRef base = sRef_getRootBase (el); - if (sRef_isGlobal (base) || sRef_isInternalState (base) + if (sRef_isFileOrGlobalScope (base) || sRef_isInternalState (base) || (sRef_isKindSpecial (base) && !sRef_isNothing (base))) { if (!globSet_member (ue->info->fcn->globs, base)) @@ -1213,9 +1449,9 @@ void checkGlobalsModifies (/*@notnull@*/ uentry ue, sRefSet sr) } uentry -uentry_makeVariableSrefParam (cstring n, ctype t, sRef s) +uentry_makeVariableSrefParam (cstring n, ctype t, /*@only@*/ fileloc loc, /*@exposed@*/ sRef s) { - return (uentry_makeVariableParamAux (n, t, s, SS_UNKNOWN)); + return (uentry_makeVariableParamAux (n, t, s, loc, SS_UNKNOWN)); } void @@ -1238,18 +1474,34 @@ uentry_fixupSref (uentry ue) if (uentry_isVariable (ue)) { + + /*@i634 ue->sref = sRef_saveCopyShallow (ue->info->var->origsref); */ sRef_setDefState (sr, ue->info->var->defstate, fileloc_undefined); sRef_setNullState (sr, ue->info->var->nullstate, fileloc_undefined); } } -void uentry_setSpecialClauses (uentry ue, specialClauses clauses) +static void uentry_addStateClause (/*@notnull@*/ uentry ue, stateClause sc) +{ + /* + ** Okay to allow multiple clauses of the same kind. + */ /*@i834 is this true?@*/ + + ue->info->fcn->specclauses = + stateClauseList_add (ue->info->fcn->specclauses, sc); + + /* Will call checkAll to check later... */ +} + +void uentry_setStateClauseList (uentry ue, stateClauseList clauses) { llassert (uentry_isFunction (ue)); - llassert (!specialClauses_isDefined (ue->info->fcn->specclauses)); + llassert (!stateClauseList_isDefined (ue->info->fcn->specclauses)); + DPRINTF (("checked clauses: %s", stateClauseList_unparse (clauses))); ue->info->fcn->specclauses = clauses; - specialClauses_checkAll (ue); + stateClauseList_checkAll (ue); + DPRINTF (("checked clauses: %s", uentry_unparseFull (ue))); } /* @@ -1266,22 +1518,30 @@ void uentry_setSpecialClauses (uentry ue, specialClauses clauses) ** If it doesn't have modifies, set them to sr. */ -void -uentry_setModifies (uentry ue, /*@owned@*/ sRefSet sr) +static bool +uentry_checkModifiesContext (void) { if (sRef_modInFunction ()) { llparseerror - (message ("Modifies list not in function context. " - "A modifies list can only appear following the parameter list " - "in a function declaration or header.")); - - /*@-mustfree@*/ return; /*@=mustfree@*/ + (message + ("Modifies list not in function context. " + "A modifies list can only appear following the parameter list " + "in a function declaration or header.")); + + return FALSE; } + + return TRUE; +} - if (sRefSet_hasStatic (sr)) +void +uentry_setModifies (uentry ue, /*@owned@*/ sRefSet sr) +{ + if (!uentry_checkModifiesContext ()) { - context_recordFileModifies (sr); + sRefSet_free (sr); + return; } if (uentry_isValid (ue)) @@ -1293,11 +1553,7 @@ uentry_setModifies (uentry ue, /*@owned@*/ sRefSet sr) } else { - if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue))) - { - uentry_makeVarFunction (ue); - } - + uentry_convertVarFunction (ue); llassertfatal (uentry_isFunction (ue)); llassert (sRefSet_isUndefined (ue->info->fcn->mods)); @@ -1311,6 +1567,11 @@ uentry_setModifies (uentry ue, /*@owned@*/ sRefSet sr) { ue->info->fcn->hasGlobs = TRUE; } + + if (sRefSet_hasStatic (ue->info->fcn->mods)) + { + context_recordFileModifies (ue->info->fcn->mods); + } } else { @@ -1318,37 +1579,103 @@ uentry_setModifies (uentry ue, /*@owned@*/ sRefSet sr) } } -void -uentry_setPreconditions (uentry ue, /*@owned@*/ constraintList preconditions) +static void +uentry_combineModifies (uentry ue, /*@owned@*/ sRefSet sr) { - if (sRef_modInFunction ()) - { - llparseerror - (message ("Precondition list not in function context. " - "A precondition list can only appear following the parameter list " - "in a function declaration or header.")); + /* + ** Function already has one modifies clause (possibly from + ** a specification). + */ - /*@-mustfree@*/ return; /*@=mustfree@*/ + if (!uentry_checkModifiesContext ()) + { + BADBRANCH; + } + + llassert (uentry_isValid (ue)); + + if (uentry_isIter (ue)) + { + ue->info->iter->mods = sRefSet_unionFree (ue->info->iter->mods, sr); + } + else + { + llassertfatal (uentry_isFunction (ue)); + llassert (ue->info->fcn->hasMods); + + checkGlobalsModifies (ue, sr); + ue->info->fcn->mods = sRefSet_unionFree (ue->info->fcn->mods, sr); + + if (context_getFlag (FLG_MODIFIESIMPNOGLOBALS)) + { + ue->info->fcn->hasGlobs = TRUE; + } + } + + if (sRefSet_hasStatic (ue->info->fcn->mods)) + { + context_recordFileModifies (ue->info->fcn->mods); + } +} + +bool uentry_hasWarning (uentry ue) +{ + return (uentry_isValid (ue) + && warnClause_isDefined (ue->warn)); +} + +void uentry_addWarning (uentry ue, /*@only@*/ warnClause warn) +{ + llassert (uentry_isValid (ue)); + llassert (warnClause_isUndefined (ue->warn)); + ue->warn = warn; +} + +void +uentry_setPreconditions (uentry ue, /*@only@*/ functionConstraint preconditions) +{ + if (sRef_modInFunction ()) + { + llparseerror + (message ("Precondition list not in function context. " + "A precondition list can only appear following the parameter list " + "in a function declaration or header.")); + + /*@-mustfree@*/ return; /*@=mustfree@*/ } if (uentry_isValid (ue)) { + uentry_convertVarFunction (ue); + llassertfatal (uentry_isFunction (ue)); + + if (functionConstraint_isDefined (ue->info->fcn->preconditions)) + { + /*drl oops this date is wronge...*/ + /* drl 11-29-2002 + I changed this so it didn't appear as a Splint bug + among other things this gets triggered when there is + a function with two requires clauses. Now Splint + prints an error and tries to conjoin the lists. + */ + llparseerror + (message ("Duplicate precondition list" + "Attemping the conjoin the requires clauses" + )); + + + /* should conjoin constraints? */ + /*@notreached@*/ + ue->info->fcn->preconditions = functionConstraint_conjoin (ue->info->fcn->preconditions, preconditions); + } + else { - if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue))) - { - uentry_makeVarFunction (ue); - } - - llassertfatal (uentry_isFunction (ue)); - // llassert (sRefSet_isUndefined (ue->info->fcn->mods)); - ue->info->fcn->preconditions = preconditions; } - } else { - // + llfatalbug ((message("uentry_setPreconditions called with invalid uentry") )); } } @@ -1357,7 +1684,7 @@ uentry_setPreconditions (uentry ue, /*@owned@*/ constraintList preconditions) added 12/28/2000 */ void -uentry_setPostconditions (uentry ue, /*@owned@*/ constraintList postconditions) +uentry_setPostconditions (uentry ue, /*@only@*/ functionConstraint postconditions) { if (sRef_modInFunction ()) { @@ -1365,28 +1692,27 @@ uentry_setPostconditions (uentry ue, /*@owned@*/ constraintList postconditions) (message ("Postcondition list not in function context. " "A postcondition list can only appear following the parameter list " "in a function declaration or header.")); - + /*@-mustfree@*/ return; /*@=mustfree@*/ } if (uentry_isValid (ue)) { + uentry_convertVarFunction (ue); + llassertfatal (uentry_isFunction (ue)); + + if (functionConstraint_isUndefined (ue->info->fcn->postconditions)) { - if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue))) - { - uentry_makeVarFunction (ue); - } - - llassertfatal (uentry_isFunction (ue)); - // llassert (sRefSet_isUndefined (ue->info->fcn->mods)); - ue->info->fcn->postconditions = postconditions; } - + else + { + ue->info->fcn->postconditions = functionConstraint_conjoin (ue->info->fcn->postconditions, postconditions); + } } else { - // + llfatalbug ((message("uentry_setPostconditions called with invalid uentry") )); } } @@ -1552,8 +1878,8 @@ checkGlobalsConformance (/*@notnull@*/ uentry old, } } - unew->info->fcn->globs = globSet_copy (unew->info->fcn->globs, - old->info->fcn->globs); + unew->info->fcn->globs = globSet_copyInto (unew->info->fcn->globs, + old->info->fcn->globs); } } @@ -1714,6 +2040,8 @@ static void if (!ctype_isRealPointer (ct) && !ctype_isRealAbstract (ct)) { + DPRINTF (("Check mutable: %s", uentry_unparseFull (ue))); + voptgenerror (FLG_MUTREP, message ("Mutable abstract type %q declared without pointer " "indirection: %t (violates assignment semantics)", @@ -1800,12 +2128,13 @@ uentry_reflectOtherQualifier (/*@notnull@*/ uentry ue, qual qel) { if (!uentry_isRefCounted (ue)) { - llerror - (FLG_SYNTAX, + voptgenerror + (FLG_ANNOTATIONERROR, message ("Reference counting qualifier %s used on non-reference " "counted storage: %q", qual_unparse (qel), - uentry_unparse (ue))); + uentry_unparse (ue)), + uentry_whereLast (ue)); } else { @@ -1832,13 +2161,14 @@ uentry_reflectOtherQualifier (/*@notnull@*/ uentry ue, qual qel) { if (uentry_isValid (refs)) { - llerror - (FLG_SYNTAX, + voptgenerror + (FLG_ANNOTATIONERROR, message ("Reference counted structure type %s has " "multiple refs fields: %q and %q", ctype_unparse (ct), uentry_getName (refs), - uentry_getName (field))); + uentry_getName (field)), + uentry_whereLast (field)); } refs = field; @@ -1859,11 +2189,12 @@ uentry_reflectOtherQualifier (/*@notnull@*/ uentry ue, qual qel) } else if (!ctype_isInt (uentry_getType (refs))) { - llerror - (FLG_SYNTAX, + voptgenerror + (FLG_ANNOTATIONERROR, message ("Reference counted structure type %s refs field has " "type %s (should be int)", ctype_unparse (ct), - ctype_unparse (uentry_getType (refs)))); + ctype_unparse (uentry_getType (refs))), + uentry_whereLast (refs)); } else { @@ -1882,11 +2213,12 @@ uentry_reflectOtherQualifier (/*@notnull@*/ uentry ue, qual qel) } else { - llerror - (FLG_SYNTAX, + voptgenerror + (FLG_ANNOTATIONERROR, message ("Non-pointer to structure type %s declared with " "refcounted qualifier", - ctype_unparse (ct))); + ctype_unparse (ct)), + uentry_whereLast (ue)); } } } @@ -1898,10 +2230,11 @@ uentry_reflectOtherQualifier (/*@notnull@*/ uentry ue, qual qel) } else { - llerror - (FLG_SYNTAX, + voptgenerror + (FLG_ANNOTATIONERROR, message ("Refs qualifier used on non-structure field: %q", - uentry_unparse (ue))); + uentry_unparse (ue)), + uentry_whereLast (ue)); } } else if (qual_isAliasQual (qel)) @@ -1920,16 +2253,18 @@ uentry_reflectOtherQualifier (/*@notnull@*/ uentry ue, qual qel) if (uentry_isEitherConstant (ue)) { - llerror - (FLG_SYNTAX, + voptgenerror + (FLG_ANNOTATIONERROR, message ("Alias qualifier %s used on constant: %q", - alkind_unparse (ak), uentry_unparse (ue))); + alkind_unparse (ak), uentry_unparse (ue)), + uentry_whereLast (ue)); + okay = FALSE; } if (ctype_isFunction (ut)) { - ut = ctype_returnValue (ut); + ut = ctype_getReturnType (ut); } if (!(ctype_isVisiblySharable (ut) @@ -1938,10 +2273,11 @@ uentry_reflectOtherQualifier (/*@notnull@*/ uentry ue, qual qel) { if (!qual_isImplied (qel)) { - llerror - (FLG_SYNTAX, + voptgenerror + (FLG_ANNOTATIONERROR, message ("Alias qualifier %s used on unsharable storage type %t: %q", - alkind_unparse (ak), ut, uentry_getName (ue))); + alkind_unparse (ak), ut, uentry_getName (ue)), + uentry_whereLast (ue)); } okay = FALSE; @@ -1956,12 +2292,13 @@ uentry_reflectOtherQualifier (/*@notnull@*/ uentry ue, qual qel) { if (!qual_isImplied (qel)) { - llerror - (FLG_SYNTAX, + voptgenerror + (FLG_ANNOTATIONERROR, message ("Alias qualifier %s used on reference counted storage: %q", alkind_unparse (ak), - uentry_unparse (ue))); + uentry_unparse (ue)), + uentry_whereLast (ue)); } okay = FALSE; @@ -1971,10 +2308,11 @@ uentry_reflectOtherQualifier (/*@notnull@*/ uentry ue, qual qel) { if (qual_isRefQual (qel)) { - llerror - (FLG_SYNTAX, + voptgenerror + (FLG_ANNOTATIONERROR, message ("Qualifier %s used on non-reference counted storage: %q", - alkind_unparse (ak), uentry_unparse (ue))); + alkind_unparse (ak), uentry_unparse (ue)), + uentry_whereLast (ue)); okay = FALSE; } @@ -2009,26 +2347,32 @@ uentry_reflectOtherQualifier (/*@notnull@*/ uentry ue, qual qel) uentry_setNullState (ue, NS_MNOTNULL); } else if (qual_isAbstract (qel) + || qual_isNumAbstract (qel) || qual_isConcrete (qel)) { if (!uentry_isDatatype (ue)) { - llerror - (FLG_SYNTAX, + voptgenerror + (FLG_ANNOTATIONERROR, message ("Qualifier %s used with non-datatype", - qual_unparse (qel))); + qual_unparse (qel)), + uentry_whereLast (ue)); } else { - ue->info->datatype->abs = ynm_fromBool (qual_isAbstract (qel)); + ue->info->datatype->abs = qel; + DPRINTF (("Setting abstract %s: %s", + uentry_unparse (ue), qual_unparse (qel))); } } else if (qual_isMutable (qel)) { if (!uentry_isDatatype (ue)) { - llerror (FLG_SYNTAX, - message ("Qualifier %s used with non-datatype", qual_unparse (qel))); + voptgenerror + (FLG_ANNOTATIONERROR, + message ("Qualifier %s used with non-datatype", qual_unparse (qel)), + uentry_whereLast (ue)); } else { @@ -2044,8 +2388,10 @@ uentry_reflectOtherQualifier (/*@notnull@*/ uentry ue, qual qel) { if (!uentry_isDatatype (ue)) { - llerror (FLG_SYNTAX, message ("Qualifier %s used with non-datatype", - qual_unparse (qel))); + voptgenerror (FLG_ANNOTATIONERROR, + message ("Qualifier %s used with non-datatype", + qual_unparse (qel)), + uentry_whereLast (ue)); } else { @@ -2054,15 +2400,12 @@ uentry_reflectOtherQualifier (/*@notnull@*/ uentry ue, qual qel) } else if (qual_isNullPred (qel)) { - if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue))) - { - uentry_makeVarFunction (ue); - } - + uentry_convertVarFunction (ue); + if (uentry_isFunction (ue)) { ctype typ = uentry_getType (ue); - ctype rtype = ctype_returnValue (uentry_getType (ue)); + ctype rtype = ctype_getReturnType (uentry_getType (ue)); if (ctype_isRealBool (rtype)) { @@ -2074,27 +2417,30 @@ uentry_reflectOtherQualifier (/*@notnull@*/ uentry ue, qual qel) } else { - llerror (FLG_SYNTAX, - message ("Qualifier %s used with function having %d " - "arguments (should have 1)", - qual_unparse (qel), - uentryList_size (pl))); + voptgenerror (FLG_ANNOTATIONERROR, + message ("Qualifier %s used with function having %d " + "arguments (should have 1)", + qual_unparse (qel), + uentryList_size (pl)), + uentry_whereLast (ue)); } } else { - llerror (FLG_SYNTAX, - message ("Qualifier %s used with function returning %s " - "(should return bool)", - qual_unparse (qel), - ctype_unparse (rtype))); + voptgenerror (FLG_ANNOTATIONERROR, + message ("Qualifier %s used with function returning %s " + "(should return bool)", + qual_unparse (qel), + ctype_unparse (rtype)), + uentry_whereLast (ue)); } } else { - llerror (FLG_SYNTAX, - message ("Qualifier %s used with non-function", - qual_unparse (qel))); + voptgenerror (FLG_ANNOTATIONERROR, + message ("Qualifier %s used with non-function", + qual_unparse (qel)), + uentry_whereLast (ue)); } } else if (qual_isExitQual (qel)) @@ -2105,11 +2451,12 @@ uentry_reflectOtherQualifier (/*@notnull@*/ uentry ue, qual qel) { if (exitkind_isKnown (ue->info->fcn->exitCode)) { - llerror (FLG_SYNTAX, - message ("Multiple exit qualifiers used on function %q: %s, %s", - uentry_getName (ue), - exitkind_unparse (ue->info->fcn->exitCode), - exitkind_unparse (exk))); + voptgenerror (FLG_ANNOTATIONERROR, + message ("Multiple exit qualifiers used on function %q: %s, %s", + uentry_getName (ue), + exitkind_unparse (ue->info->fcn->exitCode), + exitkind_unparse (exk)), + uentry_whereLast (ue)); } ue->info->fcn->exitCode = exk; @@ -2123,10 +2470,38 @@ uentry_reflectOtherQualifier (/*@notnull@*/ uentry ue, qual qel) } else { - llerror (FLG_SYNTAX, - message ("Exit qualifier %s used with non-function (type %s)", - qual_unparse (qel), - ctype_unparse (uentry_getType (ue)))); + voptgenerror (FLG_ANNOTATIONERROR, + message ("Exit qualifier %s used with non-function (type %s)", + qual_unparse (qel), + ctype_unparse (uentry_getType (ue))), + uentry_whereLast (ue)); + } + } + } + else if (qual_isMetaState (qel)) + { + annotationInfo ainfo = qual_getAnnotationInfo (qel); + + if (annotationInfo_matchesContext (ainfo, ue)) + { + DPRINTF (("Reflecting %s on %s", + annotationInfo_unparse (ainfo), + uentry_unparseFull (ue))); + + sRef_reflectAnnotation (ue->sref, ainfo, g_currentloc); + DPRINTF (("==> %s", sRef_unparseFull (ue->sref))); + DPRINTF (("==> %s", uentry_unparseFull (ue))); + } + else + { + if (optgenerror + (FLG_ANNOTATIONERROR, + message ("Attribute annotation %s used in inconsistent context: %q", + qual_unparse (qel), + uentry_unparse (ue)), + uentry_whereLast (ue))) + { + /*@i! annotationInfo_showContextError (ainfo, ue); */ } } } @@ -2138,7 +2513,7 @@ uentry_reflectOtherQualifier (/*@notnull@*/ uentry ue, qual qel) } else { - llbug (message ("unhandled qualifier: %s", qual_unparse (qel))); + llbug (message ("Unhandled qualifier: %s", qual_unparse (qel))); } } } @@ -2148,6 +2523,9 @@ uentry_reflectQualifiers (uentry ue, qualList q) { llassert (uentry_isValid (ue)); + DPRINTF (("Reflect qualifiers: %s / %s", + uentry_unparseFull (ue), qualList_unparse (q))); + qualList_elements (q, qel) { if (qual_isStatic (qel)) @@ -2157,6 +2535,7 @@ uentry_reflectQualifiers (uentry ue, qualList q) else if (qual_isUnused (qel)) { uentry_setUsed (ue, fileloc_undefined); + DPRINTF (("Used: %s", uentry_unparseFull (ue))); } else if (qual_isExternal (qel)) { @@ -2173,11 +2552,12 @@ uentry_reflectQualifiers (uentry ue, qualList q) if (vk == VKYIELDPARAM) { - llerror - (FLG_SYNTAX, + voptgenerror + (FLG_ANNOTATIONERROR, message ("Qualifier sef cannot be used with %s: %q", cstring_makeLiteralTemp (vk == VKYIELDPARAM ? "yield" : "returned"), - uentry_unparse (ue))); + uentry_unparse (ue)), + uentry_whereLast (ue)); } else if (vk == VKRETPARAM) { @@ -2190,10 +2570,11 @@ uentry_reflectQualifiers (uentry ue, qualList q) } else { - llerror - (FLG_SYNTAX, + voptgenerror + (FLG_ANNOTATIONERROR, message ("Qualifier sef is meaningful only on parameters: %q", - uentry_unparse (ue))); + uentry_unparse (ue)), + uentry_whereLast (ue)); } } else if (qual_isExtern (qel)) @@ -2202,6 +2583,9 @@ uentry_reflectQualifiers (uentry ue, qualList q) } else if (qual_isGlobalQual (qel)) /* undef, killed */ { + DPRINTF (("Reflecting qual: %s / %s", + qual_unparse (qel), uentry_unparse (ue))); + if (uentry_isVariable (ue)) { sstate oldstate = ue->info->var->defstate; @@ -2223,21 +2607,21 @@ uentry_reflectQualifiers (uentry ue, qualList q) } else { - llerror - (FLG_SYNTAX, + voptgenerror + (FLG_ANNOTATIONERROR, message ("Qualifier %s used on non-variable: %q", - qual_unparse (qel), uentry_unparse (ue))); + qual_unparse (qel), uentry_unparse (ue)), + uentry_whereLast (ue)); } + + DPRINTF (("After: %s", uentry_unparseFull (ue))); } /* start modifications */ - else if( qual_isBufQualifier(qel) ) { ctype ct = ctype_realType(uentry_getType(ue)); - if( ctype_isArray(ct) || ctype_isPointer(ct) ) { if( uentry_hasBufStateInfo(ue) ) { - if( qual_isNullTerminated(qel) ) { /* handle Nullterm */ if (uentry_isAnyParam(ue) || uentry_isReturned (ue)) { @@ -2286,6 +2670,7 @@ uentry_reflectQualifiers (uentry ue, qualList q) message ("Qualifier %s used on non-pointer: %q", qual_unparse (qel), uentry_unparse (ue))); } + DPRINTF (("After: %s", uentry_unparseFull (ue))); }/* end else if */ else if (qual_isAllocQual (qel)) /* out, partial, reldef, special, etc. */ { @@ -2294,7 +2679,7 @@ uentry_reflectQualifiers (uentry ue, qualList q) if (ctype_isFunction (realType)) { - realType = ctype_realType (ctype_returnValue (realType)); + realType = ctype_realType (ctype_getReturnType (realType)); } if (qual_isRelDef (qel)) @@ -2308,10 +2693,11 @@ uentry_reflectQualifiers (uentry ue, qualList q) && !ctype_isUnknown (realType) && !ctype_isAbstract (ue->utype)) { - llerror - (FLG_SYNTAX, + voptgenerror + (FLG_ANNOTATIONERROR, message ("Qualifier %s used on non-pointer or struct: %q", - qual_unparse (qel), uentry_unparse (ue))); + qual_unparse (qel), uentry_unparse (ue)), + uentry_whereLast (ue)); } } @@ -2331,10 +2717,11 @@ uentry_reflectQualifiers (uentry ue, qualList q) } else { - llerror - (FLG_SYNTAX, + voptgenerror + (FLG_ANNOTATIONERROR, message ("Qualifier %s used on non-iterator parameter: %q", - qual_unparse (qel), uentry_unparse (ue))); + qual_unparse (qel), uentry_unparse (ue)), + uentry_whereLast (ue)); } } else if (qual_isExQual (qel)) @@ -2342,9 +2729,12 @@ uentry_reflectQualifiers (uentry ue, qualList q) exkind ek = exkind_fromQual (qel); ctype ut = uentry_getType (ue); + DPRINTF (("Reflect ex qual: %s / %s", + uentry_unparse (ue), exkind_unparse (ek))); + if (ctype_isFunction (ut)) { - ut = ctype_returnValue (ut); + ut = ctype_getReturnType (ut); } if (!(ctype_isVisiblySharable (ut)) @@ -2353,10 +2743,19 @@ uentry_reflectQualifiers (uentry ue, qualList q) { if (!qual_isImplied (qel)) { - llerror - (FLG_SYNTAX, - message ("Qualifier %s used on unsharable storage type %t: %q", - exkind_unparse (ek), ut, uentry_getName (ue))); + if (ctype_isImmutableAbstract (ut)) { + voptgenerror + (FLG_REDUNDANTSHAREQUAL, + message ("Qualifier %s used on unsharable storage type %t: %q", + exkind_unparse (ek), ut, uentry_getName (ue)), + uentry_whereLast (ue)); + } else { + voptgenerror + (FLG_MISPLACEDSHAREQUAL, + message ("Qualifier %s used on unsharable storage type %t: %q", + exkind_unparse (ek), ut, uentry_getName (ue)), + uentry_whereLast (ue)); + } } } else @@ -2364,11 +2763,13 @@ uentry_reflectQualifiers (uentry ue, qualList q) alkind ak = sRef_getAliasKind (ue->sref); sRef_setExKind (ue->sref, ek, uentry_whereDeclared (ue)); + DPRINTF (("Set exkind: %s", sRef_unparseFull (ue->sref))); if (alkind_isUnknown (ak) || alkind_isImplicit (ak) || alkind_isStatic (ak)) { if (!alkind_isTemp (ak)) { + DPRINTF (("imp dep: %s", uentry_unparseFull (ue))); uentry_setAliasKind (ue, AK_IMPDEPENDENT); } } @@ -2446,6 +2847,8 @@ uentry_reflectQualifiers (uentry ue, qualList q) } end_qualList_elements; qualList_clear (q); + + DPRINTF (("Done: %s", sRef_unparseFull (ue->sref))); } bool @@ -2512,14 +2915,28 @@ bool uentry_isNonLocal (uentry ue) { return (uentry_isValid (ue) && uentry_isVariable (ue) - && (sRef_isGlobal (ue->sref) || uentry_isStatic (ue))); + && (sRef_isFileOrGlobalScope (ue->sref) || uentry_isStatic (ue))); +} + +bool +uentry_isGlobalVariable (uentry ue) +{ + return (uentry_isValid (ue) && uentry_isVariable (ue) + && sRef_isFileOrGlobalScope (ue->sref)); } bool -uentry_isGlobal (uentry ue) +uentry_isVisibleExternally (uentry ue) { - return (uentry_isValid (ue) && uentry_isVariable (ue) && - sRef_isGlobal (ue->sref)); + return (uentry_isValid (ue) + && ((uentry_isVariable (ue) && sRef_isRealGlobal (ue->sref)) + || (!uentry_isStatic (ue) + && (uentry_isFunction (ue) + || uentry_isIter (ue) + || uentry_isEndIter (ue) + || uentry_isConstant (ue) + || uentry_isDatatype (ue) + || uentry_isAnyTag (ue))))); } bool @@ -2619,11 +3036,7 @@ static void checkSpecialFunction (/*@notnull@*/ uentry ue) void uentry_setPrintfLike (uentry ue) { - if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue))) - { - uentry_makeVarFunction (ue); - } - + uentry_convertVarFunction (ue); llassertfatal (uentry_isFunction (ue)); ue->info->fcn->specialCode = SPC_PRINTFLIKE; checkSpecialFunction (ue); @@ -2632,11 +3045,7 @@ uentry_setPrintfLike (uentry ue) void uentry_setScanfLike (uentry ue) { - if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue))) - { - uentry_makeVarFunction (ue); - } - + uentry_convertVarFunction (ue); llassertfatal (uentry_isFunction (ue)); ue->info->fcn->specialCode = SPC_SCANFLIKE; checkSpecialFunction (ue); @@ -2645,11 +3054,7 @@ uentry_setScanfLike (uentry ue) void uentry_setMessageLike (uentry ue) { - if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue))) - { - uentry_makeVarFunction (ue); - } - + uentry_convertVarFunction (ue); llassertfatal (uentry_isFunction (ue)); ue->info->fcn->specialCode = SPC_MESSAGELIKE; checkSpecialFunction (ue); @@ -2666,9 +3071,11 @@ uentry_isSpecialFunction (uentry ue) { ctype ct = idDecl_getCtype (t); ctype base = ct; - sRef pref = sRef_makeParam (i, ct); - uentry ue = uentry_makeVariableSrefParam (idDecl_observeId (t), ct, pref); + fileloc loc = setLocation (); + sRef pref = sRef_makeParam (i, ct, stateInfo_makeLoc (loc, SA_CREATED)); + uentry ue = uentry_makeVariableSrefParam (idDecl_observeId (t), ct, loc, pref); + DPRINTF (("Make param: %s", uentry_unparseFull (ue))); uentry_reflectQualifiers (ue, idDecl_getQuals (t)); uentry_implicitParamAnnots (ue); @@ -2698,6 +3105,7 @@ uentry_isSpecialFunction (uentry ue) } } + DPRINTF (("Param: %s", uentry_unparseFull (ue))); return ue; } @@ -2713,7 +3121,7 @@ uentry_isSpecialFunction (uentry ue) { fileloc loc = setLocation (); uentry ue = uentry_makeVariable (idDecl_observeId (t), ct, loc, FALSE); - + uentry_reflectQualifiers (ue, idDecl_getQuals (t)); if (!uentry_isExtern (ue)) @@ -2725,20 +3133,18 @@ uentry_isSpecialFunction (uentry ue) } } -# ifndef NOLCL -/*@notnull@*/ uentry uentry_makeVariableParam (cstring n, ctype t) +/*@notnull@*/ uentry uentry_makeVariableParam (cstring n, ctype t, fileloc loc) { - return (uentry_makeVariableParamAux (n, t, sRef_makeType (t), SS_DEFINED)); + return (uentry_makeVariableParamAux (n, t, sRef_makeType (t), fileloc_copy (loc), SS_DEFINED)); } -# endif /* ** constants */ -/*@only@*/ /*@notnull@*/ +static /*@only@*/ /*@notnull@*/ uentry uentry_makeConstantAux (cstring n, ctype t, - /*@keep@*/ fileloc f, bool priv, + /*@keep@*/ fileloc f, bool priv, bool macro, /*@only@*/ multiVal m) { uentry e = uentry_alloc (); @@ -2748,6 +3154,8 @@ uentry uentry_makeConstantAux (cstring n, ctype t, e->utype = t; e->storageclass = SCNONE; + e->warn = warnClause_undefined; /*@i32 warnings for constants? */ + e->sref = sRef_makeConst (t); e->lset = FALSE; @@ -2759,8 +3167,8 @@ uentry uentry_makeConstantAux (cstring n, ctype t, e->info = (uinfo) dmalloc (sizeof (*e->info)); e->info->uconst = (ucinfo) dmalloc (sizeof (*e->info->uconst)); - e->info->uconst->val = m; e->info->uconst->access = typeIdSet_undefined; + e->info->uconst->macro = macro; uentry_setSpecDef (e, f); @@ -2769,12 +3177,27 @@ uentry uentry_makeConstantAux (cstring n, ctype t, sRef_setDefNull (e->sref, uentry_whereDeclared (e)); } + uentry_setConstantValue (e, m); + return (e); } /*@notnull@*/ uentry uentry_makeConstant (cstring n, ctype t, fileloc f) { - return (uentry_makeConstantAux (n, t, f, FALSE, multiVal_unknown ())); + uentry ue = uentry_makeConstantAux (n, t, f, FALSE, FALSE, multiVal_unknown ()); + return ue; +} + +/*@notnull@*/ uentry uentry_makeConstantValue (cstring n, ctype t, fileloc f, bool priv, multiVal val) +{ + uentry ue = uentry_makeConstantAux (n, t, f, priv, FALSE, val); + return ue; +} + +/*@notnull@*/ uentry uentry_makeMacroConstant (cstring n, ctype t, fileloc f) +{ + uentry ue = uentry_makeConstantAux (n, t, f, FALSE, TRUE, multiVal_unknown ()); + return ue; } /*@notnull@*/ uentry uentry_makeIdConstant (idDecl t) @@ -2785,9 +3208,10 @@ uentry uentry_makeConstantAux (cstring n, ctype t, llassert (fileloc_isUndefined (ue->whereDeclared)); ue->whereDeclared = setLocation (); - uentry_reflectQualifiers (ue, idDecl_getQuals (t)); + DPRINTF (("Constant: %s", uentry_unparseFull (ue))); + DPRINTF (("Value: %s", multiVal_unparse (uentry_getConstantValue (ue)))); return ue; } @@ -2875,14 +3299,14 @@ void uentry_setCheckedStrict (uentry ue) } static /*@only@*/ /*@notnull@*/ - uentry uentry_makeVariableAux (cstring n, ctype t, - fileloc f, - /*@exposed@*/ sRef s, - bool priv, vkind kind) +uentry uentry_makeVariableAux (cstring n, ctype t, + fileloc f, + /*@exposed@*/ sRef s, + bool priv, vkind kind) { uentry e = uentry_alloc (); ctype rt = t; - + DPRINTF (("Make variable: %s %s %s", n, ctype_unparse (t), sRef_unparse (s))); e->ukind = KVAR; @@ -2891,6 +3315,8 @@ static /*@only@*/ /*@notnull@*/ e->storageclass = SCNONE; + e->warn = warnClause_undefined; /*@i32 warnings for variable @*/ + e->sref = s; e->used = FALSE; @@ -2904,36 +3330,44 @@ static /*@only@*/ /*@notnull@*/ e->info->var = (uvinfo) dmalloc (sizeof (*e->info->var)); e->info->var->kind = kind; + /*@i523 e->info->var->origsref = sRef_saveCopy (e->sref); */ e->info->var->checked = CH_UNKNOWN; + DPRINTF (("Here we are: %s", sRef_unparseFull (e->sref))); uentry_setSpecDef (e, f); + DPRINTF (("Here we are: %s", sRef_unparseFull (e->sref))); if (ctype_isFunction (rt)) { - rt = ctype_returnValue (rt); + rt = ctype_getReturnType (rt); } if (ctype_isUA (rt)) { + DPRINTF (("Here we are: %s", sRef_unparseFull (e->sref))); sRef_setStateFromType (e->sref, rt); } + DPRINTF (("Here we are: %s", sRef_unparseFull (e->sref))); e->info->var->defstate = sRef_getDefState (e->sref); e->info->var->nullstate = sRef_getNullState (e->sref); -/* start modifications */ -/* This function sets the uentry for a pointer or array variable declaration, - it allocates memory and sets the fields. We check if the type of the variable - is a pointer or array and allocate a `bbufinfo' struct accordingly */ - - if( ctype_isArray (t) || ctype_isPointer(t)) { - /*@i222@*/e->info->var->bufinfo = dmalloc( sizeof(*e->info->var->bufinfo) ); - e->info->var->bufinfo->bufstate = BB_NOTNULLTERMINATED; - s->bufinfo.bufstate = BB_NOTNULLTERMINATED; - } else { - e->info->var->bufinfo = NULL; - }/* end else */ -/* end modification */ + /* start modifications */ + /* This function sets the uentry for a pointer or array variable declaration, + it allocates memory and sets the fields. We check if the type of the variable + is a pointer or array and allocate a `bbufinfo' struct accordingly */ + + if (ctype_isArray (t) || ctype_isPointer(t)) + { + /*@i222@*/ e->info->var->bufinfo = dmalloc (sizeof (*e->info->var->bufinfo)); + e->info->var->bufinfo->bufstate = BB_NOTNULLTERMINATED; + sRef_setNotNullTerminatedState (s); + } + else + { + e->info->var->bufinfo = NULL; + }/* end else */ + /* end modification */ return (e); } @@ -2976,20 +3410,22 @@ void uentry_makeVarFunction (uentry ue) ak = sRef_getOrigAliasKind (ue->sref); ek = sRef_getOrigExKind (ue->sref); + llassert (uentry_isVariable (ue)); oldInfo = ue->info->var; - llassert (ctype_isUnknown (ue->utype) || ctype_isFunction (ue->utype)); + DPRINTF (("ue: %s", uentry_unparseFull (ue))); + llassert (ctype_isUnknown (ue->utype) || ctype_isFunction (ctype_realType (ue->utype))); /* - ** expanded macro is marked used (until I write a pre-processor) + ** expanded macro is marked used */ - ue->used |= (oldInfo->kind == VKEXPMACRO); + ue->used = ue->used || (oldInfo->kind == VKEXPMACRO); ue->ukind = KFCN; ue->info->fcn = (ufinfo) dmalloc (sizeof (*ue->info->fcn)); ue->info->fcn->exitCode = XK_UNKNOWN; - ue->info->fcn->nullPred = QU_UNKNOWN; + ue->info->fcn->nullPred = qual_createUnknown (); ue->info->fcn->specialCode = SPC_NONE; ue->info->fcn->access = typeIdSet_undefined; ue->info->fcn->hasGlobs = FALSE; @@ -3000,17 +3436,16 @@ void uentry_makeVarFunction (uentry ue) ue->info->fcn->defparams = uentryList_undefined; /*drl*/ - ue->info->fcn->preconditions = constraintList_undefined; + ue->info->fcn->preconditions = functionConstraint_undefined; /*end */ /*drl 12/28/2000*/ - ue->info->fcn->postconditions = constraintList_undefined; + ue->info->fcn->postconditions = functionConstraint_undefined; /*end */ - if (ctype_isFunction (ue->utype)) { - ue->sref = sRef_makeType (ctype_returnValue (ue->utype)); + ue->sref = sRef_makeType (ctype_getReturnType (ue->utype)); } else { @@ -3027,6 +3462,7 @@ void uentry_makeVarFunction (uentry ue) { if (exkind_isKnown (ek)) { + DPRINTF (("imp dep: %s", uentry_unparseFull (ue))); ak = AK_IMPDEPENDENT; } else @@ -3035,7 +3471,7 @@ void uentry_makeVarFunction (uentry ue) { if (ctype_isFunction (ue->utype) && ctype_isVisiblySharable - (ctype_realType (ctype_returnValue (ue->utype)))) + (ctype_realType (ctype_getReturnType (ue->utype)))) { if (uentryList_hasReturned (uentry_getParams (ue))) { @@ -3043,8 +3479,15 @@ void uentry_makeVarFunction (uentry ue) } else { - ak = AK_IMPONLY; - } + if (ctype_isImmutableAbstract (ctype_getReturnType (ue->utype))) + { + ; + } + else + { + ak = AK_IMPONLY; + } + } } } } @@ -3060,8 +3503,7 @@ void uentry_makeVarFunction (uentry ue) if (oldInfo->kind == VKEXPMACRO) { - fileloc_free (loc); - ue->whereDeclared = fileloc_undefined; + ; } else { @@ -3072,64 +3514,158 @@ void uentry_makeVarFunction (uentry ue) uvinfo_free (oldInfo); } -void -uentry_setGlobals (uentry ue, /*@owned@*/ globSet globs) +void uentry_makeConstantFunction (uentry ue) { + alkind ak; + exkind ek; + ucinfo oldInfo; + fileloc loc; + llassert (uentry_isValid (ue)); + llassert (!sRef_modInFunction ()); - if (uentry_isIter (ue)) - { - llassert (globSet_isUndefined (ue->info->iter->globs)); - ue->info->iter->globs = globs; - } - else - { - if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue))) - { - uentry_makeVarFunction (ue); - } - - llassert (uentry_isFunction (ue)); - llassert (!ue->info->fcn->hasGlobs - && globSet_isUndefined (ue->info->fcn->globs)); - - ue->info->fcn->hasGlobs = TRUE; - /*@-mustfree@*/ ue->info->fcn->globs = globs; - /*@=mustfree@*/ - } + ak = sRef_getOrigAliasKind (ue->sref); + ek = sRef_getOrigExKind (ue->sref); - if (globSet_hasStatic (globs)) - { - context_recordFileGlobals (globs); - } + llassert (uentry_isConstant (ue)); + oldInfo = ue->info->uconst; - if (context_getFlag (FLG_GLOBALSIMPMODIFIESNOTHING)) - { - ue->info->fcn->hasMods = TRUE; - } -} + llassert (ctype_isUnknown (ue->utype) || ctype_isFunction (ue->utype)); -void uentry_addAccessType (uentry ue, typeId tid) -{ - if (uentry_isFunction (ue)) - { - ue->info->fcn->access = typeIdSet_insert (ue->info->fcn->access, tid); - } - else if (uentry_isEitherConstant (ue)) + /* + ** expanded macro is marked used (until I write a pre-processor) + */ + + ue->ukind = KFCN; + ue->info->fcn = (ufinfo) dmalloc (sizeof (*ue->info->fcn)); + ue->info->fcn->exitCode = XK_UNKNOWN; + ue->info->fcn->nullPred = qual_createUnknown (); + ue->info->fcn->specialCode = SPC_NONE; + ue->info->fcn->access = typeIdSet_undefined; + ue->info->fcn->hasGlobs = FALSE; + ue->info->fcn->globs = globSet_undefined; + ue->info->fcn->hasMods = FALSE; + ue->info->fcn->mods = sRefSet_undefined; + ue->info->fcn->specclauses = NULL; + ue->info->fcn->defparams = uentryList_undefined; + + /*drl*/ + ue->info->fcn->preconditions = functionConstraint_undefined; + /*end */ + + /*drl 12/28/2000*/ + ue->info->fcn->postconditions = functionConstraint_undefined; + /*end */ + + + if (ctype_isFunction (ue->utype)) { - ue->info->uconst->access = typeIdSet_insert (ue->info->uconst->access, tid); + ue->sref = sRef_makeType (ctype_getReturnType (ue->utype)); } - else if (uentry_isIter (ue)) + else { - ue->info->iter->access = typeIdSet_insert (ue->info->iter->access, tid); + ue->sref = sRef_makeType (ctype_unknown); } - else if (uentry_isEndIter (ue)) + + if (sRef_isRefCounted (ue->sref)) { - ue->info->enditer->access = typeIdSet_insert (ue->info->enditer->access, tid); + ak = AK_NEWREF; } else { - llbug (message ("no access for: %q", uentry_unparse (ue))); + if (alkind_isUnknown (ak)) + { + if (exkind_isKnown (ek)) + { + DPRINTF (("imp dep: %s", uentry_unparseFull (ue))); + ak = AK_IMPDEPENDENT; + } + else + { + if (context_getFlag (FLG_RETIMPONLY)) + { + if (ctype_isFunction (ue->utype) + && ctype_isVisiblySharable + (ctype_realType (ctype_getReturnType (ue->utype)))) + { + if (uentryList_hasReturned (uentry_getParams (ue))) + { + ; + } + else + { + if (ctype_isImmutableAbstract (ctype_getReturnType (ue->utype))) + { + ; + } + else + { + ak = AK_IMPONLY; + } + } + } + } + } + } + } + + loc = ue->whereDeclared; + + sRef_setAliasKind (ue->sref, ak, loc); + sRef_setExKind (ue->sref, ek, loc); + + fileloc_free (ue->whereDefined); + ue->whereDefined = fileloc_undefined; + ucinfo_free (oldInfo); +} + +void +uentry_setGlobals (uentry ue, /*@only@*/ globSet globs) +{ + llassert (uentry_isValid (ue)); + + globSet_markImmutable (globs); + + if (uentry_isIter (ue)) + { + ue->info->iter->globs = globSet_unionFree (ue->info->iter->globs, globs); + } + else + { + uentry_convertVarFunction (ue); + llassert (uentry_isFunction (ue)); + + ue->info->fcn->hasGlobs = TRUE; + ue->info->fcn->globs = globSet_unionFree (ue->info->fcn->globs, globs); + } + + if (context_getFlag (FLG_GLOBALSIMPMODIFIESNOTHING)) + { + ue->info->fcn->hasMods = TRUE; + } +} + +void uentry_addAccessType (uentry ue, typeId tid) +{ + if (uentry_isFunction (ue)) + { + ue->info->fcn->access = typeIdSet_insert (ue->info->fcn->access, tid); + } + else if (uentry_isEitherConstant (ue)) + { + ue->info->uconst->access = typeIdSet_insert (ue->info->uconst->access, tid); + } + else if (uentry_isIter (ue)) + { + ue->info->iter->access = typeIdSet_insert (ue->info->iter->access, tid); + } + else if (uentry_isEndIter (ue)) + { + ue->info->enditer->access = typeIdSet_insert (ue->info->enditer->access, tid); + } + else + { + llbug (message ("no access for: %q", uentry_unparse (ue))); } } @@ -3137,23 +3673,26 @@ void uentry_addAccessType (uentry ue, typeId tid) uentry_makeFunction (cstring n, ctype t, typeId access, /*@only@*/ globSet globs, /*@only@*/ sRefSet mods, + /*@only@*/ warnClause warn, fileloc f) { + llassert (warnClause_isUndefined (warn)); /*@i325 remove parameter! */ return (uentry_makeFunctionAux (n, t, ((typeId_isInvalid (access)) ? typeIdSet_emptySet () : typeIdSet_single (access)), - globs, mods, f, + globs, mods, warn, + f, FALSE, FALSE)); } -# ifndef NOLCL /*@notnull@*/ uentry uentry_makePrivFunction2 (cstring n, ctype t, typeIdSet access, globSet globs, sRefSet mods, fileloc f) { - return (uentry_makeFunctionAux (n, t, access, globs, mods, f, TRUE, FALSE)); + return (uentry_makeFunctionAux (n, t, access, globs, mods, warnClause_undefined, + f, TRUE, FALSE)); } @@ -3165,8 +3704,8 @@ void uentry_addAccessType (uentry ue, typeId tid) fileloc f) { uentry ue = uentry_makeFunctionAux (n, t, access, - globs, mods, f, - FALSE, FALSE); + globs, mods, warnClause_undefined, + f, FALSE, FALSE); uentry_setHasGlobs (ue); uentry_setHasMods (ue); @@ -3174,7 +3713,6 @@ void uentry_addAccessType (uentry ue, typeId tid) reflectImplicitFunctionQualifiers (ue, TRUE); return (ue); } -# endif uentry uentry_makeExpandedMacro (cstring s, fileloc f) { @@ -3191,6 +3729,7 @@ uentry uentry_makeExpandedMacro (cstring s, fileloc f) uentry ue = uentry_makeFunctionAux (n, ctype_unknown, typeIdSet_singleOpt (access), globSet_undefined, sRefSet_undefined, + warnClause_undefined, fileloc_undefined, FALSE, TRUE); @@ -3206,20 +3745,18 @@ bool uentry_isForward (uentry e) return (ctype_isUnknown (ct) || (ctype_isFunction (ct) - && ctype_isUnknown (ctype_returnValue (ct)))); + && ctype_isUnknown (ctype_getReturnType (ct)))); } return FALSE; } -# ifndef NOLCL /*@notnull@*/ uentry uentry_makeTypeListFunction (cstring n, typeIdSet access, fileloc f) { return (uentry_makeFunctionAux (n, ctype_unknown, access, - globSet_new (), - sRefSet_new (), f, - FALSE, TRUE)); + globSet_undefined, sRefSet_undefined, warnClause_undefined, + f,FALSE, TRUE)); } /*@notnull@*/ uentry @@ -3227,13 +3764,13 @@ uentry_makeUnspecFunction (cstring n, ctype t, typeIdSet access, fileloc f) { - uentry ue = uentry_makeFunctionAux (n, t, access, globSet_new (), - sRefSet_new (), f, FALSE, TRUE); + uentry ue = uentry_makeFunctionAux (n, t, access, globSet_undefined, + sRefSet_undefined, warnClause_undefined, + f, FALSE, TRUE); reflectImplicitFunctionQualifiers (ue, TRUE); return ue; } -# endif /* ** datatypes @@ -3242,7 +3779,7 @@ uentry_makeUnspecFunction (cstring n, ctype t, /* is exported for use by usymtab_interface */ /*@notnull@*/ uentry - uentry_makeDatatypeAux (cstring n, ctype t, ynm mut, ynm abs, + uentry_makeDatatypeAux (cstring n, ctype t, ynm mut, qual abstract, fileloc f, bool priv) { uentry e = uentry_alloc (); @@ -3264,6 +3801,7 @@ uentry_makeUnspecFunction (cstring n, ctype t, uentry_setSpecDef (e, f); + e->warn = warnClause_undefined; /*@i634@*/ e->uses = filelocList_new (); e->isPrivate = priv; e->hasNameError = FALSE; @@ -3273,7 +3811,7 @@ uentry_makeUnspecFunction (cstring n, ctype t, e->info = (uinfo) dmalloc (sizeof (*e->info)); e->info->datatype = (udinfo) dmalloc (sizeof (*e->info->datatype)); - e->info->datatype->abs = abs; + e->info->datatype->abs = abstract; e->info->datatype->mut = mut; e->info->datatype->type = ctype_undefined; @@ -3282,7 +3820,7 @@ uentry_makeUnspecFunction (cstring n, ctype t, uentry_setDefined (e, f); } - if (ynm_isOn (abs) && !(uentry_isCodeDefined (e))) + if (qual_isAbstract (abstract) && !(uentry_isCodeDefined (e))) { sRef_setNullState (e->sref, NS_ABSNULL, uentry_whereDeclared (e)); } @@ -3291,16 +3829,15 @@ uentry_makeUnspecFunction (cstring n, ctype t, } /*@notnull@*/ uentry - uentry_makeDatatype (cstring n, ctype t, ynm mut, ynm abs, - fileloc f) + uentry_makeDatatype (cstring n, ctype t, ynm mut, qual abstract, fileloc f) { - return (uentry_makeDatatypeAux (n, t, mut, abs, f, FALSE)); + return (uentry_makeDatatypeAux (n, t, mut, abstract, f, FALSE)); } -/*@notnull@*/ uentry uentry_makeBoolDatatype (ynm abs) +/*@notnull@*/ uentry uentry_makeBoolDatatype (qual abstract) { uentry ret = uentry_makeDatatypeAux (context_getBoolName (), - ctype_bool, NO, abs, + ctype_bool, NO, abstract, fileloc_getBuiltin (), FALSE); @@ -3328,6 +3865,7 @@ static /*@only@*/ /*@notnull@*/ uentry uentry_setSpecDef (e, f); + e->warn = warnClause_undefined; /*@i452@*/ e->uses = filelocList_new (); e->isPrivate = FALSE; e->hasNameError = FALSE; @@ -3373,6 +3911,7 @@ uentry_makeEndIterAux (cstring n, typeIdSet access, /*@only@*/ fileloc f) e->info->enditer->access = access; + e->warn = warnClause_undefined; /*@i452@*/ return (e); } @@ -3416,9 +3955,10 @@ static /*@only@*/ /*@notnull@*/ uentry e->info = (uinfo) dmalloc (sizeof (*e->info)); e->info->datatype = (udinfo) dmalloc (sizeof (*e->info->datatype)); - e->info->datatype->abs = NO; + e->info->datatype->abs = qual_createUnknown (); e->info->datatype->mut = (kind == KENUMTAG) ? NO : MAYBE; e->info->datatype->type = t; + e->warn = warnClause_undefined; /*@i452@*/ if (uentry_isDeclared (e)) { @@ -3457,7 +3997,6 @@ uentry_makeUnionTag (cstring n, ctype t, fileloc loc) return (ret); } -# ifndef NOLCL uentry uentry_makeEnumTag (cstring n, ctype t, fileloc loc) { @@ -3467,7 +4006,6 @@ uentry_makeEnumTag (cstring n, ctype t, fileloc loc) cstring_free (ename); return ret; } -# endif uentry uentry_makeUnionTagLoc (cstring n, ctype t) @@ -3646,21 +4184,20 @@ uentry_compare (uentry u1, uentry u2) INTCOMPARERETURN (u1->ukind, u2->ukind); COMPARERETURN (ctype_compare (u1->utype, u2->utype)); COMPARERETURN (bool_compare (uentry_isPriv (u1), uentry_isPriv (u2))); - COMPARERETURN (sRef_compare (u1->sref, u2->sref)); switch (u1->ukind) { case KINVALID: case KELIPSMARKER: - /* bug detected by lclint: + /* bug detected by splint: ** uentry.c:753,14: Return value type bool does not match declared type int: TRUE */ return 0; case KENUMCONST: case KCONST: - return (multiVal_compare (u1->info->uconst->val, - u2->info->uconst->val)); + return (multiVal_compare (uentry_getConstantValue (u1), + uentry_getConstantValue (u2))); case KSTRUCTTAG: case KUNIONTAG: case KENUMTAG: @@ -3674,19 +4211,20 @@ uentry_compare (uentry u1, uentry u2) return (typeIdSet_compare (uentry_accessType (u1), uentry_accessType (u2))); case KFCN: - COMPARERETURN (typeIdSet_compare (uentry_accessType (u1), - uentry_accessType (u2))); - COMPARERETURN (globSet_compare (uentry_getGlobs (u1), - uentry_getGlobs (u2))); - COMPARERETURN (uentryList_compareParams (uentry_getParams (u1), - uentry_getParams (u2))); - COMPARERETURN (generic_compare (u1->info->fcn->specialCode, - u2->info->fcn->specialCode)); - COMPARERETURN (generic_compare (u1->info->fcn->nullPred, - u2->info->fcn->nullPred)); - - return (sRefSet_compare (uentry_getMods (u1), uentry_getMods (u2))); + /* + ** Functions are never equivalent + */ + + if (u1 - u2 < 0) /* evans 2001-08-21: was: ((int) u1 < (int) u2), changed to remove gcc warning */ + { + return -1; + } + else + { + return 1; + } case KVAR: + COMPARERETURN (generic_compare (u1->info->var->kind, u2->info->var->kind)); COMPARERETURN (generic_compare (sRef_getOrigAliasKind (u1->sref), sRef_getOrigAliasKind (u2->sref))); @@ -3703,7 +4241,7 @@ uentry_compare (uentry u1, uentry u2) u2->info->datatype->type)); COMPARERETURN (ynm_compare (u1->info->datatype->mut, u2->info->datatype->mut)); - return (ynm_compare (u1->info->datatype->abs, u2->info->datatype->abs)); + return (generic_compare (u1->info->datatype->abs, u2->info->datatype->abs)); } BADEXIT; @@ -3720,13 +4258,13 @@ uentry_compare (uentry u1, uentry u2) static void advanceField (char **s) { - checkChar (s, '@'); + reader_checkChar (s, '@'); } static void advanceName (char **s) { - checkChar (s, '#'); + reader_checkChar (s, '#'); } static vkind @@ -3774,11 +4312,13 @@ static uentry e->used = FALSE; e->lset = FALSE; + e->warn = warnClause_undefined; /*@i452@*/ + e->info = (uinfo) dmalloc (sizeof (*e->info)); e->info->uconst = (ucinfo) dmalloc (sizeof (*e->info->uconst)); - e->info->uconst->val = m; e->info->uconst->access = access; - + e->info->uconst->macro = FALSE; /*@i523! fix this when macro info added to library */ + uentry_setConstantValue (e, m); sRef_storeState (e->sref); return (e); @@ -3820,6 +4360,7 @@ static /*@only@*/ uentry e->lset = FALSE; e->uses = filelocList_new (); + e->warn = warnClause_undefined; /*@i452@*/ e->info = (uinfo) dmalloc (sizeof (*e->info)); e->info->var = (uvinfo) dmalloc (sizeof (*e->info->var)); @@ -3843,7 +4384,7 @@ static /*@only@*/ uentry } static /*@only@*/ uentry -uentry_makeDatatypeBase (/*@only@*/ cstring name, ctype ct, ynm abs, +uentry_makeDatatypeBase (/*@only@*/ cstring name, ctype ct, qual abstract, ynm mut, ctype rtype, alkind ak, exkind exp, sstate defstate, nstate isnull, /*@only@*/ fileloc loc) @@ -3856,6 +4397,7 @@ uentry_makeDatatypeBase (/*@only@*/ cstring name, ctype ct, ynm abs, e->utype = ct; e->storageclass = SCNONE; e->sref = sRef_makeUnknown (); + DPRINTF (("Merge null 1: %s", sRef_unparseFull (e->sref))); /* ** This is only setting null state. (I think?) @@ -3880,11 +4422,12 @@ uentry_makeDatatypeBase (/*@only@*/ cstring name, ctype ct, ynm abs, sRef_setDefState (e->sref, defstate, loc); - if (ynm_isOn (abs) && ctype_isUnknown (ct) && isnull == NS_UNKNOWN) + if (qual_isEitherAbstract (abstract) && ctype_isUnknown (ct) && isnull == NS_UNKNOWN) { isnull = NS_ABSNULL; } + DPRINTF (("Merge null: %s", sRef_unparseFull (e->sref))); sRef_mergeNullState (e->sref, isnull); e->whereDefined = fileloc_copy (loc); /*< bogus! (but necessary for lexer) >*/ @@ -3903,22 +4446,25 @@ uentry_makeDatatypeBase (/*@only@*/ cstring name, ctype ct, ynm abs, e->isPrivate = FALSE; e->hasNameError = FALSE; + e->warn = warnClause_undefined; /*@i452@*/ + e->used = FALSE; e->lset = FALSE; e->uses = filelocList_new (); e->info = (uinfo) dmalloc (sizeof (*e->info)); e->info->datatype = (udinfo) dmalloc (sizeof (*e->info->datatype)); - e->info->datatype->abs = abs; + e->info->datatype->abs = abstract; e->info->datatype->mut = mut; e->info->datatype->type = rtype; - + + DPRINTF (("About to store: %s", sRef_unparseFull (e->sref))); sRef_storeState (e->sref); + DPRINTF (("After store: %s", sRef_unparseFull (e->sref))); return (e); } -# ifndef NOLCL static void uentry_setHasGlobs (uentry ue) { llassert (uentry_isFunction (ue)); @@ -3932,7 +4478,6 @@ static void uentry_setHasMods (uentry ue) ue->info->fcn->hasMods = TRUE; } -# endif bool uentry_hasGlobs (uentry ue) { @@ -3944,14 +4489,27 @@ bool uentry_hasGlobs (uentry ue) return FALSE; } -bool uentry_hasSpecialClauses (uentry ue) +bool uentry_hasStateClauseList (uentry ue) { - return (uentry_isFunction (ue) && specialClauses_isDefined (ue->info->fcn->specclauses)); + return (uentry_isFunction (ue) && stateClauseList_isDefined (ue->info->fcn->specclauses)); } -specialClauses uentry_getSpecialClauses (uentry ue) +bool uentry_hasConditions (uentry ue) { - llassert (uentry_isFunction (ue)); + return (uentry_isFunction (ue) + && (functionConstraint_isDefined (ue->info->fcn->preconditions) + || functionConstraint_isDefined (ue->info->fcn->postconditions))); +} + +stateClauseList uentry_getStateClauseList (uentry ue) +{ + if (!uentry_isFunction (ue)) + { + llassert (uentry_isFunction (ue)); + return stateClauseList_undefined; + } + + DPRINTF (("Get state clause list: %s", uentry_unparse (ue))); return ue->info->fcn->specclauses; } @@ -3975,7 +4533,8 @@ static uentry exitkind exitCode, specCode sCode, qual nullPred, - /*@only@*/ specialClauses specclauses, + /*@only@*/ stateClauseList specclauses, + /*@only@*/ warnClause warnclause, /*@only@*/ fileloc loc) { uentry e = uentry_alloc (); @@ -3989,7 +4548,7 @@ static uentry if (ctype_isFunction (ct)) { - ret = ctype_returnValue (ct); + ret = ctype_getReturnType (ct); } else { @@ -4024,6 +4583,7 @@ static uentry e->used = FALSE; e->lset = FALSE; e->uses = filelocList_new (); + e->warn = warnclause; e->info = (uinfo) dmalloc (sizeof (*e->info)); e->info->fcn = (ufinfo) dmalloc (sizeof (*e->info->fcn)); @@ -4093,10 +4653,11 @@ static /*@only@*/ uentry e->used = FALSE; e->lset = FALSE; e->uses = filelocList_new (); + e->warn = warnClause_undefined; /*@i452@*/ e->info = (uinfo) dmalloc (sizeof (*e->info)); e->info->datatype = (udinfo) dmalloc (sizeof (*e->info->datatype)); - e->info->datatype->abs = NO; + e->info->datatype->abs = qual_createUnknown (); e->info->datatype->mut = MAYBE; e->info->datatype->type = rtype; @@ -4137,6 +4698,7 @@ static uentry e->used = FALSE; e->lset = FALSE; e->uses = filelocList_new (); + e->warn = warnClause_undefined; /*@i452@*/ e->info = (uinfo) dmalloc (sizeof (*e->info)); e->info->iter = (uiinfo) dmalloc (sizeof (*e->info->iter)); @@ -4180,6 +4742,7 @@ static uentry e->used = FALSE; e->lset = FALSE; e->uses = filelocList_new (); + e->warn = warnClause_undefined; /*@i452@*/ e->info = (uinfo) dmalloc (sizeof (*e->info)); e->info->enditer = (ueinfo) dmalloc (sizeof (*e->info->enditer)); @@ -4201,10 +4764,12 @@ uentry_undump (ekind kind, fileloc loc, char **s) { uentry ue; + DPRINTF (("Uentry undump: %s", *s)); + if (**s == '!') { - checkChar (s, '!'); - checkChar (s, '.'); + reader_checkChar (s, '!'); + reader_checkChar (s, '.'); ue = uentry_makeElipsisMarker (); } else @@ -4223,19 +4788,19 @@ uentry_undump (ekind kind, fileloc loc, char **s) exkind exp; chkind checked; - checkChar (s, '|'); + reader_checkChar (s, '|'); - if (optCheckChar (s, '@')) + if (reader_optCheckChar (s, '@')) { - tkind = vkind_fromInt (getInt (s)); - checkChar (s, '|'); + tkind = vkind_fromInt (reader_getInt (s)); + reader_checkChar (s, '|'); } else { tkind = VKPARAM; } - if (optCheckChar (s, '$')) + if (reader_optCheckChar (s, '$')) { defstate = SS_UNKNOWN; isnull = NS_UNKNOWN; @@ -4243,7 +4808,7 @@ uentry_undump (ekind kind, fileloc loc, char **s) exp = XO_UNKNOWN; checked = CH_UNKNOWN; } - else if (optCheckChar (s, '&')) + else if (reader_optCheckChar (s, '&')) { defstate = SS_DEFINED; isnull = NS_UNKNOWN; @@ -4251,7 +4816,7 @@ uentry_undump (ekind kind, fileloc loc, char **s) exp = XO_UNKNOWN; checked = CH_UNKNOWN; } - else if (optCheckChar (s, '^')) + else if (reader_optCheckChar (s, '^')) { defstate = SS_UNKNOWN; isnull = NS_UNKNOWN; @@ -4261,25 +4826,27 @@ uentry_undump (ekind kind, fileloc loc, char **s) } else { - defstate = sstate_fromInt (getInt (s)); - advanceField (s); isnull = nstate_fromInt (getInt (s)); - advanceField (s); aliased = alkind_fromInt (getInt (s)); + defstate = sstate_fromInt (reader_getInt (s)); + advanceField (s); isnull = nstate_fromInt (reader_getInt (s)); + advanceField (s); aliased = alkind_fromInt (reader_getInt (s)); - if (optCheckChar (s, '&')) + if (reader_optCheckChar (s, '&')) { exp = XO_UNKNOWN; checked = CH_UNKNOWN; } else { - advanceField (s); exp = exkind_fromInt (getInt (s)); - advanceField (s); checked = (chkind) (getInt (s)); + advanceField (s); exp = exkind_fromInt (reader_getInt (s)); + advanceField (s); checked = (chkind) (reader_getInt (s)); } } advanceName (s); - name = getStringWord (s); + name = reader_getStringWord (s); + llassert (!cstring_equal (name, GLOBAL_MARKER_NAME)); + ue = uentry_makeVariableBase (name, ct, tkind, defstate, isnull, aliased, exp, checked, fileloc_copy (loc)); @@ -4287,7 +4854,7 @@ uentry_undump (ekind kind, fileloc loc, char **s) break; case KDATATYPE: { - ynm abs; + qual abstract; ynm mut; ctype rtype; sstate defstate; @@ -4295,17 +4862,17 @@ uentry_undump (ekind kind, fileloc loc, char **s) alkind aliased; exkind exp; - advanceField (s); abs = ynm_fromCodeChar (loadChar (s)); - advanceField (s); mut = ynm_fromCodeChar (loadChar (s)); - advanceField (s); defstate = sstate_fromInt (getInt (s)); - advanceField (s); isnull = nstate_fromInt (getInt (s)); - advanceField (s); aliased = alkind_fromInt (getInt (s)); - advanceField (s); exp = exkind_fromInt (getInt (s)); + advanceField (s); abstract = qual_abstractFromCodeChar (reader_loadChar (s)); + advanceField (s); mut = ynm_fromCodeChar (reader_loadChar (s)); + advanceField (s); defstate = sstate_fromInt (reader_getInt (s)); + advanceField (s); isnull = nstate_fromInt (reader_getInt (s)); + advanceField (s); aliased = alkind_fromInt (reader_getInt (s)); + advanceField (s); exp = exkind_fromInt (reader_getInt (s)); advanceField (s); rtype = ctype_undump (s); advanceName (s); - name = getStringWord (s); - - ue = uentry_makeDatatypeBase (name, ct, abs, mut, rtype, + name = reader_getStringWord (s); + DPRINTF (("Datatype %s, Exp = %s", name, exkind_unparse (exp))); + ue = uentry_makeDatatypeBase (name, ct, abstract, mut, rtype, aliased, exp, defstate, isnull, fileloc_copy (loc)); } @@ -4324,33 +4891,34 @@ uentry_undump (ekind kind, fileloc loc, char **s) globSet globs; bool hasMods; sRefSet mods; - specialClauses specclauses; + stateClauseList specclauses = stateClauseList_undefined; + warnClause warnclause = warnClause_undefined; - if (optCheckChar (s, '$')) + if (reader_optCheckChar (s, '$')) { defstate = SS_DEFINED; isnull = NS_UNKNOWN; exitCode = XK_UNKNOWN; specc = SPC_NONE; - nullPred = QU_UNKNOWN; + nullPred = qual_createUnknown (); } else { - advanceField (s); defstate = sstate_fromInt (getInt (s)); - advanceField (s); isnull = nstate_fromInt (getInt (s)); - advanceField (s); exitCode = exitkind_fromInt (getInt (s)); - advanceField (s); specc = specCode_fromInt (getInt (s)); - advanceField (s); nullPred = qual_fromInt (getInt (s)); + advanceField (s); defstate = sstate_fromInt (reader_getInt (s)); + advanceField (s); isnull = nstate_fromInt (reader_getInt (s)); + advanceField (s); exitCode = exitkind_fromInt (reader_getInt (s)); + advanceField (s); specc = specCode_fromInt (reader_getInt (s)); + advanceField (s); nullPred = qual_undump (s); } - if (optCheckChar (s, '$')) + if (reader_optCheckChar (s, '$')) { hasGlobs = FALSE; globs = globSet_undefined; hasMods = FALSE; mods = sRefSet_undefined; } - else if (optCheckChar (s, '^')) + else if (reader_optCheckChar (s, '^')) { hasGlobs = TRUE; globs = globSet_undefined; @@ -4359,35 +4927,48 @@ uentry_undump (ekind kind, fileloc loc, char **s) } else { - advanceField (s); hasGlobs = bool_fromInt (getInt (s)); + advanceField (s); hasGlobs = bool_fromInt (reader_getInt (s)); advanceField (s); globs = globSet_undump (s); - advanceField (s); hasMods = bool_fromInt (getInt (s)); + advanceField (s); hasMods = bool_fromInt (reader_getInt (s)); advanceField (s); mods = sRefSet_undump (s); } - if (optCheckChar (s, '$')) + if (reader_optCheckChar (s, '$')) { ak = AK_UNKNOWN; exp = XO_UNKNOWN; } else { - advanceField (s); ak = alkind_fromInt (getInt (s)); - advanceField (s); exp = exkind_fromInt (getInt (s)); + advanceField (s); ak = alkind_fromInt (reader_getInt (s)); + advanceField (s); exp = exkind_fromInt (reader_getInt (s)); } advanceField (s); access = typeIdSet_undump (s); - if (optCheckChar (s, '@')) - { - specclauses = specialClauses_undump (s); - } - else + /* + ** Optional clauses: Start with @: + */ + + while (reader_optCheckChar (s, '@')) { - specclauses = specialClauses_undefined; + if (reader_optCheckChar (s, 'W')) /* Warn clause */ + { + reader_checkChar (s, ':'); + warnclause = warnClause_undump (s); + } + else if (reader_optCheckChar (s, 'S')) /* stateClause List */ + { + reader_checkChar (s, ':'); + specclauses = stateClauseList_undump (s); + } + else + { + BADBRANCH; + } } - advanceName (s); name = getStringWord (s); + advanceName (s); name = reader_getStringWord (s); ue = uentry_makeFunctionBase (name, ct, access, hasGlobs, globs, @@ -4395,6 +4976,7 @@ uentry_undump (ekind kind, fileloc loc, char **s) ak, exp, defstate, isnull, exitCode, specc, nullPred, specclauses, + warnclause, fileloc_copy (loc)); DPRINTF (("Undump: %s", uentry_unparse (ue))); } @@ -4404,7 +4986,7 @@ uentry_undump (ekind kind, fileloc loc, char **s) typeIdSet access; advanceField (s); access = typeIdSet_undump (s); - advanceName (s); name = getStringWord (s); + advanceName (s); name = reader_getStringWord (s); ue = uentry_makeIterBase (name, access, ct, fileloc_copy (loc)); @@ -4415,7 +4997,7 @@ uentry_undump (ekind kind, fileloc loc, char **s) typeIdSet access; advanceField (s); access = typeIdSet_undump (s); - advanceName (s); name = getStringWord (s); + advanceName (s); name = reader_getStringWord (s); ue = uentry_makeEndIterBase (name, access, fileloc_copy (loc)); } @@ -4427,7 +5009,7 @@ uentry_undump (ekind kind, fileloc loc, char **s) multiVal val; nstate nullstate; - if (optCheckChar (s, '$')) + if (reader_optCheckChar (s, '$')) { val = multiVal_undefined; access = typeIdSet_undefined; @@ -4437,10 +5019,10 @@ uentry_undump (ekind kind, fileloc loc, char **s) { advanceField (s); val = multiVal_undump (s); advanceField (s); access = typeIdSet_undump (s); - advanceField (s); nullstate = nstate_fromInt (getInt (s)); + advanceField (s); nullstate = nstate_fromInt (reader_getInt (s)); } - advanceName (s); name = getStringWord (s); + advanceName (s); name = reader_getStringWord (s); ue = uentry_makeConstantBase (name, ct, access, nullstate, fileloc_copy (loc), val); @@ -4453,7 +5035,7 @@ uentry_undump (ekind kind, fileloc loc, char **s) ctype rtype; advanceField (s); rtype = ctype_undump (s); - advanceName (s); name = getStringWord (s); + advanceName (s); name = reader_getStringWord (s); ue = uentry_makeTagBase (name, kind, ct, rtype, fileloc_copy (loc)); } break; @@ -4490,9 +5072,11 @@ static cstring uentry_dumpAux (uentry v, bool isParam) { llassert (uentry_isValid (v)); + llassert (!uentry_isGlobalMarker (v)); + DPRINTF (("Dump uentry: [%p]", v)); DPRINTF (("Dumping entry: %s", uentry_unparseFull (v))); - + switch (v->ukind) { case KINVALID: @@ -4547,7 +5131,7 @@ uentry_dumpAux (uentry v, bool isParam) else { sdump = message ("%d@%d@%d@%d@%d", - (int) dss, + (int) dss, (int) nst, (int) alk, (int) exk, @@ -4573,9 +5157,16 @@ uentry_dumpAux (uentry v, bool isParam) } case KDATATYPE: - return (message ("%q@%s@%s@%d@%d@%d@%d@%q#%s", + /* + DPRINTF (("Dumping datatype: %s -> %s type: %s [%d]", + uentry_unparse (v), + exkind_unparse (sRef_getExKind (v->sref)), + ctype_unparse (v->utype), (int) v->utype)); + */ + + return (message ("%q@%c@%s@%d@%d@%d@%d@%q#%s", ctype_dump (v->utype), - ynm_unparseCode (v->info->datatype->abs), + qual_abstractCode (v->info->datatype->abs), ynm_unparseCode (v->info->datatype->mut), (int) sRef_getDefState (v->sref), (int) sRef_getNullState (v->sref), @@ -4585,7 +5176,7 @@ uentry_dumpAux (uentry v, bool isParam) v->uname)); case KFCN: { - cstring sdump, gdump, adump; + cstring sdump, gdump, adump, xdump; alkind alk = sRef_getAliasKind (v->sref); exkind exk = sRef_getExKind (v->sref); @@ -4593,18 +5184,18 @@ uentry_dumpAux (uentry v, bool isParam) && !nstate_isKnown (sRef_getNullState (v->sref)) && !exitkind_isKnown (v->info->fcn->exitCode) && v->info->fcn->specialCode == SPC_NONE - && v->info->fcn->nullPred == QU_UNKNOWN) + && qual_isUnknown (v->info->fcn->nullPred)) { sdump = cstring_makeLiteral ("$"); } else { - sdump = message ("@%d@%d@%d@%d@%d", + sdump = message ("@%d@%d@%d@%d@%x", (int) sRef_getDefState (v->sref), (int) sRef_getNullState (v->sref), (int) v->info->fcn->exitCode, (int) v->info->fcn->specialCode, - (int) v->info->fcn->nullPred); + qual_dump (v->info->fcn->nullPred)); } if (!uentry_hasGlobs(v) && !uentry_hasMods (v)) @@ -4634,27 +5225,26 @@ uentry_dumpAux (uentry v, bool isParam) adump = message ("@%d@%d", (int) alk, (int) exk); } - if (uentry_hasSpecialClauses (v)) + xdump = cstring_undefined; + + if (uentry_hasWarning (v)) { - return (message ("%q%q%q%q@%q@%q#%s", - ctype_dump (v->utype), - sdump, - gdump, - adump, - typeIdSet_dump (uentry_accessType (v)), - specialClauses_dump (v->info->fcn->specclauses), - v->uname)); + xdump = message ("%q@W:%q", xdump, warnClause_dump (v->warn)); } - else + + if (uentry_hasStateClauseList (v)) { - return (message ("%q%q%q%q@%q#%s", - ctype_dump (v->utype), - sdump, - gdump, - adump, - typeIdSet_dump (uentry_accessType (v)), - v->uname)); + xdump = message ("%q@S:%q", xdump, stateClauseList_dump (v->info->fcn->specclauses)); } + + return (message ("%q%q%q%q@%q%q#%s", + ctype_dump (v->utype), + sdump, + gdump, + adump, + typeIdSet_dump (uentry_accessType (v)), + xdump, + v->uname)); } case KITER: return (message ("%q@%q#%s", @@ -4671,7 +5261,7 @@ uentry_dumpAux (uentry v, bool isParam) { cstring sdump; - if (multiVal_isUnknown (v->info->uconst->val) + if (multiVal_isUnknown (uentry_getConstantValue (v)) && typeIdSet_isEmpty (uentry_accessType (v)) && (sRef_getNullState (v->sref) == NS_UNKNOWN)) { @@ -4680,7 +5270,7 @@ uentry_dumpAux (uentry v, bool isParam) else { sdump = message ("@%q@%q@%d", - multiVal_dump (v->info->uconst->val), + multiVal_dump (uentry_getConstantValue (v)), typeIdSet_dump (uentry_accessType (v)), (int) sRef_getNullState (v->sref)); } @@ -4741,75 +5331,73 @@ uentry_unparseFull (uentry v) { return (cstring_makeLiteral ("")); } - else if (uentry_isDatatype (v)) - { - return (message ("[%d] [%s] %s %q : %t [%t] %s %s // %q [s: %q; d: %q]", - (int) v, - ekind_unparse (v->ukind), - v->uname, - uentry_getName (v), - v->utype, - ctype_isDefined (v->info->datatype->type) - ? v->info->datatype->type : ctype_unknown, - ynm_unparse (v->info->datatype->mut), - ynm_unparse (v->info->datatype->abs), - sRef_unparseState (v->sref), - fileloc_unparse (v->whereSpecified), - fileloc_unparse (v->whereDefined))); - } - else if (uentry_isFunction (v)) - { - return (message ("[%w] = [%s] %q : %t / sref: %q / mods: %q / " - "globs: %q / [s: %q; decl: %q; def: %q]", - (long unsigned) v, - ekind_unparse (v->ukind), - uentry_getName (v), - v->utype, - sRef_unparseFull (v->sref), - sRefSet_unparse (v->info->fcn->mods), - globSet_unparse (v->info->fcn->globs), - fileloc_unparse (v->whereSpecified), - fileloc_unparse (v->whereDeclared), - fileloc_unparse (v->whereDefined))); - } - else if (uentry_isIter (v)) - { - return (message ("[%s] %q: %t / %q [s: %q; d: %q]", - ekind_unparse (v->ukind), - uentry_getName (v), - v->utype, - sRef_unparseFull (v->sref), - fileloc_unparse (v->whereSpecified), - fileloc_unparse (v->whereDefined))); - } - else if (uentry_isVariable (v)) - { - return - (message ("[check: %s] / [%w] = [%s] %s : %t %q [s: %q; def: %q; dec: %q] " - "kind <%d> isout <%d> used <%d>", - checkedName (v->info->var->checked), - (long unsigned) v, - ekind_unparse (v->ukind), - v->uname, - v->utype, - sRef_unparseDeep (v->sref), - fileloc_unparse (v->whereSpecified), - fileloc_unparse (v->whereDefined), - fileloc_unparse (v->whereDeclared), - (int) v->info->var->kind, - (int) v->info->var->defstate, - (int) v->used)); - } else { - return (message ("[%s] %s : %t %q at [s: %q; d: %q]", - ekind_unparse (v->ukind), - v->uname, - v->utype, - sRef_unparseFull (v->sref), - fileloc_unparse (v->whereSpecified), - fileloc_unparse (v->whereDefined))); - + cstring res; + + res = message ("[%p] %s %s: %s [spec: %q; decl: %q; def: %q]", + v, ekind_unparse (v->ukind), v->uname, + ctype_unparse (v->utype), + fileloc_unparse (uentry_whereSpecified (v)), + fileloc_unparse (uentry_whereDeclared (v)), + fileloc_unparse (uentry_whereDefined (v))); + + DPRINTF (("uentry: %s", res)); + + if (uentry_isDatatype (v)) + { + res = message ("%q / type: %s mut: %s abs: %s state: %q", + res, + ctype_unparse + (ctype_isDefined (v->info->datatype->type) + ? v->info->datatype->type : ctype_unknown), + ynm_unparse (v->info->datatype->mut), + qual_unparse (v->info->datatype->abs), + sRef_unparseState (v->sref)); + } + else if (uentry_isFunction (v)) + { + res = message ("%q / sref: %q / mods: %q / " + "globs: %q / clauses: %q / pre: %q / post: %q", + res, + sRef_unparseFull (v->sref), + sRefSet_unparse (v->info->fcn->mods), + globSet_unparse (v->info->fcn->globs), + stateClauseList_unparse (v->info->fcn->specclauses), + functionConstraint_unparse (v->info->fcn->preconditions), + functionConstraint_unparse (v->info->fcn->postconditions)); + } + else if (uentry_isIter (v)) + { + res = message ("%q / sref: %q", + res, + sRef_unparseFull (v->sref)); + } + else if (uentry_isVariable (v)) + { + res = message ("%q / sref: %q / kind <%d> isout <%d> null <%d> used <%d>", + res, + sRef_unparseFull (v->sref), + (int) v->info->var->kind, + (int) v->info->var->defstate, + (int) v->info->var->nullstate, + (int) v->used); + DPRINTF (("sref: [%p]", v->sref)); + DPRINTF (("sref: %s", sRef_unparseDebug (v->sref))); + /* DPRINTF (("sref: %s", sRef_unparseDeep (v->sref))); */ + } + else if (uentry_isConstant (v)) + { + res = message ("%q = %q / %q", + res, multiVal_unparse (uentry_getConstantValue (v)), + sRef_unparseFull (v->sref)); + } + else + { + res = message ("%q :: %q", res, uentry_unparse (v)); + } + + return res; } } @@ -4904,10 +5492,10 @@ uentry_setAbstract (uentry e) typeId oldid; llassert (uentry_isDatatype (e) - && (ynm_isMaybe (e->info->datatype->abs))); + && (qual_isUnknown (e->info->datatype->abs))); oldid = ctype_typeId (e->info->datatype->type); - e->info->datatype->abs = YES; + e->info->datatype->abs = qual_createAbstract (); e->info->datatype->type = ctype_createAbstract (oldid); } @@ -4915,23 +5503,24 @@ void uentry_setConcrete (uentry e) { llassert (uentry_isDatatype (e) - && (ynm_isMaybe (e->info->datatype->abs))); + && (qual_isUnknown (e->info->datatype->abs) + || qual_isConcrete (e->info->datatype->abs))); - e->info->datatype->abs = NO; + e->info->datatype->abs = qual_createConcrete (); } bool uentry_isAbstractDatatype (uentry e) { return (uentry_isDatatype (e) - && (ynm_isOn (e->info->datatype->abs))); + && (qual_isEitherAbstract (e->info->datatype->abs))); } bool uentry_isMaybeAbstract (uentry e) { return (uentry_isDatatype (e) - && (ynm_isMaybe (e->info->datatype->abs))); + && (!qual_isConcrete (e->info->datatype->abs))); } bool @@ -5040,8 +5629,7 @@ exitkind uentry_getExitCode (uentry ue) } } -qual -uentry_nullPred (uentry u) +qual uentry_nullPred (uentry u) { llassert (uentry_isRealFunction (u)); @@ -5051,10 +5639,14 @@ uentry_nullPred (uentry u) } else { - return QU_UNKNOWN; + return qual_createUnknown (); } } +/* +** Note for variables, this is checking the declared state, not the current state. +*/ + bool uentry_possiblyNull (uentry u) { @@ -5114,7 +5706,8 @@ uentry_hasName (uentry e) { cstring s = e->uname; - return (!(cstring_isEmpty (s) || cstring_equalLit (s, "..."))); + return (!(cstring_isEmpty (s) || cstring_equalLit (s, "...") + || uentry_isFakeTag (e))); } else { @@ -5122,9 +5715,16 @@ uentry_hasName (uentry e) } } +/* +** Returns true for fake tags. +** This is used for dumping the library +*/ + bool uentry_hasRealName (uentry e) { - return (uentry_isValid (e) && cstring_isNonEmpty (e->uname)); + return (uentry_isValid (e) + && cstring_isNonEmpty (e->uname) + && !uentry_isGlobalMarker (e)); } @@ -5136,27 +5736,35 @@ uentry_getGlobs (uentry l) return globSet_undefined; } - if (l->ukind != KFCN) + if (uentry_isFunction (l)) + { + return l->info->fcn->globs; + } + else if (uentry_isIter (l)) + { + return l->info->iter->globs; + } + else if (uentry_isEndIter (l)) + { + return globSet_undefined; + } + else { - if (l->ukind != KITER && l->ukind != KENDITER) + if (l->ukind == KVAR) { - if (l->ukind == KVAR) - { - llbug (message ("Bad call to uentry_getGlobs (var): %q (%s)", + llcontbug (message ("Bad call to uentry_getGlobs (var): %q (%s)", uentry_unparse (l), ekind_unparse (l->ukind))); - } - else - { - llbug (message ("Bad call to uentry_getGlobs: %q (%s)", + } + else + { + llcontbug (message ("Bad call to uentry_getGlobs: %q (%s)", uentry_unparse (l), ekind_unparse (l->ukind))); - } } + return globSet_undefined; } - - return l->info->fcn->globs; } /*@observer@*/ sRefSet @@ -5170,9 +5778,32 @@ uentry_getMods (uentry l) return sRefSet_undefined; } - return l->info->fcn->mods; + if (uentry_isFunction (l)) + { + return l->info->fcn->mods; + } + else if (uentry_isIter (l)) + { + return l->info->iter->mods; + } + else if (uentry_isEndIter (l)) + { + return sRefSet_undefined; + } + else + { + BADBRANCH; + } +# ifdef WIN32 +/* Make Microsoft VC++ happy */ +# pragma warning (disable:4715) +# endif } +# ifdef WIN32 +# pragma warning (enable:4715) +# endif + ekind uentry_getKind (uentry e) { @@ -5183,9 +5814,8 @@ uentry_getKind (uentry e) /*@observer@*/ multiVal uentry_getConstantValue (uentry e) { - llassert (uentry_isEitherConstant (e)); - - return (e->info->uconst->val); + llassert (uentry_isEitherConstant (e)); + return (sRef_getValue (e->sref)); } /*@observer@*/ uentryList @@ -5213,7 +5843,13 @@ uentry_getParams (uentry l) { ctype ct = l->utype; - llassert (ctype_isFunction (ct)); + /*drl 12/10/2002 changed to fix bug involving multiple redefines of library functions in macros. Bug was reported by Malcolm Parsons + + Old code was simplly llassert (ctype_isFunction (ct) ); + */ + + llassert (ctype_isFunction (ct) || context_inMacro() ); + return (ctype_argsFunction (ct)); } BADDEFAULT; @@ -5254,10 +5890,9 @@ uentry_getName (uentry e) if (uentry_isValid (e)) { - if (uentry_isAnyTag (e)) { - ret = fixTagName (e->uname); + ret = fixTagName (e->uname); } else if (uentry_isAnyParam (e)) { @@ -5272,6 +5907,36 @@ uentry_getName (uentry e) return ret; } +cstring uentry_observeRealName (uentry e) +{ + cstring ret = cstring_undefined; + + if (uentry_isValid (e)) + { + if (uentry_isAnyTag (e)) + { + if (isFakeTag (e->uname)) + { + ret = cstring_undefined; + } + else + { + ret = plainTagName (e->uname); + } + } + else if (uentry_isAnyParam (e)) + { + ret = fixParamName (e->uname); + } + else + { + ret = e->uname; + } + } + + return ret; +} + cstring uentry_getRealName (uentry e) { if (uentry_isValid (e)) @@ -5540,7 +6205,9 @@ uentry_setDefined (uentry e, fileloc f) bool uentry_isCodeDefined (uentry e) { - return (uentry_isValid (e) && fileloc_isDefined (e->whereDefined)); + llassert (uentry_isValid (e)); + + return (fileloc_isDefined (e->whereDefined)); } bool @@ -5566,6 +6233,28 @@ sRef uentry_getSref (uentry e) sRef uentry_getOrigSref (uentry e) { + /*@i523*/ /* evans 2001-09-09 - need to fix this + if (uentry_isValid (e)) + { + if (uentry_isVariable (e)) + { + return e->info->var->origsref; + } + else + { + sRef sr = sRef_copy (uentry_getSref (e)); + + sRef_resetState (sr); + sRef_clearDerived (sr); + return (sr); + } + } + else + { + return sRef_undefined; + } + */ + if (uentry_isValid (e)) { sRef sr = sRef_copy (uentry_getSref (e)); @@ -5618,18 +6307,14 @@ uentry_resetParams (uentry ue, /*@only@*/ uentryList pn) llassert (uentry_isValid (ue)); - rct = ctype_realType (ue->utype); - - if (uentry_isVariable (ue) && (ctype_isFunction (rct) || ctype_isUnknown (rct))) - { - uentry_makeVarFunction (ue); - } - + uentry_convertVarFunction (ue); llassert (uentry_isFunction (ue)); + rct = ctype_realType (ue->utype); + if (ctype_isFunction (rct)) { - rettype = ctype_returnValue (rct); + rettype = ctype_getReturnType (rct); } ue->utype = ctype_makeNFParamsFunction (rettype, pn); @@ -5638,7 +6323,6 @@ uentry_resetParams (uentry ue, /*@only@*/ uentryList pn) void uentry_setRefParam (uentry e) { - if (!uentry_isVar (e)) { llbug (message ("uentry_setParam: not variable: %q", uentry_unparse (e))); @@ -5793,7 +6477,7 @@ ctype uentry_getRealType (uentry e) { usymId iid = ctype_typeId (ct); - if /*@access usymId@*/ (iid == uid) /*@noaccess usymId@*/ + if (usymId_equal (iid, uid)) { llcontbug (message ("uentry_getRealType: recursive type! %s", ctype_unparse (ct))); @@ -5803,7 +6487,12 @@ ctype uentry_getRealType (uentry e) { /* evs 2000-07-25: possible infinite recursion ? */ uentry ue2 = usymtab_getTypeEntry (iid); - llassertprint (ue2 != e, ("Bad recursion: %s", uentry_unparseFull (e))); + + if (ue2 == e) + { + llcontbug (message ("Bad recursion: %q", uentry_unparseFull (e))); + return ctype_unknown; + } return uentry_getRealType (ue2); } @@ -5853,7 +6542,7 @@ ctype uentry_getForceRealType (uentry e) { usymId iid = ctype_typeId (ct); - if /*@access usymId@*/ (iid == uid) /*@noaccess usymId@*/ + if (usymId_equal (iid, uid)) { llcontbug (message ("uentry_getRealType: recursive type! %s", ctype_unparse (ct))); @@ -5890,6 +6579,7 @@ uentry uentry_nameCopy (cstring name, uentry e) enew->hasNameError = FALSE; enew->uses = filelocList_new (); + enew->warn = warnClause_undefined; enew->storageclass = e->storageclass; enew->info = uinfo_copy (e->info, e->ukind); @@ -5904,7 +6594,15 @@ uentry_setDatatype (uentry e, usymId uid) if (uentry_isAbstractType (e)) { - e->info->datatype->type = ctype_createAbstract (uid); + if (qual_isNumAbstract (e->info->datatype->abs)) + { + e->info->datatype->type = ctype_createNumAbstract (uid); + } + else + { + llassert (qual_isAbstract (e->info->datatype->abs)); + e->info->datatype->type = ctype_createAbstract (uid); + } } else { @@ -5931,18 +6629,21 @@ uentry_setSpecDef (/*@special@*/ uentry e, /*@keep@*/ fileloc f) e->whereDeclared = f; e->whereDefined = fileloc_undefined; } + + llassert (fileloc_storable (f)); } static void ucinfo_free (/*@only@*/ ucinfo u) { - multiVal_free (u->val); sfree (u); } static void uvinfo_free (/*@only@*/ uvinfo u) { + /*drl7x added 6/29/01 */ + free (u->bufinfo); /* evans - 2001-07-19 fixed this bug */ sfree (u); } @@ -5957,8 +6658,7 @@ ufinfo_free (/*@only@*/ ufinfo u) { globSet_free (u->globs); sRefSet_free (u->mods); - specialClauses_free (u->specclauses); - + stateClauseList_free (u->specclauses); sfree (u); } @@ -5978,10 +6678,8 @@ static /*@only@*/ ucinfo ucinfo_copy (ucinfo u) { ucinfo ret = (ucinfo) dmalloc (sizeof (*ret)); - - ret->val = multiVal_copy (u->val); ret->access = u->access; - + ret->macro = u->macro; return ret; } @@ -5994,12 +6692,29 @@ uvinfo_copy (uvinfo u) ret->nullstate = u->nullstate; ret->defstate = u->defstate; ret->checked = u->checked; - //make sure line ok - //ret->bufinfo = u->bufinfo; - /*@i334@*/ return ret; -} -static /*@only@*/ udinfo + /*@i523 ret->origsref = sRef_copy (u->origsref); */ + + /* drl added 07-02-001 */ + /* copy null terminated information */ + + if (u->bufinfo != NULL) + { + ret->bufinfo = (bbufinfo) dmalloc (sizeof( * u->bufinfo ) ); + ret->bufinfo->bufstate = u->bufinfo->bufstate; + ret->bufinfo->size = u->bufinfo->size; + ret->bufinfo->len = u->bufinfo->len; + return ret; + } + else + { + ret->bufinfo = NULL; + return ret; + } + +} + +static /*@only@*/ udinfo udinfo_copy (udinfo u) { udinfo ret = (udinfo) dmalloc (sizeof (*ret)); @@ -6025,16 +6740,10 @@ ufinfo_copy (ufinfo u) ret->globs = globSet_newCopy (u->globs); ret->mods = sRefSet_newCopy (u->mods); ret->defparams = u->defparams; - ret->specclauses = specialClauses_copy (u->specclauses); - - /*drl 11 30 2000 */ - ret->preconditions = u->preconditions? constraintList_copy(u->preconditions): NULL; - /* end drl */ - + ret->specclauses = stateClauseList_copy (u->specclauses); - /*drl 11 30 2000 */ - ret->postconditions = u->postconditions? constraintList_copy(u->postconditions): NULL; - /* end drl */ + ret->preconditions = functionConstraint_copy (u->preconditions); + ret->postconditions = functionConstraint_copy (u->postconditions); return ret; } @@ -6123,9 +6832,11 @@ uentry_reallyFree (/*@notnull@*/ /*@only@*/ uentry e) fileloc_free (e->whereDefined); fileloc_free (e->whereDeclared); + warnClause_free (e->warn); + nuentries--; sfree (e); - } +} extern void uentry_markOwned (/*@owned@*/ uentry u) { @@ -6150,6 +6861,7 @@ uentry_freeComplete (/*@only@*/ uentry e) { if (uentry_isValid (e) && !uentry_isElipsisMarker (e)) { + DPRINTF (("Free complete: %s", sRef_unparseFull (e->sref))); /*@i@*/ sRef_free (e->sref); e->sref = sRef_undefined; uentry_reallyFree (e); @@ -6166,7 +6878,7 @@ KindConformanceError (/*@unique@*/ uentry old, uentry unew, bool mustConform) llassert (uentry_isValid (old)); llassert (uentry_isValid (unew)); - if (uentry_isEitherConstant (unew) + if ((uentry_isEitherConstant (unew) || uentry_isDatatype (unew)) && (fileloc_isPreproc (uentry_whereDeclared (old)) || ctype_isUnknown (old->utype)) && !uentry_isSpecified (old)) @@ -6194,9 +6906,9 @@ KindConformanceError (/*@unique@*/ uentry old, uentry unew, bool mustConform) uentry_getName (unew), ekind_unparseLong (unew->ukind), unew->utype), - uentry_whereDeclared (unew))) + uentry_whereLast (unew))) /* evans 2001-12-30: was uentry_whereDeclared */ { - uentry_showWhereLast (old); + uentry_showWhereLastKind (old); } } else @@ -6213,9 +6925,9 @@ KindConformanceError (/*@unique@*/ uentry old, uentry unew, bool mustConform) uentry_getName (unew), ekind_unparseLong (unew->ukind), unew->utype), - uentry_whereDeclared (unew))) + uentry_whereLast (unew))) /* evans 2001-12-30: was uentry_whereDeclared */ { - uentry_showWhereLast (old); + uentry_showWhereLastKind (old); } } } @@ -6223,21 +6935,24 @@ KindConformanceError (/*@unique@*/ uentry old, uentry unew, bool mustConform) { llassert (uentry_isDeclared (unew)); + DPRINTF (("Old: \n\t%s", uentry_unparseFull (old))); + DPRINTF (("New: \n\t%s", uentry_unparseFull (unew))); + if (optgenerror (FLG_INCONDEFS, message ("%s %q inconsistently redeclared as %s", ekind_capName (old->ukind), uentry_getName (unew), ekind_unparseLong (unew->ukind)), - uentry_whereDeclared (unew))) + uentry_whereLast (unew))) /* evans 2001-12-30: was uentry_whereDeclared */ { - uentry_showWhereLast (old); + uentry_showWhereLastKind (old); } } } } - uentry_copyInto (old, unew); + uentry_updateInto (old, unew); } /* @@ -6255,7 +6970,7 @@ uentry_showWhereLast (uentry spec) { if (fileloc_isDefined (spec->whereDefined) && !fileloc_isLib (spec->whereDefined) - && !fileloc_isPreproc (spec->whereDefined)) + /*!! && !fileloc_isPreproc (spec->whereDefined) */ ) { llgenindentmsg (message ("Previous definition of %q: %t", uentry_getName (spec), @@ -6291,6 +7006,54 @@ uentry_showWhereLast (uentry spec) } } +static void +uentry_showWhereLastKind (uentry spec) +{ + if (uentry_isValid (spec)) + { + if (fileloc_isDefined (spec->whereDefined) + && !fileloc_isLib (spec->whereDefined) + /*!! && !fileloc_isPreproc (spec->whereDefined) */ ) + { + llgenindentmsg (message ("Previous definition of %q as %s: %t", + uentry_getName (spec), + ekind_unparseLong (spec->ukind), + uentry_getType (spec)), + uentry_whereDefined (spec)); + } + else if (uentry_isDeclared (spec)) + { + llgenindentmsg (message ("Previous declaration of %q as %s: %t", + uentry_getName (spec), + ekind_unparseLong (spec->ukind), + uentry_getType (spec)), + uentry_whereDeclared (spec)); + } + else if (uentry_isSpecified (spec)) + { + if (uentry_hasName (spec)) + { + llgenindentmsg (message ("Specification of %q as %s: %t", + uentry_getName (spec), + ekind_unparseLong (spec->ukind), + uentry_getType (spec)), + uentry_whereSpecified (spec)); + } + else + { + llgenindentmsg (message ("Specification as %s: %t", + ekind_unparseLong (spec->ukind), + uentry_getType (spec)), + uentry_whereSpecified (spec)); + } + } + else + { + /* nothing to show */ + } + } +} + void uentry_showDefSpecInfo (uentry ce, fileloc fwhere) { @@ -6587,9 +7350,10 @@ checkEnumConformance (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew) if (optgenerror (FLG_MATCHFIELDS, message ("Enum %q declared with members { %q } but " - "specified with members { %q }", + "%s with members { %q }", uentry_getName (old), enumNameList_unparse (enew), + uentry_specOrDefName (old), enumNameList_unparse (eold)), uentry_whereDeclared (unew))) { @@ -6664,6 +7428,10 @@ paramTypeError (uentry old, uentry oldCurrent, ctype oldType, if (hasError) { + DPRINTF (("Here: %s / %s", + uentry_unparseFull (oldCurrent), + uentry_unparseFull (newCurrent))); + if (!uentry_isUndefined (oldCurrent)) { if (!uentry_isUndefined (newCurrent) @@ -6690,7 +7458,7 @@ nargsError (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew) { if (optgenerror (FLG_TYPE, - message ("Function %s %rdeclared with %d arg%p, %s with %d", + message ("Function %s %rdeclared with %d arg%&, %s with %d", unew->uname, uentry_isDeclared (old), uentryList_size (uentry_getParams (unew)), @@ -6710,10 +7478,10 @@ returnValueError (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew) message ("Function %s inconsistently %rdeclared to return %t", unew->uname, uentry_isDeclared (old), - ctype_returnValue (unew->utype)), + ctype_getReturnType (unew->utype)), uentry_whereDeclared (unew))) { - uentry_showWhereLastVal (old, ctype_unparse (ctype_returnValue (old->utype))); + uentry_showWhereLastVal (old, ctype_unparse (ctype_getReturnType (old->utype))); } } @@ -6810,7 +7578,7 @@ void checkNullState (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew, bool m if (oldState == NS_MNOTNULL && (ctype_isUA (unew->utype) || (uentry_isFunction (unew) - && ctype_isUA (ctype_returnValue (unew->utype))))) + && ctype_isUA (ctype_getReturnType (unew->utype))))) { if (uentry_isVar (unew)) { @@ -6912,7 +7680,9 @@ void checkDefState (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew, newState = sRef_getDefState (unew->sref); } - if (newState != oldState && newState != SS_UNKNOWN && newState != SS_DEFINED) + if (newState != oldState + && newState != SS_UNKNOWN + && newState != SS_DEFINED) { if (mustConform) { @@ -6935,7 +7705,7 @@ void checkDefState (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew, uentry_showWhereSpecified (old); } } - + if (vars) old->info->var->defstate = newState; sRef_setDefState (old->sref, newState, uentry_whereDeclared (unew)); } @@ -6957,7 +7727,7 @@ void checkDefState (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew, uentry_showWhereSpecified (old); } } - + if (vars) unew->info->var->defstate = oldState; sRef_setDefState (unew->sref, oldState, uentry_whereDeclared (unew)); } @@ -7023,6 +7793,8 @@ static void { uentry_showWhereSpecified (old); + DPRINTF (("Old: %s", sRef_unparseFull (old->sref))); + DPRINTF (("New: %s", sRef_unparseFull (unew->sref))); sRef_setAliasKind (old->sref, AK_ERROR, uentry_whereDeclared (unew)); } @@ -7149,6 +7921,118 @@ static void } } +static void +checkMetaState (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew, + bool mustConform, /*@unused@*/ bool completeConform) +{ + valueTable newvals = sRef_getValueTable (unew->sref); + + if (valueTable_isDefined (newvals)) + { + DPRINTF (("Check meta state: %s -> %s", + uentry_unparseFull (old), + uentry_unparseFull (unew))); + + DPRINTF (("Check meta state refs: %s -> %s", + sRef_unparseFull (old->sref), + sRef_unparseFull (unew->sref))); + + DPRINTF (("Value table: %s", valueTable_unparse (newvals))); + + /* + ** Copy the new values into the old ref + */ + + valueTable_elements (newvals, key, newval) + { + metaStateInfo msinfo = context_lookupMetaStateInfo (key); + stateValue oldval = sRef_getMetaStateValue (old->sref, key); + + llassert (metaStateInfo_isDefined (msinfo)); + + if (stateValue_isUndefined (oldval)) + { + sRef_setMetaStateValue (old->sref, key, stateValue_getValue (newval), uentry_whereLast (unew)); + } + else + { + if (stateValue_isError (oldval)) + { + if (!stateValue_isError (newval)) + { + sRef_setMetaStateValue (old->sref, key, stateValue_getValue (newval), uentry_whereLast (unew)); + } + else + { + ; /* No change necessary. */ + } + } + else + { + if (stateValue_getValue (newval) != stateValue_getValue (oldval)) + { + if (fileloc_isXHFile (uentry_whereDeclared (unew))) + { + ; + } + else + { + if (!stateValue_isError (newval) + && !stateValue_isImplicit (newval)) + { + if (uentry_hasName (unew) + || !sRef_isParam (uentry_getSref (unew))) + { + if (mustConform + && optgenerror + (FLG_INCONDEFS, + message ("%s %q inconsistently %rdeclared %s %q, %s as %q", + uentry_ekindName (unew), + uentry_getName (unew), + uentry_isDeclared (old), + fcnErrName (unew), + stateValue_unparseValue (newval, msinfo), + uentry_specOrDefName (old), + stateValue_unparseValue (oldval, msinfo)), + uentry_whereDeclared (unew))) + { + uentry_showWhereSpecified (old); + } + } + else + { + if (mustConform + && optgenerror + (FLG_INCONDEFS, + message ("%s %d inconsistently %rdeclared %s %q, %s as %q", + uentry_ekindName (unew), + sRef_getParam (uentry_getSref (unew)), + uentry_isDeclared (old), + fcnErrName (unew), + stateValue_unparseValue (newval, msinfo), + uentry_specOrDefName (old), + stateValue_unparseValue (oldval, msinfo)), + uentry_whereDeclared (unew))) + { + uentry_showWhereSpecified (old); + } + } + } + } + + DPRINTF (("Updating!")); + sRef_setMetaStateValue (old->sref, key, stateValue_getValue (newval), uentry_whereLast (unew)); + } + else + { + DPRINTF (("Values match")); + } + } + } + } end_valueTable_elements ; + } +} + static void uentry_checkStateConformance (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew, @@ -7158,6 +8042,7 @@ uentry_checkStateConformance (/*@notnull@*/ uentry old, checkNullState (old, unew, mustConform, completeConform); checkAliasState (old, unew, mustConform, completeConform); checkExpState (old, unew, mustConform, completeConform); + checkMetaState (old, unew, mustConform, completeConform); sRef_storeState (old->sref); sRef_storeState (unew->sref); @@ -7425,14 +8310,18 @@ checkFunctionConformance (/*@unique@*/ /*@notnull@*/ uentry old, uentryList oldParams = uentry_getParams (old); uentryList newParams = uentry_getParams (unew); ctype newType = unew->utype; - ctype oldType = old->utype; + ctype oldType = ctype_realType (old->utype); ctype oldRetType = ctype_unknown; ctype newRetType = ctype_unknown; + DPRINTF (("Function conform: %s ==> %s", + uentry_unparseFull (old), + uentry_unparseFull (unew))); + if (uentry_isForward (old)) { mustConform = FALSE; - uentry_copyInto (old, unew); + uentry_updateInto (old, unew); return; } @@ -7443,15 +8332,13 @@ checkFunctionConformance (/*@unique@*/ /*@notnull@*/ uentry old, if (ctype_isKnown (oldType)) { llassert (ctype_isFunction (oldType)); - - oldRetType = ctype_returnValue (oldType); + oldRetType = ctype_getReturnType (oldType); } if (ctype_isKnown (newType)) { llassert (ctype_isFunction (newType)); - - newRetType = ctype_returnValue (newType); + newRetType = ctype_getReturnType (newType); } if (ctype_isKnown (oldRetType) && ctype_isKnown (newRetType) @@ -7489,7 +8376,11 @@ checkFunctionConformance (/*@unique@*/ /*@notnull@*/ uentry old, } } + DPRINTF (("Before state: %s", + uentry_unparseFull (old))); uentry_checkStateConformance (old, unew, mustConform, completeConform); + DPRINTF (("After state: %s", + uentry_unparseFull (old))); if (!exitkind_equal (unew->info->fcn->exitCode, old->info->fcn->exitCode)) { @@ -7514,7 +8405,7 @@ checkFunctionConformance (/*@unique@*/ /*@notnull@*/ uentry old, if (!qual_isUnknown (unew->info->fcn->nullPred)) { - if (!qual_equal (old->info->fcn->nullPred, unew->info->fcn->nullPred)) + if (!qual_match (old->info->fcn->nullPred, unew->info->fcn->nullPred)) { if (optgenerror (FLG_INCONDEFS, @@ -7606,7 +8497,7 @@ checkFunctionConformance (/*@unique@*/ /*@notnull@*/ uentry old, cstring nnamefix; if (cstring_isDefined (pfx) - && cstring_equalPrefix (oldname, cstring_toCharsSafe (pfx))) + && cstring_equalPrefix (oldname, pfx)) { oname = cstring_suffix (oldname, cstring_length (pfx)); } @@ -7616,7 +8507,7 @@ checkFunctionConformance (/*@unique@*/ /*@notnull@*/ uentry old, /*@-branchstate@*/ } /*@=branchstate@*/ if (cstring_isDefined (pfx) - && cstring_equalPrefix (nname, cstring_toCharsSafe (pfx))) + && cstring_equalPrefix (nname, pfx)) { nnamefix = cstring_suffix (nname, cstring_length (pfx)); } @@ -7711,7 +8602,7 @@ checkFunctionConformance (/*@unique@*/ /*@notnull@*/ uentry old, paramno++; /* - ** Forgot this! detected by lclint: + ** Forgot this! detected by splint: ** uentry.c:1257,15: Suspected infinite loop */ } @@ -7734,10 +8625,14 @@ checkFunctionConformance (/*@unique@*/ /*@notnull@*/ uentry old, checkGlobalsConformance (old, unew, mustConform, completeConform); checkModifiesConformance (old, unew, mustConform, completeConform); - if (specialClauses_isDefined (unew->info->fcn->specclauses)) + DPRINTF (("Before list: %s", + uentry_unparseFull (old))); + + if (stateClauseList_isDefined (unew->info->fcn->specclauses)) { - if (!specialClauses_isDefined (old->info->fcn->specclauses)) + if (!stateClauseList_isDefined (old->info->fcn->specclauses)) { + /* if (optgenerror (FLG_INCONDEFS, message ("Function %q redeclared using special clauses (can only " @@ -7747,12 +8642,23 @@ checkFunctionConformance (/*@unique@*/ /*@notnull@*/ uentry old, { uentry_showWhereLast (old); } + */ + + /*@i23 need checking @*/ + + old->info->fcn->specclauses = unew->info->fcn->specclauses; } else { - specialClauses_checkEqual (old, unew); + /*@i43 should be able to append? @*/ + + stateClauseList_checkEqual (old, unew); + stateClauseList_free (unew->info->fcn->specclauses); + unew->info->fcn->specclauses = stateClauseList_undefined; + /*@-branchstate@*/ } } + /*@=branchstate@*/ /*@i23 shouldn't need this@*/ if (fileloc_isUndefined (old->whereDeclared)) { @@ -7766,7 +8672,7 @@ checkFunctionConformance (/*@unique@*/ /*@notnull@*/ uentry old, { /* no change */ } -} +/*@i523 @*/ } void uentry_mergeConstantValue (uentry ue, /*@only@*/ multiVal m) @@ -7776,7 +8682,8 @@ uentry_mergeConstantValue (uentry ue, /*@only@*/ multiVal m) llassert (uentry_isValid (ue)); llassert (uentry_isEitherConstant (ue)); - uval = ue->info->uconst->val; + DPRINTF (("Constant value: %s / %s", uentry_unparse (ue), multiVal_unparse (m))); + uval = uentry_getConstantValue (ue); if (multiVal_isDefined (uval)) { @@ -7800,8 +8707,7 @@ uentry_mergeConstantValue (uentry ue, /*@only@*/ multiVal m) } else { - ue->info->uconst->val = m; - multiVal_free (uval); + uentry_setConstantValue (ue, m); } } @@ -7817,6 +8723,9 @@ bool checkTypeConformance (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew, { if (mustConform) { + DPRINTF (("Check struct conformance: %s / %s", + uentry_unparseFull (old), + uentry_unparseFull (unew))); checkStructConformance (old, unew); } } @@ -7846,6 +8755,10 @@ bool checkTypeConformance (/*@notnull@*/ uentry old, /*@notnull@*/ uentry unew, } else if (!ctype_match (old->utype, unew->utype)) { + DPRINTF (("Type mismatch: %s / %s", + ctype_unparse (old->utype), + ctype_unparse (unew->utype))); + if (cstring_equal (uentry_rawName (old), context_getBoolName ())) { ctype realt = ctype_realType (unew->utype); @@ -7976,10 +8889,10 @@ uentry_checkDatatypeConformance (/*@notnull@*/ uentry old, } } - if (unew->info->datatype->abs != MAYBE) + if (!qual_isUnknown (unew->info->datatype->abs)) { - if (ynm_isOff (old->info->datatype->abs) - && ynm_isOn (unew->info->datatype->abs)) + if (qual_isConcrete (old->info->datatype->abs) + && qual_isEitherAbstract (unew->info->datatype->abs)) { if (!ctype_isDirectBool (old->utype)) { @@ -7995,8 +8908,8 @@ uentry_checkDatatypeConformance (/*@notnull@*/ uentry old, } } } - else if (ynm_isOn (old->info->datatype->abs) - && ynm_isOff (unew->info->datatype->abs)) + else if (qual_isEitherAbstract (old->info->datatype->abs) + && qual_isConcrete (unew->info->datatype->abs)) { if (!ctype_isDirectBool (old->utype)) { @@ -8019,7 +8932,7 @@ uentry_checkDatatypeConformance (/*@notnull@*/ uentry old, } else { - if (ynm_isOn (old->info->datatype->abs)) + if (qual_isEitherAbstract (old->info->datatype->abs)) { old->sref = unew->sref; unew->info->datatype->mut = old->info->datatype->mut; @@ -8068,7 +8981,7 @@ uentry_checkDatatypeConformance (/*@notnull@*/ uentry old, } else { - if (ynm_isOn (old->info->datatype->abs)) + if (qual_isEitherAbstract (old->info->datatype->abs)) { if (ynm_isOn (old->info->datatype->mut) && ynm_isOff (unew->info->datatype->mut)) { @@ -8111,14 +9024,14 @@ uentry_checkConstantConformance (/*@notnull@*/ uentry old, bool mustConform, /*@unused@*/ bool completeConform) { - multiVal oldVal = old->info->uconst->val; - multiVal newVal = unew->info->uconst->val; + multiVal oldval = uentry_getConstantValue (old); + multiVal newval = uentry_getConstantValue (unew); - if (multiVal_isDefined (oldVal)) + if (multiVal_isDefined (oldval)) { - if (multiVal_isDefined (newVal)) + if (multiVal_isDefined (newval)) { - if (!multiVal_equiv (oldVal, newVal)) + if (!multiVal_equiv (oldval, newval)) { if (mustConform && optgenerror @@ -8127,15 +9040,14 @@ uentry_checkConstantConformance (/*@notnull@*/ uentry old, ekind_capName (unew->ukind), uentry_getName (unew), uentry_isDeclared (old), - multiVal_unparse (newVal)), + multiVal_unparse (newval)), uentry_whereDeclared (unew))) { - uentry_showWhereLastExtra (old, multiVal_unparse (oldVal)); + uentry_showWhereLastExtra (old, multiVal_unparse (oldval)); } } - unew->info->uconst->val = multiVal_copy (oldVal); - multiVal_free (newVal); + uentry_setConstantValue (unew, multiVal_copy (oldval)); } else { @@ -8144,7 +9056,7 @@ uentry_checkConstantConformance (/*@notnull@*/ uentry old, } else { - old->info->uconst->val = multiVal_copy (newVal); + uentry_setConstantValue (old, multiVal_copy (newval)); } } @@ -8178,14 +9090,14 @@ uentry_checkConformance (/*@unique@*/ /*@notnull@*/ uentry old, ** When a function is defined with an unparam macro */ - uentry_copyInto (old, unew); + uentry_updateInto (old, unew); return; } if (uentry_isExpandedMacro (old) && uentry_isEitherConstant (unew)) { - uentry_copyInto (old, unew); + uentry_updateInto (old, unew); return; } @@ -8212,7 +9124,7 @@ uentry_checkConformance (/*@unique@*/ /*@notnull@*/ uentry old, } } - uentry_copyInto (old, unew); + uentry_updateInto (old, unew); return; } else @@ -8249,7 +9161,7 @@ uentry_checkConformance (/*@unique@*/ /*@notnull@*/ uentry old, old->whereDefined); } - uentry_copyInto (old, unew); + uentry_updateInto (old, unew); old->used = unew->used = TRUE; return; } @@ -8416,6 +9328,84 @@ uentry_checkConformance (/*@unique@*/ /*@notnull@*/ uentry old, sRef_storeState (unew->sref); } +static void uentry_mergeConstraints (uentry spec, uentry def) +{ + if (uentry_isFunction (def)) + { + DPRINTF (("Here: %s / %s", + uentry_unparseFull (spec), + uentry_unparseFull (def))); + /* evans 2001-07-21 */ + llassert (uentry_isFunction (spec)); + + if (functionConstraint_isDefined (def->info->fcn->preconditions)) + { + if (fileloc_isXHFile (uentry_whereLast (def))) + { + llassert (uentry_isFunction (spec)); + spec->info->fcn->preconditions = functionConstraint_conjoin (spec->info->fcn->preconditions, + def->info->fcn->preconditions); + } + else if (fileloc_equal (uentry_whereLast (spec), uentry_whereLast (def))) + { + ; + } + else + { + /* Check if the constraints are identical */ + + if (optgenerror + (FLG_INCONDEFS, + message + ("Preconditions for %q redeclared. Dropping previous precondition: %q", + uentry_getName (spec), + functionConstraint_unparse (spec->info->fcn->preconditions)), + uentry_whereLast (def))) + { + uentry_showWhereSpecified (spec); + } + + functionConstraint_free (spec->info->fcn->preconditions); + spec->info->fcn->preconditions = def->info->fcn->preconditions; + } + + def->info->fcn->preconditions = functionConstraint_undefined; + } + + if (functionConstraint_isDefined (def->info->fcn->postconditions)) + { + if (fileloc_isXHFile (uentry_whereLast (def))) + { + llassert (uentry_isFunction (spec)); + DPRINTF (("Post: %s /++/ %s", + functionConstraint_unparse (spec->info->fcn->postconditions), + functionConstraint_unparse (def->info->fcn->postconditions))); + spec->info->fcn->postconditions = functionConstraint_conjoin (spec->info->fcn->postconditions, + def->info->fcn->postconditions); + def->info->fcn->postconditions = functionConstraint_undefined; + DPRINTF (("Conjoined post: %s", functionConstraint_unparse (spec->info->fcn->postconditions))); + } + else + { + if (optgenerror + (FLG_INCONDEFS, + message + ("Postconditions for %q redeclared. Dropping previous postcondition: %q", + uentry_getName (spec), + functionConstraint_unparse (spec->info->fcn->postconditions)), + uentry_whereLast (def))) + { + uentry_showWhereSpecified (spec); + } + + functionConstraint_free (spec->info->fcn->postconditions); + spec->info->fcn->postconditions = def->info->fcn->postconditions; + def->info->fcn->postconditions = functionConstraint_undefined; + } + } + } +} + /* ** modifies spec to reflect def, reports any inconsistencies */ @@ -8427,9 +9417,34 @@ uentry_mergeEntries (uentry spec, /*@only@*/ uentry def) llassert (uentry_isValid (def)); llassert (cstring_equal (spec->uname, def->uname)); + if (uentry_isFunction (def)) + { + if (uentry_isConstant (spec)) + { + llassert (ctype_isUnknown (spec->utype) || ctype_isFunction (spec->utype)); + uentry_makeConstantFunction (spec); + } + else + { + uentry_convertVarFunction (spec); + } + + llassert (uentry_isFunction (spec)); + } + + DPRINTF (("Merge entries: %s / %s", + uentry_unparseFull (spec), + uentry_unparseFull (def))); + + uentry_mergeConstraints (spec, def); + uentry_checkConformance (spec, def, TRUE, context_getFlag (FLG_NEEDSPEC)); + DPRINTF (("Merge entries after conform: %s / %s", + uentry_unparseFull (spec), + uentry_unparseFull (def))); + /* was: !(fileloc_isImport (uentry_whereSpecified (spec)))); */ /* @@ -8490,7 +9505,7 @@ uentry_clearDecl (void) void uentry_checkDecl (void) { - if (uentry_isValid (posRedeclared)) + if (uentry_isValid (posRedeclared) && !fileloc_isXHFile (posLoc)) { llassert (fileloc_isDefined (posLoc)); @@ -8535,20 +9550,19 @@ uentry_checkDecl (void) void uentry_mergeDefinition (uentry old, /*@only@*/ uentry unew) { - fileloc olddef = uentry_whereDeclared (old); + fileloc olddef = uentry_whereDeclared (old); fileloc unewdef = uentry_whereDeclared (unew); bool mustConform; bool wasForward; - - if (uentry_isExtern (unew)) - { - uentry_setUsed (old, unewdef); - } + DPRINTF (("uentry merge: %s / %s", + uentry_unparseFull (old), + uentry_unparseFull (unew))); + wasForward = fileloc_isUndefined (olddef) - && fileloc_isDefined (uentry_whereDefined (old)) - && !uentry_isExpandedMacro (old); + && fileloc_isDefined (uentry_whereDefined (old)) + && !uentry_isExpandedMacro (old); if (!context_getFlag (FLG_INCONDEFSLIB) && (fileloc_isLib (olddef) || fileloc_isImport (olddef))) @@ -8564,6 +9578,30 @@ uentry_mergeDefinition (uentry old, /*@only@*/ uentry unew) llassert (uentry_isValid (unew)); llassert (cstring_equal (old->uname, unew->uname)); + if (uentry_isFunction (unew) && !uentry_isFunction (old)) + { + if (uentry_isConstant (old)) + { + llassert (ctype_isUnknown (old->utype) || ctype_isFunction (old->utype)); + uentry_makeConstantFunction (old); + } + else + { + uentry_convertVarFunction (old); + } + + llassert (uentry_isFunction (old)); + } + + DPRINTF (("uentry merge: %s / %s", + uentry_unparseFull (old), + uentry_unparseFull (unew))); + + if (uentry_isExtern (unew)) + { + uentry_setUsed (old, unewdef); + } + /* ** should check old one was extern! */ @@ -8597,7 +9635,8 @@ uentry_mergeDefinition (uentry old, /*@only@*/ uentry unew) } else { - if (!uentry_isExtern (unew) && !uentry_isForward (old) + if (!uentry_isExtern (unew) + && !uentry_isForward (old) && !fileloc_equal (olddef, unewdef) && !fileloc_isUndefined (olddef) && !fileloc_isUndefined (unewdef) @@ -8629,7 +9668,7 @@ uentry_mergeDefinition (uentry old, /*@only@*/ uentry unew) /* if (uentry_isDatatype (old) || uentry_isAnyTag (old)) { - uentry_copyInto (old, unew); + uentry_updateInto (old, unew); old->sref = sRef_saveCopy (old->sref); } */ @@ -8667,13 +9706,25 @@ uentry_mergeDefinition (uentry old, /*@only@*/ uentry unew) } else { - uentry_setDefined (old, unewdef); + uentry_setDeclared (old, unewdef); /* evans 2001-07-23 was setDefined */ } } } } + DPRINTF (("uentry merge: %s / %s", + uentry_unparseFull (old), + uentry_unparseFull (unew))); + + uentry_mergeConstraints (old, unew); + DPRINTF (("uentry merge: %s / %s", + uentry_unparseFull (old), + uentry_unparseFull (unew))); + uentry_checkConformance (old, unew, mustConform, FALSE); + DPRINTF (("uentry merge: %s / %s", + uentry_unparseFull (old), + uentry_unparseFull (unew))); old->used = old->used || unew->used; old->uses = filelocList_append (old->uses, unew->uses); @@ -8688,6 +9739,8 @@ uentry_mergeDefinition (uentry old, /*@only@*/ uentry unew) fileloc_undefined); } + DPRINTF (("here: %s", uentry_unparseFull (old))); + /* ** No redeclaration errors for functions here, since we ** don't know if this is the definition of the function. @@ -8779,6 +9832,7 @@ uentry_mergeDefinition (uentry old, /*@only@*/ uentry unew) uentry_checkName (old); } + DPRINTF (("After: %s", uentry_unparseFull (old))); llassert (!ctype_isUndefined (old->utype)); } @@ -8825,39 +9879,101 @@ uentry_sameKind (uentry u1, uentry u2) return FALSE; } -static void uentry_copyInto (/*@unique@*/ uentry unew, uentry old) +static void uentry_updateInto (/*@unique@*/ uentry unew, uentry old) { + ekind okind; llassert (uentry_isValid (unew)); llassert (uentry_isValid (old)); + DPRINTF (("Update into: %s / %s", uentry_unparseFull (unew), uentry_unparseFull (old))); + okind = unew->ukind; unew->ukind = old->ukind; - unew->uname = cstring_copy (old->uname); + llassert (cstring_equal (unew->uname, old->uname)); unew->utype = old->utype; - unew->whereSpecified = fileloc_copy (old->whereSpecified); - unew->whereDefined = fileloc_copy (old->whereDefined); - unew->whereDeclared = fileloc_copy (old->whereDeclared); + if (fileloc_isDefined (unew->whereSpecified) + && !fileloc_isDefined (old->whereSpecified)) + { + ; /* Keep the old value */ + } + else + { + fileloc_free (unew->whereSpecified); /*@i523 why no error without this? */ + unew->whereSpecified = fileloc_copy (old->whereSpecified); + } + + if (fileloc_isDefined (unew->whereDefined) + && !fileloc_isDefined (old->whereDefined)) + { + ; /* Keep the old value */ + } + else + { + fileloc_free (unew->whereDefined); /*@i523 why no error without this? */ + unew->whereDefined = fileloc_copy (old->whereDefined); + } + + if (fileloc_isDefined (unew->whereDeclared) + && !fileloc_isDefined (old->whereDeclared)) + { + ; /* Keep the old value */ + } + else + { + fileloc_free (unew->whereDeclared); /*@i523 why no error without this? */ + unew->whereDeclared = fileloc_copy (old->whereDeclared); + } + + DPRINTF (("Update into: %s / %s", uentry_unparseFull (unew), uentry_unparseFull (old))); unew->sref = sRef_saveCopy (old->sref); /* Memory leak! */ unew->used = old->used; unew->lset = FALSE; unew->isPrivate = old->isPrivate; unew->hasNameError = old->hasNameError; - unew->uses = filelocList_undefined; + unew->uses = filelocList_append (unew->uses, old->uses); + old->uses = filelocList_undefined; unew->storageclass = old->storageclass; + uinfo_free (unew->info, okind); unew->info = uinfo_copy (old->info, old->ukind); } - -uentry -uentry_copy (uentry e) +static uentry +uentry_copyAux (uentry e, bool saveCopy) { + if (uentry_isValid (e)) { uentry enew = uentry_alloc (); DPRINTF (("copy: %s", uentry_unparseFull (e))); - uentry_copyInto (enew, e); + enew->ukind = e->ukind; + enew->uname = cstring_copy (e->uname); + enew->utype = e->utype; + + enew->whereSpecified = fileloc_copy (e->whereSpecified); + enew->whereDefined = fileloc_copy (e->whereDefined); + enew->whereDeclared = fileloc_copy (e->whereDeclared); + + if (saveCopy) + { + enew->sref = sRef_saveCopy (e->sref); /* Memory leak! */ + } + else + { + enew->sref = sRef_copy (e->sref); + } + + enew->used = e->used; + enew->lset = FALSE; + enew->isPrivate = e->isPrivate; + enew->hasNameError = e->hasNameError; + enew->uses = filelocList_undefined; + + enew->storageclass = e->storageclass; + enew->info = uinfo_copy (e->info, e->ukind); + enew->warn = warnClause_copy (e->warn); + DPRINTF (("Here we are...")); DPRINTF (("original: %s", uentry_unparseFull (e))); DPRINTF (("copy: %s", uentry_unparse (enew))); @@ -8870,6 +9986,18 @@ uentry_copy (uentry e) } } +uentry +uentry_copy (uentry e) +{ + return uentry_copyAux (e, TRUE); +} + +uentry +uentry_copyNoSave (uentry e) +{ + return uentry_copyAux (e, FALSE); +} + void uentry_setState (uentry res, uentry other) { @@ -8921,8 +10049,8 @@ uentry_mergeUses (uentry res, uentry other) */ static void - branchStateError (/*@notnull@*/ uentry res, /*@notnull@*/ uentry other, - bool flip, clause cl, fileloc loc) +branchStateError (/*@notnull@*/ uentry res, /*@notnull@*/ uentry other, + bool flip, clause cl, fileloc loc) { if (optgenerror (FLG_BRANCHSTATE, @@ -8932,25 +10060,50 @@ static void sRef_stateAltVerb (res->sref), clause_nameFlip (cl, !flip)), loc)) { + DPRINTF (("Here: %s / %s", sRef_unparseFull (res->sref), sRef_unparseFull (other->sref))); + if (sRef_isDead (res->sref)) { - sRef_showStateInfo (res->sref); + if (sRef_hasStateInfoLoc (res->sref)) { + llgenindentmsg (message ("%s:", clause_nameFlip (cl, flip)), loc); + sRef_showStateInfo (res->sref); + } + + if (sRef_hasStateInfoLoc (other->sref)) { + llgenindentmsg (message ("%s:", clause_nameFlip (cl, !flip)), loc); + sRef_showStateInfo (other->sref); + } } else if (sRef_isKept (res->sref)) { - sRef_showAliasInfo (res->sref); + if (sRef_hasAliasInfoLoc (res->sref)) { + llgenindentmsg (message ("%s:", clause_nameFlip (cl, flip)), loc); + sRef_showAliasInfo (res->sref); + } + + if (sRef_hasAliasInfoLoc (other->sref)) { + llgenindentmsg (message ("%s:", clause_nameFlip (cl, !flip)), loc); + sRef_showAliasInfo (other->sref); + } } else /* dependent */ { - sRef_showAliasInfo (res->sref); - sRef_showAliasInfo (other->sref); + if (sRef_hasAliasInfoLoc (res->sref)) { + llgenindentmsg (message ("%s:", clause_nameFlip (cl, flip)), loc); + sRef_showAliasInfo (res->sref); + } + + if (sRef_hasAliasInfoLoc (other->sref)) { + llgenindentmsg (message ("%s:", clause_nameFlip (cl, !flip)), loc); + sRef_showAliasInfo (other->sref); + } } sRef_setAliasKind (res->sref, AK_ERROR, fileloc_undefined); } } -static bool incompatibleStates (sRef rs, sRef os) +static bool uentry_incompatibleMemoryStates (sRef rs, sRef os) { alkind rk = sRef_getAliasKind (rs); alkind ok = sRef_getAliasKind (os); @@ -8984,11 +10137,27 @@ static void { if (sRef_isDead (other->sref)) { - sRef_showStateInfo (other->sref); + if (sRef_hasStateInfoLoc (other->sref)) { + llgenindentmsg (message ("%s:", clause_nameFlip (cl, flip)), loc); + sRef_showStateInfo (other->sref); + } + + if (sRef_hasStateInfoLoc (res->sref)) { + llgenindentmsg (message ("%s:", clause_nameFlip (cl, !flip)), loc); + sRef_showStateInfo (res->sref); + } } else /* kept */ { - sRef_showAliasInfo (other->sref); + if (sRef_hasAliasInfoLoc (other->sref)) { + llgenindentmsg (message ("%s:", clause_nameFlip (cl, flip)), loc); + sRef_showAliasInfo (other->sref); + } + + if (sRef_hasAliasInfoLoc (res->sref)) { + llgenindentmsg (message ("%s:", clause_nameFlip (cl, !flip)), loc); + sRef_showAliasInfo (res->sref); + } } sRef_setAliasKind (res->sref, AK_ERROR, fileloc_undefined); @@ -8999,46 +10168,62 @@ static void } } -static bool notNull (sRef sr, bool flip) +/* +** A reference is relevant for certain checks, only if it +** is not definitely null on this path (but not declared +** to always be null.) +*/ + +static bool uentry_relevantReference (sRef sr, bool flip) { - return (!sRef_definitelyNull (sr) - && !(sRef_isKept (sr)) - && !(sRef_isDependent (sr)) - && !(flip ? usymtab_isProbableDeepNull (sr) - : usymtab_isAltProbablyDeepNull (sr))); + if (sRef_isKept (sr) || sRef_isDependent (sr)) + { + return FALSE; + } + else + { + if (flip) + { + return !sRef_definitelyNullContext (sr); + } + else + { + return !sRef_definitelyNullAltContext (sr); + } + } } - -void -uentry_mergeState (uentry res, uentry other, fileloc loc, - bool mustReturn, bool flip, bool opt, - clause cl) -{ - llassert (uentry_isValid (res)); - llassert (uentry_isValid (other)); - llassert (res->ukind == other->ukind); - llassert (res->ukind == KVAR); +static void +uentry_mergeAliasStates (/*@notnull@*/ uentry res, /*@notnull@*/ uentry other, + fileloc loc, bool mustReturn, bool flip, bool opt, + clause cl) +{ + sRef rs = res->sref; + sRef os = other->sref; - DPRINTF (("Merge state: %s / %s", - uentry_unparse (res), - uentry_unparse (other))); + DPRINTF (("Merge alias states: %s / %s", + uentry_unparseFull (res), + uentry_unparseFull (other))); - if (sRef_isValid (res->sref)) + if (sRef_isValid (rs)) { if (!mustReturn) { - if (incompatibleStates (res->sref, other->sref)) + if (uentry_incompatibleMemoryStates (rs, os)) { - if (sRef_isThroughArrayFetch (res->sref) + DPRINTF (("Incompatible: \n\t%s / \n\t%s", + sRef_unparseFull (rs), sRef_unparseFull (os))); + + if (sRef_isThroughArrayFetch (rs) && !context_getFlag (FLG_STRICTBRANCHSTATE)) { - if (sRef_isKept (res->sref) || sRef_isKept (other->sref)) + if (sRef_isKept (rs) || sRef_isKept (os)) { - sRef_maybeKill (res->sref, loc); + sRef_maybeKill (rs, loc); } - else if (sRef_isPossiblyDead (other->sref)) + else if (sRef_isPossiblyDead (os)) { - sRef_maybeKill (res->sref, loc); + sRef_maybeKill (rs, loc); } else { @@ -9047,55 +10232,56 @@ uentry_mergeState (uentry res, uentry other, fileloc loc, } else { - if (notNull (other->sref, flip)) + if (uentry_relevantReference (os, flip)) { - if (sRef_isLocalParamVar (res->sref) - && (sRef_isLocalState (other->sref) - || sRef_isDependent (other->sref))) + if (sRef_isLocalParamVar (rs) + && (sRef_isLocalState (os) + || sRef_isDependent (os))) { - if (sRef_isDependent (res->sref)) + if (sRef_isDependent (rs)) { - sRef_setDependent (other->sref, loc); + sRef_setDependent (os, loc); } else { - sRef_setDefState (res->sref, SS_UNUSEABLE, loc); + sRef_setDefState (rs, SS_UNUSEABLE, loc); } } else { - branchStateError (res, other, flip, cl, loc); + branchStateError (res, other, !flip, cl, loc); /* evans 2002-12-15: changed flip to !flip */ } } } - if (sRef_isKept (res->sref)) + if (sRef_isKept (rs)) { - sRef_setKept (other->sref, loc); + DPRINTF (("Setting kept: %s", sRef_unparseFull (os))); + sRef_setKept (os, loc); } } else { - if (incompatibleStates (other->sref, res->sref)) + if (uentry_incompatibleMemoryStates (os, rs)) { - if (notNull (res->sref, !flip)) + if (uentry_relevantReference (rs, !flip)) { - if (sRef_isLocalParamVar (res->sref) - && (sRef_isDependent (res->sref) - || sRef_isLocalState (res->sref))) + if (sRef_isLocalParamVar (rs) + && (sRef_isDependent (rs) + || sRef_isLocalState (rs))) { - if (sRef_isDependent (other->sref)) + if (sRef_isDependent (os)) { - sRef_setDependent (res->sref, loc); + sRef_setDependent (rs, loc); } else { - sRef_setDefState (res->sref, SS_UNUSEABLE, loc); + sRef_setDefState (rs, SS_UNUSEABLE, loc); } } else { - if (sRef_isParam (other->sref)) + if (sRef_isParam (os)) { /* ** If the local variable associated @@ -9103,13 +10289,13 @@ uentry_mergeState (uentry res, uentry other, fileloc loc, ** its okay. ** (e.g., free (s); s = new(); ... */ - + uentry uvar = usymtab_lookupSafe (other->uname); - + if (uentry_isValid (uvar) - && ((sRef_isDead (other->sref) + && ((sRef_isDead (os) && sRef_isOnly (uvar->sref)) - || (sRef_isDependent (other->sref) + || (sRef_isDependent (os) && sRef_isOwned (uvar->sref)))) { /* no error */ @@ -9122,105 +10308,322 @@ uentry_mergeState (uentry res, uentry other, fileloc loc, } else { + DPRINTF (("Here: %s / %s", + uentry_unparseFull (res), + uentry_unparseFull (other))); + branchStateAltError (res, other, flip, cl, loc); } } } } - - if (sRef_isKept (other->sref)) + + if (sRef_isKept (os)) { - sRef_setKept (res->sref, loc); + sRef_setKept (rs, loc); } } if (opt) { DPRINTF (("Merge opt...")); - sRef_mergeOptState (res->sref, other->sref, cl, loc); + sRef_mergeOptState (rs, os, cl, loc); DPRINTF (("Done!")); } else { - sRef_mergeState (res->sref, other->sref, cl, loc); + DPRINTF (("Merging states: \n\t%s / \n\t%s", sRef_unparseFull (rs), sRef_unparseFull (os))); + sRef_mergeState (rs, os, cl, loc); + DPRINTF (("After merging : \n\t%s / \n\t%s", sRef_unparseFull (rs), sRef_unparseFull (os))); } } else { - if (sRef_isModified (other->sref)) + if (sRef_isModified (os)) { - sRef_setModified (res->sref); + sRef_setModified (rs); } } + } - if (cl == DOWHILECLAUSE) - { - res->used = other->used || res->used; - res->lset = other->lset || res->lset; - res->uses = filelocList_append (res->uses, other->uses); - other->uses = filelocList_undefined; - } - else + DPRINTF (("After merge: %s", sRef_unparseFull (res->sref))); +} + +static void +uentry_mergeValueStates (/*@notnull@*/ uentry res, /*@notnull@*/ uentry other, + fileloc loc, bool mustReturn, /*@unused@*/ bool flip) +{ + valueTable rvalues; + valueTable ovalues; + + DPRINTF (("Merge values: %s / %s", sRef_unparseFull (res->sref), sRef_unparseFull (other->sref))); + + if (mustReturn) + { + return; + } + /* flip? */ + + rvalues = sRef_getValueTable (res->sref); + ovalues = sRef_getValueTable (other->sref); + + if (valueTable_isUndefined (ovalues)) + { + DPRINTF (("No value table: %s", sRef_unparseFull (other->sref))); + ; + } + else if (valueTable_isUndefined (rvalues)) + { + /* + ** Copy values from other + */ + + /*@i$@#@*/ + DPRINTF (("Has value table: %s", sRef_unparseFull (other->sref))); + DPRINTF (("No value table: %s", sRef_unparseFull (res->sref))); + ; + } + else + { + valueTable_elements (ovalues, fkey, fval) { + stateValue tval; + metaStateInfo minfo; + stateCombinationTable sctable; + cstring msg; + int nval; + + tval = valueTable_lookup (rvalues, fkey); + + DPRINTF (("Merge value: %s / %s X %s", fkey, + stateValue_unparse (fval), stateValue_unparse (tval))); + + minfo = context_lookupMetaStateInfo (fkey); + llassert (stateValue_isDefined (tval)); + + if (metaStateInfo_isUndefined (minfo) || !stateValue_isDefined (tval)) + { + DPRINTF (("Cannot find meta state for: %s", fkey)); + BADBRANCH; + } + else + { + llassert (metaStateInfo_isDefined (minfo)); + + if (stateValue_isError (fval) + || sRef_definitelyNullContext (res->sref)) + { + sRef_setMetaStateValueComplete (res->sref, + fkey, stateValue_getValue (fval), + stateValue_getLoc (fval)); + DPRINTF (("Setting res: %s", sRef_unparseFull (res->sref))); + } + else if (stateValue_isError (tval) + || sRef_definitelyNullAltContext (other->sref)) + { + DPRINTF (("Other branch is definitely null!")); + } + else if (sRef_isStateUndefined (res->sref) + || sRef_isDead (res->sref)) + { + ; /* Combination state doesn't matter if it is undefined or dead */ + } + else + { + DPRINTF (("Check: %s / %s / %s / %s", fkey, + metaStateInfo_unparse (minfo), + stateValue_unparse (fval), + stateValue_unparse (tval))); + + DPRINTF (("state values: %d / %d", + stateValue_getValue (fval), stateValue_getValue (tval))); + + sctable = metaStateInfo_getMergeTable (minfo); + + DPRINTF (("Merge table: %s", + stateCombinationTable_unparse (sctable))); + + msg = cstring_undefined; + + nval = stateCombinationTable_lookup (sctable, + stateValue_getValue (fval), + stateValue_getValue (tval), + &msg); + + DPRINTF (("nval: %d / %d / %d", nval, + stateValue_getValue (fval), stateValue_getValue (tval))); + + if (nval == stateValue_error) + { + /*@i32 print extra info for assignments@*/ + + if (uentry_isGlobalMarker (res)) + { + if (optgenerror + (FLG_STATEMERGE, + message + ("Control branches merge with incompatible global states (%s and %s)%q", + metaStateInfo_unparseValue (minfo, stateValue_getValue (fval)), + metaStateInfo_unparseValue (minfo, stateValue_getValue (tval)), + cstring_isDefined (msg) + ? message (": %s", msg) : cstring_undefined), + loc)) + { + sRef_showMetaStateInfo (res->sref, fkey); + sRef_showMetaStateInfo (other->sref, fkey); + } + } + else + { + if (optgenerror + (FLG_STATEMERGE, + message + ("Control branches merge with incompatible states for %q (%s and %s)%q", + uentry_getName (res), + metaStateInfo_unparseValue (minfo, stateValue_getValue (fval)), + metaStateInfo_unparseValue (minfo, stateValue_getValue (tval)), + cstring_isDefined (msg) + ? message (": %s", msg) : cstring_undefined), + loc)) + { + sRef_showMetaStateInfo (res->sref, fkey); + sRef_showMetaStateInfo (other->sref, fkey); + DPRINTF (("Res: %s", sRef_unparseFull (res->sref))); + DPRINTF (("Other: %s", sRef_unparseFull (other->sref))); + DPRINTF (("Null: %s / %s", + bool_unparse (usymtab_isDefinitelyNull (res->sref)), + bool_unparse (usymtab_isDefinitelyNull (other->sref)))); + + } + } + } + + if (nval == stateValue_getValue (fval) + && nval != stateValue_getValue (tval)) + { + loc = stateValue_getLoc (fval); + } + else if (nval == stateValue_getValue (tval) + && nval != stateValue_getValue (fval)) + { + loc = stateValue_getLoc (tval); + } + else + { + ; + } + + if (stateValue_getValue (sRef_getMetaStateValue (res->sref, fkey)) == nval + && nval == stateValue_getValue (fval) + && nval == stateValue_getValue (tval)) + { + ; + } + else + { + sRef_setMetaStateValueComplete (res->sref, fkey, nval, loc); + } + } + } + } end_valueTable_elements ; + } +} + + +static void +uentry_mergeSetStates (/*@notnull@*/ uentry res, + /*@notnull@*/ uentry other, /*@unused@*/ fileloc loc, + bool flip, clause cl) +{ + if (cl == DOWHILECLAUSE) + { + res->used = other->used || res->used; + res->lset = other->lset || res->lset; + res->uses = filelocList_append (res->uses, other->uses); + other->uses = filelocList_undefined; + } + else + { + if (sRef_isMacroParamRef (res->sref) + && !uentry_isSefParam (other) + && !uentry_isSefParam (res)) { - if (sRef_isMacroParamRef (res->sref) - && !uentry_isSefParam (other) - && !uentry_isSefParam (res)) + bool hasError = FALSE; + + if (bool_equal (res->used, other->used)) { - bool hasError = FALSE; - - if (bool_equal (res->used, other->used)) + res->used = other->used; + } + else + { + if (other->used && !flip) { - res->used = other->used; + hasError = + optgenerror + (FLG_MACROPARAMS, + message ("Macro parameter %q used in true clause, " + "but not in false clause", + uentry_getName (res)), + uentry_whereDeclared (res)); } else + { + hasError = + optgenerror + (FLG_MACROPARAMS, + message ("Macro parameter %q used in false clause, " + "but not in true clause", + uentry_getName (res)), + uentry_whereDeclared (res)); + } + res->used = TRUE; + + if (hasError) { - if (other->used && !flip) - { - hasError = - optgenerror - (FLG_MACROPARAMS, - message ("Macro parameter %q used in true clause, " - "but not in false clause", - uentry_getName (res)), - uentry_whereDeclared (res)); - } - else - { - hasError = - optgenerror - (FLG_MACROPARAMS, - message ("Macro parameter %q used in false clause, " - "but not in true clause", - uentry_getName (res)), - uentry_whereDeclared (res)); - } - res->used = TRUE; - - if (hasError) - { - /* make it sef now, prevent more errors */ - res->info->var->kind = VKREFSEFPARAM; - } + /* make it sef now, prevent more errors */ + res->info->var->kind = VKREFSEFPARAM; } } - else - { - res->used = other->used || res->used; - res->lset = other->lset || res->lset; - res->uses = filelocList_append (res->uses, other->uses); - other->uses = filelocList_undefined; - } + } + else + { + res->used = other->used || res->used; + res->lset = other->lset || res->lset; + res->uses = filelocList_append (res->uses, other->uses); + other->uses = filelocList_undefined; } } } +void +uentry_mergeState (uentry res, uentry other, fileloc loc, + bool mustReturn, bool flip, bool opt, + clause cl) +{ + llassert (uentry_isValid (res)); + llassert (uentry_isValid (other)); + + llassert (res->ukind == other->ukind); + llassert (res->ukind == KVAR); + + DPRINTF (("Merge state: %s / %s", uentry_unparseFull (res), + uentry_unparseFull (other))); + + uentry_mergeAliasStates (res, other, loc, mustReturn, flip, opt, cl); + uentry_mergeValueStates (res, other, loc, mustReturn, flip); + uentry_mergeSetStates (res, other, loc, flip, cl); + + DPRINTF (("Merge ==> %s", uentry_unparseFull (res))); +} + void uentry_setUsed (uentry e, fileloc loc) { static bool firstTime = TRUE; static bool showUses = FALSE; static bool exportLocal = FALSE; + DPRINTF (("Used: %s / %s", uentry_unparse (e), fileloc_unparse (loc))); + if (firstTime) { /* need to track uses is FLG_SHOWUSES or FLG_EXPORTLOCAL is true */ @@ -9234,7 +10637,27 @@ void uentry_setUsed (uentry e, fileloc loc) if (uentry_isValid (e)) { int dp; - + + if (warnClause_isDefined (e->warn)) + { + flagSpec flg = warnClause_getFlag (e->warn); + cstring msg; + + if (warnClause_hasMessage (e->warn)) + { + msg = cstring_copy (warnClause_getMessage (e->warn)); + } + else + { + msg = message ("Use of possibly dangerous %s", + uentry_ekindNameLC (e)); + } + + vfsgenerror (flg, + message ("%q: %q", msg, uentry_getName (e)), + loc); + } + if (sRef_isMacroParamRef (e->sref)) { if (uentry_isYield (e) || uentry_isSefParam (e)) @@ -9279,7 +10702,7 @@ void uentry_setUsed (uentry e, fileloc loc) } e->used = TRUE; - + if (!sRef_isLocalVar (e->sref)) { if (showUses) @@ -9314,43 +10737,253 @@ bool uentry_isReturned (uentry u) || u->info->var->kind == VKSEFRETPARAM)); } +/*@i52323@*/ +# if 0 /*@exposed@*/ sRef uentry_returnedRef (uentry u, exprNodeList args) { llassert (uentry_isRealFunction (u)); - if (ctype_isFunction (u->utype) - && sRef_isStateSpecial (uentry_getSref (u))) + if (ctype_isFunction (u->utype) && sRef_isStateSpecial (uentry_getSref (u))) { - specialClauses clauses = uentry_getSpecialClauses (u); - sRef res = sRef_makeNew (ctype_returnValue (u->utype), u->sref, u->uname); + stateClauseList clauses = uentry_getStateClauseList (u); + sRef res = sRef_makeNew (ctype_getReturnType (u->utype), u->sref, u->uname); + DPRINTF (("Returned: %s", sRef_unparseFull (res))); sRef_setAllocated (res, g_currentloc); - specialClauses_postElements (clauses, cl) - { - sRefSet refs = specialClause_getRefs (cl); - sRefMod modf = specialClause_getEffectFunction (cl); + DPRINTF (("ensures clause: %s / %s", uentry_unparse (u), + stateClauseList_unparse (clauses))); + + /* + ** This should be in exprNode_reflectEnsuresClause + */ - sRefSet_elements (refs, el) + stateClauseList_postElements (clauses, cl) + { + if (!stateClause_isGlobal (cl)) { - sRef base = sRef_getRootBase (el); + sRefSet refs = stateClause_getRefs (cl); + sRefMod modf = stateClause_getEffectFunction (cl); + + sRefSet_elements (refs, el) + { + sRef base = sRef_getRootBase (el); + + if (sRef_isResult (base)) + { + if (modf != NULL) + { + sRef sr = sRef_fixBase (el, res); + modf (sr, g_currentloc); + } + } + else + { + ; + } + } end_sRefSet_elements ; + } + } end_stateClauseList_postElements ; + + return res; + } + else + { + uentryList params; + alkind ak; + sRefSet prefs = sRefSet_new (); + sRef res = sRef_undefined; + sRef tcref = sRef_undefined; + sRef tref = sRef_undefined; + int paramno = 0; + + params = uentry_getParams (u); - if (sRef_isResult (base)) + /* + ** Setting up aliases has to happen *after* setting null state! + */ + + uentryList_elements (params, current) + { + if (uentry_isReturned (current)) + { + if (exprNodeList_size (args) >= paramno) { - if (modf != NULL) + exprNode ecur = exprNodeList_nth (args, paramno); + tref = exprNode_getSref (ecur); + + DPRINTF (("Returned reference: %s", sRef_unparseFull (tref))); + + if (sRef_isValid (tref)) { - sRef sr = sRef_fixBase (el, res); - modf (sr, g_currentloc); + tcref = sRef_copy (tref); + + if (sRef_isDead (tcref)) + { + sRef_setDefined (tcref, g_currentloc); + sRef_setOnly (tcref, g_currentloc); + } + + if (sRef_isRefCounted (tcref)) + { + /* could be a new ref now (but only if its returned) */ + sRef_setAliasKindComplete (tcref, AK_ERROR, g_currentloc); + } + + sRef_makeSafe (tcref); + prefs = sRefSet_insert (prefs, tcref); } } + } + + paramno++; + } end_uentryList_elements ; + + if (sRefSet_size (prefs) > 0) + { + nstate n = sRef_getNullState (u->sref); + + if (sRefSet_size (prefs) == 1) + { + sRef rref = sRefSet_choose (prefs); + tref = rref; + res = sRef_makeType (sRef_getType (rref)); + sRef_copyState (res, tref); + } + else + { + /* should this ever happen? */ /*@i534 evans 2001-05-27 */ + res = sRefSet_mergeIntoOne (prefs); + } + + if (nstate_isKnown (n)) + { + sRef_setNullState (res, n, g_currentloc); + DPRINTF (("Setting null: %s", sRef_unparseFull (res))); + } + } + else + { + if (ctype_isFunction (u->utype)) + { + DPRINTF (("Making new from %s -->", uentry_unparseFull (u))); + res = sRef_makeNew (ctype_getReturnType (u->utype), u->sref, u->uname); + } + else + { + DPRINTF (("Making new from %s -->", uentry_unparseFull (u))); + res = sRef_makeNew (ctype_unknown, u->sref, u->uname); + } + + if (sRef_isRefCounted (res)) + { + sRef_setAliasKind (res, AK_NEWREF, g_currentloc); + } + } + + if (sRef_getNullState (res) == NS_ABSNULL) + { + ctype ct = ctype_realType (u->utype); + + if (ctype_isAbstract (ct)) + { + sRef_setNotNull (res, g_currentloc); + } + else + { + if (ctype_isUser (ct)) + { + sRef_setStateFromUentry (res, usymtab_getTypeEntry (ctype_typeId (ct))); + } else { - ; + sRef_setNotNull (res, g_currentloc); } - } end_sRefSet_elements ; + } + } + + if (sRef_isRefCounted (res)) + { + sRef_setAliasKind (res, AK_NEWREF, g_currentloc); + } + else if (sRef_isKillRef (res)) + { + sRef_setAliasKind (res, AK_REFCOUNTED, g_currentloc); + } + else + { + ; + } + + ak = sRef_getAliasKind (res); + + if (alkind_isImplicit (ak)) + { + sRef_setAliasKind (res, alkind_fixImplicit (ak), g_currentloc); + } - } end_specialClauses_postElements ; +# if 0 + DPRINTF (("Aliasing: %s / %s", sRef_unparseFull (res), sRef_unparseFull (tref))); + usymtab_addReallyForceMustAlias (tref, res); /* evans 2001-05-27 */ + /* evans 2002-03-03 - need to be symettric explicitly, since its not a local now */ + usymtab_addReallyForceMustAlias (res, tref); +# endif + + sRefSet_free (prefs); + + DPRINTF (("Returns ref: %s", sRef_unparseFull (res))); + return res; + } +} +# endif + +/*@exposed@*/ sRef uentry_returnedRef (uentry u, exprNodeList args, fileloc loc) +{ + llassert (uentry_isRealFunction (u)); + + if (ctype_isFunction (u->utype) && sRef_isStateSpecial (uentry_getSref (u))) + { + stateClauseList clauses = uentry_getStateClauseList (u); + sRef res = sRef_makeNew (ctype_getReturnType (u->utype), u->sref, u->uname); + + DPRINTF (("Returned: %s", sRef_unparseFull (res))); + sRef_setAllocated (res, loc); + + DPRINTF (("ensures clause: %s / %s", uentry_unparse (u), + stateClauseList_unparse (clauses))); + + /* + ** This should be in exprNode_reflectEnsuresClause + */ + + stateClauseList_postElements (clauses, cl) + { + if (!stateClause_isGlobal (cl)) + { + sRefSet refs = stateClause_getRefs (cl); + sRefMod modf = stateClause_getEffectFunction (cl); + + sRefSet_elements (refs, el) + { + sRef base = sRef_getRootBase (el); + + if (sRef_isResult (base)) + { + if (modf != NULL) + { + sRef sr = sRef_fixBase (el, res); + modf (sr, loc); + } + } + else + { + ; + } + } end_sRefSet_elements ; + } + } end_stateClauseList_postElements ; + return res; } else @@ -9372,24 +11005,33 @@ bool uentry_isReturned (uentry u) exprNode ecur = exprNodeList_nth (args, paramno); sRef tref = exprNode_getSref (ecur); + DPRINTF (("Returned reference: %s", sRef_unparseFull (tref))); + if (sRef_isValid (tref)) { sRef tcref = sRef_copy (tref); + usymtab_addForceMustAlias (tcref, tref); /* evans 2001-05-27 */ + + if (sRef_isNew (tcref)) + { + /* tcref->kind = SK_OBJECT; */ /*!! Not new anymore */ + } + if (sRef_isDead (tcref)) { - sRef_setDefined (tcref, g_currentloc); - sRef_setOnly (tcref, g_currentloc); + sRef_setDefined (tcref, loc); + sRef_setOnly (tcref, loc); } if (sRef_isRefCounted (tcref)) { /* could be a new ref now (but only if its returned) */ - sRef_setAliasKindComplete (tcref, AK_ERROR, g_currentloc); + sRef_setAliasKindComplete (tcref, AK_ERROR, loc); } sRef_makeSafe (tcref); - + DPRINTF (("Returns tcref / %s", sRef_unparseFull (tcref))); prefs = sRefSet_insert (prefs, tcref); } } @@ -9408,19 +11050,21 @@ bool uentry_isReturned (uentry u) } else { + /* should this ever happen? */ /*@i534 evans 2001-05-27 */ res = sRefSet_mergeIntoOne (prefs); } if (nstate_isKnown (n)) { - sRef_setNullState (res, n, g_currentloc); + sRef_setNullState (res, n, loc); } } else { if (ctype_isFunction (u->utype)) { - res = sRef_makeNew (ctype_returnValue (u->utype), u->sref, u->uname); + DPRINTF (("Making new from %s -->", uentry_unparseFull (u))); + res = sRef_makeNew (ctype_getReturnType (u->utype), u->sref, u->uname); } else { @@ -9429,17 +11073,18 @@ bool uentry_isReturned (uentry u) if (sRef_isRefCounted (res)) { - sRef_setAliasKind (res, AK_NEWREF, g_currentloc); + sRef_setAliasKind (res, AK_NEWREF, loc); } } + if (sRef_getNullState (res) == NS_ABSNULL) { ctype ct = ctype_realType (u->utype); if (ctype_isAbstract (ct)) { - sRef_setNotNull (res, g_currentloc); + sRef_setNotNull (res, loc); } else { @@ -9449,18 +11094,18 @@ bool uentry_isReturned (uentry u) } else { - sRef_setNotNull (res, g_currentloc); + sRef_setNotNull (res, loc); } } } if (sRef_isRefCounted (res)) { - sRef_setAliasKind (res, AK_NEWREF, g_currentloc); + sRef_setAliasKind (res, AK_NEWREF, loc); } else if (sRef_isKillRef (res)) { - sRef_setAliasKind (res, AK_REFCOUNTED, g_currentloc); + sRef_setAliasKind (res, AK_REFCOUNTED, loc); } else { @@ -9473,11 +11118,19 @@ bool uentry_isReturned (uentry u) { sRef_setAliasKind (res, alkind_fixImplicit (ak), - g_currentloc); + loc); } sRefSet_free (prefs); - + + /* + if (sRef_isOnly (res)) + { + sRef_setFresh (res, loc); + } + */ + + DPRINTF (("Returns ref: %s", sRef_unparseFull (res))); return res; } } @@ -9488,7 +11141,7 @@ static bool uentry_isRefCounted (uentry ue) if (ctype_isFunction (ct)) { - return (ctype_isRefCounted (ctype_returnValue (ct))); + return (ctype_isRefCounted (ctype_getReturnType (ct))); } else { @@ -9575,6 +11228,58 @@ uentry_ekindName (uentry ue) BADEXIT; } +/*@observer@*/ cstring +uentry_ekindNameLC (uentry ue) +{ + if (uentry_isValid (ue)) + { + switch (ue->ukind) + { + case KINVALID: + return cstring_makeLiteralTemp (""); + case KDATATYPE: + return cstring_makeLiteralTemp ("datatype"); + case KENUMCONST: + return cstring_makeLiteralTemp ("enum member"); + case KCONST: + return cstring_makeLiteralTemp ("constant"); + case KVAR: + if (uentry_isParam (ue)) + { + return cstring_makeLiteralTemp ("parameter"); + } + else if (uentry_isExpandedMacro (ue)) + { + return cstring_makeLiteralTemp ("expanded macro"); + } + else + { + return cstring_makeLiteralTemp ("variable"); + } + case KFCN: + return cstring_makeLiteralTemp ("function"); + case KITER: + return cstring_makeLiteralTemp ("iterator"); + case KENDITER: + return cstring_makeLiteralTemp ("iterator finalizer"); + case KSTRUCTTAG: + return cstring_makeLiteralTemp ("struct tag"); + case KUNIONTAG: + return cstring_makeLiteralTemp ("union tag"); + case KENUMTAG: + return cstring_makeLiteralTemp ("enum tag"); + case KELIPSMARKER: + return cstring_makeLiteralTemp ("optional parameters"); + } + } + else + { + return cstring_makeLiteralTemp (""); + } + + BADEXIT; +} + void uentry_setHasNameError (uentry ue) { llassert (uentry_isValid (ue)); @@ -9584,15 +11289,22 @@ void uentry_setHasNameError (uentry ue) void uentry_checkName (uentry ue) { + DPRINTF (("Checking name: %s / %s / %s", uentry_unparse (ue), + uentry_observeRealName (ue), + bool_unparse (uentry_isVisibleExternally (ue)))); + if (uentry_isValid (ue) + && !context_inXHFile () + && uentry_hasName (ue) && !uentry_isElipsisMarker (ue) && context_getFlag (FLG_NAMECHECKS) && !ue->hasNameError && !uentry_isEndIter (ue) && !fileloc_isBuiltin (uentry_whereLast (ue)) && (uentry_isExpandedMacro (ue) || !uentry_isForward (ue))) - { - + { + DPRINTF (("Here...")); + if (uentry_isPriv (ue)) { ; /* any checks here? */ @@ -9642,63 +11354,40 @@ void uentry_checkName (uentry ue) usymtab_checkDistinctName (ue, scope); } - + if (context_getFlag (FLG_CPPNAMES)) { - if (checkCppName (uentry_rawName (ue), uentry_whereLast (ue))) - { - uentry_setHasNameError (ue); - } + checkCppName (ue); } if (scope == globScope) { - checkGlobalName (ue); - - if (context_getFlag (FLG_ANSIRESERVED)) - { - if (uentry_hasName (ue) - && !uentry_isAnyTag (ue)) - { - if (checkAnsiName (uentry_rawName (ue), - uentry_whereLast (ue))) - { - uentry_setHasNameError (ue); - } - } - } + checkExternalName (ue); } - else + else if (scope == fileScope) + { + checkFileScopeName (ue); + } + else { checkLocalName (ue); - - if (context_getFlag (FLG_ANSIRESERVEDLOCAL)) - { - if (uentry_hasName (ue) - && !uentry_isAnyTag (ue)) - { - if (checkAnsiName (uentry_rawName (ue), - uentry_whereLast (ue))) - { - uentry_setHasNameError (ue); - } - } - } } - DPRINTF (("Check prefix: %s", uentry_unparse (ue))); checkPrefix (ue); + checkAnsiName (ue); } } } -/*@exposed@*/ uentry uentry_makeUnrecognized (cstring c, /*@keep@*/ fileloc loc) +/*@exposed@*/ uentry uentry_makeUnrecognized (cstring c, /*@only@*/ fileloc loc) { uentry ue; fileloc tloc; /* - ** Can't but unrecognized ids in macros in global scope, because srefs will break! */ + ** Can't but unrecognized ids in macros in global scope, because srefs will break! + */ + if (!context_inMacro ()) { sRef_setGlobalScopeSafe (); @@ -9712,7 +11401,7 @@ void uentry_checkName (uentry ue) fileloc_free (tloc); uentry_setHasNameError (ue); - if (context_getFlag (FLG_REPEATUNRECOG)) + if (context_getFlag (FLG_REPEATUNRECOG) || (context_inOldStyleScope())) { uentry_markOwned (ue); } @@ -9729,52 +11418,36 @@ void uentry_checkName (uentry ue) return ue; } -/* new start modifications */ +uentry uentry_makeGlobalMarker () +{ + uentry ue; + fileloc tloc; -void uentry_testInRange (uentry p_e, uentry cconstant) { - if( uentry_isValid(p_e) ) { - if( sRef_isValid (p_e->sref) ) { - char * t = cstring_toCharsSafe (uentry_unparse(cconstant) ); - int index = atoi( t ); - free (t); - usymtab_testInRange (p_e->sref, index); - }//end if - }//endif -} - -void uentry_setStringLength (uentry p_e, uentry cconstant) { -if( uentry_isValid(p_e) ) { - if( p_e->info != NULL) { - if( p_e->info->var != NULL) { - char *t = cstring_toCharsSafe (uentry_unparse(cconstant)); - int length = atoi( t ); - free (t); - p_e->info->var->bufinfo->len = length; - p_e->sref->bufinfo.len = length; - printf("Set string length of buff to %d \n", p_e->sref->bufinfo.size); - }//end if - }//endif -}//end if -} - - -void uentry_setBufferSize (uentry p_e, exprNode cconstant) { -if( uentry_isValid(p_e) ) { - if( p_e->info != NULL) { - if( p_e->info->var != NULL) { - int size = atoi(cstring_toCharsSafe(exprNode_unparse(cconstant) ) ); - p_e->info->var->bufinfo->size = size; - p_e->sref->bufinfo.size = size; - printf("Set buffer size to %d \n", p_e->sref->bufinfo.size); - // fprintf(stderr, "For %s and %s\n", uentry_unparse(p_e) ); - // fprintf(stderr, "and %d\n", size ); - - }//end if - }//endif -}//end if + llassert (sRef_inGlobalScope ()); + + ue = uentry_makeVariableAux + (GLOBAL_MARKER_NAME, ctype_unknown, fileloc_undefined, + sRef_makeGlobalMarker (), + FALSE, VKNORMAL); + + tloc = fileloc_createExternal (); + uentry_setUsed (ue, tloc); + uentry_setDefined (ue, tloc); + fileloc_free (tloc); + uentry_setHasNameError (ue); + + return ue; } - + +bool uentry_isGlobalMarker (uentry ue) +{ + return (uentry_isValid (ue) + && (cstring_equal (uentry_rawName (ue), GLOBAL_MARKER_NAME))); +} + +/* new start modifications */ + /* start modifications */ /* requires: p_e is defined, is a ptr/array variable @@ -9782,18 +11455,20 @@ modifies: p_e effects: sets the state of the variable */ -void uentry_setPossiblyNullTerminatedState (uentry p_e) { - if( uentry_isValid(p_e) ) { - if( p_e->info != NULL) { - if( p_e->info->var != NULL) { - p_e->info->var->bufinfo->bufstate = BB_POSSIBLYNULLTERMINATED; - p_e->sref->bufinfo.bufstate = BB_POSSIBLYNULLTERMINATED; - return; - }/* End if */ - }/* End if */ - }/* End if */ - fprintf(stderr, "uentry:Error in setPossiblyNullTerminatedState\n"); +void uentry_setPossiblyNullTerminatedState (uentry p_e) +{ + llassert (uentry_isValid (p_e)); + + if (p_e->info != NULL) + { + if (p_e->info->var != NULL) + { + llassert (p_e->info->var->bufinfo != NULL); + p_e->info->var->bufinfo->bufstate = BB_POSSIBLYNULLTERMINATED; + sRef_setPossiblyNullTerminatedState (p_e->sref); + } + } } /* @@ -9803,80 +11478,93 @@ effects: sets the size of the buffer */ void uentry_setNullTerminatedState (uentry p_e) { - if( uentry_isValid(p_e) ) { - if( p_e->info != NULL) { - if( p_e->info->var != NULL) { - p_e->info->var->bufinfo->bufstate = BB_NULLTERMINATED; - p_e->sref->bufinfo.bufstate = BB_NULLTERMINATED; - return; - }//End if - }//End if - }//End if + llassert (uentry_isValid (p_e)); - fprintf(stderr, "uentry:Error in setNullTerminatedState\n"); + if (p_e->info != NULL) + { + if (p_e->info->var != NULL) + { + llassert (p_e->info->var->bufinfo != NULL); + p_e->info->var->bufinfo->bufstate = BB_NULLTERMINATED; + sRef_setNullTerminatedState (p_e->sref); + } + } } - /* requires: p_e is defined, is a ptr/array variable modifies: p_e -effects: sets the state of the variable +effects: sets the size of the buffer */ -void uentry_setNotNullTerminatedState (uentry p_e) { - if( uentry_isValid(p_e) ) { - if( p_e->info != NULL) { - if( p_e->info->var != NULL) { - p_e->info->var->bufinfo->bufstate = BB_NOTNULLTERMINATED; - p_e->sref->bufinfo.bufstate = BB_NOTNULLTERMINATED; - return; - }//End if - }//End if - }//End if - - fprintf(stderr, "uentry:Error in setNotNullTerminatedState\n"); +void uentry_setSize (uentry p_e, int size) +{ + if (uentry_isValid (p_e)) + { + if (p_e->info != NULL) + { + if (p_e->info->var != NULL) + { + llassert (p_e->info->var->bufinfo != NULL); + p_e->info->var->bufinfo->size = size; + sRef_setSize (p_e->sref, size); + } + } + } } - /* requires: p_e is defined, is a ptr/array variable modifies: p_e -effects: sets the size of the buffer +effects: sets the length of the buffer */ -void uentry_setSize (uentry p_e, int size) { - if( uentry_isValid(p_e) ) { - if( p_e->info != NULL) { - if( p_e->info->var != NULL) { - p_e->info->var->bufinfo->size = size; - p_e->sref->bufinfo.size = size; - return; - }//End if - }//End if - }//End if +void uentry_setLen (uentry p_e, int len) +{ + if (uentry_isValid (p_e)) + { + if (p_e->info != NULL + && p_e->info->var != NULL) + { + llassert (p_e->info->var->bufinfo != NULL); + p_e->info->var->bufinfo->len = len; + sRef_setLen (p_e->sref, len); + } + } +} + +/*@=type*/ - fprintf(stderr, "uentry:Error in setSize\n"); +bool uentry_hasMetaStateEnsures (uentry e) +{ + if (uentry_isValid (e) && uentry_isFunction (e)) + { + return functionConstraint_hasMetaStateConstraint (e->info->fcn->postconditions); + } + else + { + return FALSE; + } +} + +metaStateConstraintList uentry_getMetaStateEnsures (uentry e) +{ + llassert (uentry_isValid (e) && uentry_isFunction (e)); + return functionConstraint_getMetaStateConstraints (e->info->fcn->postconditions); } +# ifdef DEBUGSPLINT /* -requires: p_e is defined, is a ptr/array variable -modifies: p_e -effects: sets the length of the buffer +** For debugging only */ -void uentry_setLen (uentry p_e, int len) { - if( uentry_isValid(p_e) ) { - if( p_e->info != NULL) { - if( p_e->info->var != NULL) { - p_e->info->var->bufinfo->len = len; - p_e->sref->bufinfo.len = len; - return; - }//End if - }//End if - }//End if - - fprintf(stderr, "uentry:Error in setLen\n"); +void uentry_checkValid (uentry ue) +{ + if (uentry_isValid (ue)) + { + sRef_checkCompletelyReasonable (ue->sref); + } } -/*@=type*/ +# endif