c++: Fix ICE with CTAD in concept [PR98611]
authorPatrick Palka <ppalka@redhat.com>
Tue, 12 Jan 2021 14:34:41 +0000 (09:34 -0500)
committerPatrick Palka <ppalka@redhat.com>
Tue, 12 Jan 2021 14:34:41 +0000 (09:34 -0500)
This patch teaches cp_walk_subtrees to visit the template represented
by a CTAD placeholder, which would otherwise be not visited during
find_template_parameters.  The template may be a template template
parameter (as in the first testcase), or it may implicitly use the
template parameters of an enclosing class template (as in the second
testcase), and in either case we need to visit this tree to record the
template parameters used therein for later satisfaction.

gcc/cp/ChangeLog:

PR c++/98611
* tree.c (cp_walk_subtrees) <case TEMPLATE_TYPE_PARM>: Visit
the template of a CTAD placeholder.

gcc/testsuite/ChangeLog:

PR c++/98611
* g++.dg/cpp2a/concepts-ctad1.C: New test.
* g++.dg/cpp2a/concepts-ctad2.C: New test.

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

index c536eb581a768fab25272b14450e999f7cec87a1..d339036e88e766db81b6cc5f419c5b5e83cc6be2 100644 (file)
@@ -5173,12 +5173,15 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func,
   result = NULL_TREE;
   switch (code)
     {
+    case TEMPLATE_TYPE_PARM:
+      if (template_placeholder_p (*tp))
+       WALK_SUBTREE (CLASS_PLACEHOLDER_TEMPLATE (*tp));
+      /* Fall through.  */
     case DEFERRED_PARSE:
     case TEMPLATE_TEMPLATE_PARM:
     case BOUND_TEMPLATE_TEMPLATE_PARM:
     case UNBOUND_CLASS_TEMPLATE:
     case TEMPLATE_PARM_INDEX:
-    case TEMPLATE_TYPE_PARM:
     case TYPEOF_TYPE:
     case UNDERLYING_TYPE:
       /* None of these have subtrees other than those already walked
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-ctad1.C b/gcc/testsuite/g++.dg/cpp2a/concepts-ctad1.C
new file mode 100644 (file)
index 0000000..ec2e4b0
--- /dev/null
@@ -0,0 +1,16 @@
+// PR c++/98611
+// { dg-do compile { target c++20 } }
+
+template <class T, class U>
+concept IsSame = __is_same(T, U);
+
+template <class T, template <class...> class _Class>
+concept IsInstantiationOf = requires(T object) {
+ { _Class{object} } -> IsSame<T>;
+};
+
+template <class T> struct Degrees {};
+static_assert(IsInstantiationOf<Degrees<int>, Degrees>);
+
+template <class T> struct NotDegrees {};
+static_assert(!IsInstantiationOf<Degrees<int>, NotDegrees>);
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-ctad2.C b/gcc/testsuite/g++.dg/cpp2a/concepts-ctad2.C
new file mode 100644 (file)
index 0000000..0d7f979
--- /dev/null
@@ -0,0 +1,13 @@
+// PR c++/98611
+// { dg-do compile { target c++20 } }
+
+template <class>
+struct S {
+  template <class T> struct Tmpl { Tmpl(T); };
+
+  template <class T>
+    requires requires (T object) { Tmpl{object}; }
+  static int f(T);
+};
+
+int a = S<int>::f(0);