/*
-** LCLint - annotation-assisted static program checker
-** Copyright (C) 1994-2001 University of Virginia,
+** Splint - annotation-assisted static program checker
+** Copyright (C) 1994-2002 University of Virginia,
** Massachusetts Institute of Technology
**
** This program is free software; you can redistribute it and/or modify it
** 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"
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@*/ ;
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);
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)
{
functionConstraint constraint;
- DPRINTF( (message ("called uentry_getFcnPostconditions on %s",
+ 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",
+ DPRINTF((message ("called uentry_getFunctionConditions on nonfunction %s",
uentry_unparse (ue) ) ) );
if (!uentry_isFunction (ue) )
{
if (!uentry_isFunction(ue))
{
- DPRINTF( (message ("called uentry_getFunctionConditions on non function %s",
+ DPRINTF((message ("called uentry_getFunctionConditions on non function %s",
uentry_unparse (ue) ) ) );
return constraintList_undefined;
return ue;
}
-# ifndef NOLCL
/*@notnull@*/ uentry uentry_makeSpecEnumConstant (cstring n, ctype t, fileloc loc)
{
uentry ue = uentry_makeConstant (n, t, loc);
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)
{
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;
}
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));
+ }
}
}
}
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))
return (e);
}
-# ifndef NOLCL
void
uentry_setRefCounted (uentry e)
{
sRef_storeState (e->sref);
}
}
-# endif
void
uentry_setStatic (uentry c)
if (uentry_isVariable (ue))
{
- /*@i634 ue->sref = sRef_saveCopyShallow (ue->info->var->origsref); */
+
+ /*@i634 ue->sref = sRef_saveCopyShallow (ue->info->var->origsref); */
sRef_setDefState (sr, ue->info->var->defstate, fileloc_undefined);
sRef_setNullState (sr, ue->info->var->nullstate, fileloc_undefined);
}
}
-static void uentry_addStateClause (uentry ue, stateClause sc)
+static void uentry_addStateClause (/*@notnull@*/ uentry ue, stateClause sc)
{
/*
** Okay to allow multiple clauses of the same kind.
void uentry_addWarning (uentry ue, /*@only@*/ warnClause warn)
{
+ llassert (uentry_isValid (ue));
llassert (warnClause_isUndefined (ue->warn));
ue->warn = warn;
}
if (functionConstraint_isDefined (ue->info->fcn->preconditions))
{
- /* drl 11-29-2001
- I changed this so it didn't appear as an LCLint bug
+ /* 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 LCLint
+ a function with two requires clauses. Now Splint
prints an error and tries to conjoin the lists.
*/
llparseerror
}
else
{
- llfatalbug ( (message("uentry_setPreconditions called with invalid uentry") ));
+ llfatalbug ((message("uentry_setPreconditions called with invalid uentry") ));
}
}
}
else
{
- llfatalbug ( (message("uentry_setPostconditions called with invalid uentry") ));
+ llfatalbug ((message("uentry_setPostconditions called with invalid uentry") ));
}
}
else if (qual_isUnused (qel))
{
uentry_setUsed (ue, fileloc_undefined);
+ DPRINTF (("Used: %s", uentry_unparseFull (ue)));
}
else if (qual_isExternal (qel))
{
{
fileloc loc = setLocation ();
uentry ue = uentry_makeVariable (idDecl_observeId (t), ct, loc, FALSE);
-
+
uentry_reflectQualifiers (ue, idDecl_getQuals (t));
if (!uentry_isExtern (ue))
}
}
-# ifndef NOLCL
/*@notnull@*/ uentry uentry_makeVariableParam (cstring n, ctype t, fileloc loc)
{
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 ();
e->info = (uinfo) dmalloc (sizeof (*e->info));
e->info->uconst = (ucinfo) dmalloc (sizeof (*e->info->uconst));
e->info->uconst->access = typeIdSet_undefined;
+ e->info->uconst->macro = macro;
uentry_setSpecDef (e, f);
/*@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)
}
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;
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;
- /*@access sRef@*/ /*i@222*/
- /* It probably isn't necessary to violate the abstraction here
- I'll fix this later
- */
- s->bufinfo.bufstate = BB_NOTNULLTERMINATED;
- /*@noaccess sRef@*/
- } else {
- e->info->var->bufinfo = NULL;
- }/* end else */
-/* end modification */
+ if (ctype_isArray (t) || ctype_isPointer(t))
+ {
+ /*@i222@*/ e->info->var->bufinfo = dmalloc (sizeof (*e->info->var->bufinfo));
+ e->info->var->bufinfo->bufstate = BB_NOTNULLTERMINATED;
+ sRef_setNotNullTerminatedState (s);
+ }
+ else
+ {
+ e->info->var->bufinfo = NULL;
+ }/* end else */
+ /* end modification */
return (e);
}
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 = ue->used || (oldInfo->kind == VKEXPMACRO);
}
void
-uentry_setGlobals (uentry ue, /*@owned@*/ globSet globs)
+uentry_setGlobals (uentry ue, /*@only@*/ globSet globs)
{
llassert (uentry_isValid (ue));
+ globSet_markImmutable (globs);
+
if (uentry_isIter (ue))
{
- llassert (globSet_isUndefined (ue->info->iter->globs));
- ue->info->iter->globs = globs;
+ ue->info->iter->globs = globSet_unionFree (ue->info->iter->globs, globs);
}
else
{
uentry_convertVarFunction (ue);
-
llassert (uentry_isFunction (ue));
- llassert (!ue->info->fcn->hasGlobs
- && globSet_isUndefined (ue->info->fcn->globs));
-
+
ue->info->fcn->hasGlobs = TRUE;
- globSet_markImmutable (globs);
- /*@-mustfree@*/ ue->info->fcn->globs = globs;
- /*@=mustfree@*/
+ ue->info->fcn->globs = globSet_unionFree (ue->info->fcn->globs, globs);
}
- /*@i23*/
- /* ??? - evans 2001-09-09 not sure what's going on here...?
- if (globSet_hasStatic (globs))
- {
- context_recordFileGlobals (globs);
- }
- */
-
if (context_getFlag (FLG_GLOBALSIMPMODIFIESNOTHING))
{
ue->info->fcn->hasMods = TRUE;
FALSE, FALSE));
}
-# ifndef NOLCL
/*@notnull@*/ uentry
uentry_makePrivFunction2 (cstring n, ctype t,
typeIdSet access,
reflectImplicitFunctionQualifiers (ue, TRUE);
return (ue);
}
-# endif
uentry uentry_makeExpandedMacro (cstring s, fileloc f)
{
return FALSE;
}
-# ifndef NOLCL
/*@notnull@*/ uentry
uentry_makeTypeListFunction (cstring n, typeIdSet access, fileloc f)
{
reflectImplicitFunctionQualifiers (ue, TRUE);
return ue;
}
-# endif
/*
** datatypes
return (ret);
}
-# ifndef NOLCL
uentry
uentry_makeEnumTag (cstring n, ctype t, fileloc loc)
{
cstring_free (ename);
return ret;
}
-# endif
uentry
uentry_makeUnionTagLoc (cstring n, ctype t)
{
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;
e->info = (uinfo) dmalloc (sizeof (*e->info));
e->info->uconst = (ucinfo) dmalloc (sizeof (*e->info->uconst));
e->info->uconst->access = access;
-
+ e->info->uconst->macro = FALSE; /*@i523! fix this when macro info added to library */
uentry_setConstantValue (e, m);
sRef_storeState (e->sref);
return (e);
}
-# ifndef NOLCL
static void uentry_setHasGlobs (uentry ue)
{
llassert (uentry_isFunction (ue));
ue->info->fcn->hasMods = TRUE;
}
-# endif
bool uentry_hasGlobs (uentry ue)
{
}
else if (uentry_isConstant (v))
{
- res = message ("%q = %q",
- res, multiVal_unparse (uentry_getConstantValue (v)));
+ res = message ("%q = %q / %q",
+ res, multiVal_unparse (uentry_getConstantValue (v)),
+ sRef_unparseFull (v->sref));
}
else
{
return globSet_undefined;
}
- if (l->ukind != KFCN)
+ if (uentry_isFunction (l))
+ {
+ return l->info->fcn->globs;
+ }
+ else if (uentry_isIter (l))
{
- if (l->ukind != KITER && l->ukind != KENDITER)
+ return l->info->iter->globs;
+ }
+ else if (uentry_isEndIter (l))
+ {
+ return globSet_undefined;
+ }
+ else
+ {
+ if (l->ukind == KVAR)
{
- if (l->ukind == KVAR)
- {
- llbug (message ("Bad call to uentry_getGlobs (var): %q (%s)",
+ llcontbug (message ("Bad call to uentry_getGlobs (var): %q (%s)",
uentry_unparse (l),
ekind_unparse (l->ukind)));
- }
- else
- {
- llbug (message ("Bad call to uentry_getGlobs: %q (%s)",
+ }
+ else
+ {
+ llcontbug (message ("Bad call to uentry_getGlobs: %q (%s)",
uentry_unparse (l),
ekind_unparse (l->ukind)));
- }
}
+
return globSet_undefined;
}
-
- return l->info->fcn->globs;
}
/*@observer@*/ sRefSet
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
{
ucinfo ret = (ucinfo) dmalloc (sizeof (*ret));
ret->access = u->access;
+ ret->macro = u->macro;
return ret;
}
nuentries--;
sfree (e);
- }
+}
extern void uentry_markOwned (/*@owned@*/ uentry u)
{
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))
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
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);
}
}
}
{
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);
}
}
}
{
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),
}
}
+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)
{
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)))
{
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;
if (ctype_isKnown (oldType))
{
llassert (ctype_isFunction (oldType));
-
oldRetType = ctype_getReturnType (oldType);
}
if (ctype_isKnown (newType))
{
llassert (ctype_isFunction (newType));
-
newRetType = ctype_getReturnType (newType);
}
paramno++;
/*
- ** Forgot this! detected by lclint:
+ ** Forgot this! detected by splint:
** uentry.c:1257,15: Suspected infinite loop
*/
}
unew->info->fcn->specclauses = stateClauseList_undefined;
/*@-branchstate@*/
}
- /*@=branchstate@*/ /*@i23 shouldn't need this@*/
}
+ /*@=branchstate@*/ /*@i23 shouldn't need this@*/
if (fileloc_isUndefined (old->whereDeclared))
{
{
/* no change */
}
-}
+/*@i523 @*/ }
void
uentry_mergeConstantValue (uentry ue, /*@only@*/ multiVal m)
static void uentry_updateInto (/*@unique@*/ uentry unew, uentry old)
{
- ekind okind = unew->ukind;
+ 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;
llassert (cstring_equal (unew->uname, old->uname));
unew->utype = old->utype;
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 ();
enew->whereDefined = fileloc_copy (e->whereDefined);
enew->whereDeclared = fileloc_copy (e->whereDeclared);
- enew->sref = sRef_saveCopy (e->sref); /* Memory leak! */
+ 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;
}
}
+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)
{
*/
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,
if (sRef_isDead (res->sref))
{
sRef_showStateInfo (res->sref);
+ sRef_showStateInfo (other->sref);
}
else if (sRef_isKept (res->sref))
{
sRef_showAliasInfo (res->sref);
+ sRef_showAliasInfo (other->sref);
}
else /* dependent */
{
}
}
-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);
}
static void
-uentry_mergeAliasStates (uentry res, uentry other, fileloc loc,
- bool mustReturn, bool flip, bool opt,
+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 alias states: %s / %s",
uentry_unparseFull (res),
uentry_unparseFull (other)));
- if (sRef_isValid (res->sref))
+ if (sRef_isValid (rs))
{
if (!mustReturn)
{
- DPRINTF (("1"));
- if (incompatibleStates (res->sref, other->sref))
+ if (uentry_incompatibleMemoryStates (rs, os))
{
- DPRINTF (("2"));
+ DPRINTF (("Incompatible: \n\t%s / \n\t%s",
+ sRef_unparseFull (rs), sRef_unparseFull (os)));
- if (sRef_isThroughArrayFetch (res->sref)
+ 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
{
}
else
{
- if (uentry_relevantReference (other->sref, flip))
+ if (uentry_relevantReference (os, flip))
{
- DPRINTF (("4"));
- 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
}
}
- 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 (uentry_relevantReference (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
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 */
}
}
- 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);
}
}
}
+
+ DPRINTF (("After merge: %s", sRef_unparseFull (res->sref)));
}
static void
-uentry_mergeValueStates (uentry res, uentry other, fileloc loc, bool mustReturn, /*@unused@*/ bool flip)
+uentry_mergeValueStates (/*@notnull@*/ uentry res, /*@notnull@*/ uentry other,
+ fileloc loc, bool mustReturn, /*@unused@*/ bool flip)
{
valueTable rvalues;
valueTable ovalues;
static void
-uentry_mergeSetStates (uentry res, uentry other, /*@unused@*/ fileloc loc,
+uentry_mergeSetStates (/*@notnull@*/ uentry res,
+ /*@notnull@*/ uentry other, /*@unused@*/ fileloc loc,
bool flip, clause cl)
{
if (cl == DOWHILECLAUSE)
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)
|| u->info->var->kind == VKSEFRETPARAM));
}
+/*@i52323@*/
+# if 0
/*@exposed@*/ sRef uentry_returnedRef (uentry u, exprNodeList args)
{
llassert (uentry_isRealFunction (u));
alkind ak;
sRefSet prefs = sRefSet_new ();
sRef res = sRef_undefined;
+ sRef tcref = sRef_undefined;
+ sRef tref = sRef_undefined;
int paramno = 0;
params = uentry_getParams (u);
-
+
+ /*
+ ** Setting up aliases has to happen *after* setting null state!
+ */
+
uentryList_elements (params, current)
{
if (uentry_isReturned (current))
if (exprNodeList_size (args) >= paramno)
{
exprNode ecur = exprNodeList_nth (args, paramno);
- sRef tref = exprNode_getSref (ecur);
+ tref = exprNode_getSref (ecur);
DPRINTF (("Returned reference: %s", sRef_unparseFull (tref)));
if (sRef_isValid (tref))
{
- sRef tcref = sRef_copy (tref);
+ tcref = sRef_copy (tref);
- usymtab_addForceMustAlias (tcref, tref); /* evans 2001-05-27 */
-
if (sRef_isDead (tcref))
{
sRef_setDefined (tcref, g_currentloc);
paramno++;
} end_uentryList_elements ;
-
+
if (sRefSet_size (prefs) > 0)
{
nstate n = sRef_getNullState (u->sref);
-
+
if (sRefSet_size (prefs) == 1)
{
- res = sRefSet_choose (prefs);
+ sRef rref = sRefSet_choose (prefs);
+ tref = rref;
+ res = sRef_makeType (sRef_getType (rref));
+ sRef_copyState (res, tref);
}
else
{
if (nstate_isKnown (n))
{
sRef_setNullState (res, n, g_currentloc);
+ DPRINTF (("Setting null: %s", sRef_unparseFull (res)));
}
}
else
}
else
{
+ DPRINTF (("Making new from %s -->", uentry_unparseFull (u)));
res = sRef_makeNew (ctype_unknown, u->sref, u->uname);
}
}
}
-
if (sRef_getNullState (res) == NS_ABSNULL)
{
ctype ct = ctype_realType (u->utype);
ak = sRef_getAliasKind (res);
+ if (alkind_isImplicit (ak))
+ {
+ sRef_setAliasKind (res, alkind_fixImplicit (ak), g_currentloc);
+ }
+
+# if 0
+ DPRINTF (("Aliasing: %s / %s", sRef_unparseFull (res), sRef_unparseFull (tref)));
+ usymtab_addReallyForceMustAlias (tref, res); /* evans 2001-05-27 */
+
+ /* evans 2002-03-03 - need to be symettric explicitly, since its not a local now */
+ usymtab_addReallyForceMustAlias (res, tref);
+# endif
+
+ sRefSet_free (prefs);
+
+ DPRINTF (("Returns ref: %s", sRef_unparseFull (res)));
+ return res;
+ }
+}
+# endif
+
+/*@exposed@*/ sRef uentry_returnedRef (uentry u, exprNodeList args, fileloc loc)
+{
+ llassert (uentry_isRealFunction (u));
+
+ if (ctype_isFunction (u->utype) && sRef_isStateSpecial (uentry_getSref (u)))
+ {
+ stateClauseList clauses = uentry_getStateClauseList (u);
+ sRef res = sRef_makeNew (ctype_getReturnType (u->utype), u->sref, u->uname);
+
+ DPRINTF (("Returned: %s", sRef_unparseFull (res)));
+ sRef_setAllocated (res, loc);
+
+ DPRINTF (("ensures clause: %s / %s", uentry_unparse (u),
+ stateClauseList_unparse (clauses)));
+
+ /*
+ ** This should be in exprNode_reflectEnsuresClause
+ */
+
+ stateClauseList_postElements (clauses, cl)
+ {
+ if (!stateClause_isGlobal (cl))
+ {
+ sRefSet refs = stateClause_getRefs (cl);
+ sRefMod modf = stateClause_getEffectFunction (cl);
+
+ sRefSet_elements (refs, el)
+ {
+ sRef base = sRef_getRootBase (el);
+
+ if (sRef_isResult (base))
+ {
+ if (modf != NULL)
+ {
+ sRef sr = sRef_fixBase (el, res);
+ modf (sr, loc);
+ }
+ }
+ else
+ {
+ ;
+ }
+ } end_sRefSet_elements ;
+ }
+ } end_stateClauseList_postElements ;
+
+ return res;
+ }
+ else
+ {
+ uentryList params;
+ alkind ak;
+ sRefSet prefs = sRefSet_new ();
+ sRef res = sRef_undefined;
+ int paramno = 0;
+
+ params = uentry_getParams (u);
+
+ uentryList_elements (params, current)
+ {
+ if (uentry_isReturned (current))
+ {
+ if (exprNodeList_size (args) >= paramno)
+ {
+ 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, 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, loc);
+ }
+
+ sRef_makeSafe (tcref);
+ DPRINTF (("Returns tcref / %s", sRef_unparseFull (tcref)));
+ prefs = sRefSet_insert (prefs, tcref);
+ }
+ }
+ }
+
+ paramno++;
+ } end_uentryList_elements ;
+
+ if (sRefSet_size (prefs) > 0)
+ {
+ nstate n = sRef_getNullState (u->sref);
+
+ if (sRefSet_size (prefs) == 1)
+ {
+ res = sRefSet_choose (prefs);
+ }
+ else
+ {
+ /* should this ever happen? */ /*@i534 evans 2001-05-27 */
+ res = sRefSet_mergeIntoOne (prefs);
+ }
+
+ if (nstate_isKnown (n))
+ {
+ sRef_setNullState (res, n, loc);
+ }
+ }
+ else
+ {
+ if (ctype_isFunction (u->utype))
+ {
+ DPRINTF (("Making new from %s -->", uentry_unparseFull (u)));
+ res = sRef_makeNew (ctype_getReturnType (u->utype), u->sref, u->uname);
+ }
+ else
+ {
+ res = sRef_makeNew (ctype_unknown, u->sref, u->uname);
+ }
+
+ if (sRef_isRefCounted (res))
+ {
+ 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, loc);
+ }
+ else
+ {
+ if (ctype_isUser (ct))
+ {
+ sRef_setStateFromUentry (res, usymtab_getTypeEntry (ctype_typeId (ct)));
+ }
+ else
+ {
+ sRef_setNotNull (res, loc);
+ }
+ }
+ }
+
+ if (sRef_isRefCounted (res))
+ {
+ sRef_setAliasKind (res, AK_NEWREF, loc);
+ }
+ else if (sRef_isKillRef (res))
+ {
+ sRef_setAliasKind (res, AK_REFCOUNTED, loc);
+ }
+ else
+ {
+ ;
+ }
+
+ ak = sRef_getAliasKind (res);
+
if (alkind_isImplicit (ak))
{
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;
}
fileloc_free (tloc);
uentry_setHasNameError (ue);
- if (context_getFlag (FLG_REPEATUNRECOG))
+ if (context_getFlag (FLG_REPEATUNRECOG) || (context_inOldSytleScope() ) )
{
uentry_markOwned (ue);
}
*/
-void uentry_setPossiblyNullTerminatedState (uentry p_e) {
- /*@access sRef@*/ /*i523 shouldn't do this! */
- 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;
- }
- }
- }
- /*@noaccess sRef@*/
+void uentry_setPossiblyNullTerminatedState (uentry p_e)
+{
+ llassert (uentry_isValid (p_e));
- fprintf(stderr, "uentry:Error in setPossiblyNullTerminatedState\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_POSSIBLYNULLTERMINATED;
+ sRef_setPossiblyNullTerminatedState (p_e->sref);
+ }
+ }
}
/*
*/
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;
- /*@access sRef@*/ /*@i523 bad!*/
- p_e->sref->bufinfo.bufstate = BB_NULLTERMINATED;
- /*@noaccess sRef@*/
- return;
- }
- }
- }
+ 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);
+ }
+ }
}
/*
effects: sets the size 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;
- /*@access sRef@*/ /*@i523 bad!*/
- p_e->sref->bufinfo.size = size;
- /*@noaccess sRef@*/
- return;
- }
+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);
+ }
+ }
}
- }
-
- fprintf(stderr, "uentry:Error in setSize\n");
}
-
/*
requires: p_e is defined, is a ptr/array variable
modifies: p_e
effects: sets the length of the buffer
*/
-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;
- /*@access sRef@*/ /*@i523 bad!*/
- p_e->sref->bufinfo.len = len;
- /*@noaccess sRef@*/
- return;
- }
+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);
+ }
}
- }
-
- fprintf(stderr, "uentry:Error in setLen\n");
}
/*@=type*/
llassert (uentry_isValid (e) && uentry_isFunction (e));
return functionConstraint_getMetaStateConstraints (e->info->fcn->postconditions);
}
+
+# ifdef DEBUGSPLINT
+
+/*
+** For debugging only
+*/
+
+void uentry_checkValid (uentry ue)
+{
+ if (uentry_isValid (ue))
+ {
+ sRef_checkCompletelyReasonable (ue->sref);
+ }
+}
+
+# endif