Templates: Scaled up the handling of default values for template parameters (#638)

This commit is contained in:
Daniel Marjamäki 2009-09-06 08:22:45 +02:00
parent 75a65a02a8
commit 535fe17ffd
2 changed files with 99 additions and 49 deletions

View File

@ -512,8 +512,10 @@ void Tokenizer::simplifyTemplates()
if (Token::simpleMatch(tok, "template <")) if (Token::simpleMatch(tok, "template <"))
{ {
while (tok->str() != ">") while (tok && tok->str() != ">")
tok = tok->next(); tok = tok->next();
if (!tok)
break;
} }
} }
@ -582,47 +584,69 @@ void Tokenizer::simplifyTemplates()
// Template arguments with default values // Template arguments with default values
for (std::list<Token *>::iterator iter1 = templates.begin(); iter1 != templates.end(); ++iter1) for (std::list<Token *>::iterator iter1 = templates.begin(); iter1 != templates.end(); ++iter1)
{ {
Token *eq = 0; std::list<Token *> eq;
std::string pattern; unsigned int templatepar = 1;
std::string classname;
for (Token *tok = *iter1; tok; tok = tok->next()) 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() == ",")
++templatepar;
else if (tok->str() == "=")
eq.push_back(tok);
}
if (eq.empty() || classname.empty())
continue;
for (std::list<Token *>::iterator iter2 = used.begin(); iter2 != used.end(); ++iter2)
{
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))
{ {
if (tok->str() == ">") if (tok->str() == ">")
break; break;
if (tok->str() == ",") if (tok->str() == ",")
{ ++usedpar;
if (pattern.empty())
pattern = " < ";
else else
pattern += "%any% , ";
}
if (tok->str() == "=")
{
if (Token::Match(tok, "= %any% > class %var% {"))
{
pattern = tok->strAt(4) + pattern + "%any% >";
eq = tok;
}
break; break;
} }
} if (tok && tok->str() == ">")
if (!eq || pattern.empty())
continue;
for (std::list<Token *>::iterator iter2 = used.begin(); iter2 != used.end(); ++iter2)
{ {
if (Token::Match(*iter2, pattern.c_str())) tok = tok->previous();
std::list<Token *>::const_iterator it = eq.begin();
for (unsigned int i = (templatepar - eq.size()); it != eq.end() && i < usedpar; ++i)
++it;
while (it != eq.end())
{ {
Token *tok = *iter2;
while (tok->next()->str() != ">")
tok = tok->next();
tok->insertToken(eq->strAt(1));
tok->insertToken(","); tok->insertToken(",");
tok = tok->next();
tok->insertToken((*it)->strAt(1));
tok = tok->next();
++it;
}
} }
} }
eq->deleteThis(); for (std::list<Token *>::iterator it = eq.begin(); it != eq.end(); ++it)
eq->deleteThis(); {
(*it)->deleteThis();
(*it)->deleteThis();
}
} }

View File

@ -924,6 +924,7 @@ private:
} }
void template_default_parameter() void template_default_parameter()
{
{ {
const char code[] = "template <class T, int n=3>\n" const char code[] = "template <class T, int n=3>\n"
"class A\n" "class A\n"
@ -950,6 +951,31 @@ private:
" { int ar [ 3 ] ; }"); " { int ar [ 3 ] ; }");
ASSERT_EQUALS(expected, sizeof_(code)); ASSERT_EQUALS(expected, sizeof_(code));
} }
{
const char code[] = "template <class T, int n1=3, int n2=2>\n"
"class A\n"
"{ T ar[n1+n2]; };\n"
"\n"
"void f()\n"
"{\n"
" A<int> a1;\n"
" A<int,3> 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<int,3,2> a1 ;"
" A<int,3,2> a2 ;"
" }"
" class A<int,3,2>"
" { int ar [ 5 ] ; }");
ASSERT_EQUALS(expected, sizeof_(code));
}
}
void template_typename() void template_typename()
{ {