On Sat, Nov 22, 2025 at 04:53:56PM +0530, Jason Merrill wrote:
> > The following testcase is rejected, because due to the C++17
> > b @= a ordering of side-effects cp_stabilize_reference is called
> > on the lhs of the compound assignment. For some cases
> > cp_stabilize_reference just uses stabilize_reference, but for other
> > cases it attempts to bind a reference to the expression.
> > This doesn't work for bit-fields and DECL_PACKED fields though,
> > we can't take address of a bit-field (not DECL_PACKED field)
> > and error on that.
> > First I was thinking about just adjusting the expression so that
> > it is a reference to the structure which contains the bit-field
> > and make the whole thing COMPONENT_REF of that, but there doesn't
> > have to be just one such struct, there can be many and each one
> > having different bit-field.
>
> I don't understand the "but"; there can only be one bit-field in a
> COMPONENT_REF chain, and it should be fine to bind a reference to the last
> struct. There are no bit-fields of class type.
See the testcase, e.g. that
(fred (b) ? (baz ().y = foo ()) : (qux ().z = foo ())) += bar ();
line. baz () returns S &, qux () returns T &, completely unrelated
type.
So, I can't bind a reference to S & for the whole expression, I can't
bind a reference to T & for the whole expression either.
So, the patch handles it as separate SAVE_EXPRs, one around fred (b),
one around baz (), one around baz ().y = foo (), one around
qux () and one around qux ().z = foo ().
So it is
(SAVE_EXPR <fred (b)>
? ((SAVE_EXPR <baz ()>.y = foo ()), SAVE_EXPR <baz ()>.y)
: ((SAVE_EXPR <qux ()>.z = foo ()), SAVE_EXPR <qux ()>.z))
and so nothing is evaluated more than once (and the testcase verifies that).
Basically what stabilize_expr does normally, except it has special handling
for COMPOUND_EXPR, COND_EXPR, PREINCREMENT_EXPR and PREDECREMENT_EXPR.
And for DECL_PACKED it is even worse, because it isn't just the outermost
COMPONENT_REF, there can be other COMPONENT_REFs and ARRAY_REFs and
REALPART_EXPR and IMAGPART_EXPR etc. around it.
Jakub