Date: Wed, 11 May 2022 08:56:39 -0400
On 5/10/22 17:09, Myria via Std-Discussion wrote:
> What is the reasoning behind C++'s type aliasing rules prohibiting
> accessing an enum through a pointer to its underlying type? This
> differs from C and feels counter-intuitive when C++ does allow
> accessing an int from an unsigned pointer.
>
> enum Kitty { KITTY };
> enum Kitty Test(enum Kitty* x, int* y)
> {
> *x = KITTY;
> *y = -1;
> return *x;
> }
>
> This works in C when x and y alias, returning (Kitty) -1, but in C++
> is undefined behavior. Clang even enforces this rule difference
> between C++ as shown in its assembly output:
>
> https://gcc.godbolt.org/z/xqanYjs4j
>
> Loosening the restriction would also delete a bunch of mentions of
> std::byte from the Standard, because std::byte would get its magic
> properties from its underlying type instead of by commandment.
>
> Melissa
This would first be problematic because Kitty need not be able to hold
the value of -1. The values of the enumeration need only be 0 and 1, per
[dcl.enum]/8.
Second, this wouldn't permit removing the special casing of std::byte,
because just because std::byte could alias with unsigned char does not
mean that it could alias with other types.
Consider:
int i = 12;
*reinterpret_cast<std::byte*>(&i) = 42;
int is not the underlying type of std::byte, so even with the proposed
rule, this would only be permitted by virtue of the special casing of
std::byte. The strict aliasing rules are not transitive.
> What is the reasoning behind C++'s type aliasing rules prohibiting
> accessing an enum through a pointer to its underlying type? This
> differs from C and feels counter-intuitive when C++ does allow
> accessing an int from an unsigned pointer.
>
> enum Kitty { KITTY };
> enum Kitty Test(enum Kitty* x, int* y)
> {
> *x = KITTY;
> *y = -1;
> return *x;
> }
>
> This works in C when x and y alias, returning (Kitty) -1, but in C++
> is undefined behavior. Clang even enforces this rule difference
> between C++ as shown in its assembly output:
>
> https://gcc.godbolt.org/z/xqanYjs4j
>
> Loosening the restriction would also delete a bunch of mentions of
> std::byte from the Standard, because std::byte would get its magic
> properties from its underlying type instead of by commandment.
>
> Melissa
This would first be problematic because Kitty need not be able to hold
the value of -1. The values of the enumeration need only be 0 and 1, per
[dcl.enum]/8.
Second, this wouldn't permit removing the special casing of std::byte,
because just because std::byte could alias with unsigned char does not
mean that it could alias with other types.
Consider:
int i = 12;
*reinterpret_cast<std::byte*>(&i) = 42;
int is not the underlying type of std::byte, so even with the proposed
rule, this would only be permitted by virtue of the special casing of
std::byte. The strict aliasing rules are not transitive.
-- Jason Cobb
Received on 2022-05-11 12:56:42