On Mon, 12 Apr 2021, Patrick Palka wrote:

> Here we're crashing during deduction for a template placeholder from a
> dependent initializer because one of the initializer's elements has an
> empty TREE_TYPE, something which resolve_args and later unify_one_argument
> don't expect.  And if the deduction from a dependent initializer
> otherwise fails, we prematurely issue an error rather than reattempting
> the deduction at instantiation time.
> 
> This patch makes do_class_deduction more tolerant about dependent
> initializers, in a manner similar to what do_auto_deduction does: if
> deduction from a dependent initializer fails, just return the original
> placeholder unchanged.
> 
> Bootstrapped and regtested on x86_64-pc-linux-gnu, and also tested on
> cmcstl2 and range-v3, and on all the testcases in PR93383, does this
> look OK for trunk?

Ping.  This patch apparently also fixes the ICE reported in PR95291 and
its related/duplicate PRs.

> 
> gcc/cp/ChangeLog:
> 
>       PR c++/89565
>       PR c++/93383
>       PR c++/99200
>       * pt.c (do_class_deduction): If an argument has no type, don't
>       attempt deduction.  If deduction fails and the initializer is
>       type-dependent, try again at instantiation time.
> 
> gcc/testsuite/ChangeLog:
> 
>       PR c++/89565
>       PR c++/93383
>       PR c++/99200
>       * g++.dg/cpp2a/nontype-class39.C: Remove dg-ice.
>       * g++.dg/cpp2a/nontype-class44.C: New test.
>       * g++.dg/cpp2a/nontype-class45.C: New test.
> ---
>  gcc/cp/pt.c                                  | 11 +++++++
>  gcc/testsuite/g++.dg/cpp2a/nontype-class39.C |  1 -
>  gcc/testsuite/g++.dg/cpp2a/nontype-class44.C | 11 +++++++
>  gcc/testsuite/g++.dg/cpp2a/nontype-class45.C | 32 ++++++++++++++++++++
>  4 files changed, 54 insertions(+), 1 deletion(-)
>  create mode 100644 gcc/testsuite/g++.dg/cpp2a/nontype-class44.C
>  create mode 100644 gcc/testsuite/g++.dg/cpp2a/nontype-class45.C
> 
> diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
> index 0ce7fa359c1..612feac7976 100644
> --- a/gcc/cp/pt.c
> +++ b/gcc/cp/pt.c
> @@ -29334,6 +29334,13 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
>    else
>      args = make_tree_vector_single (init);
>  
> +  /* If an argument is missing its type, we can't possibly deduce from this
> +     (type-dependent) initializer ahead of time.  */
> +  if (processing_template_decl)
> +    for (tree arg : *args)
> +      if (!TREE_TYPE (arg))
> +     return ptype;
> +
>    /* Do this now to avoid problems with erroneous args later on.  */
>    args = resolve_args (args, complain);
>    if (args == NULL)
> @@ -29419,6 +29426,10 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
>  
>    if (call == error_mark_node)
>      {
> +      if (type_dependent_expression_p (init))
> +     /* Try again at instantiation time.  */
> +     return ptype;
> +
>        if (complain & tf_warning_or_error)
>       {
>         error ("class template argument deduction failed:");
> diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class39.C 
> b/gcc/testsuite/g++.dg/cpp2a/nontype-class39.C
> index f5f79a71ec2..9b4da4f02ea 100644
> --- a/gcc/testsuite/g++.dg/cpp2a/nontype-class39.C
> +++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class39.C
> @@ -1,6 +1,5 @@
>  // PR c++/89565
>  // { dg-do compile { target c++20 } }
> -// { dg-ice "resolve_args" }
>  
>  template <auto>
>  struct N{};
> diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class44.C 
> b/gcc/testsuite/g++.dg/cpp2a/nontype-class44.C
> new file mode 100644
> index 00000000000..d91e800424f
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class44.C
> @@ -0,0 +1,11 @@
> +// PR c++/93383
> +// { dg-do compile { target c++20 } }
> +
> +template <int> struct A {};
> +
> +template <A a> struct B {
> +  void foo(B<+a>);
> +  void bar(B<a.x>);
> +  template <class T> using type = B<T{}>;
> +  template <class> static inline auto y = A{0}; // { dg-error "deduction|no 
> match" }
> +};
> diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class45.C 
> b/gcc/testsuite/g++.dg/cpp2a/nontype-class45.C
> new file mode 100644
> index 00000000000..e7addf5f291
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class45.C
> @@ -0,0 +1,32 @@
> +// PR c++/99200
> +// { dg-do compile { target c++20 } }
> +
> +template <int N>
> +struct A
> +{
> +  constexpr A (const char (&s)[N]) { for (int i = 0; i < N; i++) v[i] = 
> s[i]; v[N] = 0; }
> +  char v[N + 1];
> +};
> +
> +template <A s>
> +struct B
> +{
> +  constexpr operator const char *() { return s.v; }
> +};
> +
> +template <typename T>
> +const char *
> +foo ()
> +{ 
> +  return B<__PRETTY_FUNCTION__>{};
> +}
> +
> +template <typename T>
> +const char *
> +bar ()
> +{ 
> +  return B<__FUNCTION__>{};
> +}
> +
> +auto a = foo <int> ();
> +auto b = bar <double> ();
> -- 
> 2.31.1.272.g89b43f80a5
> 
> 

Reply via email to