This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 118d. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2025-10-27
Subclause 6.10.3.4 [basic.start.term] paragraph 3 conflates the idea of completing a constructor (which, in theory, can include the non-delegating constructor called by a delegating constructor) and completing dynamic initialization of an object (possibly including the destruction of any temporaries). Additional clarity over what happens for block-scope statics initialized as part of executing destructor calls for temporaries of the initialization construct is needed.
Furthermore, the subject paragraph talks about the destructor of objects (of which arrays of class objects have none) and is incompatible with the treatment (consistent with the 2024-11-22 proposed resolution to issue 2929, "Lifetime of trivially-destructible static or thread-local objects") where cleanup registration does not happen individually for the destruction of array elements.
Also, the word "during" in the last sentence of the subject paragraph seems imprecise in the presence of asynchronous execution.
Additionally, without changes like the proposed resolution to issue 2929, that last sentence raises questions as to whether the destruction of subobjects occurs when exit is called during initialization of a complete class object of static storage duration.
Suggested resolution:
Change in 6.10.3.4 [basic.start.term] paragraph 3 as follows:
If thecompletion of the constructor or dynamic initializationdeemed construction (9.5.1 [dcl.init.general]) ofana complete object with static storage duration strongly happens before that of another, the completion of thedestructordestruction of the second is sequenced before the initiation of thedestructordestruction of the first. If thecompletion of the constructor or dynamic initializationdeemed construction ofana complete object with thread storage duration is sequenced before that of another, the completion of thedestructordestruction of the second is sequenced before the initiation of thedestructordestruction of the first. If an object is initialized statically, the object is destroyed in the same order as if the object was dynamically initialized.For an object of array or class type, all subobjects of that object are destroyed before any block variable with static storage duration initialized during the construction of the subobjects is destroyed.If the destruction of an object with static or thread storage duration exits via an exception, the function std::terminate is called (14.6.2 [except.terminate]). [ Example: In the following program, the elements of a are destroyed, followed by dt, and finally the two BTemp objects:struct DTemp { ~DTemp(); }; struct Temp { ~Temp() { static DTemp dt; } }; struct BTemp { ~BTemp(); }; struct A { const BTemp &tb; ~A(); }; A a[] = { (Temp(), BTemp()), BTemp() }; int main() {}-- end example ]
Change in 6.10.3.4 [basic.start.term] paragraph 5 as follows:
If thecompletion of the initializationdeemed construction ofana complete object with static storage duration strongly happens before a call to std::atexit (see <cstdlib>, 17.5 [support.start.term]), the call to the function passed to std::atexit is sequenced before thecall to the destructor forinitiation of the destruction of the object. If a call to std::atexit strongly happens before thecompletion of the initializationdeemed construction ofana complete object with static storage duration, thecall to the destructor forcompletion of the destruction of the object is sequenced before the call to the function passed to std::atexit. If a call to std::atexit strongly happens before another call to std::atexit, the call to the function passed to the second std::atexit call is sequenced before the call to the function passed to the first std::atexit call.
Change in 9.5.1 [dcl.init.general] paragraph 22
An object whose initialization has completedThe deemed construction of an object occurs when its initialization (including, if the initialization is a full-expression, the destruction of associated temporaries) completes. The object is deemed to be constructed, even if the object is of non-class type or no constructor of the object's class is invoked for the initialization. [Note 9: Such an object might have been value-initialized or initialized by aggregate initialization (9.5.2 [dcl.init.aggr]) or by an inherited constructor (11.9.4 [class.inhctor.init]). —end note] Destroying an object of class type invokes the destructor of the class. Destroying a scalar type has no effect other than ending the lifetime of the object (6.8.4 [basic.life]). Destroying an array destroys each element in reverse subscript order.