#include <memory>
int main() {
constexpr auto v = [] {
std::allocator<char> a;
auto x = a.allocate(10);
x[2] = 1;
auto r = x[2];
a.deallocate(x, 10);
return r;
}();
return v;
}
Is the program ill-formed? Clang thinks so, GCC and MSVC don't: https://godbolt.org/z/o3bcbxKWz
Removing the constexpr I think the program is not ill-formed and has well-defined behavior:
By [allocator.members]/5 the call a.allocate(10) starts the lifetime of the char[10] array it allocates storage for.
According to [intro.object]/13 starting the lifetime of an array of type char implicitly creates objects in its storage.
Scalar types such as char are implicit lifetime types. ([basic.types.general]/9
[intro.object]/10 then says that objects of type char are created in the storage of the char[10] array (and their lifetime started) if that can give the program defined behavior.
Without beginning the lifetime of the char object at x[2], the program without constexpr would have undefined behavior due to the write to x[2] outside its lifetime, but the char object can be implicitly created due to the arguments above, making the program behavior well-defined to exit with status 1.
With constexpr, I am wondering if the program is ill-formed or not. Does implicit object creation apply in constant expressions?
According to [intro.object]/10 objects are implicitly created to give the program defined behavior, but does being ill-formed count as defined behavior?
If not, then the program should not be ill-formed because of implicit creation of the char object for x[2].
If yes, then the next question would be if it is unspecified whether the program is ill-formed or not, because [intro.object]/10 also says that it is unspecified which objects are implicitly created if multiple sets can give the program defined behavior.
From a language design perspective I would expect that implicit object creation is not supposed to happen in constant expressions, because verifying the (non-)existence of a set of objects making the constant expression valid is probably infeasible for a compiler in general.