https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109442
--- Comment #16 from Richard Smith <richard-gccbugzilla at metafoo dot co.uk> --- (In reply to Richard Biener from comment #15) > I was specifically looking at C++20 7.6.2.7/10 to /14 (but maybe also > others and of course the relevant parts of the delete expression). In > particular the extra leeway the standard provides to new/delete _expressions_ > vs. calls of the global replaceable operators directly - do the > __builtin_operator_{new,delete} in this regard behave like new/delete > _expressions_ or like direct calls to the operators? They permit the same optimizations as new/delete expressions. The sections of the C++ standard that you referred to are what the documentation for the builtins means when it says: "[__builtin_operator_new] allows certain optimizations that the C++ standard does not permit for a direct function call to ::operator new (in particular, removing new / delete pairs and merging allocations)" > Do the builtins call one of the replaceable global new/delete operators > and thus users can reliably override them? If the implementation doesn't provide storage in some other way, optimize away the allocation, or merge it with another allocation, then yes, the storage is obtained by calling the corresponding replaceable global new/delete operators. Per the documentation: "A call to __builtin_operator_new(args) is exactly the same as a call to ::operator new(args), except that [text quoted above]" > How do the builtins behave during constexpr evaluation? new/delete > expressions have their behavior documented in the standard. They behave exactly like a direct call to the replaceable global allocation function. In Clang's implementation, direct calls to ::operator new and ::operator delete are permitted within calls to std::allocator<T>::allocate and std::allocator<T>::deallocate during constant evaluation, and are treated as allocating or deallocating arrays of T; consequently, calls to __builtin_operator_new and __builtin_operator_delete are permitted in the same contexts. In all other contexts, Clang rejects such calls, because the callee is not declared `constexpr`.