From d2634ba2c775201eeb105943712f0a41d099fdae Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Wed, 3 Apr 2024 21:58:13 +0200 Subject: [PATCH 1/5] Partial fix for #12564 using type for enum class causes false positives --- lib/symboldatabase.cpp | 2 +- test/testother.cpp | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index f8390ee2338..adb0360a602 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -6370,7 +6370,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", From 6e4dddd5736b2ae0b647b3ee55833cf8fb08e6f5 Mon Sep 17 00:00:00 2001 From: chrchr-github Date: Wed, 3 Apr 2024 22:46:13 +0200 Subject: [PATCH 2/5] Handle scope operator in enum type --- lib/symboldatabase.cpp | 10 +++++++--- test/testsymboldatabase.cpp | 20 ++++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index adb0360a602..d03ddb5ce0d 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); @@ -5149,7 +5152,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 diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 6e24b8420a8..8188b1e6bc1 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); @@ -6312,6 +6313,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" From cfbf0dbd02f8f71836460d31bc5387ec2f130f7d Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Thu, 4 Apr 2024 12:55:51 +0200 Subject: [PATCH 3/5] Update symboldatabase.cpp --- lib/symboldatabase.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index a4cb42383a4..bfd4a1b5c3d 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -123,6 +123,20 @@ static bool isExecutableScope(const Token* tok) return false; } +static bool isEnumDefinition(const Token* tok) +{ + if (!Token::Match(tok, "enum class| %name% {|:")) + return false; + while (!Token::Match(tok, "[{:]")) + tok = tok->next(); + if (tok->str() == "{") + return true; + tok = tok->next(); // skip ':' + while (Token::Match(tok, "%name%|::")) + tok = tok->next(); + return Token::simpleMatch(tok, "{"); +} + void SymbolDatabase::createSymbolDatabaseFindAllScopes() { // create global scope @@ -163,8 +177,7 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes() if ((tok->isCpp() && tok->isKeyword() && ((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% ::|{")))) + isEnumDefinition(tok))) || (tok->isC() && tok->isKeyword() && Token::Match(tok, "struct|union|enum %name% {"))) { const Token *tok2 = tok->tokAt(2); From d49ef4adc236f3b5982140f5b0fe9ba3d1bf7cee Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Thu, 4 Apr 2024 12:57:49 +0200 Subject: [PATCH 4/5] Update testsymboldatabase.cpp --- test/testsymboldatabase.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index ab73df1f46e..ababd60cc2d 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -6372,6 +6372,7 @@ class TestSymbolDatabase : public TestFixture { void enum17() { { GET_SYMBOL_DB("struct S {\n" // #12564 + " enum class E : std::uint8_t;\n" " enum class E : std::uint8_t { E0 };\n" " static void f(S::E e) {\n" " if (e == S::E::E0) {}\n" From f8b613f1908fec885dcb917939678985813e24b8 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Thu, 4 Apr 2024 12:59:55 +0200 Subject: [PATCH 5/5] Update testsymboldatabase.cpp --- test/testsymboldatabase.cpp | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index ababd60cc2d..01a54720496 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -6389,25 +6389,6 @@ 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"