Skip to content

Conversation

@H-G-Hristov
Copy link
Contributor

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

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

It was already discussed not to mark the type std::expected as [[nodiscard]] see:
#139651
#130820
Also:
#154943

@H-G-Hristov H-G-Hristov force-pushed the hgh/libcxx/nodiscard-to-expected branch from e7baa25 to ff344f6 Compare December 2, 2025 05:38
@github-actions
Copy link

github-actions bot commented Dec 2, 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-expected branch from ff344f6 to 65d0809 Compare December 2, 2025 06:11
@H-G-Hristov H-G-Hristov force-pushed the hgh/libcxx/nodiscard-to-expected branch from 65d0809 to ef8aa11 Compare December 2, 2025 06:14
@H-G-Hristov H-G-Hristov marked this pull request as ready for review December 3, 2025 05:50
@H-G-Hristov H-G-Hristov requested a review from a team as a code owner December 3, 2025 05:50
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Dec 3, 2025
@llvmbot
Copy link
Member

llvmbot commented Dec 3, 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.

It was already discussed not to mark the type std::expected as [[nodiscard]] see:
#139651
#130820
Also:
#154943


Patch is 87.59 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/170245.diff

14 Files Affected:

  • (modified) libcxx/include/__expected/bad_expected_access.h (+8-6)
  • (modified) libcxx/include/__expected/expected.h (+62-62)
  • (modified) libcxx/include/__expected/unexpected.h (+4-4)
  • (modified) libcxx/test/libcxx/utilities/expected/expected.expected/and_then.mandates.verify.cpp (+8-8)
  • (modified) libcxx/test/libcxx/utilities/expected/expected.expected/error_or.mandates.verify.cpp (+4-4)
  • (modified) libcxx/test/libcxx/utilities/expected/expected.expected/or_else.mandates.verify.cpp (+8-8)
  • (modified) libcxx/test/libcxx/utilities/expected/expected.expected/transform_error.mandates.verify.cpp (+8-8)
  • (modified) libcxx/test/libcxx/utilities/expected/expected.expected/value_or.mandates.verify.cpp (+8-4)
  • (modified) libcxx/test/libcxx/utilities/expected/expected.void/and_then.mandates.verify.cpp (+8-8)
  • (modified) libcxx/test/libcxx/utilities/expected/expected.void/error_or.mandates.verify.cpp (+4-4)
  • (modified) libcxx/test/libcxx/utilities/expected/expected.void/or_else.mandates.verify.cpp (+8-8)
  • (modified) libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp (+8-8)
  • (modified) libcxx/test/libcxx/utilities/expected/expected.void/value.lwg3940.verify.cpp (+5-4)
  • (added) libcxx/test/libcxx/utilities/expected/nodiscard.verify.cpp (+175)
diff --git a/libcxx/include/__expected/bad_expected_access.h b/libcxx/include/__expected/bad_expected_access.h index 1b734389e8311..b1958101d5178 100644 --- a/libcxx/include/__expected/bad_expected_access.h +++ b/libcxx/include/__expected/bad_expected_access.h @@ -43,9 +43,11 @@ class _LIBCPP_EXPORTED_FROM_ABI bad_expected_access<void> : public exception { public: # if _LIBCPP_AVAILABILITY_HAS_BAD_EXPECTED_ACCESS_KEY_FUNCTION - const char* what() const noexcept override; + [[nodiscard]] const char* what() const noexcept override; # else - _LIBCPP_HIDE_FROM_ABI_VIRTUAL const char* what() const noexcept override { return "bad access to std::expected"; } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI_VIRTUAL const char* what() const noexcept override { + return "bad access to std::expected"; + } # endif }; _LIBCPP_DIAGNOSTIC_POP @@ -55,10 +57,10 @@ class bad_expected_access : public bad_expected_access<void> { public: _LIBCPP_HIDE_FROM_ABI explicit bad_expected_access(_Err __e) : __unex_(std::move(__e)) {} - _LIBCPP_HIDE_FROM_ABI _Err& error() & noexcept { return __unex_; } - _LIBCPP_HIDE_FROM_ABI const _Err& error() const& noexcept { return __unex_; } - _LIBCPP_HIDE_FROM_ABI _Err&& error() && noexcept { return std::move(__unex_); } - _LIBCPP_HIDE_FROM_ABI const _Err&& error() const&& noexcept { return std::move(__unex_); } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _Err& error() & noexcept { return __unex_; } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI const _Err& error() const& noexcept { return __unex_; } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _Err&& error() && noexcept { return std::move(__unex_); } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI const _Err&& error() const&& noexcept { return std::move(__unex_); } private: _Err __unex_; diff --git a/libcxx/include/__expected/expected.h b/libcxx/include/__expected/expected.h index be37e8ab66ac4..b6a9211ae3cdc 100644 --- a/libcxx/include/__expected/expected.h +++ b/libcxx/include/__expected/expected.h @@ -798,25 +798,25 @@ class expected : private __expected_base<_Tp, _Err> { return std::addressof(this->__val()); } - _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator*() const& noexcept { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator*() const& noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( this->__has_val(), "expected::operator* requires the expected to contain a value"); return this->__val(); } - _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() & noexcept { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() & noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( this->__has_val(), "expected::operator* requires the expected to contain a value"); return this->__val(); } - _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& operator*() const&& noexcept { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& operator*() const&& noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( this->__has_val(), "expected::operator* requires the expected to contain a value"); return std::move(this->__val()); } - _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& operator*() && noexcept { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& operator*() && noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( this->__has_val(), "expected::operator* requires the expected to contain a value"); return std::move(this->__val()); @@ -824,9 +824,9 @@ class expected : private __expected_base<_Tp, _Err> { _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return this->__has_val(); } - _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return this->__has_val(); } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return this->__has_val(); } - _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& value() const& { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& value() const& { static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible"); if (!this->__has_val()) { std::__throw_bad_expected_access<_Err>(std::as_const(error())); @@ -834,7 +834,7 @@ class expected : private __expected_base<_Tp, _Err> { return this->__val(); } - _LIBCPP_HIDE_FROM_ABI constexpr _Tp& value() & { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp& value() & { static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible"); if (!this->__has_val()) { std::__throw_bad_expected_access<_Err>(std::as_const(error())); @@ -842,7 +842,7 @@ class expected : private __expected_base<_Tp, _Err> { return this->__val(); } - _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& value() const&& { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& value() const&& { static_assert(is_copy_constructible_v<_Err> && is_constructible_v<_Err, decltype(std::move(error()))>, "error_type has to be both copy constructible and constructible from decltype(std::move(error()))"); if (!this->__has_val()) { @@ -851,7 +851,7 @@ class expected : private __expected_base<_Tp, _Err> { return std::move(this->__val()); } - _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& value() && { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& value() && { static_assert(is_copy_constructible_v<_Err> && is_constructible_v<_Err, decltype(std::move(error()))>, "error_type has to be both copy constructible and constructible from decltype(std::move(error()))"); if (!this->__has_val()) { @@ -860,46 +860,46 @@ class expected : private __expected_base<_Tp, _Err> { return std::move(this->__val()); } - _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( !this->__has_val(), "expected::error requires the expected to contain an error"); return this->__unex(); } - _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( !this->__has_val(), "expected::error requires the expected to contain an error"); return this->__unex(); } - _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( !this->__has_val(), "expected::error requires the expected to contain an error"); return std::move(this->__unex()); } - _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( !this->__has_val(), "expected::error requires the expected to contain an error"); return std::move(this->__unex()); } template <class _Up = remove_cv_t<_Tp>> - _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) const& { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) const& { static_assert(is_copy_constructible_v<_Tp>, "value_type has to be copy constructible"); static_assert(is_convertible_v<_Up, _Tp>, "argument has to be convertible to value_type"); return this->__has_val() ? this->__val() : static_cast<_Tp>(std::forward<_Up>(__v)); } template <class _Up = remove_cv_t<_Tp>> - _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) && { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) && { static_assert(is_move_constructible_v<_Tp>, "value_type has to be move constructible"); static_assert(is_convertible_v<_Up, _Tp>, "argument has to be convertible to value_type"); return this->__has_val() ? std::move(this->__val()) : static_cast<_Tp>(std::forward<_Up>(__v)); } template <class _Up = _Err> - _LIBCPP_HIDE_FROM_ABI constexpr _Err error_or(_Up&& __error) const& { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Err error_or(_Up&& __error) const& { static_assert(is_copy_constructible_v<_Err>, "error_type has to be copy constructible"); static_assert(is_convertible_v<_Up, _Err>, "argument has to be convertible to error_type"); if (has_value()) @@ -908,7 +908,7 @@ class expected : private __expected_base<_Tp, _Err> { } template <class _Up = _Err> - _LIBCPP_HIDE_FROM_ABI constexpr _Err error_or(_Up&& __error) && { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Err error_or(_Up&& __error) && { static_assert(is_move_constructible_v<_Err>, "error_type has to be move constructible"); static_assert(is_convertible_v<_Up, _Err>, "argument has to be convertible to error_type"); if (has_value()) @@ -919,7 +919,7 @@ class expected : private __expected_base<_Tp, _Err> { // [expected.void.monadic], monadic template <class _Func> requires is_constructible_v<_Err, _Err&> - _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) & { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) & { using _Up = remove_cvref_t<invoke_result_t<_Func, _Tp&>>; static_assert(__is_std_expected<_Up>::value, "The result of f(value()) must be a specialization of std::expected"); static_assert(is_same_v<typename _Up::error_type, _Err>, @@ -932,7 +932,7 @@ class expected : private __expected_base<_Tp, _Err> { template <class _Func> requires is_constructible_v<_Err, const _Err&> - _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const& { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const& { using _Up = remove_cvref_t<invoke_result_t<_Func, const _Tp&>>; static_assert(__is_std_expected<_Up>::value, "The result of f(value()) must be a specialization of std::expected"); static_assert(is_same_v<typename _Up::error_type, _Err>, @@ -945,7 +945,7 @@ class expected : private __expected_base<_Tp, _Err> { template <class _Func> requires is_constructible_v<_Err, _Err&&> - _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) && { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) && { using _Up = remove_cvref_t<invoke_result_t<_Func, _Tp&&>>; static_assert( __is_std_expected<_Up>::value, "The result of f(std::move(value())) must be a specialization of std::expected"); @@ -959,7 +959,7 @@ class expected : private __expected_base<_Tp, _Err> { template <class _Func> requires is_constructible_v<_Err, const _Err&&> - _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const&& { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const&& { using _Up = remove_cvref_t<invoke_result_t<_Func, const _Tp&&>>; static_assert( __is_std_expected<_Up>::value, "The result of f(std::move(value())) must be a specialization of std::expected"); @@ -973,7 +973,7 @@ class expected : private __expected_base<_Tp, _Err> { template <class _Func> requires is_constructible_v<_Tp, _Tp&> - _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) & { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) & { using _Gp = remove_cvref_t<invoke_result_t<_Func, _Err&>>; static_assert(__is_std_expected<_Gp>::value, "The result of f(error()) must be a specialization of std::expected"); static_assert(is_same_v<typename _Gp::value_type, _Tp>, @@ -986,7 +986,7 @@ class expected : private __expected_base<_Tp, _Err> { template <class _Func> requires is_constructible_v<_Tp, const _Tp&> - _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) const& { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) const& { using _Gp = remove_cvref_t<invoke_result_t<_Func, const _Err&>>; static_assert(__is_std_expected<_Gp>::value, "The result of f(error()) must be a specialization of std::expected"); static_assert(is_same_v<typename _Gp::value_type, _Tp>, @@ -999,7 +999,7 @@ class expected : private __expected_base<_Tp, _Err> { template <class _Func> requires is_constructible_v<_Tp, _Tp&&> - _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) && { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) && { using _Gp = remove_cvref_t<invoke_result_t<_Func, _Err&&>>; static_assert( __is_std_expected<_Gp>::value, "The result of f(std::move(error())) must be a specialization of std::expected"); @@ -1013,7 +1013,7 @@ class expected : private __expected_base<_Tp, _Err> { template <class _Func> requires is_constructible_v<_Tp, const _Tp&&> - _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) const&& { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto or_else(_Func&& __f) const&& { using _Gp = remove_cvref_t<invoke_result_t<_Func, const _Err&&>>; static_assert( __is_std_expected<_Gp>::value, "The result of f(std::move(error())) must be a specialization of std::expected"); @@ -1027,7 +1027,7 @@ class expected : private __expected_base<_Tp, _Err> { template <class _Func> requires is_constructible_v<_Err, _Err&> - _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) & { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) & { using _Up = remove_cv_t<invoke_result_t<_Func, _Tp&>>; if (!has_value()) { return expected<_Up, _Err>(unexpect, error()); @@ -1043,7 +1043,7 @@ class expected : private __expected_base<_Tp, _Err> { template <class _Func> requires is_constructible_v<_Err, const _Err&> - _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const& { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const& { using _Up = remove_cv_t<invoke_result_t<_Func, const _Tp&>>; if (!has_value()) { return expected<_Up, _Err>(unexpect, error()); @@ -1059,7 +1059,7 @@ class expected : private __expected_base<_Tp, _Err> { template <class _Func> requires is_constructible_v<_Err, _Err&&> - _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) && { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) && { using _Up = remove_cv_t<invoke_result_t<_Func, _Tp&&>>; if (!has_value()) { return expected<_Up, _Err>(unexpect, std::move(error())); @@ -1075,7 +1075,7 @@ class expected : private __expected_base<_Tp, _Err> { template <class _Func> requires is_constructible_v<_Err, const _Err&&> - _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const&& { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const&& { using _Up = remove_cv_t<invoke_result_t<_Func, const _Tp&&>>; if (!has_value()) { return expected<_Up, _Err>(unexpect, std::move(error())); @@ -1091,7 +1091,7 @@ class expected : private __expected_base<_Tp, _Err> { template <class _Func> requires is_constructible_v<_Tp, _Tp&> - _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) & { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) & { using _Gp = remove_cv_t<invoke_result_t<_Func, _Err&>>; static_assert(__valid_std_unexpected<_Gp>::value, "The result of f(error()) must be a valid template argument for unexpected"); @@ -1103,7 +1103,7 @@ class expected : private __expected_base<_Tp, _Err> { template <class _Func> requires is_constructible_v<_Tp, const _Tp&> - _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) const& { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) const& { using _Gp = remove_cv_t<invoke_result_t<_Func, const _Err&>>; static_assert(__valid_std_unexpected<_Gp>::value, "The result of f(error()) must be a valid template argument for unexpected"); @@ -1115,7 +1115,7 @@ class expected : private __expected_base<_Tp, _Err> { template <class _Func> requires is_constructible_v<_Tp, _Tp&&> - _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) && { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) && { using _Gp = remove_cv_t<invoke_result_t<_Func, _Err&&>>; static_assert(__valid_std_unexpected<_Gp>::value, "The result of f(std::move(error())) must be a valid template argument for unexpected"); @@ -1128,7 +1128,7 @@ class expected : private __expected_base<_Tp, _Err> { template <class _Func> requires is_constructible_v<_Tp, const _Tp&&> - _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) const&& { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto transform_error(_Func&& __f) const&& { using _Gp = remove_cv_t<invoke_result_t<_Func, const _Err&&>>; static_assert(__valid_std_unexpected<_Gp>::value, "The result of f(std::move(error())) must be a valid template argument for unexpected"); @@ -1145,8 +1145,8 @@ class expected : private __expected_base<_Tp, _Err> { requires(!is_void_v<_T2>) # if _LIBCPP_STD_VER >= 26 && requires { - { *__x == *__y } -> __core_convertible_to<bool>; - { __x.error() == __y.error() } -> __core_convertible_to<bool>; + { *__x == *__y }->__core_convertible_to<bool>; + { __x.error() == __y.error() }->__core_convertible_to<bool>; } # endif { @@ -1165,7 +1165,7 @@ class expected : private __expected_base<_Tp, _Err> { _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const _T2& __v) # if _LIBCPP_STD_VER >= 26 requires(!__is_std_expected<_T2>::value) && requires { - { *__x == __v } -> __core_convertible_to<bool>; + { *__x == __v }->__core_convertible_to<bool>; } # endif { @@ -1176,7 +1176,7 @@ class expected : private __expected_base<_Tp, _Err> { _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __e) # if _LIBCPP_STD_VER >= 26 requires requires { - { __x.error() == __e.error() } -> __core_convertible_to<bool>; + { __x.error() == __e.error() }->__core_convertible_to<bool>; } # endif { @@ -1595,7 +1595,7 @@ class expected<_Tp, _Err> : private __expected_void_base<_Err> { // [expected.void.obs], observers _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return this->__has_val(); } - _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return this->__has_val(); } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return this->__has_val(); } _LIBCPP_HIDE_FROM_ABI constexpr void operator*() const noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( @@ -1616,32 +1616,32 @@ class expected<_Tp, _Err> : private __expected_void_base<_Err> { } } - _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const _Err& error() const& noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( !this->__has_val(), "expected::error requires the expected to contain an error"); return this->__unex(); } - _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Err& error() & noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( !this->__has_val(), "expected::error requires the expected to contain an error"); return this->__unex(); } - _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const _Err&& error() const&& noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( !this->__has_val(), "expected::error requires the expected to contain an error"); return std::move(this->__unex()); } - _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept { + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Err&& error() && noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( !this->__has_val(), "expected::error requires the expected to contain an error"); return std::move(this->__unex()); } template <class _Up = _Err> - _LIBCPP_HIDE_FROM_ABI constexpr _Err error_or(_Up&& __error) const& { + [[nodiscard]] _LIBC... [truncated] 
Copy link
Contributor

@frederick-vs-ja frederick-vs-ja left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with pure formatting changes dropped.

@H-G-Hristov
Copy link
Contributor Author

H-G-Hristov commented Dec 14, 2025

LGTM with pure formatting changes dropped.

Thank you! Reverted the formatting changes.

@Zingam Zingam merged commit 9975cb1 into llvm:main Dec 14, 2025
80 checks passed
anonymouspc pushed a commit to anonymouspc/llvm that referenced this pull request Dec 15, 2025
[[nodiscard]] should be applied to functions where discarding the return value is most likely a correctness issue. - https://libcxx.llvm.org/CodingGuidelines.html - https://wg21.link/expected.bad.void - https://wg21.link/expected.bad - https://wg21.link/expected.expected - https://wg21.link/expected.void - https://wg21.link/expected.unexpected It was already discussed not to mark the type `std::expected` as `[[nodiscard]]` see: llvm#139651 llvm#130820 Also: llvm#154943
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.

4 participants