[libcxx-commits] [libcxx] [libc++] Add ABI tests for introducing _LIBCPP_COMPRESSED_ELEMENT (PR #156416)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Tue Sep 2 00:25:54 PDT 2025


https://github.com/philnik777 created https://github.com/llvm/llvm-project/pull/156416

#134253 refactors a few classes to use `[[no_unique_address]]` instead of the EBO. This adds tests to ensure there are no ABI breaks.


>From d122fe9138b7fd3e112402294a81ab5644264093 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Tue, 2 Sep 2025 09:24:50 +0200
Subject: [PATCH] [libc++] Add ABI tests for introducing
 _LIBCPP_COMPRESSED_ELEMENT

---
 .../associative/map/abi.compile.pass.cpp      | 23 ++++--
 .../unord.map/abi.compile.pass.cpp            | 36 ++++++++-
 .../utilities/tuple/abi.compile.pass.cpp      | 79 +++++++++++++++++++
 3 files changed, 129 insertions(+), 9 deletions(-)
 create mode 100644 libcxx/test/libcxx/utilities/tuple/abi.compile.pass.cpp

diff --git a/libcxx/test/libcxx/containers/associative/map/abi.compile.pass.cpp b/libcxx/test/libcxx/containers/associative/map/abi.compile.pass.cpp
index e0598b4ff1746..8bd9afa75cbf2 100644
--- a/libcxx/test/libcxx/containers/associative/map/abi.compile.pass.cpp
+++ b/libcxx/test/libcxx/containers/associative/map/abi.compile.pass.cpp
@@ -87,6 +87,13 @@ struct user_struct {
   [[no_unique_address]] common_base_allocator<int> a;
 };
 
+struct TEST_ALIGNAS(32) AlignedLess {};
+struct FinalLess final {};
+struct NonEmptyLess {
+  int i;
+  char c;
+};
+
 #if __SIZE_WIDTH__ == 64
 // TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed
 #  ifdef TEST_COMPILER_GCC
@@ -120,10 +127,13 @@ static_assert(TEST_ALIGNOF(map_alloc<char, test_allocator<std::pair<const char,
 static_assert(TEST_ALIGNOF(map_alloc<char, small_iter_allocator<std::pair<const char, char> > >) == 2, "");
 static_assert(TEST_ALIGNOF(map_alloc<char, final_small_iter_allocator<std::pair<const char, char> > >) == 2, "");
 
-struct TEST_ALIGNAS(32) AlignedLess {};
-
 static_assert(sizeof(std::map<int, int, AlignedLess>) == 64, "");
+static_assert(sizeof(std::map<int, int, FinalLess>) == 32, "");
+static_assert(sizeof(std::map<int, int, NonEmptyLess>) == 32, "");
+
 static_assert(TEST_ALIGNOF(std::map<int, int, AlignedLess>) == 32, "");
+static_assert(TEST_ALIGNOF(std::map<int, int, FinalLess>) == 8, "");
+static_assert(TEST_ALIGNOF(std::map<int, int, NonEmptyLess>) == 8, "");
 
 #elif __SIZE_WIDTH__ == 32
 // TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed
@@ -158,10 +168,13 @@ static_assert(TEST_ALIGNOF(map_alloc<char, test_allocator<std::pair<const char,
 static_assert(TEST_ALIGNOF(map_alloc<char, small_iter_allocator<std::pair<const char, char> > >) == 2, "");
 static_assert(TEST_ALIGNOF(map_alloc<char, final_small_iter_allocator<std::pair<const char, char> > >) == 2, "");
 
-struct TEST_ALIGNAS(32) AlignedLess {};
+static_assert(sizeof(std::map<int, int, AlignedLess>) == 64, "");
+static_assert(sizeof(std::map<int, int, FinalLess>) == 16, "");
+static_assert(sizeof(std::map<int, int, NonEmptyLess>) == 20, "");
 
-static_assert(sizeof(std::map<int, int, AlignedLess>) == 64);
-static_assert(TEST_ALIGNOF(std::map<int, int, AlignedLess>) == 32);
+static_assert(TEST_ALIGNOF(std::map<int, int, AlignedLess>) == 32, "");
+static_assert(TEST_ALIGNOF(std::map<int, int, FinalLess>) == 4, "");
+static_assert(TEST_ALIGNOF(std::map<int, int, NonEmptyLess>) == 4, "");
 
 #else
 #  error std::size_t has an unexpected size
diff --git a/libcxx/test/libcxx/containers/associative/unord.map/abi.compile.pass.cpp b/libcxx/test/libcxx/containers/associative/unord.map/abi.compile.pass.cpp
index 60c3e5bf31b00..43934bf3c5b47 100644
--- a/libcxx/test/libcxx/containers/associative/unord.map/abi.compile.pass.cpp
+++ b/libcxx/test/libcxx/containers/associative/unord.map/abi.compile.pass.cpp
@@ -91,6 +91,19 @@ struct user_struct {
   [[no_unique_address]] common_base_allocator<int> a;
 };
 
+struct TEST_ALIGNAS(32) AlignedHash {};
+struct FinalHash final {};
+struct NonEmptyHash final {
+  int i;
+  char c;
+};
+struct UnalignedEqualTo {};
+struct FinalEqualTo final {};
+struct NonEmptyEqualTo {
+  int i;
+  char c;
+};
+
 #if __SIZE_WIDTH__ == 64
 // TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed
 #  ifdef TEST_COMPILER_GCC
@@ -125,8 +138,16 @@ static_assert(TEST_ALIGNOF(unordered_map_alloc<char, small_iter_allocator<std::p
 static_assert(TEST_ALIGNOF(unordered_map_alloc<char, final_small_iter_allocator<std::pair<const char, char> > >) == 4,
               "");
 
-struct TEST_ALIGNAS(32) AlignedHash {};
-struct UnalignedEqualTo {};
+static_assert(sizeof(std::unordered_map<int, int, FinalHash, UnalignedEqualTo>) == 48, "");
+static_assert(sizeof(std::unordered_map<int, int, FinalHash, FinalEqualTo>) == 48, "");
+static_assert(sizeof(std::unordered_map<int, int, NonEmptyHash, FinalEqualTo>) == 48, "");
+static_assert(sizeof(std::unordered_map<int, int, NonEmptyHash, NonEmptyEqualTo>) == 56, "");
+
+static_assert(TEST_ALIGNOF(std::unordered_map<int, int, FinalHash, UnalignedEqualTo>) == 8, "");
+static_assert(TEST_ALIGNOF(std::unordered_map<int, int, FinalHash, FinalEqualTo>) == 8, "");
+static_assert(TEST_ALIGNOF(std::unordered_map<int, int, NonEmptyHash, FinalEqualTo>) == 8, "");
+static_assert(TEST_ALIGNOF(std::unordered_map<int, int, NonEmptyHash, NonEmptyEqualTo>) == 8, "");
+
 // TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed
 #  ifdef TEST_COMPILER_GCC
 static_assert(sizeof(std::unordered_map<int, int, AlignedHash, UnalignedEqualTo>) == 64, "");
@@ -169,8 +190,15 @@ static_assert(TEST_ALIGNOF(unordered_map_alloc<char, small_iter_allocator<std::p
 static_assert(TEST_ALIGNOF(unordered_map_alloc<char, final_small_iter_allocator<std::pair<const char, char> > >) == 4,
               "");
 
-struct TEST_ALIGNAS(32) AlignedHash {};
-struct UnalignedEqualTo {};
+static_assert(sizeof(std::unordered_map<int, int, FinalHash, UnalignedEqualTo>) == 24, "");
+static_assert(sizeof(std::unordered_map<int, int, FinalHash, FinalEqualTo>) == 24, "");
+static_assert(sizeof(std::unordered_map<int, int, NonEmptyHash, FinalEqualTo>) == 28, "");
+static_assert(sizeof(std::unordered_map<int, int, NonEmptyHash, NonEmptyEqualTo>) == 32, "");
+
+static_assert(TEST_ALIGNOF(std::unordered_map<int, int, FinalHash, UnalignedEqualTo>) == 4, "");
+static_assert(TEST_ALIGNOF(std::unordered_map<int, int, FinalHash, FinalEqualTo>) == 4, "");
+static_assert(TEST_ALIGNOF(std::unordered_map<int, int, NonEmptyHash, FinalEqualTo>) == 4, "");
+static_assert(TEST_ALIGNOF(std::unordered_map<int, int, NonEmptyHash, NonEmptyEqualTo>) == 4, "");
 
 // TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed
 #  ifdef TEST_COMPILER_GCC
diff --git a/libcxx/test/libcxx/utilities/tuple/abi.compile.pass.cpp b/libcxx/test/libcxx/utilities/tuple/abi.compile.pass.cpp
new file mode 100644
index 0000000000000..a0774bb49b608
--- /dev/null
+++ b/libcxx/test/libcxx/utilities/tuple/abi.compile.pass.cpp
@@ -0,0 +1,79 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: libcpp-abi-no-compressed-pair-padding
+
+#include <tuple>
+
+#include "test_macros.h"
+
+struct S {};
+
+struct Final final {};
+
+struct NonEmpty {
+  int i;
+  char c;
+};
+
+struct NonEmptyFinal final {
+  int i;
+  char c;
+};
+
+struct TEST_ALIGNAS(16) Overaligned {};
+struct TEST_ALIGNAS(16) OveralignedFinal final {};
+
+static_assert(sizeof(std::tuple<S>) == 1);
+static_assert(sizeof(std::tuple<Final>) == 1);
+static_assert(sizeof(std::tuple<NonEmpty>) == 8);
+static_assert(sizeof(std::tuple<NonEmptyFinal>) == 8);
+static_assert(sizeof(std::tuple<Overaligned>) == 16);
+static_assert(sizeof(std::tuple<OveralignedFinal>) == 16);
+
+static_assert(sizeof(std::tuple<S, S>) == 2);
+static_assert(sizeof(std::tuple<Final, S>) == 1);
+static_assert(sizeof(std::tuple<NonEmpty, S>) == 8);
+static_assert(sizeof(std::tuple<NonEmptyFinal, S>) == 8);
+static_assert(sizeof(std::tuple<Overaligned, S>) == 16);
+static_assert(sizeof(std::tuple<OveralignedFinal, S>) == 16);
+
+static_assert(sizeof(std::tuple<S, Final>) == 1);
+static_assert(sizeof(std::tuple<Final, Final>) == 2);
+static_assert(sizeof(std::tuple<NonEmpty, Final>) == 12);
+static_assert(sizeof(std::tuple<NonEmptyFinal, Final>) == 12);
+static_assert(sizeof(std::tuple<Overaligned, Final>) == 16);
+static_assert(sizeof(std::tuple<OveralignedFinal, Final>) == 32);
+
+static_assert(sizeof(std::tuple<S, NonEmpty>) == 8);
+static_assert(sizeof(std::tuple<Final, NonEmpty>) == 12);
+static_assert(sizeof(std::tuple<NonEmpty, NonEmpty>) == 16);
+static_assert(sizeof(std::tuple<NonEmptyFinal, NonEmpty>) == 16);
+static_assert(sizeof(std::tuple<Overaligned, NonEmpty>) == 16);
+static_assert(sizeof(std::tuple<OveralignedFinal, NonEmpty>) == 32);
+
+static_assert(sizeof(std::tuple<S, NonEmptyFinal>) == 8);
+static_assert(sizeof(std::tuple<Final, NonEmptyFinal>) == 12);
+static_assert(sizeof(std::tuple<NonEmpty, NonEmptyFinal>) == 16);
+static_assert(sizeof(std::tuple<NonEmptyFinal, NonEmptyFinal>) == 16);
+static_assert(sizeof(std::tuple<Overaligned, NonEmptyFinal>) == 16);
+static_assert(sizeof(std::tuple<OveralignedFinal, NonEmptyFinal>) == 32);
+
+static_assert(sizeof(std::tuple<S, Overaligned>) == 16);
+static_assert(sizeof(std::tuple<Final, Overaligned>) == 16);
+static_assert(sizeof(std::tuple<NonEmpty, Overaligned>) == 16);
+static_assert(sizeof(std::tuple<NonEmptyFinal, Overaligned>) == 16);
+static_assert(sizeof(std::tuple<Overaligned, Overaligned>) == 32);
+static_assert(sizeof(std::tuple<OveralignedFinal, Overaligned>) == 16);
+
+static_assert(sizeof(std::tuple<S, OveralignedFinal>) == 16);
+static_assert(sizeof(std::tuple<Final, OveralignedFinal>) == 32);
+static_assert(sizeof(std::tuple<NonEmpty, OveralignedFinal>) == 32);
+static_assert(sizeof(std::tuple<NonEmptyFinal, OveralignedFinal>) == 32);
+static_assert(sizeof(std::tuple<Overaligned, OveralignedFinal>) == 16);
+static_assert(sizeof(std::tuple<OveralignedFinal, OveralignedFinal>) == 32);



More information about the libcxx-commits mailing list