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 1/6] [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 2/6] 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 3/6] 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 4/6] 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 5/6] 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 6/6] 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); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits