Search code examples
clanguage-lawyerstrict-aliasing

Can an object have more than one effective type?


Consider the following code on a platform where the ABI does not insert padding into unions:

union { int xi; } x;
x.xi = 1;

I believe that the second line exhibits undefined behaviour as it violates the strict aliasing rule:

  1. The object referred to by x.xi is the same object as the object referred to by x. Both are the same region of storage and the term object is defined in ISO 9899:2011 §3.15 as:

    object

    1 region of data storage in the execution environment, the contents of which can represent values

    2 NOTE When referenced, an object may be interpreted as having a particular type; see 6.3.2.1.

    As an object is not more than a region of storage, I conclude that as x and x.xi occupy the same storage, they are the same object.

  2. The effective type of x is union { int xi; } as that's the type it has been declared with. See §6.5 ¶6:

    6  The effective type of an object for an access to its stored value is the declared type of the object, if any.87) If a value is stored into an object having no declared type through an lvalue having a type that is not a character type, then the type of the lvalue becomes the effective type of the object for that access and for subsequent accesses that do not modify the stored value. If a value is copied into an object having no declared type using memcpy or memmove, or is copied as an array of character type, then the effective type of the modified object for that access and for subsequent accesses that do not modify the value is the effective type of the object from which the value is copied, if it has one. For all other accesses to an object having no declared type, the effective type of the object is simply the type of the lvalue used for the access.


    87) Allocated objects have no declared type.

    By the wording of ¶6 it is also clear that each object can only have one effective type.

  3. In the statement x.xi I access x through the lvalue x.xi typed int. This is not one of the types listed in §6.5 ¶7:

    7 An object shall have its stored value accessed only by an lvalue expression that has one of the following types:88)

    • a type compatible with the effective type of the object,
    • a qualified version of a type compatible with the effective type of the object,
    • a type that is the signed or unsigned type corresponding to the effective type of the object,
    • a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object,
    • an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or
    • a character type.

    88) The intent of this list is to specify those circumstances in which an object may or may not be aliased.

  4. Therefore, the second line exhibits undefined behaviour.

As this interpretation is clearly wrong, where lies my misreading of the standard?


Solution

  • The error is thinking that x and x.xi are the same object.

    The union is an object and it contains member objects1. They are distinct objects, each with it's own type.


    1. (Quoted from: ISO/IEC 9899:20x1 6.2.5 Types 20)
    A union type describes an overlapping nonempty set of member objects, each of which has an optionally specified name and possibly distinct type.