From fdc769195ac4833e26d99a56e111577bafc72eb4 Mon Sep 17 00:00:00 2001 From: Leander Schulten Date: Wed, 23 Sep 2026 18:46:31 +0200 Subject: [PATCH] Fix #15062 Wrong varid for shadowed member in initializer list after braced init list argument (FP uninitMemberVar, selfInitialization, functionStatic) In setVarIdPass1 a '{' inside a constructor initializer list was only recognized as part of an argument if it was preceded by a name, '>', '>>' or '('. A braced init list that is not the first argument, e.g. x(f(0, {0})), or a nested one, e.g. x(f(0, {{1}, 2})), was treated as the start of the constructor body. As a result the parameter scope was not left correctly, so the member in a following p(p) got the varid of the parameter, and the parameter varid leaked into later functions. Co-Authored-By: Claude Opus 5.5 --- lib/tokenize.cpp | 2 +- test/testvarid.cpp | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index d67356ad086..f59a4d665d3 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -4835,7 +4835,7 @@ void Tokenizer::setVarIdPass1() // parse anonymous namespaces as part of the current scope if (!Token::Match(startToken->previous(), "union|struct|enum|namespace {") && - !(initlist && Token::Match(startToken->previous(), "%name%|>|>>|(") && Token::Match(startToken->link(), "} ,|{|)|..."))) { + !(initlist && Token::Match(startToken->previous(), "%name%|>|>>|(|,|{") && Token::Match(startToken->link(), "} ,|{|)|}|..."))) { if (tok->str() == "{") { bool isExecutable; diff --git a/test/testvarid.cpp b/test/testvarid.cpp index 4186917cc35..96e0bb0fe71 100644 --- a/test/testvarid.cpp +++ b/test/testvarid.cpp @@ -2715,6 +2715,30 @@ class TestVarID : public TestFixture { "10: D < T ... > d@2 ;\n" "11: } ;\n", tokenize(code13)); + + const char code14[] = "struct S {\n" // #15062 + " int x;\n" + " int* p;\n" + " S(int* p) : x(f(0, {0})), p(p) {}\n" + " S(int* p, int) : x(f(0, {{1}, 2})), p(p) {}\n" + "};\n" + "struct T {\n" + " int* p;\n" + " int g();\n" + "};\n" + "int T::g() { return *p; }\n"; + ASSERT_EQUALS("1: struct S {\n" + "2: int x@1 ;\n" + "3: int * p@2 ;\n" + "4: S ( int * p@3 ) : x@1 ( f ( 0 , { 0 } ) ) , p@2 ( p@3 ) { }\n" + "5: S ( int * p@4 , int ) : x@1 ( f ( 0 , { { 1 } , 2 } ) ) , p@2 ( p@4 ) { }\n" + "6: } ;\n" + "7: struct T {\n" + "8: int * p@5 ;\n" + "9: int g ( ) ;\n" + "10: } ;\n" + "11: int T :: g ( ) { return * p@5 ; }\n", + tokenize(code14)); } void varid_initListWithBaseTemplate() {