On Wed, 8 May 2024, Patrick Palka wrote:

> Bootstrapped and regtested on x86-64-pc-linux-gnu, does this look
> OK for trunk and perhaps 14?
> 
> -- >8 --
> 
> During maybe_aggr_guide with a nested class template and paren init,
> like with list init we need to consider the generic template type rather
> than the partially instantiated type since only the former has
> TYPE_FIELDS.  And in turn we need to partially substitute PARMs in the
> paren init case as well.  As a drive-by improvement it seems better to
> use outer_template_args instead of DECL_TI_ARGS during this partial
> substitution so that we lower instead of substitute the innermost
> generic template arguments, which is generally more robust.

... lower instead of substitute the innermost _template parameters_, rather

> 
> And during alias_ctad_tweaks with a nested class template, even though
> the guides may be already partially instantiated we still need to
> use the full set of arguments, not just the innermost, when substituting
> its constraints.
> 
>       PR c++/114974
>       PR c++/114901
>       PR c++/114903
> 
> gcc/cp/ChangeLog:
> 
>       * pt.cc (maybe_aggr_guide): Fix obtaining TYPE_FIELDS in
>       the paren init case.  Hoist out partial substitution logic
>       to apply to the paren init case as well.
>       (alias_ctad_tweaks): Substitute constraints using the full
>       set of template arguments.
> 
> gcc/testsuite/ChangeLog:
> 
>       * g++.dg/cpp2a/class-deduction-aggr14.C: New test.
>       * g++.dg/cpp2a/class-deduction-alias20.C: New test.
>       * g++.dg/cpp2a/class-deduction-alias21.C: New test.
> ---
>  gcc/cp/pt.cc                                  | 39 +++++++++++--------
>  .../g++.dg/cpp2a/class-deduction-aggr14.C     | 11 ++++++
>  .../g++.dg/cpp2a/class-deduction-alias20.C    | 22 +++++++++++
>  .../g++.dg/cpp2a/class-deduction-alias21.C    | 38 ++++++++++++++++++
>  4 files changed, 93 insertions(+), 17 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr14.C
>  create mode 100644 gcc/testsuite/g++.dg/cpp2a/class-deduction-alias20.C
>  create mode 100644 gcc/testsuite/g++.dg/cpp2a/class-deduction-alias21.C
> 
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index 1816bfd1f40..f3d52acaaac 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -30192,26 +30192,11 @@ maybe_aggr_guide (tree tmpl, tree init, 
> vec<tree,va_gc> *args)
>        if (init == error_mark_node)
>       return NULL_TREE;
>        parms = collect_ctor_idx_types (init, parms);
> -      /* If we're creating a deduction guide for a member class template,
> -      we've used the original template pattern type for the reshape_init
> -      above; this is done because we want PARMS to be a template parameter
> -      type, something that can be deduced when used as a function template
> -      parameter.  At this point the outer class template has already been
> -      partially instantiated (we deferred the deduction until the enclosing
> -      scope is non-dependent).  Therefore we have to partially instantiate
> -      PARMS, so that its template level is properly reduced and we don't get
> -      mismatches when deducing types using the guide with PARMS.  */
> -      if (member_template_p)
> -     {
> -       ++processing_template_decl;
> -       parms = tsubst (parms, DECL_TI_ARGS (tmpl), complain, init);
> -       --processing_template_decl;
> -     }
>      }
>    else if (TREE_CODE (init) == TREE_LIST)
>      {
>        int len = list_length (init);
> -      for (tree field = TYPE_FIELDS (type);
> +      for (tree field = TYPE_FIELDS (template_type);
>          len;
>          --len, field = DECL_CHAIN (field))
>       {
> @@ -30226,6 +30211,22 @@ maybe_aggr_guide (tree tmpl, tree init, 
> vec<tree,va_gc> *args)
>      /* Aggregate initialization doesn't apply to an initializer expression.  
> */
>      return NULL_TREE;
>  
> +  /* If we're creating a deduction guide for a member class template,
> +     we've used the original template pattern type for the reshape_init
> +     above; this is done because we want PARMS to be a template parameter
> +     type, something that can be deduced when used as a function template
> +     parameter.  At this point the outer class template has already been
> +     partially instantiated (we deferred the deduction until the enclosing
> +     scope is non-dependent).  Therefore we have to partially instantiate
> +     PARMS, so that its template level is properly reduced and we don't get
> +     mismatches when deducing types using the guide with PARMS.  */
> +  if (member_template_p)
> +    {
> +      ++processing_template_decl;
> +      parms = tsubst (parms, outer_template_args (tmpl), complain, init);
> +      --processing_template_decl;
> +    }
> +
>    if (parms)
>      {
>        tree last = parms;
> @@ -30417,7 +30418,11 @@ alias_ctad_tweaks (tree tmpl, tree uguides)
>         /* Substitute the associated constraints.  */
>         tree ci = get_constraints (f);
>         if (ci)
> -         ci = tsubst_constraint_info (ci, targs, complain, in_decl);
> +         {
> +           if (tree outer_targs = outer_template_args (f))
> +             ci = tsubst_constraint_info (ci, outer_targs, complain, 
> in_decl);
> +           ci = tsubst_constraint_info (ci, targs, complain, in_decl);
> +         }
>         if (ci == error_mark_node)
>           continue;
>  
> diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr14.C 
> b/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr14.C
> new file mode 100644
> index 00000000000..68786652502
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr14.C
> @@ -0,0 +1,11 @@
> +// PR c++/114974
> +// { dg-do compile { target c++20 } }
> +
> +template<typename T1>
> +struct A {
> +  template<typename T2>
> +  struct B { T2 t; };
> +};
> +
> +A<int>::B x{2}; // OK
> +A<int>::B y(2); // previously rejected
> diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias20.C 
> b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias20.C
> new file mode 100644
> index 00000000000..8cc56d91e37
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias20.C
> @@ -0,0 +1,22 @@
> +// PR c++/114901
> +// { dg-do compile { target c++20 } }
> +
> +template <class D>
> +constexpr bool C = sizeof(D);
> +
> +template <typename U>
> +struct T {
> +  template<typename V, typename N>
> +  struct Foo {
> +    Foo(V, N);
> +  };
> +
> +  template<typename X, typename N>
> +  requires (C<N>) // removes the require-clause will make the crash disappear
> +  Foo(X, N) -> Foo<X, N>;
> +
> +  template <typename Y, typename Y2, int N = sizeof(Y2)>
> +  using AFoo = Foo<decltype(N), Y2>;
> +};
> +
> +T<double>::AFoo s{1, 2}; // { dg-error "deduction|no match" }
> diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias21.C 
> b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias21.C
> new file mode 100644
> index 00000000000..c39a0f9f141
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias21.C
> @@ -0,0 +1,38 @@
> +// PR c++/114903
> +// { dg-do compile { target c++20 } }
> +
> +template <typename T>
> +struct Key {
> +  Key(int);
> +};
> +
> +class Forward {};
> +
> +template <typename T>
> +constexpr bool C = __is_same(T, Forward);
> +
> +template <typename Z>
> +struct Outer {
> +  template <typename U>
> +  struct Foo {
> +    Foo(U);
> +    U u;
> +  };
> +
> +  template <typename V>
> +    requires(C<Z>)
> +  Foo(V) -> Foo<int>;
> +};
> +
> +template <typename Y>
> +struct T {
> +  template <typename Y2>
> +  struct T2 {
> +    template <typename K>
> +    using AFoo = Outer<Y2>::template Foo<K>;
> +  };
> +};
> +
> +T<Forward>::T2<Forward>::AFoo a(1.0);
> +using type = decltype(a);
> +using type = Outer<Forward>::Foo<int>;
> -- 
> 2.45.0.31.gd4cc1ec35f
> 
> 

Reply via email to