From 8573d060e79e34e4826546dedf3a82f90ccdd558 Mon Sep 17 00:00:00 2001 From: NagaChaitanya Vellanki Date: Sun, 5 Oct 2025 15:33:46 -0700 Subject: [PATCH] [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 --- libcxx/include/string | 2 + .../resize_and_overwrite.pass.cpp | 25 +++++++++++- .../resize_and_overwrite.verify.cpp | 40 +++++++++++++++++++ 3 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 libcxx/test/std/strings/basic.string/string.capacity/resize_and_overwrite.verify.cpp diff --git a/libcxx/include/string b/libcxx/include/string index 363f27a51648c..5f1662b87f1bc 100644 --- a/libcxx/include/string +++ b/libcxx/include/string @@ -1311,6 +1311,8 @@ public: # if _LIBCPP_STD_VER >= 23 template _LIBCPP_HIDE_FROM_ABI constexpr void resize_and_overwrite(size_type __n, _Op __op) { + using __result_type = decltype(std::move(__op)(data(), auto(__n))); + static_assert(__integer_like<__result_type>, "Operation return type must be integer-like"); size_type __sz = size(); size_type __cap = capacity(); if (__n > __cap) diff --git a/libcxx/test/std/strings/basic.string/string.capacity/resize_and_overwrite.pass.cpp b/libcxx/test/std/strings/basic.string/string.capacity/resize_and_overwrite.pass.cpp index abd284852a189..aca5644ef7094 100644 --- a/libcxx/test/std/strings/basic.string/string.capacity/resize_and_overwrite.pass.cpp +++ b/libcxx/test/std/strings/basic.string/string.capacity/resize_and_overwrite.pass.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include "make_string.h" #include "test_macros.h" @@ -77,17 +78,30 @@ constexpr bool test() { return true; } -void test_value_categories() { +constexpr bool test_value_categories() { std::string s; s.resize_and_overwrite(10, [](char*&&, std::size_t&&) { return 0; }); LIBCPP_ASSERT(is_string_asan_correct(s)); s.resize_and_overwrite(10, [](char* const&, const std::size_t&) { return 0; }); LIBCPP_ASSERT(is_string_asan_correct(s)); struct RefQualified { - int operator()(char*, std::size_t) && { return 0; } + constexpr int operator()(char*, std::size_t) && { return 0; } }; s.resize_and_overwrite(10, RefQualified{}); LIBCPP_ASSERT(is_string_asan_correct(s)); + return true; +} + +constexpr bool test_integer_like_return_types() { + types::for_each(types::integer_types(), [] { + std::string s; + s.resize_and_overwrite(10, [](char* p, std::size_t n) -> IntegerType { + std::fill(p, p + n, 'f'); + return n; + }); + assert(s.size() == 10); + }); + return true; } int main(int, char**) { @@ -105,5 +119,12 @@ int main(int, char**) { test, std::allocator>>(); static_assert(test, std::allocator>>()); #endif + + test_value_categories(); + test_integer_like_return_types(); + + static_assert(test_value_categories()); + static_assert(test_integer_like_return_types()); + return 0; } diff --git a/libcxx/test/std/strings/basic.string/string.capacity/resize_and_overwrite.verify.cpp b/libcxx/test/std/strings/basic.string/string.capacity/resize_and_overwrite.verify.cpp new file mode 100644 index 0000000000000..1345fde296a20 --- /dev/null +++ b/libcxx/test/std/strings/basic.string/string.capacity/resize_and_overwrite.verify.cpp @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// + +// template +// void resize_and_overwrite(size_type n, Operation op) + +// Verify that the operation's return type must be integer-like + +#include + +void test_bool_return_type() { + std::string s; + s.resize_and_overwrite(10, [](char*, std::size_t) { + return true; // expected-error-re@*:* {{{{(static_assertion|static assertion)}}{{.*}}integer-like}} + }); +} + +void test_pointer_return_type() { + std::string s; + s.resize_and_overwrite(10, [](char* p, std::size_t) { + return p; // expected-error-re@*:* {{{{(static_assertion|static assertion)}}{{.*}}integer-like}} + // expected-error@*:* {{cannot initialize}} + }); +} + +void test_float_return_type() { + std::string s; + s.resize_and_overwrite(10, [](char*, std::size_t) { + return 5.0f; // expected-error-re@*:* {{{{(static_assertion|static assertion)}}{{.*}}integer-like}} + }); +}