https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100197
Martin Sebor <msebor at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Known to fail| |10.2.0, 11.0 Status|UNCONFIRMED |NEW Keywords| |alias, missed-optimization Last reconfirmed| |2021-04-22 Ever confirmed|0 |1 Component|c++ |tree-optimization --- Comment #1 from Martin Sebor <msebor at gcc dot gnu.org> --- The warning only runs at -O2 (and with -Wextra). It works as designed. It's issued for the IL below. The String::_smallBuffer is defined as: char _smallBuffer[8]; The reason for the warning is missing folding/constant prtopagation due to overly conservative alias analysis: GCC assumes that the call to printf() might modify the String object because it's passed the this pointer (the address of &s). That prevents the constant store to _buffLen from being propagated. But the only standard directive that can clobber an object is %n, so the assumption could be avoided by scanning the format string for %n (and either matching it to the argument or simply assuming it clobbers any argument). This is the missed-optimization part. The same false positive would still happen with any other function whose semantics GCC doesn't have knowledge of. To avoid it in those cases the warning (but not optimizers) could assume that the argument might be clobbered only when passed to a non-const pointer/reference. This would be a good change to make in all these flow-sensitive warnings (all of which are subject to the same class of false positives as a result of the overly conservative escape/alias analysis). This is the diagnostic aspect of this bug. int main (int D.4559, char * * D.4560) { bool D.4665; const size_t sLen; struct String s; int _1; int _6; long unsigned int _8; char * _9; long unsigned int _10; char * _11; long unsigned int _20; char * iftmp.2_21; int _22; char * iftmp.2_24; void * _26; long unsigned int _27; const char * iftmp.3_28; <bb 2> [local count: 1073741824]: s ={v} {CLOBBER}; s._length = 0; s._bufferLen = 128; <<< store _26 = malloc (128); s._bigBuffer = _26; __printf_chk (1, "EnsureBufSize on String %p: _bigBuffer=%p _bufferLen=%zu\n", &s, _26, 128); <<< assumed to clobber s._bufferLen _20 = MEM[(const struct String *)&s]._bufferLen; <<< load if (_20 > 8) goto <bb 3>; [50.00%] else goto <bb 4>; [50.00%] <bb 3> [local count: 536870913]: iftmp.2_21 = s._bigBuffer; <bb 4> [local count: 1073741824]: # iftmp.2_24 = PHI <iftmp.2_21(3), &s._smallBuffer(2)> __builtin_memcpy (iftmp.2_24, "1234567890", 11); s._length = 10; _1 = rand (); if (_1 != 0) goto <bb 6>; [50.00%] else goto <bb 5>; [50.00%] <bb 5> [local count: 714038312]: _8 = s._bufferLen; if (_8 > 8) goto <bb 8>; [24.44%] else goto <bb 10>; [75.56%] <bb 6> [local count: 536870913]: _27 = s._bufferLen; <<< load if (_27 > 8) goto <bb 7>; [50.00%] else goto <bb 15>; [50.00%] <bb 7> [local count: 268435456]: iftmp.3_28 = s._bigBuffer; _22 = strcmp (iftmp.3_28, "1234567890"); if (_22 == 0) goto <bb 9>; [33.00%] else goto <bb 8>; [67.00%] <bb 8> [local count: 354334801]: _9 = s._bigBuffer; free (_9); goto <bb 11>; [100.00%] <bb 9> [local count: 177167400]: __builtin_puts (&"Mwahey!"[0]); goto <bb 5>; [100.00%] <bb 10> [local count: 719407023]: <bb 11> [local count: 1073741824]: s ={v} {CLOBBER}; s ={v} {CLOBBER}; return 0; <bb 12> [count: 0]: <L10>: _10 = s._bufferLen; if (_10 > 8) goto <bb 13>; [0.00%] else goto <bb 14>; [0.00%] <bb 13> [count: 0]: _11 = s._bigBuffer; free (_11); <bb 14> [count: 0]: s ={v} {CLOBBER}; resx 2 <bb 15> [local count: 268435457]: _6 = strcmp (&s._smallBuffer, "1234567890"); <<< -Wstring-compare if (_6 == 0) goto <bb 9>; [33.00%] else goto <bb 10>; [67.00%] }