https://github.com/yronglin updated https://github.com/llvm/llvm-project/pull/85263
>From fc8c1a24f09c8860269fbdcfb0b285ffd19f427c Mon Sep 17 00:00:00 2001 From: yronglin <yronglin...@gmail.com> Date: Fri, 15 Mar 2024 00:48:08 +0800 Subject: [PATCH 01/11] [libc++] Implement LWG3528 (`make_from_tuple` can perform (the equivalent of) a C-style cast) Signed-off-by: yronglin <yronglin...@gmail.com> --- libcxx/docs/Status/Cxx23Issues.csv | 2 +- libcxx/include/tuple | 12 ++- .../tuple.apply/make_from_tuple.verify.cpp | 74 +++++++++++++++++++ 3 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp diff --git a/libcxx/docs/Status/Cxx23Issues.csv b/libcxx/docs/Status/Cxx23Issues.csv index e00345533b865d..0fd58649b0cf64 100644 --- a/libcxx/docs/Status/Cxx23Issues.csv +++ b/libcxx/docs/Status/Cxx23Issues.csv @@ -77,7 +77,7 @@ `3523 <https://wg21.link/LWG3523>`__,"``iota_view::sentinel`` is not always ``iota_view``'s sentinel","June 2021","","","|ranges|" `3526 <https://wg21.link/LWG3526>`__,"Return types of ``uses_allocator_construction_args`` unspecified","June 2021","","" `3527 <https://wg21.link/LWG3527>`__,"``uses_allocator_construction_args`` handles rvalue pairs of rvalue references incorrectly","June 2021","","" -`3528 <https://wg21.link/LWG3528>`__,"``make_from_tuple`` can perform (the equivalent of) a C-style cast","June 2021","","" +`3528 <https://wg21.link/LWG3528>`__,"``make_from_tuple`` can perform (the equivalent of) a C-style cast","June 2021","|Complete|","19.0" `3529 <https://wg21.link/LWG3529>`__,"``priority_queue(first, last)`` should construct ``c`` with ``(first, last)``","June 2021","|Complete|","14.0" `3530 <https://wg21.link/LWG3530>`__,"``BUILTIN-PTR-MEOW`` should not opt the type out of syntactic checks","June 2021","","" `3532 <https://wg21.link/LWG3532>`__,"``split_view<V, P>::inner-iterator<true>::operator++(int)`` should depend on ``Base``","June 2021","","","|ranges|" diff --git a/libcxx/include/tuple b/libcxx/include/tuple index 8808db6739fb9b..1ef546c5b2153d 100644 --- a/libcxx/include/tuple +++ b/libcxx/include/tuple @@ -1423,8 +1423,16 @@ inline _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) apply(_Fn&& __f, _Tuple&& typename __make_tuple_indices<tuple_size_v<remove_reference_t<_Tuple>>>::type{})) template <class _Tp, class _Tuple, size_t... _Idx> -inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp __make_from_tuple_impl(_Tuple&& __t, __tuple_indices<_Idx...>) - _LIBCPP_NOEXCEPT_RETURN(_Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...)) +inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp __make_from_tuple_impl(_Tuple&& __t, __tuple_indices<_Idx...>) + noexcept(noexcept(_Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...))) +#if _LIBCPP_STD_VER >= 20 + requires is_constructible_v<_Tp, decltype(std::get<_Idx>(std::forward<_Tuple>(__t)))...> +#endif +{ + static_assert(is_constructible_v<_Tp, decltype(std::get<_Idx>(std::forward<_Tuple>(__t)))...>, + "Cannot constructible target type from the fields of the argument tuple."); + return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...); +} template <class _Tp, class _Tuple> inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp make_from_tuple(_Tuple&& __t) 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 00000000000000..9bdca4dc7813cb --- /dev/null +++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// 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, c++11, c++14 + +// <tuple> + +// template <class T, class Tuple> constexpr T make_from_tuple(Tuple&&); + +#include <tuple> + +int main() { + // clang-format off +#if _LIBCPP_STD_VER <= 20 + // reinterpret_cast + { + struct B { int b; } b; + std::tuple<B *> t{&b}; + auto a = std::make_from_tuple<int *>(t); // expected-error-re@*:* {{static assertion failed {{.*}}Cannot constructible target type from the fields of the argument tuple.}} + (void)a; + } + + // const_cast + { + const char *str = "Hello"; + std::tuple<const char *> t{str}; + auto a = std::make_from_tuple<char *>(t); // expected-error-re@*:* {{static assertion failed {{.*}}Cannot constructible target type from the fields of the argument tuple.}} + (void)a; + } + + // static_cast + { + struct B {}; + struct C : public B {} c; + B &br = c; + std::tuple<const B&> t{br}; + auto a = std::make_from_tuple<const C&>(t); // expected-error-re@*:* {{static assertion failed {{.*}}Cannot constructible target type from the fields of the argument tuple.}} + (void)a; + } +#else + // reinterpret_cast + { + struct B { int b; } b; + std::tuple<B *> t{&b}; + auto a = std::make_from_tuple<int *>(t); // expected-error-re@*:*2 {{no matching function for call to{{.*}}}} + (void)a; + } + + // const_cast + { + const char *str = "Hello"; + std::tuple<const char *> t{str}; + auto a = std::make_from_tuple<char *>(t); // expected-error-re@*:*2 {{no matching function for call to{{.*}}}} + (void)a; + } + + // static_cast + { + struct B {}; + struct C : public B {} c; + B &br = c; + std::tuple<const B &> t{br}; + auto a = std::make_from_tuple<const C&>(t); // expected-error-re@*:*2 {{no matching function for call to{{.*}}}} + (void)a; + } +#endif + // clang-format on + return 0; +} >From 14d6e7168e52c3236685dc3d947a37d9926bf8a2 Mon Sep 17 00:00:00 2001 From: yronglin <yronglin...@gmail.com> Date: Fri, 15 Mar 2024 00:54:47 +0800 Subject: [PATCH 02/11] Add comment after #endif Signed-off-by: yronglin <yronglin...@gmail.com> --- libcxx/include/tuple | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/include/tuple b/libcxx/include/tuple index 1ef546c5b2153d..0839fa7d1280a0 100644 --- a/libcxx/include/tuple +++ b/libcxx/include/tuple @@ -1427,7 +1427,7 @@ inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp __make_from_tuple_impl(_Tuple&& __t, noexcept(noexcept(_Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...))) #if _LIBCPP_STD_VER >= 20 requires is_constructible_v<_Tp, decltype(std::get<_Idx>(std::forward<_Tuple>(__t)))...> -#endif +#endif // _LIBCPP_STD_VER >= 20 { static_assert(is_constructible_v<_Tp, decltype(std::get<_Idx>(std::forward<_Tuple>(__t)))...>, "Cannot constructible target type from the fields of the argument tuple."); >From 14ae30770795c9d06ca83b23bf903922965b6ea0 Mon Sep 17 00:00:00 2001 From: yronglin <yronglin...@gmail.com> Date: Fri, 15 Mar 2024 20:59:40 +0800 Subject: [PATCH 03/11] Address comments and uses SFINAE to remove the function from the overload set Signed-off-by: yronglin <yronglin...@gmail.com> --- libcxx/include/tuple | 16 ++++++----- .../tuple.apply/make_from_tuple.verify.cpp | 28 ------------------- 2 files changed, 9 insertions(+), 35 deletions(-) diff --git a/libcxx/include/tuple b/libcxx/include/tuple index 0839fa7d1280a0..4d0e89d74ba14b 100644 --- a/libcxx/include/tuple +++ b/libcxx/include/tuple @@ -1422,17 +1422,19 @@ inline _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) apply(_Fn&& __f, _Tuple&& std::forward<_Tuple>(__t), typename __make_tuple_indices<tuple_size_v<remove_reference_t<_Tuple>>>::type{})) +#if _LIBCPP_STD_VER >= 20 template <class _Tp, class _Tuple, size_t... _Idx> -inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp __make_from_tuple_impl(_Tuple&& __t, __tuple_indices<_Idx...>) +inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp __make_from_tuple_impl(_Tuple&& __t, __tuple_indices<_Idx...>) noexcept(noexcept(_Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...))) -#if _LIBCPP_STD_VER >= 20 - requires is_constructible_v<_Tp, decltype(std::get<_Idx>(std::forward<_Tuple>(__t)))...> -#endif // _LIBCPP_STD_VER >= 20 -{ - static_assert(is_constructible_v<_Tp, decltype(std::get<_Idx>(std::forward<_Tuple>(__t)))...>, - "Cannot constructible target type from the fields of the argument tuple."); + requires is_constructible_v<_Tp, decltype(std::get<_Idx>(std::forward<_Tuple>(__t)))...> { return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...); } +#else +template <class _Tp, class _Tuple, size_t... _Idx> +inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp __make_from_tuple_impl(_Tuple&& __t, __tuple_indices<_Idx...>, + enable_if_t<is_constructible_v<_Tp, decltype(std::get<_Idx>(std::forward<_Tuple>(__t)))...>> * = nullptr) + _LIBCPP_NOEXCEPT_RETURN(_Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...)) +#endif // _LIBCPP_STD_VER >= 20 template <class _Tp, class _Tuple> inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp make_from_tuple(_Tuple&& __t) 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 index 9bdca4dc7813cb..d5905404d43a35 100644 --- 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 @@ -16,33 +16,6 @@ int main() { // clang-format off -#if _LIBCPP_STD_VER <= 20 - // reinterpret_cast - { - struct B { int b; } b; - std::tuple<B *> t{&b}; - auto a = std::make_from_tuple<int *>(t); // expected-error-re@*:* {{static assertion failed {{.*}}Cannot constructible target type from the fields of the argument tuple.}} - (void)a; - } - - // const_cast - { - const char *str = "Hello"; - std::tuple<const char *> t{str}; - auto a = std::make_from_tuple<char *>(t); // expected-error-re@*:* {{static assertion failed {{.*}}Cannot constructible target type from the fields of the argument tuple.}} - (void)a; - } - - // static_cast - { - struct B {}; - struct C : public B {} c; - B &br = c; - std::tuple<const B&> t{br}; - auto a = std::make_from_tuple<const C&>(t); // expected-error-re@*:* {{static assertion failed {{.*}}Cannot constructible target type from the fields of the argument tuple.}} - (void)a; - } -#else // reinterpret_cast { struct B { int b; } b; @@ -68,7 +41,6 @@ int main() { auto a = std::make_from_tuple<const C&>(t); // expected-error-re@*:*2 {{no matching function for call to{{.*}}}} (void)a; } -#endif // clang-format on return 0; } >From 6f4ad45219b8b437489da8222cfc353f67aa584b Mon Sep 17 00:00:00 2001 From: yronglin <yronglin...@gmail.com> Date: Tue, 19 Mar 2024 21:46:50 +0800 Subject: [PATCH 04/11] Add SFINAE based test Signed-off-by: yronglin <yronglin...@gmail.com> --- .../tuple.apply/make_from_tuple.pass.cpp | 28 +++++++++++ .../tuple.apply/make_from_tuple.verify.cpp | 46 ------------------- 2 files changed, 28 insertions(+), 46 deletions(-) delete mode 100644 libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp index e3a21149c21e4c..1ff148f0cfb00d 100644 --- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp +++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp @@ -195,6 +195,34 @@ void test_noexcept() { } } +namespace LWG3528 { +template <class _Tp, class _Tuple, class = std::void_t<>> +struct can_make_from_tuple : std::false_type {}; +template <class _Tp, class _Tuple> +struct can_make_from_tuple< + _Tp, + _Tuple, + std::void_t<decltype(std::__make_from_tuple_impl<_Tp>( + std::declval<_Tuple>(), + std::declval< + typename std::__make_tuple_indices< std::tuple_size_v<std::remove_reference_t<_Tuple>>>::type>()))>> + : std::true_type {}; + +struct A { + int a; +}; +struct B : public A {}; + +// reinterpret_cast +static_assert(!can_make_from_tuple<int*, std::tuple<A*>>::value); + +// const_cast +static_assert(!can_make_from_tuple<char*, std::tuple<const char*>>::value); + +// static_cast +static_assert(!can_make_from_tuple<const B&, std::tuple<const A&>>::value); +} // namespace LWG3528 + int main(int, char**) { test_constexpr_construction(); 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 deleted file mode 100644 index d5905404d43a35..00000000000000 --- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.verify.cpp +++ /dev/null @@ -1,46 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// 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, c++11, c++14 - -// <tuple> - -// template <class T, class Tuple> constexpr T make_from_tuple(Tuple&&); - -#include <tuple> - -int main() { - // clang-format off - // reinterpret_cast - { - struct B { int b; } b; - std::tuple<B *> t{&b}; - auto a = std::make_from_tuple<int *>(t); // expected-error-re@*:*2 {{no matching function for call to{{.*}}}} - (void)a; - } - - // const_cast - { - const char *str = "Hello"; - std::tuple<const char *> t{str}; - auto a = std::make_from_tuple<char *>(t); // expected-error-re@*:*2 {{no matching function for call to{{.*}}}} - (void)a; - } - - // static_cast - { - struct B {}; - struct C : public B {} c; - B &br = c; - std::tuple<const B &> t{br}; - auto a = std::make_from_tuple<const C&>(t); // expected-error-re@*:*2 {{no matching function for call to{{.*}}}} - (void)a; - } - // clang-format on - return 0; -} >From b5b0cc080a9587e1fdd2c44a887d6df57a74f0e9 Mon Sep 17 00:00:00 2001 From: yronglin <yronglin...@gmail.com> Date: Tue, 19 Mar 2024 21:52:37 +0800 Subject: [PATCH 05/11] Format Signed-off-by: yronglin <yronglin...@gmail.com> --- .../tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp index 1ff148f0cfb00d..fef3e389390fee 100644 --- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp +++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp @@ -209,7 +209,7 @@ struct can_make_from_tuple< : std::true_type {}; struct A { - int a; + int a; }; struct B : public A {}; >From d46837885ebf1beb9fc2ce9f58f9d6adef37cf89 Mon Sep 17 00:00:00 2001 From: yronglin <yronglin...@gmail.com> Date: Tue, 19 Mar 2024 22:25:41 +0800 Subject: [PATCH 06/11] Fix test failure Signed-off-by: yronglin <yronglin...@gmail.com> --- clang/lib/Frontend/TextDiagnosticPrinter.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/lib/Frontend/TextDiagnosticPrinter.cpp b/clang/lib/Frontend/TextDiagnosticPrinter.cpp index b2fb762537573e..83e6d1446d7d22 100644 --- a/clang/lib/Frontend/TextDiagnosticPrinter.cpp +++ b/clang/lib/Frontend/TextDiagnosticPrinter.cpp @@ -108,6 +108,7 @@ static void printDiagnosticOptions(raw_ostream &OS, void TextDiagnosticPrinter::HandleDiagnostic(DiagnosticsEngine::Level Level, const Diagnostic &Info) { + abort(); // Default implementation (Warnings/errors count). DiagnosticConsumer::HandleDiagnostic(Level, Info); >From 34666461f7cb880fa8b1510df97506099831c38b Mon Sep 17 00:00:00 2001 From: yronglin <yronglin...@gmail.com> Date: Tue, 19 Mar 2024 22:29:23 +0800 Subject: [PATCH 07/11] Revert "Fix test failure" This reverts commit d46837885ebf1beb9fc2ce9f58f9d6adef37cf89. --- clang/lib/Frontend/TextDiagnosticPrinter.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/clang/lib/Frontend/TextDiagnosticPrinter.cpp b/clang/lib/Frontend/TextDiagnosticPrinter.cpp index 83e6d1446d7d22..b2fb762537573e 100644 --- a/clang/lib/Frontend/TextDiagnosticPrinter.cpp +++ b/clang/lib/Frontend/TextDiagnosticPrinter.cpp @@ -108,7 +108,6 @@ static void printDiagnosticOptions(raw_ostream &OS, void TextDiagnosticPrinter::HandleDiagnostic(DiagnosticsEngine::Level Level, const Diagnostic &Info) { - abort(); // Default implementation (Warnings/errors count). DiagnosticConsumer::HandleDiagnostic(Level, Info); >From 290260dfa0a1f666135d249f4f504d7601f0050c Mon Sep 17 00:00:00 2001 From: yronglin <yronglin...@gmail.com> Date: Tue, 19 Mar 2024 22:29:42 +0800 Subject: [PATCH 08/11] Fix test failure Signed-off-by: yronglin <yronglin...@gmail.com> --- .../tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp index fef3e389390fee..347934a478de69 100644 --- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp +++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp @@ -220,7 +220,7 @@ static_assert(!can_make_from_tuple<int*, std::tuple<A*>>::value); static_assert(!can_make_from_tuple<char*, std::tuple<const char*>>::value); // static_cast -static_assert(!can_make_from_tuple<const B&, std::tuple<const A&>>::value); +static_assert(!can_make_from_tuple<const B*, std::tuple<const A*>>::value); } // namespace LWG3528 int main(int, char**) >From 4ff01715d26aa1ecb831c24044faa28d59ab01bd Mon Sep 17 00:00:00 2001 From: yronglin <yronglin...@gmail.com> Date: Wed, 20 Mar 2024 21:25:10 +0800 Subject: [PATCH 09/11] Make a SFINAE based test Signed-off-by: yronglin <yronglin...@gmail.com> --- .../tuple.apply/make_from_tuple.pass.cpp | 51 ++++++++++++++----- 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp index 347934a478de69..68f12623423bbf 100644 --- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp +++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp @@ -196,31 +196,54 @@ void test_noexcept() { } namespace LWG3528 { -template <class _Tp, class _Tuple, class = std::void_t<>> -struct can_make_from_tuple : std::false_type {}; -template <class _Tp, class _Tuple> -struct can_make_from_tuple< - _Tp, - _Tuple, - std::void_t<decltype(std::__make_from_tuple_impl<_Tp>( - std::declval<_Tuple>(), - std::declval< - typename std::__make_tuple_indices< std::tuple_size_v<std::remove_reference_t<_Tuple>>>::type>()))>> - : std::true_type {}; +template <class T, class Tuple> +auto test(T&&, Tuple&& t) + -> decltype(std::__make_from_tuple_impl<T>( + t, typename std::__make_tuple_indices< std::tuple_size_v<std::remove_reference_t<Tuple>>>::type{}), + uint8_t()) { + return 0; +} +template <class T, class Tuple> +uint32_t test(...) { + return 0; +} + +template <class T, class Tuple> +static constexpr bool can_make_from_tuple = std::is_same_v<decltype(test<T, Tuple>(T{}, Tuple{})), uint8_t>; struct A { int a; }; struct B : public A {}; +struct C { + C(const B&) {} +}; + +enum class D { + ONE, + TWO, +}; + // reinterpret_cast -static_assert(!can_make_from_tuple<int*, std::tuple<A*>>::value); +static_assert(!can_make_from_tuple<int*, std::tuple<A*>>); +static_assert(can_make_from_tuple<A*, std::tuple<A*>>); // const_cast -static_assert(!can_make_from_tuple<char*, std::tuple<const char*>>::value); +static_assert(!can_make_from_tuple<char*, std::tuple<const char*>>); +static_assert(!can_make_from_tuple<volatile char*, std::tuple<const volatile char*>>); +static_assert(can_make_from_tuple<volatile char*, std::tuple<volatile char*>>); +static_assert(can_make_from_tuple<char*, std::tuple<char*>>); +static_assert(can_make_from_tuple<const char*, std::tuple<char*>>); +static_assert(can_make_from_tuple<const volatile char*, std::tuple<volatile char*>>); // static_cast -static_assert(!can_make_from_tuple<const B*, std::tuple<const A*>>::value); +static_assert(!can_make_from_tuple<int, std::tuple<D>>); +static_assert(!can_make_from_tuple<D, std::tuple<int>>); +static_assert(can_make_from_tuple<long, std::tuple<int>>); +static_assert(can_make_from_tuple<double, std::tuple<float>>); +static_assert(can_make_from_tuple<float, std::tuple<double>>); + } // namespace LWG3528 int main(int, char**) >From 923070351574ac62f126e48166a1a1c7a6f39b6a Mon Sep 17 00:00:00 2001 From: yronglin <yronglin...@gmail.com> Date: Thu, 21 Mar 2024 23:21:12 +0800 Subject: [PATCH 10/11] Add constraint to std::make_from_tuple Signed-off-by: yronglin <yronglin...@gmail.com> --- libcxx/include/tuple | 27 +++++++++++-------- .../tuple.apply/make_from_tuple.pass.cpp | 5 +--- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/libcxx/include/tuple b/libcxx/include/tuple index 415521a523e238..c3da08ed6ca5a0 100644 --- a/libcxx/include/tuple +++ b/libcxx/include/tuple @@ -1377,25 +1377,30 @@ inline _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) apply(_Fn&& __f, _Tuple&& std::forward<_Tuple>(__t), typename __make_tuple_indices<tuple_size_v<remove_reference_t<_Tuple>>>::type{})) -#if _LIBCPP_STD_VER >= 20 template <class _Tp, class _Tuple, size_t... _Idx> inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp __make_from_tuple_impl(_Tuple&& __t, __tuple_indices<_Idx...>) - noexcept(noexcept(_Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...))) - requires is_constructible_v<_Tp, decltype(std::get<_Idx>(std::forward<_Tuple>(__t)))...> { - return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...); -} -#else -template <class _Tp, class _Tuple, size_t... _Idx> -inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp __make_from_tuple_impl(_Tuple&& __t, __tuple_indices<_Idx...>, - enable_if_t<is_constructible_v<_Tp, decltype(std::get<_Idx>(std::forward<_Tuple>(__t)))...>> * = nullptr) _LIBCPP_NOEXCEPT_RETURN(_Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...)) -#endif // _LIBCPP_STD_VER >= 20 +template <class _Tp, class _Tuple, + class _Seq = typename __make_tuple_indices<tuple_size_v<remove_reference_t<_Tuple>>>::type, class = void> +inline constexpr bool __can_make_from_tuple = false; + +template <class _Tp, class _Tuple, size_t... _Idx> +inline constexpr bool __can_make_from_tuple<_Tp, _Tuple, __tuple_indices<_Idx...>, + enable_if_t<is_constructible_v<_Tp, decltype(std::get<_Idx>(std::declval<_Tuple>()))...>>> = true; + +// Based on LWG3528(https://wg21.link/LWG3528) and http://eel.is/c++draft/description#structure.requirements-9, +// the standard allows to impose requirements, we constraint std::make_from_tuple but not touch std::__make_from_tuple_impl +// to make std::make_from_tuple SFINAE friendly and also avoid worse diagnostic messages. +#if _LIBCPP_STD_VER >= 20 template <class _Tp, class _Tuple> + requires __can_make_from_tuple<_Tp, _Tuple> // strengthen +#else +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) _LIBCPP_NOEXCEPT_RETURN(std::__make_from_tuple_impl<_Tp>( std::forward<_Tuple>(__t), typename __make_tuple_indices<tuple_size_v<remove_reference_t<_Tuple>>>::type{})) - # undef _LIBCPP_NOEXCEPT_RETURN # endif // _LIBCPP_STD_VER >= 17 diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp index 68f12623423bbf..9c4a29a2c0de28 100644 --- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp +++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp @@ -197,10 +197,7 @@ void test_noexcept() { namespace LWG3528 { template <class T, class Tuple> -auto test(T&&, Tuple&& t) - -> decltype(std::__make_from_tuple_impl<T>( - t, typename std::__make_tuple_indices< std::tuple_size_v<std::remove_reference_t<Tuple>>>::type{}), - uint8_t()) { +auto test(T&&, Tuple&& t) -> decltype(std::make_from_tuple<T>(t), uint8_t()) { return 0; } template <class T, class Tuple> >From e19dda8e27fda737f881356ad6b855fd21c4013e Mon Sep 17 00:00:00 2001 From: yronglin <yronglin...@gmail.com> Date: Fri, 22 Mar 2024 07:38:56 +0800 Subject: [PATCH 11/11] Keep constraints of std::__make_from_tuple_impl Signed-off-by: yronglin <yronglin...@gmail.com> --- libcxx/include/tuple | 14 +++++- .../tuple.apply/make_from_tuple.pass.cpp | 46 +++++++++++++++++-- 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/libcxx/include/tuple b/libcxx/include/tuple index c3da08ed6ca5a0..b8d3836ac2fefd 100644 --- a/libcxx/include/tuple +++ b/libcxx/include/tuple @@ -1377,9 +1377,19 @@ inline _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) apply(_Fn&& __f, _Tuple&& std::forward<_Tuple>(__t), typename __make_tuple_indices<tuple_size_v<remove_reference_t<_Tuple>>>::type{})) +#if _LIBCPP_STD_VER >= 20 template <class _Tp, class _Tuple, size_t... _Idx> inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp __make_from_tuple_impl(_Tuple&& __t, __tuple_indices<_Idx...>) + noexcept(noexcept(_Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...))) + requires is_constructible_v<_Tp, decltype(std::get<_Idx>(std::forward<_Tuple>(__t)))...> { + return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...); +} +#else +template <class _Tp, class _Tuple, size_t... _Idx> +inline _LIBCPP_HIDE_FROM_ABI constexpr _Tp __make_from_tuple_impl(_Tuple&& __t, __tuple_indices<_Idx...>, + enable_if_t<is_constructible_v<_Tp, decltype(std::get<_Idx>(std::forward<_Tuple>(__t)))...>> * = nullptr) _LIBCPP_NOEXCEPT_RETURN(_Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...)) +#endif // _LIBCPP_STD_VER >= 20 template <class _Tp, class _Tuple, class _Seq = typename __make_tuple_indices<tuple_size_v<remove_reference_t<_Tuple>>>::type, class = void> @@ -1390,8 +1400,8 @@ inline constexpr bool __can_make_from_tuple<_Tp, _Tuple, __tuple_indices<_Idx... enable_if_t<is_constructible_v<_Tp, decltype(std::get<_Idx>(std::declval<_Tuple>()))...>>> = true; // Based on LWG3528(https://wg21.link/LWG3528) and http://eel.is/c++draft/description#structure.requirements-9, -// the standard allows to impose requirements, we constraint std::make_from_tuple but not touch std::__make_from_tuple_impl -// to make std::make_from_tuple SFINAE friendly and also avoid worse diagnostic messages. +// the standard allows to impose requirements, we constraint std::make_from_tuple to make std::make_from_tuple +// SFINAE friendly and also avoid worse diagnostic messages. #if _LIBCPP_STD_VER >= 20 template <class _Tp, class _Tuple> requires __can_make_from_tuple<_Tp, _Tuple> // strengthen diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp index 9c4a29a2c0de28..d7374351afa8bf 100644 --- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp +++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp @@ -197,16 +197,33 @@ void test_noexcept() { namespace LWG3528 { template <class T, class Tuple> -auto test(T&&, Tuple&& t) -> decltype(std::make_from_tuple<T>(t), uint8_t()) { +auto test_make_from_tuple(T&&, Tuple&& t) -> decltype(std::make_from_tuple<T>(t), uint8_t()) { return 0; } template <class T, class Tuple> -uint32_t test(...) { +uint32_t test_make_from_tuple(...) { return 0; } template <class T, class Tuple> -static constexpr bool can_make_from_tuple = std::is_same_v<decltype(test<T, Tuple>(T{}, Tuple{})), uint8_t>; +static constexpr bool can_make_from_tuple = + std::is_same_v<decltype(test_make_from_tuple<T, Tuple>(T{}, Tuple{})), uint8_t>; + +template <class T, class Tuple> +auto test_make_from_tuple_impl(T&&, Tuple&& t) + -> decltype(std::__make_from_tuple_impl<T>( + t, typename std::__make_tuple_indices< std::tuple_size_v<std::remove_reference_t<Tuple>>>::type{}), + uint8_t()) { + return 0; +} +template <class T, class Tuple> +uint32_t test_make_from_tuple_impl(...) { + return 0; +} + +template <class T, class Tuple> +static constexpr bool can_make_from_tuple_impl = + std::is_same_v<decltype(test_make_from_tuple_impl<T, Tuple>(T{}, Tuple{})), uint8_t>; struct A { int a; @@ -222,6 +239,8 @@ enum class D { TWO, }; +// Test std::make_from_tuple constraints. + // reinterpret_cast static_assert(!can_make_from_tuple<int*, std::tuple<A*>>); static_assert(can_make_from_tuple<A*, std::tuple<A*>>); @@ -241,6 +260,27 @@ static_assert(can_make_from_tuple<long, std::tuple<int>>); static_assert(can_make_from_tuple<double, std::tuple<float>>); static_assert(can_make_from_tuple<float, std::tuple<double>>); +// Test std::__make_from_tuple_impl constraints. + +// reinterpret_cast +static_assert(!can_make_from_tuple_impl<int*, std::tuple<A*>>); +static_assert(can_make_from_tuple_impl<A*, std::tuple<A*>>); + +// const_cast +static_assert(!can_make_from_tuple_impl<char*, std::tuple<const char*>>); +static_assert(!can_make_from_tuple_impl<volatile char*, std::tuple<const volatile char*>>); +static_assert(can_make_from_tuple_impl<volatile char*, std::tuple<volatile char*>>); +static_assert(can_make_from_tuple_impl<char*, std::tuple<char*>>); +static_assert(can_make_from_tuple_impl<const char*, std::tuple<char*>>); +static_assert(can_make_from_tuple_impl<const volatile char*, std::tuple<volatile char*>>); + +// static_cast +static_assert(!can_make_from_tuple_impl<int, std::tuple<D>>); +static_assert(!can_make_from_tuple_impl<D, std::tuple<int>>); +static_assert(can_make_from_tuple_impl<long, std::tuple<int>>); +static_assert(can_make_from_tuple_impl<double, std::tuple<float>>); +static_assert(can_make_from_tuple_impl<float, std::tuple<double>>); + } // namespace LWG3528 int main(int, char**) _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits