-
Notifications
You must be signed in to change notification settings - Fork 15.5k
[libc++] Applied [[nodiscard]] to <exception>, <stdexcept> and <system_error>
#170837
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Zingam
merged 4 commits into
llvm:main
from
H-G-Hristov:hgh/libcxx/nodiscard-to-exception
Dec 6, 2025
Merged
[libc++] Applied [[nodiscard]] to <exception>, <stdexcept> and <system_error>
#170837
Zingam
merged 4 commits into
llvm:main
from
H-G-Hristov:hgh/libcxx/nodiscard-to-exception
Dec 6, 2025
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
40a08d7 to
50ab874
Compare
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
[[nodiscard] to <exception>, <stdexcept> and <system_error>[[nodiscard]] to <exception>, <stdexcept> and <system_error>
…<system_error>` [[nodiscard]] should be applied to functions where discarding the return value is most likely a correctness issue. - https://libcxx.llvm.org/CodingGuidelines.html
50ab874 to
5f2d335
Compare
Member
|
@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/170837.diff 10 Files Affected:
diff --git a/libcxx/include/__exception/exception.h b/libcxx/include/__exception/exception.h
index 161cc49979e4a..ddc34b0fa8fa1 100644
--- a/libcxx/include/__exception/exception.h
+++ b/libcxx/include/__exception/exception.h
@@ -54,7 +54,9 @@ class exception { // base of all library exceptions
virtual ~exception() _NOEXCEPT {}
- virtual char const* what() const _NOEXCEPT { return __data_._What ? __data_._What : "Unknown exception"; }
+ [[__nodiscard__]] virtual char const* what() const _NOEXCEPT {
+ return __data_._What ? __data_._What : "Unknown exception";
+ }
private:
__std_exception_data __data_;
@@ -76,7 +78,7 @@ class _LIBCPP_EXPORTED_FROM_ABI exception {
_LIBCPP_HIDE_FROM_ABI exception& operator=(const exception&) _NOEXCEPT = default;
virtual ~exception() _NOEXCEPT;
- virtual const char* what() const _NOEXCEPT;
+ [[__nodiscard__]] virtual const char* what() const _NOEXCEPT;
};
class _LIBCPP_EXPORTED_FROM_ABI bad_exception : public exception {
@@ -85,7 +87,7 @@ class _LIBCPP_EXPORTED_FROM_ABI bad_exception : public exception {
_LIBCPP_HIDE_FROM_ABI bad_exception(const bad_exception&) _NOEXCEPT = default;
_LIBCPP_HIDE_FROM_ABI bad_exception& operator=(const bad_exception&) _NOEXCEPT = default;
~bad_exception() _NOEXCEPT override;
- const char* what() const _NOEXCEPT override;
+ [[__nodiscard__]] const char* what() const _NOEXCEPT override;
};
#endif // !_LIBCPP_ABI_VCRUNTIME
diff --git a/libcxx/include/__exception/nested_exception.h b/libcxx/include/__exception/nested_exception.h
index dc3266a27cdfd..dd84efbccde88 100644
--- a/libcxx/include/__exception/nested_exception.h
+++ b/libcxx/include/__exception/nested_exception.h
@@ -40,7 +40,7 @@ class _LIBCPP_EXPORTED_FROM_ABI nested_exception {
// access functions
[[__noreturn__]] void rethrow_nested() const;
- _LIBCPP_HIDE_FROM_ABI exception_ptr nested_ptr() const _NOEXCEPT { return __ptr_; }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI exception_ptr nested_ptr() const _NOEXCEPT { return __ptr_; }
};
template <class _Tp>
diff --git a/libcxx/include/__exception/operations.h b/libcxx/include/__exception/operations.h
index 29d5c698a96db..2b93ad260c30b 100644
--- a/libcxx/include/__exception/operations.h
+++ b/libcxx/include/__exception/operations.h
@@ -20,22 +20,22 @@ _LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD
defined(_LIBCPP_BUILDING_LIBRARY)
using unexpected_handler = void (*)();
_LIBCPP_EXPORTED_FROM_ABI unexpected_handler set_unexpected(unexpected_handler) _NOEXCEPT;
-_LIBCPP_EXPORTED_FROM_ABI unexpected_handler get_unexpected() _NOEXCEPT;
+[[__nodiscard__]] _LIBCPP_EXPORTED_FROM_ABI unexpected_handler get_unexpected() _NOEXCEPT;
[[__noreturn__]] _LIBCPP_EXPORTED_FROM_ABI void unexpected();
#endif
using terminate_handler = void (*)();
_LIBCPP_EXPORTED_FROM_ABI terminate_handler set_terminate(terminate_handler) _NOEXCEPT;
-_LIBCPP_EXPORTED_FROM_ABI terminate_handler get_terminate() _NOEXCEPT;
+[[__nodiscard__]] _LIBCPP_EXPORTED_FROM_ABI terminate_handler get_terminate() _NOEXCEPT;
#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_UNCAUGHT_EXCEPTION)
-_LIBCPP_EXPORTED_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX17 bool uncaught_exception() _NOEXCEPT;
+[[__nodiscard__]] _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_DEPRECATED_IN_CXX17 bool uncaught_exception() _NOEXCEPT;
#endif // _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_UNCAUGHT_EXCEPTION)
-_LIBCPP_EXPORTED_FROM_ABI int uncaught_exceptions() _NOEXCEPT;
+[[__nodiscard__]] _LIBCPP_EXPORTED_FROM_ABI int uncaught_exceptions() _NOEXCEPT;
class _LIBCPP_EXPORTED_FROM_ABI exception_ptr;
-_LIBCPP_EXPORTED_FROM_ABI exception_ptr current_exception() _NOEXCEPT;
+[[__nodiscard__]] _LIBCPP_EXPORTED_FROM_ABI exception_ptr current_exception() _NOEXCEPT;
[[__noreturn__]] _LIBCPP_EXPORTED_FROM_ABI void rethrow_exception(exception_ptr);
_LIBCPP_END_UNVERSIONED_NAMESPACE_STD
diff --git a/libcxx/include/__system_error/error_category.h b/libcxx/include/__system_error/error_category.h
index 191f4d83a90c0..7f7c7355c7e7f 100644
--- a/libcxx/include/__system_error/error_category.h
+++ b/libcxx/include/__system_error/error_category.h
@@ -37,11 +37,11 @@ class _LIBCPP_EXPORTED_FROM_ABI error_category {
error_category(const error_category&) = delete;
error_category& operator=(const error_category&) = delete;
- virtual const char* name() const _NOEXCEPT = 0;
- virtual error_condition default_error_condition(int __ev) const _NOEXCEPT;
- virtual bool equivalent(int __code, const error_condition& __condition) const _NOEXCEPT;
- virtual bool equivalent(const error_code& __code, int __condition) const _NOEXCEPT;
- virtual string message(int __ev) const = 0;
+ [[__nodiscard__]] virtual const char* name() const _NOEXCEPT = 0;
+ [[__nodiscard__]] virtual error_condition default_error_condition(int __ev) const _NOEXCEPT;
+ [[__nodiscard__]] virtual bool equivalent(int __code, const error_condition& __condition) const _NOEXCEPT;
+ [[__nodiscard__]] virtual bool equivalent(const error_code& __code, int __condition) const _NOEXCEPT;
+ [[__nodiscard__]] virtual string message(int __ev) const = 0;
_LIBCPP_HIDE_FROM_ABI bool operator==(const error_category& __rhs) const _NOEXCEPT { return this == &__rhs; }
@@ -67,8 +67,8 @@ class _LIBCPP_HIDDEN __do_message : public error_category {
string message(int __ev) const override;
};
-[[__gnu__::__const__]] _LIBCPP_EXPORTED_FROM_ABI const error_category& generic_category() _NOEXCEPT;
-[[__gnu__::__const__]] _LIBCPP_EXPORTED_FROM_ABI const error_category& system_category() _NOEXCEPT;
+[[__gnu__::__const__]] [[__nodiscard__]] _LIBCPP_EXPORTED_FROM_ABI const error_category& generic_category() _NOEXCEPT;
+[[__gnu__::__const__]] [[__nodiscard__]] _LIBCPP_EXPORTED_FROM_ABI const error_category& system_category() _NOEXCEPT;
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__system_error/error_code.h b/libcxx/include/__system_error/error_code.h
index f6ea40d6efcb9..e904376939753 100644
--- a/libcxx/include/__system_error/error_code.h
+++ b/libcxx/include/__system_error/error_code.h
@@ -71,20 +71,20 @@ class _LIBCPP_EXPORTED_FROM_ABI error_code {
__cat_ = &system_category();
}
- _LIBCPP_HIDE_FROM_ABI int value() const _NOEXCEPT { return __val_; }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI int value() const _NOEXCEPT { return __val_; }
- _LIBCPP_HIDE_FROM_ABI const error_category& category() const _NOEXCEPT { return *__cat_; }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const error_category& category() const _NOEXCEPT { return *__cat_; }
- _LIBCPP_HIDE_FROM_ABI error_condition default_error_condition() const _NOEXCEPT {
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI error_condition default_error_condition() const _NOEXCEPT {
return __cat_->default_error_condition(__val_);
}
- string message() const;
+ [[__nodiscard__]] string message() const;
_LIBCPP_HIDE_FROM_ABI explicit operator bool() const _NOEXCEPT { return __val_ != 0; }
};
-inline _LIBCPP_HIDE_FROM_ABI error_code make_error_code(errc __e) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI error_code make_error_code(errc __e) _NOEXCEPT {
return error_code(static_cast<int>(__e), generic_category());
}
diff --git a/libcxx/include/__system_error/error_condition.h b/libcxx/include/__system_error/error_condition.h
index 34819f4b6de4c..be7deaba0444c 100644
--- a/libcxx/include/__system_error/error_condition.h
+++ b/libcxx/include/__system_error/error_condition.h
@@ -80,15 +80,15 @@ class _LIBCPP_EXPORTED_FROM_ABI error_condition {
__cat_ = &generic_category();
}
- _LIBCPP_HIDE_FROM_ABI int value() const _NOEXCEPT { return __val_; }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI int value() const _NOEXCEPT { return __val_; }
- _LIBCPP_HIDE_FROM_ABI const error_category& category() const _NOEXCEPT { return *__cat_; }
- string message() const;
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const error_category& category() const _NOEXCEPT { return *__cat_; }
+ [[__nodiscard__]] string message() const;
_LIBCPP_HIDE_FROM_ABI explicit operator bool() const _NOEXCEPT { return __val_ != 0; }
};
-inline _LIBCPP_HIDE_FROM_ABI error_condition make_error_condition(errc __e) _NOEXCEPT {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI error_condition make_error_condition(errc __e) _NOEXCEPT {
return error_condition(static_cast<int>(__e), generic_category());
}
diff --git a/libcxx/include/__system_error/system_error.h b/libcxx/include/__system_error/system_error.h
index 36ccf94cc010d..74427d8f0bf9b 100644
--- a/libcxx/include/__system_error/system_error.h
+++ b/libcxx/include/__system_error/system_error.h
@@ -36,7 +36,7 @@ class _LIBCPP_EXPORTED_FROM_ABI system_error : public runtime_error {
_LIBCPP_HIDE_FROM_ABI system_error(const system_error&) _NOEXCEPT = default;
~system_error() _NOEXCEPT override;
- _LIBCPP_HIDE_FROM_ABI const error_code& code() const _NOEXCEPT { return __ec_; }
+ [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const error_code& code() const _NOEXCEPT { return __ec_; }
};
// __ev is expected to be an error in the generic_category domain (e.g. from
diff --git a/libcxx/include/stdexcept b/libcxx/include/stdexcept
index 85e11629bd6e3..d01de5c46211c 100644
--- a/libcxx/include/stdexcept
+++ b/libcxx/include/stdexcept
@@ -91,7 +91,7 @@ public:
~logic_error() _NOEXCEPT override;
- const char* what() const _NOEXCEPT override;
+ [[__nodiscard__]] const char* what() const _NOEXCEPT override;
# else
public:
@@ -115,7 +115,7 @@ public:
~runtime_error() _NOEXCEPT override;
- const char* what() const _NOEXCEPT override;
+ [[__nodiscard__]] const char* what() const _NOEXCEPT override;
# else
public:
diff --git a/libcxx/test/libcxx/diagnostics/syserr/nodiscard.verify.cpp b/libcxx/test/libcxx/diagnostics/syserr/nodiscard.verify.cpp
new file mode 100644
index 0000000000000..26565a1ecdd10
--- /dev/null
+++ b/libcxx/test/libcxx/diagnostics/syserr/nodiscard.verify.cpp
@@ -0,0 +1,108 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// Check that functions are marked [[nodiscard]]
+
+#include <stdexcept>
+#include <system_error>
+
+void test() {
+ { // <stdexcept>
+ std::logic_error le("logic error");
+ le.what(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+ std::runtime_error re("runtime error");
+ re.what(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+ std::domain_error de("domain error");
+ de.what(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+ std::invalid_argument ia("invalid argument");
+ ia.what(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+ std::length_error lerr("length error");
+ lerr.what(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+ std::out_of_range oor("out of range");
+ oor.what(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+ std::range_error rerr("range error");
+ rerr.what(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+ std::overflow_error oferr("overflow error");
+ oferr.what(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+ std::underflow_error uferr("underflow error");
+ uferr.what(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ }
+ { // <system_error>
+ {
+ // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::generic_category();
+
+ const std::error_category& ec = std::generic_category();
+
+ // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ ec.name();
+ // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ ec.default_error_condition(94);
+ // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ ec.equivalent(94, ec.default_error_condition(82));
+ // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ ec.equivalent(std::error_code(49, ec), 94);
+ // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ ec.message(82);
+ }
+ {
+ // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::system_category();
+
+ const std::error_category& ec = std::system_category();
+
+ // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ ec.name();
+ // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ ec.default_error_condition(94);
+ // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ ec.equivalent(94, ec.default_error_condition(82));
+ // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ ec.equivalent(std::error_code(49, ec), 94);
+ // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ ec.message(82);
+ }
+ {
+ std::error_code ec;
+
+ // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ ec.value();
+ // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ ec.category();
+ // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ ec.default_error_condition();
+
+ // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ ec.message();
+
+ // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::make_error_code(std::errc::invalid_argument);
+ }
+ {
+ std::error_condition ec;
+
+ // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ ec.value();
+ // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ ec.category();
+ // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ ec.message();
+
+ // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::make_error_condition(std::errc::invalid_argument);
+ }
+ }
+}
diff --git a/libcxx/test/libcxx/language.support/nodiscard.verify.cpp b/libcxx/test/libcxx/language.support/nodiscard.verify.cpp
index b87b04ad9f1ef..40dbe5c90afee 100644
--- a/libcxx/test/libcxx/language.support/nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/language.support/nodiscard.verify.cpp
@@ -6,12 +6,15 @@
//
//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03
+// ADDITIONAL_COMPILE_FLAGS: -Wno-deprecated
+// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX17_REMOVED_UNEXPECTED_FUNCTIONS
+// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX20_REMOVED_UNCAUGHT_EXCEPTION
// Check that functions are marked [[nodiscard]]
#include <compare>
#include <coroutine>
+#include <exception>
#include <functional>
#include <initializer_list>
@@ -81,6 +84,41 @@ void test() {
}
#endif
+ { // <exception>
+ {
+ std::bad_exception bex;
+
+ bex.what(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ }
+ {
+ std::exception ex;
+
+ ex.what(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ }
+ {
+ std::nested_exception nex;
+
+ nex.nested_ptr(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+ }
+
+#if TEST_STD_VER <= 14
+ std::get_unexpected(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+#endif
+
+ std::get_terminate(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+#if _LIBCPP_STD_VER <= 17
+ // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::uncaught_exception();
+#endif
+ // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::uncaught_exceptions();
+
+ // expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::current_exception();
+ }
+
+#if TEST_STD_VER >= 11
{ // <initializer_list>
std::initializer_list<int> il{94, 82, 49};
@@ -88,4 +126,5 @@ void test() {
il.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
il.end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
}
+#endif
}
|
Contributor
Author
|
@frederick-vs-ja Sorry for nagging! Can we merge this? |
frederick-vs-ja
approved these changes
Dec 6, 2025
honeygoyal
pushed a commit
to honeygoyal/llvm-project
that referenced
this pull request
Dec 9, 2025
…`<system_error>` (llvm#170837) [[nodiscard]] should be applied to functions where discarding the return value is most likely a correctness issue. - https://libcxx.llvm.org/CodingGuidelines.html
84 tasks
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
[[nodiscard]] should be applied to functions where discarding the return value is most likely a correctness issue.