Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[libc++] Make sure basic_string::reserve(n) never shrinks in all Stan…
…dard modes Since basic_string::reserve(n) is instantiated in the shared library but also available to the compiler for inlining, its definition should not depend on things like the Standard mode in use. Indeed, that flag may not match between how the shared library is compiled and how users are compiling their own code, resulting in ODR violations. However, note that we retain the behavior of basic_string::reserve() to shrink the string for backwards compatibility reasons. While it would technically be conforming to not shrink, we believe user expectation is for it to shrink, and so existing code might have been written based on that assumption. We prefer to not break such code, even though that makes basic_string::reserve() and basic_string::reserve(0) not equivalent anymore. Fixes llvm-project#53170 Differential Revision: https://reviews.llvm.org/D117332
- Loading branch information
Showing
4 changed files
with
96 additions
and
54 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
79 changes: 79 additions & 0 deletions
79
libcxx/test/libcxx/strings/basic.string/string.capacity/PR53170.pass.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
// <string> | ||
|
||
// void reserve(); // Deprecated in C++20. | ||
// void reserve(size_type); | ||
|
||
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS | ||
|
||
// This test ensures that libc++ implements https://wg21.link/P0966R1 (reserve never shrinks) | ||
// even before C++20. This is required in order to avoid ODR violations because basic_string::reserve(size) | ||
// is compiled into the shared library. Hence, it needs to have the same definition in all Standard modes. | ||
// | ||
// However, note that reserve() does shrink, and it does so in all Standard modes. | ||
// | ||
// Reported as https://llvm.org/PR53170. | ||
|
||
// reserve(n) used to shrink the string until https://llvm.org/D117332 was shipped. | ||
// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11|12|13|14|15}} | ||
// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{11|12}} | ||
|
||
#include <string> | ||
#include <stdexcept> | ||
#include <cassert> | ||
|
||
#include "test_macros.h" | ||
#include "min_allocator.h" | ||
|
||
template <class S> | ||
void test() { | ||
// Test that a call to reserve() does shrink the string. | ||
{ | ||
S s(1000, 'a'); | ||
typename S::size_type old_cap = s.capacity(); | ||
s.resize(20); | ||
assert(s.capacity() == old_cap); | ||
|
||
s.reserve(); | ||
assert(s.capacity() < old_cap); | ||
} | ||
|
||
// Test that a call to reserve(smaller-than-capacity) never shrinks the string. | ||
{ | ||
S s(1000, 'a'); | ||
typename S::size_type old_cap = s.capacity(); | ||
s.resize(20); | ||
assert(s.capacity() == old_cap); | ||
|
||
s.reserve(10); | ||
assert(s.capacity() == old_cap); | ||
} | ||
|
||
// In particular, test that reserve(0) does NOT shrink the string. | ||
{ | ||
S s(1000, 'a'); | ||
typename S::size_type old_cap = s.capacity(); | ||
s.resize(20); | ||
assert(s.capacity() == old_cap); | ||
|
||
s.reserve(0); | ||
assert(s.capacity() == old_cap); | ||
} | ||
} | ||
|
||
int main(int, char**) { | ||
test<std::string>(); | ||
|
||
#if TEST_STD_VER >= 11 | ||
test<std::basic_string<char, std::char_traits<char>, min_allocator<char> > >(); | ||
#endif | ||
|
||
return 0; | ||
} |
50 changes: 0 additions & 50 deletions
50
libcxx/test/libcxx/strings/basic.string/string.capacity/reserve.pass.cpp
This file was deleted.
Oops, something went wrong.