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
2 changes: 1 addition & 1 deletion lib/tokenize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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(), "} ,|{|)|}|..."))) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an AI review. Take it with a grain of salt and feel free to reject it by resolving the comment.

The change looks good to me. I built it and checked some more nested forms: x{{1, 2}}, x(A{{1, 2}}), v{1, 2}, v(std::vector<int>{1, {2}}), and a braced local in the body. The member/parameter varids are now correct, and the leaked varid in the following T::g() is gone.

FYI, a closely related case that still gives the same false positives on both main and this PR is a lambda in the initializer list:

struct S {
    int* p;
    int x;
    S(int* p) : x([p]{ return *p; }()), p(p) {}
};
struct T { int* p; int g(); };
int T::g() { return *p; }

This gives uninitMemberVar + selfInitialization on line 4 and functionStatic on line 7. It may be out of scope for this PR, but maybe it's worth a ticket, or a TODO test next to code14.


if (tok->str() == "{") {
bool isExecutable;
Expand Down
24 changes: 24 additions & 0 deletions test/testvarid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
Loading