https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71002
--- Comment #6 from rguenther at suse dot de <rguenther at suse dot de> --- On Mon, 9 May 2016, tavianator at gmail dot com wrote: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71002 > > --- Comment #5 from Tavian Barnes <tavianator at gmail dot com> --- > > But if it is not POD then assuming it gets copied correctly when > > init-constructing a POD union where they placed such object is > > an interesting assumption... > > Hrm? They seem to always copy it manually with long_t's copy constructor: > > ::new(&m_repr.long_repr()) long_t(other.m_repr.long_repr()); I stand corrected. At least they always read from short_t when computing is_short() even if that is not the active union member. Some missed optimizations: foo::foo(string) (struct foo * const this, struct string & restrict str) { ... <bb 2>: MEM[(struct short_t &)this_2(D)].h.is_short = 1; MEM[(struct short_t &)this_2(D)].h.length = 0; MEM[(struct short_t &)this_2(D)].data[0] = 0; _19 = BIT_FIELD_REF <MEM[(const struct string *)this_2(D)], 8, 0>; _20 = _19 & 1; if (_20 != 0) this is fold-const.c at work replacing the load from h.is_short with the BIT_FIELD_REF. But then we go to short_t short_backup(m_repr.short_repr()); m_repr.short_repr().~short_t(); ::new(&m_repr.long_repr()) long_t(other.m_repr.long_repr()); other.m_repr.long_repr().~long_t(); ::new(&other.m_repr.short_repr()) short_t(short_backup); <bb 5>: short_backup = MEM[(const struct short_t &)this_2(D)]; MEM[(struct long_t *)this_2(D)] = MEM[(const struct long_t *)str_5(D)]; MEM[(struct short_t *)str_5(D)] = short_backup; short_backup ={v} {CLOBBER}; goto <bb 11>; which looks good. But <bb 11>: # prephitmp_52 = PHI <_51(10), 0(5)> goto <bb 13>; <bb 13>: # iftmp.7_13 = PHI <prephitmp_52(11), _12(12)> *this_2(D).m_len = iftmp.7_13; stores zero into the length field. Somehow PRE does this transform. I'll investigate some more.