Fixes issue with case inside switch that is not a compound statement (#1031)

* Fixes issue with case inside switch that is not a compound statement was treated as garbage

This fixes an issue with the check for case keywords outside of switch
detection that would treat a case statement inside a switch that is not
a compound statement as garbage, but this is perfectly valid C++. This
construct is used in several libraries, i.e. Google Test.

* Tweak check and handle missing semicolon

Tweaks the check with feedback from danmar.
Handle the case where there is no semicolon and document it with a unit
test.
This commit is contained in:
David Hallas 2018-01-27 22:21:26 +01:00 committed by Daniel Marjamäki
parent 5b6ec49a6f
commit 4d18d3948f
3 changed files with 20 additions and 4 deletions

View File

@ -8346,13 +8346,23 @@ const Token * Tokenizer::findGarbageCode() const
// case keyword must be inside switch
for (const Token *tok = tokens(); tok; tok = tok->next()) {
if (Token::simpleMatch(tok, "switch (") && Token::simpleMatch(tok->linkAt(1), ") {"))
if (Token::simpleMatch(tok, "switch (")) {
if (Token::simpleMatch(tok->linkAt(1), ") {")) {
tok = tok->linkAt(1)->linkAt(1);
else if (tok->str() == "(")
tok = tok->link();
else if (tok->str() == "case")
} else {
while (tok->str() != ";" && tok->str() != "{") {
if (tok->next() == nullptr) {
return tok;
}
tok = tok->next();
}
}
} else if (tok->str() == "(") {
tok = tok->link();
} else if (tok->str() == "case") {
return tok;
}
}
for (const Token *tok = tokens(); tok ; tok = tok->next()) {
if (!Token::simpleMatch(tok, "for (")) // find for loops

View File

@ -379,6 +379,9 @@ private:
//ticket #4267
ASSERT_THROW(checkCode("f ( ) { switch break; { switch ( x ) { case } case break; -6: ( ) ; } }"), InternalError);
// Missing semicolon
ASSERT_THROW(checkCode("void foo () { switch(0) case 0 : default : }"), InternalError);
}
void garbageCode1() {

View File

@ -4750,6 +4750,9 @@ private:
//ticket #3227
ASSERT_EQUALS("void foo ( ) { switch ( n ) { label : ; case 1 : ; label1 : ; label2 : ; break ; } }",
tokenizeAndStringify("void foo(){ switch (n){ label: case 1: label1: label2: break; }}"));
//ticket #8345
ASSERT_EQUALS("void foo ( ) { switch ( 0 ) { case 0 : ; default : ; } }",
tokenizeAndStringify("void foo () { switch(0) case 0 : default : ; }"));
}
void simplifyPointerToStandardType() {