On 7/13/26 5:52 PM, Marek Polacek wrote:
On Mon, Jul 13, 2026 at 11:57:54AM -0400, Jason Merrill wrote:
On 7/10/26 4:28 PM, Marek Polacek wrote:
On Thu, Jul 09, 2026 at 08:43:42PM -0400, Jason Merrill wrote:
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?
Done.
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
Both fixed.
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.
This is so that I can set TREE_TYPE on a REQUIRES_EXPR. Code like
maybe_convert_cond needs a tree with a TREE_TYPE.
...but then we should use MARK_TS_TYPED instead. Fixed.
@@ -7128,7 +7133,10 @@ trees_in::core_vals (tree t)
if (CODE_CONTAINS_STRUCT (code, TS_EXP))
Likewise.
Done.
@@ -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.
I've used that style; it's a bit shorter. Thanks,
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
OK, thanks.
For 16, maybe we can just remove the assert.
Or change it to _checking_.
Here's a patch for that, ok for 16?
OK.
-- >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
REQUIRES_EXPR looks like a normal expression (tcc_expression).
The trunk patch changed REQUIRES_EXPR to tcc_exceptional. But in 16, we
can just dial the assert down to _checking.
gcc/cp/ChangeLog:
* tree.cc (lvalue_kind) <case MODOP_EXPR>: Use
gcc_checking_assert instead of gcc_assert.
---
gcc/cp/tree.cc | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index 2bcbfa84707..1da3e7d6fc2 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -280,7 +280,7 @@ lvalue_kind (const_tree ref)
case MODOP_EXPR:
/* We expect to see unlowered MODOP_EXPRs only during
template processing. */
- gcc_assert (processing_template_decl);
+ gcc_checking_assert (processing_template_decl);
if (CLASS_TYPE_P (TREE_TYPE (TREE_OPERAND (ref, 0))))
goto default_;
else