Tokenizer: improve the new 'skipTernaryOp' function by supporting GCC '{(var|num;)}' statement expression extension; improve 'Tokenizer::simplifyQuestionMark' by supporting simplification with 'case' before ternary operation, using skipTernaryOp to get colon and, most importantly, supporting indented '?:' operations.
This commit is contained in:
parent
d4a3c1617a
commit
1951d1cdc5
|
@ -2370,6 +2370,11 @@ static Token *skipTernaryOp(Token *tok)
|
|||
break;
|
||||
}
|
||||
}
|
||||
//allow GCC '({ %var%|%num% ; })' statement expression extension
|
||||
if (Token::Match(tok, "( { %any% ; } )") &&
|
||||
(tok->tokAt(2)->isNumber() || tok->tokAt(2)->isName())) {
|
||||
tok = tok->link();
|
||||
}
|
||||
if (Token::Match(tok->next(), "[{};]"))
|
||||
break;
|
||||
}
|
||||
|
@ -4426,7 +4431,7 @@ bool Tokenizer::simplifyQuestionMark()
|
|||
if (!tok->tokAt(-2))
|
||||
continue;
|
||||
|
||||
if (!Token::Match(tok->tokAt(-2), "[=,(]"))
|
||||
if (!Token::Match(tok->tokAt(-2), "=|,|(|case"))
|
||||
continue;
|
||||
|
||||
if (!tok->previous()->isBoolean() &&
|
||||
|
@ -4434,19 +4439,10 @@ bool Tokenizer::simplifyQuestionMark()
|
|||
continue;
|
||||
|
||||
// Find the ":" token..
|
||||
Token *semicolon = 0;
|
||||
for (Token *tok2 = tok; tok2; tok2 = tok2->next()) {
|
||||
if (tok2->str() == "(" || tok2->str() == "[")
|
||||
tok2 = tok2->link();
|
||||
else if (tok2->str() == ")" || tok2->str() == "]")
|
||||
break;
|
||||
else if (tok2->str() == ":") {
|
||||
semicolon = tok2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!semicolon || !semicolon->next())
|
||||
Token *semicolon = skipTernaryOp(tok);
|
||||
if (!semicolon || semicolon->previous()->str() != ":" || !semicolon->next())
|
||||
continue;
|
||||
semicolon = semicolon->previous();
|
||||
|
||||
if (tok->previous()->str() == "false" ||
|
||||
tok->previous()->str() == "0") {
|
||||
|
@ -4480,24 +4476,18 @@ bool Tokenizer::simplifyQuestionMark()
|
|||
continue;
|
||||
}
|
||||
|
||||
int ind = 0;
|
||||
for (const Token *endTok = semicolon; endTok; endTok = endTok->next()) {
|
||||
if (endTok->str() == ";") {
|
||||
//we can remove the semicolon if after it there's at least another token
|
||||
if (endTok->next())
|
||||
endTok = endTok->next();
|
||||
Token::eraseTokens(semicolon->previous(), endTok);
|
||||
ret = true;
|
||||
break;
|
||||
unsigned int colonlevel = 0;
|
||||
for (const Token *endTok = semicolon->next(); endTok; endTok = endTok->next()) {
|
||||
if (endTok->str() == "(" || endTok->str() == "[" || endTok->str() == "{") {
|
||||
endTok = endTok->link();
|
||||
}
|
||||
|
||||
else if (Token::Match(endTok, "[({[]")) {
|
||||
++ind;
|
||||
}
|
||||
|
||||
else if (Token::Match(endTok, "[)}]]")) {
|
||||
--ind;
|
||||
if (ind < 0) {
|
||||
else if (endTok->str() == "?")
|
||||
++colonlevel;
|
||||
else if (Token::Match(endTok, ")|}|]|;|:")) {
|
||||
if (endTok->str() == ":" && colonlevel)
|
||||
--colonlevel;
|
||||
else {
|
||||
Token::eraseTokens(semicolon->previous(), endTok);
|
||||
ret = true;
|
||||
break;
|
||||
|
|
|
@ -2759,6 +2759,21 @@ private:
|
|||
ASSERT_EQUALS("( 0 )", tok(code));
|
||||
}
|
||||
|
||||
{
|
||||
const char code[] = "void f () { switch(n) { case 1?0:foo(): break; }}";
|
||||
ASSERT_EQUALS("void f ( ) { switch ( n ) { case 0 : ; break ; } }", tok(code));
|
||||
}
|
||||
|
||||
{
|
||||
const char code[] = "void f () { switch(n) { case 1?0?1:0:foo(): break; }}";
|
||||
ASSERT_EQUALS("void f ( ) { switch ( n ) { case 0 : ; break ; } }", tok(code));
|
||||
}
|
||||
|
||||
{
|
||||
const char code[] = "void f () { switch(n) { case 0?foo():1: break; }}";
|
||||
ASSERT_EQUALS("void f ( ) { switch ( n ) { case 1 : ; break ; } }", tok(code));
|
||||
}
|
||||
|
||||
{
|
||||
const char code[] = "( true ? a ( ) : b ( ) )";
|
||||
ASSERT_EQUALS("( a ( ) )", tok(code));
|
||||
|
|
|
@ -738,6 +738,10 @@ private:
|
|||
tokenizeAndStringify("void f() {switch (n) { case 0?(1?3:4):2 : z(); break;}}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
//allow GCC '({ %var%|%num%|%bool% ; })' statement expression extension
|
||||
tokenizeAndStringify("void f() {switch (n) { case 0?({0;}):1: z(); break;}}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
//'b' can be or a macro or an undefined enum
|
||||
tokenizeAndStringify("void f() {switch (n) { case b: z(); break;}}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
|
Loading…
Reference in New Issue