value flow: use more specific bailouts when analysing value flow after assignment
This commit is contained in:
parent
cc38dec3ad
commit
43db1ee797
|
@ -583,7 +583,7 @@ void CheckNullPointer::nullPointerByDeRefAndChec()
|
||||||
parseFunctionCall(*ftok->previous(), varlist, &_settings->library, 0);
|
parseFunctionCall(*ftok->previous(), varlist, &_settings->library, 0);
|
||||||
if (std::find(varlist.begin(), varlist.end(), tok) != varlist.end()) {
|
if (std::find(varlist.begin(), varlist.end(), tok) != varlist.end()) {
|
||||||
if (value->condition == NULL)
|
if (value->condition == NULL)
|
||||||
nullPointerError(tok);
|
nullPointerError(tok, tok->str());
|
||||||
else if (_settings->isEnabled("warning"))
|
else if (_settings->isEnabled("warning"))
|
||||||
nullPointerError(tok, tok->str(), value->condition, value->inconclusive);
|
nullPointerError(tok, tok->str(), value->condition, value->inconclusive);
|
||||||
}
|
}
|
||||||
|
@ -593,13 +593,13 @@ void CheckNullPointer::nullPointerByDeRefAndChec()
|
||||||
// Pointer dereference.
|
// Pointer dereference.
|
||||||
bool unknown = false;
|
bool unknown = false;
|
||||||
if (!isPointerDeRef(tok,unknown)) {
|
if (!isPointerDeRef(tok,unknown)) {
|
||||||
if (_settings->inconclusive && unknown)
|
if (_settings->inconclusive && unknown && value->condition)
|
||||||
nullPointerError(tok, tok->str(), value->condition, true);
|
nullPointerError(tok, tok->str(), value->condition, true);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value->condition == NULL)
|
if (value->condition == NULL)
|
||||||
nullPointerError(tok);
|
nullPointerError(tok, tok->str());
|
||||||
else if (_settings->isEnabled("warning"))
|
else if (_settings->isEnabled("warning"))
|
||||||
nullPointerError(tok, tok->str(), value->condition, value->inconclusive);
|
nullPointerError(tok, tok->str(), value->condition, value->inconclusive);
|
||||||
}
|
}
|
||||||
|
|
|
@ -461,16 +461,35 @@ static void valueFlowAfterAssign(TokenList *tokenlist, ErrorLogger *errorLogger,
|
||||||
for (Token *tok2 = tok; tok2; tok2 = tok2->next()) {
|
for (Token *tok2 = tok; tok2; tok2 = tok2->next()) {
|
||||||
if (Token::Match(tok2, "[{}]"))
|
if (Token::Match(tok2, "[{}]"))
|
||||||
break;
|
break;
|
||||||
if (Token::Match(tok2, "sizeof ("))
|
if (Token::Match(tok2, "sizeof|typeof|typeid ("))
|
||||||
tok2 = tok2->linkAt(1);
|
tok2 = tok2->linkAt(1);
|
||||||
if (tok2->varId() == varid) {
|
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;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
std::list<ValueFlow::Value>::const_iterator it;
|
std::list<ValueFlow::Value>::const_iterator it;
|
||||||
for (it = values.begin(); it != values.end(); ++it)
|
for (it = values.begin(); it != values.end(); ++it)
|
||||||
setTokenValue(tok2, *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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1126,7 +1126,8 @@ private:
|
||||||
" std::string * x = 0;\n"
|
" std::string * x = 0;\n"
|
||||||
" *x = \"test\";\n"
|
" *x = \"test\";\n"
|
||||||
"}", false, "test.cpp", false);
|
"}", 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() {
|
void nullpointer10() {
|
||||||
|
@ -1156,7 +1157,8 @@ private:
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
check(code, false, "test.cpp", false); // C++ file => nullptr means NULL
|
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
|
check(code, false, "test.c", false); // C file => nullptr does not mean NULL
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
@ -1229,7 +1231,8 @@ private:
|
||||||
" i++;\n"
|
" i++;\n"
|
||||||
" };\n"
|
" };\n"
|
||||||
"}\n", false, "test.cpp", false);
|
"}\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
|
void nullpointer19() { // #3811
|
||||||
|
@ -1715,7 +1718,8 @@ private:
|
||||||
" int* p = 0;\n"
|
" int* p = 0;\n"
|
||||||
" return p[4];\n"
|
" return p[4];\n"
|
||||||
"}", false, "test.cpp", false);
|
"}", 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"
|
check("void f(int x) {\n" // #4809 - passing "NULL"
|
||||||
" itoa(x,NULL,10);\n"
|
" itoa(x,NULL,10);\n"
|
||||||
|
@ -1969,14 +1973,12 @@ private:
|
||||||
" std::string s5(p);\n"
|
" std::string s5(p);\n"
|
||||||
" foo(std::string(p));\n"
|
" foo(std::string(p));\n"
|
||||||
"}", true);
|
"}", true);
|
||||||
ASSERT_EQUALS("[test.cpp:7]: (error) Null pointer dereference\n"
|
ASSERT_EQUALS("[test.cpp:7]: (error) Possible null pointer dereference: p\n"
|
||||||
"[test.cpp:8]: (error) Null pointer dereference\n"
|
"[test.cpp:8]: (error) Possible null pointer dereference: p\n"
|
||||||
"[test.cpp:3]: (error) Null pointer dereference\n"
|
"[test.cpp:3]: (error) Null pointer dereference\n"
|
||||||
"[test.cpp:4]: (error) Null pointer dereference\n"
|
"[test.cpp:4]: (error) Null pointer dereference\n"
|
||||||
"[test.cpp:5]: (error) Null pointer dereference\n"
|
"[test.cpp:5]: (error) Null pointer dereference\n"
|
||||||
"[test.cpp:6]: (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:9]: (error) Possible null pointer dereference: p\n"
|
||||||
"[test.cpp:10]: (error) Possible null pointer dereference: p\n", errout.str());
|
"[test.cpp:10]: (error) Possible null pointer dereference: p\n", errout.str());
|
||||||
|
|
||||||
|
|
|
@ -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"
|
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: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: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() {
|
void simplifyTypedef36() {
|
||||||
|
|
Loading…
Reference in New Issue