https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97595
Martin Sebor <msebor at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |jason at gcc dot gnu.org Summary|[11 Regression] warning: |[11 Regression] bogus |writing 1 byte into a |-Wstringop-overflow due to |region of size 0 |DECL_SIZE_UNIT |[-Wstringop-overflow=] |underreporting field size Keywords| |diagnostic Status|UNCONFIRMED |NEW Ever confirmed|0 |1 Last reconfirmed| |2020-10-27 --- Comment #3 from Martin Sebor <msebor at gcc dot gnu.org> --- I can confirm the warning but I'm not sure the bug is in the middle end code. Let me CC Jason for his comments. The warning triggers for the MEM_REF below: MEM[(char &)_10 + 224] = _24; in the following GIMPLE ("type" is char). The destination of the access is this_3(D)->D.45669 which is the basic_istream subobject. Its size reported by DECL_SIZE_UNIT() in component_ref_size() is 16. The initial offset (i.e., _10) is indeterminate but it's taken to be in the range bounded by the size of the object, or [0, 16]. Given that, the constant offset 224 is determined to be out of bounds. The change introduced in r11-3827 that triggers the warning is the assumption that unless determined otherwise, an indeterminate offset into an object must be bounded by the object's size. But sizeof (basic_istream) is 280, not 16. This is also what TYPE_SIZE_UNIT() reports, so the bug here is either in DECL_SIZE_UNIT(), or in using it in lieu of TYPE_SIZE_UNIT(). I'd expect the two to return the same result so this seems like a front end bug to me but I will defer to Jason. std::basic_iostream<char>::swap (struct basic_iostream * const this, struct basic_iostream & __rhs) { struct basic_istream * _1; struct basic_istream * _2; int (*) () * _7; long int _8; sizetype _9; struct basic_ios * _10; int (*) () * _11; long int _12; sizetype _13; struct basic_ios & _14; long int _15; long int _16; struct ios_base * _17; struct ios_base * _18; struct locale * _19; struct locale * _20; struct basic_ostream * _21; struct basic_ostream * _22; char _23; char _24; bool _25; bool _26; <bb 2> [local count: 1073741824]: _1 = &this_3(D)->D.45669; _2 = &__rhs_4(D)->D.45669; _7 = MEM[(struct basic_istream *)this_3(D)]._vptr.basic_istream; _8 = MEM[(long int *)_7 + -24B]; _9 = (sizetype) _8; _10 = _1 + _9; _11 = MEM[(struct basic_istream *)__rhs_4(D)]._vptr.basic_istream; _12 = MEM[(long int *)_11 + -24B]; _13 = (sizetype) _12; _14 = _2 + _13; _17 = &_10->D.42253; _18 = &_14->D.42253; std::ios_base::_M_swap (_17, _18); _19 = &_10->D.42253._M_ios_locale; std::basic_ios<char>::_M_cache_locale (_10, _19); _20 = &_14->D.42253._M_ios_locale; std::basic_ios<char>::_M_cache_locale (_14, _20); _21 = MEM[(struct basic_ostream * &)_10 + 216]; _22 = MEM[(struct basic_ostream * &)_14 + 216]; MEM[(struct basic_ostream * &)_10 + 216] = _22; MEM[(struct basic_ostream * &)_14 + 216] = _21; _23 = MEM[(type &)_10 + 224]; <<< -Wstringop-overflow _24 = MEM[(type &)_14 + 224]; MEM[(char &)_10 + 224] = _24; MEM[(char &)_14 + 224] = _23; _25 = MEM[(type &)_10 + 225]; _26 = MEM[(type &)_14 + 225]; MEM[(bool &)_10 + 225] = _26; MEM[(bool &)_14 + 225] = _25; _15 = MEM[(type &)this_3(D) + 8]; _16 = MEM[(type &)__rhs_4(D) + 8]; MEM[(long int &)this_3(D) + 8] = _16; MEM[(long int &)__rhs_4(D) + 8] = _15; return; }