https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107206

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
          Component|c++                         |libstdc++
             Status|UNCONFIRMED                 |NEW
   Last reconfirmed|                            |2022-10-11
     Ever confirmed|0                           |1

--- Comment #1 from Richard Biener <rguenth at gcc dot gnu.org> ---
Confirmed.  We diagnose

<bb 2> [local count: 1073741824]:
MEM[(struct optional *)&y + 4B] ={v} {CLOBBER};
MEM[(union _Storage *)&y + 4B] ={v} {CLOBBER};
MEM[(struct _Optional_payload_base *)&y + 4B]._M_engaged = 0;
D.11546.o = y.o;
SR.27_14 = MEM <int> [(struct optional *)&y + 4B];    <--------- this
MEM <int> [(struct optional *)&D.11546 + 4B] = SR.27_14;
MEM <unsigned char> [(struct optional *)&D.11546 + 8B] = 0;
MEM[(struct Y *)&z].o = MEM[(const struct Y &)&D.11546].o;
D.11546 ={v} {CLOBBER(eol)};
MEM[(struct Y *)&w] ={v} {CLOBBER};
MEM[(struct X *)&w] ={v} {CLOBBER};
MEM[(struct X *)&w].i = 0;
MEM <int> [(struct optional *)&z + 4B] = 1;
MEM <unsigned char> [(struct optional *)&z + 8B] = 1;
MEM[(struct Y *)&w].o = MEM[(const struct Y &)&z].o;
f (&w.y);
y ={v} {CLOBBER(eol)};
z ={v} {CLOBBER(eol)};
w ={v} {CLOBBER(eol)};
return;

Here the aggregate copy

   D.11546.o = y.o;

is effectively scalarized and that accesses the data member of the not
engaged std::optional<>.

IMHO that's a standard library issue?  The copy is due to the by value
passing and we get in .original

  <<cleanup_point <<< Unknown tree: expr_stmt
    Z::Z (&z, &TARGET_EXPR <D.11546, <<< Unknown tree: aggr_init_expr
      5
      __ct_comp
      D.11546
      (struct Y *) <<< Unknown tree: void_cst >>>
      (const struct Y &) &y >>>>) >>>>>;

which eventually leads to

          Y::Y (&D.11546, &y);
          Z::Z (&z, &D.11546);

which contains
void Y::Y (struct Y * const this, const struct Y & D.11498)
{
  *this = {CLOBBER};
  {
    _1 = &this->x;
    _2 = &D.11498->x;
    X::X (_1, _2);
    this->o = D.11498->o;
  }

so the std::optional<> is simply aggregate copied, accessing any not
engaged member.

GCC is correct in diagnosing this uninitialized access.

Reply via email to