diff --git a/libcxx/include/tuple b/libcxx/include/tuple index be30ab5b2173d..2618e2d7334d0 100644 --- a/libcxx/include/tuple +++ b/libcxx/include/tuple @@ -1432,6 +1432,7 @@ inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp __make_from_tuple_impl(_Tuple&& __t, enable_if_t(std::forward<_Tuple>(__t)))...>> * = nullptr) _LIBCPP_NOEXCEPT_RETURN(_Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...)) #endif // _LIBCPP_STD_VER >= 20 +#undef _LIBCPP_NOEXCEPT_RETURN template >>, class = void> @@ -1451,10 +1452,19 @@ template #else template >> // strengthen #endif // _LIBCPP_STD_VER >= 20 + inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp make_from_tuple(_Tuple&& __t) - _LIBCPP_NOEXCEPT_RETURN(std::__make_from_tuple_impl<_Tp>( - std::forward<_Tuple>(__t), make_index_sequence>>())) -# undef _LIBCPP_NOEXCEPT_RETURN + noexcept(noexcept(std::__make_from_tuple_impl<_Tp>(std::forward<_Tuple>(__t), + make_index_sequence>>()))) { +#if _LIBCPP_STD_VER >= 23 && __has_builtin(__reference_constructs_from_temporary) + if constexpr (tuple_size_v> == 1) { + static_assert(!__reference_constructs_from_temporary_v<_Tp, decltype(std::get<0>(std::declval<_Tuple>()))>, + "Attempted construction of reference element binds to a temporary whose lifetime has ended"); + } +#endif // _LIBCPP_STD_VER >= 23 + return std::__make_from_tuple_impl<_Tp>( + std::forward<_Tuple>(__t), make_index_sequence>>()); +} # endif // _LIBCPP_STD_VER >= 17 diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp new file mode 100644 index 0000000000000..12d778408d5ec --- /dev/null +++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// 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++23 + +// + +// template constexpr T make_from_tuple(Tuple&&); +// Mandates: If tuple_size_v> is 1, then reference_constructs_from_temporary_v(declval()))> is false. + +#include +#include + +#include "test_macros.h" + +void test() { + // expected-error@*:* {{static assertion failed}} + + // Turns to an error since C++26 (Disallow Binding a Returned Glvalue to a Temporary https://wg21.link/P2748R5). +#if TEST_STD_VER >= 26 + // expected-error@tuple:* {{returning reference to local temporary object}} +#else + // expected-warning@tuple:* {{returning reference to local temporary object}} +#endif + std::ignore = std::make_from_tuple(std::tuple{}); +}