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:  */

Reply via email to