Skip to content

Conversation

@H-G-Hristov
Copy link
Contributor

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

@H-G-Hristov H-G-Hristov requested a review from a team as a code owner November 20, 2025 05:09
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Nov 20, 2025
@llvmbot
Copy link
Member

llvmbot commented Nov 20, 2025

@llvm/pr-subscribers-libcxx

Author: Hristo Hristov (H-G-Hristov)

Changes

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


Full diff: https://github.com/llvm/llvm-project/pull/168826.diff

2 Files Affected:

  • (modified) libcxx/include/any (+9-9)
  • (added) libcxx/test/libcxx/utilities/any/nodiscard.verify.cpp (+45)
diff --git a/libcxx/include/any b/libcxx/include/any
index b3e5b8748df4c..5c779e397c9ea 100644
--- a/libcxx/include/any
+++ b/libcxx/include/any
@@ -262,10 +262,10 @@ public:
   _LIBCPP_HIDE_FROM_ABI void swap(any& __rhs) _NOEXCEPT;
 
   // 6.3.4 any observers
-  _LIBCPP_HIDE_FROM_ABI bool has_value() const _NOEXCEPT { return __h_ != nullptr; }
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool has_value() const _NOEXCEPT { return __h_ != nullptr; }
 
 #    if _LIBCPP_HAS_RTTI
-  _LIBCPP_HIDE_FROM_ABI const type_info& type() const _NOEXCEPT {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI const type_info& type() const _NOEXCEPT {
     if (__h_) {
       return *static_cast<type_info const*>(this->__call(_Action::_TypeInfo));
     } else {
@@ -492,17 +492,17 @@ inline _LIBCPP_HIDE_FROM_ABI void any::swap(any& __rhs) _NOEXCEPT {
 inline _LIBCPP_HIDE_FROM_ABI void swap(any& __lhs, any& __rhs) _NOEXCEPT { __lhs.swap(__rhs); }
 
 template <class _Tp, class... _Args>
-inline _LIBCPP_HIDE_FROM_ABI any make_any(_Args&&... __args) {
+[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI any make_any(_Args&&... __args) {
   return any(in_place_type<_Tp>, std::forward<_Args>(__args)...);
 }
 
 template <class _Tp, class _Up, class... _Args>
-inline _LIBCPP_HIDE_FROM_ABI any make_any(initializer_list<_Up> __il, _Args&&... __args) {
+[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI any make_any(initializer_list<_Up> __il, _Args&&... __args) {
   return any(in_place_type<_Tp>, __il, std::forward<_Args>(__args)...);
 }
 
 template <class _ValueType>
-inline _LIBCPP_HIDE_FROM_ABI _ValueType any_cast(any const& __v) {
+[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI _ValueType any_cast(any const& __v) {
   using _RawValueType = __remove_cvref_t<_ValueType>;
   static_assert(is_constructible<_ValueType, _RawValueType const&>::value,
                 "ValueType is required to be a const lvalue reference "
@@ -514,7 +514,7 @@ inline _LIBCPP_HIDE_FROM_ABI _ValueType any_cast(any const& __v) {
 }
 
 template <class _ValueType>
-inline _LIBCPP_HIDE_FROM_ABI _ValueType any_cast(any& __v) {
+[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI _ValueType any_cast(any& __v) {
   using _RawValueType = __remove_cvref_t<_ValueType>;
   static_assert(is_constructible<_ValueType, _RawValueType&>::value,
                 "ValueType is required to be an lvalue reference "
@@ -526,7 +526,7 @@ inline _LIBCPP_HIDE_FROM_ABI _ValueType any_cast(any& __v) {
 }
 
 template <class _ValueType>
-inline _LIBCPP_HIDE_FROM_ABI _ValueType any_cast(any&& __v) {
+[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI _ValueType any_cast(any&& __v) {
   using _RawValueType = __remove_cvref_t<_ValueType>;
   static_assert(is_constructible<_ValueType, _RawValueType>::value,
                 "ValueType is required to be an rvalue reference "
@@ -538,7 +538,7 @@ inline _LIBCPP_HIDE_FROM_ABI _ValueType any_cast(any&& __v) {
 }
 
 template <class _ValueType>
-inline _LIBCPP_HIDE_FROM_ABI add_pointer_t<add_const_t<_ValueType>> any_cast(any const* __any) _NOEXCEPT {
+[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI add_pointer_t<add_const_t<_ValueType>> any_cast(any const* __any) _NOEXCEPT {
   static_assert(!is_void_v<_ValueType>, "_ValueType may not be void.");
   static_assert(!is_reference<_ValueType>::value, "_ValueType may not be a reference.");
   return std::any_cast<_ValueType>(const_cast<any*>(__any));
@@ -555,7 +555,7 @@ inline _LIBCPP_HIDE_FROM_ABI _RetType __pointer_or_func_cast(void*, /*IsFunction
 }
 
 template <class _ValueType>
-_LIBCPP_HIDE_FROM_ABI add_pointer_t<_ValueType> any_cast(any* __any) _NOEXCEPT {
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI add_pointer_t<_ValueType> any_cast(any* __any) _NOEXCEPT {
   using __any_imp::_Action;
   static_assert(!is_void_v<_ValueType>, "_ValueType may not be void.");
   static_assert(!is_reference<_ValueType>::value, "_ValueType may not be a reference.");
diff --git a/libcxx/test/libcxx/utilities/any/nodiscard.verify.cpp b/libcxx/test/libcxx/utilities/any/nodiscard.verify.cpp
new file mode 100644
index 0000000000000..13a67bd3c3044
--- /dev/null
+++ b/libcxx/test/libcxx/utilities/any/nodiscard.verify.cpp
@@ -0,0 +1,45 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 <any>
+#include <utility>
+#include <vector>
+
+#include "test_macros.h"
+
+void test() {
+  std::any a{94};
+
+  // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+  a.has_value();
+#if !defined(TEST_HAS_NO_RTTI)
+  // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+  a.type();
+#endif
+
+  // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+  std::make_any<int>(82);
+  // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+  std::make_any<std::vector<int>>({94, 82, 50});
+
+  // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+  std::any_cast<const int&>(std::as_const(a));
+  // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+  std::any_cast<int&>(a);
+  // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+  std::any_cast<int&&>(std::move(a));
+
+  // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+  std::any_cast<int*>(&a);
+  // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+  std::any_cast<const int*>(&std::as_const(a));
+}

@frederick-vs-ja
Copy link
Contributor

Looks like that we should add void casts to some test files.

`[[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
@H-G-Hristov H-G-Hristov force-pushed the hgh/libcxx/nodiscard-to-any branch from 1f4da8f to 7910416 Compare November 20, 2025 06:32
@github-actions
Copy link

github-actions bot commented Nov 20, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@philnik777
Copy link
Contributor

@H-G-Hristov Please commit the format-only changes separately.

@Zingam
Copy link
Contributor

Zingam commented Nov 21, 2025

@H-G-Hristov Please commit the format-only changes separately.

These formatting changes are required by the code formatter job to get the CI green.

Any suggestions how to procceed in such situations. Maybe files should be formatted before the changes?

Actually only the changed lines need to be formatted but then the file will have some lines indented to 2 and some to 4 spaces.

@philnik777
Copy link
Contributor

@H-G-Hristov Please commit the format-only changes separately.

These formatting changes are required by the code formatter job to get the CI green.

Any suggestions how to procceed in such situations. Maybe files should be formatted before the changes?

You can just push a commit to format the files.

Actually only the changed lines need to be formatted but then the file will have some lines indented to 2 and some to 4 spaces.

H-G-Hristov added a commit to H-G-Hristov/llvm-project that referenced this pull request Nov 21, 2025
...in preparation for llvm#168826 as requested in the review.
Zingam added a commit that referenced this pull request Nov 22, 2025
...in preparation for #168826
as requested in the review.

Co-authored-by: Hristo Hristov <zingam@outlook.com>
@H-G-Hristov
Copy link
Contributor Author

@H-G-Hristov Please commit the format-only changes separately.

These formatting changes are required by the code formatter job to get the CI green.
Any suggestions how to procceed in such situations. Maybe files should be formatted before the changes?

You can just push a commit to format the files.

Actually only the changed lines need to be formatted but then the file will have some lines indented to 2 and some to 4 spaces.

Thank you! Done.

llvm-sync bot pushed a commit to arm/arm-toolchain that referenced this pull request Nov 22, 2025
…169057)

...in preparation for llvm/llvm-project#168826
as requested in the review.

Co-authored-by: Hristo Hristov <zingam@outlook.com>
@Zingam Zingam merged commit 8ba2713 into llvm:main Nov 22, 2025
70 of 71 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants