diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 07ffa4c666c..71c8d5e517c 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -5269,7 +5269,16 @@ 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 (isEnumStart(tok)) { + enumEnd = tok->link(); + continue; + } + 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 +5308,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()) diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index 79da0177e19..600d457e944 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,21 @@ 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" + " E E0 = E::E0;\n" + "}\n"; + const char expected[] = "2: namespace N {\n" + "3: using namespace O ;\n" + "4: enum class E { E0 } ;\n" + "5: E E0@1 ; E0@1 = E :: E0 ;\n" + "6: }\n"; + ASSERT_EQUALS(expected, tokenizeDebugListing(code)); + } + void validate() { // C++ code in C file ASSERT_THROW_INTERNAL(tokenizeAndStringify(";using namespace std;",dinit(TokenizeOptions, $.expand = false, $.cpp = false)), SYNTAX);