[PATCH] c++: CTAD within alias template [PR91911]

Jason Merrill jason@redhat.com
Fri Jun 25 15:42:47 GMT 2021


On 6/24/21 4:45 PM, Patrick Palka wrote:
> In the first testcase below, during parsing of the alias template
> ConstSpanType, transparency of alias template specializations means we
> replace SpanType<T> with SpanType's substituted definition.  But this
> substitution lowers the level of the CTAD placeholder for span(T()) from
> 2 to 1, and so the later instantiantion of ConstSpanType<int>
> erroneously substitutes this CTAD placeholder with the template argument
> at level 1 index 0, i.e. with int, before we get a chance to perform the
> CTAD.
> 
> In light of this, it seems we should avoid level lowering when
> substituting through through the type-id of a dependent alias template
> specialization.  To that end this patch makes lookup_template_class_1
> pass tf_partial to tsubst in this situation.

This makes sense, but what happens if SpanType is a member template, so 
that the levels of it and ConstSpanType don't match?  Or the other way 
around?

> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
> trunk?
> 
> 	PR c++/91911
> 
> gcc/cp/ChangeLog:
> 
> 	* pt.c (lookup_template_class_1): When looking up a dependent
> 	alias template specialization, pass tf_partial to tsubst.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/cpp1z/class-deduction92.C: New test.
> ---
>   gcc/cp/pt.c                                   |  7 +++++-
>   .../g++.dg/cpp1z/class-deduction92.C          | 17 +++++++++++++
>   .../g++.dg/cpp1z/class-deduction93.C          | 25 +++++++++++++++++++
>   3 files changed, 48 insertions(+), 1 deletion(-)
>   create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction92.C
>   create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction93.C
> 
> diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
> index f73c7471a33..23c5f515716 100644
> --- a/gcc/cp/pt.c
> +++ b/gcc/cp/pt.c
> @@ -9954,7 +9954,12 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
>   		template-arguments for the template-parameters in the
>   		type-id of the alias template.  */
>   
> -	  t = tsubst (TREE_TYPE (gen_tmpl), arglist, complain, in_decl);
> +	  /* When substituting a dependent alias template specialization,
> +	     we pass tf_partial to avoid lowering the level of any 'auto'
> +	     in its type-id which might correspond to CTAD placeholders.  */
> +	  t = tsubst (TREE_TYPE (gen_tmpl), arglist,
> +		      complain | (is_dependent_type * tf_partial),
> +		      in_decl);
>   	  /* Note that the call above (by indirectly calling
>   	     register_specialization in tsubst_decl) registers the
>   	     TYPE_DECL representing the specialization of the alias
> diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction92.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction92.C
> new file mode 100644
> index 00000000000..ae3c55508b2
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction92.C
> @@ -0,0 +1,17 @@
> +// PR c++/91911
> +// { dg-do compile { target c++17 } }
> +
> +template<class T>
> +struct span {
> +  using value_type = T;
> +  span(T);
> +};
> +
> +template<class T>
> +using SpanType = decltype(span(T()));
> +
> +template<class T>
> +using ConstSpanType = span<const typename SpanType<T>::value_type>;
> +
> +using type = ConstSpanType<int>;
> +using type = span<const int>;
> diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction93.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction93.C
> new file mode 100644
> index 00000000000..eebc986832e
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction93.C
> @@ -0,0 +1,25 @@
> +// PR c++/98077
> +// { dg-do compile { target c++17 } }
> +
> +template<class R>
> +struct function {
> +  template<class T> function(T) { }
> +  using type = R;
> +};
> +
> +template<class T> function(T) -> function<decltype(T()())>;
> +
> +template<class T>
> +struct CallableTrait;
> +
> +template<class R>
> +struct CallableTrait<function<R>> { using ReturnType = R; };
> +
> +template<class F>
> +using CallableTraitT = decltype(function{F()});
> +
> +template<class F>
> +using ReturnType = typename CallableTraitT<F>::type;
> +
> +using type = ReturnType<int(*)()>;
> +using type = int;
> 



More information about the Gcc-patches mailing list