9955: Fix ast when throwing a cast (#2900)

```
throw (std::string)"Error: " + strerror(errnum);
```
would result in a broken ast:
```
throw
`-::
  |-std
  `-string
```
instead of
```
throw
`-+ 'signed char *'
  |-( 'container(std :: string|wstring|u16string|u32string)'
  | `-"Error: " 'const char *'
  `-( 'signed char *'
    |-strerror
    `-errnum 'signed int'
```
This commit is contained in:
Ken-Patrick Lehrmann 2020-11-15 10:37:29 +01:00 committed by GitHub
parent f779a44be0
commit 7c3afa0b36
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 10 additions and 8 deletions

View File

@ -493,7 +493,7 @@ static Token * skipDecl(Token *tok)
return tok; return tok;
} }
static bool iscast(const Token *tok) static bool iscast(const Token *tok, bool cpp)
{ {
if (!Token::Match(tok, "( ::| %name%")) if (!Token::Match(tok, "( ::| %name%"))
return false; return false;
@ -501,7 +501,8 @@ static bool iscast(const Token *tok)
if (Token::simpleMatch(tok->link(), ") ( )")) if (Token::simpleMatch(tok->link(), ") ( )"))
return false; return false;
if (tok->previous() && tok->previous()->isName() && tok->previous()->str() != "return") if (tok->previous() && tok->previous()->isName() && tok->previous()->str() != "return" &&
(!cpp || tok->previous()->str() != "throw"))
return false; return false;
if (Token::simpleMatch(tok->previous(), ">") && tok->previous()->link()) if (Token::simpleMatch(tok->previous(), ">") && tok->previous()->link())
@ -830,7 +831,7 @@ static void compileTerm(Token *&tok, AST_state& state)
} }
} else if (tok->str() == "{") { } else if (tok->str() == "{") {
const Token *prev = tok->previous(); const Token *prev = tok->previous();
if (Token::simpleMatch(prev, ") {") && iscast(prev->link())) if (Token::simpleMatch(prev, ") {") && iscast(prev->link(), state.cpp))
prev = prev->link()->previous(); prev = prev->link()->previous();
if (Token::simpleMatch(tok->link(),"} [")) { if (Token::simpleMatch(tok->link(),"} [")) {
tok = tok->next(); tok = tok->next();
@ -905,7 +906,7 @@ static bool isPrefixUnary(const Token* tok, bool cpp)
if (tok->str() == "*" && tok->previous()->tokType() == Token::eIncDecOp && isPrefixUnary(tok->previous(), cpp)) if (tok->str() == "*" && tok->previous()->tokType() == Token::eIncDecOp && isPrefixUnary(tok->previous(), cpp))
return true; return true;
return tok->strAt(-1) == ")" && iscast(tok->linkAt(-1)); return tok->strAt(-1) == ")" && iscast(tok->linkAt(-1), cpp);
} }
static void compilePrecedence2(Token *&tok, AST_state& state) static void compilePrecedence2(Token *&tok, AST_state& state)
@ -973,7 +974,7 @@ static void compilePrecedence2(Token *&tok, AST_state& state)
else else
compileUnaryOp(tok, state, compileExpression); compileUnaryOp(tok, state, compileExpression);
tok = tok2->link()->next(); tok = tok2->link()->next();
} else if (tok->str() == "(" && (!iscast(tok) || Token::Match(tok->previous(), "if|while|for|switch|catch"))) { } else if (tok->str() == "(" && (!iscast(tok, state.cpp) || Token::Match(tok->previous(), "if|while|for|switch|catch"))) {
Token* tok2 = tok; Token* tok2 = tok;
tok = tok->next(); tok = tok->next();
const bool opPrevTopSquare = !state.op.empty() && state.op.top() && state.op.top()->str() == "["; const bool opPrevTopSquare = !state.op.empty() && state.op.top() && state.op.top()->str() == "[";
@ -984,7 +985,7 @@ static void compilePrecedence2(Token *&tok, AST_state& state)
|| (tok->previous() && tok->previous()->isName() && !Token::Match(tok->previous(), "return|case") && (!state.cpp || !Token::Match(tok->previous(), "throw|delete"))) || (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), state.cpp)) // Don't treat brackets to clarify precedence as function calls
|| (tok->strAt(-1) == "}" && opPrevTopSquare)) { || (tok->strAt(-1) == "}" && opPrevTopSquare)) {
const bool operandInside = oldOpSize < state.op.size(); const bool operandInside = oldOpSize < state.op.size();
if (operandInside) if (operandInside)
@ -993,7 +994,7 @@ static void compilePrecedence2(Token *&tok, AST_state& state)
compileUnaryOp(tok, state, nullptr); compileUnaryOp(tok, state, nullptr);
} }
tok = tok->link()->next(); tok = tok->link()->next();
} else if (iscast(tok) && Token::simpleMatch(tok->link(), ") {") && Token::simpleMatch(tok->link()->linkAt(1), "} [")) { } else if (iscast(tok, state.cpp) && Token::simpleMatch(tok->link(), ") {") && Token::simpleMatch(tok->link()->linkAt(1), "} [")) {
Token *cast = tok; Token *cast = tok;
tok = tok->link()->next(); tok = tok->link()->next();
Token *tok1 = tok; Token *tok1 = tok;
@ -1027,7 +1028,7 @@ static void compilePrecedence3(Token *&tok, AST_state& state)
} }
} }
compileUnaryOp(tok, state, compilePrecedence3); compileUnaryOp(tok, state, compilePrecedence3);
} else if (tok->str() == "(" && iscast(tok)) { } else if (tok->str() == "(" && iscast(tok, state.cpp)) {
Token* castTok = tok; Token* castTok = tok;
castTok->isCast(true); castTok->isCast(true);
tok = tok->link()->next(); tok = tok->link()->next();

View File

@ -7884,6 +7884,7 @@ private:
ASSERT_EQUALS("x(throw", testAst(";throw x();")); ASSERT_EQUALS("x(throw", testAst(";throw x();"));
ASSERT_EQUALS("a*bc:?return", testAst("return *a ? b : c;")); ASSERT_EQUALS("a*bc:?return", testAst("return *a ? b : c;"));
ASSERT_EQUALS("xy*--=", testAst("x = -- * y;")); ASSERT_EQUALS("xy*--=", testAst("x = -- * y;"));
ASSERT_EQUALS("x(throw", testAst(";throw (foo) x;")); // #9955
// Unary :: operator // Unary :: operator
ASSERT_EQUALS("abcd::12,(e/:?=", testAst("a = b ? c : ::d(1,2) / e;")); ASSERT_EQUALS("abcd::12,(e/:?=", testAst("a = b ? c : ::d(1,2) / e;"));