[libcxx-commits] [libcxx] [libc++][format] Applied `[[nodiscard]]` to more classes (PR #170808)

Hristo Hristov via libcxx-commits libcxx-commits at lists.llvm.org
Thu Dec 4 23:57:57 PST 2025


https://github.com/H-G-Hristov created https://github.com/llvm/llvm-project/pull/170808

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

- https://libcxx.llvm.org/CodingGuidelines.html

Some classes in `<format>` were already annotated. This patch completes the remaining.

>From 7d3001b64c8c39002c21c78b610e5755543d5f15 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Fri, 5 Dec 2025 06:26:30 +0200
Subject: [PATCH 1/3] [libc++][charconv]

---
 .../__charconv/from_chars_floating_point.h    |  4 +-
 .../include/__charconv/from_chars_integral.h  |  4 +-
 .../__charconv/to_chars_floating_point.h      | 18 +++---
 libcxx/include/__charconv/to_chars_integral.h |  4 +-
 .../utilities/charconv/nodiscard.verify.cpp   | 59 +++++++++++++++++++
 5 files changed, 74 insertions(+), 15 deletions(-)
 create mode 100644 libcxx/test/libcxx/utilities/charconv/nodiscard.verify.cpp

diff --git a/libcxx/include/__charconv/from_chars_floating_point.h b/libcxx/include/__charconv/from_chars_floating_point.h
index 811e518a81db7..7bf2bf466dd6d 100644
--- a/libcxx/include/__charconv/from_chars_floating_point.h
+++ b/libcxx/include/__charconv/from_chars_floating_point.h
@@ -54,12 +54,12 @@ __from_chars(const char* __first, const char* __last, _Fp& __value, chars_format
   return {__first + __r.__n, __r.__ec};
 }
 
-_LIBCPP_AVAILABILITY_FROM_CHARS_FLOATING_POINT _LIBCPP_HIDE_FROM_ABI inline from_chars_result
+[[nodiscard]] _LIBCPP_AVAILABILITY_FROM_CHARS_FLOATING_POINT _LIBCPP_HIDE_FROM_ABI inline from_chars_result
 from_chars(const char* __first, const char* __last, float& __value, chars_format __fmt = chars_format::general) {
   return std::__from_chars<float>(__first, __last, __value, __fmt);
 }
 
-_LIBCPP_AVAILABILITY_FROM_CHARS_FLOATING_POINT _LIBCPP_HIDE_FROM_ABI inline from_chars_result
+[[nodiscard]] _LIBCPP_AVAILABILITY_FROM_CHARS_FLOATING_POINT _LIBCPP_HIDE_FROM_ABI inline from_chars_result
 from_chars(const char* __first, const char* __last, double& __value, chars_format __fmt = chars_format::general) {
   return std::__from_chars<double>(__first, __last, __value, __fmt);
 }
diff --git a/libcxx/include/__charconv/from_chars_integral.h b/libcxx/include/__charconv/from_chars_integral.h
index 903e892cab85b..e65faea6f4082 100644
--- a/libcxx/include/__charconv/from_chars_integral.h
+++ b/libcxx/include/__charconv/from_chars_integral.h
@@ -220,13 +220,13 @@ __from_chars_integral(const char* __first, const char* __last, _Tp& __value, int
 }
 
 template <typename _Tp, __enable_if_t<is_integral<_Tp>::value, int> = 0>
-inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result
+[[nodiscard]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result
 from_chars(const char* __first, const char* __last, _Tp& __value) {
   return std::__from_chars_atoi(__first, __last, __value);
 }
 
 template <typename _Tp, __enable_if_t<is_integral<_Tp>::value, int> = 0>
-inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result
+[[nodiscard]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result
 from_chars(const char* __first, const char* __last, _Tp& __value, int __base) {
   _LIBCPP_ASSERT_UNCATEGORIZED(2 <= __base && __base <= 36, "base not in [2, 36]");
   return std::__from_chars_integral(__first, __last, __value, __base);
diff --git a/libcxx/include/__charconv/to_chars_floating_point.h b/libcxx/include/__charconv/to_chars_floating_point.h
index 118f316b21a10..bfa3bf1bdbc09 100644
--- a/libcxx/include/__charconv/to_chars_floating_point.h
+++ b/libcxx/include/__charconv/to_chars_floating_point.h
@@ -22,31 +22,31 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 #if _LIBCPP_STD_VER >= 17
 
-_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result
+[[nodiscard]] _LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result
 to_chars(char* __first, char* __last, float __value);
 
-_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result
+[[nodiscard]] _LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result
 to_chars(char* __first, char* __last, double __value);
 
-_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result
+[[nodiscard]] _LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result
 to_chars(char* __first, char* __last, long double __value);
 
-_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result
+[[nodiscard]] _LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result
 to_chars(char* __first, char* __last, float __value, chars_format __fmt);
 
-_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result
+[[nodiscard]] _LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result
 to_chars(char* __first, char* __last, double __value, chars_format __fmt);
 
-_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result
+[[nodiscard]] _LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result
 to_chars(char* __first, char* __last, long double __value, chars_format __fmt);
 
-_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result
+[[nodiscard]] _LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result
 to_chars(char* __first, char* __last, float __value, chars_format __fmt, int __precision);
 
-_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result
+[[nodiscard]] _LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result
 to_chars(char* __first, char* __last, double __value, chars_format __fmt, int __precision);
 
-_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result
+[[nodiscard]] _LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result
 to_chars(char* __first, char* __last, long double __value, chars_format __fmt, int __precision);
 #endif // _LIBCPP_STD_VER >= 17
 
diff --git a/libcxx/include/__charconv/to_chars_integral.h b/libcxx/include/__charconv/to_chars_integral.h
index 6d425139260b6..5792539af75b1 100644
--- a/libcxx/include/__charconv/to_chars_integral.h
+++ b/libcxx/include/__charconv/to_chars_integral.h
@@ -319,7 +319,7 @@ _LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX14 char __hex_to_upper(c
 to_chars_result to_chars(char*, char*, bool, int = 10) = delete;
 
 template <typename _Tp, __enable_if_t<is_integral<_Tp>::value, int> = 0>
-inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
+[[nodiscard]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
 to_chars(char* __first, char* __last, _Tp __value) {
   using _Type = __make_32_64_or_128_bit_t<_Tp>;
   static_assert(!is_same<_Type, void>::value, "unsupported integral type used in to_chars");
@@ -327,7 +327,7 @@ to_chars(char* __first, char* __last, _Tp __value) {
 }
 
 template <typename _Tp, __enable_if_t<is_integral<_Tp>::value, int> = 0>
-inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
+[[nodiscard]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
 to_chars(char* __first, char* __last, _Tp __value, int __base) {
   _LIBCPP_ASSERT_UNCATEGORIZED(2 <= __base && __base <= 36, "base not in [2, 36]");
 
diff --git a/libcxx/test/libcxx/utilities/charconv/nodiscard.verify.cpp b/libcxx/test/libcxx/utilities/charconv/nodiscard.verify.cpp
new file mode 100644
index 0000000000000..923023bc084e9
--- /dev/null
+++ b/libcxx/test/libcxx/utilities/charconv/nodiscard.verify.cpp
@@ -0,0 +1,59 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++17
+
+// <flat_set>
+
+// Check that functions are marked [[nodiscard]]
+
+#include <charconv>
+
+void test() {
+  char buf[32];
+
+  // expected-warning @+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+  std::to_chars(buf, buf + sizeof(buf), 49.0f);
+  // expected-warning @+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+  std::to_chars(buf, buf + sizeof(buf), 82.0);
+
+  // expected-warning @+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+  std::to_chars(buf, buf + sizeof(buf), 49);
+  // expected-warning @+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+  std::to_chars(buf, buf + sizeof(buf), 49, 16);
+
+  float f2;
+  double d2;
+  long double ld2;
+
+  // expected-warning @+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+  std::from_chars(buf, buf + sizeof(buf), f2);
+  // expected-warning @+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+  std::from_chars(buf, buf + sizeof(buf), d2);
+  // expected-warning @+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+  std::from_chars(buf, buf + sizeof(buf), ld2);
+  // expected-warning @+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+  std::from_chars(buf, buf + sizeof(buf), f2, std::chars_format::general);
+  // expected-warning @+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+  std::from_chars(buf, buf + sizeof(buf), d2, std::chars_format::general);
+  // expected-warning @+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+  std::from_chars(buf, buf + sizeof(buf), ld2, std::chars_format::general);
+  // expected-warning @+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+  std::from_chars(buf, buf + sizeof(buf), f2, std::chars_format::general, 5);
+  // expected-warning @+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+  std::from_chars(buf, buf + sizeof(buf), d2, std::chars_format::general, 5);
+  // expected-warning @+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+  std::from_chars(buf, buf + sizeof(buf), ld2, std::chars_format::general, 5);
+
+  int i;
+
+  // expected-warning @+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+  std::from_chars(buf, buf + sizeof(buf), i);
+  // expected-warning @+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+  std::from_chars(buf, buf + sizeof(buf), i, 16);
+}
\ No newline at end of file

>From d5dfc4254707707e9ca42b042e32dcc739534ab5 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Fri, 5 Dec 2025 08:31:10 +0200
Subject: [PATCH 2/3] Revert

---
 .../__charconv/from_chars_floating_point.h    |  4 +-
 .../include/__charconv/from_chars_integral.h  |  4 +-
 .../__charconv/to_chars_floating_point.h      | 18 +++---
 libcxx/include/__charconv/to_chars_integral.h |  4 +-
 .../utilities/charconv/nodiscard.verify.cpp   | 59 -------------------
 5 files changed, 15 insertions(+), 74 deletions(-)
 delete mode 100644 libcxx/test/libcxx/utilities/charconv/nodiscard.verify.cpp

diff --git a/libcxx/include/__charconv/from_chars_floating_point.h b/libcxx/include/__charconv/from_chars_floating_point.h
index 7bf2bf466dd6d..811e518a81db7 100644
--- a/libcxx/include/__charconv/from_chars_floating_point.h
+++ b/libcxx/include/__charconv/from_chars_floating_point.h
@@ -54,12 +54,12 @@ __from_chars(const char* __first, const char* __last, _Fp& __value, chars_format
   return {__first + __r.__n, __r.__ec};
 }
 
-[[nodiscard]] _LIBCPP_AVAILABILITY_FROM_CHARS_FLOATING_POINT _LIBCPP_HIDE_FROM_ABI inline from_chars_result
+_LIBCPP_AVAILABILITY_FROM_CHARS_FLOATING_POINT _LIBCPP_HIDE_FROM_ABI inline from_chars_result
 from_chars(const char* __first, const char* __last, float& __value, chars_format __fmt = chars_format::general) {
   return std::__from_chars<float>(__first, __last, __value, __fmt);
 }
 
-[[nodiscard]] _LIBCPP_AVAILABILITY_FROM_CHARS_FLOATING_POINT _LIBCPP_HIDE_FROM_ABI inline from_chars_result
+_LIBCPP_AVAILABILITY_FROM_CHARS_FLOATING_POINT _LIBCPP_HIDE_FROM_ABI inline from_chars_result
 from_chars(const char* __first, const char* __last, double& __value, chars_format __fmt = chars_format::general) {
   return std::__from_chars<double>(__first, __last, __value, __fmt);
 }
diff --git a/libcxx/include/__charconv/from_chars_integral.h b/libcxx/include/__charconv/from_chars_integral.h
index e65faea6f4082..903e892cab85b 100644
--- a/libcxx/include/__charconv/from_chars_integral.h
+++ b/libcxx/include/__charconv/from_chars_integral.h
@@ -220,13 +220,13 @@ __from_chars_integral(const char* __first, const char* __last, _Tp& __value, int
 }
 
 template <typename _Tp, __enable_if_t<is_integral<_Tp>::value, int> = 0>
-[[nodiscard]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result
+inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result
 from_chars(const char* __first, const char* __last, _Tp& __value) {
   return std::__from_chars_atoi(__first, __last, __value);
 }
 
 template <typename _Tp, __enable_if_t<is_integral<_Tp>::value, int> = 0>
-[[nodiscard]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result
+inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result
 from_chars(const char* __first, const char* __last, _Tp& __value, int __base) {
   _LIBCPP_ASSERT_UNCATEGORIZED(2 <= __base && __base <= 36, "base not in [2, 36]");
   return std::__from_chars_integral(__first, __last, __value, __base);
diff --git a/libcxx/include/__charconv/to_chars_floating_point.h b/libcxx/include/__charconv/to_chars_floating_point.h
index bfa3bf1bdbc09..118f316b21a10 100644
--- a/libcxx/include/__charconv/to_chars_floating_point.h
+++ b/libcxx/include/__charconv/to_chars_floating_point.h
@@ -22,31 +22,31 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 #if _LIBCPP_STD_VER >= 17
 
-[[nodiscard]] _LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result
+_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result
 to_chars(char* __first, char* __last, float __value);
 
-[[nodiscard]] _LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result
+_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result
 to_chars(char* __first, char* __last, double __value);
 
-[[nodiscard]] _LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result
+_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result
 to_chars(char* __first, char* __last, long double __value);
 
-[[nodiscard]] _LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result
+_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result
 to_chars(char* __first, char* __last, float __value, chars_format __fmt);
 
-[[nodiscard]] _LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result
+_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result
 to_chars(char* __first, char* __last, double __value, chars_format __fmt);
 
-[[nodiscard]] _LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result
+_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result
 to_chars(char* __first, char* __last, long double __value, chars_format __fmt);
 
-[[nodiscard]] _LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result
+_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result
 to_chars(char* __first, char* __last, float __value, chars_format __fmt, int __precision);
 
-[[nodiscard]] _LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result
+_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result
 to_chars(char* __first, char* __last, double __value, chars_format __fmt, int __precision);
 
-[[nodiscard]] _LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result
+_LIBCPP_AVAILABILITY_TO_CHARS_FLOATING_POINT _LIBCPP_EXPORTED_FROM_ABI to_chars_result
 to_chars(char* __first, char* __last, long double __value, chars_format __fmt, int __precision);
 #endif // _LIBCPP_STD_VER >= 17
 
diff --git a/libcxx/include/__charconv/to_chars_integral.h b/libcxx/include/__charconv/to_chars_integral.h
index 5792539af75b1..6d425139260b6 100644
--- a/libcxx/include/__charconv/to_chars_integral.h
+++ b/libcxx/include/__charconv/to_chars_integral.h
@@ -319,7 +319,7 @@ _LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX14 char __hex_to_upper(c
 to_chars_result to_chars(char*, char*, bool, int = 10) = delete;
 
 template <typename _Tp, __enable_if_t<is_integral<_Tp>::value, int> = 0>
-[[nodiscard]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
+inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
 to_chars(char* __first, char* __last, _Tp __value) {
   using _Type = __make_32_64_or_128_bit_t<_Tp>;
   static_assert(!is_same<_Type, void>::value, "unsupported integral type used in to_chars");
@@ -327,7 +327,7 @@ to_chars(char* __first, char* __last, _Tp __value) {
 }
 
 template <typename _Tp, __enable_if_t<is_integral<_Tp>::value, int> = 0>
-[[nodiscard]] inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
+inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
 to_chars(char* __first, char* __last, _Tp __value, int __base) {
   _LIBCPP_ASSERT_UNCATEGORIZED(2 <= __base && __base <= 36, "base not in [2, 36]");
 
diff --git a/libcxx/test/libcxx/utilities/charconv/nodiscard.verify.cpp b/libcxx/test/libcxx/utilities/charconv/nodiscard.verify.cpp
deleted file mode 100644
index 923023bc084e9..0000000000000
--- a/libcxx/test/libcxx/utilities/charconv/nodiscard.verify.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-// REQUIRES: std-at-least-c++17
-
-// <flat_set>
-
-// Check that functions are marked [[nodiscard]]
-
-#include <charconv>
-
-void test() {
-  char buf[32];
-
-  // expected-warning @+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
-  std::to_chars(buf, buf + sizeof(buf), 49.0f);
-  // expected-warning @+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
-  std::to_chars(buf, buf + sizeof(buf), 82.0);
-
-  // expected-warning @+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
-  std::to_chars(buf, buf + sizeof(buf), 49);
-  // expected-warning @+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
-  std::to_chars(buf, buf + sizeof(buf), 49, 16);
-
-  float f2;
-  double d2;
-  long double ld2;
-
-  // expected-warning @+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
-  std::from_chars(buf, buf + sizeof(buf), f2);
-  // expected-warning @+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
-  std::from_chars(buf, buf + sizeof(buf), d2);
-  // expected-warning @+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
-  std::from_chars(buf, buf + sizeof(buf), ld2);
-  // expected-warning @+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
-  std::from_chars(buf, buf + sizeof(buf), f2, std::chars_format::general);
-  // expected-warning @+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
-  std::from_chars(buf, buf + sizeof(buf), d2, std::chars_format::general);
-  // expected-warning @+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
-  std::from_chars(buf, buf + sizeof(buf), ld2, std::chars_format::general);
-  // expected-warning @+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
-  std::from_chars(buf, buf + sizeof(buf), f2, std::chars_format::general, 5);
-  // expected-warning @+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
-  std::from_chars(buf, buf + sizeof(buf), d2, std::chars_format::general, 5);
-  // expected-warning @+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
-  std::from_chars(buf, buf + sizeof(buf), ld2, std::chars_format::general, 5);
-
-  int i;
-
-  // expected-warning @+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
-  std::from_chars(buf, buf + sizeof(buf), i);
-  // expected-warning @+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
-  std::from_chars(buf, buf + sizeof(buf), i, 16);
-}
\ No newline at end of file

>From 511d6b3d00ec7e699c6eb717f4a574d91a64b8d4 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Fri, 5 Dec 2025 09:57:16 +0200
Subject: [PATCH 3/3] [libc++][format] Applied `[[nodiscard]]` to more classes

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

- https://libcxx.llvm.org/CodingGuidelines.html

Some classes in `<format>` were already annotated. This patch completes the remaining.
---
 libcxx/include/__format/format_args.h         |  2 +-
 libcxx/include/__format/format_context.h      |  6 ++---
 .../include/__format/format_parse_context.h   |  4 ++--
 .../diagnostics/format.nodiscard.verify.cpp   | 23 +++++++++++++++++++
 4 files changed, 29 insertions(+), 6 deletions(-)

diff --git a/libcxx/include/__format/format_args.h b/libcxx/include/__format/format_args.h
index 9dd7a5ed9c094..f1b648a10ac4f 100644
--- a/libcxx/include/__format/format_args.h
+++ b/libcxx/include/__format/format_args.h
@@ -40,7 +40,7 @@ class basic_format_args {
     }
   }
 
-  _LIBCPP_HIDE_FROM_ABI basic_format_arg<_Context> get(size_t __id) const noexcept {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI basic_format_arg<_Context> get(size_t __id) const noexcept {
     if (__id >= __size_)
       return basic_format_arg<_Context>{};
 
diff --git a/libcxx/include/__format/format_context.h b/libcxx/include/__format/format_context.h
index 1771dd34b82fb..9732ea9bf7f85 100644
--- a/libcxx/include/__format/format_context.h
+++ b/libcxx/include/__format/format_context.h
@@ -80,17 +80,17 @@ class _LIBCPP_PREFERRED_NAME(format_context)
   template <class _Tp>
   using formatter_type = formatter<_Tp, _CharT>;
 
-  _LIBCPP_HIDE_FROM_ABI basic_format_arg<basic_format_context> arg(size_t __id) const noexcept {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI basic_format_arg<basic_format_context> arg(size_t __id) const noexcept {
     return __args_.get(__id);
   }
 #  if _LIBCPP_HAS_LOCALIZATION
-  _LIBCPP_HIDE_FROM_ABI std::locale locale() {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI std::locale locale() {
     if (!__loc_)
       __loc_ = std::locale{};
     return *__loc_;
   }
 #  endif
-  _LIBCPP_HIDE_FROM_ABI iterator out() { return std::move(__out_it_); }
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI iterator out() { return std::move(__out_it_); }
   _LIBCPP_HIDE_FROM_ABI void advance_to(iterator __it) { __out_it_ = std::move(__it); }
 
 private:
diff --git a/libcxx/include/__format/format_parse_context.h b/libcxx/include/__format/format_parse_context.h
index 67b90c7b7e62a..2eda9d7f1f972 100644
--- a/libcxx/include/__format/format_parse_context.h
+++ b/libcxx/include/__format/format_parse_context.h
@@ -41,8 +41,8 @@ class basic_format_parse_context {
   basic_format_parse_context(const basic_format_parse_context&)            = delete;
   basic_format_parse_context& operator=(const basic_format_parse_context&) = delete;
 
-  _LIBCPP_HIDE_FROM_ABI constexpr const_iterator begin() const noexcept { return __begin_; }
-  _LIBCPP_HIDE_FROM_ABI constexpr const_iterator end() const noexcept { return __end_; }
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const_iterator begin() const noexcept { return __begin_; }
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const_iterator end() const noexcept { return __end_; }
   _LIBCPP_HIDE_FROM_ABI constexpr void advance_to(const_iterator __it) { __begin_ = __it; }
 
   _LIBCPP_HIDE_FROM_ABI constexpr size_t next_arg_id() {
diff --git a/libcxx/test/libcxx/diagnostics/format.nodiscard.verify.cpp b/libcxx/test/libcxx/diagnostics/format.nodiscard.verify.cpp
index ede6988f8bb4e..cf2a5602ef6a1 100644
--- a/libcxx/test/libcxx/diagnostics/format.nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/diagnostics/format.nodiscard.verify.cpp
@@ -14,7 +14,9 @@
 // UNSUPPORTED: c++03, c++11, c++14, c++17
 
 #include <format>
+#include <string>
 
+#include "test_format_context.h"
 #include "test_macros.h"
 
 #ifndef TEST_HAS_NO_LOCALIZATION
@@ -46,4 +48,25 @@ void test() {
 #  endif // TEST_HAS_NO_WIDE_CHARACTERS
 #endif   // TEST_HAS_NO_LOCALIZATION
   // clang-format on
+
+  std::basic_format_args args{std::make_format_args()};
+
+  args.get(0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+  using OutItT = std::back_insert_iterator<std::string>;
+  std::string str;
+  OutItT outIt{str};
+  using FormatCtxT = std::basic_format_context<OutItT, char>;
+  FormatCtxT fCtx  = test_format_context_create<OutItT, char>(outIt, std::make_format_args<FormatCtxT>());
+
+  fCtx.arg(0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+#if !defined(TEST_HAS_NO_LOCALIZATION)
+  fCtx.locale(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+#endif
+  fCtx.out(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+  std::basic_format_parse_context<char> fpCtx{""};
+
+  fpCtx.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  fpCtx.end();   // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
 }



More information about the libcxx-commits mailing list