From edfcc317a2bd8bb56a1e87a07c89adb9d03b3f70 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Wed, 3 Apr 2024 23:39:33 +0200 Subject: [PATCH] Fix #12567 valueFlowBailoutIncompleteVar with nested enum (#6224) --- lib/symboldatabase.cpp | 10 +++++--- test/testsymboldatabase.cpp | 46 +++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index f8390ee2338..d391f053496 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -5246,8 +5246,6 @@ const Enumerator * SymbolDatabase::findEnumerator(const Token * tok, std::setstrAt(-1) == "::") scope = &scopeList.front(); else { - // FIXME search base class here - const Scope* temp = nullptr; if (scope) temp = scope->findRecordInNestedList(tok1->str()); @@ -5255,8 +5253,14 @@ const Enumerator * SymbolDatabase::findEnumerator(const Token * tok, std::setnestedIn) { if (!temp) temp = scope->nestedIn->findRecordInNestedList(tok1->str()); - if (!temp && scope->functionOf) + if (!temp && scope->functionOf) { temp = scope->functionOf->findRecordInNestedList(tok1->str()); + const Scope* nested = scope->functionOf->nestedIn; + while (!temp && nested) { + temp = nested->findRecordInNestedList(tok1->str()); + nested = nested->nestedIn; + } + } if (!temp) temp = findEnumScopeInBase(scope, tok1->str()); if (temp) { diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 6e24b8420a8..fc684d9314b 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -6310,6 +6310,52 @@ class TestSymbolDatabase : public TestFixture { ASSERT(e && e->enumerator()); ASSERT_EQUALS(E0, e->enumerator()); } + { + GET_SYMBOL_DB("namespace ns {\n" // #12567 + " struct S1 {\n" + " enum E { E1 } e;\n" + " };\n" + " struct S2 {\n" + " static void f();\n" + " };\n" + "}\n" + "void ns::S2::f() {\n" + " S1 s;\n" + " s.e = S1::E1;\n" + "}\n"); + ASSERT(db != nullptr); + auto it = db->scopeList.begin(); + std::advance(it, 3); + const Enumerator* E1 = it->findEnumerator("E1"); + ASSERT(E1 && E1->value_known && E1->value == 0); + const Token* const e = Token::findsimplematch(tokenizer.tokens(), "E1 ;"); + ASSERT(e && e->enumerator()); + ASSERT_EQUALS(E1, e->enumerator()); + } + { + GET_SYMBOL_DB("namespace N {\n" + " struct S1 {\n" + " enum E { E1 } e;\n" + " };\n" + " namespace O {\n" + " struct S2 {\n" + " static void f();\n" + " };\n" + " }\n" + "}\n" + "void N::O::S2::f() {\n" + " S1 s;\n" + " s.e = S1::E1;\n" + "}\n"); + ASSERT(db != nullptr); + auto it = db->scopeList.begin(); + std::advance(it, 3); + const Enumerator* E1 = it->findEnumerator("E1"); + ASSERT(E1 && E1->value_known && E1->value == 0); + const Token* const e = Token::findsimplematch(tokenizer.tokens(), "E1 ;"); + ASSERT(e && e->enumerator()); + ASSERT_EQUALS(E1, e->enumerator()); + } } void sizeOfType() {