On Mon, 11 Jan 2021, Jason Merrill wrote:

> On 1/9/21 5:23 PM, Patrick Palka wrote:
> > This patch teaches find_template_parameters to visit the template
> > represented by a CTAD placeholder, which is normally not visited by
> > for_each_template_parm.  This 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 record the template parameters
> > used therein for later satisfaction.
> > 
> > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
> > trunk and perhaps the 10 branch?  Also tested on range-v3 and cmcstl2.
> > 
> > gcc/cp/ChangeLog:
> > 
> >     PR c++/98611
> >     * pt.c (any_template_parm_r) <case TEMPLATE_TYPE_PARM>: Visit
> >     the template of a CTAD placeholder.
> 
> Did you consider doing this in cp_walk_subtrees instead of here?

Briefly, but I couldn't convince myself which of the three visitors
(cp_walk_subtrees, for_each_template_parm_r or any_template_parm_r) is
the most appropriate place to do it in, so I defaulted to the most
specific routine of the three.

The following passes bootstrap and regtesting on x86_64-pc-linux-gnu.
Shall we go with this?

-- >8 --

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                               |  5 ++++-
 gcc/testsuite/g++.dg/cpp2a/concepts-ctad1.C | 16 ++++++++++++++++
 gcc/testsuite/g++.dg/cpp2a/concepts-ctad2.C | 13 +++++++++++++
 3 files changed, 33 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-ctad1.C
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-ctad2.C

diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index c536eb581a7..d339036e88e 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -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
index 00000000000..ec2e4b014d7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-ctad1.C
@@ -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
index 00000000000..0d7f9790777
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-ctad2.C
@@ -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);
-- 
2.30.0

Reply via email to