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

2024-04-28


2751. Order of destruction for parameters for operator functions

Section: 8.8  [stmt.dcl]     Status: NAD     Submitter: Richard Smith     Date: 2020-06-10     Liaison: EWG

Subclause 8.8 [stmt.dcl] paragraph 2 specifies:

Upon each transfer of control (including sequential execution of statements) within a function from point P to point Q, all variables with automatic storage duration that are active at P and not at Q are destroyed in the reverse order of their construction. ... when a function returns, Q is after its body.

Another description of the same rule is in a note in 8.7.1 [stmt.jump.general] paragraph 2:

[Note 1: On exit from a scope (however accomplished), objects with automatic storage duration (6.7.5.4 [basic.stc.auto]) that have been constructed in that scope are destroyed in the reverse order of their construction. ... —end note]

However, 12.2.2.3 [over.match.oper] paragraph 2 specifies:

... Therefore, the operator notation is first transformed to the equivalent function-call notation as summarized in Table 18 (where @ denotes one of the operators covered in the specified subclause). However, the operands are sequenced in the order prescribed for the built-in operator (7.6 [expr.compound]).

For operator+= (for example), 7.6.19 [expr.ass] paragraph 1 requires:

... The right operand is sequenced before the left operand. ...

Now, consider an ABI with callee-cleanup and this example:

  void operator<<(A, B);
  void operator+=(A, B);
  void (*p)(A, B) = cond ? &operator<< : &operator+=;

In A() << B(), A() is sequenced before B(). In A() += B(), B() is sequenced before A(). For an ABI with callee-cleanup, this means that operator<< must destroy the B parameter before the A parameter, and operator+= must destroy the A parameter before the B parameter.

But this means we have a problem emitting a call to p(A(), B()): no order of parameter initialization guarantees that parameters are destroyed in reverse construction order.

A possible implementation strategy would be to emit a second definition of operator+= with the opposite parameter destruction order that is used when naming the function operator+=, e.g. when taking the address or using function call notation (as opposed to using operator notation).

Another alternative is to relax the rules about destruction of parameters in the reverse order of construction for the case of binary operator functions and operator new and operator delete.

Additional notes (June, 2023)

Forwarded to EWG via paper issue 1583, per decision of the CWG chair, to either affirm the intent of the rules (requiring a more involved implementation strategy as outlined above) or agree on a relaxation of the rules for the order of destruction of parameters.

EWG 2023-11-07

Not a defect; the suggested implementation strategy is viable.