diff --git a/src/tokenize.cpp b/src/tokenize.cpp index 4c9451a2b..455ce2fae 100644 --- a/src/tokenize.cpp +++ b/src/tokenize.cpp @@ -512,8 +512,10 @@ void Tokenizer::simplifyTemplates() if (Token::simpleMatch(tok, "template <")) { - while (tok->str() != ">") + while (tok && tok->str() != ">") tok = tok->next(); + if (!tok) + break; } } @@ -582,47 +584,69 @@ void Tokenizer::simplifyTemplates() // Template arguments with default values for (std::list::iterator iter1 = templates.begin(); iter1 != templates.end(); ++iter1) { - Token *eq = 0; - std::string pattern; + std::list eq; + unsigned int templatepar = 1; + std::string classname; for (Token *tok = *iter1; tok; tok = tok->next()) { if (tok->str() == ">") + { + if (Token::Match(tok, "> class %var%")) + classname = tok->strAt(2); break; + } if (tok->str() == ",") - { - if (pattern.empty()) - pattern = " < "; - else - pattern += "%any% , "; - } - if (tok->str() == "=") - { - if (Token::Match(tok, "= %any% > class %var% {")) - { - pattern = tok->strAt(4) + pattern + "%any% >"; - eq = tok; - } - break; - } + ++templatepar; + + else if (tok->str() == "=") + eq.push_back(tok); } - if (!eq || pattern.empty()) + if (eq.empty() || classname.empty()) continue; for (std::list::iterator iter2 = used.begin(); iter2 != used.end(); ++iter2) { - if (Token::Match(*iter2, pattern.c_str())) + Token *tok = *iter2; + + if (!Token::Match(tok, (classname + " < %any%").c_str())) + continue; + + // count the parameters.. + unsigned int usedpar = 1; + for (tok = tok->tokAt(3); tok; tok = tok->tokAt(2)) { - Token *tok = *iter2; - while (tok->next()->str() != ">") + if (tok->str() == ">") + break; + + if (tok->str() == ",") + ++usedpar; + + else + break; + } + if (tok && tok->str() == ">") + { + tok = tok->previous(); + std::list::const_iterator it = eq.begin(); + for (unsigned int i = (templatepar - eq.size()); it != eq.end() && i < usedpar; ++i) + ++it; + while (it != eq.end()) + { + tok->insertToken(","); tok = tok->next(); - tok->insertToken(eq->strAt(1)); - tok->insertToken(","); + tok->insertToken((*it)->strAt(1)); + tok = tok->next(); + ++it; + } } } - eq->deleteThis(); - eq->deleteThis(); + for (std::list::iterator it = eq.begin(); it != eq.end(); ++it) + { + (*it)->deleteThis(); + (*it)->deleteThis(); + } } diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index 2e1780c22..e912bbb79 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -925,30 +925,56 @@ private: void template_default_parameter() { - const char code[] = "template \n" - "class A\n" - "{ T ar[n]; };\n" - "\n" - "void f()\n" - "{\n" - " A a1;\n" - " A a2;\n" - "}\n"; + { + const char code[] = "template \n" + "class A\n" + "{ T ar[n]; };\n" + "\n" + "void f()\n" + "{\n" + " A a1;\n" + " A a2;\n" + "}\n"; - // The expected result.. - const std::string expected(" template < class T , int n >" - " class A" - " { T ar [ n ] ; } ;" - " void f ( )" - " {" - " A a1 ;" - " A a2 ;" - " }" - " class A" - " { int ar [ 2 ] ; }" - " class A" - " { int ar [ 3 ] ; }"); - ASSERT_EQUALS(expected, sizeof_(code)); + // The expected result.. + const std::string expected(" template < class T , int n >" + " class A" + " { T ar [ n ] ; } ;" + " void f ( )" + " {" + " A a1 ;" + " A a2 ;" + " }" + " class A" + " { int ar [ 2 ] ; }" + " class A" + " { int ar [ 3 ] ; }"); + ASSERT_EQUALS(expected, sizeof_(code)); + } + { + const char code[] = "template \n" + "class A\n" + "{ T ar[n1+n2]; };\n" + "\n" + "void f()\n" + "{\n" + " A a1;\n" + " A a2;\n" + "}\n"; + + // The expected result.. + const std::string expected(" template < class T , int n1 , int n2 >" + " class A" + " { T ar [ n1 + n2 ] ; } ;" + " void f ( )" + " {" + " A a1 ;" + " A a2 ;" + " }" + " class A" + " { int ar [ 5 ] ; }"); + ASSERT_EQUALS(expected, sizeof_(code)); + } } void template_typename()