From 223258a4d8a319221ed2db3681cde3cbd07cf309 Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Tue, 11 Aug 2026 20:17:15 +0200 Subject: [PATCH] Fix #14972 [regression] Syntax Error: AST broken, '!' doesn't have an operand. --- lib/tokenize.cpp | 4 ++-- test/testvarid.cpp | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 1a6d4a4e53f..eabf1bd811e 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -5238,7 +5238,7 @@ static Token * matchMemberVarName(const Member &var, const std::list { Token *tok = matchMemberName(var, scopeInfo); if (Token::Match(tok, "%name%")) { - if (!tok->next() || tok->strAt(1) != "(" || (tok->tokAt(2) && tok->tokAt(2)->isLiteral())) + if (!tok->next() || tok->strAt(1) != "(" || (tok->tokAt(2) && (tok->tokAt(2)->isLiteral() || tok->tokAt(2)->isOp()))) return tok; } return nullptr; @@ -5338,7 +5338,7 @@ void Tokenizer::setVarIdPass2() } if (!tok->next()) syntaxError(tok); - if (Token::Match(tok, "%name% (") && !(tok->tokAt(2) && tok->tokAt(2)->isLiteral())) + if (Token::Match(tok, "%name% (") && !(tok->tokAt(2) && (tok->tokAt(2)->isLiteral() || tok->tokAt(2)->isOp()))) allMemberFunctions.emplace_back(scope, usingnamespaces, tok1); else allMemberVars.emplace_back(scope, usingnamespaces, tok1); diff --git a/test/testvarid.cpp b/test/testvarid.cpp index e30c613c0bc..493546f28d0 100644 --- a/test/testvarid.cpp +++ b/test/testvarid.cpp @@ -222,6 +222,7 @@ class TestVarID : public TestFixture { TEST_CASE(varidclass18); TEST_CASE(varidclass19); // initializer list TEST_CASE(varidclass20); // #7578: int (*p)[2] + TEST_CASE(varidclass21); TEST_CASE(varid_classnameshaddowsvariablename); // #3990 TEST_CASE(varid_classnametemplate); // #10221 @@ -4021,6 +4022,14 @@ class TestVarID : public TestFixture { ASSERT_EQUALS(expected, tokenize(code)); } + void varidclass21() { + const char code[] = "struct T { static bool b; };\n" // #14972 + "bool T::b(!false);\n"; + const char expected[] = "1: struct T { static bool b@1 ; } ;\n" + "2: bool T :: b@1 ( ! false ) ;\n"; + ASSERT_EQUALS(expected, tokenize(code)); + } + void varidenum1() { const char code[] = "const int eStart = 6;\n" "enum myEnum {\n"