Skip to content

Commit afc0f86

Browse files
committed
[libc++][tuple] Applied [[nodiscard]]
`[[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
1 parent 80ec43d commit afc0f86

File tree

3 files changed

+87
-16
lines changed

3 files changed

+87
-16
lines changed

libcxx/include/tuple

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,28 +1113,32 @@ swap(const tuple<_Tp...>& __lhs,
11131113
// get
11141114

11151115
template <size_t _Ip, class... _Tp>
1116-
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 typename tuple_element<_Ip, tuple<_Tp...> >::type&
1116+
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
1117+
typename tuple_element<_Ip, tuple<_Tp...> >::type&
11171118
get(tuple<_Tp...>& __t) _NOEXCEPT {
11181119
using type _LIBCPP_NODEBUG = typename tuple_element<_Ip, tuple<_Tp...> >::type;
11191120
return static_cast<__tuple_leaf<_Ip, type>&>(__t.__base_).get();
11201121
}
11211122

11221123
template <size_t _Ip, class... _Tp>
1123-
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const typename tuple_element<_Ip, tuple<_Tp...> >::type&
1124+
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI
1125+
_LIBCPP_CONSTEXPR_SINCE_CXX14 const typename tuple_element<_Ip, tuple<_Tp...> >::type&
11241126
get(const tuple<_Tp...>& __t) _NOEXCEPT {
11251127
using type _LIBCPP_NODEBUG = typename tuple_element<_Ip, tuple<_Tp...> >::type;
11261128
return static_cast<const __tuple_leaf<_Ip, type>&>(__t.__base_).get();
11271129
}
11281130

11291131
template <size_t _Ip, class... _Tp>
1130-
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 typename tuple_element<_Ip, tuple<_Tp...> >::type&&
1132+
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
1133+
typename tuple_element<_Ip, tuple<_Tp...> >::type&&
11311134
get(tuple<_Tp...>&& __t) _NOEXCEPT {
11321135
using type _LIBCPP_NODEBUG = typename tuple_element<_Ip, tuple<_Tp...> >::type;
11331136
return static_cast<type&&>(static_cast<__tuple_leaf<_Ip, type>&&>(__t.__base_).get());
11341137
}
11351138

11361139
template <size_t _Ip, class... _Tp>
1137-
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const typename tuple_element<_Ip, tuple<_Tp...> >::type&&
1140+
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI
1141+
_LIBCPP_CONSTEXPR_SINCE_CXX14 const typename tuple_element<_Ip, tuple<_Tp...> >::type&&
11381142
get(const tuple<_Tp...>&& __t) _NOEXCEPT {
11391143
using type _LIBCPP_NODEBUG = typename tuple_element<_Ip, tuple<_Tp...> >::type;
11401144
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 {
11431147
# if _LIBCPP_STD_VER >= 14
11441148

11451149
template <class _T1, class... _Args>
1146-
inline _LIBCPP_HIDE_FROM_ABI constexpr _T1& get(tuple<_Args...>& __tup) noexcept {
1150+
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI constexpr _T1& get(tuple<_Args...>& __tup) noexcept {
11471151
return std::get<__find_exactly_one_t<_T1, _Args...>::value>(__tup);
11481152
}
11491153

11501154
template <class _T1, class... _Args>
1151-
inline _LIBCPP_HIDE_FROM_ABI constexpr _T1 const& get(tuple<_Args...> const& __tup) noexcept {
1155+
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI constexpr _T1 const& get(tuple<_Args...> const& __tup) noexcept {
11521156
return std::get<__find_exactly_one_t<_T1, _Args...>::value>(__tup);
11531157
}
11541158

11551159
template <class _T1, class... _Args>
1156-
inline _LIBCPP_HIDE_FROM_ABI constexpr _T1&& get(tuple<_Args...>&& __tup) noexcept {
1160+
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI constexpr _T1&& get(tuple<_Args...>&& __tup) noexcept {
11571161
return std::get<__find_exactly_one_t<_T1, _Args...>::value>(std::move(__tup));
11581162
}
11591163

11601164
template <class _T1, class... _Args>
1161-
inline _LIBCPP_HIDE_FROM_ABI constexpr _T1 const&& get(tuple<_Args...> const&& __tup) noexcept {
1165+
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI constexpr _T1 const&& get(tuple<_Args...> const&& __tup) noexcept {
11621166
return std::get<__find_exactly_one_t<_T1, _Args...>::value>(std::move(__tup));
11631167
}
11641168

@@ -1167,18 +1171,19 @@ inline _LIBCPP_HIDE_FROM_ABI constexpr _T1 const&& get(tuple<_Args...> const&& _
11671171
// tie
11681172

11691173
template <class... _Tp>
1170-
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 tuple<_Tp&...> tie(_Tp&... __t) _NOEXCEPT {
1174+
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 tuple<_Tp&...> tie(_Tp&... __t) _NOEXCEPT {
11711175
return tuple<_Tp&...>(__t...);
11721176
}
11731177

11741178
template <class... _Tp>
1175-
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 tuple<__unwrap_ref_decay_t<_Tp>...>
1179+
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 tuple<__unwrap_ref_decay_t<_Tp>...>
11761180
make_tuple(_Tp&&... __t) {
11771181
return tuple<__unwrap_ref_decay_t<_Tp>...>(std::forward<_Tp>(__t)...);
11781182
}
11791183

11801184
template <class... _Tp>
1181-
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 tuple<_Tp&&...> forward_as_tuple(_Tp&&... __t) _NOEXCEPT {
1185+
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 tuple<_Tp&&...>
1186+
forward_as_tuple(_Tp&&... __t) _NOEXCEPT {
11821187
return tuple<_Tp&&...>(std::forward<_Tp>(__t)...);
11831188
}
11841189

@@ -1300,7 +1305,7 @@ template <class... _Tuples>
13001305
using __tuple_cat_return_t _LIBCPP_NODEBUG =
13011306
typename __tuple_cat_return_impl<tuple<>, __remove_cvref_t<_Tuples>...>::type;
13021307

1303-
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 tuple<> tuple_cat() { return tuple<>(); }
1308+
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 tuple<> tuple_cat() { return tuple<>(); }
13041309

13051310
template <class _Rp, class _Indices, class _Tuple0, class... _Tuples>
13061311
struct __tuple_cat_return_ref_imp;
@@ -1368,7 +1373,7 @@ __tuple_cat_select_element_wise(_TupleSrc&& __src, __index_sequence<_Indices...>
13681373
}
13691374

13701375
template <class _Tuple0, class... _Tuples>
1371-
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __tuple_cat_return_t<_Tuple0, _Tuples...>
1376+
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __tuple_cat_return_t<_Tuple0, _Tuples...>
13721377
tuple_cat(_Tuple0&& __t0, _Tuples&&... __tpls) {
13731378
using _T0 _LIBCPP_NODEBUG = __libcpp_remove_reference_t<_Tuple0>;
13741379
using _TRet _LIBCPP_NODEBUG = __tuple_cat_return_t<_Tuple0, _Tuples...>;
@@ -1435,7 +1440,7 @@ template <class _Tp, class _Tuple>
14351440
template <class _Tp, class _Tuple, class = enable_if_t<__can_make_from_tuple<_Tp, _Tuple>>> // strengthen
14361441
#endif // _LIBCPP_STD_VER >= 20
14371442

1438-
inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp make_from_tuple(_Tuple&& __t)
1443+
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp make_from_tuple(_Tuple&& __t)
14391444
noexcept(noexcept(std::__make_from_tuple_impl<_Tp>(std::forward<_Tuple>(__t),
14401445
make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>()))) {
14411446
#if _LIBCPP_STD_VER >= 23
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// REQUIRES: std-at-least-c++11
10+
11+
// Check that functions are marked [[nodiscard]]
12+
13+
#include <tuple>
14+
15+
#include "test_macros.h"
16+
17+
void test() {
18+
struct First {};
19+
struct Second {};
20+
struct Third {};
21+
22+
std::tuple<First, Second, Third> t;
23+
const std::tuple<First, Second, Third> ct;
24+
25+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
26+
std::get<0>(t);
27+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
28+
std::get<0>(ct);
29+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
30+
std::get<0>(std::move(t));
31+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
32+
std::get<0>(std::move(t));
33+
#if TEST_STD_VER >= 14
34+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
35+
std::get<Third>(t);
36+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
37+
std::get<Third>(ct);
38+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
39+
std::get<Third>(std::move(t));
40+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
41+
std::get<Third>(std::move(t));
42+
#endif
43+
44+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
45+
std::tie(ct);
46+
47+
First e1;
48+
Second e2;
49+
Third e3;
50+
51+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
52+
std::make_tuple(e1, e2, e3);
53+
54+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
55+
std::forward_as_tuple(First{}, Second{}, Third{});
56+
57+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
58+
std::tuple_cat(std::tuple<First>{}, std::tuple<Second, Third>{});
59+
60+
#if TEST_STD_VER >= 17
61+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
62+
std::make_from_tuple<First>(std::tuple<First>{});
63+
#endif
64+
}

libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/recursion_depth.pass.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@ constexpr void CreateTuple(std::index_sequence<I...>) {
2222
using LargeTuple = std::tuple<std::integral_constant<std::size_t, I>...>;
2323
using TargetTuple = std::tuple<decltype(I)...>;
2424
LargeTuple tuple(std::integral_constant<std::size_t, I>{}...);
25-
assert(std::get<0>(tuple).value == 0);
26-
assert(std::get<sizeof...(I)-1>(tuple).value == sizeof...(I)-1);
25+
auto e1 = std::get<0>(tuple);
26+
assert(e1.value == 0);
27+
auto e2 = std::get<sizeof...(I) - 1>(tuple);
28+
assert(e2.value == sizeof...(I) - 1);
2729

2830
TargetTuple t1 = tuple; // converting copy constructor from &
2931
TargetTuple t2 = static_cast<LargeTuple const&>(tuple); // converting copy constructor from const&

0 commit comments

Comments
 (0)