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

2024-11-11


2557. Class member access referring to an unrelated class

Section: 7.6.1.5  [expr.ref]     Status: drafting     Submitter: Jens Maurer     Date: 2022-03-25

Consider:

  struct A {
    static int x;
  };

  struct B {
    using type = A;
  };

  int y = B().type::x;

There seems to be no requirement that the member named in a class member access actually is a member of the class of the object expression. Subclause 7.5.5.1 [expr.prim.id.general] paragraph 3 does not cover static members:

An id-expression that denotes a non-static data member or non-static member function of a class can only be used:

Suggested resolution:

  1. Change in 7.6.1.5 [expr.ref] paragraph 4 as follows:

    Otherwise, the object expression shall be of class type. The class type shall be complete unless the class member access appears in the definition of that class.
    [Note: The program is ill-formed if the result differs from that when the class is complete (6.5.2 [class.member.lookup]). —end note]
    [Note: 6.5.5 [basic.lookup.qual] describes how names are looked up after the . and -> operators. —end note] If E2 is a qualified-id, the terminal name of its nested-name-specifier shall denote the type of E1 or a base class thereof.

    [Example:

      struct A {
        static int x;
      };
    
      struct B {
        static int x;
      };
    
      struct D : B {
        using type = A;
      };
    
      int y1 = D().B::x;         // OK, B is a base class of D
      int y2 = D().type::x;      // error: A is not a base class of D
      int y3 = D::type::x;       // OK, evaluates A::x
    

    end example ]

  2. Change in 7.6.1.5 [expr.ref] bullet 6.5 as follows:

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

    An id-expression that denotes a non-static data member or non-static member function of a class can only be used:
    • as part of a class member access (7.6.1.5 [expr.ref]) in which the object expression refers to the member's class [ Footnote: ... ] or a class derived from that class, or
    • to form a pointer to member (7.6.2.2 [expr.unary.op]), or
    • if that id-expression denotes a non-static data member and it appears in an unevaluated operand.