From dd67935e4cf9533b9504a0eec64ecdd7fe481ef3 Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Sun, 14 Jun 2026 21:10:28 +0200 Subject: [PATCH 1/3] Partial fix for #14842 FN memleak in function with trailing return type (regression) --- lib/tokenize.cpp | 2 ++ test/testtokenize.cpp | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index c5b001f5d32..1c7df0bdd4c 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -7368,6 +7368,8 @@ void Tokenizer::simplifyVarDecl(Token * tokBegin, const Token * const tokEnd, co 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..f29417f13a5 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); @@ -2856,6 +2857,19 @@ class TestTokenizer : public TestFixture { ASSERT_EQUALS("enum Anonymous0 { E } ; static enum Anonymous0 const * f ( ) { return NULL ; }", tokenizeAndStringify(code, dinit(TokenizeOptions, $.cpp = false))); } } + 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(); + } + } void volatile_variables() { { From d7c9b4047f240e8e822e8c624a4a2359d728f384 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Mon, 15 Jun 2026 10:48:20 +0200 Subject: [PATCH 2/3] Update tokenize.cpp --- lib/tokenize.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 1c7df0bdd4c..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,9 +7373,9 @@ 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); From abb2266cf41ffbc59c06023ed89c049b9edafe20 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Mon, 15 Jun 2026 10:49:45 +0200 Subject: [PATCH 3/3] Update testtokenize.cpp --- test/testtokenize.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index f29417f13a5..b1e3e87cdcf 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -2857,6 +2857,7 @@ class TestTokenizer : public TestFixture { ASSERT_EQUALS("enum Anonymous0 { E } ; static enum Anonymous0 const * f ( ) { return NULL ; }", tokenizeAndStringify(code, dinit(TokenizeOptions, $.cpp = false))); } } + void vardecl35() { // #14842 { const char code[] = "auto f() -> void {\n" @@ -2869,6 +2870,18 @@ class TestTokenizer : public TestFixture { "}", 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() {