[libc++][tuple] Applied [[nodiscard]] (#172008)
`[[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/tuple
This commit is contained in:
parent
23f967ada0
commit
18e9b48c4c
@ -1113,28 +1113,32 @@ swap(const tuple<_Tp...>& __lhs,
|
||||
// get
|
||||
|
||||
template <size_t _Ip, class... _Tp>
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 typename tuple_element<_Ip, tuple<_Tp...> >::type&
|
||||
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
|
||||
typename tuple_element<_Ip, tuple<_Tp...> >::type&
|
||||
get(tuple<_Tp...>& __t) _NOEXCEPT {
|
||||
using type _LIBCPP_NODEBUG = typename tuple_element<_Ip, tuple<_Tp...> >::type;
|
||||
return static_cast<__tuple_leaf<_Ip, type>&>(__t.__base_).get();
|
||||
}
|
||||
|
||||
template <size_t _Ip, class... _Tp>
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const typename tuple_element<_Ip, tuple<_Tp...> >::type&
|
||||
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX14 const typename tuple_element<_Ip, tuple<_Tp...> >::type&
|
||||
get(const tuple<_Tp...>& __t) _NOEXCEPT {
|
||||
using type _LIBCPP_NODEBUG = typename tuple_element<_Ip, tuple<_Tp...> >::type;
|
||||
return static_cast<const __tuple_leaf<_Ip, type>&>(__t.__base_).get();
|
||||
}
|
||||
|
||||
template <size_t _Ip, class... _Tp>
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 typename tuple_element<_Ip, tuple<_Tp...> >::type&&
|
||||
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
|
||||
typename tuple_element<_Ip, tuple<_Tp...> >::type&&
|
||||
get(tuple<_Tp...>&& __t) _NOEXCEPT {
|
||||
using type _LIBCPP_NODEBUG = typename tuple_element<_Ip, tuple<_Tp...> >::type;
|
||||
return static_cast<type&&>(static_cast<__tuple_leaf<_Ip, type>&&>(__t.__base_).get());
|
||||
}
|
||||
|
||||
template <size_t _Ip, class... _Tp>
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const typename tuple_element<_Ip, tuple<_Tp...> >::type&&
|
||||
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX14 const typename tuple_element<_Ip, tuple<_Tp...> >::type&&
|
||||
get(const tuple<_Tp...>&& __t) _NOEXCEPT {
|
||||
using type _LIBCPP_NODEBUG = typename tuple_element<_Ip, tuple<_Tp...> >::type;
|
||||
return static_cast<const type&&>(static_cast<const __tuple_leaf<_Ip, type>&&>(__t.__base_).get());
|
||||
@ -1143,22 +1147,22 @@ get(const tuple<_Tp...>&& __t) _NOEXCEPT {
|
||||
# if _LIBCPP_STD_VER >= 14
|
||||
|
||||
template <class _T1, class... _Args>
|
||||
inline _LIBCPP_HIDE_FROM_ABI constexpr _T1& get(tuple<_Args...>& __tup) noexcept {
|
||||
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI constexpr _T1& get(tuple<_Args...>& __tup) noexcept {
|
||||
return std::get<__find_exactly_one_t<_T1, _Args...>::value>(__tup);
|
||||
}
|
||||
|
||||
template <class _T1, class... _Args>
|
||||
inline _LIBCPP_HIDE_FROM_ABI constexpr _T1 const& get(tuple<_Args...> const& __tup) noexcept {
|
||||
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI constexpr _T1 const& get(tuple<_Args...> const& __tup) noexcept {
|
||||
return std::get<__find_exactly_one_t<_T1, _Args...>::value>(__tup);
|
||||
}
|
||||
|
||||
template <class _T1, class... _Args>
|
||||
inline _LIBCPP_HIDE_FROM_ABI constexpr _T1&& get(tuple<_Args...>&& __tup) noexcept {
|
||||
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI constexpr _T1&& get(tuple<_Args...>&& __tup) noexcept {
|
||||
return std::get<__find_exactly_one_t<_T1, _Args...>::value>(std::move(__tup));
|
||||
}
|
||||
|
||||
template <class _T1, class... _Args>
|
||||
inline _LIBCPP_HIDE_FROM_ABI constexpr _T1 const&& get(tuple<_Args...> const&& __tup) noexcept {
|
||||
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI constexpr _T1 const&& get(tuple<_Args...> const&& __tup) noexcept {
|
||||
return std::get<__find_exactly_one_t<_T1, _Args...>::value>(std::move(__tup));
|
||||
}
|
||||
|
||||
@ -1167,18 +1171,19 @@ inline _LIBCPP_HIDE_FROM_ABI constexpr _T1 const&& get(tuple<_Args...> const&& _
|
||||
// tie
|
||||
|
||||
template <class... _Tp>
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 tuple<_Tp&...> tie(_Tp&... __t) _NOEXCEPT {
|
||||
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 tuple<_Tp&...> tie(_Tp&... __t) _NOEXCEPT {
|
||||
return tuple<_Tp&...>(__t...);
|
||||
}
|
||||
|
||||
template <class... _Tp>
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 tuple<__unwrap_ref_decay_t<_Tp>...>
|
||||
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 tuple<__unwrap_ref_decay_t<_Tp>...>
|
||||
make_tuple(_Tp&&... __t) {
|
||||
return tuple<__unwrap_ref_decay_t<_Tp>...>(std::forward<_Tp>(__t)...);
|
||||
}
|
||||
|
||||
template <class... _Tp>
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 tuple<_Tp&&...> forward_as_tuple(_Tp&&... __t) _NOEXCEPT {
|
||||
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 tuple<_Tp&&...>
|
||||
forward_as_tuple(_Tp&&... __t) _NOEXCEPT {
|
||||
return tuple<_Tp&&...>(std::forward<_Tp>(__t)...);
|
||||
}
|
||||
|
||||
@ -1300,7 +1305,7 @@ template <class... _Tuples>
|
||||
using __tuple_cat_return_t _LIBCPP_NODEBUG =
|
||||
typename __tuple_cat_return_impl<tuple<>, __remove_cvref_t<_Tuples>...>::type;
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 tuple<> tuple_cat() { return tuple<>(); }
|
||||
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 tuple<> tuple_cat() { return tuple<>(); }
|
||||
|
||||
template <class _Rp, class _Indices, class _Tuple0, class... _Tuples>
|
||||
struct __tuple_cat_return_ref_imp;
|
||||
@ -1368,7 +1373,7 @@ __tuple_cat_select_element_wise(_TupleSrc&& __src, __index_sequence<_Indices...>
|
||||
}
|
||||
|
||||
template <class _Tuple0, class... _Tuples>
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __tuple_cat_return_t<_Tuple0, _Tuples...>
|
||||
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __tuple_cat_return_t<_Tuple0, _Tuples...>
|
||||
tuple_cat(_Tuple0&& __t0, _Tuples&&... __tpls) {
|
||||
using _T0 _LIBCPP_NODEBUG = __libcpp_remove_reference_t<_Tuple0>;
|
||||
using _TRet _LIBCPP_NODEBUG = __tuple_cat_return_t<_Tuple0, _Tuples...>;
|
||||
@ -1435,7 +1440,7 @@ template <class _Tp, class _Tuple>
|
||||
template <class _Tp, class _Tuple, class = enable_if_t<__can_make_from_tuple<_Tp, _Tuple>>> // strengthen
|
||||
#endif // _LIBCPP_STD_VER >= 20
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp make_from_tuple(_Tuple&& __t)
|
||||
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp make_from_tuple(_Tuple&& __t)
|
||||
noexcept(noexcept(std::__make_from_tuple_impl<_Tp>(std::forward<_Tuple>(__t),
|
||||
make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>()))) {
|
||||
#if _LIBCPP_STD_VER >= 23
|
||||
|
||||
66
libcxx/test/libcxx/utilities/tuple/nodiscard.verify.cpp
Normal file
66
libcxx/test/libcxx/utilities/tuple/nodiscard.verify.cpp
Normal file
@ -0,0 +1,66 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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++11
|
||||
|
||||
// Check that functions are marked [[nodiscard]]
|
||||
|
||||
#include <tuple>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
void test() {
|
||||
struct First {};
|
||||
struct Second {};
|
||||
struct Third {};
|
||||
|
||||
std::tuple<First, Second, Third> t;
|
||||
const std::tuple<First, Second, Third> ct;
|
||||
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::get<0>(t);
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::get<0>(ct);
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::get<0>(std::move(t));
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::get<0>(std::move(t));
|
||||
#if TEST_STD_VER >= 14
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::get<Third>(t);
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::get<Third>(ct);
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::get<Third>(std::move(t));
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::get<Third>(std::move(t));
|
||||
#endif
|
||||
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::tie(ct);
|
||||
|
||||
First e1;
|
||||
Second e2;
|
||||
Third e3;
|
||||
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::make_tuple(e1, e2, e3);
|
||||
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::forward_as_tuple(First{}, Second{}, Third{});
|
||||
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::tuple_cat();
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::tuple_cat(std::tuple<First>{}, std::tuple<Second, Third>{});
|
||||
|
||||
#if TEST_STD_VER >= 17
|
||||
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||
std::make_from_tuple<First>(std::tuple<First>{});
|
||||
#endif
|
||||
}
|
||||
@ -22,8 +22,10 @@ constexpr void CreateTuple(std::index_sequence<I...>) {
|
||||
using LargeTuple = std::tuple<std::integral_constant<std::size_t, I>...>;
|
||||
using TargetTuple = std::tuple<decltype(I)...>;
|
||||
LargeTuple tuple(std::integral_constant<std::size_t, I>{}...);
|
||||
assert(std::get<0>(tuple).value == 0);
|
||||
assert(std::get<sizeof...(I)-1>(tuple).value == sizeof...(I)-1);
|
||||
auto e1 = std::get<0>(tuple);
|
||||
assert(e1.value == 0);
|
||||
auto e2 = std::get<sizeof...(I) - 1>(tuple);
|
||||
assert(e2.value == sizeof...(I) - 1);
|
||||
|
||||
TargetTuple t1 = tuple; // converting copy constructor from &
|
||||
TargetTuple t2 = static_cast<LargeTuple const&>(tuple); // converting copy constructor from const&
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user