[libcxx-commits] [libcxx] [libcxx] retain a version of basic_string::reserve(0) that shrinks (PR #74168)

David Tenty via libcxx-commits libcxx-commits at lists.llvm.org
Fri Dec 15 15:06:19 PST 2023


https://github.com/daltenty updated https://github.com/llvm/llvm-project/pull/74168

>From 379dc1721fdb20365a6a40a0cf490dc0bffeb2f6 Mon Sep 17 00:00:00 2001
From: David Tenty <daltenty at ibm.com>
Date: Thu, 30 Nov 2023 21:00:12 -0500
Subject: [PATCH 1/5] [libcxx] retain a version of basic_string::reserve(0)
 that shrinks

    Old (LLVM >=6) versions of the move assignment operator in basic string used
    to (indirectly) zero the size of the string then call reserve(0) to
    deallocate the memory they were holding. Implementing p0966r1 changed this by changing the contract of reserve() to never shrink, leading to memory leaks.

    This PR attempts to fix this situation by:
    1. reverting the shrinking behaviour in the restricted case where we reserve(0) on a zero-sized string (i.e. it has been cleared first)
    2. applying an ABI-tag to reserve with the new behaviour, so uses going forward will always get the C++20+ standard compliant non-shrinking reserve in all cases
---
 libcxx/include/__config                       |  3 ++
 libcxx/include/string                         | 10 +++++
 libcxx/lib/abi/CHANGELOG.TXT                  | 13 ++++++
 ...bcxxabi.v1.stable.exceptions.nonew.abilist |  2 +
 ...bcxxabi.v1.stable.exceptions.nonew.abilist |  2 +
 ...bcxxabi.v1.stable.exceptions.nonew.abilist |  2 +
 ...bcxxabi.v1.stable.exceptions.nonew.abilist |  2 +
 ...bcxxabi.v1.stable.exceptions.nonew.abilist |  2 +
 ...bcxxabi.v1.stable.exceptions.nonew.abilist |  2 +
 ...xxabi.v1.stable.noexceptions.nonew.abilist |  2 +
 libcxx/src/CMakeLists.txt                     |  1 +
 libcxx/src/string_compat.cpp                  | 25 +++++++++++
 .../reserve_with_shrink.pass.cpp              | 44 +++++++++++++++++++
 13 files changed, 110 insertions(+)
 create mode 100644 libcxx/src/string_compat.cpp
 create mode 100644 libcxx/test/libcxx/strings/basic.string/string.modifiers/reserve_with_shrink.pass.cpp

diff --git a/libcxx/include/__config b/libcxx/include/__config
index ee77305162f7fc..2c42bfbbb4b087 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -133,6 +133,9 @@
 // Re-worked external template instantiations for std::string with a focus on
 // performance and fast-path inlining.
 #    define _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION
+// Don't retain a copy of the old shrinking behaviour of basic_string::reserve(size_type)
+// and alter it's mangling for compatibility reasons.
+#    define _LIBCPP_ABI_DO_NOT_RETAIN_SHRINKING_RESERVE
 // Enable clang::trivial_abi on std::unique_ptr.
 #    define _LIBCPP_ABI_ENABLE_UNIQUE_PTR_TRIVIAL_ABI
 // Enable clang::trivial_abi on std::shared_ptr and std::weak_ptr
diff --git a/libcxx/include/string b/libcxx/include/string
index 25f307825fa28a..2e64a999bc73f6 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -1174,6 +1174,9 @@ public:
     _LIBCPP_CONSTEXPR_SINCE_CXX20 void resize(size_type __n, value_type __c);
     _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void resize(size_type __n) { resize(__n, value_type()); }
 
+#if !defined(_LIBCPP_ABI_DO_NOT_RETAIN_SHRINKING_RESERVE) && !defined(_LIBCPP_ENABLE_RESERVE_SHRINKING_ABI)
+    __attribute__((__abi_tag__("v2")))
+#endif
     _LIBCPP_CONSTEXPR_SINCE_CXX20 void reserve(size_type __requested_capacity);
 
 #if _LIBCPP_STD_VER >= 23
@@ -3226,11 +3229,18 @@ basic_string<_CharT, _Traits, _Allocator>::reserve(size_type __requested_capacit
     if (__requested_capacity > max_size())
         __throw_length_error();
 
+#if defined(_LIBCPP_ENABLE_RESERVE_SHRINKING_ABI)
+    // Shrink in the case of a zero-sized reserve on a cleared string, as we did before P0966R1,
+    // for compatibility with older versions of the move assignment operator that expected this.
+    if (!(__is_long() && __requested_capacity == 0 && size() == 0) && __requested_capacity <= capacity())
+        return;
+#else
     // Make sure reserve(n) never shrinks. This is technically only required in C++20
     // and later (since P0966R1), however we provide consistent behavior in all Standard
     // modes because this function is instantiated in the shared library.
     if (__requested_capacity <= capacity())
         return;
+#endif
 
     size_type __target_capacity = std::max(__requested_capacity, size());
     __target_capacity = __recommend(__target_capacity);
diff --git a/libcxx/lib/abi/CHANGELOG.TXT b/libcxx/lib/abi/CHANGELOG.TXT
index df4e5aa3859543..9b1f5cb2d9c496 100644
--- a/libcxx/lib/abi/CHANGELOG.TXT
+++ b/libcxx/lib/abi/CHANGELOG.TXT
@@ -16,6 +16,19 @@ New entries should be added directly below the "Version" header.
 Version 18.0
 ------------
 
+* [libcxx] retain a version of basic_string::reserve(0) that shrinks
+
+  This PR adds a different mangling for the version of basic_string<>::reserve(size_type) that
+  doesn't deallocates/shrinks. P0966R1 in C++20 requires we no longer do the shrink, but
+  certain versions of the move assignment operator in basic string for LLVM >= 6 used this
+  to free memory as part of the move, so we retain a restricted version of this with alternate
+  mangling for compatibility.
+
+  All platforms
+  -------------
+  Symbol added: _ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7reserveB2v2Em
+  Symbol added: _ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7reserveB2v2Em
+
 * [libc++] Simplify the implementation of locale::id
 
   This patch removes a symbol defined in the library for std::locale::id::__init().
diff --git a/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
index 8daad89f52e6f7..8c9afe2dfe6a1e 100644
--- a/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -954,6 +954,7 @@
 {'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7replaceEmmPKcm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7replaceEmmRKS5_mm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7replaceEmmmc', 'type': 'FUNC'}
+{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7reserveB2v2Em', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7reserveEm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE9__grow_byEmmmmmm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE9push_backEc', 'type': 'FUNC'}
@@ -992,6 +993,7 @@
 {'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7replaceEmmPKwm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7replaceEmmRKS5_mm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7replaceEmmmw', 'type': 'FUNC'}
+{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7reserveB2v2Em', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7reserveEm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE9__grow_byEmmmmmm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE9push_backEw', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
index 91976f500539da..aace62e32776d0 100644
--- a/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -1365,6 +1365,7 @@
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7replaceEmmPKcm', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7replaceEmmRKS5_mm', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7replaceEmmmc', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
+{'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7reserveB2v2Em', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7reserveEm', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE9__grow_byEmmmmmm', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE9push_backEc', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
@@ -1403,6 +1404,7 @@
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7replaceEmmPKwm', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7replaceEmmRKS5_mm', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7replaceEmmmw', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
+{'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7reserveB2v2Em', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7reserveEm', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE9__grow_byEmmmmmm', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE9push_backEw', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
index 8a98d42a2a1aa0..712bed447ee768 100644
--- a/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -1365,6 +1365,7 @@
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7replaceEmmPKcm', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7replaceEmmRKS5_mm', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7replaceEmmmc', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
+{'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7reserveB2v2Em', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7reserveEm', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE9__grow_byEmmmmmm', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE9push_backEc', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
@@ -1403,6 +1404,7 @@
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7replaceEmmPKwm', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7replaceEmmRKS5_mm', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7replaceEmmmw', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
+{'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7reserveB2v2Em', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7reserveEm', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE9__grow_byEmmmmmm', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'wEXP', 'is_defined': True, 'name': '_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE9push_backEw', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
index 0c06b5097b83f8..6a30e8ec7e38e0 100644
--- a/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -954,6 +954,7 @@
 {'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7replaceEmmPKcm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7replaceEmmRKS5_mm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7replaceEmmmc', 'type': 'FUNC'}
+{'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7reserveB2v2Em', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7reserveEm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE9__grow_byEmmmmmm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE9push_backEc', 'type': 'FUNC'}
@@ -992,6 +993,7 @@
 {'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7replaceEmmPKwm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7replaceEmmRKS5_mm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7replaceEmmmw', 'type': 'FUNC'}
+{'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7reserveB2v2Em', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7reserveEm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE9__grow_byEmmmmmm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE9push_backEw', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist
index 16658fdff54932..b8cb2f865650f9 100644
--- a/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -649,6 +649,7 @@
 {'is_defined': True, 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7replaceEmmPKcm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7replaceEmmRKS5_mm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7replaceEmmmc', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7reserveB2v2Em', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7reserveEm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE9__grow_byEmmmmmm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE9push_backEc', 'type': 'FUNC'}
@@ -687,6 +688,7 @@
 {'is_defined': True, 'name': '_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7replaceEmmPKwm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7replaceEmmRKS5_mm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7replaceEmmmw', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7reserveB2v2Em', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7reserveEm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE9__grow_byEmmmmmm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE9push_backEw', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist
index 49e3579614ee8c..f6918cbd83ebb0 100644
--- a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -647,6 +647,7 @@
 {'is_defined': True, 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7replaceEmmPKcm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7replaceEmmRKS5_mm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7replaceEmmmc', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7reserveB2v2Em', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7reserveEm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE9__grow_byEmmmmmm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE9push_backEc', 'type': 'FUNC'}
@@ -685,6 +686,7 @@
 {'is_defined': True, 'name': '_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7replaceEmmPKwm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7replaceEmmRKS5_mm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7replaceEmmmw', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7reserveB2v2Em', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7reserveEm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE9__grow_byEmmmmmm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE9push_backEw', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist
index 764e7c37daacb7..e1d67da005857e 100644
--- a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist
@@ -619,6 +619,7 @@
 {'is_defined': True, 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7replaceEmmPKcm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7replaceEmmRKS5_mm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7replaceEmmmc', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7reserveB2v2Em', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE7reserveEm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE9__grow_byEmmmmmm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE9push_backEc', 'type': 'FUNC'}
@@ -657,6 +658,7 @@
 {'is_defined': True, 'name': '_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7replaceEmmPKwm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7replaceEmmRKS5_mm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7replaceEmmmw', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7reserveB2v2Em', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE7reserveEm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE9__grow_byEmmmmmm', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNSt3__112basic_stringIwNS_11char_traitsIwEENS_9allocatorIwEEE9push_backEw', 'type': 'FUNC'}
diff --git a/libcxx/src/CMakeLists.txt b/libcxx/src/CMakeLists.txt
index be0113e6b0a585..5bf9b0fbfcead4 100644
--- a/libcxx/src/CMakeLists.txt
+++ b/libcxx/src/CMakeLists.txt
@@ -43,6 +43,7 @@ set(LIBCXX_SOURCES
   ryu/f2s.cpp
   stdexcept.cpp
   string.cpp
+  string_compat.cpp
   support/runtime/exception_fallback.ipp
   support/runtime/exception_glibcxx.ipp
   support/runtime/exception_libcxxabi.ipp
diff --git a/libcxx/src/string_compat.cpp b/libcxx/src/string_compat.cpp
new file mode 100644
index 00000000000000..84fd991859eef5
--- /dev/null
+++ b/libcxx/src/string_compat.cpp
@@ -0,0 +1,25 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#if !defined(_LIBCPP_ABI_DO_NOT_RETAIN_SHRINKING_RESERVE)
+
+// Instantiate a copy of the shrinking reserve implementation to maintain ABI compatibility for older versions of
+// basic_string which relied on this behavior in move assignment.
+#define _LIBCPP_ENABLE_RESERVE_SHRINKING_ABI
+#include <string>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+template _LIBCPP_EXPORTED_FROM_ABI void basic_string<char>::reserve(size_type);
+#   ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
+template _LIBCPP_EXPORTED_FROM_ABI void basic_string<wchar_t >::reserve(size_type);
+#   endif
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif
diff --git a/libcxx/test/libcxx/strings/basic.string/string.modifiers/reserve_with_shrink.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.modifiers/reserve_with_shrink.pass.cpp
new file mode 100644
index 00000000000000..ceac830c1af65f
--- /dev/null
+++ b/libcxx/test/libcxx/strings/basic.string/string.modifiers/reserve_with_shrink.pass.cpp
@@ -0,0 +1,44 @@
+//===----------------------------------------------------------------------===//
+//
+// 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>
+
+// Check reserve(0) with old mangling shrinks for compatibility if it exists.
+#if !defined(_LIBCPP_ABI_DO_NOT_RETAIN_SHRINKING_RESERVE)
+#define _LIBCPP_ENABLE_RESERVE_SHRINKING_ABI
+#include <string>
+#include <cassert>
+
+#include "test_macros.h"
+#include "min_allocator.h"
+
+bool test() {
+  std::string l = "Long string so that allocation definitely, for sure, absolutely happens. Probably.";
+  const char *c = l.c_str();
+
+  assert(l.__invariants());
+
+  l.clear();
+  assert(l.__invariants());
+  assert(l.size() == 0);
+
+  l.reserve(0);
+  assert(l.__invariants());
+  assert(l.size() == 0);
+  assert(c != l.c_str());
+
+  return true;
+}
+#else
+bool test() { return true; }
+#endif
+
+int main(int, char**) {
+  test();
+  return 0;
+}

>From 6e021baebfa36eb5b3015e9e003f0643a7a04974 Mon Sep 17 00:00:00 2001
From: David Tenty <daltenty at ibm.com>
Date: Fri, 1 Dec 2023 22:13:56 -0500
Subject: [PATCH 2/5] clang-format

---
 libcxx/src/string_compat.cpp                         |  8 ++++----
 .../string.modifiers/reserve_with_shrink.pass.cpp    | 12 ++++++------
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/libcxx/src/string_compat.cpp b/libcxx/src/string_compat.cpp
index 84fd991859eef5..5d4ab6923350cb 100644
--- a/libcxx/src/string_compat.cpp
+++ b/libcxx/src/string_compat.cpp
@@ -10,15 +10,15 @@
 
 // Instantiate a copy of the shrinking reserve implementation to maintain ABI compatibility for older versions of
 // basic_string which relied on this behavior in move assignment.
-#define _LIBCPP_ENABLE_RESERVE_SHRINKING_ABI
-#include <string>
+#  define _LIBCPP_ENABLE_RESERVE_SHRINKING_ABI
+#  include <string>
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
 template _LIBCPP_EXPORTED_FROM_ABI void basic_string<char>::reserve(size_type);
-#   ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
+#  ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
 template _LIBCPP_EXPORTED_FROM_ABI void basic_string<wchar_t >::reserve(size_type);
-#   endif
+#  endif
 
 _LIBCPP_END_NAMESPACE_STD
 
diff --git a/libcxx/test/libcxx/strings/basic.string/string.modifiers/reserve_with_shrink.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.modifiers/reserve_with_shrink.pass.cpp
index ceac830c1af65f..a8718567fd4a09 100644
--- a/libcxx/test/libcxx/strings/basic.string/string.modifiers/reserve_with_shrink.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.modifiers/reserve_with_shrink.pass.cpp
@@ -10,16 +10,16 @@
 
 // Check reserve(0) with old mangling shrinks for compatibility if it exists.
 #if !defined(_LIBCPP_ABI_DO_NOT_RETAIN_SHRINKING_RESERVE)
-#define _LIBCPP_ENABLE_RESERVE_SHRINKING_ABI
-#include <string>
-#include <cassert>
+#  define _LIBCPP_ENABLE_RESERVE_SHRINKING_ABI
+#  include <string>
+#  include <cassert>
 
-#include "test_macros.h"
-#include "min_allocator.h"
+#  include "test_macros.h"
+#  include "min_allocator.h"
 
 bool test() {
   std::string l = "Long string so that allocation definitely, for sure, absolutely happens. Probably.";
-  const char *c = l.c_str();
+  const char* c = l.c_str();
 
   assert(l.__invariants());
 

>From 10ab8155182e23ba2c0dbfdc49e69d5f7635009c Mon Sep 17 00:00:00 2001
From: David Tenty <daltenty at ibm.com>
Date: Fri, 15 Dec 2023 16:39:27 -0500
Subject: [PATCH 3/5] Mark test unsupported if we are using clang modules

---
 .../basic.string/string.modifiers/reserve_with_shrink.pass.cpp | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/libcxx/test/libcxx/strings/basic.string/string.modifiers/reserve_with_shrink.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.modifiers/reserve_with_shrink.pass.cpp
index a8718567fd4a09..89ad16acd2358e 100644
--- a/libcxx/test/libcxx/strings/basic.string/string.modifiers/reserve_with_shrink.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.modifiers/reserve_with_shrink.pass.cpp
@@ -8,6 +8,9 @@
 
 // <string>
 
+// modules builds should follow the new ABI
+// UNSUPPORTED: clang-modules-build
+
 // Check reserve(0) with old mangling shrinks for compatibility if it exists.
 #if !defined(_LIBCPP_ABI_DO_NOT_RETAIN_SHRINKING_RESERVE)
 #  define _LIBCPP_ENABLE_RESERVE_SHRINKING_ABI

>From 95bcc4b58c0cb5eadb77d70e8eb6f822b2069ff3 Mon Sep 17 00:00:00 2001
From: David Tenty <daltenty at ibm.com>
Date: Fri, 15 Dec 2023 17:46:24 -0500
Subject: [PATCH 4/5] Include __config early in the test

so we can query the ABI version properly.
---
 .../basic.string/string.modifiers/reserve_with_shrink.pass.cpp  | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/libcxx/test/libcxx/strings/basic.string/string.modifiers/reserve_with_shrink.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.modifiers/reserve_with_shrink.pass.cpp
index 89ad16acd2358e..677a75a16bcb26 100644
--- a/libcxx/test/libcxx/strings/basic.string/string.modifiers/reserve_with_shrink.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.modifiers/reserve_with_shrink.pass.cpp
@@ -11,6 +11,8 @@
 // modules builds should follow the new ABI
 // UNSUPPORTED: clang-modules-build
 
+#  include <__config>
+
 // Check reserve(0) with old mangling shrinks for compatibility if it exists.
 #if !defined(_LIBCPP_ABI_DO_NOT_RETAIN_SHRINKING_RESERVE)
 #  define _LIBCPP_ENABLE_RESERVE_SHRINKING_ABI

>From c2c0cc62d99c6536a5cf34d19b0e75fa0eb0bfb5 Mon Sep 17 00:00:00 2001
From: David Tenty <daltenty at ibm.com>
Date: Fri, 15 Dec 2023 18:06:00 -0500
Subject: [PATCH 5/5] fix format

---
 .../basic.string/string.modifiers/reserve_with_shrink.pass.cpp  | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/test/libcxx/strings/basic.string/string.modifiers/reserve_with_shrink.pass.cpp b/libcxx/test/libcxx/strings/basic.string/string.modifiers/reserve_with_shrink.pass.cpp
index 677a75a16bcb26..53e69f78f7a482 100644
--- a/libcxx/test/libcxx/strings/basic.string/string.modifiers/reserve_with_shrink.pass.cpp
+++ b/libcxx/test/libcxx/strings/basic.string/string.modifiers/reserve_with_shrink.pass.cpp
@@ -11,7 +11,7 @@
 // modules builds should follow the new ABI
 // UNSUPPORTED: clang-modules-build
 
-#  include <__config>
+#include <__config>
 
 // Check reserve(0) with old mangling shrinks for compatibility if it exists.
 #if !defined(_LIBCPP_ABI_DO_NOT_RETAIN_SHRINKING_RESERVE)



More information about the libcxx-commits mailing list