<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/96899>96899</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
Libc++ breakage with -fsized-deallocation on MinGW
</td>
</tr>
<tr>
<th>Labels</th>
<td>
clang,
libc++,
platform:windows
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
mstorsjo
</td>
</tr>
</table>
<pre>
Since 130e93cc26ca9d3ac50ec5a92e3109577ca2e702, included in the upcoming 19.x branch, Clang now enables `-fsized-deallocation` by default when targeting C++14 or newer.
Running the libc++ tests with such a clang binary ends up with 27 tests failing, see e.g. https://github.com/mstorsjo/llvm-mingw/actions/runs/9414695194/job/25934131202. (This is in build configurations with libc++ built as a DLL, it's not a problem when libc++ is linked statically.)
The effect of this change, is that when invoking `delete`, it generates a call to `operator delete(void*, size_t)` instead of a call to `operator delete(void*)`.
By default, both `operator delete(void*)` and `operator delete(void*, size_t)` are provided by libcx++/libc++abi. If the user overrides `operator delete(void*)`, but the compiler calls `operator delete(void*, size_t)`, it should hit the libc++/libc++abi fallback implementation which calls `operator delete(void*)`.
When everything is linked statically, the fallback `operator delete(void*, size_t)` ends up calling the user provided, overridden `operator delete(void*)`. However, if the fallback `operator delete(void*, size_t)` resides in libc++.dll, a user provided `operator delete(void*)` won't get called, but it just calls the default `operator delete(void*)`.
Thus, this change breaks the case when users override only `operator delete(void*)`, not `operator delete(void*, size_t)` (which the user may not even have heard about), as the compiler generated code no longer ends up calling the user's overridden operator.
---
This isn't an entirely new issue; the same issue with operator overloading already exists in a number of cases, e.g. where the user overrides `operator new(size_t)` but the caller calls `operator new(size_t, nothrow_t)`. We have covered these cases in libc++ tests by omitting some individual checks in these cases using `ASSERT_WITH_OPERATOR_NEW_FALLBACKS`, see https://github.com/llvm/llvm-project/blob/llvmorg-19-init/libcxx/test/support/test_macros.h#L353-L371
There is also another similar situation; if the user overrides operator new/delete, any calls to these functions within libc++.dll will still call the default functions within the DLL, instead of the functions provided by the user code (in another EXE/DLL) - these are waived in tests with `ASSERT_WITH_LIBRARY_INTERNAL_ALLOCATIONS` in the same file above.
For the fallbacks between different kinds of operators, this situation actually works correctly with MS STL, when linked as a DLL. This is because the import library to the MS STL DLL, `msvcprt.lib`, isn't a regular pure import library, but it contains a handful of regular object files (which end up statically linked into the user executables, if needed) that provide the fallback `operator new`/`delete`, so that fallbacks from a more specialized operator to a less specialized one do work in user code.
CC people involved in MinGW/libc++, @lazka @mati865 @alvinhochun @cjacek @jeremyd2019 - and from the libc++ side @ldionne
With around 4 weeks to go to the 19.x branch date, what direction should we take wrt this for the MinGW target?
I see two aspects of this; we want the libc++ testsuite to still work. But user code, that previously just did override `operator delete(void*)` but didn't override `operator delete(void*, size_t)`, no longer works as it did, when using libc++ as a DLL. That's possibly a surprising change (even though the amount of projects overriding operators probably is quite small).
I see the following options:
- We can revert the Clang change for the MinGW target. Keep defaulting to `-fno-sized-deallocation` for MinGW targets, just like before. The linked change above does this when targeting zOS already, and when targeting older versions of Darwin. See https://github.com/mstorsjo/llvm-project/commit/clang-no-sized-dealloc-mingw for an example of this.
- We can add `-fno-sized-deallocation` to the MinGW libc++ testsuite configs. This silences the issue in the libc++ tests, but the potential issue for users still exists. See https://github.com/mstorsjo/llvm-project/commit/libcxx-mingw-no-sized-dealloc
- We can also add another wrapping around the checks that we know and expect to fail when using a libc++ DLL build, like `ASSERT_WITH_OPERATOR_NEW_FALLBACKS`, see https://github.com/mstorsjo/llvm-project/commit/libcxx-waive-sized-operator-delete-fallback. The issue remains for users here as well.
- We could construct a hybrid import library, with the operator new/delete fallback operators linked statically, just like MS STL does. I have a proof of concept of this ready, see https://github.com/mstorsjo/llvm-project/commit/libcxx-static-operators-import-library. (It's not complete and tested for MSVC style targets yet, and obviously would need to go behind conditionals etc. And this currently relies on `llvm-ar` specifically for merging static libraries, iirc GNU ar doesn't implement those options.) Technically, this is the best solution, as it makes the operator overloading work as expected - it also would allow getting rid of the existing `ASSERT_WITH_OPERATOR_NEW_FALLBACKS` check waivers for MinGW/DLL configs. But implementation wise it's quite messy.
With a couple weeks to go to the branch, which way do we go?
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJysWd9z2zgO_muUF4w9Nu3Y0UMenLTezay3vUly17unDEVCFmuK9JGUFfevvwEp-Vez23SuM50mcUQK-AB8-IBw79XaIN5m13fZ9Ycr3oTKutvaB-v8V3tVWLm_fVJGIIwnI8wnQrCZ4LmccHE9QnHNc4aT8Si_ns8FZzgfsYzdgzJCNxIlKAOhQmi2wtbKrGGcD1-hcNyIip6719yswdgW0PBCo4dsNhqUXn1DOZDItbaCB2VNNhtBsQeJJW90gLZCA4G7NQa69T5jdxm7G0_BOjDYohtmow_ZaJH-f2yMocfIEq0KkZ6GgD54aFWowDeiAg4imlMow90e0EgPzTY9wObd4yVXWpk1Ge8RAYfrIVQhbH02WWRsmbHlWoWqKYbC1hlb9kBmbKn1rh4QCG3GllyQVz5jS9fEL_l0PJ3l1-N8mrHlV1tkbMmu88l0PBmzERtCxm6eK-WB_hkoGqUlCGtKtW5cRKjz5MQ_eigA98Dhw2oVwxIyNvdgbAAOW2cLjXXC8uSY8qCV2aAEH3hQgmu9H2YsP0X0uULAskQRwJYQyDBRcbPG-BYPoeJdkJTZ2Q2Bn81GEjUGzGajZAus0aDjAclCeg0ES4_ZLX1qHXTPs5udVTJjiwi6-oYvgcyZjUAZH5BLsuG9N9C5s-S4O2QVXV_YUL3jBuBG_pyp3CEhvlNUFcU-Av6aEKfcOMDPCzWEhzJVjUcHdofOKZlK4wdmRQ-aEA8LW2-VRhdx-dHhc2O78PjKNlpCpcJF5VwaDCXXuuBiA6reaqzRhJiS0FZKVO8y4LuwfKHkwR26fagofd7KSrKTLDu8_qci0tc3XdWzQ0S8DxOd6NCXaN7jAPxuW7I5Alj-H7Y59DHk6rQyh1JrepKfm_medG2tydicKi5Ef5NzlCoqwNfGhy5IZHHPsT8ZsHN6aHwKzoEYoHDIN-kNgntM7ECO-EOKgzV6_840Jw77KUgzdpPS8RDnmu_jNbhDAxXfIVTInQRe2CaeIqz9eTH1lEXkKxGMBW3NGt1fZlMk3JMs6g0-w24wGJzDF4k-hYwbQBOUQ72n1gbK-wazyV18g-c1pk8S-x_goDdqyyWZwrVDLveAr4o6mDLAwTR1QeRSxmDEYMVW1lbo8EfkY7DN2M0ZugfWoeR6i3POz8T4Vc62_QVD-IIpBoLeiZJu8ylVLsqga8TFHmytQuz_3hIMRqqdkg3XICoUG9-Jj8Mtje_60OLp6ePj88uXh-ffXz7_4-Pj4vnz48unj19elovV6m5x_8dTl2TU4f-muVNH7xv71tmvKELGloWO3Zs-tW49GOcDZajxRs58fc3YkhzI2NI32611ofvgpebCWT-sMjZZTa4ng9VkPr7ouY6CDVx7C5wARAde1Upz-hqapJQmdz33XITwPBbLvmLugZt9X_-2Q6xsjDiqiu9oCFqlNfhA_6e-e0Ic352lX_YK5NixIzseHj3tjQfbY41l7IZStvP3478_ZmwZb8th0FlLzbXlatcJzqOuuwj26uHucfH4n5eHT88fHz8tVi-L1erz_eL54fOnp6QnjlVVKo1EBTs8K9WldWe87qHA0CIakKos0aEJsFFEBrY8IH4kw0OYgIvQUBOD1rqNB2GdQxHoZzL8zyd4eo6IdfIstr5eyw2h14IFCt74VLGqpnSiSDnSrymW3U09_tlsVPud2Low1Kroe31PNeBw3VA2bRt3ed9JwxDWBK4MGVNxI8tGk7P9WVtQIUT8_JF10Uiix2Pz7n1SpjM0RhxfUTQhjgJdEzWIsRfnSVR2efLXvZWSm9xaXgpOb9MNx8iVztbAobYOwW9RKK5p8DgWSrDAQaP35782CNLGuFHGHDL1LE_u72GLdqsxKmDdpeafyvz25Uw-xaBMR5p_23D6puZB3cyu6Vuud8pUVlSNoR_FVy5wQ999RYf1XrLRmEqApGj05GK8IQURr5bKGoNwpq4ox7izjZEwhRZxE2t_bfusOZnTQPJEEy2hJxWlKSVwJw9bhMA3CK0LKcXLrkKir92Qlk2Wp69_iMwaWgucgA2-nyKIvFqqZXOpOVNVNyogmZiYhyIwhLsmHGOQCi3mCe6UbbzeJ30jlTzqjHcoJkp1qWQqjHce_F5FH_VBqnLuqX6kkofKTk3pxM_TGudpXtta71Wh98DBN27rVDzT6aqM3UQBEyrbrJO64bVtTJzMuq50UCB07kBKcQLkdK_y8N8Ira85acx8-Ea0qOCs1rZNl6T5dXKm-wbUxQU34EgFpxCmEb8z9q3cGMIfiNu-e0TtZNMawNjB25sAuub0isgVMcxabRAKLK1DAhB7luneH_kcpEWfcvVij_Dt81OvllJflJdPWC3RwQ6dj13LlvCBu1aZITz9vVa4XAQc9YKwdR31Qdw-DC6dTiuD6DJJwVdOI1ZfL8ML3LmUP4Cu7woRvTfLK20VfNdjvNJoBCYZnJRm1yUvD58On1sbSLRy3R0h65PWT5WbpOivAC2JqgTSd9hdohOFk5QHMdE6vt1GiZyoMCrYpB3TBgNhY2wbEwFfiakIv5IrfVq8_BSKD6tV2s4QHDEbf6HgfD8eUQ11YPQFP0iMNegbYCqQFCCHdezox0BFtck9tKj1WZpF1hfW-OAaQaKh2hdOyTfkQlQyhOmbyvPYvo-M9OaIfyzsTstQ_Q7hIc0LcZFFWqskowRujyupQyH_MliTYQdE_SA5Peicjmu6h-OSjcbG6ColEBUJysRdT_-6Bx_2GnsCgz2GnnJs0XeuNmJNCqjrzgVWykT0paKK5toDBjGERcxemrYbRxpU78GhVqT64-Yi-sUdMUCUMmUnwsiaGt06TlHRuS6AqhNgygn47dM_gbsIe-qHhzUPdR2PfTcYkkp7RlGZ0_1MEqqUBgX6AN7qJpJRmq5VgJpvOn55c3yNOov7rgBRwoAOxVpO-FCpt7DGNAtSKnbTRWSZn5n5UvGnUcL5Y5tJE8eRGUlyXK66lMd-v5p6aY3e74ffqy6qIKLwN1TXcTGeRHPL91FpIqxtNlleyduJzCc5v8Lb8XycT_PxdD6-qm6vGRMsz6fXJY5wXkxv2Gg0v77BGRPiJi9GV-qWjdh0NGPzMZuMx-PhaDYaTcucTedsfDNj02w6IgbQQ0qUoXXrq8gLt_nsJs-vNC9Q-_g3AsZim8oYy9h9xtipku0-2moeSuvqbLJolZG29fSr6w9X7jamYdGsPenS2AIO7wsqaLxdnayvHfINX3ebjbf-KEC5HeNz1Th9-9ODevQw7t6jk7tb9r8AAAD___01cgQ">