[libcxx-commits] [libcxx] [libc++] Apply `[[nodiscard]]` to `wstring_convert`, `wbuffer_convert` (PR #205486)

A. Jiang via libcxx-commits libcxx-commits at lists.llvm.org
Tue Jun 23 23:11:55 PDT 2026


https://github.com/frederick-vs-ja updated https://github.com/llvm/llvm-project/pull/205486

>From 29a49d2b0a5431e97e5780d04e89ccb9c14ff095 Mon Sep 17 00:00:00 2001
From: "A. Jiang" <de34 at live.cn>
Date: Wed, 24 Jun 2026 13:43:53 +0800
Subject: [PATCH] [libc++] Apply `[[nodiscard]]` to `wstring_convert`,
 `wbuffer_convert`

`[[nodiscard]]` should be applied to functions where discarding the
return value is most likely a correctness issue.

- https://libcxx.llvm.org/CodingGuidelines.html
- https://timsong-cpp.github.io/cppwp/n4950/depr.conversions.string
- https://timsong-cpp.github.io/cppwp/n4950/depr.conversions.buffer
---
 libcxx/include/__locale_dir/wbuffer_convert.h |  4 +-
 libcxx/include/__locale_dir/wstring_convert.h | 22 +++++-----
 .../conversions.string/ctor_move.pass.cpp     |  2 +-
 .../libcxx/localization/nodiscard.verify.cpp  | 41 +++++++++++++++++++
 4 files changed, 56 insertions(+), 13 deletions(-)

diff --git a/libcxx/include/__locale_dir/wbuffer_convert.h b/libcxx/include/__locale_dir/wbuffer_convert.h
index a6818aadf5d0b..c8bad68011a09 100644
--- a/libcxx/include/__locale_dir/wbuffer_convert.h
+++ b/libcxx/include/__locale_dir/wbuffer_convert.h
@@ -67,7 +67,7 @@ class _LIBCPP_DEPRECATED_IN_CXX17 wbuffer_convert : public basic_streambuf<_Elem
 
   _LIBCPP_HIDE_FROM_ABI ~wbuffer_convert();
 
-  _LIBCPP_HIDE_FROM_ABI streambuf* rdbuf() const { return __bufptr_; }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI streambuf* rdbuf() const { return __bufptr_; }
   _LIBCPP_HIDE_FROM_ABI streambuf* rdbuf(streambuf* __bytebuf) {
     streambuf* __r = __bufptr_;
     __bufptr_      = __bytebuf;
@@ -77,7 +77,7 @@ class _LIBCPP_DEPRECATED_IN_CXX17 wbuffer_convert : public basic_streambuf<_Elem
   wbuffer_convert(const wbuffer_convert&)            = delete;
   wbuffer_convert& operator=(const wbuffer_convert&) = delete;
 
-  _LIBCPP_HIDE_FROM_ABI state_type state() const { return __st_; }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI state_type state() const { return __st_; }
 
 protected:
   _LIBCPP_HIDE_FROM_ABI_VIRTUAL virtual int_type underflow();
diff --git a/libcxx/include/__locale_dir/wstring_convert.h b/libcxx/include/__locale_dir/wstring_convert.h
index 8f6dc9af8da91..05b81e0a880ed 100644
--- a/libcxx/include/__locale_dir/wstring_convert.h
+++ b/libcxx/include/__locale_dir/wstring_convert.h
@@ -64,28 +64,30 @@ class _LIBCPP_DEPRECATED_IN_CXX17 wstring_convert {
   wstring_convert(const wstring_convert& __wc)            = delete;
   wstring_convert& operator=(const wstring_convert& __wc) = delete;
 
-  _LIBCPP_HIDE_FROM_ABI wide_string from_bytes(char __byte) { return from_bytes(&__byte, &__byte + 1); }
-  _LIBCPP_HIDE_FROM_ABI wide_string from_bytes(const char* __ptr) {
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI wide_string from_bytes(char __byte) {
+    return from_bytes(&__byte, &__byte + 1);
+  }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI wide_string from_bytes(const char* __ptr) {
     return from_bytes(__ptr, __ptr + char_traits<char>::length(__ptr));
   }
-  _LIBCPP_HIDE_FROM_ABI wide_string from_bytes(const byte_string& __str) {
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI wide_string from_bytes(const byte_string& __str) {
     return from_bytes(__str.data(), __str.data() + __str.size());
   }
-  _LIBCPP_HIDE_FROM_ABI wide_string from_bytes(const char* __first, const char* __last);
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI wide_string from_bytes(const char* __first, const char* __last);
 
-  _LIBCPP_HIDE_FROM_ABI byte_string to_bytes(_Elem __wchar) {
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI byte_string to_bytes(_Elem __wchar) {
     return to_bytes(std::addressof(__wchar), std::addressof(__wchar) + 1);
   }
-  _LIBCPP_HIDE_FROM_ABI byte_string to_bytes(const _Elem* __wptr) {
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI byte_string to_bytes(const _Elem* __wptr) {
     return to_bytes(__wptr, __wptr + char_traits<_Elem>::length(__wptr));
   }
-  _LIBCPP_HIDE_FROM_ABI byte_string to_bytes(const wide_string& __wstr) {
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI byte_string to_bytes(const wide_string& __wstr) {
     return to_bytes(__wstr.data(), __wstr.data() + __wstr.size());
   }
-  _LIBCPP_HIDE_FROM_ABI byte_string to_bytes(const _Elem* __first, const _Elem* __last);
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI byte_string to_bytes(const _Elem* __first, const _Elem* __last);
 
-  _LIBCPP_HIDE_FROM_ABI size_t converted() const _NOEXCEPT { return __cvtcount_; }
-  _LIBCPP_HIDE_FROM_ABI state_type state() const { return __cvtstate_; }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t converted() const _NOEXCEPT { return __cvtcount_; }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI state_type state() const { return __cvtstate_; }
 };
 
 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
diff --git a/libcxx/test/extensions/libcxx/localization/locale.convenience/conversions/conversions.string/ctor_move.pass.cpp b/libcxx/test/extensions/libcxx/localization/locale.convenience/conversions/conversions.string/ctor_move.pass.cpp
index a536e6e9b04c6..6cf0c68232cd0 100644
--- a/libcxx/test/extensions/libcxx/localization/locale.convenience/conversions/conversions.string/ctor_move.pass.cpp
+++ b/libcxx/test/extensions/libcxx/localization/locale.convenience/conversions/conversions.string/ctor_move.pass.cpp
@@ -31,7 +31,7 @@ int main(int, char**)
     // create a converter and perform some conversions to generate some
     // interesting state.
     Myconv myconv;
-    myconv.from_bytes("\xEF\xBF\xBD");
+    (void)myconv.from_bytes("\xEF\xBF\xBD");
     const auto old_converted = myconv.converted();
     assert(myconv.converted() == 3);
     // move construct a new converter and make sure the state is the same.
diff --git a/libcxx/test/libcxx/localization/nodiscard.verify.cpp b/libcxx/test/libcxx/localization/nodiscard.verify.cpp
index 80691e276deab..dd14091b90182 100644
--- a/libcxx/test/libcxx/localization/nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/localization/nodiscard.verify.cpp
@@ -7,9 +7,12 @@
 //===----------------------------------------------------------------------===//
 
 // ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS
+// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX26_REMOVED_CODECVT
+// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX26_REMOVED_WSTRING_CONVERT
 
 // Check that functions are marked [[nodiscard]]
 
+#include <codecvt>
 #include <cwchar>
 #include <locale>
 #include <string>
@@ -242,4 +245,42 @@ void test() {
     f.get(0, 0, 0, std::wstring());
   }
 #endif
+
+  // C++23 [depr.conversions.string]
+  {
+    typedef std::wstring_convert<std::codecvt_utf8<char16_t>, char16_t> converter_type;
+
+    converter_type myconv;
+    converter_type::byte_string bs;
+    converter_type::wide_string ws;
+
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    myconv.from_bytes('*');
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    myconv.from_bytes("");
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    myconv.from_bytes(bs);
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    myconv.from_bytes(bs.data(), bs.data());
+
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    myconv.to_bytes(char16_t());
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    myconv.to_bytes(ws.data());
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    myconv.to_bytes(ws);
+    // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    myconv.to_bytes(ws.data(), ws.data());
+
+    myconv.converted(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+    myconv.state();     // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  }
+
+  // C++23 [depr.conversions.buffer]
+  {
+    std::wbuffer_convert<std::codecvt_utf8<char16_t>, char16_t> myconv;
+
+    myconv.rdbuf(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+    myconv.state(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  }
 }



More information about the libcxx-commits mailing list