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