X-Git-Url: http://andersk.mit.edu/gitweb/splint.git/blobdiff_plain/3120b46202eb0e24e26bafc9c49cdad77a6ba32c..73441cf5bc8a5de8673dd8652956875e14682944:/src/context.c diff --git a/src/context.c b/src/context.c index 446faae..86b6af9 100644 --- a/src/context.c +++ b/src/context.c @@ -35,7 +35,6 @@ # include "lclintMacros.nf" # include "llbasic.h" -# include "mtincludes.h" # ifndef NOLCL # include "usymtab_interface.h" @@ -64,7 +63,8 @@ typedef enum { 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; @@ -135,7 +135,6 @@ static struct /*@reldef@*/ maccesst *moduleaccess; /* Not defined is nmods == 0. */ kcontext kind; - kcontext savekind; ctype boolType; @@ -152,12 +151,15 @@ static struct 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) ; @@ -822,6 +824,11 @@ context_resetAllFlags (void) 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; @@ -970,17 +977,19 @@ context_setMode (cstring s) 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, @@ -1056,6 +1065,7 @@ context_setMode (cstring s) FLG_CHECKSTRICTGLOBALS, FLG_MACROMATCHNAME, FLG_RETVALOTHER, FLG_IFEMPTY, + FLG_BUFFEROVERFLOWHIGH, FLG_RETSTACK, FLG_PTRNEGATE, FLG_STATETRANSFER, FLG_STATEMERGE, FLG_LONGUNSIGNEDINTEGRAL, @@ -1080,9 +1090,11 @@ context_setMode (cstring s) 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, @@ -1111,6 +1123,10 @@ context_setMode (cstring s) FLG_NESTEDEXTERN, + /* warn use flags */ + FLG_MULTITHREADED, FLG_PORTABILITY, FLG_SUPERUSER, FLG_IMPLEMENTATIONOPTIONAL, + FLG_BUFFEROVERFLOWHIGH, + /* memchecks flags */ FLG_NULLSTATE, FLG_NULLDEREF, FLG_NULLASSIGN, @@ -1167,6 +1183,8 @@ context_setMode (cstring s) FLG_MODFILESYSTEM, FLG_MACROMATCHNAME, FLG_FORMATCONST, + FLG_STRINGLITNOROOM, + FLG_STRINGLITSMALLER, FLG_STATETRANSFER, FLG_STATEMERGE, FLG_MACROUNDEF, FLG_MUTREP, FLG_MUSTMOD, FLG_ALLGLOBALS, FLG_IMPTYPE, @@ -1191,8 +1209,8 @@ context_setMode (cstring s) 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, @@ -1214,6 +1232,11 @@ context_setMode (cstring s) 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, @@ -1295,44 +1318,44 @@ context_isSpecialFile (cstring fname) 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 @@ -1342,6 +1365,7 @@ context_isSystemDir (cstring dir) } DPRINTF (("Returns FALSE")); + cstring_free (savedir); return FALSE; } @@ -1378,6 +1402,11 @@ context_removeFileAccessType (typeId t) 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 @@ -1393,6 +1422,11 @@ void context_enterFunctionHeader (void) void context_exitFunctionHeader (void) { + if (context_getFlag (FLG_GRAMMAR)) + { + lldiagmsg (message ("Exit function header: %q", context_unparse ())); + } + DPRINTF (("Exit function header!")); gc.inFunctionHeader = FALSE; } @@ -1404,21 +1438,38 @@ bool context_inFunctionHeader (void) 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) @@ -1760,6 +1811,61 @@ context_enterFunction (/*@exposed@*/ uentry e) 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)); @@ -2306,13 +2412,17 @@ context_returnFunction (void) 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 { @@ -2357,6 +2467,7 @@ context_exitFunction (void) llassert (clauseStack_isEmpty (gc.clauses)); llassert (gc.inclause == NOCLAUSE); + DPRINTF (("After exit function: %s", context_unparse ())); } void @@ -2367,7 +2478,7 @@ context_quietExitFunction (void) context_exitInnerPlain (); } - if (!context_inFunction () && !context_inMacroConstant () && !context_inMacroUnknown () + if (!context_inFunction () && !context_inMacroConstant () && !context_inUnknownMacro () && !context_inIterDef () && !context_inIterEnd ()) { } @@ -2746,7 +2857,7 @@ context_setString (flagcode flag, cstring val) } if (cstring_length (val) >= 1 - && cstring_firstChar (val) == '"') + && cstring_firstChar (val) == '\"') { llerror_flagWarning (message ("setting %s to string beginning with \". You probably " @@ -2787,7 +2898,10 @@ void context_initMod (void) /*@globals undef gc; @*/ { gc.kind = CX_GLOBAL; + gc.savekind = CX_ERROR; + gc.savecont.glob = FALSE; + gc.instandardlib = FALSE; gc.numerrors = 0; gc.neednl = FALSE; @@ -2918,7 +3032,9 @@ context_unparse (void) 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", @@ -2942,6 +3058,9 @@ context_unparse (void) 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; @@ -2974,6 +3093,11 @@ context_currentFunctionType (void) 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; @@ -2988,7 +3112,6 @@ context_enterInnerContext (void) ; } - usymtab_enterScope (); pushClause (NOCLAUSE); } @@ -3002,7 +3125,11 @@ context_exitInnerPlain (void) /*@modifies gc;@*/ 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))); @@ -3033,6 +3160,11 @@ context_exitInner (exprNode exp) 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; @@ -3048,18 +3180,39 @@ context_enterStructInnerContext (void) } 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 { @@ -3071,17 +3224,26 @@ context_exitStructInnerContext (void) } 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) @@ -3345,18 +3507,15 @@ void 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; } @@ -3939,14 +4098,14 @@ void context_setFilename (fileId fid, int lineno) 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; } @@ -4058,6 +4217,7 @@ bool context_anyErrors (void) void context_hasError (void) { gc.numerrors++; + DPRINTF (("num errors: %d", gc.numerrors)); } int context_numErrors (void) @@ -4157,7 +4317,7 @@ bool context_inMacroConstant (void) return (gc.kind == CX_MACROCONST); } -bool context_inMacroUnknown (void) +bool context_inUnknownMacro (void) { return (gc.kind == CX_UNKNOWNMACRO); } @@ -4253,6 +4413,37 @@ bool context_inGlobalContext (void) 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); @@ -4390,7 +4581,7 @@ void context_addMetaState (cstring mname, metaStateInfo msinfo) } } -valueTable context_createValueTable (sRef s) +valueTable context_createValueTable (sRef s, stateInfo sinfo) { if (metaStateTable_size (gc.stateTable) > 0) { @@ -4410,8 +4601,8 @@ valueTable context_createValueTable (sRef s) 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 { @@ -4420,16 +4611,18 @@ valueTable context_createValueTable (sRef s) } 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) { @@ -4445,15 +4638,17 @@ valueTable context_createGlobalMarkerValueTable () 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; } }