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.