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;
|
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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) */
|
||||||
|
|
|
@ -603,7 +603,7 @@ 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"
|
||||||
|
@ -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:4]: (error) Uninitialized variable: x\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:3]: (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: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"
|
checkUninitVar2("static int foo() {\n"
|
||||||
"{\n"
|
|
||||||
" int ret;\n"
|
" int ret;\n"
|
||||||
" return ret+5;\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"
|
checkUninitVarB("static int foo() {\n"
|
||||||
" int ret;\n"
|
" int ret;\n"
|
||||||
|
@ -1750,7 +1747,7 @@ 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");
|
||||||
|
@ -1759,7 +1756,7 @@ private:
|
||||||
|
|
||||||
// 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,7 +1800,7 @@ 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"
|
||||||
"}");
|
"}");
|
||||||
|
@ -1819,7 +1814,7 @@ 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"
|
||||||
"}");
|
"}");
|
||||||
|
|
Loading…
Reference in New Issue