From 43db1ee797dc3b31d7ccb9d28452fbcf02f7b9b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Wed, 22 Jan 2014 06:38:25 +0100 Subject: [PATCH] value flow: use more specific bailouts when analysing value flow after assignment --- lib/checknullpointer.cpp | 6 +++--- lib/valueflow.cpp | 29 ++++++++++++++++++++++++----- test/testnullpointer.cpp | 18 ++++++++++-------- test/testsimplifytokens.cpp | 3 ++- 4 files changed, 39 insertions(+), 17 deletions(-) diff --git a/lib/checknullpointer.cpp b/lib/checknullpointer.cpp index 7a73c029d..dbad9304d 100644 --- a/lib/checknullpointer.cpp +++ b/lib/checknullpointer.cpp @@ -583,7 +583,7 @@ void CheckNullPointer::nullPointerByDeRefAndChec() parseFunctionCall(*ftok->previous(), varlist, &_settings->library, 0); if (std::find(varlist.begin(), varlist.end(), tok) != varlist.end()) { if (value->condition == NULL) - nullPointerError(tok); + nullPointerError(tok, tok->str()); else if (_settings->isEnabled("warning")) nullPointerError(tok, tok->str(), value->condition, value->inconclusive); } @@ -593,13 +593,13 @@ void CheckNullPointer::nullPointerByDeRefAndChec() // Pointer dereference. bool unknown = false; if (!isPointerDeRef(tok,unknown)) { - if (_settings->inconclusive && unknown) + if (_settings->inconclusive && unknown && value->condition) nullPointerError(tok, tok->str(), value->condition, true); continue; } if (value->condition == NULL) - nullPointerError(tok); + nullPointerError(tok, tok->str()); else if (_settings->isEnabled("warning")) nullPointerError(tok, tok->str(), value->condition, value->inconclusive); } diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index a87076ec8..7edfd558e 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -461,15 +461,34 @@ static void valueFlowAfterAssign(TokenList *tokenlist, ErrorLogger *errorLogger, for (Token *tok2 = tok; tok2; tok2 = tok2->next()) { if (Token::Match(tok2, "[{}]")) break; - if (Token::Match(tok2, "sizeof (")) + if (Token::Match(tok2, "sizeof|typeof|typeid (")) tok2 = tok2->linkAt(1); if (tok2->varId() == varid) { - if (!Token::Match(tok2->previous(), "%cop%|= %var% %cop%|;")) + // bailout: assignment + if (Token::Match(tok2->previous(), "!!* %var% =")) { + if (settings->debugwarnings) + bailout(tokenlist, errorLogger, tok2, "assignment of " + tok2->str()); break; + } - std::list::const_iterator it; - for (it = values.begin(); it != values.end(); ++it) - setTokenValue(tok2, *it); + { + std::list::const_iterator it; + for (it = values.begin(); it != values.end(); ++it) + setTokenValue(tok2, *it); + } + + // assigned by subfunction? + bool inconclusive = false; + if (bailoutFunctionPar(tok2, ValueFlow::Value(), settings, &inconclusive)) { + if (settings->debugwarnings) + bailout(tokenlist, errorLogger, tok2, "possible assignment of " + tok2->str() + " by subfunction"); + break; + } + if (inconclusive) { + std::list::iterator it; + for (it = values.begin(); it != values.end(); ++it) + it->inconclusive = true; + } } } } diff --git a/test/testnullpointer.cpp b/test/testnullpointer.cpp index 429f0054e..6bf52b481 100644 --- a/test/testnullpointer.cpp +++ b/test/testnullpointer.cpp @@ -1126,7 +1126,8 @@ private: " std::string * x = 0;\n" " *x = \"test\";\n" "}", false, "test.cpp", false); - ASSERT_EQUALS("[test.cpp:4]: (error) Null pointer dereference\n", errout.str()); + ASSERT_EQUALS("[test.cpp:4]: (error) Possible null pointer dereference: x\n" + "[test.cpp:4]: (error) Null pointer dereference\n", errout.str()); } void nullpointer10() { @@ -1156,7 +1157,8 @@ private: "}\n"; check(code, false, "test.cpp", false); // C++ file => nullptr means NULL - ASSERT_EQUALS("[test.cpp:4]: (error) Null pointer dereference\n", errout.str()); + ASSERT_EQUALS("[test.cpp:4]: (error) Possible null pointer dereference: i\n" + "[test.cpp:4]: (error) Null pointer dereference\n", errout.str()); check(code, false, "test.c", false); // C file => nullptr does not mean NULL ASSERT_EQUALS("", errout.str()); @@ -1229,7 +1231,8 @@ private: " i++;\n" " };\n" "}\n", false, "test.cpp", false); - ASSERT_EQUALS("[test.cpp:5]: (error) Null pointer dereference\n", errout.str()); + ASSERT_EQUALS("[test.cpp:5]: (error) Possible null pointer dereference: str\n" + "[test.cpp:5]: (error) Null pointer dereference\n", errout.str()); } void nullpointer19() { // #3811 @@ -1715,7 +1718,8 @@ private: " int* p = 0;\n" " return p[4];\n" "}", false, "test.cpp", false); - ASSERT_EQUALS("[test.cpp:3]: (error) Null pointer dereference\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (error) Possible null pointer dereference: p\n" + "[test.cpp:3]: (error) Null pointer dereference\n", errout.str()); check("void f(int x) {\n" // #4809 - passing "NULL" " itoa(x,NULL,10);\n" @@ -1969,14 +1973,12 @@ private: " std::string s5(p);\n" " foo(std::string(p));\n" "}", true); - ASSERT_EQUALS("[test.cpp:7]: (error) Null pointer dereference\n" - "[test.cpp:8]: (error) Null pointer dereference\n" + ASSERT_EQUALS("[test.cpp:7]: (error) Possible null pointer dereference: p\n" + "[test.cpp:8]: (error) Possible null pointer dereference: p\n" "[test.cpp:3]: (error) Null pointer dereference\n" "[test.cpp:4]: (error) Null pointer dereference\n" "[test.cpp:5]: (error) Null pointer dereference\n" "[test.cpp:6]: (error) Null pointer dereference\n" - "[test.cpp:7]: (error) Possible null pointer dereference: p\n" - "[test.cpp:8]: (error) Possible null pointer dereference: p\n" "[test.cpp:9]: (error) Possible null pointer dereference: p\n" "[test.cpp:10]: (error) Possible null pointer dereference: p\n", errout.str()); diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index fe359d973..6ebfba1ed 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -4361,7 +4361,8 @@ private: ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:1]: (style, inconclusive) The typedef 'A' hides a typedef with the same name.\n" "[test.cpp:20] -> [test.cpp:1]: (style, inconclusive) The function parameter 'A' hides a typedef with the same name.\n" "[test.cpp:21] -> [test.cpp:1]: (style, inconclusive) The variable 'A' hides a typedef with the same name.\n" - "[test.cpp:24] -> [test.cpp:1]: (style, inconclusive) The typedef 'A' hides a typedef with the same name.\n", errout.str()); + "[test.cpp:24] -> [test.cpp:1]: (style, inconclusive) The typedef 'A' hides a typedef with the same name.\n" + "[test.cpp:24]: (debug) ValueFlow bailout: parameter a\n", errout.str()); } void simplifyTypedef36() {