As per C++17 standard, §6.10 item 8:
8 If a program attempts to access the stored value of an object through a glvalue of other than one of the following types the behavior is undefined:
(8.1) — the dynamic type of the object,
...
(8.7) — a type that is a (possibly cv-qualified) base class type of the dynamic type of the object,
(8.8) — a char, unsigned char, or std::byte type.
I understand that both downcast (8.1) and upcast (8.7) do respect strict aliasing rule. Is this correct ? So, the following code should be legitimate; right ?
struct A { int x = 1; };
struct B : A { int y = 2; };
B bb;
A* ab = &bb;
auto x = static_cast<A&>(bb).x; // ok
auto y = static_cast<B*>(ab)->y; // ok
Now, reading the C++20 Standard, §7.2.1 item 11 (I only have the draft, though), I am surprised that point (8.7) relating to the type of the object's base class has simply disappeared !
11 If a program attempts to access (3.1) the stored value of an object through a glvalue whose type is not similar (7.3.5) to one of the following types the behavior is undefined:
(11.1) — the dynamic type of the object,
(11.2) — a type that is the signed or unsigned type corresponding to the dynamic type of the object, or
(11.3) — a char, unsigned char, or std::byte type.
I find it hard to imagine that upcast violates the rule from C++20 onwards. Does it ? If not, what rule in the standard states that it does not ?
EDIT:
My question has been marked as duplicate of What happened to the "aggregate or union type that includes one of the aforementioned types" strict aliasing rule?
Well, this is true that the other question answers why 8.4 to 8.8 disappeared from C++17 §6.10, however it does not answer my 2nd question:
What rule of the standard states that accessing an object through a base type of its class does not violate strict aliasing ?