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


2761. Implicitly invoking the deleted destructor of an anonymous union member

Section: 11.4.7  [class.dtor]     Status: DRWP     Submitter: Corentin Jabot     Date: 2023-07-11

[Accepted as a DR at the November, 2023 meeting.]

Consider:

  struct S{
    ~S() {}
  };

  struct A {
    union {
      S arr_;
    };
    ~A(); // user-provided!
  };

  auto foo() {
    return A{S()};
  }

Does the destructor of A attempt to destroy the (unnamed) data member that is the anonymous union? The latter has a deleted destructor per 11.4.7 [class.dtor]. For the default constructor, 11.9.3 [class.base.init] paragraph 9.2 prevents the corresponding construction.

Proposed resolution (approved by CWG 2023-08-25):

  1. Change in 9.4.2 [dcl.init.aggr] paragraph 9 as follows:

    The destructor for each element of class type other than an anonymous union member is potentially invoked (11.4.7 [class.dtor]) from the context where the aggregate initialization occurs
  2. Change in 11.4.7 [class.dtor] paragraph 13 as follows:

    After executing the body of the destructor and destroying any objects with automatic storage duration allocated within the body, a destructor for class X calls the destructors for X's direct non-variant non-static data members other than anonymous unions, the destructors for X's non-virtual direct base classes and, if X is the most derived class (11.9.3 [class.base.init]), its destructor calls the destructors for X's virtual base classes. All destructors are called as if they were referenced with a qualified name, that is, ignoring any possible virtual overriding destructors in more derived classes. Bases and members are destroyed in the reverse order of the completion of their constructor (see 11.9.3 [class.base.init]).
  3. Change in 14.3 [except.ctor] paragraph 3 as follows:

    A subobject is known to be initialized if it is not an anonymous union member and its initialization is specified
    • in 11.9.3 [class.base.init] for initialization by constructor,
    • in 11.4.5.3 [class.copy.ctor] for initialization by defaulted copy/move constructor,
    • in 11.9.4 [class.inhctor.init] for initialization by inherited constructor,
    • in 9.4.2 [dcl.init.aggr] for aggregate initialization,
    • in 7.5.6.3 [expr.prim.lambda.capture] for the initialization of the closure object when evaluating a lambda-expression,
    • in 9.4.1 [dcl.init.general] for default-initialization, value-initialization, or direct-initialization of an array.