This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115d. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2024-10-26
[Adopted as a DR at the November, 2019 meeting.]
The effect of a non-static data member initializer in an anonymous union is not clearly described in the current wording. Consider the following example:
struct A {
struct B {
union {
int x = 37;
};
union {
int y = x + 47; // Well-formed?
};
} a;
};
Does an anonymous union have a constructor that applies a non-static data member initializer? Or is the initialization performed by the constructor of the class in which the anonymous union appears? In particular, is the reference to x in the initializer for y well-formed or not? If the initialization of y is performed by B's constructor, there is no problem because B::x is a member of the object being initialized. If an anonymous union has its own constructor, B::x is just a member of the containing class and is a reference to a non-static data member without an object, which is ill-formed. Implementations currently appear to take the latter interpretation and report an error for that initializer.
As a further example, consider:
union { // #1 union { // #2 union { // #3 int y = 32; }; }; } a { } ;
One interpretation might be that union #3 has a non-trivial default constructor because of the initializer of y, which would give union #2 a deleted default constructor, which would make the example ill-formed.
As yet another example, consider:
union { union { int x; }; union { int y = 3; }; union { int z; }; } a { };
Assuming the current proposed resolution of issue 1502, what is the correct interpretation of this code? Is it well-formed, and if so, what initialization is performed?
Finally, consider
struct S { union { int x = 1; }; union { int y = 2; }; } s{};
Does this violate the prohibition of aggregates containing member initializers in 9.4.2 [dcl.init.aggr] paragraph 1?
See also issues 1460, 1562, 1587, and 1623.
Proposed resolution (October, 2019):
Change 11.4.3 [class.mfct.non.static] paragraph 1 as follows:
...A non-static member function may also be called directly using the function call syntax (7.6.1.3 [expr.call], 12.2.2.2 [over.match.call]) from withinthe body of a member function ofits class orofa class derived from its class, or a member thereof, as described below. .
Change 11.4.3 [class.mfct.non.static] paragraph 3 as follows:
When an id-expression (7.5.5 [expr.prim.id]) that is not part of a class member access syntax (7.6.1.5 [expr.ref]) and not used to form a pointer to member (7.6.2.2 [expr.unary.op]) is used in a member of class X in a context where this can be used (7.5.3 [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) (_N4868_.11.4.3.2 [class.this]) as the postfix-expression to the left of the . operator. [Note: If C is not X or a base class of X, the class member access expression is ill-formed. —end note]Similarly during name lookup, when an unqualified-id (7.5.5.2 [expr.prim.id.unqual]) used in the definition of a member function for class X resolves to a static member, an enumerator or a nested type of class X or of a base class of X, the unqualified-id is transformed into a qualified-id (7.5.5.3 [expr.prim.id.qual]) in which the nested-name-specifier names the class of the member function. These transformations doThis transformation does not apply in the template definition context (13.8.3.2 [temp.dep.type]). [Example:...
Delete 11.4.9 [class.static] paragraph 3:
If an unqualified-id (7.5.5.2 [expr.prim.id.unqual]) is used in the definition of a static member following the member's declarator-id, and name lookup (6.5.3 [basic.lookup.unqual]) finds that the unqualified-id refers to a static member, enumerator, or nested type of the member's class (or of a base class of the member's class), the unqualified-id is transformed into a qualified-id expression in which the nested-name-specifier names the class scope from which the member is referenced. [Note: See 7.5.5 [expr.prim.id] for restrictions on the use of non-static data members and non-static member functions. —end note]
Change 11.5.2 [class.union.anon] paragraph 1 as follows:
A union of the form
union { member-specification } ;
is called an anonymous union; it defines an unnamed type and an unnamed object of that type called an anonymous union object. Each member-declaration in the member-specification of an anonymous union shall either define a non-static data member or be a static_assert-declaration.
[Note:Nested types, anonymous unions, and functionscannotshall not be declared within an anonymous union.—end note]The names of the members...