Notes from the August, 2011 meeting: The proposed resolution must be updated with respect to the current
wording of the WP.
Proposed resolution (June, 2008): Add a new paragraph following 7.6.1 [expr.post] paragraph 2
as follows: Change _N4778_.7.6.1.4 [expr.pseudo] paragraph 2 as follows: Change 7.6.1.5 [expr.ref] paragraph 2 as follows: Add a new paragraph following 6.5 [basic.lookup] paragraph 2
as follows: Delete the last sentence of _N4868_.6.5.6 [basic.lookup.classref] paragraph 2:
When a postfix-expression is followed by a dot . or
arrow -> operator, the interpretation depends on the type
T of the expression preceding the operator. If the operator
is . , T shall be a scalar type or a complete class
type; otherwise, T shall be a pointer to a scalar type or a
pointer to a complete class type. When T is a (pointer to) a
scalar type, the postfix-expression to which the operator
belongs shall be a pseudo-destructor call (_N4778_.7.6.1.4 [expr.pseudo]); otherwise, it shall be a class member access
(7.6.1.5 [expr.ref]).
The left-hand side of the dot operator shall be of scalar type. The
left-hand side of the arrow operator shall be of pointer to scalar
type. This scalar type The type of the expression preceding the dot
operator, or the type to which the expression preceding the arrow
operator points, is the object type...
For the first option (dot) the type of the first expression (the
object expression)
shall be “class object” (of a
complete type) is a 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) is a pointer to a class type. In these cases, the
id-expression shall name a member of the class or of one of its
base classes.
In a pseudo-destructor-name that does not include a
nested-name-specifier, the type-names are looked up as
types in the context of the complete expression.
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.
[Adopted at the November, 2018 meeting as part of paper P1131R2.] The Standard does not completely specify how to look up the
type-name(s) in a pseudo-destructor-name (7.6.1 [expr.post] paragraph 1, _N4778_.7.6.1.4 [expr.pseudo]), and what
information it does have is incorrect and/or in the wrong place.
Consider, for instance, _N4868_.6.5.6 [basic.lookup.classref] paragraphs
2-3: 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 (or of pointer to 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. If the unqualified-id is ~ type-name, and the
type of the object expression is of a class type C (or of
pointer to a class type C ), the type-name is looked up
in the context of the entire postfix-expression and in the
scope of class C . The type-name shall refer to
a class-name. If type-name is found in both contexts,
the name shall refer to the same class type. If the type of the object
expression is of scalar type, the type-name is looked up in the
scope of the complete postfix-expression. There are at least three things wrong with this passage with
respect to pseudo-destructors: A pseudo-destructor call (_N4778_.7.6.1.4 [expr.pseudo]) is not
a “class member access”, so the statements about scalar
types in the object expressions are vacuous: the object expression in
a class member access is required to be a class type or pointer to
class type (7.6.1.5 [expr.ref] paragraph 2). On a related note, the lookup for the type-name(s) in a
pseudo-destructor name should not be described in a section entitled
“Class member access.” Although the class member access object expressions are
carefully allowed to be either a class type or a pointer to a class
type, paragraph 2 mentions only a “pointer to scalar type”
(disallowing references) and paragraph 3 deals only with a
“scalar type,” presumably disallowing pointers (although
it could possibly be a very subtle way of referring to both non-class
pointers and references to scalar types at once). The other point at which lookup of pseudo-destructors is
mentioned is 6.5.5 [basic.lookup.qual] paragraph 5: Again, this specification is in the wrong location (a
pseudo-destructor-name is not a qualified-id and
thus should not be treated in the “Qualified name lookup”
section). Finally, there is no place in the Standard that describes the
lookup for pseudo-destructor calls of the form
p->T::~T() and r.T::~T() , where p
and r are a pointer and reference to scalar, respectively.
To the extent that it gives any guidance at all,
_N4868_.6.5.6 [basic.lookup.classref] deals only with the case where the
~ immediately follows the . or -> , and
6.5.5 [basic.lookup.qual] deals only with the case where the
pseudo-destructor-name contains
a nested-name-specifier that designates a scope in which
names can be looked up. See document J16/06-0008 = WG21 N1938 for further discussion of
this and related issues, including 244,
305, 399,
and 414.
If a pseudo-destructor-name (_N4778_.7.6.1.4 [expr.pseudo])
contains a nested-name-specifier, the type-names are
looked up as types in the scope designated by the
nested-name-specifier.