value flow: use more specific bailouts when analysing value flow after assignment

This commit is contained in:
Daniel Marjamäki 2014-01-22 06:38:25 +01:00
parent cc38dec3ad
commit 43db1ee797
4 changed files with 39 additions and 17 deletions

View File

@ -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);
}

View File

@ -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<ValueFlow::Value>::const_iterator it;
for (it = values.begin(); it != values.end(); ++it)
setTokenValue(tok2, *it);
{
std::list<ValueFlow::Value>::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<ValueFlow::Value>::iterator it;
for (it = values.begin(); it != values.end(); ++it)
it->inconclusive = true;
}
}
}
}

View File

@ -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());

View File

@ -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() {