template simplifier: fix out of line member function scope and use more full name matching (#1617)

This commit is contained in:
IOBYTE 2019-01-24 01:21:22 -05:00 committed by Daniel Marjamäki
parent 080c9d53af
commit cb1a1df0fa
2 changed files with 51 additions and 42 deletions

View File

@ -94,6 +94,36 @@ TemplateSimplifier::TokenAndName::TokenAndName(Token *tok, const std::string &s,
if (tok1) if (tok1)
isForwardDeclaration(tok1->str() == ";"); isForwardDeclaration(tok1->str() == ";");
} }
// check for member function and adjust scope
if (isFunction() && nameToken->strAt(-1) == "::") {
const Token * start = nameToken;
while (Token::Match(start->tokAt(-2), "%name% ::") ||
(Token::simpleMatch(start->tokAt(-2), "> ::") &&
Token::Match(start->tokAt(-2)->findOpeningBracket()->previous(), "%name% <"))) {
if (start->strAt(-2) == ">")
start = start->tokAt(-2)->findOpeningBracket()->previous();
else
start = start->tokAt(-2);
}
if (start && start != nameToken) {
if (!scope.empty())
scope += " ::";
while (start && start->next() != nameToken) {
if (start->str() == "<")
start = start->findClosingBracket();
else {
if (!scope.empty())
scope += " ";
scope += start->str();
}
start = start->next();
}
if (start)
fullName = scope.empty() ? name : (scope + " :: " + name);
}
}
} }
if (token) if (token)
@ -1118,18 +1148,25 @@ void TemplateSimplifier::addNamespace(const TokenAndName &templateDeclaration, c
std::string::size_type end = 0; std::string::size_type end = 0;
while ((end = templateDeclaration.scope.find(" ", start)) != std::string::npos) { while ((end = templateDeclaration.scope.find(" ", start)) != std::string::npos) {
std::string token = templateDeclaration.scope.substr(start, end - start); std::string token = templateDeclaration.scope.substr(start, end - start);
// done if scopes overlap
if (token == tokStart->str() && tok->strAt(-1) != "::")
break;
if (insert) if (insert)
mTokenList.back()->tokAt(offset)->insertToken(token, ""); mTokenList.back()->tokAt(offset)->insertToken(token, "");
else else
mTokenList.addtoken(token, tok->linenr(), tok->fileIndex()); mTokenList.addtoken(token, tok->linenr(), tok->fileIndex());
start = end + 1; start = end + 1;
} }
if (insert) { // don't add if it already exists
mTokenList.back()->tokAt(offset)->insertToken(templateDeclaration.scope.substr(start), ""); std::string token = templateDeclaration.scope.substr(start, end - start);
mTokenList.back()->tokAt(offset)->insertToken("::", ""); if (token != tokStart->str() || tok->strAt(-1) != "::") {
} else { if (insert) {
mTokenList.addtoken(templateDeclaration.scope.substr(start), tok->linenr(), tok->fileIndex()); mTokenList.back()->tokAt(offset)->insertToken(templateDeclaration.scope.substr(start), "");
mTokenList.addtoken("::", tok->linenr(), tok->fileIndex()); mTokenList.back()->tokAt(offset)->insertToken("::", "");
} else {
mTokenList.addtoken(templateDeclaration.scope.substr(start), tok->linenr(), tok->fileIndex());
mTokenList.addtoken("::", tok->linenr(), tok->fileIndex());
}
} }
} }
@ -1482,7 +1519,7 @@ void TemplateSimplifier::expandTemplate(
continue; continue;
} else if (!templateDeclaration.scope.empty() && } else if (!templateDeclaration.scope.empty() &&
!alreadyHasNamespace(templateDeclaration, tok3) && !alreadyHasNamespace(templateDeclaration, tok3) &&
closingBracket->strAt(1) != "(") { !Token::Match(closingBracket->next(), "(|::")) {
if (copy) if (copy)
addNamespace(templateDeclaration, tok3); addNamespace(templateDeclaration, tok3);
} }
@ -2024,7 +2061,7 @@ bool TemplateSimplifier::simplifyTemplateInstantiations(
continue; continue;
if (instantiation.fullName != templateDeclaration.fullName) { if (instantiation.fullName != templateDeclaration.fullName) {
// FIXME: fallback to not matching scopes until using namespace and type deduction work // FIXME: fallback to not matching scopes until type deduction work
// names must match // names must match
if (instantiation.name != templateDeclaration.name) if (instantiation.name != templateDeclaration.name)
@ -2275,41 +2312,18 @@ void TemplateSimplifier::replaceTemplateUsage(
} }
} }
static std::string getPathName(const TemplateSimplifier::TokenAndName & decl)
{
std::string name = decl.scope;
if (!name.empty())
name += " :: ";
if (decl.nameToken->strAt(-1) == "::") {
const Token * start = decl.nameToken;
while (Token::Match(start->tokAt(-2), "%name% ::"))
start = start->tokAt(-2);
while (start != decl.nameToken) {
name += (start->str() + " ");
start = start->next();
}
}
name += decl.name;
return name;
}
void TemplateSimplifier::getUserDefinedSpecializations() void TemplateSimplifier::getUserDefinedSpecializations()
{ {
// try to locate a matching declaration for each user defined specialization // try to locate a matching declaration for each user defined specialization
for (auto & spec : mTemplateDeclarations) { for (auto & spec : mTemplateDeclarations) {
if (spec.isSpecialized()) { if (spec.isSpecialized()) {
std::string specName = getPathName(spec);
bool found = false; bool found = false;
for (auto & decl : mTemplateDeclarations) { for (auto & decl : mTemplateDeclarations) {
if (decl.isSpecialized()) if (decl.isSpecialized())
continue; continue;
std::string declName = getPathName(decl);
// make sure the scopes and names match // make sure the scopes and names match
if (specName == declName) { if (spec.fullName == decl.fullName) {
// @todo make sure function parameters also match // @todo make sure function parameters also match
mTemplateUserSpecializationMap[spec.token] = decl.token; mTemplateUserSpecializationMap[spec.token] = decl.token;
found = true; found = true;
@ -2318,10 +2332,8 @@ void TemplateSimplifier::getUserDefinedSpecializations()
if (!found) { if (!found) {
for (auto & decl : mTemplateForwardDeclarations) { for (auto & decl : mTemplateForwardDeclarations) {
std::string declName = getPathName(decl);
// make sure the scopes and names match // make sure the scopes and names match
if (specName == declName) { if (spec.fullName == decl.fullName) {
// @todo make sure function parameters also match // @todo make sure function parameters also match
mTemplateUserSpecializationMap[spec.token] = decl.token; mTemplateUserSpecializationMap[spec.token] = decl.token;
} }
@ -2346,11 +2358,8 @@ void TemplateSimplifier::fixForwardDeclaredDefaultArgumentValues()
// make sure the number of arguments match // make sure the number of arguments match
if (params1.size() == params2.size()) { if (params1.size() == params2.size()) {
std::string declName = getPathName(decl);
std::string forwardDeclName = getPathName(forwardDecl);
// make sure the scopes and names match // make sure the scopes and names match
if (forwardDeclName == declName) { if (forwardDecl.fullName == decl.fullName) {
// save forward declaration for lookup later // save forward declaration for lookup later
if ((decl.nameToken->strAt(1) == "(" && forwardDecl.nameToken->strAt(1) == "(") || if ((decl.nameToken->strAt(1) == "(" && forwardDecl.nameToken->strAt(1) == "(") ||
(decl.nameToken->strAt(1) == "{" && forwardDecl.nameToken->strAt(1) == ";")) { (decl.nameToken->strAt(1) == "{" && forwardDecl.nameToken->strAt(1) == ";")) {
@ -2519,7 +2528,7 @@ void TemplateSimplifier::simplifyTemplates(
// get specializations.. // get specializations..
std::list<const Token *> specializations; std::list<const Token *> specializations;
for (std::list<TokenAndName>::const_iterator iter2 = mTemplateDeclarations.begin(); iter2 != mTemplateDeclarations.end(); ++iter2) { for (std::list<TokenAndName>::const_iterator iter2 = mTemplateDeclarations.begin(); iter2 != mTemplateDeclarations.end(); ++iter2) {
if (iter1->name == iter2->name) if (iter1->fullName == iter2->fullName)
specializations.push_back(iter2->nameToken); specializations.push_back(iter2->nameToken);
} }

View File

@ -2636,7 +2636,7 @@ private:
"public:\n" "public:\n"
" TestClass() {\n" " TestClass() {\n"
" SomeFunction();\n" " SomeFunction();\n"
" TemplatedMethod< int >();\n" " TemplatedMethod< int >( 0 );\n"
" }\n" " }\n"
" void SomeFunction() { }\n" " void SomeFunction() { }\n"
"private:\n" "private:\n"
@ -2649,7 +2649,7 @@ private:
"public: " "public: "
"TestClass ( ) { " "TestClass ( ) { "
"SomeFunction ( ) ; " "SomeFunction ( ) ; "
"TemplatedMethod<int> ( ) ; " "TemplatedMethod<int> ( 0 ) ; "
"} " "} "
"void SomeFunction ( ) { } " "void SomeFunction ( ) { } "
"private: " "private: "