[Bug lto/51744] Erroneous warning: memset used with constant zero length parameter
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51744 Alan Modra amodra at gmail dot com changed: What|Removed |Added Status|NEW |RESOLVED CC||amodra at gmail dot com Resolution|--- |FIXED --- Comment #11 from Alan Modra amodra at gmail dot com --- This has now been fixed on mainline binutils
[Bug lto/51744] Erroneous warning: memset used with constant zero length parameter
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51744 --- Comment #6 from Richard Biener rguenth at gcc dot gnu.org --- Btw, it works when using gold ...
[Bug lto/51744] Erroneous warning: memset used with constant zero length parameter
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51744 --- Comment #7 from Mark Pizzolato mark at infocomm dot com --- Thanks for reducing this test case further. That illuminates something for me: Specifically: Notice in the following lines: if (__builtin_constant_p (__len) __len == 0 (!__builtin_constant_p (__ch) || __ch != 0)) { The part of the expression || __ch != 0) What could possibly be the purpose of this check? That is exactly why the 3rd condition I previously mentioned: 3) memset is called with a NON zero fill value argument. triggers this issue. The warning is about the length, but it is checking the value being set. How could that make sense? Clearly this check lets the vast majority of uses of memset pass without issue since all of those cases use 0 as the value to be set. From my point of view, if that check wasn't there (i.e. remove || __ch != 0 from the expression), the problem would not exist.
[Bug lto/51744] Erroneous warning: memset used with constant zero length parameter
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51744 --- Comment #8 from Richard Biener rguenth at gcc dot gnu.org --- (In reply to Mark Pizzolato from comment #7) Thanks for reducing this test case further. That illuminates something for me: Specifically: Notice in the following lines: if (__builtin_constant_p (__len) __len == 0 (!__builtin_constant_p (__ch) || __ch != 0)) { The part of the expression || __ch != 0) What could possibly be the purpose of this check? That is exactly why the 3rd condition I previously mentioned: 3) memset is called with a NON zero fill value argument. triggers this issue. The warning is about the length, but it is checking the value being set. How could that make sense? Clearly this check lets the vast majority of uses of memset pass without issue since all of those cases use 0 as the value to be set. From my point of view, if that check wasn't there (i.e. remove || __ch != 0 from the expression), the problem would not exist. When val == 0 then the case of len == 0 is ambiguous and you can't really tell the user they swapped val and len (because they are equal).
[Bug lto/51744] Erroneous warning: memset used with constant zero length parameter
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51744 --- Comment #9 from Mark Pizzolato mark at infocomm dot com --- When val == 0 then the case of len == 0 is ambiguous and you can't really tell the user they swapped val and len (because they are equal). That is certainly true. I'm not sure how that specifically relates to the problem since the warning message is only about the length being 0. The problem is that the warning is being issued incorrectly when the set value is != 0 and the length is not a constant.
[Bug lto/51744] Erroneous warning: memset used with constant zero length parameter
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51744 --- Comment #10 from Richard Biener rguenth at gcc dot gnu.org --- It's a GNU ld bug I believe. https://sourceware.org/bugzilla/show_bug.cgi?id=16746
[Bug lto/51744] Erroneous warning: memset used with constant zero length parameter
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51744 --- Comment #4 from Richard Biener rguenth at gcc dot gnu.org --- typedef __SIZE_TYPE__ size_t; extern void *memset (void *__s, int __c, size_t __n) __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1))); extern void __warn_memset_zero_len (void) __attribute__((__warning__ (memset used with constant zero length parameter; this could be due to transposed parameters))); extern __inline __attribute__((__always_inline__)) __attribute__((__artificial__)) void * __attribute__ ((__nothrow__)) memset (void *__dest, int __ch, size_t __len) { if (__builtin_constant_p (__len) __len == 0 (!__builtin_constant_p (__ch) || __ch != 0)) { __warn_memset_zero_len (); return __dest; } return __builtin___memset_chk (__dest, __ch, __len, __builtin_object_size (__dest, 0)); } void main (int argc, char **argv) { char buf[5000]; memset (buf, 0xFF, argc); } This breaks a lot of applications if you build them with LTO and -D_FORTIFY_SOURCE=2. The reason this happens is that when LTO bytecode is output we still have bb 2: _2 = (long unsigned int) argc_1(D); _6 = __builtin_constant_p (_2); if (_6 != 0) goto bb 3; else goto bb 5; bb 3: if (_2 == 0) goto bb 4; else goto bb 5; bb 4: __warn_memset_zero_len (); goto bb 6; bb 5: __memset_chk (buf, 255, _2, 5000); bb 6: buf ={v} {CLOBBER}; thus __builtin_constant_p is not yet forced to be evaluated. This means that we put __warn_memset_zero_len into the LTO symbol table which is queried by the linker and this causes it to warn at the beginning of link-time. Also (as can be seen with the cases where we introduce a call late) the linker wants to see a final set of symbols at this time, thus it won't drop the reference to __warn_memset_zero_len even if during LTRANS phase we optimize it away.
[Bug lto/51744] Erroneous warning: memset used with constant zero length parameter
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51744 --- Comment #5 from Richard Biener rguenth at gcc dot gnu.org --- It also (sadly) means this works with -fno-use-linker-plugin. It also means that not outputting the UNDEF into the LTO symbol table for this case doesn't work as the executable will not link (we optimize the symbol away) if we don't fold away the reference to it later. I see no better way than either forcing the linker to re-scan needed symbols and warn at a second stage only or to fold __builtin_constant_p earlier.
[Bug lto/51744] Erroneous warning: memset used with constant zero length parameter
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51744 Richard Biener rguenth at gcc dot gnu.org changed: What|Removed |Added Known to fail||4.7.3, 4.8.3, 4.9.0 Severity|normal |major
[Bug lto/51744] Erroneous warning: memset used with constant zero length parameter
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51744 --- Comment #2 from Mark Pizzolato mark at infocomm dot com 2012-10-23 16:42:06 UTC --- Created attachment 28514 -- http://gcc.gnu.org/bugzilla/attachment.cgi?id=28514 MUCH simpler test case
[Bug lto/51744] Erroneous warning: memset used with constant zero length parameter
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51744 Mark Pizzolato mark at infocomm dot com changed: What|Removed |Added CC||mark at infocomm dot com --- Comment #3 from Mark Pizzolato mark at infocomm dot com 2012-10-23 16:43:01 UTC --- This may be a bug in gcc OR the linker. I don't know, BUT I have a more precise description of the issue and a much simpler minimal test case. The problem occurs when all of the following conditions are true: 1) gcc is invoked with -O2 and -flto 2) memset is called with a non-constant length argument 3) memset is called with a NON zero fill value argument. The minimal test case is: #include string.h void main (int argc, char **argv) { char buf[5000]; memset (buf, 0xFF, argc); } To conform to the bug submission guidelines, the preprocessed file for the this test is attached.
[Bug lto/51744] Erroneous warning: memset used with constant zero length parameter
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51744 Richard Guenther rguenth at gcc dot gnu.org changed: What|Removed |Added Keywords||diagnostic, lto Status|UNCONFIRMED |NEW Last reconfirmed||2012-01-04 CC||hubicka at gcc dot gnu.org Ever Confirmed|0 |1 --- Comment #1 from Richard Guenther rguenth at gcc dot gnu.org 2012-01-04 10:31:09 UTC --- I think this is a linker bug, GCC optimizes away the function (seeing that the argument is _not_ zero), but the linker warns about it anyway and it is still output for some reason: 72: 004006f0 2 FUNCGLOBAL HIDDEN15 __warn_memset_zero_le n resolution file: 2 ma2.o 4 84 cd7721f0 PREVAILING_DEF_IRONLY ma_init 95 cd7721f0 PREVAILING_DEF_IRONLY ma_pool 105 cd7721f0 PREVAILING_DEF_IRONLY ma_get_cell 124 cd7721f0 RESOLVED_EXEC __warn_memset_zero_len ma2_test.o 4 86 64da28d6 PREVAILING_DEF main 108 64da28d6 RESOLVED_IR ma_get_cell 113 64da28d6 RESOLVED_IR ma_pool 117 64da28d6 RESOLVED_IR ma_init