X-Git-Url: http://andersk.mit.edu/gitweb/splint.git/blobdiff_plain/b072092f32623dab70e6ffe1613740542ea66748..061ece7d6fedbde47030222fea74b575c12707dc:/src/clabstract.c diff --git a/src/clabstract.c b/src/clabstract.c index e0f0c6f..3bf4168 100644 --- a/src/clabstract.c +++ b/src/clabstract.c @@ -1,6 +1,6 @@ /* -** LCLint - annotation-assisted static program checker -** Copyright (C) 1994-2001 University of Virginia, +** Splint - annotation-assisted static program checker +** Copyright (C) 1994-2003 University of Virginia, ** Massachusetts Institute of Technology ** ** This program is free software; you can redistribute it and/or modify it @@ -17,9 +17,9 @@ ** 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 */ /* ** clabstract.c @@ -28,17 +28,16 @@ ** */ -# include "lclintMacros.nf" -# include "llbasic.h" +# include "splintMacros.nf" +# include "basic.h" # include "cgrammar.h" - -# ifndef NOLCL # include "usymtab_interface.h" -# endif # include "structNames.h" # include "nameChecks.h" +# include "cscannerHelp.h" + # ifdef SANITIZER # include "sgrammar_tokens.h" # else @@ -51,19 +50,18 @@ ** right values are available in the right place. */ -/*drl */ -static /*@only@*/ constraintList implicitFcnConstraints = NULL; - - -//static constraintList fcnPreConditions = NULL; +/*drl*/ +static /*@only@*/ constraintList implicitFcnConstraints = NULL; static void clabstract_prepareFunction (uentry p_e) /*@modifies p_e@*/ ; static bool fcnNoGlobals = FALSE; -static bool ProcessingVars = FALSE; -static bool ProcessingParams = FALSE; -static bool ProcessingGlobals = FALSE; -static bool ProcessingTypedef = FALSE; -static bool ProcessingIterVars = FALSE; +static void processVariable (/*@temp@*/ idDecl p_t) /*@modifies internalState@*/ ; + +static bool s_processingVars = FALSE; +static bool s_processingParams = FALSE; +static bool s_processingGlobals = FALSE; +static bool s_processingTypedef = FALSE; +static bool s_processingIterVars = FALSE; static /*@only@*/ qtype processingType = qtype_undefined; static uentry currentIter = uentry_undefined; static /*@dependent@*/ uentryList saveParamList; /* for old style functions */ @@ -299,13 +297,13 @@ extern void declareCIter (cstring name, /*@owned@*/ uentryList params) extern void nextIterParam (void) { - llassert (ProcessingIterVars); + llassert (s_processingIterVars); saveIterParamNo++; } extern int iterParamNo (void) { - llassert (ProcessingIterVars); + llassert (s_processingIterVars); return saveIterParamNo; } @@ -496,49 +494,79 @@ declareEnumList (enumNameList el, ctype c, fileloc loc) static /*@dependent@*/ uentryList currentParamList; -/*drl added 3-28-2001*/ +/*drl added 3-28-2002*/ /* this function takes a list of paramentar and generates a list of constraints. - Currently the only constraints gnerated are MaxSet(p) >= 0 for all pointers */ -void setImplictfcnConstraints (void) +/* drl modified 10/23/2002 + +The current semantics are generated constraints of the form MaxSet(p) >= 0 and MaxRead(p) >= 0 for all pointers +unless the @out@ annotation has been applied to a parameter, then we only want to generate maxSet(p) > = 0 +*/ + +void setImplicitfcnConstraints (void) { uentryList params; sRef s; constraint c; params = currentParamList; - if (constraintList_isDefined(implicitFcnConstraints) ) - constraintList_free(implicitFcnConstraints); - - implicitFcnConstraints = constraintList_makeNew(); + if (constraintList_isDefined (implicitFcnConstraints)) + { + constraintList_free (implicitFcnConstraints); + } + + implicitFcnConstraints = constraintList_makeNew(); uentryList_elements (params, el) { - DPRINTF((message("setImplictfcnConstraints doing: %s", uentry_unparse(el) ) )); + DPRINTF (("setImplicitfcnConstraints doing: %s", uentry_unparse(el))); - s = uentry_getSref(el); - if (sRef_isReference (s) ) + if (uentry_isVariable (el)) + { + s = uentry_getSref(el); + + if (sRef_isReference (s)) + { + DPRINTF((message ("%s is a pointer", sRef_unparse(s) ) )); + /*drl 4/26/01 + chagned this from MaxSet(s) == 0 to MaxSet(s) >= 0 */ + c = constraint_makeSRefWriteSafeInt (s, 0); + + implicitFcnConstraints = constraintList_add (implicitFcnConstraints , c); + + /*drl 10/23/2002 added support for out*/ + + if (!uentry_isOut(el)) + { + c = constraint_makeSRefReadSafeInt (s, 0); + implicitFcnConstraints = constraintList_add (implicitFcnConstraints , c); + } + } + else + { + DPRINTF((message ("%s is NOT a pointer", sRef_unparse(s) ) )); + } + } /*end uentry_isVariable*/ + else if (uentry_isElipsisMarker (el) ) { - DPRINTF((message ("%s is a pointer", sRef_unparse(s) ) )); + /* just ignore these*/ + ; } + else { - DPRINTF((message ("%s is NOT a pointer", sRef_unparse(s) ) )); + /* just ignore this + I'm not sure if this is possible though + */ + ; } - /*drl 4/26/01 - chagned this is MaxSet(s) == 0 to MaxSet(s) >= 0 */ - - c = constraint_makeSRefWriteSafeInt (s, 0); - // constraint_makeSRefSetBufferSize (s, 0); - implicitFcnConstraints = constraintList_add(implicitFcnConstraints , c); - } - end_uentryList_elements; + } end_uentryList_elements; } -/*@observer@*/ constraintList getImplicitFcnConstraints (void) +/*@observer@*/ constraintList getImplicitFcnConstraints (void) { return implicitFcnConstraints; } @@ -550,7 +578,7 @@ void setCurrentParams (/*@dependent@*/ uentryList ue) void clearCurrentParams (void) { - currentParamList = uentryList_undefined; + currentParamList = uentryList_undefined; } /* @@ -612,31 +640,28 @@ static /*@exposed@*/ uentry clabstract_globalDeclareFunction (idDecl tid) ue = uentry_makeIdFunction (tid); reflectSpecialCode (ue); reflectArgsUsed (ue); + reflectStorageClass (ue); + uentry_checkParams (ue); + + DPRINTF (("Supercede function: %s", uentry_unparseFull (ue))); + + ue = usymtab_supGlobalEntryReturn (ue); + DPRINTF (("After supercede function: %s", uentry_unparseFull (ue))); + + DPRINTF (("Enter function: %s", uentry_unparseFull (ue))); + context_enterFunction (ue); + enterFunctionParams (uentry_getParams (ue)); + + resetStorageClass (); + DPRINTF (("Function: %s", uentry_unparseFull (ue))); + return (ue); } else { - llparseerror (message ("Inconsistent function declaration: %q", + llparseerror (message ("Non-function declaration: %q", idDecl_unparse (tid))); - - tid = idDecl_replaceCtype - (tid, ctype_makeFunction (ctype_unknown, uentryList_undefined)); - ue = uentry_makeIdFunction (tid); + return (uentry_undefined); } - - reflectStorageClass (ue); - uentry_checkParams (ue); - - DPRINTF (("Supercede function: %s", uentry_unparseFull (ue))); - - ue = usymtab_supGlobalEntryReturn (ue); - DPRINTF (("After supercede function: %s", uentry_unparseFull (ue))); - - context_enterFunction (ue); - enterFunctionParams (uentry_getParams (ue)); - - resetStorageClass (); - DPRINTF (("Function: %s", uentry_unparseFull (ue))); - return (ue); } /* @@ -664,6 +689,9 @@ static /*@only@*/ uentry globalDeclareOldStyleFunction (idDecl tid) uentry_setDefined (ue, g_currentloc); uentry_checkParams (ue); resetStorageClass (); + + /* context_enterOldStyleScope (); */ + return (ue); } @@ -674,6 +702,13 @@ static void oldStyleDeclareFunction (/*@only@*/ uentry e) llassert (ctype_isFunction (rt)); + if (uentry_hasStateClauseList (e) + || uentry_hasConditions (e)) + { + llfatalerror (message ("%q: Old-style function declaration uses a clause (rewrite with function parameters): %q", + fileloc_unparse (g_currentloc), uentry_unparse (e))); + } + e = usymtab_supGlobalEntryReturn (e); context_enterFunction (e); @@ -682,54 +717,95 @@ static void oldStyleDeclareFunction (/*@only@*/ uentry e) resetStorageClass (); } +static void oldStyleCompleteFunction (/*@only@*/ uentry e) +{ + uentryList params = saveParamList; + ctype rt = uentry_getType (e); + + llassert (ctype_isFunction (rt)); + + if (uentry_hasStateClauseList (e) + || uentry_hasConditions (e)) + { + llfatalerror (message ("%q: Old-style function declaration uses a clause (rewrite with function parameters): %q", + fileloc_unparse (g_currentloc), uentry_unparse (e))); + } + + e = usymtab_supGlobalEntryReturn (e); + + context_completeOldStyleFunction (e); + enterFunctionParams (params); + saveParamList = uentryList_undefined; + resetStorageClass (); +} + void clabstract_declareFunction (idDecl tid) /*@globals undef saveFunction; @*/ { uentry ue; DPRINTF (("Declare function: %s", idDecl_unparse (tid))); - if (ProcessingParams) + if (ctype_isUnknown (idDecl_getCtype (tid))) { - ue = globalDeclareOldStyleFunction (tid); - saveFunction = ue; + /* + ** No type, its really a plain name (int) declaration + */ + + voptgenerror (FLG_IMPTYPE, + message ("No type before declaration name (implicit int type): %q", + idDecl_unparse (tid)), + g_currentloc); + tid = idDecl_replaceCtype (tid, ctype_int); + processVariable (tid); + saveFunction = uentry_undefined; } else { - saveFunction = uentry_undefined; - - if (context_inRealFunction ()) + if (s_processingParams) { - ue = uentry_makeVariableLoc (idDecl_observeId (tid), ctype_unknown); - - llparseerror (message ("Function declared inside function: %q", - idDecl_unparse (tid))); - - context_quietExitFunction (); - ue = usymtab_supEntryReturn (ue); + ue = globalDeclareOldStyleFunction (tid); + saveFunction = ue; + DPRINTF (("Set save function: %s", uentry_unparseFull (ue))); } else { - if (context_inInnerScope ()) + saveFunction = uentry_undefined; + + if (context_inRealFunction ()) { - llparseerror (message ("Declaration in inner context: %q", + ue = uentry_makeVariableLoc (idDecl_observeId (tid), ctype_unknown); + + llparseerror (message ("Function declared inside function: %q", idDecl_unparse (tid))); - sRef_setGlobalScope (); - ue = uentry_makeVariableLoc (idDecl_observeId (tid), - ctype_unknown); - ue = usymtab_supGlobalEntryReturn (ue); - sRef_clearGlobalScope (); + context_quietExitFunction (); + ue = usymtab_supEntryReturn (ue); } else { - ue = clabstract_globalDeclareFunction (tid); + if (context_inInnerScope ()) + { + llparseerror (message ("Declaration in inner context: %q", + idDecl_unparse (tid))); + + sRef_setGlobalScope (); + ue = uentry_makeVariableLoc (idDecl_observeId (tid), + ctype_unknown); + ue = usymtab_supGlobalEntryReturn (ue); + sRef_clearGlobalScope (); + } + else + { + ue = clabstract_globalDeclareFunction (tid); + } } + + resetGlobals (); } - - resetGlobals (); + + resetStorageClass (); } - resetStorageClass (); idDecl_free (tid); } @@ -739,7 +815,7 @@ void declareStaticFunction (idDecl tid) /*@globals undef saveFunction; @*/ DPRINTF (("Declare static funciton: %s", idDecl_unparse (tid))); - if (ProcessingParams) + if (s_processingParams) { ue = globalDeclareOldStyleFunction (tid); saveFunction = ue; @@ -797,6 +873,7 @@ void declareStaticFunction (idDecl tid) /*@globals undef saveFunction; @*/ } else { + DPRINTF (("Here we are!")); llparseerror (message ("Inconsistent function declaration: %q", idDecl_unparse (tid))); @@ -864,8 +941,8 @@ checkTypeDecl (uentry e, ctype rep) vgenhinterror (FLG_SYNTAX, message ("Member of boolean enumerated type definition " - "does not match name set to represent TRUE " - "or FALSE: %s", + "does not match name set to represent true " + "or false: %s", ye), message ("Use -boolfalse and -booltrue to set the " "name of false and true boolean values."), @@ -878,10 +955,10 @@ checkTypeDecl (uentry e, ctype rep) if (usymtab_exists (n)) { usymId llm = usymtab_getId (n); - uentry le = usymtab_getTypeEntry (llm); + uentry le = usymtab_getTypeEntry (typeId_fromUsymId (llm)); uentry_setDeclared (e, g_currentloc); - uentry_setSref (e, sRef_makeGlobal (llm, uentry_getType (le))); + uentry_setSref (e, sRef_makeGlobal (llm, uentry_getType (le), stateInfo_currentLoc ())); DPRINTF (("Here we are: %s / %s", n, context_getBoolName ())); @@ -909,12 +986,23 @@ checkTypeDecl (uentry e, ctype rep) uentry ue = usymtab_lookupSafe (ye); llassert (uentry_isEitherConstant (ue)); - llassertprint (ctype_match (uentry_getType (ue), rrep), - ("Bad enum: %s / %s", - uentry_unparse (ue), - ctype_unparse (rrep))); - - uentry_setType (ue, at); + + /* evans 2002-04-22 */ + if (ctype_isBool (uentry_getType (ue))) + { + /* + ** If set using -booltrue or -boolfalse, don't change the type. + */ + } + else + { + llassertprint (ctype_match (uentry_getType (ue), rrep), + ("Bad enum: %s / %s", + uentry_unparse (ue), + ctype_unparse (rrep))); + + uentry_setType (ue, at); + } } } end_enumNameList_elements; } @@ -1046,7 +1134,7 @@ fixUentryList (idDeclList tl, qtype q) ** Microsoft VC++. It is not supported by the ANSI standard. ** ** The inner fields are added to the outer structure. This is meaningful -** for nesting structs inside unions, but lclint does no related +** for nesting structs inside unions, but Splint does no related ** checking. */ @@ -1057,13 +1145,19 @@ fixUnnamedDecl (qtype q) if (ctype_isStruct (ct) || ctype_isUnion (ct)) { - uentryList res = ctype_getFields (ct); - - return (uentryList_copy (res)); + return uentryList_single (uentry_makeUnnamedVariable (ct)); + } + else if (ctype_isEnum (ct)) + { + /* evans 2002-02-05: nothing to do for unnamed enum lists */ + return uentryList_undefined; } else - { - BADBRANCHCONT; + { + voptgenerror + (FLG_SYNTAX, + message ("Type name in field declarations: %s", qtype_unparse (q)), + g_currentloc); } return uentryList_undefined; @@ -1077,7 +1171,7 @@ void setStorageClass (storageClassCode sc) void setProcessingIterVars (uentry iter) { - ProcessingIterVars = TRUE; + s_processingIterVars = TRUE; currentIter = iter; saveIterParamNo = 0; } @@ -1085,7 +1179,7 @@ setProcessingIterVars (uentry iter) void setProcessingGlobalsList () { - ProcessingGlobals = TRUE; + s_processingGlobals = TRUE; fcnNoGlobals = FALSE; } @@ -1111,20 +1205,20 @@ isProcessingGlobMods () static void resetGlobals (void) { - ProcessingGlobals = FALSE; + s_processingGlobals = FALSE; fcnNoGlobals = FALSE; } void unsetProcessingGlobals () { - ProcessingGlobals = FALSE; + s_processingGlobals = FALSE; } void setProcessingVars (/*@only@*/ qtype q) { - ProcessingVars = TRUE; + s_processingVars = TRUE; qtype_free (processingType); processingType = q; } @@ -1132,14 +1226,14 @@ setProcessingVars (/*@only@*/ qtype q) static void setGenericParamList (/*@dependent@*/ uentryList pm) { - ProcessingParams = TRUE; + s_processingParams = TRUE; saveParamList = pm; } void -setProcessingTypedef (/*@only@*/ qtype q) +setProcessingTypedef (qtype q) { - ProcessingTypedef = TRUE; + s_processingTypedef = TRUE; qtype_free (processingType); processingType = q; @@ -1149,13 +1243,13 @@ void unsetProcessingVars () { resetStorageClass (); - ProcessingVars = FALSE; + s_processingVars = FALSE; } void -doneParams () +oldStyleDoneParams () { - if (ProcessingParams) + if (s_processingParams) { if (uentry_isInvalid (saveFunction)) { @@ -1168,9 +1262,9 @@ doneParams () ctype ct2 = ctype_makeFunction (ct, params); uentry_setType (saveFunction, ct2); - ProcessingParams = FALSE; + s_processingParams = FALSE; - oldStyleDeclareFunction (saveFunction); + oldStyleCompleteFunction (saveFunction); saveFunction = uentry_undefined; resetGlobals (); } @@ -1198,6 +1292,8 @@ checkDoneParams () ctype ct = ctype_getReturnType (uentry_getType (saveFunction)); ctype ct2; + DPRINTF (("save function: %s", uentry_unparseFull (saveFunction))); + uentryList_elements (saveParamList, current) { uentry_setType (current, ctype_int); /* all params are ints */ @@ -1206,29 +1302,71 @@ checkDoneParams () ct2 = ctype_makeParamsFunction (ct, uentryList_copy (saveParamList)); uentry_setType (saveFunction, ct2); - ProcessingParams = FALSE; + s_processingParams = FALSE; oldStyleDeclareFunction (saveFunction); saveFunction = uentry_undefined; } } +void clabstract_declareType (/*@only@*/ exprNodeList decls, /*@only@*/ warnClause warn) +{ + llassert (s_processingTypedef); + + DPRINTF (("Declare type: %s", exprNodeList_unparse (decls))); + + if (warnClause_isDefined (warn)) + { + DPRINTF (("Has a warn clause!")); + DPRINTF (("Warn: %s", warnClause_unparse (warn))); + + exprNodeList_elements (decls, el) + { + uentry ue = exprNode_getUentry (el); + cstring uname = uentry_getName (ue); + + DPRINTF (("Entry: %s", exprNode_unparse (el))); + + /* + ** Need to lookup again to make sure we have the right one... + */ + + ue = usymtab_lookupExposeGlob (uname); + + llassert (uentry_isValid (ue)); + llassert (uentry_isDatatype (ue)); + + DPRINTF (("Warning for %s: %s", + uentry_unparse (ue), warnClause_unparse (warn))); + + uentry_addWarning (ue, warnClause_copy (warn)); + DPRINTF (("After add warning: %s", uentry_unparseFull (ue))); + cstring_free (uname); + } end_exprNodeList_elements; + } + + warnClause_free (warn); + exprNodeList_free (decls); + unsetProcessingTypedef (); +} + void unsetProcessingTypedef () { - ProcessingTypedef = FALSE; + s_processingTypedef = FALSE; } void checkConstant (qtype t, idDecl id) { uentry e; - + id = idDecl_fixBase (id, t); e = uentry_makeIdConstant (id); - + reflectStorageClass (e); resetStorageClass (); + DPRINTF (("Constant: %s", uentry_unparseFull (e))); usymtab_supGlobalEntry (e); } @@ -1261,210 +1399,228 @@ void checkValueConstant (qtype t, idDecl id, exprNode e) { uentry_mergeConstantValue (ue, multiVal_copy (exprNode_getValue (e))); } + else + { + DPRINTF (("No value: %s", exprNode_unparse (e))); + } } } + DPRINTF (("Constant value: %s", uentry_unparseFull (ue))); usymtab_supGlobalEntry (ue); } -void processNamedDecl (idDecl t) +static void processVariable (idDecl t) { - if (qtype_isUndefined (processingType)) - { - llparseerror (message ("No type before declaration name: %q", idDecl_unparse (t))); - - processingType = qtype_create (ctype_unknown); - } - - t = idDecl_fixBase (t, processingType); - - DPRINTF (("Declare: %s", idDecl_unparse (t))); - - if (ProcessingGlobals) + uentry e; + ctype ct; + + ct = ctype_realType (idDecl_getCtype (t)); + + if (s_processingParams) { cstring id = idDecl_getName (t); - uentry ue = usymtab_lookupSafe (id); + int paramno = uentryList_lookupRealName (saveParamList, id); - if (!uentry_isValid (ue)) + if (paramno >= 0) { - llerror (FLG_UNRECOG, - message ("Variable used in globals list is undeclared: %s", id)); + uentry cparam = uentryList_getN (saveParamList, paramno); + + DPRINTF (("Processing param: %s", uentry_unparseFull (cparam))); + uentry_setType (cparam, idDecl_getCtype (t)); + uentry_reflectQualifiers (cparam, idDecl_getQuals (t)); + uentry_setDeclaredOnly (cparam, context_getSaveLocation ()); + DPRINTF (("Processing param: %s", uentry_unparseFull (cparam))); } else { - if (!ctype_match (uentry_getType (ue), idDecl_getCtype (t))) - { - voptgenerror - (FLG_INCONDEFS, - message ("Variable %s used in globals list declared %s, " - "but listed as %s", - id, ctype_unparse (uentry_getType (ue)), - ctype_unparse (idDecl_getCtype (t))), - g_currentloc); - } - else - { - sRef sr = sRef_copy (uentry_getSref (ue)); - reflectGlobalQualifiers (sr, idDecl_getQuals (t)); - } + llfatalerrorLoc + (message ("Old style declaration uses unlisted parameter: %s", + id)); } } - else if (ProcessingVars) + else { - uentry e; - ctype ct; + fileloc loc; - ct = ctype_realType (idDecl_getCtype (t)); - - if (ProcessingParams) + if (context_inIterDef ()) { - cstring id = idDecl_getName (t); - int paramno = uentryList_lookupRealName (saveParamList, id); - - if (paramno >= 0) - { - uentry cparam = uentryList_getN (saveParamList, paramno); - - uentry_setType (cparam, idDecl_getCtype (t)); - uentry_reflectQualifiers (cparam, idDecl_getQuals (t)); - uentry_setDeclaredOnly (cparam, context_getSaveLocation ()); - } - else + cstring pname = makeParam (idDecl_observeId (t)); + uentry p = usymtab_lookupSafe (pname); + + cstring_free (pname); + + if (uentry_isYield (p)) { - llfatalerrorLoc - (message ("Old style declaration uses unlisted parameter: %s", - id)); + e = uentry_makeParam (t, sRef_getParam (uentry_getSref (p))); + uentry_checkYieldParam (p, e); + usymtab_supEntrySref (e); + return; } } + + if ((hasSpecialCode () || argsUsed) + && ctype_isFunction (idDecl_getCtype (t))) + { + e = uentry_makeIdFunction (t); + reflectSpecialCode (e); + reflectArgsUsed (e); + } else { - fileloc loc; - - if (context_inIterDef ()) - { - cstring pname = makeParam (idDecl_observeId (t)); - uentry p = usymtab_lookupSafe (pname); - - cstring_free (pname); - - if (uentry_isYield (p)) - { - e = uentry_makeParam (t, sRef_getParam (uentry_getSref (p))); - uentry_checkYieldParam (p, e); - usymtab_supEntrySref (e); - return; - } - } - - if ((hasSpecialCode () || argsUsed) - && ctype_isFunction (idDecl_getCtype (t))) - { - e = uentry_makeIdFunction (t); - reflectSpecialCode (e); - reflectArgsUsed (e); - } - else - { - e = uentry_makeIdVariable (t); - } - - loc = uentry_whereDeclared (e); - - /* - if (context_inGlobalScope ()) - { - uentry_checkParams was here! - } - */ + e = uentry_makeIdVariable (t); + } + + loc = uentry_whereDeclared (e); + + /* + if (context_inGlobalScope ()) + { + uentry_checkParams was here! + } + */ + + if (ctype_isFunction (uentry_getType (e))) + { + clabstract_prepareFunction (e); + } + + DPRINTF (("Superceding... %s", uentry_unparseFull (e))); + e = usymtab_supEntrySrefReturn (e); + DPRINTF (("After superceding... %s", uentry_unparseFull (e))); + + if (uentry_isExtern (e) && !context_inGlobalScope ()) + { + voptgenerror + (FLG_NESTEDEXTERN, + message ("Declaration using extern inside function scope: %q", + uentry_unparse (e)), + g_currentloc); - if (ctype_isFunction (uentry_getType (e))) + uentry_setDefined (e, fileloc_getExternal ()); + sRef_setDefined (uentry_getSref (e), fileloc_getExternal ()); + } + + if (uentry_isFunction (e)) + { + if (!context_inXHFile ()) { - clabstract_prepareFunction (e); + checkParamNames (e); } + } + + if (uentry_isVar (e) && uentry_isCheckedUnknown (e)) + { + sRef sr = uentry_getSref (e); - DPRINTF (("Superceding... %s", uentry_unparseFull (e))); - e = usymtab_supEntrySrefReturn (e); - DPRINTF (("After superceding... %s", uentry_unparseFull (e))); - - if (uentry_isExtern (e) && !context_inGlobalScope ()) + if (sRef_isLocalVar (sr)) { - voptgenerror - (FLG_NESTEDEXTERN, - message ("Declaration using extern inside function scope: %q", - uentry_unparse (e)), - g_currentloc); - - uentry_setDefined (e, fileloc_getExternal ()); - sRef_setDefined (uentry_getSref (e), fileloc_getExternal ()); + if (context_getFlag (FLG_IMPCHECKMODINTERNALS)) + { + uentry_setCheckMod (e); + } + else + { + uentry_setUnchecked (e); + } } - - if (uentry_isFunction (e)) + else if (sRef_isFileStatic (sr)) { - if (!context_inXHFile ()) + if (context_getFlag (FLG_IMPCHECKEDSTRICTSTATICS)) { - checkParamNames (e); + uentry_setCheckedStrict (e); + } + else if (context_getFlag (FLG_IMPCHECKEDSTATICS)) + { + uentry_setChecked (e); + } + else if (context_getFlag (FLG_IMPCHECKMODSTATICS)) + { + uentry_setCheckMod (e); + } + else + { + ; } } - - if (uentry_isVar (e) && uentry_isCheckedUnknown (e)) + else /* real global */ { - sRef sr = uentry_getSref (e); + llassert (sRef_isRealGlobal (sr)); - if (sRef_isLocalVar (sr)) + if (context_getFlag (FLG_IMPCHECKEDSTRICTGLOBALS)) { - if (context_getFlag (FLG_IMPCHECKMODINTERNALS)) - { - uentry_setCheckMod (e); - } - else - { - uentry_setUnchecked (e); - } + uentry_setCheckedStrict (e); } - else if (sRef_isFileStatic (sr)) + else if (context_getFlag (FLG_IMPCHECKEDGLOBALS)) { - if (context_getFlag (FLG_IMPCHECKEDSTRICTSTATICS)) - { - uentry_setCheckedStrict (e); - } - else if (context_getFlag (FLG_IMPCHECKEDSTATICS)) - { - uentry_setChecked (e); - } - else if (context_getFlag (FLG_IMPCHECKMODSTATICS)) - { - uentry_setCheckMod (e); - } - else - { - ; - } + uentry_setChecked (e); } - else /* real global */ + else if (context_getFlag (FLG_IMPCHECKMODGLOBALS)) { - llassert (sRef_isRealGlobal (sr)); - - if (context_getFlag (FLG_IMPCHECKEDSTRICTGLOBALS)) - { - uentry_setCheckedStrict (e); - } - else if (context_getFlag (FLG_IMPCHECKEDGLOBALS)) - { - uentry_setChecked (e); - } - else if (context_getFlag (FLG_IMPCHECKMODGLOBALS)) - { - uentry_setCheckMod (e); - } - else - { - ; - } + uentry_setCheckMod (e); + } + else + { + ; } } } } - else if (ProcessingTypedef) +} + +void processNamedDecl (idDecl t) +{ + if (qtype_isUndefined (processingType)) + { + processingType = qtype_create (ctype_int); + t = idDecl_fixBase (t, processingType); + + voptgenerror (FLG_IMPTYPE, + message ("No type before declaration name (implicit int type): %q", + idDecl_unparse (t)), + g_currentloc); + } + else + { + t = idDecl_fixBase (t, processingType); + } + + DPRINTF (("Declare: %s", idDecl_unparse (t))); + + if (s_processingGlobals) + { + cstring id = idDecl_getName (t); + uentry ue = usymtab_lookupSafe (id); + + if (!uentry_isValid (ue)) + { + llerror (FLG_UNRECOG, + message ("Variable used in globals list is undeclared: %s", id)); + } + else + { + if (!ctype_match (uentry_getType (ue), idDecl_getCtype (t))) + { + voptgenerror + (FLG_INCONDEFS, + message ("Variable %s used in globals list declared %s, " + "but listed as %s", + id, ctype_unparse (uentry_getType (ue)), + ctype_unparse (idDecl_getCtype (t))), + g_currentloc); + } + else + { + sRef sr = sRef_copy (uentry_getSref (ue)); + reflectGlobalQualifiers (sr, idDecl_getQuals (t)); + } + } + } + else if (s_processingVars) + { + processVariable (t); + } + else if (s_processingTypedef) { ctype ct = idDecl_getCtype (t); uentry e; @@ -1560,6 +1716,8 @@ declareUnnamedStruct (/*@only@*/ uentryList f) ctype declareUnnamedUnion (/*@only@*/ uentryList f) { + DPRINTF (("Unnamed union: %s", uentryList_unparse (f))); + if (context_maybeSet (FLG_NUMSTRUCTFIELDS)) { int num = uentryList_size (f); @@ -1585,7 +1743,8 @@ ctype declareStruct (cstring id, /*@only@*/ uentryList f) uentry ue; int num = uentryList_size (f); - DPRINTF (("Declare struct: %s / %s", id, uentryList_unparse (f))); + DPRINTF (("Declare struct: %s / %s [%d]", id, uentryList_unparse (f), + uentryList_size (f))); ct = ctype_createStruct (cstring_copy (id), f); @@ -1680,13 +1839,13 @@ handleEnum (cstring id) } else { - return (declareEnum (id, enumNameList_new ())); + return (ctype_createForwardEnum (id)); } } bool processingIterVars (void) { - return ProcessingIterVars; + return s_processingIterVars; } uentry getCurrentIter (void) @@ -1715,15 +1874,19 @@ void setNewStyle () { flipNewStyle = TRUE; } cstring_makeLiteral ("Old style function declaration"), g_currentloc); + DPRINTF (("Handle old style params: %s", uentryList_unparseFull (params))); + uentryList_elements (params, current) { uentry_setParam (current); - uentry_setSref (current, sRef_makeParam (paramno, ctype_unknown)); + uentry_setSref (current, sRef_makeParam + (paramno, ctype_unknown, + stateInfo_makeLoc (uentry_whereLast (current), SA_DECLARED))); paramno++; } end_uentryList_elements; setGenericParamList (params); - g_expectingTypeName = TRUE; + cscannerHelp_setExpectingTypeName (); return params; } @@ -1740,7 +1903,7 @@ void setNewStyle () { flipNewStyle = TRUE; } setGenericParamList (params); flipOldStyle = FALSE; - g_expectingTypeName = TRUE; + cscannerHelp_setExpectingTypeName (); } return (params); @@ -1753,13 +1916,16 @@ doVaDcl () cstring id = cstring_makeLiteral ("va_alist"); uentry e; - if (ProcessingParams) + if (s_processingParams) { int i = uentryList_lookupRealName (saveParamList, id); if (i >= 0) { - e = uentry_makeVariableSrefParam (id, c, sRef_makeParam (i, c)); + fileloc loc = context_getSaveLocation (); + e = uentry_makeVariableSrefParam + (id, c, loc, + sRef_makeParam (i, c, stateInfo_makeLoc (loc, SA_DECLARED))); } else { @@ -1939,15 +2105,15 @@ doVaDcl () } else { - if (ctype_isAbstract (ct)) + if (ctype_isAbstract (rt)) { voptgenerror (FLG_ABSTRACT, message - ("Modifies clause in header file arrow accesses abstract " + ("Modifies clause arrow accesses inaccessible abstract " "type %s (interface modifies clause should not depend " "on or expose type representation): %q", - ctype_unparse (ct), + ctype_unparse (rt), sRef_unparse (s)), g_currentloc); } @@ -1990,11 +2156,13 @@ sRef checkStateClausesId (uentry ue) { voptgenerror (FLG_COMMENTERROR, - message ("Global variable %s used special clause. (Global variables " - "are not recognized in special clauses. If there is " + message ("Global variable %s used state clause. (Global variables " + "are not recognized in state clauses. If they are present " + "they are ignored. " + " If there is " "sufficient interest in support for this, it may be " "added to a future release. Send mail to " - "lclint@cs.virginia.edu.)", + "info@splint.org.)", s), g_currentloc); @@ -2032,6 +2200,7 @@ sRef checkStateClausesId (uentry ue) sRef checkbufferConstraintClausesId (uentry ue) { + sRef sr; cstring s = uentry_rawName (ue); if (cstring_equalLit (s, "result")) @@ -2046,7 +2215,20 @@ sRef checkbufferConstraintClausesId (uentry ue) } } - return sRef_saveCopy (uentry_getSref (ue)); /*@i523 why the saveCopy? */ + sr = uentry_getSref (ue); + + if (sRef_isInvalid (sr)) + { + llfatalerrorLoc (cstring_makeLiteral ("Macro defined constants can not be used in function " + "constraints unless they are specifed with the constant " + "annotation. To use a macro defined constant include an " + "annotation of the form /*@constant =@*/ " + "somewhere before the function constraint. This restriction " + "may be removed in future releases.")); + } + + /* saveCopy to used to mitigate danger of accessing freed memory*/ + return sRef_saveCopy (sr); } void checkModifiesId (uentry ue) @@ -2114,7 +2296,7 @@ void checkModifiesId (uentry ue) } else { - fileloc loc = fileloc_decColumn (g_currentloc, cstring_length (s)); + fileloc loc = fileloc_decColumn (g_currentloc, size_toInt (cstring_length (s))); ret = sRef_undefined; voptgenerror @@ -2171,7 +2353,7 @@ sRef fixStateClausesId (cstring s) "are not recognized in function clauses. If there is " "sufficient interest in support for this, it may be " "added to a future release. Send mail to " - "lclint@cs.virginia.edu.)", + "info@splint.org.)", s), g_currentloc); @@ -2180,9 +2362,43 @@ sRef fixStateClausesId (cstring s) } else { - fileloc loc = fileloc_decColumn (g_currentloc, cstring_length (s)); + + /* drl This is the code for structure invariants + + It is no yet stable enough to be included in a Splint release. + */ + + /*check that we're in a structure */ +#if 0 + /*@unused@*/ uentryList ueL; + /*@unused@*/ uentry ue2; + /*@unused@*/ ctype ct; +#endif + fileloc loc = fileloc_decColumn (g_currentloc, size_toInt (cstring_length (s))); ret = sRef_undefined; +# if 0 + ct = context_getLastStruct ( ct ); + + llassert( ctype_isStruct(ct) ); + + ueL = ctype_getFields (ct); + + ue2 = uentryList_lookupField (ueL, s); + + if (!uentry_isUndefined(ue2) ) + { + ret = uentry_getSref(ue2); + + DPRINTF(( + message("Got field in structure in the annotation constraint: %s (or sref: %s)", s, sRef_unparse(ret) ) + )); + + return ret; + } + +#endif + voptgenerror (FLG_UNRECOG, message ("Unrecognized identifier in function clause: %s", s), @@ -2246,11 +2462,3 @@ sRef clabstract_checkGlobal (exprNode e) exprNode_free (e); return sRef_copy (s); } - - - - - - - -