Fixed false negatives on try and non-executable scopes in checkUninitVar, removed unnecessary function parameters
This commit is contained in:
parent
bdae9064ea
commit
f4d11a4209
|
@ -1087,10 +1087,10 @@ void CheckUninitVar::checkScope(const Scope* scope)
|
||||||
|
|
||||||
if (stdtype || i->isPointer()) {
|
if (stdtype || i->isPointer()) {
|
||||||
bool alloc = false;
|
bool alloc = false;
|
||||||
checkScopeForVariable(scope, tok, *i, nullptr, nullptr, &alloc, "");
|
checkScopeForVariable(tok, *i, nullptr, nullptr, &alloc, "");
|
||||||
}
|
}
|
||||||
if (i->type())
|
if (i->type())
|
||||||
checkStruct(scope, tok, *i);
|
checkStruct(tok, *i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scope->function) {
|
if (scope->function) {
|
||||||
|
@ -1102,10 +1102,10 @@ void CheckUninitVar::checkScope(const Scope* scope)
|
||||||
if (Token::Match(tok, "[;{}] %varid% = %var% (", arg->declarationId()) &&
|
if (Token::Match(tok, "[;{}] %varid% = %var% (", arg->declarationId()) &&
|
||||||
_settings->library.returnuninitdata.count(tok->strAt(3)) == 1U) {
|
_settings->library.returnuninitdata.count(tok->strAt(3)) == 1U) {
|
||||||
if (arg->typeStartToken()->str() == "struct")
|
if (arg->typeStartToken()->str() == "struct")
|
||||||
checkStruct(scope, tok, *arg);
|
checkStruct(tok, *arg);
|
||||||
else if (arg->typeStartToken()->isStandardType()) {
|
else if (arg->typeStartToken()->isStandardType()) {
|
||||||
bool alloc = false;
|
bool alloc = false;
|
||||||
checkScopeForVariable(scope, tok->next(), *arg, nullptr, nullptr, &alloc, "");
|
checkScopeForVariable(tok->next(), *arg, nullptr, nullptr, &alloc, "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1114,7 +1114,7 @@ void CheckUninitVar::checkScope(const Scope* scope)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckUninitVar::checkStruct(const Scope* scope, const Token *tok, const Variable &structvar)
|
void CheckUninitVar::checkStruct(const Token *tok, const Variable &structvar)
|
||||||
{
|
{
|
||||||
const Token *typeToken = structvar.typeStartToken();
|
const Token *typeToken = structvar.typeStartToken();
|
||||||
if (typeToken->str() == "struct")
|
if (typeToken->str() == "struct")
|
||||||
|
@ -1149,7 +1149,7 @@ void CheckUninitVar::checkStruct(const Scope* scope, const Token *tok, const Var
|
||||||
const Token *tok2 = tok;
|
const Token *tok2 = tok;
|
||||||
if (tok->str() == "}")
|
if (tok->str() == "}")
|
||||||
tok2 = tok2->next();
|
tok2 = tok2->next();
|
||||||
checkScopeForVariable(scope, tok2, structvar, nullptr, nullptr, &alloc, var.name());
|
checkScopeForVariable(tok2, structvar, nullptr, nullptr, &alloc, var.name());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1197,7 +1197,7 @@ static void conditionAlwaysTrueOrFalse(const Token *tok, const std::map<unsigned
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckUninitVar::checkScopeForVariable(const Scope* scope, const Token *tok, const Variable& var, bool * const possibleInit, bool * const noreturn, bool * const alloc, const std::string &membervar)
|
bool CheckUninitVar::checkScopeForVariable(const Token *tok, const Variable& var, bool * const possibleInit, bool * const noreturn, bool * const alloc, const std::string &membervar)
|
||||||
{
|
{
|
||||||
const bool suppressErrors(possibleInit && *possibleInit);
|
const bool suppressErrors(possibleInit && *possibleInit);
|
||||||
|
|
||||||
|
@ -1229,9 +1229,9 @@ bool CheckUninitVar::checkScopeForVariable(const Scope* scope, const Token *tok,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unconditional inner scope..
|
// Unconditional inner scope or try..
|
||||||
if (tok->str() == "{" && Token::Match(tok->previous(), "[;{}]")) {
|
if (tok->str() == "{" && Token::Match(tok->previous(), ";|{|}|try")) {
|
||||||
if (checkScopeForVariable(scope, tok->next(), var, possibleInit, nullptr, alloc, membervar))
|
if (checkScopeForVariable(tok->next(), var, possibleInit, noreturn, alloc, membervar))
|
||||||
return true;
|
return true;
|
||||||
tok = tok->link();
|
tok = tok->link();
|
||||||
continue;
|
continue;
|
||||||
|
@ -1242,7 +1242,7 @@ bool CheckUninitVar::checkScopeForVariable(const Scope* scope, const Token *tok,
|
||||||
variableValue[tok->varId()] = NOT_ZERO;
|
variableValue[tok->varId()] = NOT_ZERO;
|
||||||
|
|
||||||
// Inner scope..
|
// Inner scope..
|
||||||
if (Token::simpleMatch(tok, "if (")) {
|
else if (Token::simpleMatch(tok, "if (")) {
|
||||||
bool alwaysTrue = false;
|
bool alwaysTrue = false;
|
||||||
bool alwaysFalse = false;
|
bool alwaysFalse = false;
|
||||||
|
|
||||||
|
@ -1272,7 +1272,7 @@ bool CheckUninitVar::checkScopeForVariable(const Scope* scope, const Token *tok,
|
||||||
if (tok->str() == "{") {
|
if (tok->str() == "{") {
|
||||||
bool possibleInitIf(number_of_if > 0 || suppressErrors);
|
bool possibleInitIf(number_of_if > 0 || suppressErrors);
|
||||||
bool noreturnIf = false;
|
bool noreturnIf = false;
|
||||||
const bool initif = !alwaysFalse && checkScopeForVariable(scope, tok->next(), var, &possibleInitIf, &noreturnIf, alloc, membervar);
|
const bool initif = !alwaysFalse && checkScopeForVariable(tok->next(), var, &possibleInitIf, &noreturnIf, alloc, membervar);
|
||||||
|
|
||||||
// bail out for such code:
|
// bail out for such code:
|
||||||
// if (a) x=0; // conditional initialization
|
// if (a) x=0; // conditional initialization
|
||||||
|
@ -1322,7 +1322,7 @@ bool CheckUninitVar::checkScopeForVariable(const Scope* scope, const Token *tok,
|
||||||
|
|
||||||
bool possibleInitElse(number_of_if > 0 || suppressErrors);
|
bool possibleInitElse(number_of_if > 0 || suppressErrors);
|
||||||
bool noreturnElse = false;
|
bool noreturnElse = false;
|
||||||
const bool initelse = !alwaysTrue && checkScopeForVariable(scope, tok->next(), var, &possibleInitElse, nullptr, alloc, membervar);
|
const bool initelse = !alwaysTrue && checkScopeForVariable(tok->next(), var, &possibleInitElse, nullptr, alloc, membervar);
|
||||||
|
|
||||||
std::map<unsigned int, int> varValueElse;
|
std::map<unsigned int, int> varValueElse;
|
||||||
if (!alwaysTrue && !initelse && !noreturnElse) {
|
if (!alwaysTrue && !initelse && !noreturnElse) {
|
||||||
|
@ -1354,7 +1354,7 @@ bool CheckUninitVar::checkScopeForVariable(const Scope* scope, const Token *tok,
|
||||||
}
|
}
|
||||||
|
|
||||||
// = { .. }
|
// = { .. }
|
||||||
if (Token::simpleMatch(tok, "= {")) {
|
else if (Token::simpleMatch(tok, "= {")) {
|
||||||
// end token
|
// end token
|
||||||
const Token *end = tok->next()->link();
|
const Token *end = tok->next()->link();
|
||||||
|
|
||||||
|
@ -1372,7 +1372,7 @@ bool CheckUninitVar::checkScopeForVariable(const Scope* scope, const Token *tok,
|
||||||
tok = tok->next()->link();
|
tok = tok->next()->link();
|
||||||
|
|
||||||
// for/while..
|
// for/while..
|
||||||
if (Token::Match(tok, "for|while (") || Token::simpleMatch(tok, "do {")) {
|
else if (Token::Match(tok, "for|while (") || Token::simpleMatch(tok, "do {")) {
|
||||||
const bool forwhile = Token::Match(tok, "for|while (");
|
const bool forwhile = Token::Match(tok, "for|while (");
|
||||||
|
|
||||||
// is variable initialized in for-head (don't report errors yet)?
|
// is variable initialized in for-head (don't report errors yet)?
|
||||||
|
@ -1422,8 +1422,12 @@ bool CheckUninitVar::checkScopeForVariable(const Scope* scope, const Token *tok,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: handle loops, try, etc
|
// Unknown or unhandled inner scope
|
||||||
if (Token::simpleMatch(tok, ") {") || Token::Match(tok, "%var% {")) {
|
else if (Token::simpleMatch(tok, ") {") || (Token::Match(tok, "%var% {") && tok->str() != "try")) {
|
||||||
|
if (tok->str() == "struct" || tok->str() == "union") {
|
||||||
|
tok = tok->linkAt(1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ public:
|
||||||
/** @brief Run checks against the simplified token list */
|
/** @brief Run checks against the simplified token list */
|
||||||
void runSimplifiedChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) {
|
void runSimplifiedChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) {
|
||||||
CheckUninitVar checkUninitVar(tokenizer, settings, errorLogger);
|
CheckUninitVar checkUninitVar(tokenizer, settings, errorLogger);
|
||||||
checkUninitVar.executionPaths();
|
//checkUninitVar.executionPaths();
|
||||||
checkUninitVar.check();
|
checkUninitVar.check();
|
||||||
checkUninitVar.deadPointer();
|
checkUninitVar.deadPointer();
|
||||||
}
|
}
|
||||||
|
@ -56,8 +56,8 @@ public:
|
||||||
/** Check for uninitialized variables */
|
/** Check for uninitialized variables */
|
||||||
void check();
|
void check();
|
||||||
void checkScope(const Scope* scope);
|
void checkScope(const Scope* scope);
|
||||||
void checkStruct(const Scope* scope, const Token *tok, const Variable &structvar);
|
void checkStruct(const Token *tok, const Variable &structvar);
|
||||||
bool checkScopeForVariable(const Scope* scope, const Token *tok, const Variable& var, bool * const possibleInit, bool * const noreturn, bool * const alloc, const std::string &membervar);
|
bool checkScopeForVariable(const Token *tok, const Variable& var, bool * const possibleInit, bool * const noreturn, bool * const alloc, const std::string &membervar);
|
||||||
bool checkIfForWhileHead(const Token *startparentheses, const Variable& var, bool suppressErrors, bool isuninit, bool alloc, const std::string &membervar);
|
bool checkIfForWhileHead(const Token *startparentheses, const Variable& var, bool suppressErrors, bool isuninit, bool alloc, const std::string &membervar);
|
||||||
bool checkLoopBody(const Token *tok, const Variable& var, const bool alloc, const std::string &membervar, const bool suppressErrors);
|
bool checkLoopBody(const Token *tok, const Variable& var, const bool alloc, const std::string &membervar, const bool suppressErrors);
|
||||||
void checkRhs(const Token *tok, const Variable &var, bool alloc, const std::string &membervar);
|
void checkRhs(const Token *tok, const Variable &var, bool alloc, const std::string &membervar);
|
||||||
|
|
|
@ -70,6 +70,7 @@ private:
|
||||||
TEST_CASE(uninitvar7); // ticket #5971
|
TEST_CASE(uninitvar7); // ticket #5971
|
||||||
TEST_CASE(uninitvar8); // ticket #6230
|
TEST_CASE(uninitvar8); // ticket #6230
|
||||||
TEST_CASE(uninitvar9); // ticket #6424
|
TEST_CASE(uninitvar9); // ticket #6424
|
||||||
|
TEST_CASE(uninitvar_unconditionalTry);
|
||||||
|
|
||||||
TEST_CASE(syntax_error); // Ticket #5073
|
TEST_CASE(syntax_error); // Ticket #5073
|
||||||
|
|
||||||
|
@ -2745,6 +2746,25 @@ private:
|
||||||
"[test.cpp:4]: (error) Uninitialized variable: p\n", errout.str());
|
"[test.cpp:4]: (error) Uninitialized variable: p\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void uninitvar_unconditionalTry() {
|
||||||
|
// Unconditional scopes and try{} scopes
|
||||||
|
checkUninitVar2("int f() {\n"
|
||||||
|
" int i;\n"
|
||||||
|
" {\n"
|
||||||
|
" return i;\n"
|
||||||
|
" }\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: i\n", errout.str());
|
||||||
|
|
||||||
|
checkUninitVar2("int f() {\n"
|
||||||
|
" int i;\n"
|
||||||
|
" try {\n"
|
||||||
|
" return i;\n"
|
||||||
|
" } catch(...) {}\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: i\n", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
// Handling of function calls
|
// Handling of function calls
|
||||||
void uninitvar2_func() {
|
void uninitvar2_func() {
|
||||||
// non-pointer variable
|
// non-pointer variable
|
||||||
|
|
Loading…
Reference in New Issue