[libc++] Applied [[nodiscard]] to Language Support (partially) (#169611)
https://wg21.link/#support `[[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 was implemented in this patch: - [x] `<compare>` - [x] `<corotine>` - [x] `<initializer_list>` - [x] Integer comparisons --------- Co-authored-by: Hristo Hristov <zingam@outlook.com> Co-authored-by: A. Jiang <de34@live.cn>
This commit is contained in:
parent
bbb8f7aaf8
commit
8706d82bd4
@ -20,12 +20,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if _LIBCPP_STD_VER >= 20
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI inline constexpr bool is_eq(partial_ordering __c) noexcept { return __c == 0; }
|
||||
_LIBCPP_HIDE_FROM_ABI inline constexpr bool is_neq(partial_ordering __c) noexcept { return __c != 0; }
|
||||
_LIBCPP_HIDE_FROM_ABI inline constexpr bool is_lt(partial_ordering __c) noexcept { return __c < 0; }
|
||||
_LIBCPP_HIDE_FROM_ABI inline constexpr bool is_lteq(partial_ordering __c) noexcept { return __c <= 0; }
|
||||
_LIBCPP_HIDE_FROM_ABI inline constexpr bool is_gt(partial_ordering __c) noexcept { return __c > 0; }
|
||||
_LIBCPP_HIDE_FROM_ABI inline constexpr bool is_gteq(partial_ordering __c) noexcept { return __c >= 0; }
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline constexpr bool is_eq(partial_ordering __c) noexcept { return __c == 0; }
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline constexpr bool is_neq(partial_ordering __c) noexcept { return __c != 0; }
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline constexpr bool is_lt(partial_ordering __c) noexcept { return __c < 0; }
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline constexpr bool is_lteq(partial_ordering __c) noexcept { return __c <= 0; }
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline constexpr bool is_gt(partial_ordering __c) noexcept { return __c > 0; }
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline constexpr bool is_gteq(partial_ordering __c) noexcept { return __c >= 0; }
|
||||
|
||||
#endif // _LIBCPP_STD_VER >= 20
|
||||
|
||||
|
||||
@ -44,9 +44,9 @@ public:
|
||||
}
|
||||
|
||||
// [coroutine.handle.export.import], export/import
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr void* address() const noexcept { return __handle_; }
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr void* address() const noexcept { return __handle_; }
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI static constexpr coroutine_handle from_address(void* __addr) noexcept {
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr coroutine_handle from_address(void* __addr) noexcept {
|
||||
coroutine_handle __tmp;
|
||||
__tmp.__handle_ = __addr;
|
||||
return __tmp;
|
||||
@ -55,7 +55,7 @@ public:
|
||||
// [coroutine.handle.observers], observers
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __handle_ != nullptr; }
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI bool done() const {
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool done() const {
|
||||
_LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(__is_suspended(), "done() can be called only on suspended coroutines");
|
||||
return __builtin_coro_done(__handle_);
|
||||
}
|
||||
@ -100,7 +100,7 @@ public:
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr coroutine_handle(nullptr_t) noexcept {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI static coroutine_handle from_promise(_Promise& __promise) {
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static coroutine_handle from_promise(_Promise& __promise) {
|
||||
using _RawPromise = __remove_cv_t<_Promise>;
|
||||
coroutine_handle __tmp;
|
||||
__tmp.__handle_ =
|
||||
@ -114,9 +114,9 @@ public:
|
||||
}
|
||||
|
||||
// [coroutine.handle.export.import], export/import
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr void* address() const noexcept { return __handle_; }
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr void* address() const noexcept { return __handle_; }
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI static constexpr coroutine_handle from_address(void* __addr) noexcept {
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr coroutine_handle from_address(void* __addr) noexcept {
|
||||
coroutine_handle __tmp;
|
||||
__tmp.__handle_ = __addr;
|
||||
return __tmp;
|
||||
@ -130,7 +130,7 @@ public:
|
||||
// [coroutine.handle.observers], observers
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return __handle_ != nullptr; }
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI bool done() const {
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool done() const {
|
||||
_LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL(__is_suspended(), "done() can be called only on suspended coroutines");
|
||||
return __builtin_coro_done(__handle_);
|
||||
}
|
||||
@ -150,7 +150,7 @@ public:
|
||||
}
|
||||
|
||||
// [coroutine.handle.promise], promise access
|
||||
_LIBCPP_HIDE_FROM_ABI _Promise& promise() const {
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _Promise& promise() const {
|
||||
return *static_cast<_Promise*>(__builtin_coro_promise(this->__handle_, alignof(_Promise), false));
|
||||
}
|
||||
|
||||
@ -165,7 +165,7 @@ private:
|
||||
// [coroutine.handle.hash]
|
||||
template <class _Tp>
|
||||
struct hash<coroutine_handle<_Tp>> {
|
||||
_LIBCPP_HIDE_FROM_ABI size_t operator()(const coroutine_handle<_Tp>& __v) const noexcept {
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI size_t operator()(const coroutine_handle<_Tp>& __v) const noexcept {
|
||||
return hash<void*>()(__v.address());
|
||||
}
|
||||
};
|
||||
|
||||
@ -35,7 +35,7 @@ public:
|
||||
|
||||
// [coroutine.handle.noop.observers], observers
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return true; }
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr bool done() const noexcept { return false; }
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool done() const noexcept { return false; }
|
||||
|
||||
// [coroutine.handle.noop.resumption], resumption
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr void operator()() const noexcept {}
|
||||
@ -43,13 +43,13 @@ public:
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr void destroy() const noexcept {}
|
||||
|
||||
// [coroutine.handle.noop.promise], promise access
|
||||
_LIBCPP_HIDE_FROM_ABI noop_coroutine_promise& promise() const noexcept {
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI noop_coroutine_promise& promise() const noexcept {
|
||||
return *static_cast<noop_coroutine_promise*>(
|
||||
__builtin_coro_promise(this->__handle_, alignof(noop_coroutine_promise), false));
|
||||
}
|
||||
|
||||
// [coroutine.handle.noop.address], address
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr void* address() const noexcept { return __handle_; }
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr void* address() const noexcept { return __handle_; }
|
||||
|
||||
private:
|
||||
_LIBCPP_HIDE_FROM_ABI friend coroutine_handle<noop_coroutine_promise> noop_coroutine() noexcept;
|
||||
@ -86,7 +86,9 @@ inline noop_coroutine_handle::__noop_coroutine_frame_ty_ noop_coroutine_handle::
|
||||
# endif
|
||||
|
||||
// [coroutine.noop.coroutine]
|
||||
inline _LIBCPP_HIDE_FROM_ABI noop_coroutine_handle noop_coroutine() noexcept { return noop_coroutine_handle(); }
|
||||
[[nodiscard]] inline _LIBCPP_HIDE_FROM_ABI noop_coroutine_handle noop_coroutine() noexcept {
|
||||
return noop_coroutine_handle();
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
|
||||
@ -31,7 +31,7 @@ concept __comparison_can_promote_to =
|
||||
sizeof(_Tp) < sizeof(_Ip) || (sizeof(_Tp) == sizeof(_Ip) && __signed_integer<_Tp>);
|
||||
|
||||
template <__signed_or_unsigned_integer _Tp, __signed_or_unsigned_integer _Up>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr bool cmp_equal(_Tp __t, _Up __u) noexcept {
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool cmp_equal(_Tp __t, _Up __u) noexcept {
|
||||
if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>)
|
||||
return __t == __u;
|
||||
else if constexpr (__comparison_can_promote_to<_Tp, int> && __comparison_can_promote_to<_Up, int>)
|
||||
@ -45,12 +45,12 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool cmp_equal(_Tp __t, _Up __u) noexcept {
|
||||
}
|
||||
|
||||
template <__signed_or_unsigned_integer _Tp, __signed_or_unsigned_integer _Up>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr bool cmp_not_equal(_Tp __t, _Up __u) noexcept {
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool cmp_not_equal(_Tp __t, _Up __u) noexcept {
|
||||
return !std::cmp_equal(__t, __u);
|
||||
}
|
||||
|
||||
template <__signed_or_unsigned_integer _Tp, __signed_or_unsigned_integer _Up>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr bool cmp_less(_Tp __t, _Up __u) noexcept {
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool cmp_less(_Tp __t, _Up __u) noexcept {
|
||||
if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>)
|
||||
return __t < __u;
|
||||
else if constexpr (__comparison_can_promote_to<_Tp, int> && __comparison_can_promote_to<_Up, int>)
|
||||
@ -64,22 +64,22 @@ _LIBCPP_HIDE_FROM_ABI constexpr bool cmp_less(_Tp __t, _Up __u) noexcept {
|
||||
}
|
||||
|
||||
template <__signed_or_unsigned_integer _Tp, __signed_or_unsigned_integer _Up>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr bool cmp_greater(_Tp __t, _Up __u) noexcept {
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool cmp_greater(_Tp __t, _Up __u) noexcept {
|
||||
return std::cmp_less(__u, __t);
|
||||
}
|
||||
|
||||
template <__signed_or_unsigned_integer _Tp, __signed_or_unsigned_integer _Up>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr bool cmp_less_equal(_Tp __t, _Up __u) noexcept {
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool cmp_less_equal(_Tp __t, _Up __u) noexcept {
|
||||
return !std::cmp_greater(__t, __u);
|
||||
}
|
||||
|
||||
template <__signed_or_unsigned_integer _Tp, __signed_or_unsigned_integer _Up>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr bool cmp_greater_equal(_Tp __t, _Up __u) noexcept {
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool cmp_greater_equal(_Tp __t, _Up __u) noexcept {
|
||||
return !std::cmp_less(__t, __u);
|
||||
}
|
||||
|
||||
template <__signed_or_unsigned_integer _Tp, __signed_or_unsigned_integer _Up>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr bool in_range(_Up __u) noexcept {
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool in_range(_Up __u) noexcept {
|
||||
return std::cmp_less_equal(__u, numeric_limits<_Tp>::max()) &&
|
||||
std::cmp_greater_equal(__u, numeric_limits<_Tp>::min());
|
||||
}
|
||||
|
||||
@ -78,11 +78,17 @@ public:
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 initializer_list() _NOEXCEPT : __begin_(nullptr), __size_(0) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 size_t size() const _NOEXCEPT { return __size_; }
|
||||
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 size_t size() const _NOEXCEPT {
|
||||
return __size_;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Ep* begin() const _NOEXCEPT { return __begin_; }
|
||||
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Ep* begin() const _NOEXCEPT {
|
||||
return __begin_;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Ep* end() const _NOEXCEPT { return __begin_ + __size_; }
|
||||
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Ep* end() const _NOEXCEPT {
|
||||
return __begin_ + __size_;
|
||||
}
|
||||
};
|
||||
|
||||
template <class _Ep>
|
||||
|
||||
@ -10,8 +10,6 @@
|
||||
|
||||
// check that <utility> functions are marked [[nodiscard]]
|
||||
|
||||
// clang-format off
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "test_macros.h"
|
||||
@ -19,15 +17,33 @@
|
||||
void test() {
|
||||
int i = 0;
|
||||
|
||||
std::forward<int>(i); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::forward<int>(1); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::move(i); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::move_if_noexcept(i); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::forward<int>(i); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::forward<int>(1); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::move(i); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::move_if_noexcept(i);
|
||||
|
||||
#if TEST_STD_VER >= 17
|
||||
std::as_const(i); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
#endif
|
||||
|
||||
#if TEST_STD_VER >= 20
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::cmp_equal(94, 82);
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::cmp_not_equal(94, 82);
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::cmp_less(94, 82);
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::cmp_greater(94, 82);
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::cmp_less_equal(94, 82);
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::cmp_greater_equal(94, 82);
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::in_range<long>(49);
|
||||
#endif
|
||||
|
||||
#if TEST_STD_VER >= 23
|
||||
enum E { Apple, Orange } e = Apple;
|
||||
std::to_underlying(e); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
|
||||
91
libcxx/test/libcxx/language.support/nodiscard.verify.cpp
Normal file
91
libcxx/test/libcxx/language.support/nodiscard.verify.cpp
Normal file
@ -0,0 +1,91 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03
|
||||
|
||||
// Check that functions are marked [[nodiscard]]
|
||||
|
||||
#include <compare>
|
||||
#include <coroutine>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
void test() {
|
||||
#if TEST_STD_VER >= 20
|
||||
{ // <compare>
|
||||
int x = 94;
|
||||
int y = 82;
|
||||
auto oRes = x <=> y;
|
||||
|
||||
std::is_eq(oRes); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::is_neq(oRes); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::is_lt(oRes); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::is_lteq(oRes); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::is_gt(oRes); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::is_gteq(oRes); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TEST_STD_VER >= 20
|
||||
{ // <coroutine>
|
||||
struct EmptyPromise {
|
||||
} promise;
|
||||
|
||||
{
|
||||
std::coroutine_handle<void> cr{};
|
||||
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
cr.address();
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::coroutine_handle<void>::from_address(&promise);
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
cr.done();
|
||||
|
||||
std::hash<std::coroutine_handle<void>> hash;
|
||||
hash(cr); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
}
|
||||
{
|
||||
std::coroutine_handle<EmptyPromise> cr;
|
||||
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::coroutine_handle<EmptyPromise>::from_promise(promise);
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
cr.address();
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::coroutine_handle<EmptyPromise>::from_address(&promise);
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
cr.done();
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
cr.promise();
|
||||
}
|
||||
{
|
||||
std::coroutine_handle<std::noop_coroutine_promise> cr = std::noop_coroutine();
|
||||
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
cr.done();
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
cr.promise();
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
cr.address();
|
||||
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::noop_coroutine();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
{ // <initializer_list>
|
||||
std::initializer_list<int> il{94, 82, 49};
|
||||
|
||||
il.size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
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}}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user