Fixed false positive about redundant variable assignment in try-scopes if the variable is read in catch block (#6555)
This commit is contained in:
parent
a8cf63239a
commit
36c5815ddb
|
@ -458,6 +458,28 @@ static void eraseMemberAssignments(const unsigned int varId, const std::map<unsi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool checkExceptionHandling(const Token* tok)
|
||||||
|
{
|
||||||
|
const Variable* var = tok->variable();
|
||||||
|
const Scope* upperScope = tok->scope();
|
||||||
|
if (upperScope == var->scope())
|
||||||
|
return true;
|
||||||
|
while (upperScope && upperScope->type != Scope::eTry && upperScope->type != Scope::eLambda && upperScope->nestedIn != var->scope() && upperScope->isExecutable()) {
|
||||||
|
upperScope = upperScope->nestedIn;
|
||||||
|
}
|
||||||
|
if (upperScope && upperScope->type == Scope::eTry) {
|
||||||
|
// Check all exception han
|
||||||
|
const Token* tok2 = upperScope->classEnd;
|
||||||
|
while (Token::simpleMatch(tok2, "} catch (")) {
|
||||||
|
tok2 = tok2->linkAt(2)->next();
|
||||||
|
if (Token::findmatch(tok2, "%varid%", tok2->link(), var->declarationId()))
|
||||||
|
return false;
|
||||||
|
tok2 = tok2->link();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void CheckOther::checkRedundantAssignment()
|
void CheckOther::checkRedundantAssignment()
|
||||||
{
|
{
|
||||||
const bool printPerformance = _settings->isEnabled("performance");
|
const bool printPerformance = _settings->isEnabled("performance");
|
||||||
|
@ -541,7 +563,8 @@ void CheckOther::checkRedundantAssignment()
|
||||||
else if (printPerformance) {
|
else if (printPerformance) {
|
||||||
const bool nonlocal = nonLocal(it->second->variable());
|
const bool nonlocal = nonLocal(it->second->variable());
|
||||||
if (printInconclusive || !nonlocal) // see #5089 - report inconclusive only when requested
|
if (printInconclusive || !nonlocal) // see #5089 - report inconclusive only when requested
|
||||||
redundantAssignmentError(it->second, tok, tok->str(), nonlocal); // Inconclusive for non-local variables
|
if (_tokenizer->isC() || checkExceptionHandling(tok)) // see #6555 to see how exception handling might have an impact
|
||||||
|
redundantAssignmentError(it->second, tok, tok->str(), nonlocal); // Inconclusive for non-local variables
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
it->second = tok;
|
it->second = tok;
|
||||||
|
|
|
@ -5568,6 +5568,46 @@ private:
|
||||||
" i = 1;\n"
|
" i = 1;\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
// #6555
|
||||||
|
check("void foo() {\n"
|
||||||
|
" char *p = 0;\n"
|
||||||
|
" try {\n"
|
||||||
|
" p = fred();\n"
|
||||||
|
" p = wilma();\n"
|
||||||
|
" }\n"
|
||||||
|
" catch (...) {\n"
|
||||||
|
" barney(p);\n"
|
||||||
|
" }\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("void foo() {\n"
|
||||||
|
" char *p = 0;\n"
|
||||||
|
" try {\n"
|
||||||
|
" p = fred();\n"
|
||||||
|
" p = wilma();\n"
|
||||||
|
" }\n"
|
||||||
|
" catch (...) {\n"
|
||||||
|
" barney(x);\n"
|
||||||
|
" }\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:5]: (performance) Variable 'p' is reassigned a value before the old one has been used.\n"
|
||||||
|
"[test.cpp:2]: (style) The scope of the variable 'p' can be reduced.\n", errout.str());
|
||||||
|
|
||||||
|
check("void foo() {\n"
|
||||||
|
" char *p = 0;\n"
|
||||||
|
" try {\n"
|
||||||
|
" if(z) {\n"
|
||||||
|
" p = fred();\n"
|
||||||
|
" p = wilma();\n"
|
||||||
|
" }\n"
|
||||||
|
" }\n"
|
||||||
|
" catch (...) {\n"
|
||||||
|
" barney(p);\n"
|
||||||
|
" }\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void redundantMemWrite() {
|
void redundantMemWrite() {
|
||||||
|
|
Loading…
Reference in New Issue