From 7d3001b64c8c39002c21c78b610e5755543d5f15 Mon Sep 17 00:00:00 2001 From: Hristo Hristov 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(__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(__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 ::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 ::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 ::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 ::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 + +// + +// Check that functions are marked [[nodiscard]] + +#include + +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 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(__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(__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 ::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 ::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 ::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 ::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 - -// - -// Check that functions are marked [[nodiscard]] - -#include - -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 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 `` 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 using formatter_type = formatter<_Tp, _CharT>; - _LIBCPP_HIDE_FROM_ABI basic_format_arg arg(size_t __id) const noexcept { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI basic_format_arg 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 +#include +#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 str; + OutItT outIt{str}; + using FormatCtxT = std::basic_format_context; + FormatCtxT fCtx = test_format_context_create(outIt, std::make_format_args()); + + 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 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}} }