Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it a strict aliasing violation to alias a struct as its first member?

Tags:

Sample code:

struct S { int x; };  int func() {      S s{2};      return (int &)s;    // Equivalent to *reinterpret_cast<int *>(&s) } 

I believe this is common and considered acceptable. The standard does guarantee that there is no initial padding in the struct. However this case is not listed in the strict aliasing rule (C++17 [basic.lval]/11):

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:

  • (11.1) the dynamic type of the object,
  • (11.2) a cv-qualified version of the dynamic type of the object,
  • (11.3) a type similar (as defined in 7.5) to the dynamic type of the object,
  • (11.4) a type that is the signed or unsigned type corresponding to the dynamic type of the object,
  • (11.5) a type that is the signed or unsigned type corresponding to a cv-qualified version of the dynamic type of the object,
  • (11.6) an aggregate or union type that includes one of the aforementioned types among its elements or non-static data members (including, recursively, an element or non-static data member of a subaggregate or contained union),
  • (11.7) a type that is a (possibly cv-qualified) base class type of the dynamic type of the object,
  • (11.8) a char, unsigned char, or std::byte type.

It seems clear that the object s is having its stored value accessed.

The types listed in the bullet points are the type of the glvalue doing the access, not the type of the object being accessed. In this code the glvalue type is int which is not an aggregate or union type, ruling out 11.6.

My question is: Is this code correct, and if so, under which of the above bullet points is it allowed?

like image 903
M.M Avatar asked May 17 '18 04:05

M.M


People also ask

What is the strict aliasing rule and why do we care?

"Strict aliasing is an assumption, made by the C (or C++) compiler, that dereferencing pointers to objects of different types will never refer to the same memory location (i.e. alias each other.)"

What is aliasing in compiler?

An alias occurs when different variables point directly or indirectly to a single area of storage. Aliasing refers to assumptions made during optimization about which variables can point to or occupy the same storage area.

What is pointer aliasing in C?

Pointer aliasing is a hidden kind of data dependency that can occur in C, C++, or any other language that uses pointers for array addresses in arithmetic operations. Array data identified by pointers in C can overlap, because the C language puts very few restrictions on pointers.


1 Answers

The behaviour of the cast comes down to [expr.static.cast]/13;

A prvalue of type “pointer to cv1 void” can be converted to a prvalue of type “pointer to cv2 T”, where T is an object type and cv2 is the same cv-qualification as, or greater cv-qualification than, cv1. If the original pointer value represents the address A of a byte in memory and A does not satisfy the alignment requirement of T , then the resulting pointer value is unspecified. Otherwise, if the original pointer value points to an object a, and there is an object b of type T (ignoring cv-qualification) that is pointer-interconvertible with a, the result is a pointer to b. Otherwise, the pointer value is unchanged by the conversion.

The definition of pointer-interconvertible is:

Two objects a and b are pointer-interconvertible if:

  • they are the same object, or
  • one is a union object and the other is a non-static data member of that object, or
  • one is a standard-layout class object and the other is the first non-static data member of that object, or, if the object has no non-static data members, the first base class subobject of that object, or
  • there exists an object c such that a and c are pointer-interconvertible, and c and b are pointer-interconvertible.

So in the original code, s and s.x are pointer-interconvertible and it follows that (int &)s actually designates s.x.

So, in the strict aliasing rule, the object whose stored value is being accessed is s.x and not s and so there is no problem, the code is correct.

like image 79
M.M Avatar answered Oct 14 '22 00:10

M.M