diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index c5b001f5d32..c8a832e6348 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -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) { @@ -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); diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 5f4d59503e2..b1e3e87cdcf 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -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); @@ -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 {\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"