diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 8428093cb..b85bc8670 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1750,9 +1750,11 @@ namespace { ScopeInfo3() : parent(nullptr), type(Global), bodyStart(nullptr), bodyEnd(nullptr) {} ScopeInfo3(ScopeInfo3 *parent_, Type type_, const std::string &name_, const Token *bodyStart_, const Token *bodyEnd_) : parent(parent_), type(type_), name(name_), bodyStart(bodyStart_), bodyEnd(bodyEnd_) { + if (name.empty()) + return; fullName = name; ScopeInfo3 *scope = parent; - while (!fullName.empty() && scope && scope->parent) { + while (scope && scope->parent) { fullName = scope->name + " :: " + fullName; scope = scope->parent; } @@ -1806,9 +1808,31 @@ namespace { } } + const ScopeInfo3 * findScope(const std::string & scope) const { + const ScopeInfo3 * tempScope = this; + while (tempScope) { + for (const auto & child : tempScope->children) { + if (child.name == scope || child.fullName == scope) + return &child; + } + + tempScope = tempScope->parent; + } + return nullptr; + } + bool findTypeInBase(const std::string &scope) const { + // check in base types first if (baseTypes.find(scope) != baseTypes.end()) return true; + // check in base types base types + for (const std::string & base : baseTypes) { + const ScopeInfo3 * baseScope = findScope(base); + if (baseScope && baseScope->fullName == scope) + return true; + if (baseScope && baseScope->findTypeInBase(scope)) + return true; + } return false; } }; diff --git a/test/testsimplifyusing.cpp b/test/testsimplifyusing.cpp index a30a860cb..458ce81c9 100644 --- a/test/testsimplifyusing.cpp +++ b/test/testsimplifyusing.cpp @@ -79,6 +79,7 @@ private: TEST_CASE(simplifyUsing10008); TEST_CASE(simplifyUsing10054); TEST_CASE(simplifyUsing10136); + TEST_CASE(simplifyUsing10171); } std::string tok(const char code[], bool simplify = true, Settings::PlatformType type = Settings::Native, bool debugwarnings = true) { @@ -984,7 +985,7 @@ private: "namespace NS3 { " "class C : public A { " "public: " - "void f ( const V & ) const override ; " + "void f ( const std :: vector < char > & ) const override ; " "} ; " "void C :: f ( const V & ) const { } " "} " @@ -998,9 +999,42 @@ private: "c . f ( v ) ; " "}"; TODO_ASSERT_EQUALS(exp, act, tok(code, true)); - TODO_ASSERT_EQUALS("", "[test.cpp:20]: (debug) Executable scope 'f' with unknown function.\n", errout.str()); + TODO_ASSERT_EQUALS("", + "[test.cpp:18]: (debug) Executable scope 'f' with unknown function.\n" + "[test.cpp:20]: (debug) Executable scope 'f' with unknown function.\n", errout.str()); } } + + void simplifyUsing10171() { + const char code[] = "namespace ns {\n" + " class A {\n" + " public:\n" + " using V = std::vector;\n" + " virtual void f(const V&) const = 0;\n" + " };\n" + " class B : public A {\n" + " public:\n" + " void f(const V&) const override;\n" + " };\n" + "}\n" + "namespace ns {\n" + " void B::f(const std::vector&) const { }\n" + "}"; + const char exp[] = "namespace ns { " + "class A { " + "public: " + "virtual void f ( const std :: vector < unsigned char > & ) const = 0 ; " + "} ; " + "class B : public A { " + "public: " + "void f ( const std :: vector < unsigned char > & ) const override ; " + "} ; " + "} " + "namespace ns { " + "void B :: f ( const std :: vector < unsigned char > & ) const { } " + "}"; + ASSERT_EQUALS(exp, tok(code, false)); + } }; REGISTER_TEST(TestSimplifyUsing)