[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 23:13:20 PDT 2025


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

>From 1a23b359fdf69a4e16017f3ed8b422fc1e692438 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      |  28 +++-
 .../unord.map/abi.compile.pass.cpp            |  50 ++++++-
 .../utilities/tuple/abi.compile.pass.cpp      | 124 ++++++++++++++++++
 3 files changed, 193 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..15ab4ade830c7 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,18 @@ 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;
+};
+
+static_assert(std::is_empty<std::__map_value_compare<int, std::pair<const int, int>, std::less<int>>>::value);
+static_assert(std::is_empty<std::__map_value_compare<int, std::pair<const int, int>, AlignedLess>>::value);
+static_assert(!std::is_empty<std::__map_value_compare<int, std::pair<const int, int>, FinalLess>>::value);
+static_assert(!std::is_empty<std::__map_value_compare<int, std::pair<const int, int>, NonEmptyLess>>::value);
+
 #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 +132,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 +173,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..4a9224eb6f327 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,29 @@ 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;
+};
+
+static_assert(std::is_empty<std::__unordered_map_hasher<int, std::pair<const int, int>, std::hash<int>, int>>::value);
+static_assert(std::is_empty<std::__unordered_map_hasher<int, std::pair<const int, int>, AlignedHash, int>>::value);
+static_assert(!std::is_empty<std::__unordered_map_hasher<int, std::pair<const int, int>, FinalHash, int>>::value);
+static_assert(!std::is_empty<std::__unordered_map_hasher<int, std::pair<const int, int>, NonEmptyHash, int>>::value);
+
+static_assert(std::is_empty<std::__unordered_map_equal<int, std::pair<const int, int>, std::hash<int>, int>>::value);
+static_assert(std::is_empty<std::__unordered_map_equal<int, std::pair<const int, int>, AlignedHash, int>>::value);
+static_assert(!std::is_empty<std::__unordered_map_equal<int, std::pair<const int, int>, FinalHash, int>>::value);
+static_assert(!std::is_empty<std::__unordered_map_equal<int, std::pair<const int, int>, NonEmptyHash, int>>::value);
+
 #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 +148,20 @@ 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 {};
+#ifdef TEST_COMPILER_GCC
+static_assert(sizeof(std::unordered_map<int, int, FinalHash, UnalignedEqualTo>) == 40, "");
+#else
+static_assert(sizeof(std::unordered_map<int, int, FinalHash, UnalignedEqualTo>) == 48, "");
+#endif
+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 +204,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..467214a0779db
--- /dev/null
+++ b/libcxx/test/libcxx/utilities/tuple/abi.compile.pass.cpp
@@ -0,0 +1,124 @@
+//===----------------------------------------------------------------------===//
+//
+// 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: c++03
+
+// UNSUPPORTED: libcpp-abi-no-compressed-pair-padding
+
+#include <tuple>
+#include <type_traits>
+
+#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(std::is_empty<std::tuple<>>::value, "");
+static_assert(!std::is_empty<std::tuple<S>>::value, "");
+static_assert(!std::is_empty<std::tuple<S&>>::value, "");
+static_assert(!std::is_empty<std::tuple<S&&>>::value, "");
+static_assert(!std::is_empty<std::tuple<Final>>::value, "");
+static_assert(!std::is_empty<std::tuple<NonEmpty>>::value, "");
+static_assert(!std::is_empty<std::tuple<NonEmptyFinal>>::value, "");
+static_assert(!std::is_empty<std::tuple<Overaligned>>::value, "");
+static_assert(!std::is_empty<std::tuple<OveralignedFinal>>::value, "");
+
+static_assert(sizeof(std::tuple<S>) == 1, "");
+static_assert(sizeof(std::tuple<S&>) == sizeof(void*), "");
+static_assert(sizeof(std::tuple<S&&>) == sizeof(void*), "");
+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<S&, S>) == sizeof(void*), "");
+static_assert(sizeof(std::tuple<S&&, S>) == sizeof(void*), "");
+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, S&>) == sizeof(void*), "");
+static_assert(sizeof(std::tuple<S&, S&>) == 2 * sizeof(void*), "");
+static_assert(sizeof(std::tuple<S&&, S&>) == 2 * sizeof(void*), "");
+static_assert(sizeof(std::tuple<Final, S&>) == 2 * sizeof(void*), "");
+static_assert(sizeof(std::tuple<NonEmpty, S&>) == 8 + sizeof(void*), "");
+static_assert(sizeof(std::tuple<NonEmptyFinal, S&>) == 8 + sizeof(void*), "");
+static_assert(sizeof(std::tuple<Overaligned, S&>) == 16, "");
+static_assert(sizeof(std::tuple<OveralignedFinal, S&>) == 32, "");
+
+static_assert(sizeof(std::tuple<S, S&&>) == sizeof(void*), "");
+static_assert(sizeof(std::tuple<S&, S&&>) == 2 * sizeof(void*), "");
+static_assert(sizeof(std::tuple<S&&, S&&>) == 2 * sizeof(void*), "");
+static_assert(sizeof(std::tuple<Final, S&&>) == 2 * sizeof(void*), "");
+static_assert(sizeof(std::tuple<NonEmpty, S&&>) == 8 + sizeof(void*), "");
+static_assert(sizeof(std::tuple<NonEmptyFinal, S&&>) == 8 + sizeof(void*), "");
+static_assert(sizeof(std::tuple<Overaligned, S&&>) == 16, "");
+static_assert(sizeof(std::tuple<OveralignedFinal, S&&>) == 32, "");
+
+static_assert(sizeof(std::tuple<S, Final>) == 1, "");
+static_assert(sizeof(std::tuple<S&, Final>) == 2 * sizeof(void*), "");
+static_assert(sizeof(std::tuple<S&&, Final>) == 2 * sizeof(void*), "");
+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<S&, NonEmpty>) == sizeof(void*) + 8, "");
+static_assert(sizeof(std::tuple<S&&, NonEmpty>) == sizeof(void*) + 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<S&, NonEmptyFinal>) == sizeof(void*) + 8, "");
+static_assert(sizeof(std::tuple<S&&, NonEmptyFinal>) == sizeof(void*) + 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<S&, Overaligned>) == 16, "");
+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<S&, OveralignedFinal>) == 32, "");
+static_assert(sizeof(std::tuple<S&&, OveralignedFinal>) == 32, "");
+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