Improve support for labels in simplifyAddBraces step (#3278)
Previously only a single regular label before a compound statement was allowed in simplifyAddBracesPair() after if/switch/do/while/for. This patch adds support for: * case-labels; * labels before a single statement; * labels before try/catch blocks; * multiple consecutive labels. Additionally the code for skipping a case label was extracted into a separate function from simplifyLabelsCaseDefault() and reused in simplifyAddBracesPair().
This commit is contained in:
parent
f64011b669
commit
9652ca39a3
|
@ -3168,6 +3168,27 @@ static Token *skipTernaryOp(Token *tok)
|
||||||
return tok;
|
return tok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Skips until the colon at the end of the case label, the argument must point to the "case" token.
|
||||||
|
// In case of success returns the colon token.
|
||||||
|
// In case of failure returns the token that caused the error.
|
||||||
|
static Token *skipCaseLabel(Token *tok)
|
||||||
|
{
|
||||||
|
assert(tok->str() == "case");
|
||||||
|
while (nullptr != (tok = tok->next())) {
|
||||||
|
if (Token::Match(tok, "(|["))
|
||||||
|
tok = tok->link();
|
||||||
|
else if (tok->str() == "?") {
|
||||||
|
Token * tok1 = skipTernaryOp(tok);
|
||||||
|
if (!tok1)
|
||||||
|
return tok;
|
||||||
|
tok = tok1;
|
||||||
|
}
|
||||||
|
if (Token::Match(tok, "[:{};]"))
|
||||||
|
return tok;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
const Token * Tokenizer::startOfExecutableScope(const Token * tok)
|
const Token * Tokenizer::startOfExecutableScope(const Token * tok)
|
||||||
{
|
{
|
||||||
if (tok->str() != ")")
|
if (tok->str() != ")")
|
||||||
|
@ -3217,32 +3238,15 @@ void Tokenizer::simplifyLabelsCaseDefault()
|
||||||
tok = tok->link();
|
tok = tok->link();
|
||||||
|
|
||||||
if (Token::Match(tok, "[;{}:] case")) {
|
if (Token::Match(tok, "[;{}:] case")) {
|
||||||
while (nullptr != (tok = tok->next())) {
|
tok = skipCaseLabel(tok->next());
|
||||||
if (Token::Match(tok, "(|[")) {
|
|
||||||
tok = tok->link();
|
|
||||||
} else if (tok->str() == "?") {
|
|
||||||
Token *tok1 = skipTernaryOp(tok);
|
|
||||||
if (!tok1) {
|
|
||||||
syntaxError(tok);
|
|
||||||
}
|
|
||||||
tok = tok1;
|
|
||||||
}
|
|
||||||
if (Token::Match(tok->next(),"[:{};]"))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!tok)
|
if (!tok)
|
||||||
break;
|
break;
|
||||||
if (tok->str() != "case" && tok->next() && tok->next()->str() == ":") {
|
if (tok->str() != ":" || tok->strAt(-1) == "case" || !tok->next())
|
||||||
tok = tok->next();
|
|
||||||
if (!tok->next())
|
|
||||||
syntaxError(tok);
|
|
||||||
if (tok->next()->str() != ";" && tok->next()->str() != "case")
|
|
||||||
tok->insertToken(";");
|
|
||||||
else
|
|
||||||
tok = tok->previous();
|
|
||||||
} else {
|
|
||||||
syntaxError(tok);
|
syntaxError(tok);
|
||||||
}
|
if (tok->next()->str() != ";" && tok->next()->str() != "case")
|
||||||
|
tok->insertToken(";");
|
||||||
|
else
|
||||||
|
tok = tok->previous();
|
||||||
} else if (Token::Match(tok, "[;{}] %name% : !!;")) {
|
} else if (Token::Match(tok, "[;{}] %name% : !!;")) {
|
||||||
if (!cpp || !Token::Match(tok->next(), "class|struct|enum")) {
|
if (!cpp || !Token::Match(tok->next(), "class|struct|enum")) {
|
||||||
tok = tok->tokAt(2);
|
tok = tok->tokAt(2);
|
||||||
|
@ -6267,30 +6271,46 @@ Token *Tokenizer::simplifyAddBracesPair(Token *tok, bool commandWithCondition)
|
||||||
return tok;
|
return tok;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Skip labels
|
||||||
|
Token * tokStatement = tokAfterCondition;
|
||||||
|
while (true) {
|
||||||
|
if (Token::Match(tokStatement, "%name% :"))
|
||||||
|
tokStatement = tokStatement->tokAt(2);
|
||||||
|
else if (tokStatement->str() == "case") {
|
||||||
|
tokStatement = skipCaseLabel(tokStatement);
|
||||||
|
if (!tokStatement)
|
||||||
|
return tok;
|
||||||
|
if (tokStatement->str() != ":")
|
||||||
|
syntaxError(tokStatement);
|
||||||
|
tokStatement = tokStatement->next();
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
if (!tokStatement)
|
||||||
|
return tok;
|
||||||
|
}
|
||||||
Token * tokBracesEnd=nullptr;
|
Token * tokBracesEnd=nullptr;
|
||||||
if (tokAfterCondition->str()=="{") {
|
if (tokStatement->str() == "{") {
|
||||||
// already surrounded by braces
|
// already surrounded by braces
|
||||||
tokBracesEnd=tokAfterCondition->link();
|
if (tokStatement != tokAfterCondition) {
|
||||||
} else if (Token::simpleMatch(tokAfterCondition, "try {") &&
|
// Move the opening brace before labels
|
||||||
Token::simpleMatch(tokAfterCondition->linkAt(1), "} catch (")) {
|
Token::move(tokStatement, tokStatement, tokAfterCondition->previous());
|
||||||
|
}
|
||||||
|
tokBracesEnd = tokStatement->link();
|
||||||
|
} else if (Token::simpleMatch(tokStatement, "try {") &&
|
||||||
|
Token::simpleMatch(tokStatement->linkAt(1), "} catch (")) {
|
||||||
tokAfterCondition->previous()->insertToken("{");
|
tokAfterCondition->previous()->insertToken("{");
|
||||||
Token * tokOpenBrace = tokAfterCondition->previous();
|
Token * tokOpenBrace = tokAfterCondition->previous();
|
||||||
Token * tokEnd = tokAfterCondition->linkAt(1)->linkAt(2)->linkAt(1);
|
Token * tokEnd = tokStatement->linkAt(1)->linkAt(2)->linkAt(1);
|
||||||
if (!tokEnd) {
|
if (!tokEnd) {
|
||||||
syntaxError(tokAfterCondition);
|
syntaxError(tokStatement);
|
||||||
}
|
}
|
||||||
tokEnd->insertToken("}");
|
tokEnd->insertToken("}");
|
||||||
Token * tokCloseBrace = tokEnd->next();
|
Token * tokCloseBrace = tokEnd->next();
|
||||||
|
|
||||||
Token::createMutualLinks(tokOpenBrace, tokCloseBrace);
|
Token::createMutualLinks(tokOpenBrace, tokCloseBrace);
|
||||||
tokBracesEnd = tokCloseBrace;
|
tokBracesEnd = tokCloseBrace;
|
||||||
} else if (Token::Match(tokAfterCondition, "%name% : {")) {
|
|
||||||
tokAfterCondition->previous()->insertToken("{");
|
|
||||||
tokAfterCondition->linkAt(2)->insertToken("}");
|
|
||||||
tokBracesEnd = tokAfterCondition->linkAt(2)->next();
|
|
||||||
Token::createMutualLinks(tokAfterCondition->previous(), tokBracesEnd);
|
|
||||||
} else {
|
} else {
|
||||||
Token * tokEnd = simplifyAddBracesToCommand(tokAfterCondition);
|
Token * tokEnd = simplifyAddBracesToCommand(tokStatement);
|
||||||
if (!tokEnd) // Ticket #4887
|
if (!tokEnd) // Ticket #4887
|
||||||
return tok;
|
return tok;
|
||||||
if (tokEnd->str()!="}") {
|
if (tokEnd->str()!="}") {
|
||||||
|
|
|
@ -124,13 +124,19 @@ private:
|
||||||
TEST_CASE(ifAddBraces18); // #3424 - if if { } else else
|
TEST_CASE(ifAddBraces18); // #3424 - if if { } else else
|
||||||
TEST_CASE(ifAddBraces19); // #3928 - if for if else
|
TEST_CASE(ifAddBraces19); // #3928 - if for if else
|
||||||
TEST_CASE(ifAddBraces20); // #5012 - syntax error 'else }'
|
TEST_CASE(ifAddBraces20); // #5012 - syntax error 'else }'
|
||||||
TEST_CASE(ifAddBraces21); // #5332 - if (x) label: {} ..
|
TEST_CASE(ifAddBracesLabels); // #5332 - if (x) label: {} ..
|
||||||
|
|
||||||
|
TEST_CASE(switchAddBracesLabels);
|
||||||
|
|
||||||
TEST_CASE(whileAddBraces);
|
TEST_CASE(whileAddBraces);
|
||||||
|
TEST_CASE(whileAddBracesLabels);
|
||||||
|
|
||||||
TEST_CASE(doWhileAddBraces);
|
TEST_CASE(doWhileAddBraces);
|
||||||
|
TEST_CASE(doWhileAddBracesLabels);
|
||||||
|
|
||||||
TEST_CASE(forAddBraces1);
|
TEST_CASE(forAddBraces1);
|
||||||
TEST_CASE(forAddBraces2); // #5088
|
TEST_CASE(forAddBraces2); // #5088
|
||||||
|
TEST_CASE(forAddBracesLabels);
|
||||||
|
|
||||||
TEST_CASE(simplifyExternC);
|
TEST_CASE(simplifyExternC);
|
||||||
TEST_CASE(simplifyKeyword); // #5842 - remove C99 static keyword between []
|
TEST_CASE(simplifyKeyword); // #5842 - remove C99 static keyword between []
|
||||||
|
@ -1227,9 +1233,76 @@ private:
|
||||||
ASSERT_THROW(tokenizeAndStringify(code), InternalError);
|
ASSERT_THROW(tokenizeAndStringify(code), InternalError);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ifAddBraces21() { // #5332 - if (x) label: {} ...
|
void ifAddBracesLabels() {
|
||||||
const char code[] = "void f() { if(x) label: {} a=1; }";
|
// Labels before statement
|
||||||
ASSERT_EQUALS("void f ( ) { if ( x ) { label : ; { } } a = 1 ; }", tokenizeAndStringify(code));
|
ASSERT_EQUALS("int f ( int x ) {\n"
|
||||||
|
"if ( x ) {\n"
|
||||||
|
"l1 : ; l2 : ; return x ; }\n"
|
||||||
|
"}",
|
||||||
|
tokenizeAndStringify("int f(int x) {\n"
|
||||||
|
" if (x)\n"
|
||||||
|
" l1: l2: return x;\n"
|
||||||
|
"}"));
|
||||||
|
|
||||||
|
// Labels before {
|
||||||
|
ASSERT_EQUALS("int f ( int x ) {\n"
|
||||||
|
"if ( x )\n"
|
||||||
|
"{ l1 : ; l2 : ; return x ; }\n"
|
||||||
|
"}",
|
||||||
|
tokenizeAndStringify("int f(int x) {\n"
|
||||||
|
" if (x)\n"
|
||||||
|
" l1: l2: { return x; }\n"
|
||||||
|
"}"));
|
||||||
|
|
||||||
|
// Labels before try/catch
|
||||||
|
ASSERT_EQUALS("int f ( int x ) {\n"
|
||||||
|
"if ( x ) {\n"
|
||||||
|
"l1 : ; l2 : ;\n"
|
||||||
|
"try { throw 1 ; }\n"
|
||||||
|
"catch ( ... ) { return x ; } }\n"
|
||||||
|
"}",
|
||||||
|
tokenizeAndStringify("int f(int x) {\n"
|
||||||
|
" if (x)\n"
|
||||||
|
" l1: l2:\n"
|
||||||
|
" try { throw 1; }\n"
|
||||||
|
" catch(...) { return x; }\n"
|
||||||
|
"}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void switchAddBracesLabels() {
|
||||||
|
// Labels before statement
|
||||||
|
ASSERT_EQUALS("int f ( int x ) {\n"
|
||||||
|
"switch ( x ) {\n"
|
||||||
|
"l1 : ; case 0 : ; l2 : ; case ( 1 ) : ; return x ; }\n"
|
||||||
|
"}",
|
||||||
|
tokenizeAndStringify("int f(int x) {\n"
|
||||||
|
" switch (x)\n"
|
||||||
|
" l1: case 0: l2: case (1): return x;\n"
|
||||||
|
"}"));
|
||||||
|
|
||||||
|
// Labels before {
|
||||||
|
ASSERT_EQUALS("int f ( int x ) {\n"
|
||||||
|
"switch ( x )\n"
|
||||||
|
"{ l1 : ; case 0 : ; l2 : ; case ( 1 ) : ; return x ; }\n"
|
||||||
|
"}",
|
||||||
|
tokenizeAndStringify("int f(int x) {\n"
|
||||||
|
" switch (x)\n"
|
||||||
|
" l1: case 0: l2: case (1): { return x; }\n"
|
||||||
|
"}"));
|
||||||
|
|
||||||
|
// Labels before try/catch
|
||||||
|
ASSERT_EQUALS("int f ( int x ) {\n"
|
||||||
|
"switch ( x ) {\n"
|
||||||
|
"l1 : ; case 0 : ; l2 : ; case ( 1 ) : ;\n"
|
||||||
|
"try { throw 1 ; }\n"
|
||||||
|
"catch ( ... ) { return x ; } }\n"
|
||||||
|
"}",
|
||||||
|
tokenizeAndStringify("int f(int x) {\n"
|
||||||
|
" switch (x)\n"
|
||||||
|
" l1: case 0: l2: case (1):\n"
|
||||||
|
" try { throw 1; }\n"
|
||||||
|
" catch(...) { return x; }\n"
|
||||||
|
"}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void whileAddBraces() {
|
void whileAddBraces() {
|
||||||
|
@ -1237,6 +1310,42 @@ private:
|
||||||
ASSERT_EQUALS("{ while ( a ) { ; } }", tokenizeAndStringify(code));
|
ASSERT_EQUALS("{ while ( a ) { ; } }", tokenizeAndStringify(code));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void whileAddBracesLabels() {
|
||||||
|
// Labels before statement
|
||||||
|
ASSERT_EQUALS("void f ( int x ) {\n"
|
||||||
|
"while ( x ) {\n"
|
||||||
|
"l1 : ; l2 : ; -- x ; }\n"
|
||||||
|
"}",
|
||||||
|
tokenizeAndStringify("void f(int x) {\n"
|
||||||
|
" while (x)\n"
|
||||||
|
" l1: l2: --x;\n"
|
||||||
|
"}"));
|
||||||
|
|
||||||
|
// Labels before {
|
||||||
|
ASSERT_EQUALS("void f ( int x ) {\n"
|
||||||
|
"while ( x )\n"
|
||||||
|
"{ l1 : ; l2 : ; -- x ; }\n"
|
||||||
|
"}",
|
||||||
|
tokenizeAndStringify("void f(int x) {\n"
|
||||||
|
" while (x)\n"
|
||||||
|
" l1: l2: { -- x; }\n"
|
||||||
|
"}"));
|
||||||
|
|
||||||
|
// Labels before try/catch
|
||||||
|
ASSERT_EQUALS("void f ( int x ) {\n"
|
||||||
|
"while ( x ) {\n"
|
||||||
|
"l1 : ; l2 : ;\n"
|
||||||
|
"try { throw 1 ; }\n"
|
||||||
|
"catch ( ... ) { -- x ; } }\n"
|
||||||
|
"}",
|
||||||
|
tokenizeAndStringify("void f(int x) {\n"
|
||||||
|
" while (x)\n"
|
||||||
|
" l1: l2:\n"
|
||||||
|
" try { throw 1; }\n"
|
||||||
|
" catch(...) { --x; }\n"
|
||||||
|
"}"));
|
||||||
|
}
|
||||||
|
|
||||||
void doWhileAddBraces() {
|
void doWhileAddBraces() {
|
||||||
{
|
{
|
||||||
const char code[] = "{do ; while (0);}";
|
const char code[] = "{do ; while (0);}";
|
||||||
|
@ -1307,6 +1416,48 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void doWhileAddBracesLabels() {
|
||||||
|
// Labels before statement
|
||||||
|
ASSERT_EQUALS("void f ( int x ) {\n"
|
||||||
|
"do {\n"
|
||||||
|
"l1 : ; l2 : ; -- x ; }\n"
|
||||||
|
"while ( x ) ;\n"
|
||||||
|
"}",
|
||||||
|
tokenizeAndStringify("void f(int x) {\n"
|
||||||
|
" do\n"
|
||||||
|
" l1: l2: --x;\n"
|
||||||
|
" while (x);\n"
|
||||||
|
"}"));
|
||||||
|
|
||||||
|
// Labels before {
|
||||||
|
ASSERT_EQUALS("void f ( int x ) {\n"
|
||||||
|
"do\n"
|
||||||
|
"{ l1 : ; l2 : ; -- x ; }\n"
|
||||||
|
"while ( x ) ;\n"
|
||||||
|
"}",
|
||||||
|
tokenizeAndStringify("void f(int x) {\n"
|
||||||
|
" do\n"
|
||||||
|
" l1: l2: { -- x; }\n"
|
||||||
|
" while (x);\n"
|
||||||
|
"}"));
|
||||||
|
|
||||||
|
// Labels before try/catch
|
||||||
|
ASSERT_EQUALS("void f ( int x ) {\n"
|
||||||
|
"do {\n"
|
||||||
|
"l1 : ; l2 : ;\n"
|
||||||
|
"try { throw 1 ; }\n"
|
||||||
|
"catch ( ... ) { -- x ; } }\n"
|
||||||
|
"while ( x ) ;\n"
|
||||||
|
"}",
|
||||||
|
tokenizeAndStringify("void f(int x) {\n"
|
||||||
|
" do\n"
|
||||||
|
" l1: l2:\n"
|
||||||
|
" try { throw 1; }\n"
|
||||||
|
" catch(...) { --x; }\n"
|
||||||
|
" while (x);\n"
|
||||||
|
"}"));
|
||||||
|
}
|
||||||
|
|
||||||
void forAddBraces1() {
|
void forAddBraces1() {
|
||||||
{
|
{
|
||||||
const char code[] = "void f() {\n"
|
const char code[] = "void f() {\n"
|
||||||
|
@ -1349,6 +1500,43 @@ private:
|
||||||
ASSERT_EQUALS(expected, tokenizeAndStringify(code));
|
ASSERT_EQUALS(expected, tokenizeAndStringify(code));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void forAddBracesLabels() {
|
||||||
|
// Labels before statement
|
||||||
|
ASSERT_EQUALS("void f ( int x ) {\n"
|
||||||
|
"for ( ; x ; ) {\n"
|
||||||
|
"l1 : ; l2 : ; -- x ; }\n"
|
||||||
|
"}",
|
||||||
|
tokenizeAndStringify("void f(int x) {\n"
|
||||||
|
" for ( ; x; )\n"
|
||||||
|
" l1: l2: --x;\n"
|
||||||
|
"}"));
|
||||||
|
|
||||||
|
// Labels before {
|
||||||
|
ASSERT_EQUALS("void f ( int x ) {\n"
|
||||||
|
"for ( ; x ; )\n"
|
||||||
|
"{ l1 : ; l2 : ; -- x ; }\n"
|
||||||
|
"}",
|
||||||
|
tokenizeAndStringify("void f(int x) {\n"
|
||||||
|
" for ( ; x; )\n"
|
||||||
|
" l1: l2: { -- x; }\n"
|
||||||
|
"}"));
|
||||||
|
|
||||||
|
// Labels before try/catch
|
||||||
|
ASSERT_EQUALS("void f ( int x ) {\n"
|
||||||
|
"for ( ; x ; ) {\n"
|
||||||
|
"l1 : ; l2 : ;\n"
|
||||||
|
"try { throw 1 ; }\n"
|
||||||
|
"catch ( ... ) { -- x ; } }\n"
|
||||||
|
"}",
|
||||||
|
tokenizeAndStringify("void f(int x) {\n"
|
||||||
|
" for ( ; x; )\n"
|
||||||
|
" l1: l2:\n"
|
||||||
|
" try { throw 1; }\n"
|
||||||
|
" catch(...) { --x; }\n"
|
||||||
|
"}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void simplifyExternC() {
|
void simplifyExternC() {
|
||||||
ASSERT_EQUALS("int foo ( ) ;", tokenizeAndStringify("extern \"C\" int foo();"));
|
ASSERT_EQUALS("int foo ( ) ;", tokenizeAndStringify("extern \"C\" int foo();"));
|
||||||
ASSERT_EQUALS("int foo ( ) ;", tokenizeAndStringify("extern \"C\" { int foo(); }"));
|
ASSERT_EQUALS("int foo ( ) ;", tokenizeAndStringify("extern \"C\" { int foo(); }"));
|
||||||
|
|
Loading…
Reference in New Issue