AST: Better handling of case
This commit is contained in:
parent
da87fdbb90
commit
fd74d455ce
|
@ -321,7 +321,8 @@ struct AST_state {
|
||||||
unsigned int inArrayAssignment;
|
unsigned int inArrayAssignment;
|
||||||
bool cpp;
|
bool cpp;
|
||||||
unsigned int assign;
|
unsigned int assign;
|
||||||
explicit AST_state(bool cpp_) : depth(0), inArrayAssignment(0), cpp(cpp_), assign(0U) {}
|
bool inCase;
|
||||||
|
explicit AST_state(bool cpp_) : depth(0), inArrayAssignment(0), cpp(cpp_), assign(0U), inCase(false) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
static Token * skipDecl(Token *tok)
|
static Token * skipDecl(Token *tok)
|
||||||
|
@ -503,10 +504,14 @@ static void compileTerm(Token *&tok, AST_state& state)
|
||||||
do {
|
do {
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
} while (Token::Match(tok, "%name%|%str%"));
|
} while (Token::Match(tok, "%name%|%str%"));
|
||||||
} else if (tok->isName() && tok->str() != "case") {
|
} else if (tok->isName()) {
|
||||||
if (tok->str() == "return") {
|
if (Token::Match(tok, "return|case")) {
|
||||||
|
if (tok->str() == "case")
|
||||||
|
state.inCase = true;
|
||||||
compileUnaryOp(tok, state, compileExpression);
|
compileUnaryOp(tok, state, compileExpression);
|
||||||
state.op.pop();
|
state.op.pop();
|
||||||
|
if (state.inCase && Token::simpleMatch(tok, ": ;"))
|
||||||
|
tok = tok->next();
|
||||||
} else if (Token::Match(tok, "sizeof !!(")) {
|
} else if (Token::Match(tok, "sizeof !!(")) {
|
||||||
compileUnaryOp(tok, state, compileExpression);
|
compileUnaryOp(tok, state, compileExpression);
|
||||||
state.op.pop();
|
state.op.pop();
|
||||||
|
@ -644,7 +649,7 @@ static void compilePrecedence2(Token *&tok, AST_state& state)
|
||||||
const std::size_t oldOpSize = state.op.size();
|
const std::size_t oldOpSize = state.op.size();
|
||||||
compileExpression(tok, state);
|
compileExpression(tok, state);
|
||||||
tok = tok2;
|
tok = tok2;
|
||||||
if ((tok->previous() && tok->previous()->isName() && (tok->strAt(-1) != "return" && (!state.cpp || !Token::Match(tok->previous(), "throw|delete"))))
|
if ((tok->previous() && tok->previous()->isName() && (!Token::Match(tok->previous(), "return|case") && (!state.cpp || !Token::Match(tok->previous(), "throw|delete"))))
|
||||||
|| (tok->strAt(-1) == "]" && (!state.cpp || !Token::Match(tok->linkAt(-1)->previous(), "new|delete")))
|
|| (tok->strAt(-1) == "]" && (!state.cpp || !Token::Match(tok->linkAt(-1)->previous(), "new|delete")))
|
||||||
|| (tok->strAt(-1) == ">" && tok->linkAt(-1))
|
|| (tok->strAt(-1) == ">" && tok->linkAt(-1))
|
||||||
|| (tok->strAt(-1) == ")" && !iscast(tok->linkAt(-1))) // Don't treat brackets to clarify precedence as function calls
|
|| (tok->strAt(-1) == ")" && !iscast(tok->linkAt(-1))) // Don't treat brackets to clarify precedence as function calls
|
||||||
|
@ -889,6 +894,8 @@ static void compileAssignTernary(Token *&tok, AST_state& state)
|
||||||
compileBinOp(tok, state, compileAssignTernary);
|
compileBinOp(tok, state, compileAssignTernary);
|
||||||
state.assign = assign;
|
state.assign = assign;
|
||||||
} else if (tok->str() == ":") {
|
} else if (tok->str() == ":") {
|
||||||
|
if (state.depth == 1U && state.inCase)
|
||||||
|
break;
|
||||||
if (state.assign > 0U)
|
if (state.assign > 0U)
|
||||||
break;
|
break;
|
||||||
compileBinOp(tok, state, compileAssignTernary);
|
compileBinOp(tok, state, compileAssignTernary);
|
||||||
|
@ -1079,7 +1086,7 @@ static Token * createAstAtToken(Token *tok, bool cpp)
|
||||||
if (Token::Match(tok, "%type% <") && !Token::Match(tok->linkAt(1), "> [({]"))
|
if (Token::Match(tok, "%type% <") && !Token::Match(tok->linkAt(1), "> [({]"))
|
||||||
return tok->linkAt(1);
|
return tok->linkAt(1);
|
||||||
|
|
||||||
if (tok->str() == "return" || !tok->previous() || Token::Match(tok, "%name% %op%|(|[|.|::|<|?|;") || Token::Match(tok->previous(), "[;{}] %cop%|++|--|( !!{")) {
|
if (Token::Match(tok, "return|case") || !tok->previous() || Token::Match(tok, "%name% %op%|(|[|.|::|<|?|;") || Token::Match(tok->previous(), "[;{}] %cop%|++|--|( !!{")) {
|
||||||
if (cpp && (Token::Match(tok->tokAt(-2), "[;{}] new|delete %name%") || Token::Match(tok->tokAt(-3), "[;{}] :: new|delete %name%")))
|
if (cpp && (Token::Match(tok->tokAt(-2), "[;{}] new|delete %name%") || Token::Match(tok->tokAt(-3), "[;{}] :: new|delete %name%")))
|
||||||
tok = tok->previous();
|
tok = tok->previous();
|
||||||
|
|
||||||
|
|
|
@ -362,7 +362,7 @@ private:
|
||||||
|
|
||||||
ASSERT_THROW(checkCode("void f() {switch (n) { case 0?1;:{2} : z(); break;}}"), InternalError);
|
ASSERT_THROW(checkCode("void f() {switch (n) { case 0?1;:{2} : z(); break;}}"), InternalError);
|
||||||
|
|
||||||
checkCode("void f() {switch (n) { case 0?(1?{3:4}):2 : z(); break;}}");
|
ASSERT_THROW(checkCode("void f() {switch (n) { case 0?(1?{3:4}):2 : z(); break;}}"), InternalError);
|
||||||
|
|
||||||
//ticket #4234
|
//ticket #4234
|
||||||
ASSERT_THROW(checkCode("( ) { switch break ; { switch ( x ) { case } y break ; : } }"), InternalError);
|
ASSERT_THROW(checkCode("( ) { switch break ; { switch ( x ) { case } y break ; : } }"), InternalError);
|
||||||
|
|
|
@ -454,6 +454,7 @@ private:
|
||||||
TEST_CASE(asttemplate);
|
TEST_CASE(asttemplate);
|
||||||
TEST_CASE(astcast);
|
TEST_CASE(astcast);
|
||||||
TEST_CASE(astlambda);
|
TEST_CASE(astlambda);
|
||||||
|
TEST_CASE(astcase);
|
||||||
|
|
||||||
TEST_CASE(startOfExecutableScope);
|
TEST_CASE(startOfExecutableScope);
|
||||||
|
|
||||||
|
@ -8283,6 +8284,12 @@ private:
|
||||||
ASSERT_EQUALS("ab{[(= cd=", testAst("a = b([&]{c=d;});"));
|
ASSERT_EQUALS("ab{[(= cd=", testAst("a = b([&]{c=d;});"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void astcase() {
|
||||||
|
ASSERT_EQUALS("0case", testAst("case 0:"));
|
||||||
|
ASSERT_EQUALS("12+case", testAst("case 1+2:"));
|
||||||
|
ASSERT_EQUALS("xyz:?case", testAst("case (x?y:z):"));
|
||||||
|
}
|
||||||
|
|
||||||
void compileLimits() {
|
void compileLimits() {
|
||||||
const char raw_code[] = "#define PTR1 (* (* (* (* (* (* (* (* (* (*\n"
|
const char raw_code[] = "#define PTR1 (* (* (* (* (* (* (* (* (* (*\n"
|
||||||
"#define PTR2 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1\n"
|
"#define PTR2 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1 PTR1\n"
|
||||||
|
|
Loading…
Reference in New Issue