From 2b88ca8660411fba8eb3d22e9363a0994656a2fd Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Thu, 4 Apr 2024 12:09:08 +0200 Subject: [PATCH] Fix #12564 using type for enum class causes false positives (#6227) --- lib/symboldatabase.cpp | 12 ++++++++---- test/testother.cpp | 9 +++++++++ test/testsymboldatabase.cpp | 20 ++++++++++++++++++++ 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index b51d10b517e..a4cb42383a4 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -164,7 +164,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes() ((Token::Match(tok, "class|struct|union|namespace ::| %name% final| {|:|::|<") && !Token::Match(tok->previous(), "new|friend|const|enum|typedef|mutable|volatile|using|)|(|<")) || (Token::Match(tok, "enum class| %name% {") || - Token::Match(tok, "enum class| %name% : %name% {")))) + Token::Match(tok, "enum class| %name% : %name% ::|{")))) || (tok->isC() && tok->isKeyword() && Token::Match(tok, "struct|union|enum %name% {"))) { const Token *tok2 = tok->tokAt(2); @@ -301,8 +301,11 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes() mTokenizer.syntaxError(tok); } } else if (new_scope->type == Scope::eEnum) { - if (tok2->str() == ":") + if (tok2->str() == ":") { tok2 = tok2->tokAt(2); + while (Token::Match(tok2, "%name%|::")) + tok2 = tok2->next(); + } } new_scope->setBodyStartEnd(tok2); @@ -5152,7 +5155,8 @@ const Token * Scope::addEnum(const Token * tok) tok2 = tok2->next(); enumType = tok2; - tok2 = tok2->next(); + while (Token::Match(tok2, "%name%|::")) + tok2 = tok2->next(); } // add enumerators @@ -6377,7 +6381,7 @@ const Type* SymbolDatabase::findTypeInNested(const Token *startTok, const Scope startTok = startTok->next(); // type same as scope - if (startTok->str() == startScope->className && startScope->isClassOrStruct()) + if (startScope->isClassOrStruct() && startTok->str() == startScope->className && !Token::simpleMatch(startTok->next(), "::")) return startScope->definedType; bool hasPath = false; diff --git a/test/testother.cpp b/test/testother.cpp index 03e349d8a48..5035795b236 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -2262,6 +2262,15 @@ class TestOther : public TestFixture { ASSERT_EQUALS("[test.cpp:2]: (performance) Function parameter 's' should be passed by const reference.\n", errout_str()); + check("struct S {\n" + " enum class E : std::uint8_t { E0 };\n" + " static void f(S::E e) {\n" + " if (e == S::E::E0) {}\n" + " }\n" + " char a[20];\n" + "};\n"); + ASSERT_EQUALS("", errout_str()); + /*const*/ Settings settings1 = settingsBuilder().platform(Platform::Type::Win64).build(); check("using ui64 = unsigned __int64;\n" "ui64 Test(ui64 one, ui64 two) { return one + two; }\n", diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 43330c0541f..271ba73770c 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -448,6 +448,7 @@ class TestSymbolDatabase : public TestFixture { TEST_CASE(enum14); TEST_CASE(enum15); TEST_CASE(enum16); + TEST_CASE(enum17); TEST_CASE(sizeOfType); @@ -6368,6 +6369,25 @@ class TestSymbolDatabase : public TestFixture { } } + void enum17() { + { + GET_SYMBOL_DB("struct S {\n" // #12564 + " enum class E : std::uint8_t { E0 };\n" + " static void f(S::E e) {\n" + " if (e == S::E::E0) {}\n" + " }\n" + "};\n"); + ASSERT(db != nullptr); + auto it = db->scopeList.begin(); + std::advance(it, 2); + const Enumerator* E0 = it->findEnumerator("E0"); + ASSERT(E0 && E0->value_known && E0->value == 0); + const Token* const e = Token::findsimplematch(tokenizer.tokens(), "E0 )"); + ASSERT(e && e->enumerator()); + ASSERT_EQUALS(E0, e->enumerator()); + } + } + void sizeOfType() { // #7615 - crash in Symboldatabase::sizeOfType() GET_SYMBOL_DB("enum e;\n"