Skip to content

Conversation

@H-G-Hristov
Copy link
Contributor

@H-G-Hristov H-G-Hristov commented Dec 8, 2025

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

Towards #172124

Implemented in this release:

  • type_info
  • type_index
  • bad_alloc, bad_array_new_length

@github-actions
Copy link

github-actions bot commented Dec 8, 2025

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

@H-G-Hristov H-G-Hristov force-pushed the hgh/libcxx/nodiscard-to-type-support branch 4 times, most recently from 89f6dbb to bf7c620 Compare December 8, 2025 05:57
@H-G-Hristov
Copy link
Contributor Author

@H-G-Hristov H-G-Hristov force-pushed the hgh/libcxx/nodiscard-to-type-support branch 2 times, most recently from 981c48f to 545dce5 Compare December 8, 2025 16:06
[[nodiscard]] should be applied to functions where discarding the return value is most likely a correctness issue.

- https://libcxx.llvm.org/CodingGuidelines.html
@H-G-Hristov H-G-Hristov force-pushed the hgh/libcxx/nodiscard-to-type-support branch from 545dce5 to 4936b77 Compare December 10, 2025 05:53
@H-G-Hristov H-G-Hristov marked this pull request as ready for review December 10, 2025 11:30
@H-G-Hristov H-G-Hristov requested a review from a team as a code owner December 10, 2025 11:30
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Dec 10, 2025
@llvmbot
Copy link
Member

llvmbot commented Dec 10, 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/171078.diff

6 Files Affected:

  • (modified) libcxx/include/__new/exceptions.h (+2-2)
  • (modified) libcxx/include/typeindex (+5-3)
  • (modified) libcxx/include/typeinfo (+12-9)
  • (modified) libcxx/test/libcxx/diagnostics/new.nodiscard.verify.cpp (+36-14)
  • (modified) libcxx/test/libcxx/language.support/nodiscard.verify.cpp (+33)
  • (modified) libcxx/test/support/test_macros.h (+4)
diff --git a/libcxx/include/__new/exceptions.h b/libcxx/include/__new/exceptions.h
index 483e5e3811182..1aadc23120cbb 100644
--- a/libcxx/include/__new/exceptions.h
+++ b/libcxx/include/__new/exceptions.h
@@ -32,7 +32,7 @@ class _LIBCPP_EXPORTED_FROM_ABI bad_alloc : public exception {
   _LIBCPP_HIDE_FROM_ABI bad_alloc(const bad_alloc&) _NOEXCEPT            = default;
   _LIBCPP_HIDE_FROM_ABI bad_alloc& operator=(const bad_alloc&) _NOEXCEPT = default;
   ~bad_alloc() _NOEXCEPT override;
-  const char* what() const _NOEXCEPT override;
+  [[__nodiscard__]] const char* what() const _NOEXCEPT override;
 };
 
 class _LIBCPP_EXPORTED_FROM_ABI bad_array_new_length : public bad_alloc {
@@ -41,7 +41,7 @@ class _LIBCPP_EXPORTED_FROM_ABI bad_array_new_length : public bad_alloc {
   _LIBCPP_HIDE_FROM_ABI bad_array_new_length(const bad_array_new_length&) _NOEXCEPT            = default;
   _LIBCPP_HIDE_FROM_ABI bad_array_new_length& operator=(const bad_array_new_length&) _NOEXCEPT = default;
   ~bad_array_new_length() _NOEXCEPT override;
-  const char* what() const _NOEXCEPT override;
+  [[__nodiscard__]] const char* what() const _NOEXCEPT override;
 };
 
 #elif defined(_HAS_EXCEPTIONS) && _HAS_EXCEPTIONS == 0 // !_LIBCPP_ABI_VCRUNTIME
diff --git a/libcxx/include/typeindex b/libcxx/include/typeindex
index e32cb074318b6..82ea3d616f35d 100644
--- a/libcxx/include/typeindex
+++ b/libcxx/include/typeindex
@@ -86,8 +86,8 @@ public:
   }
 #  endif
 
-  _LIBCPP_HIDE_FROM_ABI size_t hash_code() const _NOEXCEPT { return __t_->hash_code(); }
-  _LIBCPP_HIDE_FROM_ABI const char* name() const _NOEXCEPT { return __t_->name(); }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t hash_code() const _NOEXCEPT { return __t_->hash_code(); }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const char* name() const _NOEXCEPT { return __t_->name(); }
 };
 
 template <class _Tp>
@@ -95,7 +95,9 @@ struct hash;
 
 template <>
 struct hash<type_index> : public __unary_function<type_index, size_t> {
-  _LIBCPP_HIDE_FROM_ABI size_t operator()(type_index __index) const _NOEXCEPT { return __index.hash_code(); }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t operator()(type_index __index) const _NOEXCEPT {
+    return __index.hash_code();
+  }
 };
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/typeinfo b/libcxx/include/typeinfo
index f608c94d3031e..f67d61e368087 100644
--- a/libcxx/include/typeinfo
+++ b/libcxx/include/typeinfo
@@ -95,11 +95,13 @@ class _LIBCPP_EXPORTED_FROM_ABI type_info {
 public:
   virtual ~type_info();
 
-  const char* name() const _NOEXCEPT;
+  [[__nodiscard__]] const char* name() const _NOEXCEPT;
 
-  _LIBCPP_HIDE_FROM_ABI bool before(const type_info& __arg) const _NOEXCEPT { return __compare(__arg) < 0; }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool before(const type_info& __arg) const _NOEXCEPT {
+    return __compare(__arg) < 0;
+  }
 
-  size_t hash_code() const _NOEXCEPT;
+  [[__nodiscard__]] size_t hash_code() const _NOEXCEPT;
 
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool operator==(const type_info& __arg) const _NOEXCEPT {
     // When evaluated in a constant expression, both type infos simply can't come
@@ -306,14 +308,15 @@ protected:
 
 public:
   virtual ~type_info();
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const char* name() const _NOEXCEPT {
+    return __impl::__type_name_to_string(__type_name);
+  }
 
-  _LIBCPP_HIDE_FROM_ABI const char* name() const _NOEXCEPT { return __impl::__type_name_to_string(__type_name); }
-
-  _LIBCPP_HIDE_FROM_ABI bool before(const type_info& __arg) const _NOEXCEPT {
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool before(const type_info& __arg) const _NOEXCEPT {
     return __impl::__lt(__type_name, __arg.__type_name);
   }
 
-  _LIBCPP_HIDE_FROM_ABI size_t hash_code() const _NOEXCEPT { return __impl::__hash(__type_name); }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t hash_code() const _NOEXCEPT { return __impl::__hash(__type_name); }
 
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 bool operator==(const type_info& __arg) const _NOEXCEPT {
     // When evaluated in a constant expression, both type infos simply can't come
@@ -336,7 +339,7 @@ public:
   _LIBCPP_HIDE_FROM_ABI bad_cast(const bad_cast&) _NOEXCEPT            = default;
   _LIBCPP_HIDE_FROM_ABI bad_cast& operator=(const bad_cast&) _NOEXCEPT = default;
   ~bad_cast() _NOEXCEPT override;
-  const char* what() const _NOEXCEPT override;
+  [[__nodiscard__]] const char* what() const _NOEXCEPT override;
 };
 
 class _LIBCPP_EXPORTED_FROM_ABI bad_typeid : public exception {
@@ -345,7 +348,7 @@ public:
   _LIBCPP_HIDE_FROM_ABI bad_typeid(const bad_typeid&) _NOEXCEPT            = default;
   _LIBCPP_HIDE_FROM_ABI bad_typeid& operator=(const bad_typeid&) _NOEXCEPT = default;
   ~bad_typeid() _NOEXCEPT override;
-  const char* what() const _NOEXCEPT override;
+  [[__nodiscard__]] const char* what() const _NOEXCEPT override;
 };
 
 } // namespace std
diff --git a/libcxx/test/libcxx/diagnostics/new.nodiscard.verify.cpp b/libcxx/test/libcxx/diagnostics/new.nodiscard.verify.cpp
index 505618c0b88d7..bd5b9dd001a11 100644
--- a/libcxx/test/libcxx/diagnostics/new.nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/diagnostics/new.nodiscard.verify.cpp
@@ -6,30 +6,52 @@
 //
 //===----------------------------------------------------------------------===//
 
-// UNSUPPORTED: c++03
+// <new>
 
-// check that <array> functions are marked [[nodiscard]]
-
-// clang-format off
+// Check that functions are marked [[nodiscard]]
 
 #include <new>
 
 #include "test_macros.h"
 
 void test() {
-  ::operator new(0);                                      // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
-  ::operator new(0, std::nothrow);                        // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
-  ::operator new[](0);                                    // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
-  ::operator new[](0, std::nothrow);                      // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  {
+    std::bad_alloc ex;
+
+    ex.what(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  }
+  {
+    std::bad_array_new_length ex;
+
+    ex.what(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  }
+
+  {
+    // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    ::operator new(0);
+    // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    ::operator new(0, std::nothrow);
+    // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    ::operator new[](0);
+    // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    ::operator new[](0, std::nothrow);
 #if _LIBCPP_HAS_ALIGNED_ALLOCATION
-  ::operator new(0, std::align_val_t{1});                 // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
-  ::operator new(0, std::align_val_t{1}, std::nothrow);   // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
-  ::operator new[](0, std::align_val_t{1});               // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
-  ::operator new[](0, std::align_val_t{1}, std::nothrow); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+    // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    ::operator new(0, std::align_val_t{1});
+    // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    ::operator new(0, std::align_val_t{1}, std::nothrow);
+    // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    ::operator new[](0, std::align_val_t{1});
+    // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+    ::operator new[](0, std::align_val_t{1}, std::nothrow);
 #endif // _LIBCPP_HAS_ALIGNED_ALLOCATION
+  }
 
 #if TEST_STD_VER >= 17
-  int* ptr = nullptr;
-  std::launder(ptr); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  {
+    int* ptr = nullptr;
+
+    std::launder(ptr); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  }
 #endif
 }
diff --git a/libcxx/test/libcxx/language.support/nodiscard.verify.cpp b/libcxx/test/libcxx/language.support/nodiscard.verify.cpp
index eeadd9f545538..6d784f27440e1 100644
--- a/libcxx/test/libcxx/language.support/nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/language.support/nodiscard.verify.cpp
@@ -16,6 +16,8 @@
 #include <coroutine>
 #include <exception>
 #include <initializer_list>
+#include <typeinfo>
+#include <typeindex>
 
 #include "test_macros.h"
 
@@ -126,4 +128,35 @@ void test() {
     il.end();   // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
   }
 #endif
+
+#if !defined(TEST_HAS_NO_RTTI)
+  { // <typeindex>
+    const std::type_index ti(typeid(int));
+
+    ti.hash_code(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+    ti.name();      // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+    std::hash<std::type_index> hash;
+
+    hash(ti); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  }
+#endif
+
+#if !defined(TEST_HAS_NO_RTTI)
+  { // <typeinfo>
+    const std::type_info& ti = typeid(int);
+
+    ti.name();      // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+    ti.before(ti);  // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+    ti.hash_code(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+    const std::bad_cast bc;
+
+    bc.what(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+    const std::bad_typeid bt;
+
+    bc.what(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  }
+#endif
 }
diff --git a/libcxx/test/support/test_macros.h b/libcxx/test/support/test_macros.h
index 8d88d6fad7d0b..f75dfbfa6ada5 100644
--- a/libcxx/test/support/test_macros.h
+++ b/libcxx/test/support/test_macros.h
@@ -230,6 +230,10 @@
 #  define TEST_HAS_NO_ALIGNED_ALLOCATION
 #endif
 
+#if !defined(_LIBCPP_ABI_VCRUNTIME)
+#  define TEST_HAS_NO_ABI_VCRUNTIME
+#endif
+
 #if TEST_STD_VER > 17
 #  define TEST_CONSTINIT constinit
 #elif __has_cpp_attribute(clang::require_constant_initialization)

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.

4 participants