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.

Reply via email to