Tokenizer: improved handling of inner templates. Partial fix for #3226
This commit is contained in:
parent
f47ac539d6
commit
49784a44e1
|
@ -2614,7 +2614,10 @@ static unsigned int templateParameters(const Token *tok)
|
||||||
return 0;
|
return 0;
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
|
|
||||||
|
unsigned int level = 0;
|
||||||
|
|
||||||
while (tok) {
|
while (tok) {
|
||||||
|
if (level == 0)
|
||||||
++numberOfParameters;
|
++numberOfParameters;
|
||||||
|
|
||||||
// skip std::
|
// skip std::
|
||||||
|
@ -2632,9 +2635,20 @@ static unsigned int templateParameters(const Token *tok)
|
||||||
if (tok->str() == "*")
|
if (tok->str() == "*")
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
|
|
||||||
|
// inner template
|
||||||
|
if (tok->str() == "<") {
|
||||||
|
++level;
|
||||||
|
tok = tok->next();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// ,/>
|
// ,/>
|
||||||
if (tok->str() == ">")
|
while (tok->str() == ">") {
|
||||||
|
if (level == 0)
|
||||||
return numberOfParameters;
|
return numberOfParameters;
|
||||||
|
--level;
|
||||||
|
tok = tok->next();
|
||||||
|
}
|
||||||
if (tok->str() != ",")
|
if (tok->str() != ",")
|
||||||
break;
|
break;
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
|
@ -2817,6 +2831,32 @@ std::list<Token *> Tokenizer::simplifyTemplatesGetTemplateInstantiations()
|
||||||
break;
|
break;
|
||||||
} else if (Token::Match(tok->previous(), "[({};=] %var% <") ||
|
} else if (Token::Match(tok->previous(), "[({};=] %var% <") ||
|
||||||
Token::Match(tok->tokAt(-2), "[,:] private|protected|public %var% <")) {
|
Token::Match(tok->tokAt(-2), "[,:] private|protected|public %var% <")) {
|
||||||
|
|
||||||
|
// Add inner template instantiations first => go to the ">"
|
||||||
|
// and then parse backwards, adding all seen instantiations
|
||||||
|
const Token *tok2;
|
||||||
|
|
||||||
|
// goto end ">" token
|
||||||
|
unsigned int level = 0;
|
||||||
|
for (tok2 = tok; tok2; tok2 = tok2->next()) {
|
||||||
|
if (tok2->str() == "<") {
|
||||||
|
++level;
|
||||||
|
} else if (tok2->str() == ">") {
|
||||||
|
if (level <= 1)
|
||||||
|
break;
|
||||||
|
--level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse backwards and add template instantiations
|
||||||
|
for (; tok2 && tok2 != tok; tok2 = tok2->previous()) {
|
||||||
|
if (Token::Match(tok2, ", %var% <") &&
|
||||||
|
templateParameters(tok2->tokAt(2))) {
|
||||||
|
used.push_back(tok2->next());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add outer template..
|
||||||
if (templateParameters(tok->next()))
|
if (templateParameters(tok->next()))
|
||||||
used.push_back(tok);
|
used.push_back(tok);
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,6 +118,7 @@ private:
|
||||||
TEST_CASE(template25); // #2648 - another test for sizeof template parameter
|
TEST_CASE(template25); // #2648 - another test for sizeof template parameter
|
||||||
TEST_CASE(template26); // #2721 - passing 'char[2]' as template parameter
|
TEST_CASE(template26); // #2721 - passing 'char[2]' as template parameter
|
||||||
TEST_CASE(template27); // #3350 - removing unused template in macro call
|
TEST_CASE(template27); // #3350 - removing unused template in macro call
|
||||||
|
TEST_CASE(template28);
|
||||||
TEST_CASE(template_unhandled);
|
TEST_CASE(template_unhandled);
|
||||||
TEST_CASE(template_default_parameter);
|
TEST_CASE(template_default_parameter);
|
||||||
TEST_CASE(template_default_type);
|
TEST_CASE(template_default_type);
|
||||||
|
@ -2102,6 +2103,13 @@ private:
|
||||||
ASSERT_EQUALS("X ( class Fred ) ;", sizeof_(code));
|
ASSERT_EQUALS("X ( class Fred ) ;", sizeof_(code));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void template28() {
|
||||||
|
// #3226 - inner template
|
||||||
|
const char code[] = "template<class A, class B> class Fred {};\n"
|
||||||
|
"Fred<int,Fred<int,int> > x;\n";
|
||||||
|
ASSERT_EQUALS("; Fred<int,Fred<int,int>> x ; class Fred<int,int> { } class Fred<int,Fred<int,int>> { }", sizeof_(code));
|
||||||
|
}
|
||||||
|
|
||||||
void template_unhandled() {
|
void template_unhandled() {
|
||||||
// An unhandled template usage should be simplified..
|
// An unhandled template usage should be simplified..
|
||||||
ASSERT_EQUALS("; x<int> ( ) ;", sizeof_(";x<int>();"));
|
ASSERT_EQUALS("; x<int> ( ) ;", sizeof_(";x<int>();"));
|
||||||
|
|
Loading…
Reference in New Issue