From cb1a1df0faea66edcf07ec67a20f1a3271e29948 Mon Sep 17 00:00:00 2001 From: IOBYTE Date: Thu, 24 Jan 2019 01:21:22 -0500 Subject: [PATCH] template simplifier: fix out of line member function scope and use more full name matching (#1617) --- lib/templatesimplifier.cpp | 89 +++++++++++++++++++---------------- test/testsimplifytemplate.cpp | 4 +- 2 files changed, 51 insertions(+), 42 deletions(-) diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index 81811e05c..09d79514f 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -94,6 +94,36 @@ TemplateSimplifier::TokenAndName::TokenAndName(Token *tok, const std::string &s, if (tok1) 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) @@ -1118,18 +1148,25 @@ void TemplateSimplifier::addNamespace(const TokenAndName &templateDeclaration, c std::string::size_type end = 0; while ((end = templateDeclaration.scope.find(" ", start)) != std::string::npos) { std::string token = templateDeclaration.scope.substr(start, end - start); + // done if scopes overlap + if (token == tokStart->str() && tok->strAt(-1) != "::") + break; if (insert) mTokenList.back()->tokAt(offset)->insertToken(token, ""); else mTokenList.addtoken(token, tok->linenr(), tok->fileIndex()); start = end + 1; } - if (insert) { - mTokenList.back()->tokAt(offset)->insertToken(templateDeclaration.scope.substr(start), ""); - mTokenList.back()->tokAt(offset)->insertToken("::", ""); - } else { - mTokenList.addtoken(templateDeclaration.scope.substr(start), tok->linenr(), tok->fileIndex()); - mTokenList.addtoken("::", tok->linenr(), tok->fileIndex()); + // don't add if it already exists + std::string token = templateDeclaration.scope.substr(start, end - start); + if (token != tokStart->str() || tok->strAt(-1) != "::") { + if (insert) { + mTokenList.back()->tokAt(offset)->insertToken(templateDeclaration.scope.substr(start), ""); + 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; } else if (!templateDeclaration.scope.empty() && !alreadyHasNamespace(templateDeclaration, tok3) && - closingBracket->strAt(1) != "(") { + !Token::Match(closingBracket->next(), "(|::")) { if (copy) addNamespace(templateDeclaration, tok3); } @@ -2024,7 +2061,7 @@ bool TemplateSimplifier::simplifyTemplateInstantiations( continue; 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 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() { // try to locate a matching declaration for each user defined specialization for (auto & spec : mTemplateDeclarations) { if (spec.isSpecialized()) { - std::string specName = getPathName(spec); - bool found = false; for (auto & decl : mTemplateDeclarations) { if (decl.isSpecialized()) continue; - std::string declName = getPathName(decl); // make sure the scopes and names match - if (specName == declName) { + if (spec.fullName == decl.fullName) { // @todo make sure function parameters also match mTemplateUserSpecializationMap[spec.token] = decl.token; found = true; @@ -2318,10 +2332,8 @@ void TemplateSimplifier::getUserDefinedSpecializations() if (!found) { for (auto & decl : mTemplateForwardDeclarations) { - std::string declName = getPathName(decl); - // make sure the scopes and names match - if (specName == declName) { + if (spec.fullName == decl.fullName) { // @todo make sure function parameters also match mTemplateUserSpecializationMap[spec.token] = decl.token; } @@ -2346,11 +2358,8 @@ void TemplateSimplifier::fixForwardDeclaredDefaultArgumentValues() // make sure the number of arguments match if (params1.size() == params2.size()) { - std::string declName = getPathName(decl); - std::string forwardDeclName = getPathName(forwardDecl); - // make sure the scopes and names match - if (forwardDeclName == declName) { + if (forwardDecl.fullName == decl.fullName) { // save forward declaration for lookup later if ((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.. std::list specializations; for (std::list::const_iterator iter2 = mTemplateDeclarations.begin(); iter2 != mTemplateDeclarations.end(); ++iter2) { - if (iter1->name == iter2->name) + if (iter1->fullName == iter2->fullName) specializations.push_back(iter2->nameToken); } diff --git a/test/testsimplifytemplate.cpp b/test/testsimplifytemplate.cpp index 74b3407a4..2672e11dc 100644 --- a/test/testsimplifytemplate.cpp +++ b/test/testsimplifytemplate.cpp @@ -2636,7 +2636,7 @@ private: "public:\n" " TestClass() {\n" " SomeFunction();\n" - " TemplatedMethod< int >();\n" + " TemplatedMethod< int >( 0 );\n" " }\n" " void SomeFunction() { }\n" "private:\n" @@ -2649,7 +2649,7 @@ private: "public: " "TestClass ( ) { " "SomeFunction ( ) ; " - "TemplatedMethod ( ) ; " + "TemplatedMethod ( 0 ) ; " "} " "void SomeFunction ( ) { } " "private: "