https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85783

--- Comment #6 from Martin Sebor <msebor at gcc dot gnu.org> ---
Inlining happens automatically unless it's disabled.  The inlining of the
operator results in the excessive constant argument (created by the C++
front-end) to propagate to the call to malloc().  That's what triggers the
warning.  The GIMPLE for the function in my smaller test case (from the output
of -fdump-tree-gimple) shows this:

f (size_t n)
{
  void * D.6084;
  void * D.6059;
  size_t iftmp.1;
  long unsigned int n.2;
  struct A * retval.3;
  struct A * D.6060;
  struct A * D.6061;
  long int D.6062;
  size_t iftmp.4;

  if (n == 0) goto <D.6082>; else goto <D.6083>;
  <D.6082>:
  D.6084 = 0B;
  // predicted unlikely by early return (on trees) predictor.
  return D.6084;
  <D.6083>:
  n.2 = n;
  if (n.2 <= 9223372036854775800) goto <D.6087>; else goto <D.6088>;
  <D.6087>:
  iftmp.1 = n.2 + 8;
  goto <D.6089>;
  <D.6088>:
  iftmp.1 = 18446744073709551615;       <<< SIZE_MAX
  <D.6089>:
  D.6059 = operator new [] (iftmp.1);   <<< call to replacement operator new
  MEM[(sizetype *)D.6059] = n.2;

(Adding attribute noinline to the operator eliminates the warning.)

As we discussed in the past, the C++ standard imposes a couple of requirements
on replacement operator new that your test case violates:

1) it must not be declared inline (there must be exactly one operator new in a
program)
2) it must either return valid new pointer or fail by throwing an exception

To make the test case strictly valid the replacement operator would either have
to throw, or it would have to be the nothrow form (taking const std::nothrow_t&
as an argument), and the call to it would have to pass it std::nothrow.

The warning doesn't trigger if the replacement operator throws.  It does
trigger for the nothrow operator, which is why I agree the warning in that case
is a false positive.  (But you're not replacing the nothrow operator.)

Having said that, the C++ standard requires compilers to avoid calling the
allocation function with an argument in excess of some implementation-defined
limit, but GCC calls it regardless (e.g., it calls it with N = SIZE_MAX for new
(nothrow) T[N] even when sizeof (T) > 1).  That's a bug, and (indirectly) the
reason for the warning.  I've raised bug 85795 for that.

Reply via email to