This question followes this one
Let's consider this example code:
struct sso
{
union{
struct {
char* ptr;
char size_r[8];
} large_str;
char short_str[16];
};
bool is_short_str() const{
return *std::launder(short_str+15)=='\0'; //UB?
}
};
If short_str
is not the active member dereferencing the pointer without std::launder
would be UB. Let's consider that the ABI is well specified and that we know that size_r[7] is at the same address as short_str[15]. Does std::launder(short_str+15)
return a pointer to size_r[7]
when short_str
is not the active member of the union?
Nota: I think this is the case because [ptr.launder]/3
A byte of storage is reachable through a pointer value that points to an object Y if it is within the storage occupied by Y, an object that is pointer-interconvertible with Y, or the immediately-enclosing array object if Y is an array element.
Let's consider that the ABI is well specified and that we know that size_r[7] is at the same address as short_str[15]
It depends entirely on what that guarantee means exactly.
A compiler is free to guarantee that
Sso.short_str[15]
can be accessed and modified and everything even when Sso.large_str
is currently active, and get exactly the semantics you expect.
Or it is free not to give that guarantee.
There is no restriction on the behavior or programs that are ill-formed or exhibit undefined behavior.
As there is no object there, &Sso.short_str[15]
isn't pointer-interconvertible with anything. An object that isn't there doesn't have the "same address" as another object.
Launder is defined in terms of a pointer to a pre-existing object. That pointer is then destroyed, and a new object with the same address is created (which is well defined). std::launder
then lets you take the pointer to the object that no longer exists and get a pointer to the existing object.
What you are doing is not that. If you took &short_str[15]
when it was engaged, you'd have a pointer to an object. And the ABI could say that this was at the same address as size_r[7]
. And now std::launder
would be in the domain of validity.
But the compiler could just go a step further and define that short_str[15]
refers to the same object as size_r[7]
even if it isn't active.
The weakest ABI guarantee that I could see being consistent with your stuff would only work if you took the address of short_str[15]
when it was active; later, you would engage the large_str
, and then you could launder from &short_str[15]
to &size_r[7]
. The strongest ABI guarantee that is consistent with your statement makes the call to std::launder
not required. Somewhere in the middle std::launder
would be required.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With