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
alignofwould suggest. It also specifies that the alignment oflong doubleis16. 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 thestoragearray 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; }fwhen called has undefined behavior under the C++ standard, becauseBandAare not standard-layout and therefore it is unspecified whether theAsubobject is located at the same address asb, which causes undefined behavior on thestd::launderif it doesn't. Under the Itanium C++ ABI however it is guaranteed that theAsubobject has the same address asband therefore thestd::launderwill succeed. So under the Itanium C++ ABI, is this safe, even thoughbis 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?