diff --git a/src/tokenize.cpp b/src/tokenize.cpp index 9bb2e5e43..29793c52f 100644 --- a/src/tokenize.cpp +++ b/src/tokenize.cpp @@ -469,10 +469,30 @@ void Tokenizer::tokenize(std::istream &code, const char FileName[]) void Tokenizer::simplifyTemplates() { + // Locate templates.. + std::list templates; for (Token *tok = _tokens; tok; tok = tok->next()) { - if (!Token::simpleMatch(tok, "template <")) - continue; + if (Token::simpleMatch(tok, "template <")) + templates.push_back(tok); + } + if (templates.empty()) + return; + + // Locate possible instantiations of templates.. + std::list used; + for (Token *tok = _tokens; tok; tok = tok->next()) + { + if (Token::Match(tok, "%var% <") && tok->str() != "template") + used.push_back(tok); + } + if (used.empty()) + return; + + // expand templates + for (std::list::iterator iter1 = templates.begin(); iter1 != templates.end(); ++iter1) + { + Token *tok = *iter1; std::vector type; for (tok = tok->tokAt(2); tok && tok->str() != ">"; tok = tok->next()) @@ -490,6 +510,7 @@ void Tokenizer::simplifyTemplates() const bool isfunc(tok->strAt(3)[0] == '('); // locate template usage.. + std::string s(name + " <"); for (unsigned int i = 0; i < type.size(); ++i) { @@ -498,8 +519,11 @@ void Tokenizer::simplifyTemplates() s += " %any% "; } const std::string pattern(s + "> "); - for (Token *tok2 = _tokens; tok2; tok2 = tok2->next()) + + for (std::list::iterator iter2 = used.begin(); iter2 != used.end(); ++iter2) { + Token *tok2 = *iter2; + if (tok2->str() != name) continue; diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index d66babc91..efe54bcfd 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -83,6 +83,7 @@ private: TEST_CASE(template3); TEST_CASE(template4); TEST_CASE(template5); + TEST_CASE(template6); TEST_CASE(namespaces); @@ -561,6 +562,20 @@ private: ASSERT_EQUALS(expected, sizeof_(code)); } + void template6() + { + const char code[] = "template class Fred { };\n" + "Fred fred1;\n" + "Fred fred2;"; + + const std::string expected(" template < classname T > class Fred { } ;" + " Fred fred1 ;" + " Fred fred2 ;" + " class Fred { }"); + + ASSERT_EQUALS(expected, sizeof_(code)); + } + void namespaces() {