The expectation is if the operator new has a throw() keyword, there
will be a NULL check before initialization is done and no NULL check if the
throw() keyword is omitted.
This expectation is based on [expr.new]p13 that I find in this copy
of the standard:
[Note: unless an allocation function is declared with an empty exception-specification (15.4), throw(), it indicates
failure to allocate storage by throwing a bad_alloc exception (clause 15, 18.4.2.1); it returns a non-null pointer otherwise.
If the allocation function is declared with an empty exception-specification, throw(), it returns null to indicate failure
to allocate storage and a non-null pointer otherwise. — end note ] If the allocation function returns null, initialization
shall not be done, the deallocation function shall not be called, and the value of the new-expression shall be null.
The results I got for various permutations of compiler this code in godbolt
are:
gcc (any version/any -O/new declaration w/o throw()): no NULL check before
constructor init.
clang (any version/any -O/new declaration w/o throw()): no NULL check before
constructor init.
clang (3.3 and prior/any -O/new declaration w/ throw()): NULL check before
constructor init.
clang (3.4.1 and later/-O0/new declaration w/ throw()): NULL check before
constructor init.
clang (3.4.1 and later/-O1 and higher/new declaration w/ throw()): no NULL
check before constructor init.
clang (3.4.1 and later/-O0/new declaration w/ throw()): NULL check before
constructor init.
E.g., below is the x86_64 assembly for clang 3.3 vs. 5.0.0 with -O3:
clang 3.3, -O3 -fno-exceptions
test_new(): # @test_new()
push RAX
mov EDI, 4
call operator new(unsigned long)
test RAX, RAX
je .LBB0_1
mov DWORD PTR [RAX], 5
pop RDX
ret
.LBB0_1:
xor EAX, EAX
pop RDX
ret
clang 5.0.0, -O3 -fno-exceptions
test_new(): # @test_new()
push rax
mov edi, 4
call operator new(unsigned long)
mov dword ptr [rax], 5
pop rcx
ret
We believe there may be a bug here where clang should be doing the NULL check before initialization here regardless of the optimization level to be standard compliant.
Extended Description
I tested this example in various compilers on godbolt using
-fno-exceptions
and various-O
levels.https://godbolt.org/g/egWwC2
The expectation is if the
operator new
has athrow()
keyword, there will be aNULL
check before initialization is done and noNULL
check if thethrow()
keyword is omitted.This expectation is based on [expr.new]p13 that I find in this copy of the standard:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1905.pdf
The results I got for various permutations of compiler this code in godbolt are:
gcc (any version/any
-O
/new
declaration w/throw()
):NULL
check before constructor init.gcc (any version/any
-O
/new
declaration w/othrow()
): noNULL
check before constructor init.clang (any version/any
-O
/new
declaration w/othrow()
): noNULL
check before constructor init.clang (3.3 and prior/any
-O
/new
declaration w/throw()
):NULL
check before constructor init.clang (3.4.1 and later/
-O0
/new
declaration w/throw()
):NULL
check before constructor init.clang (3.4.1 and later/
-O1
and higher/new
declaration w/throw()
): noNULL
check before constructor init.clang (3.4.1 and later/
-O0
/new
declaration w/throw()
):NULL
check before constructor init.E.g., below is the x86_64 assembly for clang 3.3 vs. 5.0.0 with
-O3
:clang 3.3,
-O3 -fno-exceptions
clang 5.0.0,
-O3 -fno-exceptions
We believe there may be a bug here where clang should be doing the NULL check before initialization here regardless of the optimization level to be standard compliant.