# include "lclintMacros.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) ;
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;
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_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_NESTEDEXTERN,
+ /* warn use flags */
+ FLG_MULTITHREADED, FLG_PORTABILITY, FLG_SUPERUSER, FLG_IMPLEMENTATIONOPTIONAL,
+ FLG_BUFFEROVERFLOWHIGH,
+
/* memchecks flags */
FLG_NULLSTATE, FLG_NULLDEREF, FLG_NULLASSIGN,
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,
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));
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 ())
{
}
}
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;
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;
}
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;
}
}