Do memory layout related specifications in ABI standards generally apply only across ABI boundaries or also e.g. within a translation unit, or if that is not the case, do compilers generally make such additional guarantees?
If "generally" is too broad, consider e.g. GCC/Clang with the System V x64 and Itanium C++ ABIs.
Here are two examples for what I mean:
The System V x64 ABI specifies that arrays of size at least 16 bytes have an alignment of at least 16 bytes, even if the alignment of the element type is smaller and are therefore aligned stricter than
alignof
would suggest. It also specifies that the alignment oflong double
is16
. So is the following function that has undefined behavior under the C++ standard if called, safe to use under the System V x86 ABI, even though thestorage
array is never exposed across translation unit boundaries?void f() { char storage[16]; // Only guaranteed to have alignment `1` by the C++ standard. using T = long double; auto p = new(storage) T; }
The Itanium C++ ABI specifies the layout of classes. For example:
#include<new> struct A { int i; virtual ~A() {} }; struct B : A { int j; }; void f() { B b; std::launder(reinterpret_cast<A*>(&b))->i = 1; }
f
when called has undefined behavior under the C++ standard, becauseB
andA
are not standard-layout and therefore it is unspecified whether theA
subobject is located at the same address asb
, which causes undefined behavior on thestd::launder
if it doesn't. Under the Itanium C++ ABI however it is guaranteed that theA
subobject has the same address asb
and therefore thestd::launder
will succeed. So under the Itanium C++ ABI, is this safe, even thoughb
is never passed over translation unit boundaries?
I assume that both my examples are safe, but is this specified, either in the referenced standards or as by policies of the compilers?