Search code examples
cconcurrencylanguage-lawyerc11stdatomic

Assigning pointers to atomic type to pointers to non atomic type


Is the behavior of this code well-defined?

#include <stdatomic.h>

const int test = 42;
const int * _Atomic atomic_int_ptr;
atomic_init(&atomic_int_ptr, &test);
const int ** int_ptr_ptr = &atomic_int_ptr;
printf("int = %d\n", **int_ptr_ptr); //prints int = 42

I assigned a pointer to atomic type to a pointer to non-atomic type (the types are the same). Here are my thoughts of this example:

The Standard explicitly specify distinction of const, volatile and restrict qualifiers from the _Atomic qualifier 6.2.5(p27):

this Standard explicitly uses the phrase ‘‘atomic, qualified or unqualified type’’ whenever the atomic version of a type is permitted along with the other qualified versions of a type. The phrase ‘‘qualified or unqualified type’’, without specific mention of atomic, does not include the atomic types.

Also the compatibility of qualified types is defined as 6.7.3(p10):

For two qualified types to be compatible, both shall have the identically qualified versionof a compatible type; the order of type qualifiers within a list of specifiers or qualifiers does not affect the specified type.

Combining the quotes cited above I concluded that atomic and non-atomic types are compatible types. So, applying the rule of simple assigning 6.5.16.1(p1) (emp. mine):

the left operand has atomic, qualified, or unqualified pointer type, and (considering the type the left operand would have after lvalue conversion) both operands are pointers to qualified or unqualified versions of compatible types, and the type pointed to by the left has all the qualifiers of the type pointed to by the right;

So I concluded that the behavior is well defined (even in spite of assigning atomic type to a non-atomic type).

The problem with all that is that applying the rules above we can also conclude that simple assignment a non-atomic type to an atomic type is also well defined which is obviously not true since we have a dedicated generic atomic_store function for that.


Solution

  • 6.2.5p27:

    Further, there is the _Atomic qualifier. The presence of the _Atomic qualifier designates an atomic type. The size, representation, and alignment of an atomic type need not be the same as those of the corresponding unqualified type. Therefore, this Standard explicitly uses the phrase ''atomic, qualified or unqualified type'' whenever the atomic version of a type is permitted along with the other qualified versions of a type. The phrase ''qualified or unqualified type'', without specific mention of atomic, does not include the atomic types.

    I think this should make it clear that atomic-qualified types are not deemed compatible with qualified or unqualified versions of the types they're based on.