[libcxx-commits] [libcxx] [libc++] Base string's alignment on __STDCPP_DEFAULT_NEW_ALIGNMENT__ (PR #171785)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Wed Jan 28 00:59:49 PST 2026


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

>From edcd72083ffbc9b4ac6a19cffde550a0b36784e2 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Thu, 11 Dec 2025 10:14:52 +0100
Subject: [PATCH] [libc++] Base string's alignment on
 __STDCPP_DEFAULT_NEW_ALIGNMENT__

---
 libcxx/include/string                         |  10 +-
 .../string.capacity/allocation_size.pass.cpp  |  37 ------
 .../string.capacity/max_size.pass.cpp         | 117 ------------------
 .../string.capacity/allocation_size.pass.cpp  |   7 +-
 .../string.capacity/max_size.pass.cpp         |   7 +-
 5 files changed, 19 insertions(+), 159 deletions(-)
 delete mode 100644 libcxx/test/libcxx-03/strings/basic.string/string.capacity/allocation_size.pass.cpp
 delete mode 100644 libcxx/test/libcxx-03/strings/basic.string/string.capacity/max_size.pass.cpp

diff --git a/libcxx/include/string b/libcxx/include/string
index c4bf970e55004..531185da2c4cf 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -2364,7 +2364,15 @@ private:
   static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 size_type __align_it(size_type __s) _NOEXCEPT {
     return (__s + (__a - 1)) & ~(__a - 1);
   }
-  enum { __alignment = 8 };
+
+#  ifdef __STDCPP_DEFAULT_NEW_ALIGNMENT__
+  static inline const size_t
+      __alignment = __is_std_allocator_v<allocator_type> && __STDCPP_DEFAULT_NEW_ALIGNMENT__ > sizeof(void*)
+                      ? __STDCPP_DEFAULT_NEW_ALIGNMENT__
+                      : sizeof(void*);
+#  else
+  static inline const size_t __alignment = sizeof(void*);
+#  endif
 
   // This makes sure that we're using a capacity with some extra alignment, since allocators almost always over-align
   // the allocations anyways, improving memory usage. More importantly, this ensures that the lowest bit is never set
diff --git a/libcxx/test/libcxx-03/strings/basic.string/string.capacity/allocation_size.pass.cpp b/libcxx/test/libcxx-03/strings/basic.string/string.capacity/allocation_size.pass.cpp
deleted file mode 100644
index 77da29225957b..0000000000000
--- a/libcxx/test/libcxx-03/strings/basic.string/string.capacity/allocation_size.pass.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-// <string>
-
-#include <algorithm>
-#include <cassert>
-#include <cstddef>
-#include <string>
-
-#include "test_macros.h"
-
-// alignment of the string heap buffer is hardcoded to 8
-const std::size_t alignment = 8;
-
-int main(int, char**) {
-  std::string input_string;
-  input_string.resize(64, 'a');
-
-  // Call a constructor which selects its size using __recommend.
-  std::string test_string(input_string.data());
-  const std::size_t expected_align8_size = 71;
-
-  // Demonstrate the lesser capacity/allocation size when the alignment requirement is 8.
-  if (alignment == 8) {
-    assert(test_string.capacity() == expected_align8_size);
-  } else {
-    assert(test_string.capacity() == expected_align8_size + 8);
-  }
-
-  return 0;
-}
diff --git a/libcxx/test/libcxx-03/strings/basic.string/string.capacity/max_size.pass.cpp b/libcxx/test/libcxx-03/strings/basic.string/string.capacity/max_size.pass.cpp
deleted file mode 100644
index 73825ef4845f2..0000000000000
--- a/libcxx/test/libcxx-03/strings/basic.string/string.capacity/max_size.pass.cpp
+++ /dev/null
@@ -1,117 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-// <string>
-
-// This test ensures that the correct max_size() is returned depending on the platform.
-
-#include <algorithm>
-#include <cassert>
-#include <cstddef>
-#include <string>
-
-#include "test_macros.h"
-
-// alignment of the string heap buffer is hardcoded to 8
-static const std::size_t alignment = 8;
-
-template <class = int>
-TEST_CONSTEXPR_CXX20 void full_size() {
-  std::string str;
-  assert(str.max_size() == std::numeric_limits<std::size_t>::max() - alignment - 1);
-
-#ifndef TEST_HAS_NO_CHAR8_T
-  std::u8string u8str;
-  assert(u8str.max_size() == std::numeric_limits<std::size_t>::max() - alignment - 1);
-#endif
-
-#ifndef TEST_HAS_NO_WIDE_CHARACTERS
-  std::wstring wstr;
-  assert(wstr.max_size() ==
-         ((std::numeric_limits<std::size_t>::max() / sizeof(wchar_t) - alignment) & ~std::size_t(1)) - 1);
-#endif
-
-  std::u16string u16str;
-  std::u32string u32str;
-  assert(u16str.max_size() == ((std::numeric_limits<std::size_t>::max() / 2 - alignment) & ~std::size_t(1)) - 1);
-  assert(u32str.max_size() == ((std::numeric_limits<std::size_t>::max() / 4 - alignment) & ~std::size_t(1)) - 1);
-}
-
-template <class = int>
-TEST_CONSTEXPR_CXX20 void half_size() {
-  std::string str;
-  assert(str.max_size() == std::numeric_limits<std::size_t>::max() / 2 - alignment - 1);
-
-#ifndef TEST_HAS_NO_CHAR8_T
-  std::u8string u8str;
-  assert(u8str.max_size() == std::numeric_limits<std::size_t>::max() / 2 - alignment - 1);
-#endif
-
-#ifndef TEST_HAS_NO_WIDE_CHARACTERS
-  std::wstring wstr;
-  assert(wstr.max_size() ==
-         std::numeric_limits<std::size_t>::max() / std::max<size_t>(2ul, sizeof(wchar_t)) - alignment - 1);
-#endif
-
-  std::u16string u16str;
-  std::u32string u32str;
-  assert(u16str.max_size() == std::numeric_limits<std::size_t>::max() / 2 - alignment - 1);
-  assert(u32str.max_size() == std::numeric_limits<std::size_t>::max() / 4 - alignment - 1);
-}
-
-TEST_CONSTEXPR_CXX20 bool test() {
-#if _LIBCPP_ABI_VERSION == 1
-
-#  if defined(__x86_64__) || defined(__i386__)
-  full_size();
-#  elif defined(__APPLE__) && defined(__aarch64__)
-  half_size();
-#  elif defined(__arm__) || defined(__aarch64__)
-#    ifdef __BIG_ENDIAN__
-  half_size();
-#    else
-  full_size();
-#    endif
-#  elif defined(__powerpc__) || defined(__powerpc64__)
-#    ifdef __BIG_ENDIAN__
-  half_size();
-#    else
-  full_size();
-#    endif
-#  elif defined(__sparc64__)
-  half_size();
-#  elif defined(__riscv)
-  full_size();
-#  elif defined(_WIN32)
-  full_size();
-#  else
-#    error "Your target system seems to be unsupported."
-#  endif
-
-#else
-
-#  if defined(__arm__) || defined(__aarch64__)
-#    ifdef __BIG_ENDIAN__
-  full_size();
-#    else
-  half_size();
-#    endif
-#  else
-  half_size();
-#  endif
-
-#endif
-
-  return true;
-}
-
-int main(int, char**) {
-  test();
-
-  return 0;
-}
diff --git a/libcxx/test/libcxx/strings/basic.string/string.capacity/allocation_size.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.capacity/allocation_size.pass.cpp
index 77da29225957b..367a58897cec0 100644
--- a/libcxx/test/libcxx/strings/basic.string/string.capacity/allocation_size.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.capacity/allocation_size.pass.cpp
@@ -15,8 +15,11 @@
 
 #include "test_macros.h"
 
-// alignment of the string heap buffer is hardcoded to 8
-const std::size_t alignment = 8;
+#ifdef __STDCPP_DEFAULT_NEW_ALIGNMENT__
+static const std::size_t alignment = __STDCPP_DEFAULT_NEW_ALIGNMENT__;
+#else
+static const std::size_t alginment = 8;
+#endif
 
 int main(int, char**) {
   std::string input_string;
diff --git a/libcxx/test/libcxx/strings/basic.string/string.capacity/max_size.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.capacity/max_size.pass.cpp
index 6bfcb5d4bfcd8..ea4520031475b 100644
--- a/libcxx/test/libcxx/strings/basic.string/string.capacity/max_size.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.capacity/max_size.pass.cpp
@@ -17,8 +17,11 @@
 
 #include "test_macros.h"
 
-// alignment of the string heap buffer is hardcoded to 8
-static const std::size_t alignment = 8;
+#ifdef __STDCPP_DEFAULT_NEW_ALIGNMENT__
+static const std::size_t alignment = __STDCPP_DEFAULT_NEW_ALIGNMENT__;
+#else
+static const std::size_t alginment = 8;
+#endif
 
 template <class = int>
 TEST_CONSTEXPR_CXX20 void full_size() {



More information about the libcxx-commits mailing list