partial fix for #8663 (Stack overflow with template disambiguator) (#1801)

This fixes simplifyUsing to remove 'typename' and 'template' from type
aliases of the form: using T3 = typename T1::template T3<T2>;

This lets the template simplifier instantiate the type alias which will
then remove the using type alias.

The crash will still happen if there is no instantiation because the
type alias will not be removed.  The type alias is what cppcheck is
crashing on after the template simplifier and that still needs fixing.
This commit is contained in:
IOBYTE 2019-04-21 00:46:16 -04:00 committed by Daniel Marjamäki
parent ff8cf4fe25
commit e786c6b7d4
3 changed files with 42 additions and 3 deletions

View File

@ -3021,9 +3021,9 @@ void TemplateSimplifier::simplifyTemplates(
const std::time_t maxtime,
bool &codeWithTemplates)
{
// Remove "typename" unless used in template arguments..
// Remove "typename" unless used in template arguments or using type alias..
for (Token *tok = mTokenList.front(); tok; tok = tok->next()) {
if (Token::Match(tok, "typename %name%"))
if (Token::Match(tok, "typename %name%") && !Token::Match(tok->tokAt(-3), "using %name% ="))
tok->deleteThis();
if (Token::simpleMatch(tok, "template <")) {

View File

@ -1797,7 +1797,7 @@ namespace {
return false;
}
if (Token::Match(tok1->tokAt(-1), "struct|union|enum")) {
if (Token::Match(tok1->tokAt(-1), "class|struct|union|enum")) {
// fixme
return false;
}
@ -1977,6 +1977,16 @@ bool Tokenizer::simplifyUsing()
}
}
// remove 'typename' and 'template'
else if (start->str() == "typename") {
start->deleteThis();
Token *temp = start;
while (Token::Match(temp, "%name% ::"))
temp = temp->tokAt(2);
if (Token::Match(temp, "template %name%"))
temp->deleteThis();
}
// Unfortunately we have to start searching from the beginning
// of the token stream because templates are instantiated at
// the end of the token stream and it may be used before then.

View File

@ -144,6 +144,7 @@ private:
TEST_CASE(template104); // #9021
TEST_CASE(template105); // #9076
TEST_CASE(template106);
TEST_CASE(template107); // #8663
TEST_CASE(template_specialization_1); // #7868 - template specialization template <typename T> struct S<C<T>> {..};
TEST_CASE(template_specialization_2); // #7868 - template specialization template <typename T> struct S<C<T>> {..};
TEST_CASE(template_enum); // #6299 Syntax error in complex enum declaration (including template)
@ -2420,6 +2421,34 @@ private:
ASSERT_EQUALS(exp, tok(code));
}
void template107() { // #8663
const char code[] = "template <class T1, class T2>\n"
"void f() {\n"
" using T3 = typename T1::template T3<T2>;\n"
" T3 t;\n"
"}\n"
"struct C3 {\n"
" template <typename T>\n"
" class T3\n"
" {};\n"
"};\n"
"void foo() {\n"
" f<C3, long>();\n"
"}";
const char exp[] = "void f<C3,long> ( ) ; "
"struct C3 { "
"class T3<long> ; "
"} ; "
"void foo ( ) { "
"f<C3,long> ( ) ; "
"} "
"void f<C3,long> ( ) { "
"C3 :: T3<long> t ; "
"} "
"class C3 :: T3<long> { } ;";
ASSERT_EQUALS(exp, tok(code));
}
void template_specialization_1() { // #7868 - template specialization template <typename T> struct S<C<T>> {..};
const char code[] = "template <typename T> struct C {};\n"
"template <typename T> struct S {a};\n"