This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 114a. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2024-04-28


2771. Transformation for unqualified-ids in address operator

Section: 11.4.3  [class.mfct.non.static]     Status: DR     Submitter: Jim X     Date: 2023-07-16

[Accepted as a DR at the March, 2024 meeting.]

Consider:

  struct A{
    int a;
    void show(){
      int* r = &a; // #1 
    }
  };

According to 11.4.3 [class.mfct.non.static] paragraph 2, the transformation to class member access does not happen for the id-expression a, because it is the unparenthesized operand of &:

When an id-expression (7.5.4 [expr.prim.id]) that is neither part of a class member access syntax (7.6.1.5 [expr.ref]) nor the un-parenthesized operand of the unary & operator (7.6.2.2 [expr.unary.op]) is used where the current class is X (7.5.2 [expr.prim.this]), if name lookup (6.5 [basic.lookup]) resolves the name in the id-expression to a non-static non-type member of some class C, and if either the id-expression is potentially evaluated or C is X or a base class of X, the id-expression is transformed into a class member access expression (7.6.1.5 [expr.ref]) using (*this) as the postfix-expression to the left of the . operator. [Note 1: If C is not X or a base class of X, the class member access expression is ill-formed. —end note] This transformation does not apply in the template definition context (13.8.3.2 [temp.dep.type]).

Proposed resolution (approved by CWG 2024-03-20):

This resolution moves the transformation to 7.5.4.1 [expr.prim.id.general], where the similar transformation for anonymous unions is already described.

  1. Change in 6.3 [basic.def.odr] paragraph 7 as follows:

    *this is odr-used if this appears as a potentially-evaluated expression (including as the result of the any implicit transformation in the body of a non-static member function to a class member access expression (11.4.3 [class.mfct.non.static] 7.5.4.1 [expr.prim.id.general])).
  2. Add a new paragraph before 7.5.4.1 [expr.prim.id.general] paragraph 2:

    If an id-expression E denotes a non-static non-type member of some class C at a point where the current class (7.5.2 [expr.prim.this]) is X and

    • E is potentially evaluated or C is X or a base class of X, and
    • E is not the id-expression of a class member access expression (7.6.1.5 [expr.ref]), and
    • if E is a qualified-id, E is not the un-parenthesized operand of the unary & operator (7.6.2.2 [expr.unary.op]),
    the id-expression is transformed into a class member access expression using (*this) as the object expression. [Note 1: If C is not X or a base class of X, the class member access expression is ill-formed. Also, if the id-expression occurs within a static or explicit object member function, the class member access is ill-formed. —end note] This transformation does not apply in the template definition context (13.8.3.2 [temp.dep.type]).

    If an id-expression E denotes a member M of an anonymous union (11.5.2 [class.union.anon]) U:

    • If U is a non-static data member, E refers to M as a member of the lookup context of the terminal name of E (after any implicit transformation to a class member access expression (11.4.3 [class.mfct.non.static])).
    • ...

  3. Change in 7.5.4.1 [expr.prim.id.general] paragraph 3 as follows:

    An id-expression that denotes a non-static data member or implicit object member function of a class can only be used:
    • as part of a class member access (7.6.1.5 [expr.ref]after any implicit transformation (see above)) in which the object expression refers to the member's class [ Footnote: This also applies when the object expression is an implicit (*this) (11.4.3 [class.mfct.non.static]).] or a class derived from that class, or
    • ...
  4. Change in 7.5.4.2 [expr.prim.id.unqual] paragraph 1 as follows:

    ... [ Note: ... Within the definition of a non-static member function, an identifier that names a non-static member is transformed to a class member access expression (11.4.3 [class.mfct.non.static]).end note]
  5. Remove 11.4.3 [class.mfct.non.static] paragraph 2, including the example:

    When an id-expression (7.5.4 [expr.prim.id]) that is neither part of a class member access syntax (7.6.1.5 [expr.ref]) nor the un-parenthesized operand of the unary & operator (7.6.2.2 [expr.unary.op]) is used where the current class is X (7.5.2 [expr.prim.this]), if name lookup (6.5 [basic.lookup]) resolves the name in the id-expression to a non-static non-type member of some class C, and if either the id-expression is potentially evaluated or C is X or a base class of X, the id-expression is transformed into a class member access expression (7.6.1.5 [expr.ref]) using (*this) as the postfix-expression to the left of the . operator. [Note 1: If C is not X or a base class of X, the class member access expression is ill-formed. —end note] This transformation does not apply in the template definition context (13.8.3.2 [temp.dep.type]). [ Example: ... ]
  6. Change in 13.8.3.2 [temp.dep.type] paragraph 6 as follows:

    [ Example: ...
      template int C<B>::g();    // OK, transformation to class member access syntax
                                 // does not occur in the template definition context; see 11.4.3 [class.mfct.non.static] 7.5.4.1 [expr.prim.id.general]
    
    -- end example ]