SymbolDatabase: Fixed return type token detection for template member functions (#7945)

This commit is contained in:
PKEuS 2017-03-16 20:47:24 +01:00
parent ca3e3b3cdb
commit 8a3fb4dd6c
2 changed files with 39 additions and 4 deletions

View File

@ -434,24 +434,30 @@ void SymbolDatabase::createSymbolDatabaseFindAllScopes()
// look for end of previous statement // look for end of previous statement
while (tok1->previous() && !Token::Match(tok1->previous(), ";|}|{|public:|protected:|private:")) { while (tok1->previous() && !Token::Match(tok1->previous(), ";|}|{|public:|protected:|private:")) {
// virtual function // virtual function
if (tok1->previous()->str() == "virtual") { const Token* tok2 = tok1->previous();
if (tok2->str() == "virtual") {
function.isVirtual(true); function.isVirtual(true);
break; break;
} }
// static function // static function
else if (tok1->previous()->str() == "static") { else if (tok2->str() == "static") {
function.isStatic(true); function.isStatic(true);
break; break;
} }
// friend function // friend function
else if (tok1->previous()->str() == "friend") { else if (tok2->str() == "friend") {
function.isFriend(true); function.isFriend(true);
break; 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 // find the return type

View File

@ -151,6 +151,7 @@ private:
TEST_CASE(hasRegularFunctionReturningFunctionPointer); TEST_CASE(hasRegularFunctionReturningFunctionPointer);
TEST_CASE(hasInlineClassFunctionReturningFunctionPointer); TEST_CASE(hasInlineClassFunctionReturningFunctionPointer);
TEST_CASE(hasMissingInlineClassFunctionReturningFunctionPointer); TEST_CASE(hasMissingInlineClassFunctionReturningFunctionPointer);
TEST_CASE(hasInlineClassOperatorTemplate);
TEST_CASE(hasClassFunctionReturningFunctionPointer); TEST_CASE(hasClassFunctionReturningFunctionPointer);
TEST_CASE(methodWithRedundantScope); TEST_CASE(methodWithRedundantScope);
TEST_CASE(complexFunctionArrayPtr); TEST_CASE(complexFunctionArrayPtr);
@ -994,6 +995,34 @@ private:
} }
} }
void hasInlineClassOperatorTemplate() {
GET_SYMBOL_DB("struct Fred { template<typename T> 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() { void hasClassFunction() {
GET_SYMBOL_DB("class Fred { void func(); }; void Fred::func() { }\n") GET_SYMBOL_DB("class Fred { void func(); }; void Fred::func() { }\n")