[Bug c++/85783] alloc-size-larger-than fires incorrectly with new[] and can't be disabled

msebor at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Tue May 15 01:21:00 GMT 2018


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

Martin Sebor <msebor at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |diagnostic
             Status|UNCONFIRMED                 |RESOLVED
                 CC|                            |msebor at gcc dot gnu.org
         Resolution|---                         |WONTFIX

--- Comment #3 from Martin Sebor <msebor at gcc dot gnu.org> ---
I can reproduce it with the following reduced semi-valid test case.  (The test
case isn't entirely valid because it defines the array new to exit on failure
rather than to throw, but a nothrow form of the test case reproduces the
warning as well.)

void* operator new[](__SIZE_TYPE__ n)
{
  void* p = __builtin_malloc (n);
  if (p)
    return p;

  __builtin_exit (1);
}

struct A
{
  A ();
  ~A ();
};


void* f (__SIZE_TYPE__ n)
{
  if (!n)
    return 0;

  return new A[n];
}
In function ‘void* operator new [](long unsigned int)’,
    inlined from ‘void* f(long unsigned int)’ at pr85783.C:22:17:
pr85783.C:3:30: warning: argument 1 value ‘18446744073709551615’ exceeds
maximum object size 9223372036854775807 [-Walloc-size-larger-than=]
   void* p = __builtin_malloc (n);
             ~~~~~~~~~~~~~~~~~^~~
pr85783.C: In function ‘void* f(long unsigned int)’:
pr85783.C:3:30: note: in a call to built-in allocation function ‘void*
__builtin_malloc(long unsigned int)’

The excessive constant argument is introduced by the C++ front-end, in
cp/build_operator_new_call(), which emits a call to operator new[](size_t). 
The code was added in r190546 as a solution to prevent unsigned wrapping (when
array new expression must compute the amount of space to allocate as a product
of the number of elements and element size).  When the replacement operator
new[] is inlined the excessive argument is propagated to malloc() and
ultimately triggers the warning.

An easy way to suppress the warning is to check the argument in the operator
and have it fail when it's excessive:

  void* operator new[](size_t n)
  {
    if (n <= PTRDIFF_MAX)
      {
        void* p = malloc (n);
        if (p)
          return p;
      }

    exit (1);
  }

Otherwise, I'm not sure there is much GCC can do to avoid the warning, or that
it's worth putting effort into.  The use case (defining a non-throwing
replacement operator new inline) is rare and not entirely valid.  Normally, the
operator will be defined out-of-line and while that might still trigger
warnings from the same translation unit, the solution -- handling the excessive
argument in the replacement operator -- seems simple enough.

With that I'm going to resolve this report as WONTFIX.  If someone (e.g., Jeff
who chimed in on the discussion on gcc-help below) feels otherwise please feel
free to reopen it.

https://gcc.gnu.org/ml/gcc-help/2018-05/msg00088.html


More information about the Gcc-bugs mailing list