[PATCH] Fallback to operator new for MSVC compatibility

Aaron Ballman aaron at aaronballman.com
Wed May 29 07:49:40 PDT 2013


#include <stdio.h>
#include <stdlib.h>

struct arbitrary_t {} arbitrary;

void *operator new[]( size_t s, arbitrary_t ) throw() { return ::malloc( s ); }

struct S {
  void *operator new( size_t s, arbitrary_t ) throw() { return ::malloc( s ); }
};

int main() {
  S *s = new (arbitrary) S[2];
}

This will yield a call to the global operator new[] instead of the
class-specific operator new.  Using new instead of new[] yields a call
to the matching class-specific operator new still.  So I think my test
will have to move down below the check for a global operator new:

 <look for member operator new>
 <look for global operator new>
+if (not found && looking for array new && MS mode)
+  <switch to looking for non-array new>
+  <look for global operator new>

If you agree, then I'll make the changes and add another test to
CodeGenCXX to ensure we're calling the proper one.

~Aaron

On Tue, May 28, 2013 at 9:00 PM, Richard Smith <richard at metafoo.co.uk> wrote:
> OK, based on off-line discussion, it seems that MSVC doesn't use a placement
> operator delete *at all*. The approach in the patch of switching to using
> the non-array forms for both if we don't find 'operator new[]' makes sense
> to me.
>
> The patch doesn't look quite right, though. We have:
>
>  <look for member operator new>
> +if (not found && looking for array new && MS mode)
> +  <switch to looking for non-array new>
> +  <look for global operator new>
>  <look for global operator new>
>
> ... which will never use a global array new in MS mode, and will never use a
> class-specific non-array new for an array allocation.
>
> One more question, then. What happens if there's no class-specific 'operator
> new[]', but there is both a matching class-specific 'operator new' and a
> matching global 'operator new[]'?
>
> On Tue, May 28, 2013 at 5:04 PM, Richard Smith <richard at metafoo.co.uk>
> wrote:
>>
>> On Tue, May 28, 2013 at 4:50 PM, Aaron Ballman <aaron at aaronballman.com>
>> wrote:
>>>
>>> On Tue, May 28, 2013 at 6:07 PM, Richard Smith <richard at metafoo.co.uk>
>>> wrote:
>>> > What does MSVC think about:
>>> >
>>> > void *operator new(unsigned int size, arbitrary_t);
>>> > void operator delete[](unsigned int size, arbitrary_t) = delete;
>>> > struct S { S(); };
>>> > S *p = new (arbitrary) S[5];
>>> >
>>> > ? Will it call the (deleted) operator delete[] even though it picked a
>>> > non-array operator new?
>>>
>>> MSVC doesn't support deleted functions as of right now, so it just errors
>>> out.
>>>
>>> > What if there is an array new but no array delete?
>>>
>>> struct arbitrary_t {} arbitrary;
>>> void *operator new(unsigned int size, arbitrary_t);
>>>
>>> void f() {
>>>   int *p = new(arbitrary) int[4];
>>>   int *p2 = new(arbitrary) int;
>>>
>>>   delete [] p;
>>>   delete p2;
>>> }
>>>
>>> Yields calls to:
>>>
>>> call ??3 at YAXPAX@Z ; operator delete
>>>
>>> for both p and p2, so it falls back on the global delete.
>>
>>
>> I don't think that answers my question, though. What I'd like to know is,
>> should we fall back from operator delete[] to operator delete exactly when
>> we fall back from operator new[] to operator new (as your patch does), or
>> should we perform the two fallbacks independently?
>
>



More information about the cfe-commits mailing list