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;
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;
}
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;
}
@ -1463,12 +1463,8 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var
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) {
if (*alloc != NO_ALLOC)
uninitdataError(tok, var.nameToken()->str());
else
uninitvarError(tok, var.nameToken()->str());
}
if (err)
uninitvarError(tok, var.nameToken()->str(), *alloc);
// Todo: skip expression if there is no error
return true;
@ -1490,10 +1486,8 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var
// Use variable
else if (!suppressErrors && isVariableUsage(tok, var.isPointer(), *alloc)) {
if (*alloc != NO_ALLOC)
uninitdataError(tok, tok->str());
else
uninitvarError(tok, tok->str());
uninitvarError(tok, tok->str(), *alloc);
return true;
}
else
@ -1510,12 +1504,8 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var
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) {
if (*alloc != NO_ALLOC)
uninitdataError(tok, var.nameToken()->str());
else
uninitvarError(tok, var.nameToken()->str());
}
if (err)
uninitvarError(tok, var.nameToken()->str(), *alloc);
return true;
}
@ -1545,7 +1535,7 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var
if (!membervar.empty()) {
if (isMemberVariableAssignment(tok, membervar)) {
checkRhs(tok, var, *alloc, membervar);
checkRhs(tok, var, *alloc, number_of_if, membervar);
return true;
}
@ -1558,15 +1548,13 @@ bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var
} else {
// Use variable
if (!suppressErrors && isVariableUsage(tok, var.isPointer(), *alloc)) {
if (*alloc != NO_ALLOC)
uninitdataError(tok, tok->str());
else
uninitvarError(tok, tok->str());
uninitvarError(tok, tok->str(), *alloc);
return true;
}
else {
if (tok->strAt(1) == "=")
checkRhs(tok, var, *alloc, "");
checkRhs(tok, var, *alloc, number_of_if, "");
// assume that variable is assigned
return true;
@ -1599,7 +1587,7 @@ bool CheckUninitVar::checkIfForWhileHead(const Token *startparentheses, const Va
if (isVariableUsage(tok, var.isPointer(), alloc)) {
if (suppressErrors)
continue;
uninitvarError(tok, tok->str());
uninitvarError(tok, tok->str(), alloc);
}
return true;
}
@ -1684,7 +1672,7 @@ bool CheckUninitVar::checkLoopBody(const Token *tok, const Variable& var, const
if (!suppressErrors && usetok) {
if (membervar.empty())
uninitvarError(usetok, usetok->str());
uninitvarError(usetok, usetok->str(), alloc);
else
uninitStructMemberError(usetok, usetok->str() + "." + membervar);
return true;
@ -1693,7 +1681,7 @@ bool CheckUninitVar::checkLoopBody(const Token *tok, const Variable& var, const
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;
unsigned int indent = 0;
@ -1702,7 +1690,7 @@ void CheckUninitVar::checkRhs(const Token *tok, const Variable &var, Alloc alloc
rhs = true;
else if (rhs && tok->varId() == var.declarationId()) {
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))
uninitStructMemberError(tok, tok->str() + "." + membervar);
@ -1714,6 +1702,13 @@ void CheckUninitVar::checkRhs(const Token *tok, const Variable &var, Alloc alloc
if (indent == 0)
break;
--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 ("))
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 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);
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;
int isFunctionParUsage(const Token *vartok, bool ispointer, Alloc alloc) 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 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, Alloc alloc) {
if (alloc == NO_ALLOC)
uninitvarError(tok, varname);
else
uninitdataError(tok, varname);
}
void uninitStructMemberError(const Token *tok, const std::string &membername);
/** 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());
checkUninitVar("void f()\n"
"{\n"
" char *s = malloc(100);\n"
" *s += 10;\n"
"}");
checkUninitVar2("void f()\n"
"{\n"
" char *s = malloc(100);\n"
" *s += 10;\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (error) Memory is allocated but not initialized: s\n", errout.str());
checkUninitVar("void f()\n"
@ -919,12 +919,11 @@ private:
ASSERT_EQUALS("", errout.str());
// ? :
checkUninitVar("static void foo(int v)\n"
"{\n"
" int x;\n"
" x = v <= 0 ? -1 : x;\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: x\n", errout.str());
checkUninitVar2("static void foo(int v) {\n"
" int x;\n"
" x = v <= 0 ? -1 : x;\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: x\n", errout.str());
checkUninitVarB("void foo()\n"
"{\n"
@ -1723,19 +1722,17 @@ private:
void uninitvar_return() {
checkUninitVar("static int foo()\n"
"{\n"
" int ret;\n"
" return ret;\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: ret\n", errout.str());
checkUninitVar2("static int foo() {\n"
" int ret;\n"
" return ret;\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: ret\n", errout.str());
checkUninitVar("static int foo()\n"
"{\n"
" int ret;\n"
" return ret+5;\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: ret\n", errout.str());
checkUninitVar2("static int foo() {\n"
" int ret;\n"
" return ret+5;\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: ret\n", errout.str());
checkUninitVarB("static int foo() {\n"
" int ret;\n"
@ -1750,16 +1747,16 @@ private:
"}");
ASSERT_EQUALS("", errout.str());
checkUninitVar("static int foo() {\n"
" int ret;\n"
" return cin >> ret;\n"
"}\n", "test.c");
checkUninitVar2("static int foo() {\n"
" int ret;\n"
" return cin >> ret;\n"
"}\n", "test.c");
ASSERT_EQUALS("[test.c:3]: (error) Uninitialized variable: ret\n", errout.str());
}
// 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());
checkUninitVarB("wchar_t f(int i) { return btowc(i); }");
@ -1780,8 +1777,7 @@ private:
// Ticket #5412 - False negative
{
checkUninitVarB("void f(bool b)\n"
"{\n"
checkUninitVar2("void f(bool b) {\n"
" double f;\n"
" if (b) { }\n"
" else {\n"
@ -1789,11 +1785,10 @@ private:
" }\n"
" printf (\"%f\",f);\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
checkUninitVarB("void f(bool b)\n"
"{\n"
checkUninitVarB("void f(bool b) {\n"
" double f;\n"
" if (b) { f = 1.0 }\n"
" else {\n"
@ -1805,10 +1800,10 @@ private:
}
// Ticket #2146 - False negative
checkUninitVar("int f(int x) {\n"
" int y;\n"
" return x ? 1 : y;\n"
"}");
checkUninitVar2("int f(int x) {\n"
" int y;\n"
" return x ? 1 : y;\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: y\n", errout.str());
// Ticket #3106 - False positive
@ -1819,10 +1814,10 @@ private:
"}");
ASSERT_EQUALS("", errout.str());
checkUninitVar("int f() {\n"
" int i;\n"
" return x() ? i : 0;\n"
"}");
checkUninitVar2("int f() {\n"
" int i;\n"
" return x() ? i : 0;\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: i\n", errout.str());
}