Fixed false negatives on try and non-executable scopes in checkUninitVar, removed unnecessary function parameters

This commit is contained in:
PKEuS 2015-01-22 13:51:43 +01:00
parent bdae9064ea
commit f4d11a4209
3 changed files with 44 additions and 20 deletions

View File

@ -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;
} }

View File

@ -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);

View File

@ -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