From 583b3400343fd79fd61004bcfeb6301384ed5629 Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Sun, 5 Jun 2016 14:08:33 +0200 Subject: [PATCH] enum: set the return type of derived class functions returning enums defined in a base class. --- lib/symboldatabase.cpp | 37 ++++++++++++++++++++----------------- test/testsymboldatabase.cpp | 24 ++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 17 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 1c17ca089..d357298bc 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -32,6 +32,21 @@ #include #include +static const Type* findVariableTypeInBase(const Scope* scope, const Token* typeTok) +{ + if (scope && scope->definedType && !scope->definedType->derivedFrom.empty()) { + for (std::size_t i = 0; i < scope->definedType->derivedFrom.size(); ++i) { + const Type *base = scope->definedType->derivedFrom[i].type; + if (base && base->classScope) { + const Type * type = base->classScope->findType(typeTok->str()); + if (type) + return type; + } + } + } + return nullptr; +} + //--------------------------------------------------------------------------- SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) @@ -892,8 +907,11 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti const Token *type = func->retDef; while (Token::Match(type, "static|const|struct|union|enum")) type = type->next(); - if (type) - func->retType = findTypeInNested(type, func->nestedIn); + if (type) { + func->retType = findVariableTypeInBase(&*it, type); + if (!func->retType) + func->retType = findTypeInNested(type, func->nestedIn); + } } } } @@ -3413,21 +3431,6 @@ const Enumerator * SymbolDatabase::findEnumerator(const Token * tok) const //--------------------------------------------------------------------------- -static const Type* findVariableTypeInBase(const Scope* scope, const Token* typeTok) -{ - if (scope && scope->definedType && !scope->definedType->derivedFrom.empty()) { - for (std::size_t i = 0; i < scope->definedType->derivedFrom.size(); ++i) { - const Type *base = scope->definedType->derivedFrom[i].type; - if (base && base->classScope) { - const Type * type = base->classScope->findType(typeTok->str()); - if (type) - return type; - } - } - } - return nullptr; -} - const Type* SymbolDatabase::findVariableType(const Scope *start, const Token *typeTok) const { // check if type does not have a namespace diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 1ac76bc85..39fe99294 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -247,6 +247,7 @@ private: TEST_CASE(enum3); TEST_CASE(enum4); TEST_CASE(enum5); + TEST_CASE(enum6); TEST_CASE(isImplicitlyVirtual); TEST_CASE(isPure); @@ -2445,6 +2446,29 @@ private: ASSERT_EQUALS(12U, v->dimension(0)); } + void enum6() { + GET_SYMBOL_DB("struct Fred {\n" + " enum Enum { E0, E1 };\n" + "};\n" + "struct Barney : public Fred {\n" + " Enum func(Enum e) { return e; }\n" + "};"); + ASSERT(db); + if (!db) + return; + const Token * const functionToken = Token::findsimplematch(tokenizer.tokens(), "func"); + ASSERT(functionToken); + if (!functionToken) + return; + const Function *function = functionToken->function(); + ASSERT(function); + if (!function) + return; + ASSERT(function->token->str() == "func"); + ASSERT(function->retDef && function->retDef->str() == "Enum"); + ASSERT(function->retType && function->retType->name() == "Enum"); + } + void isImplicitlyVirtual() { { GET_SYMBOL_DB("class Base {\n"