Skip to content

Conversation

chaitanyav
Copy link
Contributor

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

@chaitanyav chaitanyav requested a review from a team as a code owner October 5, 2025 22:41
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Oct 5, 2025
@llvmbot
Copy link
Member

llvmbot commented Oct 5, 2025

@llvm/pr-subscribers-libcxx

Author: NagaChaitanya Vellanki (chaitanyav)

Changes

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


Full diff: https://github.com/llvm/llvm-project/pull/162030.diff

3 Files Affected:

  • (modified) libcxx/include/string (+2)
  • (modified) libcxx/test/std/strings/basic.string/string.capacity/resize_and_overwrite.pass.cpp (+16)
  • (added) libcxx/test/std/strings/basic.string/string.capacity/resize_and_overwrite.verify.cpp (+39)
diff --git a/libcxx/include/string b/libcxx/include/string
index dc562e0207630..00592e61547af 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -1311,6 +1311,8 @@ public:
 #  if _LIBCPP_STD_VER >= 23
   template <class _Op>
   _LIBCPP_HIDE_FROM_ABI constexpr void resize_and_overwrite(size_type __n, _Op __op) {
+    using __result_type = decltype(__op(data(), auto(__n)));
+    static_assert(std::__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..aa0b32bf3f589 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
@@ -90,6 +90,18 @@ void test_value_categories() {
   LIBCPP_ASSERT(is_string_asan_correct(s));
 }
 
+void test_integer_like_return_types() {
+  std::string s;
+  s.resize_and_overwrite(10, [](char*, std::size_t) -> int { return 5; });
+  s.resize_and_overwrite(10, [](char*, std::size_t) -> unsigned int { return 5u; });
+  s.resize_and_overwrite(10, [](char*, std::size_t) -> long { return 5l; });
+  s.resize_and_overwrite(10, [](char*, std::size_t) -> unsigned long { return 5ul; });
+  s.resize_and_overwrite(10, [](char*, std::size_t) -> long long { return 5ll; });
+  s.resize_and_overwrite(10, [](char*, std::size_t) -> unsigned long long { return 5ull; });
+  s.resize_and_overwrite(10, [](char*, std::size_t) -> std::size_t { return 5; });
+  s.resize_and_overwrite(10, [](char*, std::size_t) -> std::ptrdiff_t { return 5; });
+}
+
 int main(int, char**) {
   test<std::basic_string<char, std::char_traits<char>, std::allocator<char>>>();
   test<std::basic_string<char8_t, std::char_traits<char8_t>, std::allocator<char8_t>>>();
@@ -105,5 +117,9 @@ int main(int, char**) {
   test<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t>>>();
   static_assert(test<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t>>>());
 #endif
+
+  test_value_categories();
+  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..00d04e56a3aea
--- /dev/null
+++ b/libcxx/test/std/strings/basic.string/string.capacity/resize_and_overwrite.verify.cpp
@@ -0,0 +1,39 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// <string>
+
+// template<class Operation>
+// void resize_and_overwrite(size_type n, Operation op)
+
+// Verify that the operation's return type must be integer-like
+
+#include <string>
+
+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}}
+  });
+}
+
+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}}
+  });
+}

Copy link

github-actions bot commented Oct 5, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@chaitanyav chaitanyav marked this pull request as draft October 5, 2025 23:14
…r-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 llvm#160577
@chaitanyav chaitanyav marked this pull request as ready for review October 6, 2025 01:17
Copy link
Contributor

@frederick-vs-ja frederick-vs-ja left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. CI failures are unrelated.

template <class _Op>
_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(std::__integer_like<__result_type>, "Operation return type must be integer-like");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
static_assert(std::__integer_like<__result_type>, "Operation return type must be integer-like");
static_assert(__integer_like<__result_type>, "Operation return type must be integer-like");


void test_integer_like_return_types() {
std::string s;
s.resize_and_overwrite(10, [](char*, std::size_t) -> int { return 5; });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These calls have UB, since you haven't initialized the elements you claim to have initialized. Also, can we return either the exact type or have explicit return types? We can also use types::for_each with integer_types here instead.

Comment on lines +101 to +102
s.resize_and_overwrite(10, [](char*, std::size_t) -> std::size_t { return 5; });
s.resize_and_overwrite(10, [](char*, std::size_t) -> std::ptrdiff_t { return 5; });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests are entirely redundant.

Comment on lines +121 to +122
test_value_categories();
test_integer_like_return_types();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should also be run during constant evaluation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[libc++] <string>: string::resize_and_overwrite missing _Mandates_
4 participants