From faba92d7a188f9d88f458124192ad7a7ff968dfa Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Tue, 20 May 2025 02:01:07 +0800 Subject: [PATCH 01/16] Fix conditions for vectorization on trivial assignability --- stl/inc/algorithm | 10 +- stl/inc/xutility | 14 +- tests/std/test.lst | 1 + .../env.lst | 4 + .../test.cpp | 264 ++++++++++++++++++ 5 files changed, 288 insertions(+), 5 deletions(-) create mode 100644 tests/std/tests/GH_004686_vectorization_on_trivial_assignability/env.lst create mode 100644 tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 984878026db..873af91a435 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -5616,6 +5616,10 @@ namespace ranges { } // namespace ranges #endif // _HAS_CXX20 +template +struct _Is_trivially_copy_assignable_returning_same_reference + : bool_constant<_Is_trivially_assignable_returning_same_reference_v<_Ty&, const _Ty&>> {}; + _EXPORT_STD template _CONSTEXPR20 _OutIt reverse_copy(_BidIt _First, _BidIt _Last, _OutIt _Dest) { // copy reversing elements in [_First, _Last) @@ -5629,8 +5633,8 @@ _CONSTEXPR20 _OutIt reverse_copy(_BidIt _First, _BidIt _Last, _OutIt _Dest) { using _Elem = remove_reference_t<_Iter_ref_t>>; using _DestElem = remove_reference_t<_Iter_ref_t>; constexpr bool _Allow_vectorization = conjunction_v, _DestElem>, - bool_constant<_Iterators_are_contiguous>, is_trivially_copyable<_Elem>, - negation>>; + bool_constant<_Iterators_are_contiguous>, + _Is_trivially_copy_assignable_returning_same_reference<_Elem>, negation>>; constexpr size_t _Nx = sizeof(_Elem); if constexpr (_Allow_vectorization && _Nx <= 8 && (_Nx & (_Nx - 1)) == 0) { @@ -5719,7 +5723,7 @@ namespace ranges { using _Elem = remove_reference_t>; using _DestElem = remove_reference_t>; constexpr bool _Allow_vectorization = conjunction_v, _DestElem>, - is_trivially_copyable<_Elem>, negation>>; + _Is_trivially_copy_assignable_returning_same_reference<_Elem>, negation>>; constexpr size_t _Nx = sizeof(_Elem); if constexpr (_Allow_vectorization && _Nx <= 8 && (_Nx & (_Nx - 1)) == 0) { diff --git a/stl/inc/xutility b/stl/inc/xutility index 854ae81b26c..ebe48eac967 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -4683,6 +4683,15 @@ constexpr bool _Is_pointer_address_convertible = is_void_v<_Source> #endif // defined(__cpp_lib_is_pointer_interconvertible) ; +// Determines whether _DestRef is trivially assignable from _SourceRef, and if _Remove_cvref_t<_DestRef> is a class, the +// assignment uses _Remove_cvref_t<_DestRef>::operator=. +// Not pedantically reliable for vectorization, but working due to bugs of MSVC, Clang, and EDG. See LLVM-37038. +template > +constexpr bool _Is_trivially_assignable_returning_same_reference_v = + is_same_v<_DestRef, decltype(_STD declval<_DestRef>() = _STD declval<_SourceRef>())>; +template +constexpr bool _Is_trivially_assignable_returning_same_reference_v<_DestRef, _SourceRef, false> = false; + template struct _Trivial_cat { using _USource = _Unwrap_enum_t<_Source>; @@ -4701,7 +4710,7 @@ struct _Trivial_cat { _Same_size_and_compatible && is_trivially_constructible_v<_Dest, _SourceRef>; static constexpr bool _Bitcopy_assignable = - _Same_size_and_compatible && is_trivially_assignable_v<_DestRef, _SourceRef>; + _Same_size_and_compatible && _Is_trivially_assignable_returning_same_reference_v<_DestRef, _SourceRef>; }; template @@ -4710,7 +4719,8 @@ struct _Trivial_cat<_Source*, _Dest*, _SourceRef, _DestRef> { _Is_pointer_address_convertible<_Source, _Dest> && is_trivially_constructible_v<_Dest*, _SourceRef>; static constexpr bool _Bitcopy_assignable = - _Is_pointer_address_convertible<_Source, _Dest> && is_trivially_assignable_v<_DestRef, _SourceRef>; + _Is_pointer_address_convertible<_Source, _Dest> + && _Is_trivially_assignable_returning_same_reference_v<_DestRef, _SourceRef>; }; struct _False_trivial_cat { diff --git a/tests/std/test.lst b/tests/std/test.lst index 87f84f36107..4c7c40603d1 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -252,6 +252,7 @@ tests\GH_004609_heterogeneous_cmp_overloads tests\GH_004618_mixed_operator_usage_keeps_statistical_properties tests\GH_004618_normal_distribution_avoids_resets tests\GH_004657_expected_constraints_permissive +tests\GH_004686_vectorization_on_trivial_assignability tests\GH_004845_logical_operator_traits_with_non_bool_constant tests\GH_004929_internal_tag_constructors tests\GH_004930_char_traits_user_specialization diff --git a/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/env.lst b/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/env.lst new file mode 100644 index 00000000000..19f025bd0e6 --- /dev/null +++ b/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_matrix.lst diff --git a/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp b/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp new file mode 100644 index 00000000000..e6f780a4bc7 --- /dev/null +++ b/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp @@ -0,0 +1,264 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include + +#if _HAS_CXX20 +#define CONSTEXPR20 constexpr +#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv +#define CONSTEXPR20 inline +#endif // ^^^ !_HAS_CXX20 ^^^ + +using namespace std; + +struct Cat {}; +struct Leopard : Cat { + int spots_; + + Leopard() = default; + Leopard(const Leopard&) = default; + Leopard(Leopard&&) = default; + Leopard& operator=(Leopard&) && = delete; + using Cat::operator=; +}; + +constexpr pair expected_results[]{{5, 6}, {3, 4}, {1, 2}}; + +CONSTEXPR20 void test_reverse_copy() { + { + pair src[] = {{1, 2}, {3, 4}, {5, 6}}; + pair dst[] = {{3, 1}, {4, 1}, {5, 9}}; + pair srcref[] = { + {src[0].first, src[0].second}, {src[1].first, src[1].second}, {src[2].first, src[2].second}}; + pair dstref[] = { + {dst[0].first, dst[0].second}, {dst[1].first, dst[1].second}, {dst[2].first, dst[2].second}}; + + reverse_copy(srcref, srcref + 3, dstref); + assert(equal(begin(dst), end(dst), begin(expected_results), end(expected_results))); + } +#if _HAS_CXX20 + { + pair src[] = {{1, 2}, {3, 4}, {5, 6}}; + pair dst[] = {{3, 1}, {4, 1}, {5, 9}}; + pair srcref[] = { + {src[0].first, src[0].second}, {src[1].first, src[1].second}, {src[2].first, src[2].second}}; + pair dstref[] = { + {dst[0].first, dst[0].second}, {dst[1].first, dst[1].second}, {dst[2].first, dst[2].second}}; + + ranges::reverse_copy(srcref, srcref + 3, dstref); + assert(ranges::equal(dst, expected_results)); + } +#endif // _HAS_CXX20 +#if _HAS_CXX23 + { + pair src[] = {{1, 2}, {3, 4}, {5, 6}}; + pair dst[] = {{3, 1}, {4, 1}, {5, 9}}; + pair srcref[] = {src[0], src[1], src[2]}; + pair dstref[] = {dst[0], dst[1], dst[2]}; + + reverse_copy(srcref, srcref + 3, dstref); + assert(equal(begin(dst), end(dst), begin(expected_results), end(expected_results))); + } + { + pair src[] = {{1, 2}, {3, 4}, {5, 6}}; + pair dst[] = {{3, 1}, {4, 1}, {5, 9}}; + pair srcref[] = {src[0], src[1], src[2]}; + pair dstref[] = {dst[0], dst[1], dst[2]}; + + ranges::reverse_copy(srcref, dstref); + assert(ranges::equal(dst, expected_results)); + } +#endif // _HAS_CXX23 +} + +constexpr Leopard make_leopard(const int n) noexcept { + Leopard result{}; + result.spots_ = n; + return result; +} + +constexpr Leopard expected_leopards[]{ + make_leopard(3), make_leopard(1), make_leopard(4), make_leopard(1), make_leopard(5), make_leopard(9)}; + +CONSTEXPR20 void test_copy_move_leopards() { + constexpr Leopard zero_leopards[6]{}; + { + Leopard dst[]{ + make_leopard(3), make_leopard(1), make_leopard(4), make_leopard(1), make_leopard(5), make_leopard(9)}; + copy(begin(zero_leopards), end(zero_leopards), dst); + assert(equal(begin(dst), end(dst), begin(expected_leopards), end(expected_leopards), + [](const Leopard& lhs, const Leopard& rhs) { return lhs.spots_ == rhs.spots_; })); + } + { + Leopard dst[]{ + make_leopard(3), make_leopard(1), make_leopard(4), make_leopard(1), make_leopard(5), make_leopard(9)}; + copy_n(begin(zero_leopards), size(zero_leopards), dst); + assert(equal(begin(dst), end(dst), begin(expected_leopards), end(expected_leopards), + [](const Leopard& lhs, const Leopard& rhs) { return lhs.spots_ == rhs.spots_; })); + } + { + Leopard dst[]{ + make_leopard(3), make_leopard(1), make_leopard(4), make_leopard(1), make_leopard(5), make_leopard(9)}; + copy_backward(begin(zero_leopards), end(zero_leopards), dst + size(dst)); + assert(equal(begin(dst), end(dst), begin(expected_leopards), end(expected_leopards), + [](const Leopard& lhs, const Leopard& rhs) { return lhs.spots_ == rhs.spots_; })); + } + { + Leopard dst[]{ + make_leopard(3), make_leopard(1), make_leopard(4), make_leopard(1), make_leopard(5), make_leopard(9)}; + move(begin(zero_leopards), end(zero_leopards), dst); + assert(equal(begin(dst), end(dst), begin(expected_leopards), end(expected_leopards), + [](const Leopard& lhs, const Leopard& rhs) { return lhs.spots_ == rhs.spots_; })); + } + { + Leopard dst[]{ + make_leopard(3), make_leopard(1), make_leopard(4), make_leopard(1), make_leopard(5), make_leopard(9)}; + move_backward(begin(zero_leopards), end(zero_leopards), dst + size(dst)); + assert(equal(begin(dst), end(dst), begin(expected_leopards), end(expected_leopards), + [](const Leopard& lhs, const Leopard& rhs) { return lhs.spots_ == rhs.spots_; })); + } +#if _HAS_CXX20 + { + Leopard dst[]{ + make_leopard(3), make_leopard(1), make_leopard(4), make_leopard(1), make_leopard(5), make_leopard(9)}; + ranges::copy(zero_leopards, dst); + assert(ranges::equal(dst, expected_leopards, ranges::equal_to{}, &Leopard::spots_, &Leopard::spots_)); + } + { + Leopard dst[]{ + make_leopard(3), make_leopard(1), make_leopard(4), make_leopard(1), make_leopard(5), make_leopard(9)}; + ranges::copy_n(ranges::begin(zero_leopards), ranges::size(zero_leopards), dst); + assert(ranges::equal(dst, expected_leopards, ranges::equal_to{}, &Leopard::spots_, &Leopard::spots_)); + } + { + Leopard dst[]{ + make_leopard(3), make_leopard(1), make_leopard(4), make_leopard(1), make_leopard(5), make_leopard(9)}; + ranges::copy_backward(zero_leopards, dst + ranges::size(dst)); + assert(ranges::equal(dst, expected_leopards, ranges::equal_to{}, &Leopard::spots_, &Leopard::spots_)); + } + { + Leopard dst[]{ + make_leopard(3), make_leopard(1), make_leopard(4), make_leopard(1), make_leopard(5), make_leopard(9)}; + ranges::move(zero_leopards, dst); + assert(ranges::equal(dst, expected_leopards, ranges::equal_to{}, &Leopard::spots_, &Leopard::spots_)); + } + { + Leopard dst[]{ + make_leopard(3), make_leopard(1), make_leopard(4), make_leopard(1), make_leopard(5), make_leopard(9)}; + ranges::move_backward(zero_leopards, dst + ranges::size(dst)); + assert(ranges::equal(dst, expected_leopards, ranges::equal_to{}, &Leopard::spots_, &Leopard::spots_)); + } +#endif // _HAS_CXX20 +} + +// Pedantically, all of MSVC, Clang, and EDG are currently wrong on this, see LLVM-37038. +// However, if compilers get corrected, the assignment operators of `DerivedLeopard` and `LeopardHouse` will be trivial +// but no-op, and the library side can't correctly conclude that assignments for them shouldn't be vectorized. +// As a result, we keep the this as a regression test. +CONSTEXPR20 void test_llvm_37038() { + struct DerivedLeopard : Leopard {}; + static_assert(is_trivially_move_assignable_v); + + auto make_derived_leopard = [](int n) { + DerivedLeopard ret{}; + ret.spots_ = n; + return ret; + }; + + { + DerivedLeopard src[]{ + make_derived_leopard(1), make_derived_leopard(7), make_derived_leopard(2), make_derived_leopard(9)}; + DerivedLeopard dst[4]{}; + move(begin(src), end(src), dst); + assert(equal(begin(dst), end(dst), begin(src), end(src), + [](const DerivedLeopard& lhs, const DerivedLeopard& rhs) { return lhs.spots_ == rhs.spots_; })); + } + { + DerivedLeopard src[]{ + make_derived_leopard(1), make_derived_leopard(7), make_derived_leopard(2), make_derived_leopard(9)}; + DerivedLeopard dst[4]{}; + move_backward(begin(src), end(src), dst + size(dst)); + assert(equal(begin(dst), end(dst), begin(src), end(src), + [](const DerivedLeopard& lhs, const DerivedLeopard& rhs) { return lhs.spots_ == rhs.spots_; })); + } +#if _HAS_CXX20 + { + DerivedLeopard src[]{ + make_derived_leopard(1), make_derived_leopard(7), make_derived_leopard(2), make_derived_leopard(9)}; + DerivedLeopard dst[4]{}; + ranges::move(src, dst); + assert(ranges::equal( + src, dst, [](const DerivedLeopard& lhs, const DerivedLeopard& rhs) { return lhs.spots_ == rhs.spots_; })); + } + { + DerivedLeopard src[]{ + make_derived_leopard(1), make_derived_leopard(7), make_derived_leopard(2), make_derived_leopard(9)}; + DerivedLeopard dst[4]{}; + ranges::move_backward(src, ranges::end(dst)); + assert(ranges::equal( + src, dst, [](const DerivedLeopard& lhs, const DerivedLeopard& rhs) { return lhs.spots_ == rhs.spots_; })); + } +#endif // _HAS_CXX20 + + struct LeopardHouse { + Leopard bigcat_; + }; + static_assert(is_trivially_move_assignable_v); + + auto make_leopard_house = [](int n) { + LeopardHouse ret{}; + ret.bigcat_.spots_ = n; + return ret; + }; + + { + LeopardHouse src[]{make_leopard_house(1), make_leopard_house(7), make_leopard_house(2), make_leopard_house(9)}; + LeopardHouse dst[4]{}; + move(begin(src), end(src), dst); + assert(equal(begin(dst), end(dst), begin(src), end(src), + [](const LeopardHouse& lhs, const LeopardHouse& rhs) { return lhs.bigcat_.spots_ == rhs.bigcat_.spots_; })); + } + { + LeopardHouse src[]{make_leopard_house(1), make_leopard_house(7), make_leopard_house(2), make_leopard_house(9)}; + LeopardHouse dst[4]{}; + move_backward(begin(src), end(src), dst + size(dst)); + assert(equal(begin(dst), end(dst), begin(src), end(src), + [](const LeopardHouse& lhs, const LeopardHouse& rhs) { return lhs.bigcat_.spots_ == rhs.bigcat_.spots_; })); + } +#if _HAS_CXX20 + { + LeopardHouse src[]{make_leopard_house(1), make_leopard_house(7), make_leopard_house(2), make_leopard_house(9)}; + LeopardHouse dst[4]{}; + ranges::move(src, dst); + assert(ranges::equal(src, dst, + [](const LeopardHouse& lhs, const LeopardHouse& rhs) { return lhs.bigcat_.spots_ == rhs.bigcat_.spots_; })); + } + { + LeopardHouse src[]{make_leopard_house(1), make_leopard_house(7), make_leopard_house(2), make_leopard_house(9)}; + LeopardHouse dst[4]{}; + ranges::move_backward(src, ranges::end(dst)); + assert(ranges::equal(src, dst, + [](const LeopardHouse& lhs, const LeopardHouse& rhs) { return lhs.bigcat_.spots_ == rhs.bigcat_.spots_; })); + } +#endif // _HAS_CXX20 +} + +CONSTEXPR20 bool test() { + test_reverse_copy(); + test_copy_move_leopards(); + test_llvm_37038(); + + return true; +} + +#if _HAS_CXX20 +static_assert(test()); +#endif // _HAS_CXX20 + +int main() { + test(); +} From 078f51127fa52dcd8bbd2b57c7407591ffab3926 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Tue, 20 May 2025 09:16:04 +0800 Subject: [PATCH 02/16] Suppress warning C4365 --- stl/inc/xutility | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/stl/inc/xutility b/stl/inc/xutility index ebe48eac967..a67fcc7e9c8 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -4683,6 +4683,8 @@ constexpr bool _Is_pointer_address_convertible = is_void_v<_Source> #endif // defined(__cpp_lib_is_pointer_interconvertible) ; +#pragma warning(disable : 4365) // '%s': conversion from '%s' to '%s', signed/unsigned mismatch (/Wall) + // Determines whether _DestRef is trivially assignable from _SourceRef, and if _Remove_cvref_t<_DestRef> is a class, the // assignment uses _Remove_cvref_t<_DestRef>::operator=. // Not pedantically reliable for vectorization, but working due to bugs of MSVC, Clang, and EDG. See LLVM-37038. @@ -4692,6 +4694,8 @@ constexpr bool _Is_trivially_assignable_returning_same_reference_v = template constexpr bool _Is_trivially_assignable_returning_same_reference_v<_DestRef, _SourceRef, false> = false; +#pragma warning(pop) + template struct _Trivial_cat { using _USource = _Unwrap_enum_t<_Source>; From 4abef8ccafd3bfe13f482ebfc15c83804a076b14 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Tue, 20 May 2025 09:24:16 +0800 Subject: [PATCH 03/16] `#pragma warning(push)` --- stl/inc/xutility | 1 + 1 file changed, 1 insertion(+) diff --git a/stl/inc/xutility b/stl/inc/xutility index a67fcc7e9c8..7456b9f8681 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -4683,6 +4683,7 @@ constexpr bool _Is_pointer_address_convertible = is_void_v<_Source> #endif // defined(__cpp_lib_is_pointer_interconvertible) ; +#pragma warning(push) #pragma warning(disable : 4365) // '%s': conversion from '%s' to '%s', signed/unsigned mismatch (/Wall) // Determines whether _DestRef is trivially assignable from _SourceRef, and if _Remove_cvref_t<_DestRef> is a class, the From a1919c84caad4e373904ede157a0ed29bc7dc079 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Tue, 20 May 2025 10:02:56 +0800 Subject: [PATCH 04/16] Suppress warning C4244 --- stl/inc/xutility | 1 + 1 file changed, 1 insertion(+) diff --git a/stl/inc/xutility b/stl/inc/xutility index 7456b9f8681..12efd36371c 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -4684,6 +4684,7 @@ constexpr bool _Is_pointer_address_convertible = is_void_v<_Source> ; #pragma warning(push) +#pragma warning(disable : 4244) // '%s': conversion from '%s' to '%s', possible loss of data #pragma warning(disable : 4365) // '%s': conversion from '%s' to '%s', signed/unsigned mismatch (/Wall) // Determines whether _DestRef is trivially assignable from _SourceRef, and if _Remove_cvref_t<_DestRef> is a class, the From 72de94ff06da4d05c352c97ba4938b215b26d667 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Tue, 20 May 2025 10:30:15 +0800 Subject: [PATCH 05/16] Suppress warning C4242 --- stl/inc/xutility | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/stl/inc/xutility b/stl/inc/xutility index 12efd36371c..41005ae15ed 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -4684,8 +4684,9 @@ constexpr bool _Is_pointer_address_convertible = is_void_v<_Source> ; #pragma warning(push) -#pragma warning(disable : 4244) // '%s': conversion from '%s' to '%s', possible loss of data -#pragma warning(disable : 4365) // '%s': conversion from '%s' to '%s', signed/unsigned mismatch (/Wall) +#pragma warning(disable : 4242) // '%s': conversion from '%s' to '%s', possible loss of data +#pragma warning(disable : 4244) // '%s': conversion from '%s' to '%s', possible loss of data (Yes, duplicated message.) +#pragma warning(disable : 4365) // '%s': conversion from '%s' to '%s', signed/unsigned mismatch // Determines whether _DestRef is trivially assignable from _SourceRef, and if _Remove_cvref_t<_DestRef> is a class, the // assignment uses _Remove_cvref_t<_DestRef>::operator=. From f8d71684a624e2f49f719cbeff8fc6340d0f2ff8 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Tue, 20 May 2025 10:54:50 +0800 Subject: [PATCH 06/16] Suppress warning C4267 --- stl/inc/xutility | 1 + 1 file changed, 1 insertion(+) diff --git a/stl/inc/xutility b/stl/inc/xutility index 41005ae15ed..bc562ec1def 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -4686,6 +4686,7 @@ constexpr bool _Is_pointer_address_convertible = is_void_v<_Source> #pragma warning(push) #pragma warning(disable : 4242) // '%s': conversion from '%s' to '%s', possible loss of data #pragma warning(disable : 4244) // '%s': conversion from '%s' to '%s', possible loss of data (Yes, duplicated message.) +#pragma warning(disable : 4267) // '%s': conversion from '%s' to '%s', possible loss of data (Yes, duplicated message!) #pragma warning(disable : 4365) // '%s': conversion from '%s' to '%s', signed/unsigned mismatch // Determines whether _DestRef is trivially assignable from _SourceRef, and if _Remove_cvref_t<_DestRef> is a class, the From 5fc2c5d56b81b7e08a21fe93126954c9de6524c3 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Tue, 20 May 2025 11:01:38 +0800 Subject: [PATCH 07/16] Tweak test --- .../test.cpp | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp b/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp index e6f780a4bc7..35f1897e339 100644 --- a/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp +++ b/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp @@ -81,43 +81,42 @@ constexpr Leopard make_leopard(const int n) noexcept { return result; } -constexpr Leopard expected_leopards[]{ - make_leopard(3), make_leopard(1), make_leopard(4), make_leopard(1), make_leopard(5), make_leopard(9)}; - CONSTEXPR20 void test_copy_move_leopards() { + constexpr Leopard expected_leopards[]{ + make_leopard(3), make_leopard(1), make_leopard(4), make_leopard(1), make_leopard(5), make_leopard(9)}; constexpr Leopard zero_leopards[6]{}; { Leopard dst[]{ make_leopard(3), make_leopard(1), make_leopard(4), make_leopard(1), make_leopard(5), make_leopard(9)}; - copy(begin(zero_leopards), end(zero_leopards), dst); + copy(begin(zero_leopards), end(zero_leopards), begin(dst)); assert(equal(begin(dst), end(dst), begin(expected_leopards), end(expected_leopards), [](const Leopard& lhs, const Leopard& rhs) { return lhs.spots_ == rhs.spots_; })); } { Leopard dst[]{ make_leopard(3), make_leopard(1), make_leopard(4), make_leopard(1), make_leopard(5), make_leopard(9)}; - copy_n(begin(zero_leopards), size(zero_leopards), dst); + copy_n(begin(zero_leopards), end(zero_leopards) - begin(zero_leopards), begin(dst)); assert(equal(begin(dst), end(dst), begin(expected_leopards), end(expected_leopards), [](const Leopard& lhs, const Leopard& rhs) { return lhs.spots_ == rhs.spots_; })); } { Leopard dst[]{ make_leopard(3), make_leopard(1), make_leopard(4), make_leopard(1), make_leopard(5), make_leopard(9)}; - copy_backward(begin(zero_leopards), end(zero_leopards), dst + size(dst)); + copy_backward(begin(zero_leopards), end(zero_leopards), end(dst)); assert(equal(begin(dst), end(dst), begin(expected_leopards), end(expected_leopards), [](const Leopard& lhs, const Leopard& rhs) { return lhs.spots_ == rhs.spots_; })); } { Leopard dst[]{ make_leopard(3), make_leopard(1), make_leopard(4), make_leopard(1), make_leopard(5), make_leopard(9)}; - move(begin(zero_leopards), end(zero_leopards), dst); + move(begin(zero_leopards), end(zero_leopards), begin(dst)); assert(equal(begin(dst), end(dst), begin(expected_leopards), end(expected_leopards), [](const Leopard& lhs, const Leopard& rhs) { return lhs.spots_ == rhs.spots_; })); } { Leopard dst[]{ make_leopard(3), make_leopard(1), make_leopard(4), make_leopard(1), make_leopard(5), make_leopard(9)}; - move_backward(begin(zero_leopards), end(zero_leopards), dst + size(dst)); + move_backward(begin(zero_leopards), end(zero_leopards), end(dst)); assert(equal(begin(dst), end(dst), begin(expected_leopards), end(expected_leopards), [](const Leopard& lhs, const Leopard& rhs) { return lhs.spots_ == rhs.spots_; })); } @@ -131,13 +130,13 @@ CONSTEXPR20 void test_copy_move_leopards() { { Leopard dst[]{ make_leopard(3), make_leopard(1), make_leopard(4), make_leopard(1), make_leopard(5), make_leopard(9)}; - ranges::copy_n(ranges::begin(zero_leopards), ranges::size(zero_leopards), dst); + ranges::copy_n(ranges::begin(zero_leopards), ranges::distance(zero_leopards), dst); assert(ranges::equal(dst, expected_leopards, ranges::equal_to{}, &Leopard::spots_, &Leopard::spots_)); } { Leopard dst[]{ make_leopard(3), make_leopard(1), make_leopard(4), make_leopard(1), make_leopard(5), make_leopard(9)}; - ranges::copy_backward(zero_leopards, dst + ranges::size(dst)); + ranges::copy_backward(zero_leopards, dst + ranges::distance(dst)); assert(ranges::equal(dst, expected_leopards, ranges::equal_to{}, &Leopard::spots_, &Leopard::spots_)); } { @@ -149,7 +148,7 @@ CONSTEXPR20 void test_copy_move_leopards() { { Leopard dst[]{ make_leopard(3), make_leopard(1), make_leopard(4), make_leopard(1), make_leopard(5), make_leopard(9)}; - ranges::move_backward(zero_leopards, dst + ranges::size(dst)); + ranges::move_backward(zero_leopards, dst + ranges::distance(dst)); assert(ranges::equal(dst, expected_leopards, ranges::equal_to{}, &Leopard::spots_, &Leopard::spots_)); } #endif // _HAS_CXX20 @@ -181,7 +180,7 @@ CONSTEXPR20 void test_llvm_37038() { DerivedLeopard src[]{ make_derived_leopard(1), make_derived_leopard(7), make_derived_leopard(2), make_derived_leopard(9)}; DerivedLeopard dst[4]{}; - move_backward(begin(src), end(src), dst + size(dst)); + move_backward(begin(src), end(src), end(dst)); assert(equal(begin(dst), end(dst), begin(src), end(src), [](const DerivedLeopard& lhs, const DerivedLeopard& rhs) { return lhs.spots_ == rhs.spots_; })); } @@ -225,7 +224,7 @@ CONSTEXPR20 void test_llvm_37038() { { LeopardHouse src[]{make_leopard_house(1), make_leopard_house(7), make_leopard_house(2), make_leopard_house(9)}; LeopardHouse dst[4]{}; - move_backward(begin(src), end(src), dst + size(dst)); + move_backward(begin(src), end(src), end(dst)); assert(equal(begin(dst), end(dst), begin(src), end(src), [](const LeopardHouse& lhs, const LeopardHouse& rhs) { return lhs.bigcat_.spots_ == rhs.bigcat_.spots_; })); } From b57a5090dda91f10462838e783cb1b563e95b87c Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Tue, 20 May 2025 11:45:49 +0800 Subject: [PATCH 08/16] Suppress warning C5267 --- stl/inc/xutility | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stl/inc/xutility b/stl/inc/xutility index bc562ec1def..61f8e1a620d 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -4688,6 +4688,8 @@ constexpr bool _Is_pointer_address_convertible = is_void_v<_Source> #pragma warning(disable : 4244) // '%s': conversion from '%s' to '%s', possible loss of data (Yes, duplicated message.) #pragma warning(disable : 4267) // '%s': conversion from '%s' to '%s', possible loss of data (Yes, duplicated message!) #pragma warning(disable : 4365) // '%s': conversion from '%s' to '%s', signed/unsigned mismatch +#pragma warning(disable : 5267) // definition of implicit assignment operator for '%s' is deprecated because it has a + // user-provided copy constructor // Determines whether _DestRef is trivially assignable from _SourceRef, and if _Remove_cvref_t<_DestRef> is a class, the // assignment uses _Remove_cvref_t<_DestRef>::operator=. From 7921def8cd9df9989e2ce02c6e856f27a2229655 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Tue, 20 May 2025 11:46:07 +0800 Subject: [PATCH 09/16] Fix test for C++14 --- .../GH_004686_vectorization_on_trivial_assignability/test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp b/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp index 35f1897e339..9a719d35455 100644 --- a/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp +++ b/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp @@ -160,7 +160,7 @@ CONSTEXPR20 void test_copy_move_leopards() { // As a result, we keep the this as a regression test. CONSTEXPR20 void test_llvm_37038() { struct DerivedLeopard : Leopard {}; - static_assert(is_trivially_move_assignable_v); + static_assert(is_trivially_move_assignable_v, ""); auto make_derived_leopard = [](int n) { DerivedLeopard ret{}; @@ -206,7 +206,7 @@ CONSTEXPR20 void test_llvm_37038() { struct LeopardHouse { Leopard bigcat_; }; - static_assert(is_trivially_move_assignable_v); + static_assert(is_trivially_move_assignable_v, ""); auto make_leopard_house = [](int n) { LeopardHouse ret{}; From b486c6f1ccf6abff25c772d0660d5387a4e2f536 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 21 May 2025 03:33:28 -0700 Subject: [PATCH 10/16] Pass a range to `ranges::reverse_copy`. --- .../GH_004686_vectorization_on_trivial_assignability/test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp b/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp index 9a719d35455..21f7d5234e6 100644 --- a/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp +++ b/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp @@ -49,7 +49,7 @@ CONSTEXPR20 void test_reverse_copy() { pair dstref[] = { {dst[0].first, dst[0].second}, {dst[1].first, dst[1].second}, {dst[2].first, dst[2].second}}; - ranges::reverse_copy(srcref, srcref + 3, dstref); + ranges::reverse_copy(srcref, dstref); assert(ranges::equal(dst, expected_results)); } #endif // _HAS_CXX20 From e30a692d72aacb8702961d330cb07f4205fa006f Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 21 May 2025 03:34:15 -0700 Subject: [PATCH 11/16] Use begin/end. --- .../GH_004686_vectorization_on_trivial_assignability/test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp b/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp index 21f7d5234e6..3bc3d17cd66 100644 --- a/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp +++ b/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp @@ -37,7 +37,7 @@ CONSTEXPR20 void test_reverse_copy() { pair dstref[] = { {dst[0].first, dst[0].second}, {dst[1].first, dst[1].second}, {dst[2].first, dst[2].second}}; - reverse_copy(srcref, srcref + 3, dstref); + reverse_copy(begin(srcref), end(srcref), dstref); assert(equal(begin(dst), end(dst), begin(expected_results), end(expected_results))); } #if _HAS_CXX20 @@ -60,7 +60,7 @@ CONSTEXPR20 void test_reverse_copy() { pair srcref[] = {src[0], src[1], src[2]}; pair dstref[] = {dst[0], dst[1], dst[2]}; - reverse_copy(srcref, srcref + 3, dstref); + reverse_copy(begin(srcref), end(srcref), dstref); assert(equal(begin(dst), end(dst), begin(expected_results), end(expected_results))); } { From 8cd670b318e1fb82428eef40e3928ebee78b45ac Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 21 May 2025 03:35:01 -0700 Subject: [PATCH 12/16] All roads lead to Trantor, and that is where all stars end. --- .../GH_004686_vectorization_on_trivial_assignability/test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp b/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp index 3bc3d17cd66..d8d37a13ede 100644 --- a/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp +++ b/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp @@ -136,7 +136,7 @@ CONSTEXPR20 void test_copy_move_leopards() { { Leopard dst[]{ make_leopard(3), make_leopard(1), make_leopard(4), make_leopard(1), make_leopard(5), make_leopard(9)}; - ranges::copy_backward(zero_leopards, dst + ranges::distance(dst)); + ranges::copy_backward(zero_leopards, ranges::end(dst)); assert(ranges::equal(dst, expected_leopards, ranges::equal_to{}, &Leopard::spots_, &Leopard::spots_)); } { @@ -148,7 +148,7 @@ CONSTEXPR20 void test_copy_move_leopards() { { Leopard dst[]{ make_leopard(3), make_leopard(1), make_leopard(4), make_leopard(1), make_leopard(5), make_leopard(9)}; - ranges::move_backward(zero_leopards, dst + ranges::distance(dst)); + ranges::move_backward(zero_leopards, ranges::end(dst)); assert(ranges::equal(dst, expected_leopards, ranges::equal_to{}, &Leopard::spots_, &Leopard::spots_)); } #endif // _HAS_CXX20 From 454c0e6b03cc6cf5f27cafc218b29630891a16e2 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 21 May 2025 03:42:08 -0700 Subject: [PATCH 13/16] Extract lambdas. --- .../test.cpp | 46 ++++++++----------- 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp b/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp index d8d37a13ede..18d1debfa1c 100644 --- a/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp +++ b/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp @@ -85,40 +85,36 @@ CONSTEXPR20 void test_copy_move_leopards() { constexpr Leopard expected_leopards[]{ make_leopard(3), make_leopard(1), make_leopard(4), make_leopard(1), make_leopard(5), make_leopard(9)}; constexpr Leopard zero_leopards[6]{}; + auto equal_leopard = [](const Leopard& lhs, const Leopard& rhs) { return lhs.spots_ == rhs.spots_; }; { Leopard dst[]{ make_leopard(3), make_leopard(1), make_leopard(4), make_leopard(1), make_leopard(5), make_leopard(9)}; copy(begin(zero_leopards), end(zero_leopards), begin(dst)); - assert(equal(begin(dst), end(dst), begin(expected_leopards), end(expected_leopards), - [](const Leopard& lhs, const Leopard& rhs) { return lhs.spots_ == rhs.spots_; })); + assert(equal(begin(dst), end(dst), begin(expected_leopards), end(expected_leopards), equal_leopard)); } { Leopard dst[]{ make_leopard(3), make_leopard(1), make_leopard(4), make_leopard(1), make_leopard(5), make_leopard(9)}; copy_n(begin(zero_leopards), end(zero_leopards) - begin(zero_leopards), begin(dst)); - assert(equal(begin(dst), end(dst), begin(expected_leopards), end(expected_leopards), - [](const Leopard& lhs, const Leopard& rhs) { return lhs.spots_ == rhs.spots_; })); + assert(equal(begin(dst), end(dst), begin(expected_leopards), end(expected_leopards), equal_leopard)); } { Leopard dst[]{ make_leopard(3), make_leopard(1), make_leopard(4), make_leopard(1), make_leopard(5), make_leopard(9)}; copy_backward(begin(zero_leopards), end(zero_leopards), end(dst)); - assert(equal(begin(dst), end(dst), begin(expected_leopards), end(expected_leopards), - [](const Leopard& lhs, const Leopard& rhs) { return lhs.spots_ == rhs.spots_; })); + assert(equal(begin(dst), end(dst), begin(expected_leopards), end(expected_leopards), equal_leopard)); } { Leopard dst[]{ make_leopard(3), make_leopard(1), make_leopard(4), make_leopard(1), make_leopard(5), make_leopard(9)}; move(begin(zero_leopards), end(zero_leopards), begin(dst)); - assert(equal(begin(dst), end(dst), begin(expected_leopards), end(expected_leopards), - [](const Leopard& lhs, const Leopard& rhs) { return lhs.spots_ == rhs.spots_; })); + assert(equal(begin(dst), end(dst), begin(expected_leopards), end(expected_leopards), equal_leopard)); } { Leopard dst[]{ make_leopard(3), make_leopard(1), make_leopard(4), make_leopard(1), make_leopard(5), make_leopard(9)}; move_backward(begin(zero_leopards), end(zero_leopards), end(dst)); - assert(equal(begin(dst), end(dst), begin(expected_leopards), end(expected_leopards), - [](const Leopard& lhs, const Leopard& rhs) { return lhs.spots_ == rhs.spots_; })); + assert(equal(begin(dst), end(dst), begin(expected_leopards), end(expected_leopards), equal_leopard)); } #if _HAS_CXX20 { @@ -168,21 +164,21 @@ CONSTEXPR20 void test_llvm_37038() { return ret; }; + auto equal_derived = [](const DerivedLeopard& lhs, const DerivedLeopard& rhs) { return lhs.spots_ == rhs.spots_; }; + { DerivedLeopard src[]{ make_derived_leopard(1), make_derived_leopard(7), make_derived_leopard(2), make_derived_leopard(9)}; DerivedLeopard dst[4]{}; move(begin(src), end(src), dst); - assert(equal(begin(dst), end(dst), begin(src), end(src), - [](const DerivedLeopard& lhs, const DerivedLeopard& rhs) { return lhs.spots_ == rhs.spots_; })); + assert(equal(begin(dst), end(dst), begin(src), end(src), equal_derived)); } { DerivedLeopard src[]{ make_derived_leopard(1), make_derived_leopard(7), make_derived_leopard(2), make_derived_leopard(9)}; DerivedLeopard dst[4]{}; move_backward(begin(src), end(src), end(dst)); - assert(equal(begin(dst), end(dst), begin(src), end(src), - [](const DerivedLeopard& lhs, const DerivedLeopard& rhs) { return lhs.spots_ == rhs.spots_; })); + assert(equal(begin(dst), end(dst), begin(src), end(src), equal_derived)); } #if _HAS_CXX20 { @@ -190,16 +186,14 @@ CONSTEXPR20 void test_llvm_37038() { make_derived_leopard(1), make_derived_leopard(7), make_derived_leopard(2), make_derived_leopard(9)}; DerivedLeopard dst[4]{}; ranges::move(src, dst); - assert(ranges::equal( - src, dst, [](const DerivedLeopard& lhs, const DerivedLeopard& rhs) { return lhs.spots_ == rhs.spots_; })); + assert(ranges::equal(src, dst, equal_derived)); } { DerivedLeopard src[]{ make_derived_leopard(1), make_derived_leopard(7), make_derived_leopard(2), make_derived_leopard(9)}; DerivedLeopard dst[4]{}; ranges::move_backward(src, ranges::end(dst)); - assert(ranges::equal( - src, dst, [](const DerivedLeopard& lhs, const DerivedLeopard& rhs) { return lhs.spots_ == rhs.spots_; })); + assert(ranges::equal(src, dst, equal_derived)); } #endif // _HAS_CXX20 @@ -214,34 +208,34 @@ CONSTEXPR20 void test_llvm_37038() { return ret; }; + auto equal_house = [](const LeopardHouse& lhs, const LeopardHouse& rhs) { + return lhs.bigcat_.spots_ == rhs.bigcat_.spots_; + }; + { LeopardHouse src[]{make_leopard_house(1), make_leopard_house(7), make_leopard_house(2), make_leopard_house(9)}; LeopardHouse dst[4]{}; move(begin(src), end(src), dst); - assert(equal(begin(dst), end(dst), begin(src), end(src), - [](const LeopardHouse& lhs, const LeopardHouse& rhs) { return lhs.bigcat_.spots_ == rhs.bigcat_.spots_; })); + assert(equal(begin(dst), end(dst), begin(src), end(src), equal_house)); } { LeopardHouse src[]{make_leopard_house(1), make_leopard_house(7), make_leopard_house(2), make_leopard_house(9)}; LeopardHouse dst[4]{}; move_backward(begin(src), end(src), end(dst)); - assert(equal(begin(dst), end(dst), begin(src), end(src), - [](const LeopardHouse& lhs, const LeopardHouse& rhs) { return lhs.bigcat_.spots_ == rhs.bigcat_.spots_; })); + assert(equal(begin(dst), end(dst), begin(src), end(src), equal_house)); } #if _HAS_CXX20 { LeopardHouse src[]{make_leopard_house(1), make_leopard_house(7), make_leopard_house(2), make_leopard_house(9)}; LeopardHouse dst[4]{}; ranges::move(src, dst); - assert(ranges::equal(src, dst, - [](const LeopardHouse& lhs, const LeopardHouse& rhs) { return lhs.bigcat_.spots_ == rhs.bigcat_.spots_; })); + assert(ranges::equal(src, dst, equal_house)); } { LeopardHouse src[]{make_leopard_house(1), make_leopard_house(7), make_leopard_house(2), make_leopard_house(9)}; LeopardHouse dst[4]{}; ranges::move_backward(src, ranges::end(dst)); - assert(ranges::equal(src, dst, - [](const LeopardHouse& lhs, const LeopardHouse& rhs) { return lhs.bigcat_.spots_ == rhs.bigcat_.spots_; })); + assert(ranges::equal(src, dst, equal_house)); } #endif // _HAS_CXX20 } From 7b4a21ecd90ae769dd605fdd6439212feaa628a4 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 21 May 2025 03:49:49 -0700 Subject: [PATCH 14/16] Fix comment typo. --- .../GH_004686_vectorization_on_trivial_assignability/test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp b/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp index 18d1debfa1c..d46792735b0 100644 --- a/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp +++ b/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp @@ -153,7 +153,7 @@ CONSTEXPR20 void test_copy_move_leopards() { // Pedantically, all of MSVC, Clang, and EDG are currently wrong on this, see LLVM-37038. // However, if compilers get corrected, the assignment operators of `DerivedLeopard` and `LeopardHouse` will be trivial // but no-op, and the library side can't correctly conclude that assignments for them shouldn't be vectorized. -// As a result, we keep the this as a regression test. +// As a result, we keep this as a regression test. CONSTEXPR20 void test_llvm_37038() { struct DerivedLeopard : Leopard {}; static_assert(is_trivially_move_assignable_v, ""); From 8db95d948c297544a6b79cdbad19b8f38175e6d1 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 21 May 2025 03:55:52 -0700 Subject: [PATCH 15/16] Use size(). --- .../GH_004686_vectorization_on_trivial_assignability/test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp b/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp index d46792735b0..0f855320a20 100644 --- a/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp +++ b/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp @@ -95,7 +95,7 @@ CONSTEXPR20 void test_copy_move_leopards() { { Leopard dst[]{ make_leopard(3), make_leopard(1), make_leopard(4), make_leopard(1), make_leopard(5), make_leopard(9)}; - copy_n(begin(zero_leopards), end(zero_leopards) - begin(zero_leopards), begin(dst)); + copy_n(begin(zero_leopards), size(zero_leopards), begin(dst)); assert(equal(begin(dst), end(dst), begin(expected_leopards), end(expected_leopards), equal_leopard)); } { From 89afc14df9ee4776d61c0437bcd81640e07407eb Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 22 May 2025 10:17:34 -0700 Subject: [PATCH 16/16] Perma-workaround VSO-1664341 "/clr C++20 System.NullReferenceException when calling ranges algorithms with PMD projections". --- .../test.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp b/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp index 0f855320a20..370291f437c 100644 --- a/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp +++ b/tests/std/tests/GH_004686_vectorization_on_trivial_assignability/test.cpp @@ -3,7 +3,6 @@ #include #include -#include #include #include @@ -121,31 +120,31 @@ CONSTEXPR20 void test_copy_move_leopards() { Leopard dst[]{ make_leopard(3), make_leopard(1), make_leopard(4), make_leopard(1), make_leopard(5), make_leopard(9)}; ranges::copy(zero_leopards, dst); - assert(ranges::equal(dst, expected_leopards, ranges::equal_to{}, &Leopard::spots_, &Leopard::spots_)); + assert(ranges::equal(dst, expected_leopards, equal_leopard)); } { Leopard dst[]{ make_leopard(3), make_leopard(1), make_leopard(4), make_leopard(1), make_leopard(5), make_leopard(9)}; ranges::copy_n(ranges::begin(zero_leopards), ranges::distance(zero_leopards), dst); - assert(ranges::equal(dst, expected_leopards, ranges::equal_to{}, &Leopard::spots_, &Leopard::spots_)); + assert(ranges::equal(dst, expected_leopards, equal_leopard)); } { Leopard dst[]{ make_leopard(3), make_leopard(1), make_leopard(4), make_leopard(1), make_leopard(5), make_leopard(9)}; ranges::copy_backward(zero_leopards, ranges::end(dst)); - assert(ranges::equal(dst, expected_leopards, ranges::equal_to{}, &Leopard::spots_, &Leopard::spots_)); + assert(ranges::equal(dst, expected_leopards, equal_leopard)); } { Leopard dst[]{ make_leopard(3), make_leopard(1), make_leopard(4), make_leopard(1), make_leopard(5), make_leopard(9)}; ranges::move(zero_leopards, dst); - assert(ranges::equal(dst, expected_leopards, ranges::equal_to{}, &Leopard::spots_, &Leopard::spots_)); + assert(ranges::equal(dst, expected_leopards, equal_leopard)); } { Leopard dst[]{ make_leopard(3), make_leopard(1), make_leopard(4), make_leopard(1), make_leopard(5), make_leopard(9)}; ranges::move_backward(zero_leopards, ranges::end(dst)); - assert(ranges::equal(dst, expected_leopards, ranges::equal_to{}, &Leopard::spots_, &Leopard::spots_)); + assert(ranges::equal(dst, expected_leopards, equal_leopard)); } #endif // _HAS_CXX20 }