Fixed #430 (Tokenizer: handle templates with partial specialisation)
This commit is contained in:
parent
266291baf4
commit
a337708ae5
|
@ -632,6 +632,66 @@ void Tokenizer::simplifyTemplates()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Locate specialized templates..
|
||||||
|
for (Token *tok = _tokens; tok; tok = tok->next())
|
||||||
|
{
|
||||||
|
if (tok->str() != "template")
|
||||||
|
continue;
|
||||||
|
if (!Token::simpleMatch(tok->next(), "< >"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// what kind of template is this?
|
||||||
|
Token *tok2 = tok->tokAt(3);
|
||||||
|
while (tok2 && (tok2->isName() || tok2->str() == "*"))
|
||||||
|
tok2 = tok2->next();
|
||||||
|
|
||||||
|
// unknown template.. bail out
|
||||||
|
if (!tok2 || !tok2->previous()->isName())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
tok2 = tok2->previous();
|
||||||
|
std::string s(tok2->str());
|
||||||
|
{
|
||||||
|
const Token *tok3 = tok2->next();
|
||||||
|
while (Token::Match(tok3, "<|, %type%"))
|
||||||
|
{
|
||||||
|
s += " " + tok3->str() + " " + tok3->strAt(1);
|
||||||
|
tok3 = tok3->tokAt(2);
|
||||||
|
if (tok3->str() == "*")
|
||||||
|
{
|
||||||
|
tok3 = tok3->next();
|
||||||
|
s += " *";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!Token::Match(tok3, "> ("))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// save search pattern..
|
||||||
|
const std::string pattern(s + " > (");
|
||||||
|
|
||||||
|
// remove spaces to create new name
|
||||||
|
while (s.find(" ") != std::string::npos)
|
||||||
|
s.erase(s.find(" "), 1);
|
||||||
|
const std::string name(s + ">");
|
||||||
|
|
||||||
|
// Rename template..
|
||||||
|
Token::eraseTokens(tok2, Token::findmatch(tok2, "("));
|
||||||
|
tok2->str(name);
|
||||||
|
|
||||||
|
// delete the "template < >"
|
||||||
|
tok->deleteThis();
|
||||||
|
tok->deleteThis();
|
||||||
|
tok->deleteThis();
|
||||||
|
|
||||||
|
// Use this special template in the code..
|
||||||
|
while (0 != (tok2 = const_cast<Token *>(Token::findmatch(tok2, pattern.c_str()))))
|
||||||
|
{
|
||||||
|
Token::eraseTokens(tok2, Token::findmatch(tok2, "("));
|
||||||
|
tok2->str(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Locate templates..
|
// Locate templates..
|
||||||
std::list<Token *> templates;
|
std::list<Token *> templates;
|
||||||
for (Token *tok = _tokens; tok; tok = tok->next())
|
for (Token *tok = _tokens; tok; tok = tok->next())
|
||||||
|
|
|
@ -84,6 +84,7 @@ private:
|
||||||
TEST_CASE(template11);
|
TEST_CASE(template11);
|
||||||
TEST_CASE(template12);
|
TEST_CASE(template12);
|
||||||
TEST_CASE(template13);
|
TEST_CASE(template13);
|
||||||
|
TEST_CASE(template14);
|
||||||
TEST_CASE(template_default_parameter);
|
TEST_CASE(template_default_parameter);
|
||||||
TEST_CASE(template_typename);
|
TEST_CASE(template_typename);
|
||||||
|
|
||||||
|
@ -1219,6 +1220,25 @@ private:
|
||||||
sizeof_(code);
|
sizeof_(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void template14()
|
||||||
|
{
|
||||||
|
const char code[] = "template <> void foo<int *>()\n"
|
||||||
|
"{ x(); }\n"
|
||||||
|
"\n"
|
||||||
|
"int main()\n"
|
||||||
|
"{\n"
|
||||||
|
"foo<int*>();\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
// The expected result..
|
||||||
|
const std::string expected("void foo<int*> ( ) "
|
||||||
|
"{ x ( ) ; } "
|
||||||
|
"int main ( ) "
|
||||||
|
"{ foo<int*> ( ) ; }");
|
||||||
|
|
||||||
|
ASSERT_EQUALS(expected, sizeof_(code));
|
||||||
|
}
|
||||||
|
|
||||||
void template_default_parameter()
|
void template_default_parameter()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue