diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index ad3d9a3dd..099f855c2 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -434,24 +434,30 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes() // look for end of previous statement while (tok1->previous() && !Token::Match(tok1->previous(), ";|}|{|public:|protected:|private:")) { // virtual function - if (tok1->previous()->str() == "virtual") { + const Token* tok2 = tok1->previous(); + + if (tok2->str() == "virtual") { function.isVirtual(true); break; } // static function - else if (tok1->previous()->str() == "static") { + else if (tok2->str() == "static") { function.isStatic(true); break; } // friend function - else if (tok1->previous()->str() == "friend") { + else if (tok2->str() == "friend") { function.isFriend(true); break; } - tok1 = tok1->previous(); + // Function template + else if (tok2->str() == ">" && tok2->link() && Token::Match(tok2->link()->previous(), "template <")) + break; + + tok1 = tok2; } // find the return type diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 4a536b565..eba49feb3 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -151,6 +151,7 @@ private: TEST_CASE(hasRegularFunctionReturningFunctionPointer); TEST_CASE(hasInlineClassFunctionReturningFunctionPointer); TEST_CASE(hasMissingInlineClassFunctionReturningFunctionPointer); + TEST_CASE(hasInlineClassOperatorTemplate); TEST_CASE(hasClassFunctionReturningFunctionPointer); TEST_CASE(methodWithRedundantScope); TEST_CASE(complexFunctionArrayPtr); @@ -994,6 +995,34 @@ private: } } + void hasInlineClassOperatorTemplate() { + GET_SYMBOL_DB("struct Fred { template Foo & operator=(const Foo &) { return *this; } };"); + + // 3 scopes: Global, Class, and Function + ASSERT(db && db->scopeList.size() == 3); + + if (db) { + const Token * const functionToken = Token::findsimplematch(tokenizer.tokens(), "operator="); + + const Scope *scope = findFunctionScopeByToken(db, functionToken); + + ASSERT(scope && scope->className == "operator="); + if (!scope) + return; + ASSERT(scope->functionOf && scope->functionOf == db->findScopeByName("Fred")); + + const Function *function = findFunctionByName("operator=", &db->scopeList.back()); + + ASSERT(function && function->token->str() == "operator="); + ASSERT(function && function->token == functionToken); + ASSERT(function && function->hasBody() && function->isInline()); + ASSERT(function && function->functionScope == scope && scope->function == function && function->nestedIn == db->findScopeByName("Fred")); + ASSERT(function && function->retDef == functionToken->tokAt(-2)); + + ASSERT(db && db->findScopeByName("Fred") && db->findScopeByName("Fred")->definedType->getFunction("operator=") == function); + } + } + void hasClassFunction() { GET_SYMBOL_DB("class Fred { void func(); }; void Fred::func() { }\n")