From 246576fceb2c28ea4ca3b4e418e95382cf62e358 Mon Sep 17 00:00:00 2001 From: IOBYTE Date: Mon, 17 Jun 2019 15:18:27 -0400 Subject: [PATCH] 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. --- lib/templatesimplifier.cpp | 19 +++++++++++-- test/testsimplifytemplate.cpp | 50 +++++++++++++++++++++++++++-------- 2 files changed, 56 insertions(+), 13 deletions(-) diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index 0b33b0403..1c79eeda0 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -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() == ";") diff --git a/test/testsimplifytemplate.cpp b/test/testsimplifytemplate.cpp index ff81f2006..e7dce5942 100644 --- a/test/testsimplifytemplate.cpp +++ b/test/testsimplifytemplate.cpp @@ -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 struct S> {..}; TEST_CASE(template_specialization_2); // #7868 - template specialization template struct S> {..}; 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 \n" - "auto d() -> typename a::e {\n" - " d();\n" - "}"; - const char exp[] = "auto d ( ) . a < int > :: e ; " - "auto d ( ) . a < int > :: e { " - "d ( ) ; " - "}"; - ASSERT_EQUALS(exp, tok(code)); + { + const char code[] = "template \n" + "auto d() -> typename a::e {\n" + " d();\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 \n" + "auto d() -> typename a::e {\n" + " d();\n" + "}" + "void foo() { d(); }"; + const char exp[] = "auto d ( ) . a < char > :: e ; " + "auto d ( ) . a < int > :: e ; " + "void foo ( ) { d ( ) ; } " + "auto d ( ) . a < char > :: e { " + "d ( ) ; " + "} " + "auto d ( ) . a < int > :: e { " + "d ( ) ; " + "}"; + ASSERT_EQUALS(exp, tok(code)); + } } void template85() { // #8902 - crash @@ -2704,8 +2724,8 @@ private: "template using e = typename c{}, d>::f;\n"; const char exp[] = "template < typename a , a > struct b ; " "template < bool , typename > struct c ; " - "struct d ; " - "template < typename a > using e = typename c < std :: is_final < a > { } , d > :: f ; struct d : 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 auto b() -> decltype(a{}.template b);\n" + "template auto b() -> decltype(a{}.template b){}"; + 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 struct S> {..}; const char code[] = "template struct C {};\n" "template struct S {a};\n"