On 7/9/26 5:50 PM, Marek Polacek wrote:
On Wed, Jul 08, 2026 at 08:59:32AM -0400, Jason Merrill wrote:
On 7/7/26 6:16 PM, Marek Polacek wrote:
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/16?

-- >8 --
We trip on the assert in lvalue_kind/MODOP_EXPR whose comment says
that we expect to see MODOP_EXPRs only during template processing.
In this test we get there with processing_template_decl==0.  The
MODOP_EXPR is created in:

      /* Parse the requirement body. */
      ++processing_template_decl;
      reqs = cp_parser_requirement_body (parser);
      --processing_template_decl;

but we're not in a template when calling maybe_convert_cond which
calls verify_sequence_points which ends up calling lvalue_p on
the MODOP_EXPR.  verify_sequence_points is a c-family/ function
so we couldn't make it stop recursing on REQUIRES_EXPR, so I suppose
we can do the following.

Eh, this just looks like a workaround for a single testcase.

I see several problems here:

1) We're retaining template trees in a non-template function,
2) verify_sequence_points is walking the unevaluated operand of a requires
because verify_tree assumes that all unknown expressions are evaluated, and
3) REQURES_EXPR looks like a normal expression (tcc_expression).

I think the right way to approach this would be to attack 3 by changing
REQUIRES_EXPR to tcc_exceptional.  Then 1 doesn't matter because the generic
code (such as verify_tree) sees that it's magic and doesn't try to walk into
it.

I did this.  It's no longer a trivial patch but it does fix the crash.

Thanks.

We could also attack 2 by defining unevaluated_p in the C front-end as well,
and checking it in verify_tree.  2 also affects other unevaluated codes like
NOEXCEPT_EXPR, potentially leading to wrong -Wsequence-point results.

I did not do this.  If you think I should, I will.

Maybe just add a FIXME next to the SIZEOF_EXPR case?

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --
We trip on the assert in lvalue_kind/MODOP_EXPR whose comment says
that we expect to see MODOP_EXPRs only during template processing.
In this test we get there with processing_template_decl==0.  The
MODOP_EXPR is created in:

     /* Parse the requirement body. */
     ++processing_template_decl;
     reqs = cp_parser_requirement_body (parser);
     --processing_template_decl;

but we're not in a template when calling maybe_convert_cond which
calls verify_sequence_points which ends up calling lvalue_p on
the MODOP_EXPR.

verify_sequence_points is walking the unevaluated operand of a requires
because verify_tree assumes that all unknown expressions are evaluated, and
REQURES_EXPR looks like a normal expression (tcc_expression).

missing I

This patch changes REQURES_EXPR to tcc_exceptional.  That means that

likewise

the generic code (such as verify_tree) sees that it's magic and doesn't
try to walk into it.

@@ -6530,8 +6530,11 @@ trees_out::core_vals (tree t)
if (CODE_CONTAINS_STRUCT (code, TS_EXP))
      {
+      location_t loc = (code == REQUIRES_EXPR

Hmm, why does REQUIRES_EXPR have TS_EXP after this patch?

I think you want to remove the MARK_TS_EXP from cp_common_init_ts and then move REQUIRES_EXPR out of this if.

@@ -7128,7 +7133,10 @@ trees_in::core_vals (tree t)
if (CODE_CONTAINS_STRUCT (code, TS_EXP))

Likewise.

@@ -4527,6 +4528,18 @@ cp_tree_equal (tree t1, tree t2)
      case REFLECT_EXPR:
        return compare_reflections (t1, t2);
+ case REQUIRES_EXPR:
+      if (!cp_tree_equal (REQUIRES_EXPR_PARMS (t1),
+                         REQUIRES_EXPR_PARMS (t2)))
+       return false;
+      if (!cp_tree_equal (REQUIRES_EXPR_REQS (t1),
+                         REQUIRES_EXPR_REQS (t2)))
+       return false;
+      if (!cp_tree_equal (REQUIRES_EXPR_EXTRA_ARGS (t1),
+                         REQUIRES_EXPR_EXTRA_ARGS (t2)))
+       return false;
+      return true;

This could be return (x && y && z) but up to you.

Jason

Reply via email to