<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/157500>157500</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            `operator delete(void *, ...)` should not be treated as an usual deallocation function
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          ckwastra
      </td>
    </tr>
</table>

<pre>
    Test code ([CE](https://godbolt.org/z/1vzv9vfE7)):

```cpp
#include <cstddef>

struct S {
  S();
  void *operator new(std::size_t, ...); // OK
  // ✅ Clang: OK
  // ✅   EDG: OK
  // ✅   GCC: OK
  // ❌  MSVC: error C2829: 'operator delete' cannot have a variable
  //                        parameter list
  void operator delete(void *, ...);
};
void test() {
  auto p = new (1, 2, 3) S; // OK
  // ❌ Clang: OK
  // ✅   GCC: error: no suitable 'operator delete' for 'test1::S'
  // ✅   EDG: error: no appropriate operator delete is visible
  // ✅  MSVC: error C2573: 'test1::S': cannot delete pointers to objects
  //                        of this type; the class has no non-placement
  //                        overload for 'operator delete'.
  //           Use::delete, or add 'operator delete(void*)' to the class
  delete p;
}
```

According to [N4950, [basic.stc.dynamic.deallocation]/3](https://timsong-cpp.github.io/cppwp/n4950/basic.stc.dynamic.deallocation#3):

> [...] A *usual deallocation function* is a deallocation function whose parameters after the first are
> - optionally, a parameter of type `std​::​destroying_delete_t`, then
> - optionally, a parameter of type `std​::​size_t`, then
> - optionally, a parameter of type `std​::​align_val_t`.

`operator delete(void *, ...)` is not a usual deallocation function. The definition does not mention the possible presence of an ellipsis in function parameters. However, the intent seems clear: in the placement new-expression `new (1, 2, 3) S`, we call `new(std::size_t, ...)` (which is a placement allocation function; see also [CWG2592](https://cplusplus.github.io/CWG/issues/2592.html)); and if `S()` throws, the corresponding `delete(void *, ...)` is called - that is, it is treated as a placement deallocation function. Therefore, `operator delete(void *, ...)` should not be considered in `delete p`, unless we were to admit that it is both a placement deallocation function and a usual deallocation function (which is not permitted by the standard).
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJy0Vl1z6jgS_TXipQuXkTGGBx74zFZt7e5D7s59TAmpjTUjJJUkw3B__VTbEEhuvmZqJuUkNm6dbp1zupGIUe8t4pyVS1auB6JNjQtz-dtJxBTEYOfUef4NYwLpFALjU1YuVxtWrhmfNin5yIoF41vGt3unds6kzIU949sfjG9Hxx_H2bHeVIzP6CoWLO-uSd5f0nt65IW20rSEX6xkTEphzYpNHxxTaGWCR2DVkuULgEcqgtD6x6PTChhfOI9BJBfA4onxaUyK8hWLqH_gU2J8BVmW9eugLxj-9-8O4fLENpzNVmxawsoIu2fF4t0AgM364eOAh9XqnYA1m64A_vP4SxeAIbgAKz7t-AHGq-eNKDSYkPEKpLDWJWjEEUHAUQQtdgbvkd_58SKIAyYMYHRMN75-yjG90viCKFKgWvc3XUDCmHr6n-UQbXLggRVrYp4cMiIMTn8KCnz8mPGOji8wfiG044turIPY6kREvMNa7QK9oZpHvRceGa8-UfQeX3gfnA9aJHzNGOgIRx31KxnuAF8LXFbFReDXBRWLq8AXbO-0TRgiJAdu9yvKFL-gtashNTpCOnskylODII2IERoRaTvW2aE3QuIBbfoK4BGDcUJdifyZ4uxtlP9H7Ld3DVyBCyCUehOls17nvBmpltyt8g7-SsrNj3cTpJ8RCyldUNruaTUrl_8dz8qc0rJyuRNRyywmmamzFQctM4XCGCdF0s52g2xbvDXPkj5EZ_dD6X2216lpd5l2jG-l9yfP-Nb2SbafJOBF8WL2FRuqilqsXAP5YdHGVhi4XwR1a2W_ekFOE2-_hVPjIt6aPIKoqdeJv1qHmEAEvOQcgvO0RhhzJmbE3Wwg55w9ApvkNDY3nE1zNl32Gj4_KowpuLO2-6dekqdEAvAV5bN_W5rLvP4HkIXRe_t0FKaDz56_i740DCc5CUFNKuADwTL41iAorLXV3QvlsF9GTUcfkDjexW50gA8Y0UqkHQgLaIz2UUfQdyLf5M3gX-6ERwwXaoDGhE0QEQ8RpEHRTS59SXJtdZrLQ_ydckUCZJP8vUnds35CkMKYS-CHX6aTnHBOjZZNb9Rb1rfsXCypWBAmdn26-v7Ayxl_q_ukN22k3xe9t_r-wPhWx9hiZHxLi7MmHcz1gLEEYRXomkq_nhMmOaQmuFO8siZdCBi9s93EYJP8c92JDlQwhNSIBLqD0nQDKaBIqEC83Pz75ghYu9DNxD9hvdi41qjORzvagI1aYUBFWj9vAPxFv9YajJFkPGFAmolCHXS6FN-VvXOp-bzgjs0P_f5CfSrPYzjoRIzszh3bMQmrRFCMz7KBmhdqVszEAOejqqyKcVVMykEz55O8EKqUFZ-oAut6IqZVXiDnKMc7OS4Ges5zXuazfDqa5HxcZiNRTMd8UtWyrmd8V7BxjgehTWbM8UBn0EHnkvmorMo8HxixQxO7Uy7n5P7uLePkvUGY06Lhrt1HNs7ppBRvMEkng_O_rNW9P-xHTA7aYOavTtS986U7ML6lgi7_hj44OhXct8Jln8c5_yMAAP__53OTQw">