Fixed #9178 (Assertion `brackets1.empty() == false' failed on valid C++ code) (#1905)

This fixes a nasty intrinsics related bug causing instantiations that
shouldn't happen.
This commit is contained in:
IOBYTE 2019-06-17 15:18:27 -04:00 committed by Daniel Marjamäki
parent e979b0652c
commit 246576fceb
2 changed files with 56 additions and 13 deletions

View File

@ -109,7 +109,14 @@ TemplateSimplifier::TokenAndName::TokenAndName(Token *tok, const std::string &s,
else if (!isAlias()) {
if (isFunction())
tok1 = tok1->link()->next();
tok1 = Token::findmatch(tok1, "{|;");
while (tok1 && !Token::Match(tok1, ";|{")) {
if (tok1->str() == "<")
tok1 = tok1->findClosingBracket();
else if (Token::Match(tok1, "(|[") && tok1->link())
tok1 = tok1->link();
if (tok1)
tok1 = tok1->next();
}
if (tok1)
isForwardDeclaration(tok1->str() == ";");
}
@ -771,7 +778,15 @@ void TemplateSimplifier::getTemplateInstantiations()
// #7914
// Ignore template instantiations within template definitions: they will only be
// handled if the definition is actually instantiated
Token *tok2 = Token::findmatch(tok, "{|;");
Token * tok2 = tok->next();
while (tok2 && !Token::Match(tok2, ";|{")) {
if (tok2->str() == "<")
tok2 = tok2->findClosingBracket();
else if (Token::Match(tok2, "(|[") && tok2->link())
tok2 = tok2->link();
if (tok2)
tok2 = tok2->next();
}
if (tok2 && tok2->str() == "{")
tok = tok2->link();
else if (tok2 && tok2->str() == ";")

View File

@ -153,6 +153,7 @@ private:
TEST_CASE(template113);
TEST_CASE(template114); // #9155
TEST_CASE(template115); // #9153
TEST_CASE(template116); // #9178
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)
@ -1845,15 +1846,34 @@ private:
}
void template84() { // #8880
const char code[] = "template <class b, int c, class>\n"
"auto d() -> typename a<decltype(b{})>::e {\n"
" d<int, c, int>();\n"
"}";
const char exp[] = "auto d<int,c,int> ( ) . a < int > :: e ; "
"auto d<int,c,int> ( ) . a < int > :: e { "
"d<int,c,int> ( ) ; "
"}";
ASSERT_EQUALS(exp, tok(code));
{
const char code[] = "template <class b, int c, class>\n"
"auto d() -> typename a<decltype(b{})>::e {\n"
" d<int, c, int>();\n"
"}";
const char exp[] = "template < class b , int c , class > "
"auto d ( ) . a < decltype ( b { } ) > :: e { "
"d < int , c , int > ( ) ; "
"}";
ASSERT_EQUALS(exp, tok(code));
}
{
const char code[] = "template <class b, int c, class>\n"
"auto d() -> typename a<decltype(b{})>::e {\n"
" d<int, c, int>();\n"
"}"
"void foo() { d<char, 1, int>(); }";
const char exp[] = "auto d<char,1,int> ( ) . a < char > :: e ; "
"auto d<int,1,int> ( ) . a < int > :: e ; "
"void foo ( ) { d<char,1,int> ( ) ; } "
"auto d<char,1,int> ( ) . a < char > :: e { "
"d<int,1,int> ( ) ; "
"} "
"auto d<int,1,int> ( ) . a < int > :: e { "
"d<int,1,int> ( ) ; "
"}";
ASSERT_EQUALS(exp, tok(code));
}
}
void template85() { // #8902 - crash
@ -2704,8 +2724,8 @@ private:
"template <typename a> using e = typename c<std::is_final<a>{}, d<a>>::f;\n";
const char exp[] = "template < typename a , a > struct b ; "
"template < bool , typename > struct c ; "
"struct d<a> ; "
"template < typename a > using e = typename c < std :: is_final < a > { } , d<a> > :: f ; struct d<a> : b < bool , std :: is_empty < a > { } > { } ;";
"template < typename a > struct d : b < bool , std :: is_empty < a > { } > { } ; "
"template < typename a > using e = typename c < std :: is_final < a > { } , d < a > > :: f ;";
ASSERT_EQUALS(exp, tok(code));
}
}
@ -2735,6 +2755,14 @@ private:
ASSERT_EQUALS(exp, tok(code));
}
void template116() { // #9178
const char code[] = "template <class, class a> auto b() -> decltype(a{}.template b<void(int, int)>);\n"
"template <class, class a> auto b() -> decltype(a{}.template b<void(int, int)>){}";
const char exp[] = "template < class , class a > auto b ( ) . decltype ( a { } . template b < void ( int , int ) > ) ; "
"template < class , class a > auto b ( ) . decltype ( a { } . template b < void ( int , int ) > ) { }";
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"