From f783ec490cca45f7b2ccfa78294663d64e746240 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludvig=20Gunne=20Lindstr=C3=B6m?= Date: Tue, 4 Aug 2026 14:11:06 +0200 Subject: [PATCH 1/3] add test --- test/testtokenize.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 79da0177e19..4c10a5c22f6 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -93,6 +93,7 @@ class TestTokenizer : public TestFixture { TEST_CASE(tokenize41); // #13847 TEST_CASE(tokenize42); // #13861 TEST_CASE(tokenize43); // #13861 + TEST_CASE(tokenize44); // #14955 TEST_CASE(validate); @@ -949,6 +950,22 @@ class TestTokenizer : public TestFixture { (void)errout_str(); } + void tokenize44() { // #14955 + const char code[] = "namespace O {}\n" + "namespace N {\n" + " using namespace O;\n" + " enum class E { E0 };\n" + " int E0 = E::E0;\n" + "}\n"; + const char expected[] = "2: namespace N {\n" + "3: using namespace O ;\n" + "4: enum class E { E0 } ;\n" + "5: int E0@1 ; E0@1 = E :: E0 ;\n" + "6: }\n"; + ASSERT_EQUALS(expected, tokenizeDebugListing(code)); + (void)errout_str(); + } + void validate() { // C++ code in C file ASSERT_THROW_INTERNAL(tokenizeAndStringify(";using namespace std;",dinit(TokenizeOptions, $.expand = false, $.cpp = false)), SYNTAX); From 71cb315fb57e60d35921e104568dd73f48c2c14b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludvig=20Gunne=20Lindstr=C3=B6m?= Date: Mon, 3 Aug 2026 15:19:28 +0200 Subject: [PATCH 2/3] fix --- lib/tokenize.cpp | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 07ffa4c666c..4ac419c2dcf 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -5269,7 +5269,29 @@ void Tokenizer::setVarIdPass2() std::map endOfScope; std::list scope; std::list usingnamespaces; + const Token *enumEnd = nullptr; for (Token *tok = list.front(); tok; tok = tok->next()) { + if (tok->str() == "enum") { + tok = tok->next(); + if (tok->str() == "class") + tok = tok->next(); + if (tok->isName()) + tok = tok->next(); + if (tok->str() == ":") { + tok = tok->next(); + if (tok->str() == "::") + tok = tok->next(); + while (Token::Match(tok, "%name% ::")) + tok = tok->tokAt(2); + tok = tok->next(); + } + if (tok->str() == "{") + enumEnd = tok->link(); + } + if (tok == enumEnd) { + enumEnd = nullptr; + continue; + } if (!tok->previous() || Token::Match(tok->previous(), "[;{}]")) { if (Token::Match(tok, "using namespace %name% ::|;")) { Token *endtok = tok->tokAt(2); @@ -5299,7 +5321,8 @@ void Tokenizer::setVarIdPass2() tok = tok->next()->findClosingBracket()->next(); else if (usingnamespaces.empty() || tok->varId() || !tok->isName() || tok->isStandardType() || tok->tokType() == Token::eKeyword || tok->tokType() == Token::eBoolean || Token::Match(tok->previous(), ".|namespace|class|struct|&|&&|*|> %name%") || Token::Match(tok->previous(), "%type%| %name% ( %type%|)") || Token::Match(tok, "public:|private:|protected:") || - (!tok->next() && Token::Match(tok->previous(), "}|; %name%"))) + (!tok->next() && Token::Match(tok->previous(), "}|; %name%")) || + (enumEnd && Token::Match(tok->previous(), "{|, %name% =|,|}"))) continue; if (tok->strAt(-1) == "::" && tok->tokAt(-2) && tok->tokAt(-2)->isName()) From 149c8fbe2ec953b3f7e34b53c867550b573fa789 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludvig=20Gunne=20Lindstr=C3=B6m?= Date: Tue, 4 Aug 2026 16:55:10 +0200 Subject: [PATCH 3/3] use isEnumStart --- lib/tokenize.cpp | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 4ac419c2dcf..71c8d5e517c 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -5271,22 +5271,9 @@ void Tokenizer::setVarIdPass2() std::list usingnamespaces; const Token *enumEnd = nullptr; for (Token *tok = list.front(); tok; tok = tok->next()) { - if (tok->str() == "enum") { - tok = tok->next(); - if (tok->str() == "class") - tok = tok->next(); - if (tok->isName()) - tok = tok->next(); - if (tok->str() == ":") { - tok = tok->next(); - if (tok->str() == "::") - tok = tok->next(); - while (Token::Match(tok, "%name% ::")) - tok = tok->tokAt(2); - tok = tok->next(); - } - if (tok->str() == "{") - enumEnd = tok->link(); + if (isEnumStart(tok)) { + enumEnd = tok->link(); + continue; } if (tok == enumEnd) { enumEnd = nullptr;