diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index a459d72d2..bb21ad008 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -493,7 +493,7 @@ std::list TemplateSimplifier::getTemplateDecla else if (tok2->str() == "{") { int namepos = getTemplateNamePosition(parmEnd); if (namepos > 0) - declarations.push_back(TokenAndName(tok, getFullName(scopeInfo, parmEnd->strAt(namepos)))); + declarations.push_back(TokenAndName(tok, getScopeName(scopeInfo), getFullName(scopeInfo, parmEnd->strAt(namepos)))); break; } } @@ -502,7 +502,7 @@ std::list TemplateSimplifier::getTemplateDecla } -std::list TemplateSimplifier::getTemplateInstantiations(Token *tokens) +std::list TemplateSimplifier::getTemplateInstantiations(Token *tokens, const std::list &declarations) { std::list instantiations; std::list scopeList; @@ -541,13 +541,35 @@ std::list TemplateSimplifier::getTemplateInsta for (; tok2 && tok2 != tok; tok2 = tok2->previous()) { if (Token::Match(tok2, ", %name% <") && TemplateSimplifier::templateParameters(tok2->tokAt(2))) { - instantiations.push_back(TokenAndName(tok2->next(),getFullName(scopeList, tok2->strAt(1)))); + instantiations.push_back(TokenAndName(tok2->next(), getScopeName(scopeList), getFullName(scopeList, tok2->strAt(1)))); } } // Add outer template.. - if (TemplateSimplifier::templateParameters(tok->next())) - instantiations.push_back(TokenAndName(tok, scopeName + (scopeName.empty()?"":" :: ") + tok->str())); + if (TemplateSimplifier::templateParameters(tok->next())) { + bool done = false; + const std::string scopeName1(scopeName); + while (!done) { + const std::string fullName = scopeName + (scopeName.empty()?"":" :: ") + tok->str(); + + for (std::list::const_iterator it = declarations.begin(); it != declarations.end(); ++it) { + if (it->name == fullName) { + instantiations.push_back(TokenAndName(tok, getScopeName(scopeList), fullName)); + done = true; + break; + } + } + + if (!done) { + if (scopeName.empty()) { + instantiations.push_back(TokenAndName(tok, getScopeName(scopeList), scopeName1 + (scopeName1.empty()?"":" :: ") + tok->str())); + break; + } + const std::string::size_type pos = scopeName.rfind(" :: "); + scopeName = (pos == std::string::npos) ? std::string() : scopeName.substr(0,pos); + } + } + } } } @@ -995,7 +1017,7 @@ void TemplateSimplifier::expandTemplate( std::string name = tok3->str(); for (const Token *prev = tok3->tokAt(-2); Token::Match(prev, "%name% ::"); prev = prev->tokAt(-2)) name = prev->str() + " :: " + name; - templateInstantiations.push_back(TokenAndName(tokenlist.back(), getFullName(scopeInfo, name))); + templateInstantiations.push_back(TokenAndName(tokenlist.back(), getScopeName(scopeInfo), getFullName(scopeInfo, name))); } // link() newly tokens manually @@ -1636,7 +1658,7 @@ void TemplateSimplifier::simplifyTemplates( std::list templates(TemplateSimplifier::getTemplateDeclarations(tokenlist.front(), _codeWithTemplates)); // Locate possible instantiations of templates.. - std::list templateInstantiations(TemplateSimplifier::getTemplateInstantiations(tokenlist.front())); + std::list templateInstantiations(TemplateSimplifier::getTemplateInstantiations(tokenlist.front(), templates)); // No template instantiations? Then return. if (templateInstantiations.empty()) diff --git a/lib/templatesimplifier.h b/lib/templatesimplifier.h index 174d3a79b..a05fec68c 100644 --- a/lib/templatesimplifier.h +++ b/lib/templatesimplifier.h @@ -76,8 +76,9 @@ public: * Token and its full scopename */ struct TokenAndName { - TokenAndName(Token *tok, const std::string &scopeName) : token(tok), name(scopeName) {} + TokenAndName(Token *tok, const std::string &s, const std::string &n) : token(tok), scope(s), name(n) {} Token *token; + std::string scope; std::string name; }; @@ -89,9 +90,11 @@ public: /** * Get template instantiations + * @param tokens start of token list + * @param declarations template declarations, so names can be matched * @return list of template instantiations */ - static std::list getTemplateInstantiations(Token *tokens); + static std::list getTemplateInstantiations(Token *tokens, const std::list &declarations); /** * simplify template instantiations (use default argument values) diff --git a/test/testsimplifytemplate.cpp b/test/testsimplifytemplate.cpp index 8bfbc4d12..d76600f49 100644 --- a/test/testsimplifytemplate.cpp +++ b/test/testsimplifytemplate.cpp @@ -110,6 +110,7 @@ private: TEST_CASE(template_namespace_2); TEST_CASE(template_namespace_3); TEST_CASE(template_namespace_4); + TEST_CASE(template_namespace_5); // Test TemplateSimplifier::templateParameters TEST_CASE(templateParameters); @@ -1455,6 +1456,12 @@ private: "class foo::A { void dostuff ( ) { } } ;", tok(code)); } + void template_namespace_5() { + const char code[] = "template struct S {};\n" + "namespace X { S s; }"; + ASSERT_EQUALS("namespace X { S s ; } struct S { } ;", tok(code)); + } + unsigned int templateParameters(const char code[]) { Tokenizer tokenizer(&settings, this);