/*
-** 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
**
** 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 more information: http://www.splint.org
*/
/*
** usymtab
# include "exprChecks.h"
# include "transferChecks.h"
+/* Needed to install macros when loading libraries */
+
+# include "cpplib.h"
+# include "cpperror.h"
+# include "cpphash.h"
+
/*
** Keep track of type definitions inside a function.
*/
static /*@only@*/ cstring usymtab_unparseStackTab (usymtab p_t);
static /*@exposed@*/ /*@dependent@*/ uentry
usymtab_getRefTab (/*@notnull@*/ usymtab p_u, int p_level, usymId p_index);
+
+# ifdef S_SPLINT_S
+/* These are not used anymore... */
static /*@unused@*/ /*@only@*/ cstring
usymtab_unparseLocalAux (/*@notnull@*/ usymtab p_s);
static /*@unused@*/ /*@only@*/ cstring
usymtab_unparseLocalList (/*@notnull@*/ usymtab p_s);
+# endif
+
static /*@only@*/ cstring usymtab_typeName (/*@notnull@*/ usymtab p_t);
static void usymtab_handleParams (void)
/*@globals utab, globtab, filetab@*/
static void recordFunctionType (uentry ue)
{
- llassert (uentry_isDatatype (ue) || uentry_isAnyTag (ue)
+ llassert (uentry_isDatatype (ue) || uentry_isAnyTag (ue)
|| uentry_isEnumConstant (ue));
-
+ DPRINTF (("Function type: %s", uentry_unparseFull (ue)));
/*@-temptrans@*/
functypes = uentryList_add (functypes, ue);
/*@=temptrans@*/
*/
usymtab_supGlobalEntry
- (uentry_makeConstantAux (context_getFalseName (), boolt,
- fileloc_getBuiltin (), FALSE,
- multiVal_makeInt (0)));
+ (uentry_makeConstantValue (context_getFalseName (), boolt,
+ fileloc_getBuiltin (), FALSE,
+ multiVal_makeInt (0)));
+
usymtab_supGlobalEntry
- (uentry_makeConstantAux (context_getTrueName (), boolt,
- fileloc_getBuiltin (), FALSE,
- multiVal_makeInt (1)));
+ (uentry_makeConstantValue (context_getTrueName (), boolt,
+ fileloc_getBuiltin (), FALSE,
+ multiVal_makeInt (1)));
}
}
if (uentry_isVar (e))
{
uentry_setSref (e, sRef_makeCvar (globScope, thisentry,
- uentry_getType (e)));
+ uentry_getType (e),
+ stateInfo_makeLoc (uentry_whereLast (e))));
}
usymtab_addEntryQuiet (s, e);
if (uentry_isVar (e) && !uentry_isGlobalMarker (e))
{
uentry_setSref (e, sRef_makeCvar (globScope, thisentry,
- uentry_getType (e)));
+ uentry_getType (e),
+ stateInfo_makeLoc (uentry_whereLast (e))));
}
usymtab_addEntryQuiet (s, e);
if (uentry_isStatic (e))
{
- sRef sr = sRef_makeCvar (st->lexlevel, thisentry, ct);
+ sRef sr = sRef_makeCvar (st->lexlevel, thisentry, ct, stateInfo_makeLoc (uentry_whereLast (e)));
if (sRef_isStack (sr) || sRef_isLocalState (sr))
{
}
else
{
- uentry_setSref (e, sRef_makeCvar (st->lexlevel, thisentry, ct));
+ uentry_setSref (e, sRef_makeCvar (st->lexlevel, thisentry, ct, stateInfo_makeLoc (uentry_whereLast (e))));
}
-
- }
+ }
if (uentry_isDatatype (e))
{
if (uentry_isDeclared (ce))
{
- llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
+ /* evans 2001-08-26
+ No - this can happen for internal typedefs
+ llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
+ */
+
DPRINTF (("Merge defn"));
uentry_mergeDefinition (ce, e);
}
else
{
- llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
+ /* evans 2001-08-26
+ No - this can happen for internal typedefs
+ llassert ((st->lexlevel > fileScope || !sRef_modInFunction ()));
+ */
+
DPRINTF (("Merge entries..."));
uentry_mergeEntries (ce, e);
DPRINTF (("After: %s", uentry_unparseFull (ce)));
ct = ctype_getReturnType (ct);
}
- uentry_setSref (ce, sRef_makeCvar (st->lexlevel, eindex, ct));
- }
+ uentry_setSref (ce, sRef_makeCvar (st->lexlevel, eindex, ct, stateInfo_makeLoc (uentry_whereLast (ce))));
+ }
}
else /* no previous entry */
{
outer = usymtab_lookupQuiet (st->env, ename);
+ DPRINTF (("New : [%p] %s", e, uentry_unparseFull (e)));
+ DPRINTF (("Outer: [%p] %s", outer, uentry_unparseFull (outer)));
+
/*
** no previous definition, add the new one
*/
&& uentry_isValid (outer)
&& !(uentry_isYield (e) || uentry_isYield (outer))
&& fileloc_isDefined (uentry_whereLast (e))
- && fileloc_isDefined (uentry_whereLast (outer)))
+ && !fileloc_isXHFile (uentry_whereLast (e))
+ && fileloc_isDefined (uentry_whereLast (outer))
+ && !fileloc_isXHFile (uentry_whereLast (outer)))
{
if (!uentry_sameKind (outer, e))
{
bool stat = (tab == globtab) && uentry_isStatic (e);
uentry ret;
-
(void) usymtab_supEntryAux (tab, e, isref);
if (stat)
ret = usymtab_supEntryReturnAux (globtab, e, FALSE);
+ /*
+ ** We need to keep track of internal function declarations, so
+ ** we can remove them from the symbol table after exiting this
+ ** function. This is a bit bogus, of course.
+ */
+
if (sRef_modInFunction ())
{
recordFunctionType (ret);
return (uentry_getName (ue));
}
+# if 0
/*@unused@*/ static void
usymtab_rehash (/*@notnull@*/ usymtab s)
{
cstringTable_insert (s->htable, cstring_copy (uentry_rawName (s->entries[i])), i);
}
}
+# endif
/*
** superficial copy of usymtab
}
}
-
-
-
}
+
void usymtab_load (FILE *f)
/*@globals utab, globtab@*/
/*@modifies utab, *f@*/
{
int lastindex = utab->nentries;
ue = usymtab_addEntryAlways (utab, ue);
+
+
+# if 0
+ if (uentry_isConstant (ue)) /*@i23! isPreProcessorMacro */
+ {
+ cstring uname = uentry_getName (ue);
+
+ /* Also check its a macro... */
+ DPRINTF (("Installing: %s", uname));
+
+ cpphash_installMacro
+ (mstring_copy (cstring_toCharsSafe (uname)),
+ cstring_length (uname),
+ cpplib_createDefinition (message ("%s 255", uname),
+ loc,
+ FALSE, FALSE).defn,
+ cpphash_hashCode (cstring_toCharsSafe (uname),
+ cstring_length (uname),
+ CPP_HASHSIZE));
+
+ DPRINTF (("After install: %s", uname));
+ }
+# endif
+
if (utab->nentries != lastindex + 1)
{
DPRINTF (("No add: %s", uentry_unparseFull (ue)));
}
s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
- temp = cstring_fromChars(reader_getWord(&s) );
+ temp = cstring_fromChars (reader_getWord(&s) );
if (cstring_compareLit (temp,"pre:") == 0 )
{
s = fgets (os, MAX_DUMP_LINE_LENGTH, f);
temp = cstring_fromChars(reader_getWord(&s) );
- if (cstring_compareLit (temp,"post:") == 0 )
+ if (cstring_compareLit (temp, "post:") == 0 )
{
postconditions = constraintList_undump (f);
}
else
{
- if (cstring_compareLit (temp,"post:EMPTY") != 0 )
+ if (cstring_compareLit (temp, "post:EMPTY") != 0 )
llfatalbug ((message("Error reading library file post:EMPTY expected but got %s", temp ) ));
}
- cstring_free(temp);
+ cstring_free (temp);
uentry_setPreconditions (ue, functionConstraint_createBufferConstraint (preconditions));
uentry_setPostconditions (ue, functionConstraint_createBufferConstraint (postconditions));
{
if (sRef_isStateSpecial (pref))
{
- uentry_setDefState (ue, SS_ALLOCATED);
+ uentry_setDefState (ue, SS_SPECIAL); /* ALLOCATED); */
+ /* evans 2002-01-01: should be unnecessary, the pre clauses
+ ** set the state if necessary.
+ */
}
else
{
{
if (utab->lexlevel > fileScope)
{
- llparseerror (cstring_makeLiteral ("New function scope inside function."));
+ llparseerror (cstring_makeLiteral ("New function scope inside function"));
while (utab->lexlevel > fileScope)
{
{
sRef sr = uentry_getSref (glob);
- DPRINTF (("Check global return: %s // orig: %s // sr: %s",
+ DPRINTF (("Check global return: %s / orig: %s / sr: %s",
uentry_unparseFull (glob),
sRef_unparseFull (orig),
sRef_unparseFull (sr)));
{
ctype ct = ctype_realType (uentry_getType (glob));
+ DPRINTF (("Check global destroyed: %s", uentry_unparseFull (glob)));
+
if (ctype_isVisiblySharable (ct))
{
if (optgenerror
else
{
sRef_protectDerivs ();
- (void) checkGlobalDestroyed (sr, g_currentloc);
+ (void) transferChecks_globalDestroyed (sr, g_currentloc);
sRef_clearProtectDerivs ();
}
}
}
else
{
- if (sRef_isDead (sr))
+ if (sRef_isDead (sr) || sRef_isKept (sr))
{
if (optgenerror
(FLG_GLOBSTATE,
message ("Function returns with global %q "
- "referencing released storage",
- uentry_getName (glob)),
+ "referencing %s storage",
+ uentry_getName (glob),
+ cstring_makeLiteralTemp (sRef_isDead (sr) ? "released" : "kept")),
g_currentloc))
{
- sRef_showStateInfo (sr);
+ if (sRef_isKept (sr))
+ {
+ sRef_showAliasInfo (sr);
+ }
+ else
+ {
+ sRef_showStateInfo (sr);
+ }
+
sRef_setDefState (sr, SS_UNKNOWN, fileloc_undefined);
}
}
}
else
{
- checkGlobReturn (glob);
+ transferChecks_globalReturn (glob);
}
}
}
void usymtab_checkFinalScope (bool isReturn)
/*@globals utab@*/
{
- bool mustFree = context_getFlag (FLG_MUSTFREE);
+ bool mustFree = context_getFlag (FLG_MUSTFREEONLY) || context_getFlag (FLG_MUSTFREEFRESH); /*@i423 remove this mustFree */
bool mustDefine = context_getFlag (FLG_MUSTDEFINE);
/* bool mustNotAlias = context_getFlag (FLG_MUSTNOTALIAS); */
sRefSet checked = sRefSet_new ();
/*@innercontinue@*/ continue;
}
}
-
+
DPRINTF (("Here check final scope: %s", uentry_unparseFull (ce)));
if (ctype_isFunction (uentry_getType (ce)))
|| sRef_isFileOrGlobalScope (rb))
{
/* Don't do the loseref check...but should check state! */
+ DPRINTF (("Skipping check 1"));
}
else if (sRef_isDefinitelyNull (sr)
|| usymtab_isDefinitelyNull (sr))
/*
** No state reference errors for definitely null references.
*/
+
+ DPRINTF (("Skipping check 2"));
}
else
{
minfo = context_lookupMetaStateInfo (fkey);
llassert (metaStateInfo_isDefined (minfo));
- if (stateValue_isError (fval))
+ if (stateValue_isError (fval)
+ || sRef_isStateUndefined (sr)) /* No errors for undefined state */
{
- ;
+ DPRINTF (("Skipping check 3"));
}
else
{
} end_valueTable_elements;
}
+ DPRINTF (("Here 1"));
+
if (mustFree)
{
- DPRINTF (("Check entry: %s", uentry_unparseFull (ce)));
+ DPRINTF (("Check mustfree entry: %s", uentry_unparseFull (ce)));
if (!sRefSet_member (checked, sr) && !sRef_isFileOrGlobalScope (rb))
{
if (sRefSet_isEmpty (als))
{
- checkLocalDestroyed (sr, g_currentloc);
+ transferChecks_localDestroyed (sr, g_currentloc);
}
else
{
if (!isReturn)
{
- if (canLoseReference (sr, g_currentloc))
+ if (transferChecks_canLoseReference (sr, g_currentloc))
{
DPRINTF (("Can lose!"));
hasError = FALSE;
sRef ar = sRef_getAliasInfoRef (sr);
if (optgenerror
- (FLG_MUSTFREE,
+ (sRef_isFresh (ar) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
message
("Last reference %q to %s storage %qnot %q before %q",
sRef_unparse (sr),
else if (sRef_isNewRef (sr))
{
if (optgenerror
- (FLG_MUSTFREE,
+ (sRef_isFresh (sr) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
message
("%q %q not released before %q",
cstring_makeLiteral
{
if (ctype_isRealSU (sRef_getType (sr)))
{
- checkStructDestroyed (sr, g_currentloc);
+ transferChecks_structDestroyed (sr, g_currentloc);
}
else
{
DPRINTF (("Here we are: %s", sRef_unparseFull (sr)));
if (optgenerror
- (FLG_MUSTFREE,
+ (sRef_isFresh (sr) ? FLG_MUSTFREEFRESH : FLG_MUSTFREEONLY,
message
("%s storage %q not %q before %q",
alkind_capName (sRef_getAliasKind (sr)),
;
}
}
- else if (mustDefine && uentry_isOut (ce))
- {
- if (!ynm_toBoolStrict (sRef_isReadable (sr)))
- {
- voptgenerror
- (FLG_MUSTDEFINE,
- message ("Out storage %q not defined before %q",
- uentry_getName (ce),
- cstring_makeLiteral
- (isReturn ? "return" : "scope exit")),
- g_currentloc);
-
- /* uentry_showWhereDeclared (ce); */
- }
- }
- else
+ }
+
+ if (mustDefine && uentry_isOut (ce))
+ {
+ /* No error if its dead (either only or error already reported */
+ if (!sRef_isReallyDefined (sr) && !sRef_isDead (sr))
{
- ;
+ voptgenerror
+ (FLG_MUSTDEFINE,
+ message ("Out storage %q not defined before %q",
+ uentry_getName (ce),
+ cstring_makeLiteral
+ (isReturn ? "return" : "scope exit")),
+ g_currentloc);
+
+ DPRINTF (("sr: %s", sRef_unparseFull (sr)));
}
+ }
+
+ /*
+ ** also check state is okay
+ */
+
+ if (usymtab_lexicalLevel () > functionScope
+ && uentry_isVariable (ce)
+ && (sRef_isLocalVar (sr)
+ && (sRef_isDependent (sr) || sRef_isLocalState (sr))))
+ {
+ sRefSet ab = usymtab_aliasedBy (sr);
- /*
- ** also check state is okay
- */
+ /* should do something more efficient here */
- if (usymtab_lexicalLevel () > functionScope
- && uentry_isVariable (ce)
- && (sRef_isLocalVar (sr)
- && (sRef_isDependent (sr) || sRef_isLocalState (sr))))
+ if (sRefSet_isEmpty (ab))
{
- sRefSet ab = usymtab_aliasedBy (sr);
-
- /* should do something more efficient here */
-
- if (sRefSet_isEmpty (ab))
- {
- /* and no local ref */
- DPRINTF (("Check lose ref: %s", uentry_unparseFull (ce)));
- checkLoseRef (ce);
- }
- else
- {
- ;
- }
-
- sRefSet_free (ab);
+ /* and no local ref */
+ DPRINTF (("Check lose ref: %s", uentry_unparseFull (ce)));
+ transferChecks_loseReference (ce);
}
- else
+ else
{
;
}
- checked = sRefSet_insert (checked, sr);
+ sRefSet_free (ab);
}
+ else
+ {
+ ;
+ }
+
+ checked = sRefSet_insert (checked, sr);
}
llassert (usymtab_isDefined (stab->env));
{
ss (sr);
}
-
+
DPRINTF (("Storage: %s", sRef_unparseFull (sr)));
}
}
{
uentry param = usymtab_lookupQuiet (utab, uentry_rawName (arg));
DPRINTF (("Check param return: %s", uentry_unparseFull (param)));
- checkParamReturn (param);
+ transferChecks_paramReturn (param);
}
}
} end_uentryList_elements;
/*@i@*/ lctab->env = utab;
/*@i@*/ utab = ctab;
/*@-branchstate@*/ } /*@=branchstate@*/
-/*@-globstate@*/
-}
+ /*@-globstate@*/
+/*@i523@*/ }
/*@=globstate@*/
/*
while (tab->lexlevel >= lowlevel)
{
+ DPRINTF (("Is guarded? [%s] %s",
+ guardSet_unparse (tab->guards),
+ sRef_unparseFull (s)));
+
if (guardSet_isGuarded (tab->guards, s))
{
/*
bool usymtab_isGuarded (sRef s)
{
-
+ DPRINTF (("Is guarded? %s", sRef_unparseFull (s)));
return (sRef_aliasCompleteSimplePred (usymtab_isGuardedAux, s));
}
mstring_free (ind);
}
+# ifdef S_SPLINT_S
static /*@only@*/ cstring /*@unused@*/
usymtab_unparseLocalAux (/*@notnull@*/ usymtab s)
{
return (c);
}
+# endif
void
usymtab_printLocal (void)