Document Number:
    N2209
    
    Submitter:
    Martin Sebor
    
    Submission Date:
    March 26, 2018
    
    Subject:
    Atomic Pointers In Expressions
    
    Summary
    
      The current specification makes it a constraint violation to use
      pointers to objects of atomic types in certain contexts where they
      can, and in our view should be permitted.  The following paragraphs
      detail the restriction and the contexts in which it applies.
    
    
      In §6.2.5 Types, paragraph 27 reads:
    
    
      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.
    
    
      The only occurrences of the phrase "atomic, qualified or unqualified
      type" in § 6.5 Expressions are in the following subsections:
      
	- 
	  §6.5.2.3 Structure and union members,
	
 
	- 
	  §6.5.2.4 Postfix increment and decrement operators,
	
 
	- 
	  §6.5.3.1 Prefix increment and decrement operators,
	
 
	- 
	  §6.5.4 Cast operators,
	
 
	- 
	  §6.5.16.1 Simple assignment — as the left operand,
	
 
	- §6.5.16.2 Compund assignment — also as the left.
	  operand
	
 
      
    
    
      Of the remaining contexts, the following expressions specify among
      their constraints that one or both pointer operands shall be "qualified
      or unqualified" versions of a type without mentioning atomic types:
      
	- 
	  §6.5.6 Additive operators,
	
 
	- 
	  §6.5.8 Relational operators,
	
 
	- 
	  §6.5.9 Equality operators,
	
 
	- 
	  §6.5.15 Conditional operators,
	
 
	- 
	  §6.5.16.1 Simple assignment — as the right operand.
	
 
      
    
    
      Consequently, pointers to objects of atomic types are not valid
      operands in the expressions above.  We believe these constraints are
      both unnecessary and unintended.  For example, there is no reason for
      the following code to be rejected:
	extern _Atomic int a[2], *p;
	a[0] = a == p ? a[1] : a[0];
      No implementation is known to enforce the constraint in these contexts.
    
    
      The Simple assignment constraints are worth discussing in more detail.
      The relevant constraints are as follows:
    
    
      One of the following shall hold:112)
      …
      — 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;
      — the left operand has atomic, qualified, or unqualified pointer
      type, and (considering the type the left operand would have after lvalue
      conversion) one operand is a pointer to an object type, and the other is
      a pointer to a qualified or unqualified version of void, and
      the type pointed to by the left has all the qualifiers of the type
      pointed to by the right;
      …
    
    
      Atomic-qualified void types are permitted in paragraph 3
      of §6.7.3 Type qualifiers:
    
    
      The type modified by the _Atomic qualifier shall not be
      an array type or a function type.
    
    
      A strict (perhaps pedantic?) reading of the constraints implies that
      although it is valid to assign an unqualified pointer to an
      atomic-qualified pointer object it is a constraint violation to assign
      an _Atomic pointer to an object of a compatible pointer type
      because the qualifiers allowed for the right operand do not include
      _Atomic (pursuant to §6.2.5 Types, paragraph 27
      the phrase "qualified or unqualified type", without specific mention
	of atomic, does not include the atomic types).  By way of
      an example:
      
	extern T *p;
	_Atomic T *ap, *aq;
	ap = p;                // unsafe but valid
	aq = ap;               // safe but constraint violation
      The first assignment is unsafe because (unlike with other qualifiers)
      accessing a non-atomic object using an lvalue of an atomic-qualified
      type doesn't have defined semantics.
    
    
      The above is so regardless of the type T.  Provided
      atomic-qualified void pointers are intended to be allowed
      (not all implementations that support atomics accept them), this also
      affects the second bullet.  Otherwise, if atomic-qualified void
      pointers are not intended to be permitted then only the fisrst bullet
      is affected.  In that case, however, paragraph 3 of
      §6.7.3 Type qualifiers needs to be adjusted to exclude
      void from the set of types that may not be modified by
      the _Atomic qualifier.
    
    Proposed Resolution
    
      We propose to allow pointers to objects of atomic types in the contexts
      above.  Specifically, we propose to make the following changes.
    
    
      In §6.5.6 Additive operators make changes in paragraph 3
      as indicated below.
    
    
      For subtraction, one of the following shall hold:
      — both operands have arithmetic type;
      — both operands are pointers to atomic, qualified
      or unqualified versions of compatible complete object types; or
      — the left operand is a pointer to a complete object type and
      the right operand has integer type.
    
    
      In §6.5.8 Relational operators make changes in paragraph 2
      as indicated below.
    
    
      One of the following shall hold:
      — both operands have real type; or
      — both operands are pointers to atomic, qualified
      or unqualified versions of compatible object types.
    
    
      In §6.5.9 Equality operators make changes in paragraph 2
      as indicated below.
    
    
      One of the following shall hold:
      — both operands have arithmetic type;
      — both operands are pointers to atomic, qualified
      or unqualified versions of compatible types;
      …
    
    
      In §6.5.15 Conditional operator make changes in paragraph 3
      as indicated below.
    
    
      One of the following shall hold for the second and third operands:
      …
      — both operands are pointers to atomic, qualified
      or unqualified versions of compatible types;
      — one operand is a pointer and the other is a null pointer constant;
      or
      — one operand is a pointer to an object type and the other is
      a pointer to a qualified or unqualified version of void.
    
    
      In §6.5.16.1 Simple assignment make changes in paragraph 1
      as indicated below.
    
    
      One of the following shall hold:112)
      …
      — 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 atomic, 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
      ,and either both operands have an atomic-qualified pointer type
	or neither does;
      — the left operand has atomic, qualified, or unqualified pointer
      type, and (considering the type the left operand would have after lvalue
      conversion) one operand is a pointer to an object type, and the other is
      a pointer to an atomic,  qualified or unqualified version of
      void, and the type pointed to by the left has all the qualifiers
      of the type pointed to by the right, and either both operands have
	an atomic-qualified pointer type or neither does;
      …