On Mon, 7 Mar 2022, Jason Merrill wrote: > 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? That sounds like a nice improvement. But it happens to break template<int N> using type = decltype(N); beause finish_decltype_type checks instantiation_dependent_uneval_expression_p (which is false here) instead of instantiation_dependent_expression_p (which is true here) before calling instantiate_non_dependent_expr, so we end up tripping over the proposed checking_assert (which checks the latter stronger form of dependence). I suspect other callers of instantiate_non_dependent_expr might have a similar problem if they use a weaker dependence check than instantiation_dependent_expression_p, e.g. build_noexcept_spec only checks value_dependent_expression_p. I wonder if we should relax the proposed checking_assert in i_n_d_e, or strengthen the dependence checks performed by its callers, or something else? Here's the diff I'm working with: -- >8 -- gcc/cp/parser.cc | 2 +- gcc/cp/pt.cc | 21 ++++++--------------- gcc/cp/semantics.cc | 11 ++++------- 3 files changed, 11 insertions(+), 23 deletions(-) diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 20aab5eb6b1..a570a9163b9 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -7986,7 +7986,7 @@ cp_parser_parenthesized_expression_list_elt (cp_parser *parser, bool cast_p, expr = cp_parser_assignment_expression (parser, /*pidk=*/NULL, cast_p); if (fold_expr_p) - expr = instantiate_non_dependent_expr (expr); + expr = fold_non_dependent_expr (expr); /* If we have an ellipsis, then this is an expression expansion. */ if (allow_expansion_p diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 53a74636279..1b2d9a7e4b1 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -6350,8 +6350,7 @@ redeclare_class_template (tree type, tree parms, tree cons) /* The actual substitution part of instantiate_non_dependent_expr_sfinae, to be used when the caller has already checked (processing_template_decl - && !instantiation_dependent_expression_p (expr) - && potential_constant_expression (expr)) + && !instantiation_dependent_expression_p (expr)) and cleared processing_template_decl. */ tree @@ -6365,8 +6364,7 @@ instantiate_non_dependent_expr_internal (tree expr, tsubst_flags_t complain) /*integral_constant_expression_p=*/true); } -/* Simplify EXPR if it is a non-dependent expression. Returns the - (possibly simplified) expression. */ +/* Instantiate the non-dependent expression EXPR. */ tree instantiate_non_dependent_expr_sfinae (tree expr, tsubst_flags_t complain) @@ -6374,16 +6372,9 @@ instantiate_non_dependent_expr_sfinae (tree expr, tsubst_flags_t complain) if (expr == NULL_TREE) return NULL_TREE; - /* If we're in a template, but EXPR isn't value dependent, simplify - it. We're supposed to treat: - - template <typename T> void f(T[1 + 1]); - template <typename T> void f(T[2]); - - as two declarations of the same function, for example. */ - if (processing_template_decl - && is_nondependent_constant_expression (expr)) + if (processing_template_decl) { + gcc_checking_assert (!instantiation_dependent_expression_p (expr)); processing_template_decl_sentinel s; expr = instantiate_non_dependent_expr_internal (expr, complain); } @@ -6396,8 +6387,8 @@ instantiate_non_dependent_expr (tree expr) return instantiate_non_dependent_expr_sfinae (expr, tf_error); } -/* Like instantiate_non_dependent_expr, but return NULL_TREE rather than - an uninstantiated expression. */ +/* Like instantiate_non_dependent_expr, but return NULL_TREE if the + expression is dependent or non-constant. */ tree instantiate_non_dependent_or_null (tree expr) diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index 66d90c2f7be..8f744eb21b6 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -11234,16 +11234,13 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p, } else if (processing_template_decl) { - /* Instantiate the non-dependent operand to diagnose any ill-formed - expressions. And keep processing_template_decl cleared for the rest + expr = instantiate_non_dependent_expr_sfinae (expr, complain); + if (expr == error_mark_node) + return error_mark_node; + /* 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; } /* The type denoted by decltype(e) is defined as follows: */
Re: [PATCH] c++: non-constant non-dependent decltype folding [PR104823]
Patrick Palka via Gcc-patches Tue, 08 Mar 2022 08:55:14 -0800
- [PATCH] c++: non-constant non-dependent decl... Patrick Palka via Gcc-patches
- Re: [PATCH] c++: non-constant non-depen... Jason Merrill via Gcc-patches
- Re: [PATCH] c++: non-constant non-d... Patrick Palka via Gcc-patches
- Re: [PATCH] c++: non-constant n... Jason Merrill via Gcc-patches
- Re: [PATCH] c++: non-consta... Patrick Palka via Gcc-patches
- Re: [PATCH] c++: non-c... Jason Merrill via Gcc-patches