Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions lib/tokenize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7333,6 +7333,19 @@ void Tokenizer::simplifyVarDecl(const bool only_k_r_fpar)
simplifyVarDecl(list.front(), nullptr, only_k_r_fpar);
}

static Token* isTrailingReturnType(Token* tok)
{
while (Token::Match(tok, "%name%|::|>")) {
if (Token* open = tok->findOpeningBracket())
tok = open->tokAt(-1);
else
tok = tok->tokAt(-1);
}
if (tok && Token::simpleMatch(tok->tokAt(-1), ") ."))
return tok->tokAt(-1);
return nullptr;
}

// cppcheck-suppress functionConst - has side effects
void Tokenizer::simplifyVarDecl(Token * tokBegin, const Token * const tokEnd, const bool only_k_r_fpar)
{
Expand Down Expand Up @@ -7360,14 +7373,16 @@ void Tokenizer::simplifyVarDecl(Token * tokBegin, const Token * const tokEnd, co
if (!tok->linkAt(1))
syntaxError(tokBegin);
// Check for lambdas before skipping
if (Token::Match(tok->tokAt(-2), ") . %name%")) { // trailing return type
if (Token* trailingStart = isTrailingReturnType(tok)) {
// TODO: support lambda without parameter clause?
Token* lambdaStart = tok->linkAt(-2)->previous();
Token* lambdaStart = trailingStart->link()->tokAt(-1);
if (Token::simpleMatch(lambdaStart, "]"))
lambdaStart = lambdaStart->link();
Token* lambdaEnd = findLambdaEndScope(lambdaStart);
if (lambdaEnd)
simplifyVarDecl(lambdaEnd->link()->next(), lambdaEnd, only_k_r_fpar);
else
simplifyVarDecl(tok->tokAt(2), tok->linkAt(1), only_k_r_fpar);
} else {
for (Token* tok2 = tok->next(); tok2 != tok->linkAt(1); tok2 = tok2->next()) {
Token* lambdaEnd = findLambdaEndScope(tok2);
Expand Down
27 changes: 27 additions & 0 deletions test/testtokenize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ class TestTokenizer : public TestFixture {
TEST_CASE(vardecl32);
TEST_CASE(vardecl33);
TEST_CASE(vardecl34);
TEST_CASE(vardecl35);
TEST_CASE(vardecl_stl_1);
TEST_CASE(vardecl_stl_2);
TEST_CASE(vardecl_stl_3);
Expand Down Expand Up @@ -2857,6 +2858,32 @@ class TestTokenizer : public TestFixture {
}
}

void vardecl35() { // #14842
{
const char code[] = "auto f() -> void {\n"
" auto p = new int;\n"
" *p = 0;\n"
"}\n";
ASSERT_EQUALS("auto f ( ) . void {\n"
"auto p ; p = new int ;\n"
"* p = 0 ;\n"
"}", tokenizeAndStringify(code));
ignore_errout();
}
{
const char code[] = "auto f() -> ::std::vector<int> {\n"
" int i = 0;\n"
" return { i };\n"
"}";
ASSERT_EQUALS("auto f ( ) . :: std :: vector < int > {\n"
"int i ; i = 0 ;\n"
"return { i } ;\n"
"}",
tokenizeAndStringify(code));
ignore_errout();
}
}

void volatile_variables() {
{
const char code[] = "volatile int a=0;\n"
Expand Down
Loading