uninitvar: use new checking instead of executionpath in more tests. small improvements in new checking to fix testcases.
This commit is contained in:
parent
239f0d4ab4
commit
79067ac031
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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) */
|
||||
|
|
|
@ -603,7 +603,7 @@ private:
|
|||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: c\n", errout.str());
|
||||
|
||||
checkUninitVar("void f()\n"
|
||||
checkUninitVar2("void f()\n"
|
||||
"{\n"
|
||||
" char *s = malloc(100);\n"
|
||||
" *s += 10;\n"
|
||||
|
@ -919,12 +919,11 @@ private:
|
|||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
// ? :
|
||||
checkUninitVar("static void foo(int v)\n"
|
||||
"{\n"
|
||||
checkUninitVar2("static void foo(int v) {\n"
|
||||
" int x;\n"
|
||||
" x = v <= 0 ? -1 : x;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: x\n", errout.str());
|
||||
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"
|
||||
checkUninitVar2("static int foo() {\n"
|
||||
" int ret;\n"
|
||||
" return ret;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: ret\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: ret\n", errout.str());
|
||||
|
||||
checkUninitVar("static int foo()\n"
|
||||
"{\n"
|
||||
checkUninitVar2("static int foo() {\n"
|
||||
" int ret;\n"
|
||||
" return ret+5;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: ret\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: ret\n", errout.str());
|
||||
|
||||
checkUninitVarB("static int foo() {\n"
|
||||
" int ret;\n"
|
||||
|
@ -1750,7 +1747,7 @@ private:
|
|||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
checkUninitVar("static int foo() {\n"
|
||||
checkUninitVar2("static int foo() {\n"
|
||||
" int ret;\n"
|
||||
" return cin >> ret;\n"
|
||||
"}\n", "test.c");
|
||||
|
@ -1759,7 +1756,7 @@ private:
|
|||
|
||||
// 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,7 +1800,7 @@ private:
|
|||
}
|
||||
|
||||
// Ticket #2146 - False negative
|
||||
checkUninitVar("int f(int x) {\n"
|
||||
checkUninitVar2("int f(int x) {\n"
|
||||
" int y;\n"
|
||||
" return x ? 1 : y;\n"
|
||||
"}");
|
||||
|
@ -1819,7 +1814,7 @@ private:
|
|||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
checkUninitVar("int f() {\n"
|
||||
checkUninitVar2("int f() {\n"
|
||||
" int i;\n"
|
||||
" return x() ? i : 0;\n"
|
||||
"}");
|
||||
|
|
Loading…
Reference in New Issue