SymbolDatabase: Fixed return type token detection for template member functions (#7945)
This commit is contained in:
parent
ca3e3b3cdb
commit
8a3fb4dd6c
|
@ -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
|
||||||
|
|
|
@ -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")
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue