c++: Template template parameter in constraint [PR95371]
authorJason Merrill <jason@redhat.com>
Fri, 29 May 2020 20:55:52 +0000 (16:55 -0400)
committerJason Merrill <jason@redhat.com>
Fri, 29 May 2020 22:16:54 +0000 (18:16 -0400)
any_template_parm_r was assuming that the DECL_TEMPLATE_RESULT of a template
will have a suitable TEMPLATE_INFO from which we can look at the generic
arguments for that template.  But that wasn't true for a template template
parameter; this patch makes it so.

gcc/cp/ChangeLog:

PR c++/95371
* pt.c (process_template_parm): Set DECL_TEMPLATE_INFO
on the DECL_TEMPLATE_RESULT.

gcc/testsuite/ChangeLog:

PR c++/95371
* g++.dg/cpp2a/concepts-ttp1.C: New test.

gcc/cp/pt.c
gcc/testsuite/g++.dg/cpp2a/concepts-ttp1.C [new file with mode: 0644]

index 90dafff3aa700ab29d8467e0e9175e49ca2b6ac9..df647af7b463bd12a7578d036f34f7d787822f8f 100644 (file)
@@ -4575,7 +4575,16 @@ process_template_parm (tree list, location_t parm_loc, tree parm,
          /* This is for distinguishing between real templates and template
             template parameters */
          TREE_TYPE (parm) = t;
-         TREE_TYPE (DECL_TEMPLATE_RESULT (parm)) = t;
+
+         /* any_template_parm_r expects to be able to get the targs of a
+            DECL_TEMPLATE_RESULT.  */
+         tree result = DECL_TEMPLATE_RESULT (parm);
+         TREE_TYPE (result) = t;
+         tree args = template_parms_to_args (DECL_TEMPLATE_PARMS (parm));
+         tree tinfo = build_template_info (parm, args);
+         retrofit_lang_decl (result);
+         DECL_TEMPLATE_INFO (result) = tinfo;
+
          decl = parm;
        }
       else
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-ttp1.C b/gcc/testsuite/g++.dg/cpp2a/concepts-ttp1.C
new file mode 100644 (file)
index 0000000..3f6eb35
--- /dev/null
@@ -0,0 +1,16 @@
+// PR c++/95371
+// { dg-do compile { target c++20 } }
+
+template <typename...>
+struct configuration  {
+    template <template <typename...> typename query_t>
+    static constexpr bool exists() { return true; }
+
+    template <template <typename...> typename query_t>
+    void remove() requires(exists<query_t>());
+};
+
+int main() {
+    configuration<> cfg{};
+    cfg.remove<configuration>();
+}