[libcxx-commits] [PATCH] D117108: [libc++] Remove vector base class
Nikolas Klauser via Phabricator via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Jan 24 13:51:08 PST 2022
philnik added inline comments.
================
Comment at: libcxx/include/vector:316
template <class _Tp, class _Allocator>
class __vector_base
: protected __vector_base_common<true> // This base class is historical, but it needs to remain for ABI compatibility
----------------
ldionne wrote:
> I was trying to convince myself that it wouldn't be ABI breaking to do the following:
>
> ```
> template <bool> struct __vector_base_common { ... };
> template <class, class> struct __vector_base : private __vector_base_common<true> { /* nothing here */ };
>
> template <class _Tp, class _Allocator>
> class vector
> #if !defined(_LIBCPP_ABI_NO_VECTOR_BASE_CLASS)
> : private __vector_base<_Tp, _Allocator>
> #endif
> {
> pointer __begin_;
> pointer __end_;
> __compressed_pair<pointer, allocator_type> __end_cap_;
>
> // use members normally here, unconditionally
> };
> ```
>
> However, the usual pitfall of multiply inheritting from `vector<T>` applies here too. Let's assume we have:
>
> ```
> struct IntVector1 : std::vector<int> { };
> struct IntVector2 : std::vector<int> { };
> struct Foo : IntVector1, IntVector2 { };
> ```
>
> Before the change, the layout should be:
>
> ```
> +---------------------------------+
> | __vector_base_common<true> | 0 bytes, EBO'd
> | __vector_base<int>::__begin_ | 8 bytes
> | __vector_base<int>::__end_ | 8 bytes
> | __vector_base<int>::__end_cap_ | 8 bytes (disregarding allocator)
> | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
> | __vector_base_common<true> | 1 byte, can't EBO
> | __vector_base<int>::__begin_ | 8 bytes
> | __vector_base<int>::__end_ | 8 bytes
> | __vector_base<int>::__end_cap_ | 8 bytes (disregarding allocator)
> +---------------------------------+
> ```
>
> After the change, the layout should be:
>
> ```
> +---------------------------------+
> | __vector_base_common<true> | 0 bytes, EBO'd
> | __vector_base<int> | 0 bytes, EBO'd
> | vector<int>::__begin_ | 8 bytes
> | vector<int>::__end_ | 8 bytes
> | vector<int>::__end_cap_ | 8 bytes (disregarding allocator)
> | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
> | __vector_base_common<true> | 1 byte, can't EBO
> | __vector_base<int> | 1 byte, can't EBO <<-- this is the ABI break
> | vector<int>::__begin_ | 8 bytes
> | vector<int>::__end_ | 8 bytes
> | vector<int>::__end_cap_ | 8 bytes (disregarding allocator)
> +---------------------------------+
> ```
>
> Since `__vector_base<int>` would now be empty, it would get EBO'd the first time it's a base class, but not the second time, so there would be one extra byte because of that "spurious" base class.
>
> Long story short, my suggestion doesn't work because it would break multiple inheritance of `std::vector`.
https://godbolt.org/z/rdMfbchKq seems to suggest that something with your tables is wrong. My current diff has still the same size with your example.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D117108/new/
https://reviews.llvm.org/D117108
More information about the libcxx-commits
mailing list