Ping.

On Fri, Feb 12, 2021 at 06:12:12PM -0500, Marek Polacek via Gcc-patches wrote:
> We represent deduction guides with FUNCTION_DECLs, but they are built
> without DECL_CONTEXT, leading to an ICE in type_dependent_expression_p
> on the assert that the type of a function template with no dependent
> (innermost!) template arguments must be non-dependent.  Consider the
> attached class-deduction79.C: we create a deduction guide:
> 
>   template<class T> G(T)-> E<Z>::G<T>
> 
> we deduce T and create a partial instantiation:
> 
>   G(T) -> E<Z>::G<T> [with T = int]
> 
> And then do_class_deduction wants to create a CALL_EXPR from the above
> using build_new_function_call -> build_over_call which calls mark_used
> -> maybe_instantiate_noexcept -> type_dependent_expression_p.
> 
> There, the innermost template arguments are non-dependent (<int>), but
> the fntype is dependent -- the return type is a TYPENAME_TYPE, and
> since we have no DECL_CONTEXT, this check holds:
> 
>   /* Otherwise, if the function decl isn't from a dependent scope, it can't be
>      type-dependent.  Checking this is important for functions with auto 
> return
>      type, which looks like a dependent type.  */
>   if (TREE_CODE (expression) == FUNCTION_DECL
>       && !(DECL_CLASS_SCOPE_P (expression)
>            && dependent_type_p (DECL_CONTEXT (expression)))
> 
> whereupon we ICE.
> 
> Experiments with setting DECL_CONTEXT didn't pan out.  So perhaps we
> just want to skip the assert for deduction guides, because they are
> a little special.  Better ideas solicited.
> 
> Bootstrapped/regtested on x86_64-pc-linux-gnu.
> 
> gcc/cp/ChangeLog:
> 
>       PR c++/97034
>       PR c++/99009
>       * pt.c (type_dependent_expression_p): Don't assert that the type
>       of a deduction guide must non-dependent.
> 
> gcc/testsuite/ChangeLog:
> 
>       PR c++/97034
>       PR c++/99009
>       * g++.dg/cpp1z/class-deduction79.C: New test.
>       * g++.dg/cpp1z/class-deduction80.C: New test.
>       * g++.dg/cpp2a/class-deduction-aggr8.C: New test.
>       * g++.dg/cpp2a/class-deduction-aggr9.C: New test.
> ---
>  gcc/cp/pt.c                                   |  5 ++++-
>  .../g++.dg/cpp1z/class-deduction79.C          | 20 +++++++++++++++++++
>  .../g++.dg/cpp1z/class-deduction80.C          | 12 +++++++++++
>  .../g++.dg/cpp2a/class-deduction-aggr8.C      | 19 ++++++++++++++++++
>  .../g++.dg/cpp2a/class-deduction-aggr9.C      | 18 +++++++++++++++++
>  5 files changed, 73 insertions(+), 1 deletion(-)
>  create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction79.C
>  create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction80.C
>  create mode 100644 gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr8.C
>  create mode 100644 gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr9.C
> 
> diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
> index 60de8e93ff7..3e6f3407d40 100644
> --- a/gcc/cp/pt.c
> +++ b/gcc/cp/pt.c
> @@ -27282,7 +27282,10 @@ type_dependent_expression_p (tree expression)
>          && DECL_UNIQUE_FRIEND_P (expression)
>          && (!DECL_FRIEND_CONTEXT (expression)
>              || dependent_type_p (DECL_FRIEND_CONTEXT (expression))))
> -      && !DECL_LOCAL_DECL_P (expression))
> +      && !DECL_LOCAL_DECL_P (expression)
> +      /* We build deduction guides without any DECL_CONTEXT, but they can
> +      be type-dependent.  */
> +      && !deduction_guide_p (expression))
>      {
>        gcc_assert (!dependent_type_p (TREE_TYPE (expression))
>                 || undeduced_auto_decl (expression));
> diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction79.C 
> b/gcc/testsuite/g++.dg/cpp1z/class-deduction79.C
> new file mode 100644
> index 00000000000..86a68248157
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction79.C
> @@ -0,0 +1,20 @@
> +// PR c++/97034
> +// { dg-do compile { target c++17 } }
> +
> +template <typename Z>
> +struct E {
> +  template <typename T>
> +  struct G {
> +    T t;
> +    G(T) { }
> +  };
> +
> +  void fn() { G{1}; }
> +};
> +
> +void
> +g ()
> +{
> +  E<int> e;
> +  e.fn ();
> +}
> diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction80.C 
> b/gcc/testsuite/g++.dg/cpp1z/class-deduction80.C
> new file mode 100644
> index 00000000000..238024c508f
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction80.C
> @@ -0,0 +1,12 @@
> +// PR c++/99009
> +// { dg-do compile { target c++17 } }
> +
> +template<typename> struct B {
> +  B(int = A()) {}
> +  template <typename ...> struct A;
> +};
> +
> +template<typename T> struct X {
> +  template <T...> struct Y;
> +  X() { Y y; };
> +};
> diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr8.C 
> b/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr8.C
> new file mode 100644
> index 00000000000..399061100ae
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr8.C
> @@ -0,0 +1,19 @@
> +// PR c++/97034
> +// { dg-do compile { target c++20 } }
> +
> +namespace N {
> +template <typename, typename> struct S {
> +  template <typename T, typename U> S(T, U);
> +};
> +} // namespace N
> +template <int> struct E {
> +  template <typename T> struct G { T t; };
> +  void fn() { G{N::S<char, int>{'a', 1}}; }
> +};
> +
> +void
> +g ()
> +{
> +  E<1> e;
> +  e.fn ();
> +}
> diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr9.C 
> b/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr9.C
> new file mode 100644
> index 00000000000..245a04cd5f9
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-aggr9.C
> @@ -0,0 +1,18 @@
> +// PR c++/97034
> +// { dg-do compile { target c++20 } }
> +
> +template<typename>
> +struct E {
> +  template <typename T>
> +  struct G {
> +    T t;
> +  };
> +
> +  void fn() { G{1}; }
> +};
> +
> +void
> +g () {
> +  E<int> e;
> +  e.fn ();
> +}
> 
> base-commit: eb64b0b285b4fda9e8eeda4c2f370e636b1ab2ae
> -- 
> 2.29.2
> 

Marek

Reply via email to