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

David Tenty via libcxx-commits libcxx-commits at lists.llvm.org
Tue Dec 19 12:02:13 PST 2023


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

>From 15a319ae34d11c61fd886de8d3a67f3dd04aafbb 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/7] [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 adff13e714cb64..98618183b2b238 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 fdffca5aed18be..0b3cae0bb59ffe 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -1195,6 +1195,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
@@ -3194,11 +3197,18 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::re
   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 d912b1e8328a9e6a27739506e5767e3642daacc4 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/7] 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 731f40e26ecfff54ab0dad396f71c37a86aec142 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/7] 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 a5762a6289895ccbedaa5a25d56998c137dc97d0 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/7] 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 b2c796368d0e7295d3cef29267828b13e8d92514 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/7] 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)

>From e639cb0a4931ef901e24ed242863c538a5e696ec Mon Sep 17 00:00:00 2001
From: David Tenty <daltenty at ibm.com>
Date: Mon, 18 Dec 2023 23:48:50 -0500
Subject: [PATCH 6/7] Add availability macros for back deployment scenarios

---
 libcxx/include/__availability                   | 5 +++++
 libcxx/include/__string/extern_template_lists.h | 4 +++-
 libcxx/include/string                           | 2 ++
 libcxx/src/string.cpp                           | 2 ++
 4 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/libcxx/include/__availability b/libcxx/include/__availability
index e9904275e73414..8f81a8291cd2b5 100644
--- a/libcxx/include/__availability
+++ b/libcxx/include/__availability
@@ -149,6 +149,8 @@
 #    define _LIBCPP_AVAILABILITY_HAS_ADDITIONAL_IOSTREAM_EXPLICIT_INSTANTIATIONS_1 0
 #  endif
 
+#define _LIBCPP_AVAILABILITY_HAS_BASIC_STRING_RESERVE_V2_EXPLICIT_INSTANTIATIONS_ 1
+
 #elif defined(__APPLE__)
 
 #  define _LIBCPP_AVAILABILITY_HAS_BAD_OPTIONAL_ACCESS                                                                 \
@@ -268,6 +270,9 @@
 #  else
 #    define _LIBCPP_AVAILABILITY_HAS_ADDITIONAL_IOSTREAM_EXPLICIT_INSTANTIATIONS_1 1
 #  endif
+
+// TODO: Update once this is released
+#  define _LIBCPP_AVAILABILITY_HAS_BASIC_STRING_RESERVE_V2_EXPLICIT_INSTANTIATIONS_ 0
 #else
 
 // ...New vendors can add availability markup here...
diff --git a/libcxx/include/__string/extern_template_lists.h b/libcxx/include/__string/extern_template_lists.h
index cc536e514d4ffe..597d73b6342d68 100644
--- a/libcxx/include/__string/extern_template_lists.h
+++ b/libcxx/include/__string/extern_template_lists.h
@@ -47,7 +47,6 @@
   _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>::size_type basic_string<_CharType>::find_first_of(value_type const*, size_type, size_type) const) \
   _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, size_type, value_type)) \
   _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::assign(value_type const*, size_type)) \
-  _Func(_LIBCPP_EXPORTED_FROM_ABI void basic_string<_CharType>::reserve(size_type)) \
   _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::append(value_type const*, size_type)) \
   _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::assign(basic_string const&, size_type, size_type)) \
   _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>::size_type basic_string<_CharType>::copy(value_type*, size_type, size_type) const) \
@@ -79,6 +78,9 @@
   _Func(_LIBCPP_EXPORTED_FROM_ABI void basic_string<_CharType>::resize(size_type, value_type)) \
   _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::insert(size_type, basic_string const&, size_type, size_type))
 
+#define _LIBCPP_STRING_V1_BASIC_STRING_RESERVE_EXTERN_TEMPLATE_LIST(_Func, _CharType) \
+  _Func(_LIBCPP_EXPORTED_FROM_ABI void basic_string<_CharType>::reserve(size_type))
+
 #define _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_Func, _CharType) \
   _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, value_type const*, size_type)) \
   _Func(_LIBCPP_EXPORTED_FROM_ABI basic_string<_CharType>::size_type basic_string<_CharType>::rfind(value_type const*, size_type, size_type) const) \
diff --git a/libcxx/include/string b/libcxx/include/string
index 0b3cae0bb59ffe..a5a430a53d9d56 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -2127,8 +2127,10 @@ private:
 #define _LIBCPP_DECLARE(...) extern template __VA_ARGS__;
 #ifdef _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION
 _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_DECLARE, char)
+_LIBCPP_STRING_V1_BASIC_STRING_RESERVE_EXTERN_TEMPLATE_LIST(_LIBCPP_DECLARE, char)
 #  ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
 _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_DECLARE, wchar_t)
+_LIBCPP_STRING_V1_BASIC_STRING_RESERVE_EXTERN_TEMPLATE_LIST(_LIBCPP_DECLARE, wchar_t)
 #  endif
 #else
 _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_DECLARE, char)
diff --git a/libcxx/src/string.cpp b/libcxx/src/string.cpp
index cf07b3ef1ef270..7dc451b0419b3c 100644
--- a/libcxx/src/string.cpp
+++ b/libcxx/src/string.cpp
@@ -45,8 +45,10 @@ _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wch
 #  endif
 #else
 _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char)
+_LIBCPP_STRING_V1_BASIC_STRING_RESERVE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char)
 #  ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
 _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wchar_t)
+_LIBCPP_STRING_V1_BASIC_STRING_RESERVE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wchar_t)
 #  endif
 #endif
 #undef _LIBCPP_EXTERN_TEMPLATE_DEFINE

>From c57afba87b5386b0d64b3bd1998a0453679be6d3 Mon Sep 17 00:00:00 2001
From: David Tenty <daltenty at ibm.com>
Date: Tue, 19 Dec 2023 14:45:28 -0500
Subject: [PATCH 7/7] Fix mistake in where the reserve extern template macro is
 expanded

---
 libcxx/include/string | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libcxx/include/string b/libcxx/include/string
index a5a430a53d9d56..de6c582367d87b 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -2127,15 +2127,15 @@ private:
 #define _LIBCPP_DECLARE(...) extern template __VA_ARGS__;
 #ifdef _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION
 _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_DECLARE, char)
-_LIBCPP_STRING_V1_BASIC_STRING_RESERVE_EXTERN_TEMPLATE_LIST(_LIBCPP_DECLARE, char)
 #  ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
 _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_DECLARE, wchar_t)
-_LIBCPP_STRING_V1_BASIC_STRING_RESERVE_EXTERN_TEMPLATE_LIST(_LIBCPP_DECLARE, wchar_t)
 #  endif
 #else
 _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_DECLARE, char)
+_LIBCPP_STRING_V1_BASIC_STRING_RESERVE_EXTERN_TEMPLATE_LIST(_LIBCPP_DECLARE, char)
 #  ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
 _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_DECLARE, wchar_t)
+_LIBCPP_STRING_V1_BASIC_STRING_RESERVE_EXTERN_TEMPLATE_LIST(_LIBCPP_DECLARE, wchar_t)
 #  endif
 #endif
 #undef _LIBCPP_DECLARE



More information about the libcxx-commits mailing list