uninitvar: use new checking instead of executionpath in more tests. small improvements in new checking to fix testcases.

This commit is contained in:
Daniel Marjamäki 2015-07-23 08:46:59 +02:00
parent 239f0d4ab4
commit 79067ac031
3 changed files with 66 additions and 70 deletions

View File

@ -1069,11 +1069,11 @@ void CheckUninitVar::checkScope(const Scope* scope)
continue; continue;
if (Token::Match(i->nameToken(), "%name% =")) { // Variable is initialized, but Rhs might be not if (Token::Match(i->nameToken(), "%name% =")) { // Variable is initialized, but Rhs might be not
checkRhs(i->nameToken(), *i, NO_ALLOC, ""); checkRhs(i->nameToken(), *i, NO_ALLOC, 0U, "");
continue; continue;
} }
if (Token::Match(i->nameToken(), "%name% ) (") && Token::simpleMatch(i->nameToken()->linkAt(2), ") =")) { // Function pointer is initialized, but Rhs might be not if (Token::Match(i->nameToken(), "%name% ) (") && Token::simpleMatch(i->nameToken()->linkAt(2), ") =")) { // Function pointer is initialized, but Rhs might be not
checkRhs(i->nameToken()->linkAt(2)->next(), *i, NO_ALLOC, ""); checkRhs(i->nameToken()->linkAt(2)->next(), *i, NO_ALLOC, 0U, "");
continue; continue;
} }
@ -1463,12 +1463,8 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var
const bool used1 = isVariableUsed(tok->astOperand2()->astOperand1(), var); const bool used1 = isVariableUsed(tok->astOperand2()->astOperand1(), var);
const bool used0 = isVariableUsed(tok->astOperand2()->astOperand2(), var); const bool used0 = isVariableUsed(tok->astOperand2()->astOperand2(), var);
const bool err = (number_of_if == 0) ? (used1 || used0) : (used1 && used0); const bool err = (number_of_if == 0) ? (used1 || used0) : (used1 && used0);
if (err) { if (err)
if (*alloc != NO_ALLOC) uninitvarError(tok, var.nameToken()->str(), *alloc);
uninitdataError(tok, var.nameToken()->str());
else
uninitvarError(tok, var.nameToken()->str());
}
// Todo: skip expression if there is no error // Todo: skip expression if there is no error
return true; return true;
@ -1490,10 +1486,8 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var
// Use variable // Use variable
else if (!suppressErrors && isVariableUsage(tok, var.isPointer(), *alloc)) { else if (!suppressErrors && isVariableUsage(tok, var.isPointer(), *alloc)) {
if (*alloc != NO_ALLOC) uninitvarError(tok, tok->str(), *alloc);
uninitdataError(tok, tok->str()); return true;
else
uninitvarError(tok, tok->str());
} }
else else
@ -1510,12 +1504,8 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var
const bool used1 = isVariableUsed(tok->astOperand2()->astOperand1(), var); const bool used1 = isVariableUsed(tok->astOperand2()->astOperand1(), var);
const bool used0 = isVariableUsed(tok->astOperand2()->astOperand2(), var); const bool used0 = isVariableUsed(tok->astOperand2()->astOperand2(), var);
const bool err = (number_of_if == 0) ? (used1 || used0) : (used1 && used0); const bool err = (number_of_if == 0) ? (used1 || used0) : (used1 && used0);
if (err) { if (err)
if (*alloc != NO_ALLOC) uninitvarError(tok, var.nameToken()->str(), *alloc);
uninitdataError(tok, var.nameToken()->str());
else
uninitvarError(tok, var.nameToken()->str());
}
return true; return true;
} }
@ -1545,7 +1535,7 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var
if (!membervar.empty()) { if (!membervar.empty()) {
if (isMemberVariableAssignment(tok, membervar)) { if (isMemberVariableAssignment(tok, membervar)) {
checkRhs(tok, var, *alloc, membervar); checkRhs(tok, var, *alloc, number_of_if, membervar);
return true; return true;
} }
@ -1558,15 +1548,13 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var
} else { } else {
// Use variable // Use variable
if (!suppressErrors && isVariableUsage(tok, var.isPointer(), *alloc)) { if (!suppressErrors && isVariableUsage(tok, var.isPointer(), *alloc)) {
if (*alloc != NO_ALLOC) uninitvarError(tok, tok->str(), *alloc);
uninitdataError(tok, tok->str()); return true;
else
uninitvarError(tok, tok->str());
} }
else { else {
if (tok->strAt(1) == "=") if (tok->strAt(1) == "=")
checkRhs(tok, var, *alloc, ""); checkRhs(tok, var, *alloc, number_of_if, "");
// assume that variable is assigned // assume that variable is assigned
return true; return true;
@ -1599,7 +1587,7 @@ bool CheckUninitVar::checkIfForWhileHead(const Token *startparentheses, const Va
if (isVariableUsage(tok, var.isPointer(), alloc)) { if (isVariableUsage(tok, var.isPointer(), alloc)) {
if (suppressErrors) if (suppressErrors)
continue; continue;
uninitvarError(tok, tok->str()); uninitvarError(tok, tok->str(), alloc);
} }
return true; return true;
} }
@ -1684,7 +1672,7 @@ bool CheckUninitVar::checkLoopBody(const Token *tok, const Variable& var, const
if (!suppressErrors && usetok) { if (!suppressErrors && usetok) {
if (membervar.empty()) if (membervar.empty())
uninitvarError(usetok, usetok->str()); uninitvarError(usetok, usetok->str(), alloc);
else else
uninitStructMemberError(usetok, usetok->str() + "." + membervar); uninitStructMemberError(usetok, usetok->str() + "." + membervar);
return true; return true;
@ -1693,7 +1681,7 @@ bool CheckUninitVar::checkLoopBody(const Token *tok, const Variable& var, const
return false; return false;
} }
void CheckUninitVar::checkRhs(const Token *tok, const Variable &var, Alloc alloc, const std::string &membervar) void CheckUninitVar::checkRhs(const Token *tok, const Variable &var, Alloc alloc, unsigned int number_of_if, const std::string &membervar)
{ {
bool rhs = false; bool rhs = false;
unsigned int indent = 0; unsigned int indent = 0;
@ -1702,7 +1690,7 @@ void CheckUninitVar::checkRhs(const Token *tok, const Variable &var, Alloc alloc
rhs = true; rhs = true;
else if (rhs && tok->varId() == var.declarationId()) { else if (rhs && tok->varId() == var.declarationId()) {
if (membervar.empty() && isVariableUsage(tok, var.isPointer(), alloc)) if (membervar.empty() && isVariableUsage(tok, var.isPointer(), alloc))
uninitvarError(tok, tok->str()); uninitvarError(tok, tok->str(), alloc);
else if (!membervar.empty() && isMemberVariableUsage(tok, var.isPointer(), alloc, membervar)) else if (!membervar.empty() && isMemberVariableUsage(tok, var.isPointer(), alloc, membervar))
uninitStructMemberError(tok, tok->str() + "." + membervar); uninitStructMemberError(tok, tok->str() + "." + membervar);
@ -1714,6 +1702,13 @@ void CheckUninitVar::checkRhs(const Token *tok, const Variable &var, Alloc alloc
if (indent == 0) if (indent == 0)
break; break;
--indent; --indent;
} else if (tok->str() == "?" && tok->astOperand2()) {
const bool used1 = isVariableUsed(tok->astOperand2()->astOperand1(), var);
const bool used0 = isVariableUsed(tok->astOperand2()->astOperand2(), var);
const bool err = (number_of_if == 0) ? (used1 || used0) : (used1 && used0);
if (err)
uninitvarError(tok, var.nameToken()->str(), alloc);
break;
} else if (Token::simpleMatch(tok, "sizeof (")) } else if (Token::simpleMatch(tok, "sizeof ("))
tok = tok->next()->link(); tok = tok->next()->link();
} }

View File

@ -61,7 +61,7 @@ public:
bool checkScopeForVariable(const Token *tok, const Variable& var, bool* const possibleInit, bool* const noreturn, Alloc* const alloc, const std::string &membervar); bool checkScopeForVariable(const Token *tok, const Variable& var, bool* const possibleInit, bool* const noreturn, Alloc* const alloc, const std::string &membervar);
bool checkIfForWhileHead(const Token *startparentheses, const Variable& var, bool suppressErrors, bool isuninit, Alloc alloc, const std::string &membervar); bool checkIfForWhileHead(const Token *startparentheses, const Variable& var, bool suppressErrors, bool isuninit, Alloc alloc, const std::string &membervar);
bool checkLoopBody(const Token *tok, const Variable& var, const Alloc alloc, const std::string &membervar, const bool suppressErrors); bool checkLoopBody(const Token *tok, const Variable& var, const Alloc alloc, const std::string &membervar, const bool suppressErrors);
void checkRhs(const Token *tok, const Variable &var, Alloc alloc, const std::string &membervar); void checkRhs(const Token *tok, const Variable &var, Alloc alloc, unsigned int number_of_if, const std::string &membervar);
bool isVariableUsage(const Token *vartok, bool ispointer, Alloc alloc) const; bool isVariableUsage(const Token *vartok, bool ispointer, Alloc alloc) const;
int isFunctionParUsage(const Token *vartok, bool ispointer, Alloc alloc) const; int isFunctionParUsage(const Token *vartok, bool ispointer, Alloc alloc) const;
bool isMemberVariableAssignment(const Token *tok, const std::string &membervar) const; bool isMemberVariableAssignment(const Token *tok, const std::string &membervar) const;
@ -95,6 +95,12 @@ public:
void uninitstringError(const Token *tok, const std::string &varname, bool strncpy_); void uninitstringError(const Token *tok, const std::string &varname, bool strncpy_);
void uninitdataError(const Token *tok, const std::string &varname); void uninitdataError(const Token *tok, const std::string &varname);
void uninitvarError(const Token *tok, const std::string &varname); void uninitvarError(const Token *tok, const std::string &varname);
void uninitvarError(const Token *tok, const std::string &varname, Alloc alloc) {
if (alloc == NO_ALLOC)
uninitvarError(tok, varname);
else
uninitdataError(tok, varname);
}
void uninitStructMemberError(const Token *tok, const std::string &membername); void uninitStructMemberError(const Token *tok, const std::string &membername);
/** testrunner: (don't abort() when assertion fails, just write error message) */ /** testrunner: (don't abort() when assertion fails, just write error message) */

View File

@ -603,11 +603,11 @@ private:
"}"); "}");
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: c\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: c\n", errout.str());
checkUninitVar("void f()\n" checkUninitVar2("void f()\n"
"{\n" "{\n"
" char *s = malloc(100);\n" " char *s = malloc(100);\n"
" *s += 10;\n" " *s += 10;\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:4]: (error) Memory is allocated but not initialized: s\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Memory is allocated but not initialized: s\n", errout.str());
checkUninitVar("void f()\n" checkUninitVar("void f()\n"
@ -919,12 +919,11 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
// ? : // ? :
checkUninitVar("static void foo(int v)\n" checkUninitVar2("static void foo(int v) {\n"
"{\n" " int x;\n"
" int x;\n" " x = v <= 0 ? -1 : x;\n"
" x = v <= 0 ? -1 : x;\n" "}");
"}"); ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: x\n", errout.str());
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: x\n", errout.str());
checkUninitVarB("void foo()\n" checkUninitVarB("void foo()\n"
"{\n" "{\n"
@ -1723,19 +1722,17 @@ private:
void uninitvar_return() { void uninitvar_return() {
checkUninitVar("static int foo()\n" checkUninitVar2("static int foo() {\n"
"{\n" " int ret;\n"
" int ret;\n" " return ret;\n"
" return ret;\n" "}");
"}"); ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: ret\n", errout.str());
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: ret\n", errout.str());
checkUninitVar("static int foo()\n" checkUninitVar2("static int foo() {\n"
"{\n" " int ret;\n"
" int ret;\n" " return ret+5;\n"
" return ret+5;\n" "}");
"}"); ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: ret\n", errout.str());
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: ret\n", errout.str());
checkUninitVarB("static int foo() {\n" checkUninitVarB("static int foo() {\n"
" int ret;\n" " int ret;\n"
@ -1750,16 +1747,16 @@ private:
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
checkUninitVar("static int foo() {\n" checkUninitVar2("static int foo() {\n"
" int ret;\n" " int ret;\n"
" return cin >> ret;\n" " return cin >> ret;\n"
"}\n", "test.c"); "}\n", "test.c");
ASSERT_EQUALS("[test.c:3]: (error) Uninitialized variable: ret\n", errout.str()); ASSERT_EQUALS("[test.c:3]: (error) Uninitialized variable: ret\n", errout.str());
} }
// Ticket #6341- False negative // Ticket #6341- False negative
{ {
checkUninitVarB("wchar_t f() { int i; return btowc(i); }"); checkUninitVar2("wchar_t f() { int i; return btowc(i); }");
ASSERT_EQUALS("[test.cpp:1]: (error) Uninitialized variable: i\n", errout.str()); ASSERT_EQUALS("[test.cpp:1]: (error) Uninitialized variable: i\n", errout.str());
checkUninitVarB("wchar_t f(int i) { return btowc(i); }"); checkUninitVarB("wchar_t f(int i) { return btowc(i); }");
@ -1780,8 +1777,7 @@ private:
// Ticket #5412 - False negative // Ticket #5412 - False negative
{ {
checkUninitVarB("void f(bool b)\n" checkUninitVar2("void f(bool b) {\n"
"{\n"
" double f;\n" " double f;\n"
" if (b) { }\n" " if (b) { }\n"
" else {\n" " else {\n"
@ -1789,11 +1785,10 @@ private:
" }\n" " }\n"
" printf (\"%f\",f);\n" " printf (\"%f\",f);\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:8]: (error) Uninitialized variable: f\n", errout.str()); ASSERT_EQUALS("[test.cpp:7]: (error) Uninitialized variable: f\n", errout.str());
// Check for potential FP // Check for potential FP
checkUninitVarB("void f(bool b)\n" checkUninitVarB("void f(bool b) {\n"
"{\n"
" double f;\n" " double f;\n"
" if (b) { f = 1.0 }\n" " if (b) { f = 1.0 }\n"
" else {\n" " else {\n"
@ -1805,10 +1800,10 @@ private:
} }
// Ticket #2146 - False negative // Ticket #2146 - False negative
checkUninitVar("int f(int x) {\n" checkUninitVar2("int f(int x) {\n"
" int y;\n" " int y;\n"
" return x ? 1 : y;\n" " return x ? 1 : y;\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: y\n", errout.str()); ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: y\n", errout.str());
// Ticket #3106 - False positive // Ticket #3106 - False positive
@ -1819,10 +1814,10 @@ private:
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
checkUninitVar("int f() {\n" checkUninitVar2("int f() {\n"
" int i;\n" " int i;\n"
" return x() ? i : 0;\n" " return x() ? i : 0;\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: i\n", errout.str()); ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: i\n", errout.str());
} }