Title
Order of destruction for parameters for operator functions
Status
nad
Section
8.8 [stmt.dcl]
Submitter
Richard Smith

Created on 2020-06-10.00:00:00 last changed 5 months ago

Messages

Date: 2023-06-15.00:00:00

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.

Date: 2020-06-10.00:00:00

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.

History
Date User Action Args
2023-11-07 22:08:45adminsetstatus: open -> nad
2023-06-22 09:39:22adminsetmessages: + msg7338
2020-06-10 00:00:00admincreate