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

    <tr>
        <th>Summary</th>
        <td>
            [libc++]  ABI break: std::deque changes its size in LLVM 21
        </td>
    </tr>

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

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

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

<pre>
    The following code shows how the size of std::deque has changed in LLVM version 21.

// t.h
```
#include <deque>
#include <memory>
#include <cassert>


struct malloc_allocator_base {
  static std::size_t outstanding_bytes;
  static std::size_t alloc_count;
  static std::size_t dealloc_count;
  static bool disable_default_constructor;

  static std::size_t outstanding_alloc() {
    assert(alloc_count >= dealloc_count);
    return (alloc_count - dealloc_count);
  }

  static void reset() {
    assert(outstanding_alloc() == 0);
 disable_default_constructor = false;
    outstanding_bytes           = 0;
 alloc_count                 = 0;
    dealloc_count               = 0;
 }
};

size_t malloc_allocator_base::outstanding_bytes         = 0;
size_t malloc_allocator_base::alloc_count               = 0;
size_t malloc_allocator_base::dealloc_count             = 0;
bool malloc_allocator_base::disable_default_constructor = false;

template <class T>
class malloc_allocator : public malloc_allocator_base {
public:
 typedef T value_type;

  malloc_allocator() noexcept { assert(!disable_default_constructor); }

  template <class U>
 malloc_allocator(malloc_allocator<U>) noexcept {}

  T* allocate(std::size_t n) {
    const std::size_t nbytes = n * sizeof(T);
 ++alloc_count;
    outstanding_bytes += nbytes;
    return static_cast<T*>(std::malloc(nbytes));
  }

  void deallocate(T* p, std::size_t n) {
    const std::size_t nbytes = n * sizeof(T);
 ++dealloc_count;
    outstanding_bytes -= nbytes;
 std::free(static_cast<void*>(p));
  }

  friend bool operator==(malloc_allocator, malloc_allocator) { return true; }
  friend bool operator!=(malloc_allocator x, malloc_allocator y) { return !(x == y); }
};


int sizeOfCreatedDeque();
std::deque<int, malloc_allocator<int> > dq;
```
 
t.C
```
#include "t.h"

int sizeOfCreatedDeque() {
 dq.push_front(1);
  dq.push_front(2);
  dq.push_front(3);
  return sizeof(dq);
}
```

// t2.C
```
#include "t.h"
#include <iostream>

int main() {
using namespace std;
  int previousSize = sizeOfCreatedDeque();
  int currentSize = sizeof(dq);
  if (currentSize != previousSize)
    cerr << "ABI break std::deque`s change from " << previousSize << " to " << currentSize << endl;
  return 0;
}
```

compiler t2.C with clang from LLVM 21 and t.C from previous version and run executable:
I'm getting the following:
**ABI break std::deque`s change from 48 to 56**

My investigation point to https://github.com/llvm/llvm-project/pull/76756 as culprit. 
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJysV02PozgT_jXOpTQRmJDQhxzSybQ00ozew9u718hAEbxrMG2bdGd-_co2JISQdK-0EZppcLnqeerLZaY1P9SIaxI_k3g3Y60ppVr_5imns1Tmp_VriVBIIeQ7rw-QyRxBl_JdQynfwZQImv9GkAVok5NoQ6JNjm8tQsk0ZCWrD5gDr-Hnzz9_wRGV5rIGGs5JsLEPfSH0Bcy8tC_LoHvsQsTrTLQ5Aom2TiOJvt8sVFhJdZpayZjWqEy35B5tVJsZqJgQMtu7f5mRap8yjUBWzyTYAGjDDM8uZCy7vQHZGm1YnfP6sE9PBjWJHsp7G5lsa_OJZI73ZVMpBeRcs1TgPseCtcLsM1l7JlJ58a_idnYITQh9OtMF6PxEkwEMsG6LdiNs9KmHB6DQtKqG0bZvd3eQ1W6E9Ch5Dgo1mvuQ7qKPdhZecDHwwElWGgomNF7g34QTLj-v2YsOyY1_QzmAa-YPRDtPrHbn4HWhmsxLH8z7cAeaP1fzJYCfq7nPdKDGpe4jJV8PGAk2BqtGMOMrWzCt4dVXtn8Z2wESbaBpU8Gzh-XuRSygYAPm1GCOBbzCkYkW9_Z9UGBjPV0q1hI_MmyM1XhJXELDR2Xr0nZYE7f8_vD8pszefIq2TnqEZqD-ldAul5lBQpNxl6iv689BvWkltc88Gxxb-BvX-GVBaPJ6qUNCnwl9nuhoUzVnha22q4Z67i2-T-wzpg2JtpaCI3kBX_UtoVNAn6Ybjus0XdJ6_s4fDaHbW5L_sScmu_uUL77deOJstVDogzb0hyV1dklzl3uhONa5P0hkg8rni-2eU4lEtxP55vzRB8UoexD3uXtHPw2n9cPHlAU4jWzY_TT56Lv86bpcBo2TBBteG-f9_xVbhcxgvnOjgqvNrp9djSUk2nJ7ME0Q9SvRd3v4Qf7WWRnMJGAb0Xz7YFKh1E4ylH6Orc-x_G3etLrcF0paWEk4CON4jT5YiwZrff30SZm_nRc7Hw7hX4Yw-mVuV5MWl9ooZNV51LK8K8brK6attuNjzSrUDcvQZ7fHa-UbhUcuW_1_O0zaqD8Oqt-UtUphba72jBkD8MKOKVeyLkGvbFr5ruRR2fNjS6KtJb15_gGpQvb3aL4ly6Cfb6FQsrKy_bYRmV4VGDmUukbvPmGdi1EUgweBy2TVcIHKhQ7euSkhE6w-eEBu4qYhsDoHM9_6jz208yhuV1VbA35g1hp7Yvnj8AehqwoOaIyNmxleAryAbT5082X3LBJLP176bR7_rxPw-oja8AMzFkwjbViNhNKYRlt1LjUP3JRtOs9kReiLEMf-v2-Nkn9hZgh9aVohCH1ZLVfxEuzNoxWN4mYOs3wd5U_RE5vhOlzFcRxFq8VyVq4LmucZhvkCkxizgiUJRslqiXSVLMJVHs34mgY0DpIwCZdhvIjny6dsmQbpMsMgoIwuySLAinExt1jmUh1mXOsW12G8CBfLmWApCu0uVpQKnmb-RLAlRLc-s-zf8W6m1o5N2h40WQSCa6MvOg03wl3PBiriHcDZ83bWGd29vOM1cKP99ay_gNFw1iqx_tfudcQ0oS8dt-Oa_hMAAP__rDlcqA">