X-Git-Url: http://andersk.mit.edu/gitweb/splint.git/blobdiff_plain/b7b694d6212749bfa3aa56e853adff6a5aa3b87f..a6bfbad8f5ae6b3544a2c767e449ee095aad8978:/src/exprChecks.c diff --git a/src/exprChecks.c b/src/exprChecks.c index 9612a7c..4b3b81d 100644 --- a/src/exprChecks.c +++ b/src/exprChecks.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-2002 University of Virginia, ** Massachusetts Institute of Technology ** ** This program is free software; you can redistribute it and/or modify it @@ -17,15 +17,15 @@ ** 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 */ /* ** exprChecks.c */ -# include "lclintMacros.nf" +# include "splintMacros.nf" # include "basic.h" # include "cgrammar.h" # include "cgrammar_tokens.h" @@ -52,11 +52,36 @@ static void checkSafeReturnExpr (/*@notnull@*/ exprNode p_e); ** */ +static int inCompoundStatementExpression = 0; + +void +exprChecks_inCompoundStatementExpression (void) +{ + inCompoundStatementExpression++; +} + +void +exprChecks_leaveCompoundStatementExpression (void) +{ + inCompoundStatementExpression--; + llassert (inCompoundStatementExpression >= 0); +} + void -exprNode_checkStatement (exprNode e) +exprChecks_checkStatementEffect (exprNode e) { bool hasError = FALSE; + if (inCompoundStatementExpression > 0) + { + /* + ** Okay to have effectless statments in compound statement expression (should check + ** it is the last statement, but we don't for now). + */ + + return; + } + if (!exprNode_isError (e)) { exprKind ek = e->kind; @@ -385,13 +410,13 @@ exprChecks_checkNullReturn (fileloc loc) if (ctype_isUnknown (tr)) { voptgenerror - (FLG_CONTROL, + (FLG_EMPTYRETURN, cstring_makeLiteral ("Empty return in function declared to implicitly return int"), loc); } else { - voptgenerror (FLG_CONTROL, + voptgenerror (FLG_EMPTYRETURN, message ("Empty return in function declared to return %t", tr), loc); } @@ -409,7 +434,7 @@ exprNode_checkReturn (exprNode e) { if (context_inMacro ()) { - llerror (FLG_CONTROL, + llerror (FLG_MACRORETURN, message ("Macro %s uses return (not functional)", context_inFunctionName ())); } @@ -638,7 +663,7 @@ void exprNode_checkMacroBody (/*@only@*/ exprNode e) uentry hdr; if (!(context_inFunctionLike () || context_inMacroConstant () - || context_inMacroUnknown ())) + || context_inUnknownMacro ())) { llcontbug (message @@ -732,7 +757,7 @@ void exprNode_checkMacroBody (/*@only@*/ exprNode e) } } } - else if (context_inMacroFunction () || context_inMacroUnknown ()) + else if (context_inMacroFunction () || context_inUnknownMacro ()) { ctype rettype = context_getRetType (); @@ -822,7 +847,7 @@ void exprNode_checkMacroBody (/*@only@*/ exprNode e) case XPR_STRINGLITERAL: case XPR_NUMLIT: case XPR_FACCESS: case XPR_OFFSETOF: - checkReturnTransfer (e, hdr); + transferChecks_return (e, hdr); break; /* these expressions don't */ @@ -913,161 +938,154 @@ void exprNode_checkFunctionBody (exprNode body) /*drl modified */ -void exprNode_checkFunction (/*@unused@*/ uentry ue, /*@only@*/ exprNode fcnBody) +void exprNode_checkFunction (/*@unused@*/ uentry ue, /*@only@*/ exprNode body) { constraintList c, t, post; constraintList c2, fix; constraintList implicitFcnConstraints; - - /*@owned@*/ exprNode body; - context_enterInnerContext (); - body = fcnBody; + llassert (exprNode_isDefined (body)); /* if we're not going to be printing any errors for buffer overflows we can skip the checking to improve performance FLG_DEBUGFUNCTIONCONSTRAINT controls wheather we perform the check anyway - in order to find potential problems like asserts and seg faults... + in order to find potential problems like assert failures and seg faults... */ - if (!context_getFlag(FLG_DEBUGFUNCTIONCONSTRAINT) ) - /* check if errors will printed */ - if (! (context_getFlag(FLG_DEBUGFUNCTIONCONSTRAINT) || - context_getFlag(FLG_FUNCTIONCONSTRAINT) || - context_getFlag(FLG_ARRAYBOUNDS) || - context_getFlag(FLG_ARRAYBOUNDSREAD) || - context_getFlag(FLG_CHECKPOST) - ) - ) - { - exprNode_free (body); - context_exitInnerPlain(); - - return; - } + if (!context_getFlag(FLG_DEBUGFUNCTIONCONSTRAINT)) + { + /* check if errors will printed */ + if (!(context_getFlag(FLG_DEBUGFUNCTIONCONSTRAINT) || + context_getFlag(FLG_BOUNDSWRITE) || + context_getFlag(FLG_BOUNDSREAD) || + context_getFlag(FLG_CHECKPOST))) + { + exprNode_free (body); + context_exitInnerPlain(); + + return; + } + } - exprNode_generateConstraints (body); - + exprNode_generateConstraints (body); /* evans 2002-03-02: this should not be declared to take a + dependent... fix it! */ c = uentry_getFcnPreconditions (ue); DPRINTF(("function constraints\n")); DPRINTF (("\n\n\n\n\n\n\n")); - - if (constraintList_isDefined(c) ) - { - - DPRINTF ( (message ("Function preconditions are %s \n\n\n\n\n", constraintList_printDetailed (c) ) ) ); - - body->requiresConstraints = constraintList_reflectChangesFreePre (body->requiresConstraints, c); - - c2 = constraintList_copy (c); - fix = constraintList_makeFixedArrayConstraints (body->uses); - c2 = constraintList_reflectChangesFreePre (c2, fix); - constraintList_free(fix); - if ( context_getFlag (FLG_ORCONSTRAINT) ) - { - t = constraintList_reflectChangesOr (body->requiresConstraints, c2 ); - } - else - { - t = constraintList_reflectChanges(body->requiresConstraints, c2); - } - - constraintList_free(body->requiresConstraints); - DPRINTF ( (message ("The body has the required constraints: %s", constraintList_printDetailed (t) ) ) ); - - body->requiresConstraints = t; - - t = constraintList_mergeEnsures (c, body->ensuresConstraints); - constraintList_free(body->ensuresConstraints); - - body->ensuresConstraints = t; - - DPRINTF ( (message ("The body has the ensures constraints: %s", constraintList_printDetailed (t) ) ) ); - constraintList_free(c2); - } - - if (constraintList_isDefined(c) ) - { - DPRINTF((message ("The Function %s has the preconditions %s", uentry_unparse(ue), constraintList_printDetailed(c) ) ) ); - } - else - { - DPRINTF((message ("The Function %s has no preconditions", uentry_unparse(ue) ) ) ); - } - - implicitFcnConstraints = getImplicitFcnConstraints(); - - if (constraintList_isDefined(implicitFcnConstraints) ) - { - if (context_getFlag (FLG_IMPLICTCONSTRAINT) ) - { - body->requiresConstraints = constraintList_reflectChangesFreePre (body->requiresConstraints, implicitFcnConstraints ); - } - } - - body->requiresConstraints = constraintList_sort (body->requiresConstraints); - - constraintList_printError(body->requiresConstraints, g_currentloc); - - post = uentry_getFcnPostconditions (ue); + if (constraintList_isDefined(c) ) + { + DPRINTF ((message ("Function preconditions are %s \n\n\n\n\n", constraintList_printDetailed (c) ) ) ); + + body->requiresConstraints = constraintList_reflectChangesFreePre (body->requiresConstraints, c); + + c2 = constraintList_copy (c); + fix = constraintList_makeFixedArrayConstraints (body->uses); + c2 = constraintList_reflectChangesFreePre (c2, fix); + constraintList_free (fix); + + if (context_getFlag (FLG_ORCONSTRAINT)) + { + t = constraintList_reflectChangesOr (body->requiresConstraints, c2 ); + } + else + { + t = constraintList_reflectChanges(body->requiresConstraints, c2); + } + + constraintList_free (body->requiresConstraints); + DPRINTF ((message ("The body has the required constraints: %s", constraintList_printDetailed (t) ) ) ); + + body->requiresConstraints = t; + + t = constraintList_mergeEnsures (c, body->ensuresConstraints); + constraintList_free(body->ensuresConstraints); + + body->ensuresConstraints = t; + + DPRINTF ((message ("The body has the ensures constraints: %s", constraintList_printDetailed (t) ) ) ); + constraintList_free(c2); + } + + if (constraintList_isDefined(c)) + { + DPRINTF ((message ("The Function %s has the preconditions %s", + uentry_unparse(ue), constraintList_printDetailed(c)))); + } + else + { + DPRINTF((message ("The Function %s has no preconditions", uentry_unparse(ue)))); + } + + implicitFcnConstraints = getImplicitFcnConstraints(); + + if (constraintList_isDefined(implicitFcnConstraints) ) + { + if (context_getFlag (FLG_IMPLICTCONSTRAINT) ) + { + body->requiresConstraints = constraintList_reflectChangesFreePre (body->requiresConstraints, + implicitFcnConstraints ); + } + } + + body->requiresConstraints = constraintList_sort (body->requiresConstraints); + + constraintList_printError(body->requiresConstraints, g_currentloc); + + post = uentry_getFcnPostconditions (ue); + + if (context_getFlag (FLG_CHECKPOST)) + { + if (constraintList_isDefined (post)) + { + constraintList post2; + + DPRINTF ((message ("The declared function postconditions are %s \n\n\n\n\n", + constraintList_printDetailed (post) ) ) ); + + post = constraintList_reflectChangesFreePre (post, body->ensuresConstraints); + + post2 = constraintList_copy (post); + fix = constraintList_makeFixedArrayConstraints (body->uses); + post2 = constraintList_reflectChangesFreePre (post2, fix); + constraintList_free(fix); + if ( context_getFlag (FLG_ORCONSTRAINT) ) + { + t = constraintList_reflectChangesOr (post2, body->ensuresConstraints); + } + else + { + t = constraintList_reflectChanges(post2, body->ensuresConstraints); + } + + constraintList_free(post2); + constraintList_free(post); + post = t; - if ( context_getFlag (FLG_CHECKPOST) ) - { - if (constraintList_isDefined(post) ) - { - - constraintList post2; - - DPRINTF ( (message ("The declared function postconditions are %s \n\n\n\n\n", constraintList_printDetailed (post) ) ) ); - - post = constraintList_reflectChangesFreePre (post, body->ensuresConstraints); - - post2 = constraintList_copy (post); - fix = constraintList_makeFixedArrayConstraints (body->uses); - post2 = constraintList_reflectChangesFreePre (post2, fix); - constraintList_free(fix); - if ( context_getFlag (FLG_ORCONSTRAINT) ) - { - t = constraintList_reflectChangesOr (post2, body->ensuresConstraints); - } - else - { - t = constraintList_reflectChanges(post2, body->ensuresConstraints); - } - - constraintList_free(post2); - - constraintList_free(post); - post = t; - - - - printf("Unresolved post conditions\n"); - constraintList_printErrorPostConditions(post, g_currentloc); - } - } - - if (constraintList_isDefined(post) ) - { - constraintList_free(post); - } + printf("Unresolved post conditions\n"); + constraintList_printErrorPostConditions(post, g_currentloc); + } + } + + if (constraintList_isDefined (post)) + { + constraintList_free (post); + } body->ensuresConstraints = constraintList_sort(body->ensuresConstraints); - + if ( context_getFlag (FLG_FUNCTIONPOST) ) { constraintList_printError(body->ensuresConstraints, g_currentloc); } - /* ConPrint (message ("Unable to resolve function constraints:\n%s", constraintList_printDetailed(body->requiresConstraints) ), g_currentloc); - ConPrint (message ("LCLint has found function post conditions:\n%s", constraintList_printDetailed(body->ensuresConstraints) ), g_currentloc); + ConPrint (message ("Splint has found function post conditions:\n%s", constraintList_printDetailed(body->ensuresConstraints) ), g_currentloc); printf ("The required constraints are:\n%s", constraintList_printDetailed(body->requiresConstraints) ); printf ("The ensures constraints are:\n%s", constraintList_printDetailed(body->ensuresConstraints) ); @@ -1087,7 +1105,7 @@ void exprChecks_checkEmptyMacroBody (void) uentry hdr; if (!(context_inFunctionLike () || context_inMacroConstant () - || context_inMacroUnknown ())) + || context_inUnknownMacro ())) { llcontbug (message ("exprNode_checkEmptyMacroBody: not in macro function or constant: %q", @@ -1523,6 +1541,16 @@ static void checkSafeReturnExpr (/*@notnull@*/ exprNode e) ctype tr = ctype_getReturnType (context_currentFunctionType ()); ctype te = exprNode_getType (e); + /* evans 2001-08-21: added test to warn about void returns from void functions */ + if (ctype_isVoid (tr)) + { + (void) gentypeerror + (te, e, tr, exprNode_undefined, + message ("Return expression from function declared void: %s", exprNode_unparse (e)), + e->loc); + return; + } + if (!ctype_forceMatch (tr, te) && !exprNode_matchLiteral (tr, e)) { (void) gentypeerror @@ -1542,7 +1570,7 @@ static void checkSafeReturnExpr (/*@notnull@*/ exprNode e) sRef_unparseFull (e->sref), uentry_unparse (rval))); - checkReturnTransfer (e, rval); + transferChecks_return (e, rval); DPRINTF (("After return: %s / %s / %s", exprNode_unparse (e),