On 1/20/25 2:11 PM, Simon Martin wrote:
Hi Jason,

On 15 Jan 2025, at 22:42, Jason Merrill wrote:

On 12/12/24 2:07 PM, Simon Martin wrote:
We currently ICE upon the following valid (under -Wno-vla) code

=== cut here ===
void f(int c) {
    constexpr int r = 4;
    [&](auto) { int t[r * c]; }(0);
}
=== cut here ===

The problem is that when parsing the lambda body, and more
specifically
the multiplication, we mark the lambda as
LAMBDA_EXPR_CAPTURE_OPTIMIZED
even though the replacement of r by 4 is "undone" by the call to
build_min_non_dep in build_x_binary_op. This makes
prune_lambda_captures
remove the proxy declaration while it should not, and we trip on an
assert at instantiation time.

Why does prune_lambda_captures remove the declaration if it's still
used in the function body?  Setting LAMBDA_EXPR_CAPTURE_OPTIMIZED just
means "we might have optimized away some captures", the tree walk
should have found the use put back by build_x_binary_op.
I think that this is due to a bug in mark_const_cap_r, that’s been
here since the beginning, i.e. r8-7213-g1577f10a637352: it decides NOT
to walk sub-trees when encountering a DECL_EXPR for a constant capture
proxy (at lambda.cc:1769). I don’t understand why we wouldn’t want
to continue.

Because that's the declaration of the capture proxy, not a use of it.

Why aren't we finding the use in the declaration of t?

Removing that line fixes the PR, but breaks 3 existing tests
(lambda-capture1.C, lambda-const11.C and lambda-const11a.C, that all
assert that we optimise out the capture); that’s why I did not pursue
it in the first place.

Right.

But taking another look, it might not be that big a deal that we don’t
optimise those out: as soon as we use -O1 or above, the assignment to
the closure field actually disappears.

Completely breaking this optimization is a big deal, particularly since it affects the layout of closure objects. We can't always optimize everything away.

Jason

Reply via email to