Skip to content

Commit 8573d06

Browse files
committed
[libc++][string] Assert resize_and_overwrite operation returns integer-like type
Verify that the operation passed to resize_and_overwrite returns an integer-like type, matching the behavior of other standard library implementations like GCC's libstdc++ Fixes #160577
1 parent 4d45718 commit 8573d06

File tree

3 files changed

+65
-2
lines changed

3 files changed

+65
-2
lines changed

libcxx/include/string

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1311,6 +1311,8 @@ public:
13111311
# if _LIBCPP_STD_VER >= 23
13121312
template <class _Op>
13131313
_LIBCPP_HIDE_FROM_ABI constexpr void resize_and_overwrite(size_type __n, _Op __op) {
1314+
using __result_type = decltype(std::move(__op)(data(), auto(__n)));
1315+
static_assert(__integer_like<__result_type>, "Operation return type must be integer-like");
13141316
size_type __sz = size();
13151317
size_type __cap = capacity();
13161318
if (__n > __cap)

libcxx/test/std/strings/basic.string/string.capacity/resize_and_overwrite.pass.cpp

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <cassert>
1818
#include <memory>
1919
#include <string>
20+
#include <type_algorithms.h>
2021

2122
#include "make_string.h"
2223
#include "test_macros.h"
@@ -77,17 +78,30 @@ constexpr bool test() {
7778
return true;
7879
}
7980

80-
void test_value_categories() {
81+
constexpr bool test_value_categories() {
8182
std::string s;
8283
s.resize_and_overwrite(10, [](char*&&, std::size_t&&) { return 0; });
8384
LIBCPP_ASSERT(is_string_asan_correct(s));
8485
s.resize_and_overwrite(10, [](char* const&, const std::size_t&) { return 0; });
8586
LIBCPP_ASSERT(is_string_asan_correct(s));
8687
struct RefQualified {
87-
int operator()(char*, std::size_t) && { return 0; }
88+
constexpr int operator()(char*, std::size_t) && { return 0; }
8889
};
8990
s.resize_and_overwrite(10, RefQualified{});
9091
LIBCPP_ASSERT(is_string_asan_correct(s));
92+
return true;
93+
}
94+
95+
constexpr bool test_integer_like_return_types() {
96+
types::for_each(types::integer_types(), []<typename IntegerType> {
97+
std::string s;
98+
s.resize_and_overwrite(10, [](char* p, std::size_t n) -> IntegerType {
99+
std::fill(p, p + n, 'f');
100+
return n;
101+
});
102+
assert(s.size() == 10);
103+
});
104+
return true;
91105
}
92106

93107
int main(int, char**) {
@@ -105,5 +119,12 @@ int main(int, char**) {
105119
test<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t>>>();
106120
static_assert(test<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t>>>());
107121
#endif
122+
123+
test_value_categories();
124+
test_integer_like_return_types();
125+
126+
static_assert(test_value_categories());
127+
static_assert(test_integer_like_return_types());
128+
108129
return 0;
109130
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
10+
11+
// <string>
12+
13+
// template<class Operation>
14+
// void resize_and_overwrite(size_type n, Operation op)
15+
16+
// Verify that the operation's return type must be integer-like
17+
18+
#include <string>
19+
20+
void test_bool_return_type() {
21+
std::string s;
22+
s.resize_and_overwrite(10, [](char*, std::size_t) {
23+
return true; // expected-error-re@*:* {{{{(static_assertion|static assertion)}}{{.*}}integer-like}}
24+
});
25+
}
26+
27+
void test_pointer_return_type() {
28+
std::string s;
29+
s.resize_and_overwrite(10, [](char* p, std::size_t) {
30+
return p; // expected-error-re@*:* {{{{(static_assertion|static assertion)}}{{.*}}integer-like}}
31+
// expected-error@*:* {{cannot initialize}}
32+
});
33+
}
34+
35+
void test_float_return_type() {
36+
std::string s;
37+
s.resize_and_overwrite(10, [](char*, std::size_t) {
38+
return 5.0f; // expected-error-re@*:* {{{{(static_assertion|static assertion)}}{{.*}}integer-like}}
39+
});
40+
}

0 commit comments

Comments
 (0)