https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122772
Jakub Jelinek <jakub at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Last reconfirmed| |2025-11-20
Status|UNCONFIRMED |NEW
Priority|P3 |P2
Ever confirmed|0 |1
CC| |jason at gcc dot gnu.org,
| |mpolacek at gcc dot gnu.org,
| |ppalka at gcc dot gnu.org
--- Comment #4 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
So, guess cp_stabilize_expr for this needs to have another case for this.
Currently it uses
cp_lvalue_kind kind = lvalue_kind (ref);
if ((kind & ~clk_class) != clk_none)
{
tree type = unlowered_expr_type (ref);
bool rval = !!(kind & clk_rvalueref);
type = cp_build_reference_type (type, rval);
/* This inhibits warnings in, eg, cxx_mark_addressable
(c++/60955). */
warning_sentinel s (extra_warnings);
ref = build_static_cast (input_location, type, ref,
tf_error);
}
but for kind & (clk_bitfield|clk_packed) that isn't an option.
And then it uses
return stabilize_reference (ref);
for selected other trees. But for bit-fields and DECL_PACKED fields, we can't
bind a reference to those, so we really need some other function which will
return a reference to the containing aggregate but handle all the possible
trees that stand in a way, COMPOUND_EXPR, MODIFY_EXPR, the various
tcc_reference trees etc.
E.g. for
int foo () { return 0; }
int bar () { return 1; }
struct S { int y; };
S &baz () { static S s; return s; }
int
main ()
{
(baz ().y = foo ()) += bar ();
}
the current build_static_cast to reference way turns that (baz ().y = foo ())
expression into
(*(int &) (SAVE_EXPR <SAVE_EXPR <baz ()>->y = foo (), &SAVE_EXPR <baz ()>->y>)
i.e. we first call baz (), remember its result, then evaluate the whole former
expression and then bind a reference to the y member in there.
Now, for clk_bitfield and clk_packed, it would need to instead do
((S &) (SAVE_EXPR <SAVE_EXPR <baz ()>->y = foo (), SAVE_EXPR <baz ()> >).y