Skip to content

Commit 7c3afa0

Browse files
authored
9955: Fix ast when throwing a cast (cppcheck-opensource#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' ```
1 parent f779a44 commit 7c3afa0

2 files changed

Lines changed: 10 additions & 8 deletions

File tree

lib/tokenlist.cpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -493,15 +493,16 @@ static Token * skipDecl(Token *tok)
493493
return tok;
494494
}
495495

496-
static bool iscast(const Token *tok)
496+
static bool iscast(const Token *tok, bool cpp)
497497
{
498498
if (!Token::Match(tok, "( ::| %name%"))
499499
return false;
500500

501501
if (Token::simpleMatch(tok->link(), ") ( )"))
502502
return false;
503503

504-
if (tok->previous() && tok->previous()->isName() && tok->previous()->str() != "return")
504+
if (tok->previous() && tok->previous()->isName() && tok->previous()->str() != "return" &&
505+
(!cpp || tok->previous()->str() != "throw"))
505506
return false;
506507

507508
if (Token::simpleMatch(tok->previous(), ">") && tok->previous()->link())
@@ -830,7 +831,7 @@ static void compileTerm(Token *&tok, AST_state& state)
830831
}
831832
} else if (tok->str() == "{") {
832833
const Token *prev = tok->previous();
833-
if (Token::simpleMatch(prev, ") {") && iscast(prev->link()))
834+
if (Token::simpleMatch(prev, ") {") && iscast(prev->link(), state.cpp))
834835
prev = prev->link()->previous();
835836
if (Token::simpleMatch(tok->link(),"} [")) {
836837
tok = tok->next();
@@ -905,7 +906,7 @@ static bool isPrefixUnary(const Token* tok, bool cpp)
905906
if (tok->str() == "*" && tok->previous()->tokType() == Token::eIncDecOp && isPrefixUnary(tok->previous(), cpp))
906907
return true;
907908

908-
return tok->strAt(-1) == ")" && iscast(tok->linkAt(-1));
909+
return tok->strAt(-1) == ")" && iscast(tok->linkAt(-1), cpp);
909910
}
910911

911912
static void compilePrecedence2(Token *&tok, AST_state& state)
@@ -973,7 +974,7 @@ static void compilePrecedence2(Token *&tok, AST_state& state)
973974
else
974975
compileUnaryOp(tok, state, compileExpression);
975976
tok = tok2->link()->next();
976-
} else if (tok->str() == "(" && (!iscast(tok) || Token::Match(tok->previous(), "if|while|for|switch|catch"))) {
977+
} else if (tok->str() == "(" && (!iscast(tok, state.cpp) || Token::Match(tok->previous(), "if|while|for|switch|catch"))) {
977978
Token* tok2 = tok;
978979
tok = tok->next();
979980
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)
984985
|| (tok->previous() && tok->previous()->isName() && !Token::Match(tok->previous(), "return|case") && (!state.cpp || !Token::Match(tok->previous(), "throw|delete")))
985986
|| (tok->strAt(-1) == "]" && (!state.cpp || !Token::Match(tok->linkAt(-1)->previous(), "new|delete")))
986987
|| (tok->strAt(-1) == ">" && tok->linkAt(-1))
987-
|| (tok->strAt(-1) == ")" && !iscast(tok->linkAt(-1))) // Don't treat brackets to clarify precedence as function calls
988+
|| (tok->strAt(-1) == ")" && !iscast(tok->linkAt(-1), state.cpp)) // Don't treat brackets to clarify precedence as function calls
988989
|| (tok->strAt(-1) == "}" && opPrevTopSquare)) {
989990
const bool operandInside = oldOpSize < state.op.size();
990991
if (operandInside)
@@ -993,7 +994,7 @@ static void compilePrecedence2(Token *&tok, AST_state& state)
993994
compileUnaryOp(tok, state, nullptr);
994995
}
995996
tok = tok->link()->next();
996-
} else if (iscast(tok) && Token::simpleMatch(tok->link(), ") {") && Token::simpleMatch(tok->link()->linkAt(1), "} [")) {
997+
} else if (iscast(tok, state.cpp) && Token::simpleMatch(tok->link(), ") {") && Token::simpleMatch(tok->link()->linkAt(1), "} [")) {
997998
Token *cast = tok;
998999
tok = tok->link()->next();
9991000
Token *tok1 = tok;
@@ -1027,7 +1028,7 @@ static void compilePrecedence3(Token *&tok, AST_state& state)
10271028
}
10281029
}
10291030
compileUnaryOp(tok, state, compilePrecedence3);
1030-
} else if (tok->str() == "(" && iscast(tok)) {
1031+
} else if (tok->str() == "(" && iscast(tok, state.cpp)) {
10311032
Token* castTok = tok;
10321033
castTok->isCast(true);
10331034
tok = tok->link()->next();

test/testtokenize.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7884,6 +7884,7 @@ class TestTokenizer : public TestFixture {
78847884
ASSERT_EQUALS("x(throw", testAst(";throw x();"));
78857885
ASSERT_EQUALS("a*bc:?return", testAst("return *a ? b : c;"));
78867886
ASSERT_EQUALS("xy*--=", testAst("x = -- * y;"));
7887+
ASSERT_EQUALS("x(throw", testAst(";throw (foo) x;")); // #9955
78877888

78887889
// Unary :: operator
78897890
ASSERT_EQUALS("abcd::12,(e/:?=", testAst("a = b ? c : ::d(1,2) / e;"));

0 commit comments

Comments
 (0)