[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