This question refers to the current C++20 draft. The quoted passages have been slightly modified from previous standard iterations, but not in relevant ways as far as I know.
I am looking for clarification on the the terms "aliasing violation" or "strict aliasing violation".
My previous impression was that these terms refer specifically to violations of the standard paragraph [basic.lval]/11:
If a program attempts to access ([defns.access]) the stored value of an object through a glvalue whose type is not similar ([conv.qual]) to one of the following types the behavior is undefined:
- the dynamic type of the object,
- a type that is the signed or unsigned type corresponding to the dynamic type of the object, or
- a
char
,unsigned char
, orstd::byte
type.If a program invokes a defaulted copy/move constructor or copy/move assignment operator for a union of type U with a glvalue argument that does not denote an object of type cv U within its lifetime, the behavior is undefined. [ Note: Unlike in C, C++ has no accesses of class type. — end note ]
The note at the end is clarified further through notes and normative references in [defns.access] to mean that only scalar types can be accessed. See also the notes section on the related cppreference page.
Therefore it seems to me that the paragraph can never apply to access of non-static members of classes through the wrong class type and that "(strict) aliasing violation" cannot apply e.g. to the following example:
struct A { void f() {}; int a; };
struct B { void f() {}; int a; };
int main() {
auto a = new A; // aligned for all non-overaligned types
B& b = reinterpret_cast<B&>(*a);
b.f(); //1
b.a = 1; //2
}
Assume that sizeof(A) == sizeof(B)
and offsetof(A, a) == offsetof(B, b)
(although I don't think either makes a difference and the latter is trivial because the classes are standard-layout). Another variation of interest would be struct A { };
, but again I think there won't be a difference.
In the case of b.f()
there is no access to any scalar object at all. According to [expr.ref], in the latter case the referenced object is supposed to be the data member a
of the B
object referenced by b
, but since that clearly doesn't exist, I suppose forming the member access might already be undefined behavior?
Both //1
and //2
should clearly be undefined behavior in some way though. I think //1
violates [class.mfct.non-static]/2, but I am not exactly sure which paragraph //2
violates exactly.
Which standard paragraphs do the two lines //1
and //2
violate exactly and is this violation considered to be covered by the terms "(strict) aliasing violation" as well?