Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 19 additions & 14 deletions libcxx/include/tuple
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand All @@ -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));
}

Expand All @@ -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)...);
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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...>;
Expand Down Expand Up @@ -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
Expand Down
66 changes: 66 additions & 0 deletions libcxx/test/libcxx/utilities/tuple/nodiscard.verify.cpp
Original file line number Diff line number Diff line change
@@ -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
}
Original file line number Diff line number Diff line change
Expand Up @@ -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&
Expand Down
Loading