[libcxx-commits] [libcxx] b37b307 - [libc++] Applied `[[nodiscard]]` to some general utilities (#169322)

via libcxx-commits libcxx-commits at lists.llvm.org
Tue Nov 25 06:24:41 PST 2025


Author: Hristo Hristov
Date: 2025-11-25T16:24:38+02:00
New Revision: b37b307715fd1c449698aabad1fcfd188b265f2c

URL: https://github.com/llvm/llvm-project/commit/b37b307715fd1c449698aabad1fcfd188b265f2c
DIFF: https://github.com/llvm/llvm-project/commit/b37b307715fd1c449698aabad1fcfd188b265f2c.diff

LOG: [libc++] Applied `[[nodiscard]]` to some general utilities (#169322)

`[[nodiscard]]` should be applied to functions where discarding the
return value is most likely a correctness issue.
- https://libcxx.llvm.org/CodingGuidelines.html#apply-nodiscard-where-relevant

The following functions/classes have been annotated in this patch:
- [x] `bind_back`, `bind_front`, `bind`
- [x] `function`, `mem_fn`
- [x] `reference_wrapper`

Added: 
    

Modified: 
    libcxx/include/__functional/bind.h
    libcxx/include/__functional/bind_back.h
    libcxx/include/__functional/bind_front.h
    libcxx/include/__functional/function.h
    libcxx/include/__functional/mem_fn.h
    libcxx/include/__functional/reference_wrapper.h
    libcxx/test/libcxx/diagnostics/functional.nodiscard.verify.cpp
    libcxx/test/std/utilities/function.objects/refwrap/refwrap.invoke/robust_against_adl.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/include/__functional/bind.h b/libcxx/include/__functional/bind.h
index def9e4c4ec7a9..328dc3bf3dabc 100644
--- a/libcxx/include/__functional/bind.h
+++ b/libcxx/include/__functional/bind.h
@@ -278,14 +278,14 @@ template <class _Rp, class _Fp, class... _BoundArgs>
 struct is_bind_expression<__bind_r<_Rp, _Fp, _BoundArgs...> > : public true_type {};
 
 template <class _Fp, class... _BoundArgs>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bind<_Fp, _BoundArgs...>
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bind<_Fp, _BoundArgs...>
 bind(_Fp&& __f, _BoundArgs&&... __bound_args) {
   typedef __bind<_Fp, _BoundArgs...> type;
   return type(std::forward<_Fp>(__f), std::forward<_BoundArgs>(__bound_args)...);
 }
 
 template <class _Rp, class _Fp, class... _BoundArgs>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bind_r<_Rp, _Fp, _BoundArgs...>
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bind_r<_Rp, _Fp, _BoundArgs...>
 bind(_Fp&& __f, _BoundArgs&&... __bound_args) {
   typedef __bind_r<_Rp, _Fp, _BoundArgs...> type;
   return type(std::forward<_Fp>(__f), std::forward<_BoundArgs>(__bound_args)...);

diff  --git a/libcxx/include/__functional/bind_back.h b/libcxx/include/__functional/bind_back.h
index e44768d2283c0..41177144d81fe 100644
--- a/libcxx/include/__functional/bind_back.h
+++ b/libcxx/include/__functional/bind_back.h
@@ -64,7 +64,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto __bind_back(_Fn&& __f, _Args&&... __args) n
 
 #  if _LIBCPP_STD_VER >= 23
 template <class _Fn, class... _Args>
-_LIBCPP_HIDE_FROM_ABI constexpr auto bind_back(_Fn&& __f, _Args&&... __args) {
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto bind_back(_Fn&& __f, _Args&&... __args) {
   static_assert(is_constructible_v<decay_t<_Fn>, _Fn>, "bind_back requires decay_t<F> to be constructible from F");
   static_assert(is_move_constructible_v<decay_t<_Fn>>, "bind_back requires decay_t<F> to be move constructible");
   static_assert((is_constructible_v<decay_t<_Args>, _Args> && ...),

diff  --git a/libcxx/include/__functional/bind_front.h b/libcxx/include/__functional/bind_front.h
index 87ef3affe80b6..427accf96339d 100644
--- a/libcxx/include/__functional/bind_front.h
+++ b/libcxx/include/__functional/bind_front.h
@@ -43,7 +43,7 @@ struct __bind_front_t : __perfect_forward<__bind_front_op, _Fn, _BoundArgs...> {
 template <class _Fn, class... _Args>
   requires is_constructible_v<decay_t<_Fn>, _Fn> && is_move_constructible_v<decay_t<_Fn>> &&
            (is_constructible_v<decay_t<_Args>, _Args> && ...) && (is_move_constructible_v<decay_t<_Args>> && ...)
-_LIBCPP_HIDE_FROM_ABI constexpr auto bind_front(_Fn&& __f, _Args&&... __args) {
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto bind_front(_Fn&& __f, _Args&&... __args) {
   return __bind_front_t<decay_t<_Fn>, decay_t<_Args>...>(std::forward<_Fn>(__f), std::forward<_Args>(__args)...);
 }
 

diff  --git a/libcxx/include/__functional/function.h b/libcxx/include/__functional/function.h
index c768fd90d01b4..121417f90ff01 100644
--- a/libcxx/include/__functional/function.h
+++ b/libcxx/include/__functional/function.h
@@ -672,11 +672,11 @@ class function<_Rp(_ArgTypes...)>
 
 #  if _LIBCPP_HAS_RTTI
   // function target access:
-  _LIBCPP_HIDE_FROM_ABI const std::type_info& target_type() const _NOEXCEPT;
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const std::type_info& target_type() const _NOEXCEPT;
   template <typename _Tp>
-  _LIBCPP_HIDE_FROM_ABI _Tp* target() _NOEXCEPT;
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _Tp* target() _NOEXCEPT;
   template <typename _Tp>
-  _LIBCPP_HIDE_FROM_ABI const _Tp* target() const _NOEXCEPT;
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const _Tp* target() const _NOEXCEPT;
 #  endif // _LIBCPP_HAS_RTTI
 };
 

diff  --git a/libcxx/include/__functional/mem_fn.h b/libcxx/include/__functional/mem_fn.h
index 690393988c5a5..1c9340c4f4183 100644
--- a/libcxx/include/__functional/mem_fn.h
+++ b/libcxx/include/__functional/mem_fn.h
@@ -43,7 +43,8 @@ class __mem_fn : public __weak_result_type<_Tp> {
 };
 
 template <class _Rp, class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __mem_fn<_Rp _Tp::*> mem_fn(_Rp _Tp::*__pm) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __mem_fn<_Rp _Tp::*>
+mem_fn(_Rp _Tp::* __pm) _NOEXCEPT {
   return __mem_fn<_Rp _Tp::*>(__pm);
 }
 

diff  --git a/libcxx/include/__functional/reference_wrapper.h b/libcxx/include/__functional/reference_wrapper.h
index 148703b21d84a..b1efd9f76d877 100644
--- a/libcxx/include/__functional/reference_wrapper.h
+++ b/libcxx/include/__functional/reference_wrapper.h
@@ -58,7 +58,7 @@ class reference_wrapper : public __weak_result_type<_Tp> {
 
   // access
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 operator type&() const _NOEXCEPT { return *__f_; }
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 type& get() const _NOEXCEPT { return *__f_; }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 type& get() const _NOEXCEPT { return *__f_; }
 
   // invoke
   template <class... _ArgTypes>
@@ -128,23 +128,25 @@ reference_wrapper(_Tp&) -> reference_wrapper<_Tp>;
 #endif
 
 template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference_wrapper<_Tp> ref(_Tp& __t) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI
+_LIBCPP_CONSTEXPR_SINCE_CXX20 reference_wrapper<_Tp> ref(_Tp& __t) _NOEXCEPT {
   return reference_wrapper<_Tp>(__t);
 }
 
 template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference_wrapper<_Tp>
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference_wrapper<_Tp>
 ref(reference_wrapper<_Tp> __t) _NOEXCEPT {
   return __t;
 }
 
 template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference_wrapper<const _Tp> cref(const _Tp& __t) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference_wrapper<const _Tp>
+cref(const _Tp& __t) _NOEXCEPT {
   return reference_wrapper<const _Tp>(__t);
 }
 
 template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference_wrapper<const _Tp>
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference_wrapper<const _Tp>
 cref(reference_wrapper<_Tp> __t) _NOEXCEPT {
   return __t;
 }

diff  --git a/libcxx/test/libcxx/diagnostics/functional.nodiscard.verify.cpp b/libcxx/test/libcxx/diagnostics/functional.nodiscard.verify.cpp
index 4307976e9e442..898b2ac06e3f2 100644
--- a/libcxx/test/libcxx/diagnostics/functional.nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/diagnostics/functional.nodiscard.verify.cpp
@@ -6,7 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: c++03
 
 // check that <functional> functions are marked [[nodiscard]]
 
@@ -16,5 +16,47 @@
 
 void test() {
   int i = 0;
-  std::identity()(i); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+  // Function wrappers
+
+#if !defined(TEST_HAS_NO_RTTI)
+  std::function<void(int)> f;
+  const std::function<void(int)> cf;
+
+  f.target_type();        // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  f.target<void(int)>();  // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  cf.target<void(int)>(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+#endif
+  struct ZMT {
+    void member_function() {};
+  };
+  // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+  std::mem_fn(&ZMT::member_function);
+
+  // Identity
+
+#if TEST_STD_VER >= 20
+  std::identity{}(i); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+#endif
+
+  // Partial function application
+
+#if TEST_STD_VER >= 23
+  // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+  std::bind_back([](int a) { return a; }, 94);
+  // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+  std::bind_front([](int a) { return a; }, 94);
+#endif
+  // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+  std::bind([](int a) { return a; }, 94);
+  // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+  std::bind<float>([](int a) { return a; }, 94);
+
+  // Reference wrappers
+
+  std::reference_wrapper<int> rw{i};
+  rw.get(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+  std::ref(i);  // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  std::cref(i); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
 }

diff  --git a/libcxx/test/std/utilities/function.objects/refwrap/refwrap.invoke/robust_against_adl.pass.cpp b/libcxx/test/std/utilities/function.objects/refwrap/refwrap.invoke/robust_against_adl.pass.cpp
index 2774401b052b8..f666e8bc31a65 100644
--- a/libcxx/test/std/utilities/function.objects/refwrap/refwrap.invoke/robust_against_adl.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/refwrap/refwrap.invoke/robust_against_adl.pass.cpp
@@ -27,23 +27,23 @@ int main(int, char**)
 {
     Ptr x = nullptr;
     const Ptr cx = nullptr;
-    std::ref(no_args)();
-    std::ref(one_arg)(x);
-    std::ref(one_arg)(cx);
-    std::ref(two_args)(x, x);
-    std::ref(two_args)(x, cx);
-    std::ref(two_args)(cx, x);
-    std::ref(two_args)(cx, cx);
-    std::ref(three_args)(x, x, x);
-    std::ref(three_args)(x, x, cx);
-    std::ref(three_args)(x, cx, x);
-    std::ref(three_args)(cx, x, x);
-    std::ref(three_args)(x, cx, cx);
-    std::ref(three_args)(cx, x, cx);
-    std::ref(three_args)(cx, cx, x);
-    std::ref(three_args)(cx, cx, cx);
-    std::ref(one_arg_void)(x);
-    std::ref(one_arg_void)(cx);
+    (void)std::ref(no_args)();
+    (void)std::ref(one_arg)(x);
+    (void)std::ref(one_arg)(cx);
+    (void)std::ref(two_args)(x, x);
+    (void)std::ref(two_args)(x, cx);
+    (void)std::ref(two_args)(cx, x);
+    (void)std::ref(two_args)(cx, cx);
+    (void)std::ref(three_args)(x, x, x);
+    (void)std::ref(three_args)(x, x, cx);
+    (void)std::ref(three_args)(x, cx, x);
+    (void)std::ref(three_args)(cx, x, x);
+    (void)std::ref(three_args)(x, cx, cx);
+    (void)std::ref(three_args)(cx, x, cx);
+    (void)std::ref(three_args)(cx, cx, x);
+    (void)std::ref(three_args)(cx, cx, cx);
+    (void)std::ref(one_arg_void)(x);
+    (void)std::ref(one_arg_void)(cx);
 
     return 0;
 }


        


More information about the libcxx-commits mailing list