From 8b6f001f942f99cf1a5fd1daea5c712fa17ad144 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sun, 12 Jan 2014 19:48:20 +0100 Subject: [PATCH] value flow: inconclusive handling of unknown functions --- lib/checknullpointer.cpp | 4 ++-- lib/valueflow.cpp | 21 ++++++++++++++++----- lib/valueflow.h | 7 ++++--- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/lib/checknullpointer.cpp b/lib/checknullpointer.cpp index c6fb727bf..0ec380b4f 100644 --- a/lib/checknullpointer.cpp +++ b/lib/checknullpointer.cpp @@ -785,7 +785,7 @@ void CheckNullPointer::nullPointerByDeRefAndChec() if (value->condition == NULL) nullPointerError(tok); else if (_settings->isEnabled("warning")) - nullPointerError(tok, tok->str(), value->condition, false); + nullPointerError(tok, tok->str(), value->condition, value->inconclusive); } continue; } @@ -797,7 +797,7 @@ void CheckNullPointer::nullPointerByDeRefAndChec() if (value->condition == NULL) nullPointerError(tok); else if (_settings->isEnabled("warning")) - nullPointerError(tok, tok->str(), value->condition, false); + nullPointerError(tok, tok->str(), value->condition, value->inconclusive); } return; } diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 2431e9fb1..b8c863dbb 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -44,7 +44,7 @@ static void bailout(TokenList *tokenlist, ErrorLogger *errorLogger, const Token errorLogger->reportErr(errmsg); } -static bool bailoutFunctionPar(const Token *tok, const ValueFlow::Value &value, const Settings *settings) +static bool bailoutFunctionPar(const Token *tok, const ValueFlow::Value &value, const Settings *settings, bool *inconclusive) { // passing variable to subfunction? const bool addr = tok && Token::Match(tok->previous(), "&"); @@ -65,9 +65,15 @@ static bool bailoutFunctionPar(const Token *tok, const ValueFlow::Value &value, return false; // not a function => dont bailout if (!tok->function()) { - // unknown function.. bailout unless value is 0 and the library - // says 0 is invalid - return (value.intvalue!=0 || !settings->library.isnullargbad(tok->str(), 1+argnr)); + // if value is 0 and the library says 0 is invalid => dont bailout + if (value.intvalue==0 && settings->library.isnullargbad(tok->str(), 1+argnr)) + return false; + // inconclusive => don't bailout + if (inconclusive && !addr && settings->inconclusive) { + *inconclusive = true; + return false; + } + return true; } const Variable *arg = tok->function()->getArgumentVar(argnr); @@ -186,6 +192,7 @@ static void valueFlowBeforeCondition(TokenList *tokenlist, ErrorLogger *errorLog val2 = ValueFlow::Value(tok,0); } + bool inconclusive = false; for (Token *tok2 = tok->previous(); ; tok2 = tok2->previous()) { if (!tok2) { if (settings->debugwarnings) { @@ -213,11 +220,14 @@ static void valueFlowBeforeCondition(TokenList *tokenlist, ErrorLogger *errorLog } // assigned by subfunction? - if (bailoutFunctionPar(tok2,val2.condition ? val2 : val,settings)) { + bool inconclusive2 = false; + if (bailoutFunctionPar(tok2,val2.condition ? val2 : val, settings, &inconclusive2)) { if (settings->debugwarnings) bailout(tokenlist, errorLogger, tok2, "possible assignment of " + tok2->str() + " by subfunction"); break; } + inconclusive |= inconclusive2; + val2.inconclusive |= inconclusive2; // skip if variable is conditionally used in ?: expression if (const Token *parent = skipValueInConditionalExpression(tok2)) { @@ -230,6 +240,7 @@ static void valueFlowBeforeCondition(TokenList *tokenlist, ErrorLogger *errorLog } tok2->values.push_back(val); + tok2->values.back().inconclusive = inconclusive; if (val2.condition) tok2->values.push_back(val2); if (var && tok2 == var->nameToken()) diff --git a/lib/valueflow.h b/lib/valueflow.h index 3b585c5de..8f438239c 100644 --- a/lib/valueflow.h +++ b/lib/valueflow.h @@ -29,11 +29,12 @@ class Settings; namespace ValueFlow { class Value { public: - Value() : condition(0), intvalue(0) {} - Value(long long val) : condition(0), intvalue(val) {} - Value(const Token *c, long long val) : condition(c), intvalue(val) {} + Value() : condition(0), intvalue(0), inconclusive(false) {} + Value(long long val) : condition(0), intvalue(val), inconclusive(false) {} + Value(const Token *c, long long val) : condition(c), intvalue(val), inconclusive(false) {} const Token *condition; long long intvalue; + bool inconclusive; }; void setValues(TokenList *tokenlist, ErrorLogger *errorLogger, const Settings *settings);