[PATCH] c++: non-constant non-dependent decltype folding [PR104823]

Jason Merrill jason@redhat.com
Mon Mar 7 19:09:34 GMT 2022


On 3/7/22 14:41, Patrick Palka wrote:
> instantiate_non_dependent_expr_sfinae instantiates only potentially
> constant expressions

Hmm, that now strikes me as a problematic interface, as we don't know 
whether what we get back is template or non-template trees.

Maybe we want to change instantiate_non_dependent_expr to 
checking_assert that the argument is non-dependent (callers are already 
checking that), and drop the potentially-constant test?

> but when processing a non-dependent decltype
> operand we want to instantiate it even if it's non-constant since
> such non-dependent decltype is always resolved ahead of time.
> 
> Currently finish_decltype_type uses the former function, which causes us
> to miss issuing a narrowing diagnostic for S{id(v)} in the below testcase
> because we never instantiate this non-constant non-dependent decltype
> operand.
> 
> So this patch makes finish_decltype_type use i_n_d_e_internal instead of
> _sfinae.  And afterward, we need to keep processing_template_decl cleared
> for sake of the later call to lvalue_kind, which handles templated and
> non-templated COND_EXPR differently.  Otherwise we'd incorrectly reject
> the declaration of g in cpp0x/cond2.C with:
> 
>    error: ‘g’ declared as function returning a function
> 
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
> trunk?
> 
> 	PR c++/104823
> 
> gcc/cp/ChangeLog:
> 
> 	* semantics.cc (finish_decltype_type): Use i_n_d_e_internal
> 	instead of _sfinae when instantiating a non-dependent decltype
> 	operand, and keep processing_template_decl cleared afterward.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/cpp0x/Wnarrowing19.C: New test.
> ---
>   gcc/cp/semantics.cc                       | 11 ++++++++++-
>   gcc/testsuite/g++.dg/cpp0x/Wnarrowing19.C |  8 ++++++++
>   2 files changed, 18 insertions(+), 1 deletion(-)
>   create mode 100644 gcc/testsuite/g++.dg/cpp0x/Wnarrowing19.C
> 
> diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
> index 07cae993efe..66d90c2f7be 100644
> --- a/gcc/cp/semantics.cc
> +++ b/gcc/cp/semantics.cc
> @@ -11217,6 +11217,8 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
>     /* decltype is an unevaluated context.  */
>     cp_unevaluated u;
>   
> +  processing_template_decl_sentinel ptds (/*reset=*/false);
> +
>     /* Depending on the resolution of DR 1172, we may later need to distinguish
>        instantiation-dependent but not type-dependent expressions so that, say,
>        A<decltype(sizeof(T))>::U doesn't require 'typename'.  */
> @@ -11232,7 +11234,14 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
>       }
>     else if (processing_template_decl)
>       {
> -      expr = instantiate_non_dependent_expr_sfinae (expr, complain);
> +      /* Instantiate the non-dependent operand to diagnose any ill-formed
> +	 expressions.  And keep processing_template_decl cleared for the rest
> +	 of the function (for sake of the call to lvalue_kind below, which
> +	 handles templated and non-templated COND_EXPR differently).  */
> +      processing_template_decl = 0;
> +      /* Since we want to do this even for non-constant expressions, we
> +	 use i_n_d_e_internal here instead of _sfinae.  */
> +      expr = instantiate_non_dependent_expr_internal (expr, complain);
>         if (expr == error_mark_node)
>   	return error_mark_node;
>       }
> diff --git a/gcc/testsuite/g++.dg/cpp0x/Wnarrowing19.C b/gcc/testsuite/g++.dg/cpp0x/Wnarrowing19.C
> new file mode 100644
> index 00000000000..bd9fd2eb6f9
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp0x/Wnarrowing19.C
> @@ -0,0 +1,8 @@
> +// PR c++/104823
> +// { dg-do compile { target c++11 } }
> +
> +struct S { S(int); };
> +
> +double id(double v);
> +
> +template<class> auto f(double v) -> decltype(S{id(v)}); // { dg-error "narrowing" }



More information about the Gcc-patches mailing list