Fixed #4666: Implemented proper variable scope checking for switch statements

This commit is contained in:
PKEuS 2013-03-23 03:28:33 -07:00
parent c9469993e2
commit 37ac86dec9
2 changed files with 88 additions and 3 deletions

View File

@ -2141,8 +2141,18 @@ bool CheckOther::checkInnerScope(const Token *tok, const Variable* var, bool& us
end = end->linkAt(2);
} else if (loopVariable && tok->strAt(-1) == ")") {
tok = tok->linkAt(-1); // Jump to opening ( of for/while statement
} else if (scope->type == Scope::eSwitch)
return false; // TODO: Support switch properly
} else if (scope->type == Scope::eSwitch) {
for (std::list<Scope*>::const_iterator i = scope->nestedList.begin(); i != scope->nestedList.end(); ++i) {
if (used) {
bool used2 = false;
if (!checkInnerScope((*i)->classStart, var, used2) || used2) {
return false;
}
} else if (!checkInnerScope((*i)->classStart, var, used)) {
return false;
}
}
}
for (; tok != end; tok = tok->next()) {
if (tok->str() == "goto")
@ -2183,8 +2193,11 @@ bool CheckOther::checkInnerScope(const Token *tok, const Variable* var, bool& us
if (Token::Match(tok, "= %varid%", var->varId()) && (var->isArray() || var->isPointer())) // Create a copy of array/pointer. Bailout, because the memory it points to might be necessary in outer scope
return false;
if (tok->varId() == var->varId())
if (tok->varId() == var->varId()) {
used = true;
if (scope->type == Scope::eSwitch && scope == tok->scope())
return false; // Used in outer switch scope - unsafe or impossible to reduce scope
}
}
return true;

View File

@ -70,6 +70,7 @@ private:
TEST_CASE(varScope15); // #4573 if-else-if
TEST_CASE(varScope16);
TEST_CASE(varScope17);
TEST_CASE(varScope18);
TEST_CASE(oldStylePointerCast);
TEST_CASE(invalidPointerCast);
@ -927,6 +928,77 @@ private:
ASSERT_EQUALS("[test.cpp:2]: (style) The scope of the variable 'x' can be reduced.\n", errout.str());
}
void varScope18() {
varScope("void f() {\n"
" short x;\n"
"\n"
" switch (ab) {\n"
" case A:\n"
" break;\n"
" case B:\n"
" default:\n"
" break;\n"
" }\n"
"\n"
" if (c) {\n"
" x = foo();\n"
" do_something(x);\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (style) The scope of the variable 'x' can be reduced.\n", errout.str());
varScope("void f() {\n"
" short x;\n"
"\n"
" switch (ab) {\n"
" case A:\n"
" x = 10;\n"
" break;\n"
" case B:\n"
" default:\n"
" break;\n"
" }\n"
"\n"
" if (c) {\n"
" x = foo();\n"
" do_something(x);\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
varScope("void f() {\n"
" short x;\n"
"\n"
" switch (ab) {\n"
" case A:\n"
" if(c)\n"
" do_something(x);\n"
" break;\n"
" case B:\n"
" default:\n"
" break;\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (style) The scope of the variable 'x' can be reduced.\n", errout.str());
varScope("void f() {\n"
" short x;\n"
"\n"
" switch (ab) {\n"
" case A:\n"
" if(c)\n"
" do_something(x);\n"
" break;\n"
" case B:\n"
" default:\n"
" if(d)\n"
" do_something(x);\n"
" break;\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void checkOldStylePointerCast(const char code[]) {
// Clear the error buffer..
errout.str("");