]> git.ipfire.org Git - thirdparty/gcc.git/commit
c++: Properly fold <COND_EXPR>.*<COMPONENT> [PR114525]
authorSimon Martin <simon@nasilyan.com>
Tue, 25 Mar 2025 19:11:19 +0000 (20:11 +0100)
committerSimon Martin <simon@nasilyan.com>
Tue, 25 Mar 2025 19:31:42 +0000 (20:31 +0100)
commit35ce9afc84a63fb647a90cbecb2adf3e748178be
tree76870267526a8af19f76a9d9c21e1e74ab276cc6
parent0fb10aca02852b2e8d78a78c07aa2f62aec6a07e
c++: Properly fold <COND_EXPR>.*<COMPONENT> [PR114525]

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.

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/expr/cond18.C: New test.
gcc/cp/typeck2.cc
gcc/testsuite/g++.dg/expr/cond18.C [new file with mode: 0644]