X-Git-Url: http://andersk.mit.edu/gitweb/splint.git/blobdiff_plain/f5ac53de936db2ac22f6878d5516e00c222a395f..HEAD:/src/uentry.c diff --git a/src/uentry.c b/src/uentry.c index 85d5d47..6f6c090 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; 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,45 +569,71 @@ 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)) { - { - if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue))) - { - uentry_makeVarFunction (ue); - } - - //llassert (uentry_isFunction (ue)); - //llassert ((ue->info->fcn->preconditions)); + functionConstraint constraint; - if (!uentry_isFunction (ue)) + DPRINTF((message ("called uentry_getFcnPostconditions on %s", + uentry_unparse (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) ) { - BPRINTF ( (message ("called uentry_getFcnPreconditions on nonfunction %s", - uentry_unparse (ue) ) ) ); + DPRINTF((message ("called uentry_getFunctionConditions 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; + + } - if (ue->info->fcn->preconditions) - { - return constraintList_copy (ue->info->fcn->preconditions); - } - else - { - return NULL; - } + llassert (uentry_isFunction (ue)); + + 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) +{ + return uentry_getFunctionConditions (ue, TRUE); +} static /*@only@*/ fileloc setLocation (void) { @@ -612,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 (); @@ -642,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); @@ -650,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)) { @@ -696,15 +741,22 @@ 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; if (ctype_isFixedArray (ct)) { + DPRINTF (("Array: %s / %s", + ctype_unparse (ct), + ctype_unparse (ctype_baseArrayPtr (ct)))); + if (ctype_isArray (ctype_baseArrayPtr (ct)) && !ctype_isFixedArray (ctype_baseArrayPtr (ct))) { @@ -712,24 +764,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)); + } } } @@ -803,24 +879,39 @@ 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)) + || ctype_isNumAbstract (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)))); + } + } } } } @@ -832,16 +923,19 @@ 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)); + if (ctype_isFunction (t)) { - ret = ctype_returnValue (t); + ret = ctype_getReturnType (t); } else { @@ -870,7 +964,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)) { @@ -883,6 +979,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)); @@ -890,7 +988,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; @@ -907,22 +1005,208 @@ uentry_makeFunctionAux (cstring n, ctype t, e->info->fcn->preconditions = NULL; /*end drl*/ + /*drl 12 28 2000*/ + e->info->fcn->postconditions = NULL; + /*end drl*/ + checkGlobalsModifies (e, mods); e->info->fcn->mods = mods; 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)); + } + 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")) @@ -933,7 +1217,7 @@ uentry_makeFunctionAux (cstring n, ctype t, llassert (ctype_isFunction (typ)); - retval = ctype_returnValue (typ); + retval = ctype_getReturnType (typ); if (!ctype_isInt (retval)) { @@ -957,7 +1241,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)); @@ -999,6 +1283,11 @@ uentry_makeFunctionAux (cstring n, ctype t, } } + if (leaveFunc) + { + context_exitFunctionDeclaration (); + } + return ue; } @@ -1013,6 +1302,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); } @@ -1025,24 +1315,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) { 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) { @@ -1052,7 +1349,6 @@ uentry_setRefCounted (uentry e) sRef_storeState (e->sref); } } -# endif void uentry_setStatic (uentry c) @@ -1123,7 +1419,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)) @@ -1156,9 +1452,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 @@ -1181,18 +1477,33 @@ uentry_fixupSref (uentry ue) if (uentry_isVariable (ue)) { + /* removed this: no need to copy? 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. + */ + + 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))); } /* @@ -1209,22 +1520,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)) @@ -1236,11 +1555,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)); @@ -1254,6 +1569,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 { @@ -1261,8 +1581,60 @@ uentry_setModifies (uentry ue, /*@owned@*/ sRefSet sr) } } +static void +uentry_combineModifies (uentry ue, /*@owned@*/ sRefSet sr) +{ + /* + ** Function already has one modifies clause (possibly from + ** a specification). + */ + + 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, /*@owned@*/ constraintList preconditions) +uentry_setPreconditions (uentry ue, /*@only@*/ functionConstraint preconditions) { if (sRef_modInFunction ()) { @@ -1276,22 +1648,73 @@ uentry_setPreconditions (uentry ue, /*@owned@*/ constraintList preconditions) if (uentry_isValid (ue)) { - { - if (uentry_isVariable (ue) && ctype_isFunction (uentry_getType (ue))) - { - uentry_makeVarFunction (ue); - } - - llassertfatal (uentry_isFunction (ue)); - // llassert (sRefSet_isUndefined (ue->info->fcn->mods)); - + 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 + { ue->info->fcn->preconditions = preconditions; } - } else { - // + llfatalbug ((message("uentry_setPreconditions called with invalid uentry") )); + } +} + +/* + drl + added 12/28/2000 +*/ +void +uentry_setPostconditions (uentry ue, /*@only@*/ functionConstraint postconditions) +{ + if (sRef_modInFunction ()) + { + llparseerror + (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)) + { + 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") )); } } @@ -1457,8 +1880,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); } } @@ -1619,6 +2042,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)", @@ -1705,12 +2130,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 { @@ -1737,13 +2163,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; @@ -1764,11 +2191,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 { @@ -1787,11 +2215,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)); } } } @@ -1803,10 +2232,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)) @@ -1825,16 +2255,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) @@ -1843,10 +2275,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; @@ -1861,12 +2294,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; @@ -1876,10 +2310,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; } @@ -1914,26 +2349,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 { @@ -1949,8 +2390,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 { @@ -1959,15 +2402,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)) { @@ -1979,27 +2419,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)) @@ -2010,11 +2453,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; @@ -2028,10 +2472,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))) + { + /* annotationInfo_showContextError (ainfo, ue); */ } } } @@ -2043,7 +2515,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))); } } } @@ -2053,6 +2525,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)) @@ -2062,6 +2537,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)) { @@ -2078,11 +2554,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) { @@ -2095,10 +2572,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)) @@ -2107,6 +2585,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; @@ -2128,21 +2609,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)) { @@ -2191,6 +2672,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. */ { @@ -2199,7 +2681,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)) @@ -2213,10 +2695,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)); } } @@ -2236,10 +2719,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)) @@ -2247,9 +2731,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)) @@ -2258,10 +2745,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 @@ -2269,11 +2765,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); } } @@ -2351,6 +2849,8 @@ uentry_reflectQualifiers (uentry ue, qualList q) } end_qualList_elements; qualList_clear (q); + + DPRINTF (("Done: %s", sRef_unparseFull (ue->sref))); } bool @@ -2417,14 +2917,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 @@ -2524,11 +3038,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); @@ -2537,11 +3047,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); @@ -2550,11 +3056,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); @@ -2570,39 +3072,49 @@ uentry_isSpecialFunction (uentry ue) /*@notnull@*/ uentry uentry_makeParam (idDecl t, int i) { 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))); + DPRINTF (("Base: %s [%d]", ctype_unparse (ct), ctype_isFixedArray (ct))); uentry_reflectQualifiers (ue, idDecl_getQuals (t)); uentry_implicitParamAnnots (ue); - /* Parameter type [][] or [x][] is invalid */ + if (ctype_isArray (ct)) + { + /* Parameter type [][] or [x][] is invalid, but [][x] is okay */ + ctype base = ctype_baseArrayPtr (ct); - while (ctype_isFixedArray (base)) { - base = ctype_baseArrayPtr (base); - } - - if (ctype_isIncompleteArray (base)) { - base = ctype_baseArrayPtr (base); - - if (ctype_isArray (base)) { - if (!uentry_hasName (ue)) { - (void) optgenerror (FLG_INCOMPLETETYPE, - message ("Unnamed function parameter %d is incomplete type (inner array must have bounds): %s", - i + 1, - ctype_unparse (ct)), - uentry_whereLast (ue)); - } else { - (void) optgenerror (FLG_INCOMPLETETYPE, - message ("Function parameter %q is incomplete type (inner array must have bounds): %s", - uentry_getName (ue), - ctype_unparse (ct)), - uentry_whereLast (ue)); - } + DPRINTF (("Check array: %s / Base: %s", ctype_unparse (ct), + ctype_unparse (base))); + + if (ctype_isIncompleteArray (base)) + { + if (!uentry_hasName (ue)) + { + voptgenerror + (FLG_INCOMPLETETYPE, + message ("Unnamed function parameter %d is incomplete type " + "(inner array must have bounds): %s", + i + 1, + ctype_unparse (ct)), + uentry_whereLast (ue)); + } + else + { + voptgenerror + (FLG_INCOMPLETETYPE, + message ("Function parameter %q is incomplete type " + "(inner array must have bounds): %s", + uentry_getName (ue), + ctype_unparse (ct)), + uentry_whereLast (ue)); + } + } } - } - + + DPRINTF (("Param: %s", uentry_unparseFull (ue))); return ue; } @@ -2618,7 +3130,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)) @@ -2630,20 +3142,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 (); @@ -2653,6 +3163,8 @@ uentry uentry_makeConstantAux (cstring n, ctype t, e->utype = t; e->storageclass = SCNONE; + e->warn = warnClause_undefined; /* Don't support warnings for constants */ + e->sref = sRef_makeConst (t); e->lset = FALSE; @@ -2664,8 +3176,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); @@ -2674,12 +3186,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) @@ -2690,9 +3217,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; } @@ -2780,14 +3308,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; @@ -2796,6 +3324,8 @@ static /*@only@*/ /*@notnull@*/ e->storageclass = SCNONE; + e->warn = warnClause_undefined; /* Don't support warnings for variables yet @*/ + e->sref = s; e->used = FALSE; @@ -2809,36 +3339,45 @@ static /*@only@*/ /*@notnull@*/ e->info->var = (uvinfo) dmalloc (sizeof (*e->info->var)); e->info->var->kind = kind; + /* removed: 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); } 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)) + { + 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 */ + + DPRINTF (("New variable: %s", sRef_unparseFull (e->sref))); return (e); } @@ -2881,20 +3420,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; @@ -2905,12 +3446,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 = 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 { @@ -2927,6 +3472,7 @@ void uentry_makeVarFunction (uentry ue) { if (exkind_isKnown (ek)) { + DPRINTF (("imp dep: %s", uentry_unparseFull (ue))); ak = AK_IMPDEPENDENT; } else @@ -2935,7 +3481,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))) { @@ -2943,8 +3489,15 @@ void uentry_makeVarFunction (uentry ue) } else { - ak = AK_IMPONLY; - } + if (ctype_isImmutableAbstract (ctype_getReturnType (ue->utype))) + { + ; + } + else + { + ak = AK_IMPONLY; + } + } } } } @@ -2960,8 +3513,7 @@ void uentry_makeVarFunction (uentry ue) if (oldInfo->kind == VKEXPMACRO) { - fileloc_free (loc); - ue->whereDeclared = fileloc_undefined; + ; } else { @@ -2972,60 +3524,154 @@ 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)) + /* + ** 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->fcn->access = typeIdSet_insert (ue->info->fcn->access, tid); + ue->sref = sRef_makeType (ctype_getReturnType (ue->utype)); } - else if (uentry_isEitherConstant (ue)) + else { - ue->info->uconst->access = typeIdSet_insert (ue->info->uconst->access, tid); + ue->sref = sRef_makeType (ctype_unknown); } - else if (uentry_isIter (ue)) + + if (sRef_isRefCounted (ue->sref)) { - ue->info->iter->access = typeIdSet_insert (ue->info->iter->access, tid); + ak = AK_NEWREF; } - else if (uentry_isEndIter (ue)) + else { - ue->info->enditer->access = typeIdSet_insert (ue->info->enditer->access, tid); + 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 { @@ -3037,23 +3683,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)); 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)); } @@ -3065,8 +3714,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); @@ -3074,7 +3723,6 @@ void uentry_addAccessType (uentry ue, typeId tid) reflectImplicitFunctionQualifiers (ue, TRUE); return (ue); } -# endif uentry uentry_makeExpandedMacro (cstring s, fileloc f) { @@ -3091,6 +3739,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); @@ -3106,20 +3755,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 @@ -3127,13 +3774,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 @@ -3142,7 +3789,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 (); @@ -3164,6 +3811,7 @@ uentry_makeUnspecFunction (cstring n, ctype t, uentry_setSpecDef (e, f); + e->warn = warnClause_undefined; e->uses = filelocList_new (); e->isPrivate = priv; e->hasNameError = FALSE; @@ -3173,7 +3821,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; @@ -3182,7 +3830,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)); } @@ -3191,16 +3839,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); @@ -3228,6 +3875,7 @@ static /*@only@*/ /*@notnull@*/ uentry uentry_setSpecDef (e, f); + e->warn = warnClause_undefined; e->uses = filelocList_new (); e->isPrivate = FALSE; e->hasNameError = FALSE; @@ -3272,6 +3920,7 @@ uentry_makeEndIterAux (cstring n, typeIdSet access, /*@only@*/ fileloc f) e->info->enditer = (ueinfo) dmalloc (sizeof (*e->info->enditer)); e->info->enditer->access = access; + e->warn = warnClause_undefined; return (e); } @@ -3316,9 +3965,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; if (uentry_isDeclared (e)) { @@ -3357,7 +4007,6 @@ uentry_makeUnionTag (cstring n, ctype t, fileloc loc) return (ret); } -# ifndef NOLCL uentry uentry_makeEnumTag (cstring n, ctype t, fileloc loc) { @@ -3367,7 +4016,6 @@ uentry_makeEnumTag (cstring n, ctype t, fileloc loc) cstring_free (ename); return ret; } -# endif uentry uentry_makeUnionTagLoc (cstring n, ctype t) @@ -3546,21 +4194,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: @@ -3574,19 +4221,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))); @@ -3603,7 +4251,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; @@ -3620,13 +4268,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 @@ -3674,11 +4322,13 @@ static uentry e->used = FALSE; e->lset = FALSE; + e->warn = warnClause_undefined; + 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; /* fix this when macro info added to library */ + uentry_setConstantValue (e, m); sRef_storeState (e->sref); return (e); @@ -3720,6 +4370,7 @@ static /*@only@*/ uentry e->lset = FALSE; e->uses = filelocList_new (); + e->warn = warnClause_undefined; e->info = (uinfo) dmalloc (sizeof (*e->info)); e->info->var = (uvinfo) dmalloc (sizeof (*e->info->var)); @@ -3743,7 +4394,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) @@ -3756,6 +4407,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?) @@ -3780,11 +4432,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) >*/ @@ -3802,23 +4455,24 @@ uentry_makeDatatypeBase (/*@only@*/ cstring name, ctype ct, ynm abs, e->isPrivate = FALSE; e->hasNameError = FALSE; - + e->warn = warnClause_undefined; 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)); @@ -3832,7 +4486,6 @@ static void uentry_setHasMods (uentry ue) ue->info->fcn->hasMods = TRUE; } -# endif bool uentry_hasGlobs (uentry ue) { @@ -3844,14 +4497,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; } @@ -3875,7 +4541,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 (); @@ -3889,7 +4556,7 @@ static uentry if (ctype_isFunction (ct)) { - ret = ctype_returnValue (ct); + ret = ctype_getReturnType (ct); } else { @@ -3924,6 +4591,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)); @@ -3948,6 +4616,10 @@ static uentry /*drl 111 30 2000*/ e->info->fcn->preconditions = NULL; /* end drl */ + + /*drl 12 28 2000*/ + e->info->fcn->postconditions = NULL; + /* end drl */ return (e); } @@ -3989,10 +4661,11 @@ static /*@only@*/ uentry e->used = FALSE; e->lset = FALSE; e->uses = filelocList_new (); + e->warn = warnClause_undefined; 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; @@ -4033,6 +4706,7 @@ static uentry e->used = FALSE; e->lset = FALSE; e->uses = filelocList_new (); + e->warn = warnClause_undefined; e->info = (uinfo) dmalloc (sizeof (*e->info)); e->info->iter = (uiinfo) dmalloc (sizeof (*e->info->iter)); @@ -4076,6 +4750,7 @@ static uentry e->used = FALSE; e->lset = FALSE; e->uses = filelocList_new (); + e->warn = warnClause_undefined; e->info = (uinfo) dmalloc (sizeof (*e->info)); e->info->enditer = (ueinfo) dmalloc (sizeof (*e->info->enditer)); @@ -4097,10 +4772,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 @@ -4119,19 +4796,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; @@ -4139,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_DEFINED; isnull = NS_UNKNOWN; @@ -4147,7 +4824,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; @@ -4157,25 +4834,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)); @@ -4183,7 +4862,7 @@ uentry_undump (ekind kind, fileloc loc, char **s) break; case KDATATYPE: { - ynm abs; + qual abstract; ynm mut; ctype rtype; sstate defstate; @@ -4191,17 +4870,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)); } @@ -4220,33 +4899,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; @@ -4255,35 +4935,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, @@ -4291,6 +4984,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))); } @@ -4300,7 +4994,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)); @@ -4311,7 +5005,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)); } @@ -4323,7 +5017,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; @@ -4333,10 +5027,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); @@ -4349,7 +5043,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; @@ -4386,9 +5080,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: @@ -4443,7 +5139,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, @@ -4469,9 +5165,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), @@ -4481,7 +5184,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); @@ -4489,18 +5192,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)) @@ -4530,27 +5233,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", @@ -4567,7 +5269,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)) { @@ -4576,7 +5278,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)); } @@ -4637,75 +5339,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; } } @@ -4800,10 +5500,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); } @@ -4811,32 +5511,42 @@ 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 uentry_isMutableDatatype (uentry e) { - bool res = uentry_isDatatype (e) - && (ynm_toBoolRelaxed (e->info->datatype->mut)); - - return res; + if (uentry_isDatatype (e)) + { + if (ctype_isNumAbstract (e->info->datatype->type)) + { + return FALSE; + } + else + { + return ynm_toBoolRelaxed (e->info->datatype->mut); + } + } + + return FALSE; } bool @@ -4936,8 +5646,7 @@ exitkind uentry_getExitCode (uentry ue) } } -qual -uentry_nullPred (uentry u) +qual uentry_nullPred (uentry u) { llassert (uentry_isRealFunction (u)); @@ -4947,10 +5656,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) { @@ -5010,7 +5723,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 { @@ -5018,9 +5732,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)); } @@ -5032,29 +5753,42 @@ 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; } +# ifdef WIN32 +/* Make Microsoft VC++ happy */ +# pragma warning (disable : 4715) +# endif + /*@observer@*/ sRefSet uentry_getMods (uentry l) { @@ -5066,22 +5800,35 @@ 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; + } } ekind uentry_getKind (uentry e) { llassert (uentry_isValid (e)); - return (e->ukind); } /*@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 @@ -5109,7 +5856,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; @@ -5150,10 +5903,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)) { @@ -5168,6 +5920,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)) @@ -5436,7 +6218,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 @@ -5462,6 +6246,29 @@ sRef uentry_getSref (uentry e) sRef uentry_getOrigSref (uentry e) { + /* evans 2003-04-12 - removed for now */ + /* 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)); @@ -5514,18 +6321,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); @@ -5534,7 +6337,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))); @@ -5645,15 +6447,19 @@ uentry_getAbstractType (uentry e) ctype uentry_getRealType (uentry e) { ctype ct; - typeId uid = USYMIDINVALID; + typeId uid = typeId_invalid; if (uentry_isInvalid (e)) { return ctype_unknown; } + + if (!uentry_isDatatype (e)) + { + /* This shouldn't happen, except when types are redeclared in strange ways */ + return ctype_unknown; + } - llassertprint (uentry_isDatatype (e), ("not datatype: %s", uentry_unparse (e))); - if (uentry_isAnyTag (e)) { return (e->utype); @@ -5687,9 +6493,9 @@ ctype uentry_getRealType (uentry e) if (ctype_isUA (ct)) { - usymId iid = ctype_typeId (ct); + typeId iid = ctype_typeId (ct); - if /*@access usymId@*/ (iid == uid) /*@noaccess usymId@*/ + if (typeId_equal (iid, uid)) { llcontbug (message ("uentry_getRealType: recursive type! %s", ctype_unparse (ct))); @@ -5699,7 +6505,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); } @@ -5713,7 +6524,7 @@ ctype uentry_getRealType (uentry e) ctype uentry_getForceRealType (uentry e) { ctype ct; - typeId uid = USYMIDINVALID; + typeId uid = typeId_invalid; if (uentry_isInvalid (e)) { @@ -5747,9 +6558,9 @@ ctype uentry_getForceRealType (uentry e) if (ctype_isUA (ct)) { - usymId iid = ctype_typeId (ct); + typeId iid = ctype_typeId (ct); - if /*@access usymId@*/ (iid == uid) /*@noaccess usymId@*/ + if (typeId_equal (iid, uid)) { llcontbug (message ("uentry_getRealType: recursive type! %s", ctype_unparse (ct))); @@ -5786,6 +6597,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); @@ -5794,13 +6606,21 @@ uentry uentry_nameCopy (cstring name, uentry e) } void -uentry_setDatatype (uentry e, usymId uid) +uentry_setDatatype (uentry e, typeId uid) { llassert (uentry_isDatatype (e)); 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 { @@ -5827,18 +6647,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); } @@ -5853,8 +6676,7 @@ ufinfo_free (/*@only@*/ ufinfo u) { globSet_free (u->globs); sRefSet_free (u->mods); - specialClauses_free (u->specclauses); - + stateClauseList_free (u->specclauses); sfree (u); } @@ -5874,10 +6696,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; } @@ -5890,9 +6710,25 @@ 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; + + + /* 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 @@ -5921,11 +6757,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); + ret->specclauses = stateClauseList_copy (u->specclauses); - /*drl 11 30 2000 */ - ret->preconditions = u->preconditions? constraintList_copy(u->preconditions): NULL; - /* end drl */ + ret->preconditions = functionConstraint_copy (u->preconditions); + ret->postconditions = functionConstraint_copy (u->postconditions); return ret; } @@ -6014,9 +6849,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) { @@ -6041,6 +6878,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); @@ -6057,7 +6895,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)) @@ -6085,9 +6923,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 @@ -6104,9 +6942,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); } } } @@ -6114,21 +6952,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); } /* @@ -6146,7 +6987,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), @@ -6182,6 +7023,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) { @@ -6478,9 +7367,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))) { @@ -6555,6 +7445,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) @@ -6581,7 +7475,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)), @@ -6601,10 +7495,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))); } } @@ -6701,7 +7595,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)) { @@ -6803,7 +7697,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) { @@ -6826,7 +7722,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)); } @@ -6848,7 +7744,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)); } @@ -6914,6 +7810,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)); } @@ -7040,6 +7938,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, @@ -7049,6 +8059,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); @@ -7308,6 +8319,29 @@ void uentry_checkMatchParam (uentry u1, uentry u2, int paramno, exprNode e) } } +static void uentry_convertIntoFunction (/*@notnull@*/ uentry old) +{ + /* + ** Convert old into a function + */ + + old->ukind = KFCN; + old->utype = ctype_unknown; + old->info->fcn = (ufinfo) dmalloc (sizeof (*old->info->fcn)); + old->info->fcn->hasMods = FALSE; + old->info->fcn->hasGlobs = FALSE; + old->info->fcn->exitCode = XK_UNKNOWN; + old->info->fcn->nullPred = qual_createUnknown (); + old->info->fcn->specialCode = SPC_NONE; + old->info->fcn->access = typeIdSet_undefined; + old->info->fcn->globs = globSet_undefined; + old->info->fcn->defparams = uentryList_undefined; + old->info->fcn->mods = sRefSet_undefined; + old->info->fcn->specclauses = NULL; + old->info->fcn->preconditions = NULL; + old->info->fcn->postconditions = NULL; +} + static void checkFunctionConformance (/*@unique@*/ /*@notnull@*/ uentry old, /*@notnull@*/ uentry unew, @@ -7316,14 +8350,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; } @@ -7333,16 +8371,32 @@ checkFunctionConformance (/*@unique@*/ /*@notnull@*/ uentry old, if (ctype_isKnown (oldType)) { - llassert (ctype_isFunction (oldType)); + if (ctype_isFunction (oldType)) + { + oldRetType = ctype_getReturnType (oldType); + } + else + { + if (optgenerror + (FLG_INCONDEFS, + message ("%s %q declared as function, but previously declared as %s", + ekind_capName (unew->ukind), + uentry_getName (unew), + ekind_unparseLong (old->ukind)), + uentry_whereDeclared (unew))) + { + uentry_showWhereLast (old); + } - oldRetType = ctype_returnValue (oldType); + uentry_convertIntoFunction (old); + return; + } } if (ctype_isKnown (newType)) { llassert (ctype_isFunction (newType)); - - newRetType = ctype_returnValue (newType); + newRetType = ctype_getReturnType (newType); } if (ctype_isKnown (oldRetType) && ctype_isKnown (newRetType) @@ -7380,7 +8434,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)) { @@ -7405,7 +8463,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, @@ -7497,7 +8555,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)); } @@ -7507,7 +8565,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)); } @@ -7602,7 +8660,7 @@ checkFunctionConformance (/*@unique@*/ /*@notnull@*/ uentry old, paramno++; /* - ** Forgot this! detected by lclint: + ** Forgot this! detected by splint: ** uentry.c:1257,15: Suspected infinite loop */ } @@ -7625,10 +8683,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 " @@ -7638,12 +8700,22 @@ checkFunctionConformance (/*@unique@*/ /*@notnull@*/ uentry old, { uentry_showWhereLast (old); } + */ + + /* need to add some checking @*/ + old->info->fcn->specclauses = unew->info->fcn->specclauses; } else { - specialClauses_checkEqual (old, unew); + /* should be able to append? */ + + stateClauseList_checkEqual (old, unew); + stateClauseList_free (unew->info->fcn->specclauses); + unew->info->fcn->specclauses = stateClauseList_undefined; + /*@-branchstate@*/ } } + /*@=branchstate@*/ /* shouldn't need this */ if (fileloc_isUndefined (old->whereDeclared)) { @@ -7657,7 +8729,8 @@ checkFunctionConformance (/*@unique@*/ /*@notnull@*/ uentry old, { /* no change */ } -} + /*@-compmempass@*/ +} /*@=compmempass@*/ /* I think this is a spurious warning */ void uentry_mergeConstantValue (uentry ue, /*@only@*/ multiVal m) @@ -7667,7 +8740,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)) { @@ -7691,8 +8765,7 @@ uentry_mergeConstantValue (uentry ue, /*@only@*/ multiVal m) } else { - ue->info->uconst->val = m; - multiVal_free (uval); + uentry_setConstantValue (ue, m); } } @@ -7708,6 +8781,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); } } @@ -7737,6 +8813,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); @@ -7867,10 +8947,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)) { @@ -7886,8 +8966,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)) { @@ -7910,7 +8990,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; @@ -7959,7 +9039,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)) { @@ -8002,14 +9082,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 @@ -8018,15 +9098,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 { @@ -8035,7 +9114,7 @@ uentry_checkConstantConformance (/*@notnull@*/ uentry old, } else { - old->info->uconst->val = multiVal_copy (newVal); + uentry_setConstantValue (old, multiVal_copy (newval)); } } @@ -8069,14 +9148,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; } @@ -8103,7 +9182,7 @@ uentry_checkConformance (/*@unique@*/ /*@notnull@*/ uentry old, } } - uentry_copyInto (old, unew); + uentry_updateInto (old, unew); return; } else @@ -8140,7 +9219,7 @@ uentry_checkConformance (/*@unique@*/ /*@notnull@*/ uentry old, old->whereDefined); } - uentry_copyInto (old, unew); + uentry_updateInto (old, unew); old->used = unew->used = TRUE; return; } @@ -8307,6 +9386,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 */ @@ -8318,9 +9475,33 @@ 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)))); */ /* @@ -8381,7 +9562,7 @@ uentry_clearDecl (void) void uentry_checkDecl (void) { - if (uentry_isValid (posRedeclared)) + if (uentry_isValid (posRedeclared) && !fileloc_isXHFile (posLoc)) { llassert (fileloc_isDefined (posLoc)); @@ -8426,20 +9607,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))) @@ -8455,6 +9635,45 @@ 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); + } + + if (!uentry_isFunction (old)) + { + if (optgenerror + (FLG_INCONDEFS, + message ("%s %q declared as function, but previously declared as %s", + ekind_capName (unew->ukind), + uentry_getName (unew), + ekind_unparseLong (old->ukind)), + uentry_whereDeclared (unew))) + { + uentry_showWhereLast (old); + } + + uentry_convertIntoFunction (old); + return; + } + } + + 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! */ @@ -8488,7 +9707,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) @@ -8520,7 +9740,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); } */ @@ -8558,13 +9778,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); @@ -8579,6 +9811,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. @@ -8670,6 +9904,7 @@ uentry_mergeDefinition (uentry old, /*@only@*/ uentry unew) uentry_checkName (old); } + DPRINTF (("After: %s", uentry_unparseFull (old))); llassert (!ctype_isUndefined (old->utype)); } @@ -8716,39 +9951,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); + unew->whereSpecified = fileloc_copy (old->whereSpecified); + } - unew->sref = sRef_saveCopy (old->sref); /* Memory leak! */ + if (fileloc_isDefined (unew->whereDefined) + && !fileloc_isDefined (old->whereDefined)) + { + ; /* Keep the old value */ + } + else + { + fileloc_free (unew->whereDefined); + unew->whereDefined = fileloc_copy (old->whereDefined); + } + + if (fileloc_isDefined (unew->whereDeclared) + && !fileloc_isDefined (old->whereDeclared)) + { + ; /* Keep the old value */ + } + else + { + fileloc_free (unew->whereDeclared); + 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))); @@ -8761,6 +10058,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) { @@ -8812,8 +10121,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, @@ -8823,25 +10132,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); @@ -8875,11 +10209,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); @@ -8890,46 +10240,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 { @@ -8938,55 +10304,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 @@ -8994,13 +10361,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 */ @@ -9013,105 +10380,317 @@ 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 + */ + + /* ??? */ + } + 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) + { + 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 */ @@ -9124,8 +10703,26 @@ 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)) @@ -9164,13 +10761,13 @@ void uentry_setUsed (uentry e, fileloc loc) } } - if ((dp = uentry_directParamNo (e)) >= 0) + if (usymId_isValid (usymtab_directParamNo (e))) { - uentry_setUsed (usymtab_getParam (dp), loc); + uentry_setUsed (usymtab_getParam (usymId_toInt (usymtab_directParamNo (e))), loc); } e->used = TRUE; - + if (!sRef_isLocalVar (e->sref)) { if (showUses) @@ -9205,43 +10802,52 @@ bool uentry_isReturned (uentry u) || u->info->var->kind == VKSEFRETPARAM)); } -/*@exposed@*/ sRef uentry_returnedRef (uentry u, exprNodeList args) +/*@exposed@*/ sRef uentry_returnedRef (uentry u, exprNodeList args, fileloc loc) { 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); - sRef_setAllocated (res, g_currentloc); + DPRINTF (("Returned: %s", sRef_unparseFull (res))); + sRef_setAllocated (res, loc); - 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))); - sRefSet_elements (refs, el) - { - sRef base = sRef_getRootBase (el); + /* + ** This should be in exprNode_reflectEnsuresClause + */ - if (sRef_isResult (base)) + stateClauseList_postElements (clauses, cl) + { + if (!stateClause_isGlobal (cl)) + { + sRefSet refs = stateClause_getRefs (cl); + sRefMod modf = stateClause_getEffectFunction (cl); + + sRefSet_elements (refs, el) { - if (modf != NULL) + sRef base = sRef_getRootBase (el); + + if (sRef_isResult (base)) { - sRef sr = sRef_fixBase (el, res); - modf (sr, g_currentloc); + if (modf != NULL) + { + sRef sr = sRef_fixBase (el, res); + modf (sr, loc); + } } - } - else - { - ; - } - } end_sRefSet_elements ; - - } end_specialClauses_postElements ; - + else + { + ; + } + } end_sRefSet_elements ; + } + } end_stateClauseList_postElements ; + return res; } else @@ -9263,24 +10869,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); } } @@ -9299,19 +10914,21 @@ bool uentry_isReturned (uentry u) } else { + /* should this ever happen? */ 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 { @@ -9320,17 +10937,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 { @@ -9340,18 +10958,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 { @@ -9364,11 +10982,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; } } @@ -9379,7 +11005,7 @@ static bool uentry_isRefCounted (uentry ue) if (ctype_isFunction (ct)) { - return (ctype_isRefCounted (ctype_returnValue (ct))); + return (ctype_isRefCounted (ctype_getReturnType (ct))); } else { @@ -9466,6 +11092,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)); @@ -9475,15 +11153,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? */ @@ -9533,63 +11218,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 (); @@ -9603,7 +11265,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); } @@ -9620,52 +11282,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 @@ -9673,18 +11319,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); + } + } } /* @@ -9694,80 +11342,121 @@ 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*/ + +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); +} + - fprintf(stderr, "uentry:Error in setSize\n"); +bool uentry_hasBufStateInfo (uentry ue) +{ + llassert (uentry_isValid (ue)); + return (ue->info->var->bufinfo != NULL); } +bool uentry_isNullTerminated (uentry ue) +{ + llassert (uentry_hasBufStateInfo (ue)); + llassert (ue->info->var->bufinfo != NULL); + return ue->info->var->bufinfo->bufstate == BB_NULLTERMINATED; +} + +bool uentry_isPossiblyNullTerminated (uentry ue) +{ + llassert (uentry_hasBufStateInfo (ue)); + llassert (ue->info->var->bufinfo != NULL); + return (ue->info->var->bufinfo->bufstate == BB_POSSIBLYNULLTERMINATED); +} + +bool uentry_isNotNullTerminated (uentry ue) +{ + llassert (uentry_hasBufStateInfo (ue)); + llassert (ue->info->var->bufinfo != NULL); + return (ue->info->var->bufinfo->bufstate == BB_NOTNULLTERMINATED); +} + +# 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