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

    <tr>
        <th>Summary</th>
        <td>
            [libc++] Vendor communication: upcoming ABI break in various container types
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            libc++,
            ABI
      </td>
    </tr>

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

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

<pre>
    Hi @llvm/libcxx-vendors,

This issue is not a traditional issue. It is a communication to vendors about an upcoming (and past) ABI break in some of libc++'s container types. It was recently brought to our attention in https://github.com/llvm/llvm-project/issues/154146 that an ABI break had been introduced in various container types from LLVM 19 to LLVM 20, released on March 4th 2025.

There are two ways this ABI break can be witnessed:
1. The size of ``std::unordered_{map,set,multimap,multiset}`` and ``std::deque``when used with an allocator type that is empty and contains a base class that is the same across rebound allocator instantiations (e.g. ``Allocator<int>`` and ``Allocator<char>`` are both empty and contain the same base class) changed between LLVM 19 and LLVM 20.
2. The layout of a user-defined type (say `Foo`) that:
    - contains a member of type ``std::unordered_{map,set,multimap,multiset}``, ``std::deque``, ``std::map``, ``std::set``, ``std::multimap``, ``std::multiset``, ``std::list`` or ``std::vector``, and
    - passes an empty allocator, comparator or hasher type to that container, and
    - has a member of that same empty allocator, comparator or hasher type inside the enclosing type `Foo`, and
    - that member is either marked with ``[[no_unique_address]]`` or optimized out via the EBO (empty base optimization) technique
\
saw its size increase from LLVM 19 to LLVM 20.

This ABI break relates to the usage of `[[no_unique_address]]` within these containers to replace the usage of an old "compressed pair" emulation, which allowed subtle interactions with enclosing objects. See [this](https://github.com/llvm/llvm-project/issues/154146#issuecomment-3206801295) and [this](https://github.com/llvm/llvm-project/issues/154146#issuecomment-3210926293) for a more in-depth discussion of the issue. We will be [fixing this](https://github.com/llvm/llvm-project/pull/154686) in LLVM 21 when using the Clang compiler, returning to the LLVM 19 ABI. However, that implies an ABI break from LLVM 20 to LLVM 21. Furthermore, there is currently no way to realistically fix this ABI break on GCC until [an underlying compiler bug](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637) is fixed, therefore GCC will remain on the ABI introduced in LLVM 19. That also means that Clang and GCC will have a slightly different ABI for the small subset of types listed above until we are able to fix that difference.

We are still discussing whether we will be producing a fix for the already-released LLVM 20.x series. Such a fix might appear in the form of a new LLVM 20.2.y release, however this hasn't been decided yet. Please refer to this issue for updates.

The current situation puts us in a challenging position with difficult tradeoffs to make on all sides. We reached the above plan after a lot of discussion with @philnik777 and also consulted with @AaronBallman on the matter. In particular, we decided that making this ABI fix on Clang despite it not being possible with GCC is an acceptable tradeoff given that we support GCC on a best-effort basis. We decided to optimize for the most important use case (Clang / libc++) being fixed in a timely fashion. Reintroducing the original compressed pair emulation we originally had was also considered, however we decided not to opt for that option since it would require a massive refactoring that we couldn't do without seriously impacting the LLVM 21 release schedule (or missing it), and would also significantly regress compilation times and debug info sizes. We also believe that the scope of this ABI break, while large, is mitigated by some factors like the need for users to use `[[no_unique_address]]` (which is not mainstream), or to have an allocator with very specific properties, and for these uses to be relevant in their own ABIs (i.e. not a local-only usage). For all of these reasons, we think that the current decision to fix this forward on Clang with [our planned approach](https://github.com/llvm/llvm-project/pull/154686) achieves the best tradeoff.

Please watch this issue for updates on this topic and please limit discussion to necessary questions or inquiries about the strategy outlined above. Please direct technical discussions on the bug itself towards [the original bug report](https://github.com/llvm/llvm-project/issues/154146).
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJy0WF1v48bO_jXKDRHDHttxcpGLJNu8XaDFe3BatJcLaoaW5mQ0o50Pe91ff0COZHu33Z6P7gFyEVgjDvnw4UNSmJLtPNFjs31utu9usOQ-xEdnbPCebtpgTo_fW2g2S-cOQ6NenW31p0-3B_ImxNSol2b51Cyffu5tAptSIbAJfMiAkCMam23w6OqjBbzP_BhBh2Eo3mrkx5ADTPYA21AyoIcy6jBY30Gj7tEbGDHlRj3A0_N7aCPhG1gPKQwEYQ_sVKOe5W-XQAef0XqKkE8jJbn2iAkiafLZnaCNoXR95otDiYA5kxdPrIc-5zE166dGvTbqtbO5L-1CB4l9gsAdhtsxhn-Qzo16ldBSo15X281qcwe5R4ng4mmPBloiNp9jMEWT4ZsOGG0ov3MX9jEM8MMPv_wIqwd2Uf5Vy0a9QCRHmMhA8PAjRt3DJveglmq7mPNAkQAjQT4GOOIpQebUXJzR6KElONrsKSUyHOryabWAn3uCZH8TQJu7ZXO3TFmerp-KD9FQJPOh2T0PODbqJVFu1MtQXLb1B_mXf929q28Dp-0LQ4Y-Fqq_HXvyUDiWo809A4bOBY05VBwqjjYBDWM-ibEJKCZQi4lAO0zpfC6z_zgQoI4hcbbbULy5Mmt9yuizFdYlZhYtusXk49N8rFm_WJ-b9Xe_C-P6iO4xXp2JBG3I_e-dvbh1cZl5rHv0HTEv8pGpMeebX50SzilVNS8OT1wXYQ_ImMVbQ3vryVSkGnWf8MROvobAHqkHQaWmFgDg9hq7gYaWIhurb3-DXDM3v57qP3jKdr72jA1_9b3ZiT898GcWnE3TQwjxy4cH0pze87vozRnBEVOixESdknxmg3phQRsxCstChB5TTzONQ2Xoucq_tNvjF0nh08KY_-ge65M1JHQjr11ILJ5zgmdefH6z3DRdzIVmM1sbML7NVTkhwb3h2YcPxduPhT6gMZFSarbv-O-MZRizHexvrE4lw8GiOPPd8_9LpUksUgPTOalCoSrpXgyzhG25oSQ8gs2pypH1OrLofU0XF1cd6CJzkRxmShV-gpKwOyvbvwhHQq-VyxU7501sRRodavrcJnoIzkCjFKcniqzCiDY2SgENxU2hvsCxt7qXjB7JQCptdhxgpoi6ipLAfklgaLnLpAX8RATN9pnFnL1U93-1TzVqLb9wKyafb9dqeXe_XKmHLedERO9_e91q-aDu1MOar9uHyDUQIqNxa2jMPRibdEmJ27JUBc1DxK_cvZzjLtZsn_f2kzD9v_d0LM5VP-_u79gbO8mxWsHUpeoNBC8OfSdFaF2t5Ei5RC_PK9Nmgj49v1_A9-FIh3qwtqlhdLaKyIWqF16r5YXXqwW8lsgVybBUC9zbbQJdYqyDjJceX4mJrGxWo3Mn2NtPX_b94OH_Xl6g-Gwd48YzljcU3clehQRt6f4QRq0XnS-LELtGvbal-806h416TX04fmhLt9Cdbdav1jTrdyu1ulvvBMnErpA5u7_nFLMfksFIA7fIULsk-_r5hDRhyT2QZyqXAgyEfur5NRnM1LPBHg8ECMnZrmd8jN3vibES48wyaccDOsfVlyjPbTABw0eGJ9ADTTAd6yiFrRMdr6hiPpvVNInPr_VgyuzETFzfMX1EU48Xyo4SHz9EMTg7hS4SmtPtecSb5e0TJIqWx9ifCouHvDVwgIDjSMhzjVjYhzjUEcHT8fy6WpzmsZGz0FdGVnb0mHyjdrlOp4a0NWTgRHkBf5M3INKeD4d6vg747HEZDcvrZeqcSQnJ5lLH-rHkBCWxe8jzjnPkOw58DEn2gip2DKbVxWVZGCjs96K0A74RM0NSZQ3H_yv7g7rnuYcRk0yNjkfHfSZWEBckoVfSUdvYZjn21nn7ttvthDHCJR18Ki6fm91m-YQx-Gd0bsAzLQdeD-IC3nsYMWZ2FaWij3SGrHZSfJuVqNLNfmIblaaG0mgzgc2yHbU0AZEsk0vuZxZb0QbUmsZcaTdhAp09kK8XHQlSGccQs7zDIEFLKd_Sfs8_tphshevsXzh35zPhhpBEkELkoZjHStCc8kbdV5cb9frZZvUweS0VXbOa7UAsN5h6G_wC_k5zAc-KGaLtLG-AX7TGS1_kcOZT7iTLEi9r5wxZmUavuXsFPGNZg5viwiyRBg_Jei14H0NxBiJ9LJaLGQZeeg_CbeRxr7pacdV8ttaECZIWnmW4AENJ7sR4caeegpu7xFRfkJibxQmGIcJgqwpY3lyn4WvyRqLj1dvurUbR8kgd4zNJ8bQZ20G6hQFDbenA-n2QqaimV6y05Cwdpn1J5E2HkWrPvO4A0_zheJuInYiBTTDYbDvkGmhPdZ-uoLAevtU5xxOZWvRpmoKYK__OINWo-zrxTN8EWO1TjoTDBEgQbamqfb0ASj0cKJ4gjaQZI9bNkWK2PFNUJCciJ57E6qTXkqTiwHyuomgjhKM0W9n37IIW09cJvsrdBu9OdZBr1MMCXnkOcW4aOET_MAWfpnLnsfDtAvQseUzGNH3IOHfefYhHjOaiAFVjts-hRBEtXt9wHGNA3X-ryQV1z1yoyzBLwlk_JqWeZP2IWfdf0fSqe7xQh9FqQXqsbzk72HwtrjmAJ00pYTzBx0KpzrCyanO1yagjX3SElzlipu7E64GT7VUU_NxrjI2k87QOaHRXN6VZjKUIciK3hxwY31TH1Cuh4SORWNa-1eT6sLgxj2vzsH7AG3pc7bbb-_vV9m510z9ut9iS2q3arVmqe9ygRmX0Uu2Wer9U6-2NfVRLtV3eK7W626rNarHXu5VZr9vtZrfcbfaq2Sx5CnIL9oLnqxu5_3G13Tzcb28ctuSSfJ5T6lqNVaNeGqWent_z_9t3N_FR4mhLl5rNkqeZdLGZbXbyke_KxPYd_CKf3T7_HNesny5f3z773PaVD1Y3JbrHv4QyB3p4VP8MAAD__0JX8i8">