a0cbaee
From 025129663032ab6a2c12e529a0a1a96aeca10db7 Mon Sep 17 00:00:00 2001
a0cbaee
From: Robert Reif <reif@FX6840>
a0cbaee
Date: Sun, 30 Jun 2019 18:00:28 -0400
a0cbaee
Subject: [PATCH] template simplifier: consistently handle templates with no
a0cbaee
 arguments
a0cbaee
a0cbaee
this fixes daca boost1.67 crashes
a0cbaee
---
a0cbaee
 lib/templatesimplifier.cpp    | 20 ++++++++++----------
a0cbaee
 test/testsimplifytemplate.cpp | 30 ++++++++++++++++++++++++++++++
a0cbaee
 2 files changed, 40 insertions(+), 10 deletions(-)
a0cbaee
a0cbaee
diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp
a0cbaee
index 4a121e642b..0e0423691f 100644
a0cbaee
--- a/lib/templatesimplifier.cpp
a0cbaee
+++ b/lib/templatesimplifier.cpp
a0cbaee
@@ -1048,7 +1048,7 @@ void TemplateSimplifier::useDefaultArgumentValues(TokenAndName &declaration)
a0cbaee
             continue;
a0cbaee
         }
a0cbaee
 
a0cbaee
-        if (tok->str() == "<" && templateParameters(tok))
a0cbaee
+        if (tok->str() == "<" && (tok->strAt(1) == ">" || templateParameters(tok)))
a0cbaee
             ++templateParmDepth;
a0cbaee
 
a0cbaee
         // end of template parameters?
a0cbaee
@@ -1101,7 +1101,7 @@ void TemplateSimplifier::useDefaultArgumentValues(TokenAndName &declaration)
a0cbaee
                     instantiationArgs[index].push_back(tok1);
a0cbaee
                     tok1 = tok1->next();
a0cbaee
                 } while (tok1 && tok1 != endLink);
a0cbaee
-            } else if (tok1->str() == "<") {
a0cbaee
+            } else if (tok1->str() == "<" && (tok1->strAt(1) == ">" || templateParameters(tok1))) {
a0cbaee
                 const Token *endLink = tok1->findClosingBracket();
a0cbaee
                 do {
a0cbaee
                     instantiationArgs[index].push_back(tok1);
a0cbaee
@@ -1134,7 +1134,7 @@ void TemplateSimplifier::useDefaultArgumentValues(TokenAndName &declaration)
a0cbaee
                 const Token *from = (*it)->next();
a0cbaee
                 std::stack<Token *> links;
a0cbaee
                 while (from && (!links.empty() || indentlevel || !Token::Match(from, ",|>"))) {
a0cbaee
-                    if (from->str() == "<")
a0cbaee
+                    if (from->str() == "<" && (from->strAt(1) == ">" || templateParameters(from)))
a0cbaee
                         ++indentlevel;
a0cbaee
                     else if (from->str() == ">")
a0cbaee
                         --indentlevel;
a0cbaee
@@ -1181,7 +1181,7 @@ void TemplateSimplifier::useDefaultArgumentValues(TokenAndName &declaration)
a0cbaee
             }
a0cbaee
             if (Token::Match(tok2, "(|{|["))
a0cbaee
                 tok2 = tok2->link();
a0cbaee
-            else if (Token::Match(tok2, "%type% <") && templateParameters(tok2->next())) {
a0cbaee
+            else if (Token::Match(tok2, "%type% <") && (tok2->strAt(2) == ">" || templateParameters(tok2->next()))) {
a0cbaee
                 std::list<TokenAndName>::iterator ti = std::find_if(mTemplateInstantiations.begin(),
a0cbaee
                                                        mTemplateInstantiations.end(),
a0cbaee
                                                        FindToken(tok2));
a0cbaee
@@ -1346,7 +1346,7 @@ bool TemplateSimplifier::instantiateMatch(const Token *instance, const std::size
a0cbaee
         const Token *tok = instance;
a0cbaee
         unsigned int indentlevel = 0;
a0cbaee
         for (tok = instance; tok && (tok->str() != ">" || indentlevel > 0); tok = tok->next()) {
a0cbaee
-            if (Token::Match(tok, "<|,|(|:: %name% <") && templateParameters(tok->tokAt(2)) > 0)
a0cbaee
+            if (Token::Match(tok, "<|,|(|:: %name% <") && (tok->strAt(3) == ">" || templateParameters(tok->tokAt(2))))
a0cbaee
                 ++indentlevel;
a0cbaee
             if (indentlevel > 0 && tok->str() == ">")
a0cbaee
                 --indentlevel;
a0cbaee
@@ -1637,7 +1637,7 @@ void TemplateSimplifier::expandTemplate(
a0cbaee
                         typetok = typetok->tokAt(2);
a0cbaee
                         continue;
a0cbaee
                     }
a0cbaee
-                    if (Token::Match(typetok, "%name% <") && templateParameters(typetok->next()) > 0)
a0cbaee
+                    if (Token::Match(typetok, "%name% <") && (typetok->strAt(2) == ">" || templateParameters(typetok->next())))
a0cbaee
                         ++typeindentlevel;
a0cbaee
                     else if (typeindentlevel > 0 && typetok->str() == ">")
a0cbaee
                         --typeindentlevel;
a0cbaee
@@ -1859,7 +1859,7 @@ void TemplateSimplifier::expandTemplate(
a0cbaee
                                 if (Token::simpleMatch(typetok, ". . .")) {
a0cbaee
                                     typetok = typetok->tokAt(2);
a0cbaee
                                 } else {
a0cbaee
-                                    if (Token::Match(typetok, "%name% <") && templateParameters(typetok->next()) > 0)
a0cbaee
+                                    if (Token::Match(typetok, "%name% <") && (typetok->strAt(2) == ">" || templateParameters(typetok->next())))
a0cbaee
                                         ++typeindentlevel;
a0cbaee
                                     else if (typeindentlevel > 0 && typetok->str() == ">")
a0cbaee
                                         --typeindentlevel;
a0cbaee
@@ -1939,7 +1939,7 @@ void TemplateSimplifier::expandTemplate(
a0cbaee
                             typetok = typetok->tokAt(2);
a0cbaee
                             continue;
a0cbaee
                         }
a0cbaee
-                        if (Token::Match(typetok, "%name% <") && templateParameters(typetok->next()) > 0)
a0cbaee
+                        if (Token::Match(typetok, "%name% <") && (typetok->strAt(2) == ">" || templateParameters(typetok->next())))
a0cbaee
                             ++typeindentlevel;
a0cbaee
                         else if (typeindentlevel > 0 && typetok->str() == ">")
a0cbaee
                             --typeindentlevel;
a0cbaee
@@ -2710,7 +2710,7 @@ std::string TemplateSimplifier::getNewName(
a0cbaee
             typeForNewName.clear();
a0cbaee
             break;
a0cbaee
         }
a0cbaee
-        if (Token::Match(tok3->tokAt(-2), "<|,|:: %name% <") && templateParameters(tok3) > 0)
a0cbaee
+        if (Token::Match(tok3->tokAt(-2), "<|,|:: %name% <") && (tok3->strAt(1) == ">" || templateParameters(tok3)))
a0cbaee
             ++indentlevel;
a0cbaee
         else if (indentlevel > 0 && Token::Match(tok3, "> [,>]"))
a0cbaee
             --indentlevel;
a0cbaee
@@ -2975,7 +2975,7 @@ void TemplateSimplifier::replaceTemplateUsage(
a0cbaee
         const Token *typetok = (!mTypesUsedInTemplateInstantiation.empty()) ? mTypesUsedInTemplateInstantiation[0].token : nullptr;
a0cbaee
         unsigned int indentlevel2 = 0;  // indentlevel for tokgt
a0cbaee
         while (tok2 != endToken && (indentlevel2 > 0 || tok2->str() != ">")) {
a0cbaee
-            if (tok2->str() == "<" && templateParameters(tok2) > 0)
a0cbaee
+            if (tok2->str() == "<" && (tok2->strAt(1) == ">" || templateParameters(tok2)))
a0cbaee
                 ++indentlevel2;
a0cbaee
             else if (indentlevel2 > 0 && Token::Match(tok2, "> [,>]"))
a0cbaee
                 --indentlevel2;
a0cbaee
diff --git a/test/testsimplifytemplate.cpp b/test/testsimplifytemplate.cpp
a0cbaee
index c1b3214e2d..bcfcebd03c 100644
a0cbaee
--- a/test/testsimplifytemplate.cpp
a0cbaee
+++ b/test/testsimplifytemplate.cpp
a0cbaee
@@ -157,6 +157,7 @@ class TestSimplifyTemplate : public TestFixture {
a0cbaee
         TEST_CASE(template117);
a0cbaee
         TEST_CASE(template118);
a0cbaee
         TEST_CASE(template119); // #9186
a0cbaee
+        TEST_CASE(template120);
a0cbaee
         TEST_CASE(template_specialization_1);  // #7868 - template specialization template <typename T> struct S<C<T>> {..};
a0cbaee
         TEST_CASE(template_specialization_2);  // #7868 - template specialization template <typename T> struct S<C<T>> {..};
a0cbaee
         TEST_CASE(template_enum);  // #6299 Syntax error in complex enum declaration (including template)
a0cbaee
@@ -2819,6 +2820,35 @@ class TestSimplifyTemplate : public TestFixture {
a0cbaee
         }
a0cbaee
     }
a0cbaee
 
a0cbaee
+    void template120() {
a0cbaee
+        const char code[] = "template<typename Tuple>\n"
a0cbaee
+                            "struct lambda_context {\n"
a0cbaee
+                            "    template<typename Sig> struct result;\n"
a0cbaee
+                            "    template<typename This, typename I>\n"
a0cbaee
+                            "    struct result<This(terminal, placeholder)> : at<Tuple, I> {};\n"
a0cbaee
+                            "};\n"
a0cbaee
+                            "template<typename T>\n"
a0cbaee
+                            "struct lambda {\n"
a0cbaee
+                            "    template<typename Sig> struct result;\n"
a0cbaee
+                            "    template<typename This>\n"
a0cbaee
+                            "    struct result<This()> : lambda_context<tuple<> > {};\n"
a0cbaee
+                            "};\n"
a0cbaee
+                            "lambda<int> l;";
a0cbaee
+        const char exp[] = "template < typename Tuple > "
a0cbaee
+                           "struct lambda_context { "
a0cbaee
+                           "template < typename Sig > struct result ; "
a0cbaee
+                           "template < typename This , typename I > "
a0cbaee
+                           "struct result < This ( terminal , placeholder ) > : at < Tuple , I > { } ; "
a0cbaee
+                           "} ; "
a0cbaee
+                           "struct lambda<int> ; "
a0cbaee
+                           "lambda<int> l ; struct lambda<int> { "
a0cbaee
+                           "template < typename Sig > struct result ; "
a0cbaee
+                           "template < typename This > "
a0cbaee
+                           "struct result < This ( ) > : lambda_context < tuple < > > { } ; "
a0cbaee
+                           "} ;";
a0cbaee
+        ASSERT_EQUALS(exp, tok(code));
a0cbaee
+    }
a0cbaee
+
a0cbaee
     void template_specialization_1() {  // #7868 - template specialization template <typename T> struct S<C<T>> {..};
a0cbaee
         const char code[] = "template <typename T> struct C {};\n"
a0cbaee
                             "template <typename T> struct S {a};\n"