On 3/25/25 1:50 PM, Marek Polacek wrote:
On Tue, Mar 25, 2025 at 05:18:23PM +0000, Simon Martin wrote:
We've been miscompiling the following since r0-51314-gd6b4ea8592e338 (I
did not go compile something that old, and identified this change via
git blame, so might be wrong)

=== cut here ===
struct Foo { int x; };
Foo& get (Foo &v) { return v; }
void bar () {
   Foo v; v.x = 1;
   (true ? get (v) : get (v)).*(&Foo::x) = 2;
   // v.x still equals 1 here...
}
=== cut here ===

The problem lies in build_m_component_ref, that computes the address of
the COND_EXPR using build_address to build the representation of
   (true ? get (v) : get (v)).*(&Foo::x);
and gets something like
   &(true ? get (v) : get (v))  // #1
instead of
   (true ? &get (v) : &get (v)) // #2
and the write does not go where want it to, hence the miscompile.

This patch replaces the call to build_address by a call to
cp_build_addr_expr, which gives #2, that is properly handled.

Successfully tested on x86_64-pc-linux-gnu. OK for trunk? And for active
branches after 2-3 weeks since it's a nasty one (albeit very old)?

        PR c++/114525

gcc/cp/ChangeLog:

        * typeck2.cc (build_m_component_ref): Call cp_build_addr_expr
        instead of build_address.

gcc/testsuite/ChangeLog:

        * g++.dg/parse/pr114525.C: New test.

g++.dg/expr/cond18.C seems like a more appropriate place, but the
patch itself LGTM.

Sure, that does sound better.

Jason

Reply via email to