/*
-** 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: splint@cs.virginia.edu
+** To report a bug: splint-bug@cs.virginia.edu
+** For more information: http://www.splint.org
*/
/*
** context.c
* or, if not set "." will be used.
*/
-# include "lclintMacros.nf"
+# include "splintMacros.nf"
# include "llbasic.h"
-# include "mtincludes.h"
# ifndef NOLCL
# include "usymtab_interface.h"
CX_GLOBAL, CX_INNER,
CX_FUNCTION, CX_FCNDECLARATION,
CX_MACROFCN, CX_MACROCONST, CX_UNKNOWNMACRO,
- CX_ITERDEF, CX_ITEREND,
+ CX_ITERDEF, CX_ITEREND,
+ CX_OLDSTYLESCOPE, /* Parsing old-style parameter declarations */
CX_LCL, CX_LCLLIB, CX_MT
} kcontext;
/*@reldef@*/ maccesst *moduleaccess; /* Not defined is nmods == 0. */
kcontext kind;
- kcontext savekind;
ctype boolType;
metaStateTable stateTable; /* User-defined state information. */
annotationTable annotTable; /* User-defined annotations table. */
- union
+ union u_cont
{
bool glob;
int cdepth;
/*@dependent@*/ /*@exposed@*/ uentry fcn;
} cont;
+
+ kcontext savekind;
+ union u_cont savecont;
} gc;
static /*@exposed@*/ cstring context_exposeString (flagcode p_flag) ;
{
context_setFlag (code, FALSE);
}
- } end_allFlagCodes;
-
- }
+ } end_allFlagCodes;
+}
/*
** resetAllFlags
void
context_resetAllFlags (void)
{
+ DPRINTF (("******** Reset all flags"));
+
allFlagCodes (code)
{
gc.flags[code] = FALSE;
- if (flagcode_hasValue (code))
+ if (flagcode_hasNumber (code))
{
int val = 0;
case FLG_INDENTSPACES:
val = DEFAULT_INDENTSPACES; break;
case FLG_EXTERNALNAMELEN:
- val = DEFAULT_EXTERNALNAMELEN; break;
+ val = ISO99_EXTERNALNAMELEN; break;
case FLG_INTERNALNAMELEN:
- val = DEFAULT_INTERNALNAMELEN; break;
+ val = ISO99_INTERNALNAMELEN; break;
case FLG_COMMENTCHAR:
val = (int) DEFAULT_COMMENTCHAR; break;
case FLG_CONTROLNESTDEPTH:
- val = (int) DEFAULT_CONTROLNESTDEPTH; break;
+ val = (int) ISO99_CONTROLNESTDEPTH; break;
case FLG_STRINGLITERALLEN:
- val = (int) DEFAULT_STRINGLITERALLEN; break;
+ val = (int) ISO99_STRINGLITERALLEN; break;
case FLG_INCLUDENEST:
- val = (int) DEFAULT_INCLUDENEST; break;
+ val = (int) ISO99_INCLUDENEST; break;
case FLG_NUMSTRUCTFIELDS:
- val = (int) DEFAULT_NUMSTRUCTFIELDS; break;
+ val = (int) ISO99_NUMSTRUCTFIELDS; break;
case FLG_NUMENUMMEMBERS:
- val = (int) DEFAULT_NUMENUMMEMBERS; break;
+ val = (int) ISO99_NUMENUMMEMBERS; break;
case FLG_EXPECT:
case FLG_LCLEXPECT:
break;
}
/*@=loopswitchbreak@*/
+ DPRINTF (("Set value: [%s] / %d", flagcode_unparse (code), val));
context_setValue (code, val);
+ DPRINTF (("Set value: [%s] / %d", flagcode_unparse (code), context_getValue (code)));
+ llassert (context_getValue (code) == val);
+ }
+ else if (flagcode_hasChar (code))
+ {
+ llassert (code == FLG_COMMENTCHAR);
+ context_setCommentMarkerChar (DEFAULT_COMMENTCHAR);
}
else if (flagcode_hasString (code))
{
/*@i34 move this into flags.def */
+ gc.flags[FLG_OBVIOUSLOOPEXEC] = TRUE;
gc.flags[FLG_MODIFIES] = TRUE;
gc.flags[FLG_NESTCOMMENT] = TRUE;
gc.flags[FLG_GLOBALS] = TRUE;
gc.flags[FLG_FULLINITBLOCK] = TRUE;
+ gc.flags[FLG_INITSIZE] = TRUE;
+ gc.flags[FLG_INITALLELEMENTS] = TRUE;
+
+ gc.flags[FLG_STRINGLITTOOLONG] = TRUE;
+
gc.flags[FLG_LIKELYBOOL] = TRUE;
gc.flags[FLG_ZEROPTR] = TRUE;
gc.flags[FLG_NUMLITERAL] = TRUE;
gc.flags[FLG_SIZEOFFORMALARRAY] = TRUE;
gc.flags[FLG_FIXEDFORMALARRAY] = TRUE;
+ gc.flags[FLG_UNRECOGDIRECTIVE] = TRUE;
gc.flags[FLG_WARNUSE] = TRUE;
gc.flags[FLG_PREDASSIGN] = TRUE;
gc.flags[FLG_MODOBSERVER] = TRUE;
gc.flags[FLG_FORMATTYPE] = TRUE;
gc.flags[FLG_BADFLAG] = TRUE;
gc.flags[FLG_WARNFLAGS] = TRUE;
+ gc.flags[FLG_WARNRC] = TRUE;
gc.flags[FLG_FILEEXTENSIONS] = TRUE;
gc.flags[FLG_WARNUNIXLIB] = TRUE;
gc.flags[FLG_WARNPOSIX] = TRUE;
gc.flags[FLG_TYPE] = TRUE;
gc.flags[FLG_INCOMPLETETYPE] = TRUE;
gc.flags[FLG_ABSTRACT] = TRUE;
- gc.flags[FLG_ITER] = TRUE;
- gc.flags[FLG_CONTROL] = TRUE;
+ gc.flags[FLG_ITERBALANCE] = TRUE;
+ gc.flags[FLG_ITERYIELD] = TRUE;
+ gc.flags[FLG_DUPLICATECASES] = TRUE;
+ gc.flags[FLG_ALWAYSEXITS] = TRUE;
+ gc.flags[FLG_EMPTYRETURN] = TRUE;
+ gc.flags[FLG_MACRORETURN] = TRUE;
gc.flags[FLG_UNRECOG] = TRUE;
gc.flags[FLG_SYSTEMUNRECOG] = TRUE;
gc.flags[FLG_LINTCOMMENTS] = TRUE;
gc.flags[FLG_GNUEXTENSIONS] = TRUE;
+ /*
+ Changed for 3.0.0.19
+ */
+ gc.flags[FLG_ORCONSTRAINT] = TRUE;
+ gc.flags[FLG_CONSTRAINTLOCATION] = TRUE;
/*
** On by default for Win32, but not Unix (to support MS/VC++ error message format).
*/
flagcode_unparse (modeflags[i]))); } \
else { context_setFlag (modeflags[i], TRUE); } i++; }}
+static void context_setModeAux (cstring p_s, bool p_warn) ;
+
void
context_setMode (cstring s)
+{
+ context_setModeAux (s, TRUE);
+}
+
+void
+context_setModeNoWarn (cstring s)
+{
+ context_setModeAux (s, FALSE);
+}
+
+void
+context_setModeAux (cstring s, bool warn)
{
intSet setflags = intSet_new ();
}
} end_intSet_elements ;
- voptgenerror (FLG_WARNFLAGS,
- message ("Setting mode %s after setting mode flags will "
- "override set values of flags: %s",
- s, rflags),
- g_currentloc);
+ if (warn)
+ {
+ voptgenerror (FLG_WARNFLAGS,
+ message ("Setting mode %s after setting mode flags will "
+ "override set values of flags: %s",
+ s, rflags),
+ g_currentloc);
+ }
cstring_free (rflags);
}
flagcode modeflags[] =
{
FLG_ENUMINT, FLG_MACROMATCHNAME,
+ FLG_STRINGLITNOROOM,
FLG_MACROUNDEF, FLG_RELAXQUALS,
FLG_USEALLGLOBS, FLG_CHECKSTRICTGLOBALS,
FLG_CHECKSTRICTGLOBALIAS,
FLG_CHECKEDGLOBALIAS,
FLG_CHECKMODGLOBALIAS,
FLG_PREDBOOLOTHERS, FLG_PREDBOOLINT,
+ FLG_UNSIGNEDCOMPARE,
FLG_PARAMUNUSED, FLG_VARUNUSED, FLG_FUNCUNUSED,
FLG_TYPEUNUSED,
FLG_CONSTUNUSED, FLG_ENUMMEMUNUSED, FLG_FIELDUNUSED,
- FLG_PTRNUMCOMPARE, FLG_BOOLCOMPARE, FLG_MUTREP,
- FLG_NOEFFECT, FLG_IMPTYPE,
+ FLG_PTRNUMCOMPARE, FLG_BOOLCOMPARE, FLG_UNSIGNEDCOMPARE,
+ FLG_MUTREP, FLG_NOEFFECT, FLG_IMPTYPE,
FLG_RETVALOTHER, FLG_RETVALBOOL, FLG_RETVALINT,
FLG_SPECUNDEF, FLG_INCONDEFS, FLG_INCONDEFSLIB, FLG_MISPLACEDSHAREQUAL,
FLG_MATCHFIELDS,
FLG_EXPORTLOCAL,
FLG_USERELEASED, FLG_ALIASUNIQUE, FLG_MAYALIASUNIQUE,
- FLG_MUSTFREE, FLG_MUSTDEFINE, FLG_GLOBSTATE,
+ FLG_MUSTFREEONLY,
+ FLG_MUSTFREEFRESH,
+ FLG_MUSTDEFINE, FLG_GLOBSTATE,
FLG_COMPDESTROY, FLG_MUSTNOTALIAS,
FLG_MEMIMPLICIT,
FLG_BRANCHSTATE,
FLG_MODGLOBS, FLG_WARNLINTCOMMENTS,
FLG_IFEMPTY, FLG_REALCOMPARE,
FLG_BOOLOPS, FLG_PTRNEGATE,
- FLG_SHIFTSIGNED,
+ FLG_SHIFTNEGATIVE,
+ FLG_SHIFTIMPLEMENTATION,
FLG_BUFFEROVERFLOWHIGH,
FLG_BUFFEROVERFLOW,
INVALID_FLAG
FLG_CHECKSTRICTGLOBALS, FLG_MACROMATCHNAME,
FLG_RETVALOTHER,
FLG_IFEMPTY,
+ FLG_BUFFEROVERFLOWHIGH,
FLG_RETSTACK, FLG_PTRNEGATE,
FLG_STATETRANSFER, FLG_STATEMERGE,
FLG_LONGUNSIGNEDINTEGRAL,
FLG_CHECKMODGLOBALIAS,
FLG_UNCHECKEDGLOBALIAS,
FLG_FORMATCONST,
+ FLG_STRINGLITNOROOM,
+ FLG_STRINGLITSMALLER,
FLG_EXITARG, FLG_PTRNUMCOMPARE,
- FLG_BOOLCOMPARE, FLG_MACROUNDEF,
- FLG_MUSTMOD, FLG_ALLGLOBALS,
+ FLG_BOOLCOMPARE, FLG_UNSIGNEDCOMPARE,
+ FLG_MACROUNDEF, FLG_MUSTMOD, FLG_ALLGLOBALS,
FLG_PREDBOOLOTHERS, FLG_PREDBOOLPTR, FLG_PREDBOOLINT,
FLG_USEALLGLOBS, FLG_MUTREP, FLG_RETALIAS,
FLG_RETEXPOSE, FLG_ASSIGNEXPOSE, FLG_CASTEXPOSE,
FLG_UNREACHABLE,
FLG_NORETURN, FLG_CASEBREAK, FLG_MISSCASE,
FLG_EVALORDER, FLG_USEDEF,
-
FLG_NESTEDEXTERN,
+ /* warn use flags */
+ FLG_MULTITHREADED, FLG_PORTABILITY, FLG_SUPERUSER, FLG_IMPLEMENTATIONOPTIONAL,
+ FLG_BUFFEROVERFLOWHIGH,
+
/* memchecks flags */
FLG_NULLSTATE, FLG_NULLDEREF, FLG_NULLASSIGN,
FLG_IMMEDIATETRANS,
FLG_ONLYUNQGLOBALTRANS,
FLG_USERELEASED, FLG_ALIASUNIQUE, FLG_MAYALIASUNIQUE,
- FLG_MUSTFREE, FLG_MUSTDEFINE, FLG_GLOBSTATE,
+ FLG_MUSTFREEONLY,
+ FLG_MUSTFREEFRESH,
+ FLG_MUSTDEFINE, FLG_GLOBSTATE,
FLG_COMPDESTROY, FLG_MUSTNOTALIAS,
FLG_MEMIMPLICIT,
FLG_BRANCHSTATE,
FLG_MACROMATCHNAME, FLG_WARNLINTCOMMENTS,
FLG_INCLUDENEST, FLG_ANSIRESERVED, FLG_CPPNAMES,
FLG_NOPARAMS, FLG_IFEMPTY, FLG_WHILEEMPTY, FLG_REALCOMPARE,
- FLG_BOOLOPS, FLG_SHIFTSIGNED,
+ FLG_BOOLOPS, FLG_SHIFTNEGATIVE,
+ FLG_SHIFTIMPLEMENTATION,
FLG_BUFFEROVERFLOWHIGH, FLG_BUFFEROVERFLOW,
INVALID_FLAG } ;
FLG_MODFILESYSTEM,
FLG_MACROMATCHNAME,
FLG_FORMATCONST,
+ FLG_STRINGLITNOROOM,
+ FLG_STRINGLITSMALLER,
FLG_STATETRANSFER, FLG_STATEMERGE,
FLG_MACROUNDEF, FLG_MUTREP, FLG_MUSTMOD,
FLG_ALLGLOBALS, FLG_IMPTYPE,
FLG_VARUNUSED,
FLG_NULLPOINTERARITH, FLG_POINTERARITH,
FLG_PTRNUMCOMPARE,
- FLG_BOOLCOMPARE, FLG_NOEFFECT,
- FLG_RETVALINT, FLG_RETVALBOOL, FLG_RETVALOTHER,
+ FLG_BOOLCOMPARE, FLG_UNSIGNEDCOMPARE,
+ FLG_NOEFFECT, FLG_RETVALINT, FLG_RETVALBOOL, FLG_RETVALOTHER,
FLG_ANSIRESERVED, FLG_ANSIRESERVEDLOCAL, FLG_CPPNAMES,
FLG_RETVALBOOL, FLG_RETVALINT, FLG_SPECUNDEF,
FLG_DECLUNDEF, FLG_STRICTOPS, FLG_INCONDEFS,
FLG_NESTEDEXTERN,
FLG_FIRSTCASE,
+ /* warn use flags */
+ FLG_MULTITHREADED, FLG_PORTABILITY, FLG_SUPERUSER, FLG_IMPLEMENTATIONOPTIONAL,
+ FLG_BUFFEROVERFLOWHIGH,
+ FLG_BUFFEROVERFLOW, FLG_TOCTOU,
+
/* memchecks flags */
FLG_NULLSTATE, FLG_NULLDEREF, FLG_NULLASSIGN,
FLG_NULLPASS, FLG_NULLRET,
FLG_UNKNOWNINITTRANS,
FLG_USERELEASED, FLG_ALIASUNIQUE, FLG_MAYALIASUNIQUE,
- FLG_MUSTFREE, FLG_MUSTDEFINE, FLG_GLOBSTATE,
+ FLG_MUSTFREEONLY,
+ FLG_MUSTFREEFRESH,
+ FLG_MUSTDEFINE, FLG_GLOBSTATE,
FLG_COMPDESTROY, FLG_MUSTNOTALIAS,
FLG_MEMIMPLICIT,
FLG_BRANCHSTATE,
FLG_REALCOMPARE, FLG_BOOLOPS,
FLG_SYSTEMDIRERRORS, FLG_UNUSEDSPECIAL,
- FLG_SHIFTSIGNED, FLG_BITWISEOPS,
+ FLG_SHIFTNEGATIVE,
+ FLG_SHIFTIMPLEMENTATION,
+ FLG_BITWISEOPS,
FLG_BUFFEROVERFLOWHIGH, FLG_BUFFEROVERFLOW,
INVALID_FLAG
} ;
bool
context_isSystemDir (cstring dir)
{
- cstring sysDirs = context_exposeString (FLG_SYSTEMDIRS);
- char *thisdir = cstring_toCharsSafe (sysDirs);
- char *nextdir = strchr (thisdir, SEPCHAR);
-
- if (nextdir != NULL)
+ cstring thisdir = cstring_copy (context_getString (FLG_SYSTEMDIRS));
+ cstring savedir = thisdir;
+ cstring nextdir = cstring_afterChar (thisdir, PATH_SEPARATOR);
+
+ if (cstring_isDefined (nextdir))
{
- *nextdir = '\0';
+ /*@access cstring@*/
+ *nextdir = '\0'; /* closes thisdir */
nextdir += 1;
+ /*@noaccess cstring@*/
}
- while (thisdir != NULL)
+ /* 2001-09-09: added thisdir[0] != '\0'
+ ** herbert: don't compare with an empty name!
+ ** should return false for empty directory path
+ */
+
+ while (!cstring_isEmpty (thisdir))
{
DPRINTF (("Test: %s / %s", dir, thisdir));
- if (cstring_equalCanonicalPrefix (dir, thisdir))
+ if (osd_equalCanonicalPrefix (dir, thisdir))
{
- if (nextdir != NULL)
- {
- *(nextdir - 1) = SEPCHAR;
- }
-
+ cstring_free (savedir);
return TRUE;
}
- if (nextdir != NULL)
- {
- *(nextdir - 1) = SEPCHAR;
- }
-
- if (nextdir != NULL)
+ if (cstring_isDefined (nextdir))
{
thisdir = nextdir;
- nextdir = strchr (thisdir, SEPCHAR);
+ nextdir = cstring_afterChar (thisdir, PATH_SEPARATOR);
- if (nextdir != NULL)
+ if (cstring_isDefined (nextdir))
{
+ /*@access cstring@*/
*nextdir = '\0';
nextdir += 1;
+ /*@noaccess cstring@*/
}
}
else
}
DPRINTF (("Returns FALSE"));
+ cstring_free (savedir);
return FALSE;
}
void context_enterFunctionHeader (void)
{
+ if (context_getFlag (FLG_GRAMMAR))
+ {
+ lldiagmsg (message ("Enter function header: %q", context_unparse ()));
+ }
+
if (gc.kind != CX_GLOBAL)
{
llparseerror (cstring_makeLiteral
void context_exitFunctionHeader (void)
{
+ if (context_getFlag (FLG_GRAMMAR))
+ {
+ lldiagmsg (message ("Exit function header: %q", context_unparse ()));
+ }
+
DPRINTF (("Exit function header!"));
gc.inFunctionHeader = FALSE;
}
void context_enterFunctionDeclaration (uentry e)
{
+ if (context_getFlag (FLG_GRAMMAR))
+ {
+ lldiagmsg (message ("Enter function declaration: %q", context_unparse ()));
+ }
+
DPRINTF (("Enter function decl"));
llassert (gc.savekind == CX_ERROR);
gc.savekind = gc.kind;
+ gc.savecont = gc.cont;
gc.kind = CX_FCNDECLARATION;
gc.cont.fcn = e;
}
void context_exitFunctionDeclaration (void)
{
+ if (context_getFlag (FLG_GRAMMAR))
+ {
+ lldiagmsg (message ("Exit function declaration: %q", context_unparse ()));
+ }
+
DPRINTF (("Exit function decl"));
llassert (gc.savekind != CX_ERROR);
llassert (gc.kind == CX_FCNDECLARATION);
gc.kind = gc.savekind;
- gc.cont.fcn = uentry_undefined;
+ gc.cont = gc.savecont;
+
gc.savekind = CX_ERROR;
+
+ if (context_getFlag (FLG_GRAMMAR))
+ {
+ lldiagmsg (message ("After exit function declaration: %q", context_unparse ()));
+ }
}
bool context_inFunctionDeclaration (void)
sRef_enterFunctionScope ();
}
+void
+context_enterOldStyleScope (void)
+{
+ gc.kind = CX_OLDSTYLESCOPE;
+ DPRINTF (("Enter old style scope!"));
+ usymtab_enterFunctionScope (uentry_undefined);
+}
+
+void
+context_completeOldStyleFunction (uentry e)
+{
+ llassert (gc.kind == CX_OLDSTYLESCOPE);
+
+ gc.kind = CX_FUNCTION;
+ gc.cont.fcn = e;
+
+ DPRINTF (("Enter function: %s", uentry_unparse (e)));
+
+ if (uentry_hasAccessType (e))
+ {
+ gc.acct = typeIdSet_subtract (typeIdSet_union (gc.facct, uentry_accessType (e)),
+ gc.nacct);
+ }
+ else
+ {
+ gc.acct = gc.facct;
+ }
+
+ DPRINTF (("Enter function: %s / %s", uentry_unparse (e),
+ typeIdSet_unparse (gc.acct)));
+
+ gc.showfunction = context_getFlag (FLG_SHOWFUNC);
+
+ if (!globSet_isEmpty (uentry_getGlobs (e)))
+ {
+ llfatalerror (message ("%q: Old-style function declaration uses a clause (rewrite with function parameters): %q",
+ fileloc_unparse (g_currentloc), uentry_unparse (e)));
+ }
+
+ gc.showfunction = context_getFlag (FLG_SHOWFUNC);
+
+ gc.globs = uentry_getGlobs (e);
+ globSet_clear (gc.globs_used);
+
+ gc.mods = uentry_getMods (e);
+
+ if (!sRefSet_isEmpty (gc.mods))
+ {
+ llfatalerror (message ("%q: Old-style function declaration uses a clause (rewrite with function parameters): %q",
+ fileloc_unparse (g_currentloc), uentry_unparse (e)));
+ }
+
+ sRef_enterFunctionScope ();
+}
+
static bool context_checkStrictGlobals (void)
{
return (context_getFlag (FLG_CHECKSTRICTGLOBALS));
context_setJustPopped ();
- if (context_getFlag (FLG_LOOPEXEC))
+ if (context_getFlag (FLG_ITERLOOPEXEC))
{
usymtab_popTrueExecBranch (exprNode_undefined, body, ITERCLAUSE);
}
** predicate must be false after while loop (unless there are breaks)
*/
- if (context_getFlag (FLG_LOOPEXEC))
+ if (context_getFlag (FLG_WHILELOOPEXEC))
{
usymtab_popTrueExecBranch (pred, body, WHILECLAUSE);
}
llassert (gc.inclause == FORCLAUSE);
context_setJustPopped ();
+ DPRINTF (("Exit for: %s / %s", exprNode_unparse (forPred), exprNode_unparse (body)));
+
/*
- ** predicate must be false after while loop (unless there are breaks)
+ ** Predicate must be false after for loop (unless there are breaks)
*/
- if (context_getFlag (FLG_LOOPEXEC))
+ if (context_getFlag (FLG_FORLOOPEXEC))
{
+ DPRINTF (("Here: for loop exec"));
usymtab_popTrueExecBranch (forPred, body, FORCLAUSE);
}
else
{
- usymtab_popTrueBranch (forPred, body, FORCLAUSE);
+ if (context_getFlag (FLG_OBVIOUSLOOPEXEC)
+ && exprNode_loopMustExec (forPred))
+ {
+ DPRINTF (("Here: loop must exec"));
+ usymtab_popTrueExecBranch (forPred, body, FORCLAUSE);
+ }
+ else
+ {
+ DPRINTF (("Pop true branch:"));
+ usymtab_popTrueBranch (forPred, body, FORCLAUSE);
+ }
}
usymtab_addGuards (invGuards);
void
context_exitFunction (void)
{
+ DPRINTF (("Exit function: %s", context_unparse ()));
+
if (!context_inFunction () && !context_inMacroConstant ()
- && !context_inMacroUnknown ()
+ && !context_inUnknownMacro ()
&& !context_inIterDef () && !context_inIterEnd ())
{
/*
** not a bug because of parse errors
*/
+
+ BADBRANCH;
}
else
{
llassert (clauseStack_isEmpty (gc.clauses));
llassert (gc.inclause == NOCLAUSE);
+ DPRINTF (("After exit function: %s", context_unparse ()));
}
void
context_exitInnerPlain ();
}
- if (!context_inFunction () && !context_inMacroConstant () && !context_inMacroUnknown ()
+ if (!context_inFunction () && !context_inMacroConstant () && !context_inUnknownMacro ()
&& !context_inIterDef () && !context_inIterEnd ())
{
}
case FLG_INDENTSPACES:
if (val < 0)
{
-
llerror_flagWarning (message ("Value for %s must be a non-negative "
- "number (given %d)",
- flagcode_unparse (flag), val));
+ "number (given %d)",
+ flagcode_unparse (flag), val));
return;
}
default:
break;
}
-
+
+ DPRINTF (("Set value [%s] %d = %d", flagcode_unparse (flag), index, val));
gc.values[index] = val;
}
int index = flagcode_valueIndex (flag);
llassert (index >= 0 && index <= NUMVALUEFLAGS);
+ DPRINTF (("Get value [%s] %d = %d", flagcode_unparse (flag), index, gc.values[index]));
return (gc.values[index]);
}
}
if (cstring_length (val) >= 1
- && cstring_firstChar (val) == '"')
+ && cstring_firstChar (val) == '\"')
{
llerror_flagWarning (message
("setting %s to string beginning with \". You probably "
/*@globals undef gc; @*/
{
gc.kind = CX_GLOBAL;
+
gc.savekind = CX_ERROR;
+ gc.savecont.glob = FALSE;
+
gc.instandardlib = FALSE;
gc.numerrors = 0;
gc.neednl = FALSE;
{
gc.setGlobally[code] = FALSE;
gc.setLocally[code] = FALSE;
- } end_allFlagCodes ;
-
+ }
+ end_allFlagCodes ;
+
usymtab_initMod ();
context_resetAllFlags ();
+
assertSet (gc.flags); /* Can't use global in defines */
assertSet (gc.saveflags);
assertSet (gc.values);
assertSet (gc.strings);
-
+
conext_resetAllCounters ();
assertSet (gc.counters);
s = message ("Global Context:%q", fileloc_unparse (g_currentloc));
break;
case CX_INNER:
- s = message ("Inner Context:%q", fileloc_unparse (g_currentloc));
+ s = message ("Inner Context [%d] : %q",
+ gc.cont.cdepth,
+ fileloc_unparse (g_currentloc));
break;
case CX_FUNCTION:
s = message ("Function %q :%q \n\taccess %q\n\tmodifies %q",
case CX_ITEREND:
s = message ("Iter end %q", uentry_unparse (gc.cont.fcn));
break;
+ case CX_FCNDECLARATION:
+ s = message ("Function declaration %q", uentry_unparse (gc.cont.fcn));
+ break;
default:
s = message ("Un-unparseable context: %d", (int) gc.kind);
break;
void
context_enterInnerContext (void)
{
+ if (context_getFlag (FLG_GRAMMAR))
+ {
+ lldiagmsg (message ("Enter inner context: %q", context_unparse ()));
+ }
+
if (gc.kind == CX_GLOBAL)
{
gc.kind = CX_INNER;
;
}
-
usymtab_enterScope ();
pushClause (NOCLAUSE);
}
void
context_exitInner (exprNode exp)
{
-
+ if (context_getFlag (FLG_GRAMMAR))
+ {
+ lldiagmsg (message ("Enter inner context: %q", context_unparse ()));
+ }
+
llassertprint (gc.inclause == NOCLAUSE || gc.inclause == CASECLAUSE,
("inclause = %s", clause_nameTaken (gc.inclause)));
void
context_enterStructInnerContext (void)
{
+ if (context_getFlag (FLG_GRAMMAR))
+ {
+ lldiagmsg (message ("Enter struct inner context: %q", context_unparse ()));
+ }
+
if (gc.kind == CX_GLOBAL)
{
gc.kind = CX_INNER;
}
usymtab_enterScope ();
+
+ if (context_getFlag (FLG_GRAMMAR))
+ {
+ lldiagmsg (message ("Enter struct inner context: %q", context_unparse ()));
+ }
}
void
context_exitStructInnerContext (void)
{
+ if (context_getFlag (FLG_GRAMMAR))
+ {
+ lldiagmsg (message ("Exit struct inner context: %q [%d]", context_unparse (), gc.cont.cdepth));
+ }
+
if (gc.kind == CX_INNER)
{
- if (--gc.cont.cdepth == 0)
+ if (gc.cont.cdepth <= 0)
{
+ llcontbuglit ("Attempt to exit inner context with no depth");
gc.kind = CX_GLOBAL;
gc.cont.glob = TRUE;
+ gc.cont.cdepth = 0;
}
+ else {
+ gc.cont.cdepth--;
+
+ if (gc.cont.cdepth == 0)
+ {
+ gc.kind = CX_GLOBAL;
+ gc.cont.glob = TRUE;
+ }
+ }
}
else
{
}
usymtab_exitScope (exprNode_undefined);
+
+ if (context_getFlag (FLG_GRAMMAR))
+ {
+ lldiagmsg (message ("After exit struct inner context: %q [%d]", context_unparse (), gc.cont.cdepth));
+ }
}
void
context_exitInnerSafe (void)
{
-
+ if (context_getFlag (FLG_GRAMMAR))
+ {
+ lldiagmsg (message ("Exit inner safe: %q", context_unparse ()));
+ }
+
if (gc.kind == CX_INNER)
{
- if (--gc.cont.cdepth == 0)
+ if (--gc.cont.cdepth <= 0)
{
- gc.cont.cdepth++;
+ gc.cont.cdepth = 0;
}
}
else if (gc.kind == CX_GLOBAL)
context_saveLocation (void)
{
/* was llassert (fileloc_isUndefined (gc.saveloc)) */
- fileloc_free (gc.saveloc);
-
-
+ fileloc_free (gc.saveloc);
gc.saveloc = fileloc_copy (g_currentloc);
- }
+}
fileloc
context_getSaveLocation (void)
{
fileloc fl = gc.saveloc;
-
- gc.saveloc = fileloc_undefined;
+ gc.saveloc = fileloc_undefined;
return fl;
}
gc.flags[ff] = b; } while (FALSE)
static void
- context_setFlagAux (flagcode f, bool b, bool
- inFile, /*@unused@*/ bool isRestore)
+context_setFlagAux (flagcode f, bool b, bool inFile,
+ /*@unused@*/ bool isRestore)
{
- DPRINTF (("set flag: %s / %s", flagcode_unparse (f), bool_unparse (b)));
+ DPRINTF (("Set flag: %s / %s", flagcode_unparse (f), bool_unparse (b)));
if (f == FLG_USESTDERR)
{
DOSET (FLG_SPECRETIMPONLY, b);
DOSET (FLG_SPECSTRUCTIMPONLY, b);
break;
- case FLG_ANSILIMITS:
- DOSET (FLG_ANSILIMITS, b);
+ case FLG_ANSI89LIMITS:
+ DOSET (FLG_ANSI89LIMITS, b);
DOSET (FLG_CONTROLNESTDEPTH, b);
DOSET (FLG_STRINGLITERALLEN, b);
DOSET (FLG_INCLUDENEST, b);
if (b)
{
- context_setValue (FLG_CONTROLNESTDEPTH, DEFAULT_CONTROLNESTDEPTH);
- context_setValue (FLG_STRINGLITERALLEN, DEFAULT_STRINGLITERALLEN);
- context_setValue (FLG_INCLUDENEST, DEFAULT_INCLUDENEST);
- context_setValue (FLG_NUMSTRUCTFIELDS, DEFAULT_NUMSTRUCTFIELDS);
- context_setValue (FLG_NUMENUMMEMBERS, DEFAULT_NUMENUMMEMBERS);
+ context_setValue (FLG_CONTROLNESTDEPTH, ANSI89_CONTROLNESTDEPTH);
+ context_setValue (FLG_STRINGLITERALLEN, ANSI89_STRINGLITERALLEN);
+ context_setValue (FLG_INCLUDENEST, ANSI89_INCLUDENEST);
+ context_setValue (FLG_NUMSTRUCTFIELDS, ANSI89_NUMSTRUCTFIELDS);
+ context_setValue (FLG_NUMENUMMEMBERS, ANSI89_NUMENUMMEMBERS);
+ context_setValue (FLG_EXTERNALNAMELEN, ANSI89_EXTERNALNAMELEN);
+ context_setValue (FLG_INTERNALNAMELEN, ANSI89_INTERNALNAMELEN);
+ }
+ break;
+ case FLG_ISO99LIMITS:
+ DOSET (FLG_ISO99LIMITS, b);
+ DOSET (FLG_CONTROLNESTDEPTH, b);
+ DOSET (FLG_STRINGLITERALLEN, b);
+ DOSET (FLG_INCLUDENEST, b);
+ DOSET (FLG_NUMSTRUCTFIELDS, b);
+ DOSET (FLG_NUMENUMMEMBERS, b);
+
+ if (b)
+ {
+ context_setValue (FLG_CONTROLNESTDEPTH, ISO99_CONTROLNESTDEPTH);
+ context_setValue (FLG_STRINGLITERALLEN, ISO99_STRINGLITERALLEN);
+ context_setValue (FLG_INCLUDENEST, ISO99_INCLUDENEST);
+ context_setValue (FLG_NUMSTRUCTFIELDS, ISO99_NUMSTRUCTFIELDS);
+ context_setValue (FLG_NUMENUMMEMBERS, ISO99_NUMENUMMEMBERS);
+ context_setValue (FLG_EXTERNALNAMELEN, ISO99_EXTERNALNAMELEN);
+ context_setValue (FLG_INTERNALNAMELEN, ISO99_INTERNALNAMELEN);
}
break;
case FLG_EXTERNALNAMELEN:
DOSET (FLG_LOOPLOOPCONTINUE, b);
DOSET (FLG_DEEPBREAK, b);
break;
+ case FLG_LOOPEXEC:
+ DOSET (FLG_FORLOOPEXEC, b);
+ DOSET (FLG_WHILELOOPEXEC, b);
+ DOSET (FLG_ITERLOOPEXEC, b);
+ break;
case FLG_ACCESSALL:
DOSET (FLG_ACCESSMODULE, b);
DOSET (FLG_ACCESSFILE, b);
DOSET (FLG_FCNMACROS, b);
DOSET (FLG_CONSTMACROS, b);
break;
+ case FLG_BOUNDS:
+ DOSET (FLG_BOUNDSREAD, b);
+ DOSET (FLG_BOUNDSWRITE, b);
+ break;
case FLG_CZECH:
if (b) { DOSET (FLG_ACCESSCZECH, b); }
DOSET (FLG_CZECHFUNCTIONS, b);
DOSET (FLG_NULLPASS, b);
DOSET (FLG_NULLRET, b);
break;
+ case FLG_MUSTFREE:
+ DOSET (FLG_MUSTFREEONLY, b);
+ DOSET (FLG_MUSTFREEFRESH, b);
+ break;
case FLG_MEMCHECKS:
DOSET (FLG_NULLSTATE, b);
DOSET (FLG_NULLDEREF, b);
DOSET (FLG_USERELEASED, b);
DOSET (FLG_ALIASUNIQUE, b);
DOSET (FLG_MAYALIASUNIQUE, b);
- DOSET (FLG_MUSTFREE, b);
+ DOSET (FLG_MUSTFREEONLY, b);
+ DOSET (FLG_MUSTFREEFRESH, b);
DOSET (FLG_MUSTDEFINE, b);
DOSET (FLG_GLOBSTATE, b);
DOSET (FLG_COMPDESTROY, b);
void context_enterIterDef (/*@observer@*/ uentry le)
{
- context_enterMacro (le);
+ context_enterMacro (le);
gc.acct = typeIdSet_subtract (gc.facct, gc.nacct);
gc.kind = CX_ITERDEF;
}
void context_enterIterEnd (/*@observer@*/ uentry le)
{
- context_enterMacro (le);
+ context_enterMacro (le);
gc.kind = CX_ITEREND;
}
void context_hasError (void)
{
gc.numerrors++;
+ DPRINTF (("num errors: %d", gc.numerrors));
}
int context_numErrors (void)
return (gc.kind == CX_MACROCONST);
}
-bool context_inMacroUnknown (void)
+bool context_inUnknownMacro (void)
{
return (gc.kind == CX_UNKNOWNMACRO);
}
return (gc.kind == CX_GLOBAL);
}
+static void context_quietExitScopes (void)
+{
+ /*
+ ** Try to restore the global scope (after an error).
+ */
+
+ while (!usymtab_inFileScope ())
+ {
+ usymtab_quietExitScope (g_currentloc);
+ }
+
+ gc.cont.glob = TRUE;
+ gc.kind = CX_GLOBAL;
+}
+
+void context_checkGlobalScope (void)
+{
+ if (gc.kind != CX_GLOBAL)
+ {
+ if (context_inMacro ())
+ {
+ ; /* evans 2001-10-14: Okay to be in a macro here! */
+ }
+ else
+ {
+ llcontbug (message ("Not in global scope as expected: %q", context_unparse ()));
+ context_quietExitScopes ();
+ }
+ }
+}
+
void context_setFileId (fileId s)
{
g_currentloc = fileloc_updateFileId (g_currentloc, s);
}
}
-valueTable context_createValueTable (sRef s)
+valueTable context_createValueTable (sRef s, stateInfo sinfo)
{
if (metaStateTable_size (gc.stateTable) > 0)
{
valueTable_insert
(res,
cstring_copy (metaStateInfo_getName (msi)),
- stateValue_createImplicit (metaStateInfo_getDefaultValue (msi, s),
- stateInfo_undefined));
+ stateValue_createImplicit (metaStateInfo_getDefaultValue (msi, s),
+ stateInfo_copy (sinfo)));
}
else
{
}
end_metaStateTable_elements ;
+ stateInfo_free (sinfo);
DPRINTF (("Value table: %s", valueTable_unparse (res)));
return res;
}
else
{
+ stateInfo_free (sinfo);
return valueTable_undefined;
}
}
-valueTable context_createGlobalMarkerValueTable ()
+valueTable context_createGlobalMarkerValueTable (stateInfo sinfo)
{
if (metaStateTable_size (gc.stateTable) > 0)
{
valueTable_insert (res,
cstring_copy (metaStateInfo_getName (msi)),
stateValue_create (metaStateInfo_getDefaultGlobalValue (msi),
- stateInfo_undefined));
+ stateInfo_copy (sinfo)));
}
end_metaStateTable_elements ;
+ stateInfo_free (sinfo);
DPRINTF (("Value table: %s", valueTable_unparse (res)));
return res;
}
else
{
+ stateInfo_free (sinfo);
return valueTable_undefined;
}
}
+/*drl 12/30/01 these are some ugly functions that were added to facilitate struct annotations */
+
+
+/*drl added */
+static ctype lastStruct;
+
+ctype context_setLastStruct (/*@returned@*/ ctype s) /*@globals lastStruct@*/
+{
+ lastStruct = s;
+ return s;
+}
+
+ctype context_getLastStruct (/*@returned@*/ /*ctype s*/) /*@globals lastStruct@*/
+{
+ return lastStruct;
+}
+
+
+/*@unused@*/ static int sInfoNum = 0;
+
+
+struct getUe {
+ /*@unused@*/ uentry ue;
+ /*@unused@*/ sRef s;
+};
+
+struct sInfo {
+ /*@unused@*/ ctype ct;
+ /*@unused@*/ constraintList inv;
+ /*@unused@*/ int ngetUe;
+ /*@unused@*/ struct getUe * t ;
+};
+
+
+static struct sInfo globalStructInfo;
+
+
+/*drl 1/6/2001: I didn't think these functions were solid enough to include in the
+ stable release of splint. I coomented them out so that they won't break anything
+ but didn't delete them because they will be fixed and included later
+*/
+
+/*
+void setGlobalStructInfo(ctype ct, constraintList list)
+{
+ int i;
+ uentryList f;
+
+ f = ctype_getFields (ct);
+
+ if (constraintList_isDefined(list) )
+ {
+ globalStructInfo.ct = ct;
+ globalStructInfo.inv = list;
+
+ globalStructInfo.ngetUe = 0;
+
+ / *abstraction violation fix it * /
+ globalStructInfo.t = dmalloc(f->nelements * sizeof(struct getUe) );
+
+ globalStructInfo.ngetUe = f->nelements;
+
+ i = 0;
+
+ uentryList_elements(f, ue)
+ {
+ globalStructInfo.t[i].ue = ue;
+ globalStructInfo.t[i].s = uentry_getSref(ue);
+ TPRINTF(( message(" setGlobalStructInfo:: adding ue=%s and sRef=%s",
+ uentry_unparse(ue), sRef_unparse( uentry_getSref(ue) )
+ )
+ ));
+ i++;
+ }
+ end_uentryList_elements;
+ }
+}
+
+*/
+
+bool hasInvariants (ctype ct) /*@*/
+{
+ if ( ctype_sameName(globalStructInfo.ct, ct) )
+
+ return TRUE;
+
+ else
+
+ return FALSE;
+
+}
+
+/*drl 1/6/2001: I didn't think these functions were solid enough to include in the
+ stable release of splint. I coomented them out so that they won't break anything
+ but didn't delete them because they will be fixed and included later
+*/
+
+/*
+constraintList getInvariants (ctype ct)
+{
+
+ llassert(hasInvariants(ct) );
+
+ return globalStructInfo.inv;
+}
+*/
+
+/*
+static int getSref (ctype ct, sRef s)
+{
+ int i;
+
+ i = 0;
+
+ / *
+ DEBUGGIN INFO
+
+ fprintf(stderr, "getSref: ct = %s (%x)\n", ctype_unparse(ct), ct );
+
+ fprintf(stderr,"getSref: s = (%s) %X \n", sRef_unparse(s), s);
+ * /
+
+ while (i < globalStructInfo.ngetUe)
+ {
+ DPRINTF(( message(" getSref:: comparing ue=%s and sRef=%s",
+ uentry_unparse(globalStructInfo.t[i].ue),
+ sRef_unparse(globalStructInfo.t[i].s)
+ )
+ ));
+
+ / *
+ fprintf (stderr, " globalStructInfo.t[i].s = %x\n ",
+ globalStructInfo.t[i].s );
+ * /
+
+ if (sRef_same(globalStructInfo.t[i].s,s) )
+ return i;
+
+ i++;
+ }
+ return -1;
+}
+
+
+sRef fixSref (ctype ct, sRef base, sRef fix)
+{
+ int index;
+ uentry ue;
+ cstring name;
+ index = getSref(ct, fix);
+
+ if (index < 0)
+ return fix;
+
+ ue = globalStructInfo.t[index].ue;
+ name = uentry_getName(ue);
+ fix = sRef_buildField(base, name );
+ cstring_free(name);
+ return fix;
+}
+
+*/