From 1e999e0cfe3902b3294db6ee2a155874a101bd5d Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Fri, 19 Aug 2016 19:06:15 +0200 Subject: [PATCH] Fixed #7697 ((debug) Executable scope 'B' with unknown function.) --- lib/symboldatabase.cpp | 19 ++++++++++++++++--- lib/symboldatabase.h | 2 ++ test/testsymboldatabase.cpp | 38 +++++++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 3 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 254b39a04..78620a27b 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -1791,10 +1791,12 @@ bool Function::argsMatch(const Scope *scope, const Token *first, const Token *se } } - // nested class variable + // nested or base class variable else if (depth == 0 && Token::Match(first->next(), "%name%") && - second->next()->str() == scope->className && second->strAt(2) == "::" && - first->next()->str() == second->strAt(3)) { + Token::Match(second->next(), "%name% :: %name%") && + ((second->next()->str() == scope->className) || + (scope->definedType && scope->definedType->isDerivedFrom(second->next()->str()))) && + (first->next()->str() == second->strAt(3))) { second = second->tokAt(2); } @@ -2249,6 +2251,17 @@ bool Type::findDependency(const Type* ancestor) const return false; } +bool Type::isDerivedFrom(const std::string & ancestor) const +{ + for (std::vector::const_iterator parent=derivedFrom.begin(); parent!=derivedFrom.end(); ++parent) { + if (parent->name == ancestor) + return true; + if (parent->type && parent->type->isDerivedFrom(ancestor)) + return true; + } + return false; +} + bool Variable::arrayDimensions(const Library* lib) { const Library::Container* container = lib->detectContainer(_start); diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index 51499ba82..275e6ab0f 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -142,6 +142,8 @@ public: * @return true if there is a dependency */ bool findDependency(const Type* ancestor) const; + + bool isDerivedFrom(const std::string & ancestor) const; }; class CPPCHECKLIB Enumerator { diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index aa5f0a805..faabab85a 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -190,6 +190,7 @@ private: TEST_CASE(functionArgs10); TEST_CASE(functionArgs11); TEST_CASE(functionArgs12); // #7661 + TEST_CASE(functionArgs13); // #7697 TEST_CASE(namespaces1); TEST_CASE(namespaces2); @@ -1830,6 +1831,43 @@ private: } } + void functionArgs13() { // #7697 + GET_SYMBOL_DB("struct A {\n" + " enum E { };\n" + " struct S { };\n" + "};\n" + "struct B : public A {\n" + " B(E e);\n" + " B(S s);\n" + "};\n" + "B::B(A::E e) { }\n" + "B::B(A::S s) { }"); + + ASSERT_EQUALS(true, db != nullptr); + if (db) { + const Token *f = Token::findsimplematch(tokenizer.tokens(), "B ( A :: E"); + ASSERT_EQUALS(true, f && f->function()); + if (f && f->function()) { + const Function *func = f->function(); + ASSERT_EQUALS(true, func->argumentList.size() == 1 && func->argumentList.front().type()); + if (func->argumentList.size() == 1 && func->argumentList.front().type()) { + const Type * type = func->argumentList.front().type(); + ASSERT_EQUALS(true, type->isEnumType() && type->name() == "E"); + } + } + f = Token::findsimplematch(tokenizer.tokens(), "B ( A :: S"); + ASSERT_EQUALS(true, f && f->function()); + if (f && f->function()) { + const Function *func = f->function(); + ASSERT_EQUALS(true, func->argumentList.size() == 1 && func->argumentList.front().type()); + if (func->argumentList.size() == 1 && func->argumentList.front().type()) { + const Type * type = func->argumentList.front().type(); + ASSERT_EQUALS(true, type->isStructType() && type->name() == "S"); + } + } + } + } + void namespaces1() { GET_SYMBOL_DB("namespace fred {\n" " namespace barney {\n"