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

2024-03-20


1091. Inconsistent use of the term “object expression”

Section: 7.6.4  [expr.mptr.oper]     Status: C++11     Submitter: Tom Plum     Date: 2010-07-10

[Voted into the WP at the March, 2011 meeting.]

The description of class member access expressions in 7.6.1.5 [expr.ref] paragraph 2 defines the terms “object expression” and “pointer expression:”

For the first option (dot) the type of the first expression (the object expression) shall be “class object” (of a complete type). For the second option (arrow) the type of the first expression (the pointer expression) shall be “pointer to class object” (of a complete type).

(Note in passing that the phrase “class object” seems very odd when describing a type.) The rest of that section is based on the equivalence of the expression E1->E2 to (*(E1)).E2 and thus is phrased only in terms of “object expression.” This terminology appears to have been misapplied in other parts of the Standard, using the term “object expression” to refer both to class types and pointers to class types. The most egregious of these is 7.6.4 [expr.mptr.oper] paragraph 4, describing the operands of a pointer-to-member expression:

The first operand is called the object expression. If the dynamic type of the object expression does not contain the member to which the pointer refers, the behavior is undefined.

The dynamic type of the first operand in the ->* case is a pointer type, not a class type, so it cannot “contain the member to which the pointer refers.” Another example is _N4868_.6.5.6 [basic.lookup.classref], describing the lookup in a class member access expression. The first paragraph uses the term consistently with its use in 7.6.1.5 [expr.ref], but paragraph 2 reads:

If the id-expression in a class member access (7.6.1.5 [expr.ref]) is an unqualified-id, and the type of the object expression is of a class type C, the unqualified-id is looked up in the scope of class C. If the type of the object expression is of pointer to scalar type, the unqualified-id is looked up in the context of the complete postfix-expression.

Paragraph 7 gets it right:

...in the context of the class of the object expression (or the class pointed to by the pointer expression).

Another misapplication of the term occurs in 7.6.1.3 [expr.call] paragraph 1:

...the call is as a member of the object pointed to or referred to by the object expression (7.6.1.5 [expr.ref], 7.6.4 [expr.mptr.oper])... its final overrider (11.7.3 [class.virtual]) in the dynamic type of the object expression is called. [Note: the dynamic type is the type of the object pointed or referred to by the current value of the object expression...

Here again we have the idea that an object expression can “point to” an object.

Another minor complication is that Clause 7 [expr] paragraph 7 has a separate definition for the (hyphenated) term “object-expression:”

An expression designating an object is called an object-expression.

This term is used several times in the Standard, apparently interchangeably with the non-hyphenated version defined in 7.6.1.5 [expr.ref]; for example, _N4567_.5.1.1 [expr.prim.general] bullet 10.1 mentions

a class member access (7.6.1.5 [expr.ref]) in which the object-expression refers to the member's class

using the term defined in Clause 7 [expr] paragraph 7 but linking it with 7.6.1.5 [expr.ref].

These uses of “object expression” and “object-expression” need to be made consistent, especially the reference in 7.6.4 [expr.mptr.oper] that implies that the dynamic type of a pointer is that of the complete object to which it points.

Proposed resolution (February, 2011):

  1. Change _N4868_.6.5.6 [basic.lookup.classref] paragraph 2 as follows:

  2. ...If the type of the object expression is of pointer to scalar type For a pseudo-destructor call (_N4778_.7.6.1.4 [expr.pseudo]), the unqualified-id is looked up in the context of the complete postfix-expression.
  3. Delete Clause 7 [expr] paragraph 7

  4. An expression designating an object is called an object-expression.
  5. Change _N4567_.5.1.1 [expr.prim.general] paragraph 10 as follows:

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

  7. Change 7.6.1.3 [expr.call] paragraph 1 as follows:

  8. ...For a member function call, the postfix expression shall be an implicit (11.4.3 [class.mfct.non.static], 11.4.9 [class.static]) or explicit class member access (7.6.1.5 [expr.ref]) whose id-expression is a function member name, or a pointer-to-member expression (7.6.4 [expr.mptr.oper]) selecting a function member; the call is as a member of the class object pointed to or referred to by the object expression (7.6.1.5 [expr.ref], 7.6.4 [expr.mptr.oper])... [Note: the dynamic type is the type of the object pointed or referred to by the current value of the object expression. 11.9.5 [class.cdtor] describes the behavior of virtual function calls when the object-expression object expression refers to an object under construction or destruction. —end note]
  9. Change 7.6.1.5 [expr.ref] paragraph 2 as follows:

  10. For the first option (dot) the type of the first expression (the object expression) shall be “class object” (of a complete type) have complete class type. For the second option (arrow) the type of the first expression (the pointer expression) shall be “pointer to class object” (of a complete type) have pointer to complete class type. The expression E1->E2 is converted to the equivalent form (*(E1)).E2; the remainder of 7.6.1.5 [expr.ref] will address only the first option (dot) [Footnote: Note that (*(E1)) is an lvalue. —end footnote]. In these cases either case, the id-expression shall name a member of the class or of one of its base classes...
  11. Change 7.6.1.5 [expr.ref] paragraph 3 as follows:

  12. If E1 has the type “pointer to class X,” then the expression E1->E2 is converted to the equivalent form (*(E1)).E2; the remainder of 7.6.1.5 [expr.ref] will address only the first option (dot)66. Abbreviating object-expressionpostfix-expression.id-expression as E1.E2, then the E1 is called the object expression. The type and value category of this expression E1.E2 are determined as follows...
  13. Change 7.6.4 [expr.mptr.oper] paragraph 3 as follows:

  14. ...The result is an object or a function of the type specified by the second operand. The expression E1->*E2 is converted into the equivalent form (*(E1)).*E2.
  15. Change 7.6.4 [expr.mptr.oper] paragraph 4 as follows:

  16. The first operand Abbreviating pm-expression.*cast-expression as E1.*E2, E1 is called the object expression. If the dynamic type of the object expression E1 does not contain the member to which the pointer E2 refers, the behavior is undefined.
  17. Change 7.6.4 [expr.mptr.oper] paragraph 6 as follows:

  18. ...In a .* expression whose object expression is an rvalue, the program is ill-formed if the second operand is a pointer to member function with ref-qualifier &. In a ->* expression or in a .* expression whose object expression is an lvalue, the program is ill-formed if the second operand is a pointer to member function with ref-qualifier &&. The result of a .* expression whose second operand is a pointer to a data member is of the same value category (7.2.1 [basic.lval]) as its first operand. The result of a .* expression whose second operand is a pointer to a member function is a prvalue. The result of an ->* expression is an lvalue if its second operand is a pointer to data member and a prvalue otherwise. If the second operand is the null pointer to member value (7.3.13 [conv.mem]), the behavior is undefined.
  19. Change 11.4.9 [class.static] paragraph 2 as follows:

  20. ...A static member may be referred to using the class member access syntax, in which case the object-expression object expression is evaluated...
  21. Change 11.9.5 [class.cdtor] paragraph 4 as follows:

  22. ...If the virtual function call uses an explicit class member access (5.2.5) and the object-expression object expression refers to the object under construction...
  23. Change 13.3 [temp.names] paragraph 4 as follows:

  24. When the name of a member template specialization appears after . or -> in a postfix-expression or after a nested-name-specifier in a qualified-id, and the object or pointer expression of the postfix-expression or...

[Note: although the current text of _N4868_.6.5.6 [basic.lookup.classref] paragraph 7 mentions the phrase “pointer expression,” that wording will be replaced by issue 1111 or issue 1220 and is thus not addressed here.]