From 09e0dbbf150714d2a01c8ab0b9b8df02884bb0cc Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Wed, 19 Mar 2025 21:54:36 +0200 Subject: [PATCH 1/8] Handle aligned vector in constexpr properly --- stl/inc/vector | 22 ++++++++++++++++-- .../test.cpp | 23 +++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/stl/inc/vector b/stl/inc/vector index a4dcee2cfbe..75f1b8effb6 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -3816,7 +3816,7 @@ _CONSTEXPR20 _OutIt _Copy_vbool(_VbIt _First, _VbIt _Last, _OutIt _Dest) { const auto _FirstSourceMask = static_cast<_Vbase>(-1) << _First._Myoff; const auto _FirstDestMask = _Dest._Myoff == 0 ? 0 : (static_cast<_Vbase>(-1) >> (_VBITS - _Dest._Myoff)); - const auto _LastSourceMask = static_cast<_Vbase>(-1) >> (_VBITS - _Last._Myoff); + const auto _LastSourceMask = _Last._Myoff == 0 ? 0 : (static_cast<_Vbase>(-1) >> (_VBITS - _Last._Myoff)); const auto _LastDestMask = static_cast<_Vbase>(-1) << _DestEnd._Myoff; const bool _IsSingleBlockSource = _VbFirst == _VbLast; @@ -3859,7 +3859,25 @@ _CONSTEXPR20 _OutIt _Copy_vbool(_VbIt _First, _VbIt _Last, _OutIt _Dest) { } #if _HAS_CXX20 - if (!_STD is_constant_evaluated()) + if (_STD is_constant_evaluated()) { + if (_Dest._Myoff == _First._Myoff) { + const auto _FirstSourceVal = (*_VbFirst & _FirstSourceMask); + *_VbDest = (*_VbDest & _FirstDestMask) | _FirstSourceVal; + + ++_VbFirst; + ++_VbDest; + for (; _VbFirst != _VbLast; ++_VbFirst, ++_VbDest) { + *_VbDest = *_VbFirst; + } + + if (_Last._Myoff != 0) { + const auto _SourceVal = (*_VbFirst & _LastSourceMask); + *_VbDest = (*_VbDest & _LastDestMask) | _SourceVal; + } + + return _DestEnd; + } + } else #endif { // If _First and _Dest have matching char alignment, use memmove diff --git a/tests/std/tests/GH_000625_vector_bool_optimization/test.cpp b/tests/std/tests/GH_000625_vector_bool_optimization/test.cpp index c96ea1bbafd..0c556390e8e 100644 --- a/tests/std/tests/GH_000625_vector_bool_optimization/test.cpp +++ b/tests/std/tests/GH_000625_vector_bool_optimization/test.cpp @@ -1304,6 +1304,29 @@ void randomized_test_copy(mt19937_64& gen) { } } +#if _HAS_CXX20 +template +constexpr bool gh_005345() { + vector src(N, true); + + for (size_t i = 2; i != N; ++i) { + for (size_t j = i * 2; j < N; j += i) { + src[j] = false; + } + } + + vector dst(N, false); + copy(src.begin(), src.end(), dst.begin()); + return src == dst; +} + +static_assert(gh_005345<17>()); +static_assert(gh_005345<32>()); +static_assert(gh_005345<43>()); +static_assert(gh_005345<64>()); +static_assert(gh_005345<120>()); +#endif + int main() { test_fill(); test_find(); From 1456de7edca0f738aaea53fdcc9ba42672b452fa Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Thu, 20 Mar 2025 20:02:03 +0200 Subject: [PATCH 2/8] -parens --- stl/inc/vector | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/vector b/stl/inc/vector index 75f1b8effb6..6473a2126a5 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -3861,7 +3861,7 @@ _CONSTEXPR20 _OutIt _Copy_vbool(_VbIt _First, _VbIt _Last, _OutIt _Dest) { #if _HAS_CXX20 if (_STD is_constant_evaluated()) { if (_Dest._Myoff == _First._Myoff) { - const auto _FirstSourceVal = (*_VbFirst & _FirstSourceMask); + const auto _FirstSourceVal = *_VbFirst & _FirstSourceMask; *_VbDest = (*_VbDest & _FirstDestMask) | _FirstSourceVal; ++_VbFirst; @@ -3871,7 +3871,7 @@ _CONSTEXPR20 _OutIt _Copy_vbool(_VbIt _First, _VbIt _Last, _OutIt _Dest) { } if (_Last._Myoff != 0) { - const auto _SourceVal = (*_VbFirst & _LastSourceMask); + const auto _SourceVal = *_VbFirst & _LastSourceMask; *_VbDest = (*_VbDest & _LastDestMask) | _SourceVal; } From c15803285906891caf3494bb9cd5153feeddbce7 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 24 Mar 2025 22:11:45 -0700 Subject: [PATCH 3/8] Some, but not all, libcxx tests are now passing. --- tests/libcxx/expected_results.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 3285f4d32ae..1b459e07c5a 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -657,11 +657,12 @@ std/input.output/syncstream/syncbuf/syncstream.syncbuf.cons/dtor.pass.cpp FAIL std/input.output/syncstream/syncbuf/syncstream.syncbuf.members/emit.pass.cpp FAIL # GH-5345: : _Copy_vbool() mishandles vectors of size 32 and 64, revealed by constexpr Clang -std/algorithms/alg.modifying.operations/alg.copy/copy_n.pass.cpp:2 FAIL std/algorithms/alg.modifying.operations/alg.copy/copy.pass.cpp:2 FAIL std/algorithms/alg.modifying.operations/alg.move/move.pass.cpp:2 FAIL -std/algorithms/alg.nonmodifying/alg.equal/equal.pass.cpp FAIL -std/algorithms/alg.nonmodifying/alg.equal/ranges.equal.pass.cpp FAIL +std/algorithms/alg.nonmodifying/alg.equal/equal.pass.cpp:0 FAIL +std/algorithms/alg.nonmodifying/alg.equal/equal.pass.cpp:1 FAIL +std/algorithms/alg.nonmodifying/alg.equal/ranges.equal.pass.cpp:0 FAIL +std/algorithms/alg.nonmodifying/alg.equal/ranges.equal.pass.cpp:1 FAIL # *** VCRUNTIME BUGS *** From 73d75efc20859ca3ebf577890c9814a2eb1bf2b0 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 19 Apr 2025 10:15:42 -0700 Subject: [PATCH 4/8] Add `_HAS_CXX20` comments. --- stl/inc/vector | 2 +- tests/std/tests/GH_000625_vector_bool_optimization/test.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/vector b/stl/inc/vector index 1e46ebe99ab..90854b7c0e3 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -3878,7 +3878,7 @@ _CONSTEXPR20 _OutIt _Copy_vbool(_VbIt _First, _VbIt _Last, _OutIt _Dest) { return _DestEnd; } } else -#endif +#endif // _HAS_CXX20 { // If _First and _Dest have matching char alignment, use memmove const auto _UnalignedFirstBits = _First._Myoff & _Vbase{7}; diff --git a/tests/std/tests/GH_000625_vector_bool_optimization/test.cpp b/tests/std/tests/GH_000625_vector_bool_optimization/test.cpp index 0c556390e8e..6569854d54d 100644 --- a/tests/std/tests/GH_000625_vector_bool_optimization/test.cpp +++ b/tests/std/tests/GH_000625_vector_bool_optimization/test.cpp @@ -1325,7 +1325,7 @@ static_assert(gh_005345<32>()); static_assert(gh_005345<43>()); static_assert(gh_005345<64>()); static_assert(gh_005345<120>()); -#endif +#endif // _HAS_CXX20 int main() { test_fill(); From f84703f306e0e67b0831aca99657afa69165ee09 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 19 Apr 2025 10:26:52 -0700 Subject: [PATCH 5/8] Rename to `_LastSourceVal`. --- stl/inc/vector | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/vector b/stl/inc/vector index 90854b7c0e3..1ef309dffa7 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -3871,8 +3871,8 @@ _CONSTEXPR20 _OutIt _Copy_vbool(_VbIt _First, _VbIt _Last, _OutIt _Dest) { } if (_Last._Myoff != 0) { - const auto _SourceVal = *_VbFirst & _LastSourceMask; - *_VbDest = (*_VbDest & _LastDestMask) | _SourceVal; + const auto _LastSourceVal = *_VbFirst & _LastSourceMask; + *_VbDest = (*_VbDest & _LastDestMask) | _LastSourceVal; } return _DestEnd; From 5dc648773eb0d395ef3b497f8157a69ed021bbe6 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 19 Apr 2025 10:30:13 -0700 Subject: [PATCH 6/8] Rename to `test_gh_5345()`, capture bug title in comment. --- .../GH_000625_vector_bool_optimization/test.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/tests/std/tests/GH_000625_vector_bool_optimization/test.cpp b/tests/std/tests/GH_000625_vector_bool_optimization/test.cpp index 6569854d54d..cac1f009ef2 100644 --- a/tests/std/tests/GH_000625_vector_bool_optimization/test.cpp +++ b/tests/std/tests/GH_000625_vector_bool_optimization/test.cpp @@ -1306,7 +1306,8 @@ void randomized_test_copy(mt19937_64& gen) { #if _HAS_CXX20 template -constexpr bool gh_005345() { +constexpr bool test_gh_5345() { + // GH-5345 : _Copy_vbool() mishandles vectors of size 32 and 64, revealed by constexpr Clang vector src(N, true); for (size_t i = 2; i != N; ++i) { @@ -1320,11 +1321,11 @@ constexpr bool gh_005345() { return src == dst; } -static_assert(gh_005345<17>()); -static_assert(gh_005345<32>()); -static_assert(gh_005345<43>()); -static_assert(gh_005345<64>()); -static_assert(gh_005345<120>()); +static_assert(test_gh_5345<17>()); +static_assert(test_gh_5345<32>()); +static_assert(test_gh_5345<43>()); +static_assert(test_gh_5345<64>()); +static_assert(test_gh_5345<120>()); #endif // _HAS_CXX20 int main() { From 865c7983aeacc1410ac47bb833a8d2685d0ceccb Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 19 Apr 2025 10:52:57 -0700 Subject: [PATCH 7/8] Test non-zero offsets. --- .../tests/GH_000625_vector_bool_optimization/test.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/std/tests/GH_000625_vector_bool_optimization/test.cpp b/tests/std/tests/GH_000625_vector_bool_optimization/test.cpp index cac1f009ef2..79e4a7a127d 100644 --- a/tests/std/tests/GH_000625_vector_bool_optimization/test.cpp +++ b/tests/std/tests/GH_000625_vector_bool_optimization/test.cpp @@ -1305,7 +1305,7 @@ void randomized_test_copy(mt19937_64& gen) { } #if _HAS_CXX20 -template +template constexpr bool test_gh_5345() { // GH-5345 : _Copy_vbool() mishandles vectors of size 32 and 64, revealed by constexpr Clang vector src(N, true); @@ -1317,15 +1317,20 @@ constexpr bool test_gh_5345() { } vector dst(N, false); - copy(src.begin(), src.end(), dst.begin()); - return src == dst; + copy(src.begin() + Offset, src.end(), dst.begin() + Offset); + return equal(src.begin() + Offset, src.end(), dst.begin() + Offset, dst.end()); } static_assert(test_gh_5345<17>()); +static_assert(test_gh_5345<17, 1>()); static_assert(test_gh_5345<32>()); +static_assert(test_gh_5345<32, 5>()); static_assert(test_gh_5345<43>()); +static_assert(test_gh_5345<43, 10>()); static_assert(test_gh_5345<64>()); +static_assert(test_gh_5345<64, 16>()); static_assert(test_gh_5345<120>()); +static_assert(test_gh_5345<120, 31>()); #endif // _HAS_CXX20 int main() { From 1b334e4a78a2cfad90d561d432502419bd0bd1a2 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 19 Apr 2025 11:24:10 -0700 Subject: [PATCH 8/8] Categorize libcxx failures. --- tests/libcxx/expected_results.txt | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 1b459e07c5a..2d96ceff630 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -656,14 +656,6 @@ std/input.output/string.streams/stringbuf/stringbuf.members/view.pass.cpp FAIL std/input.output/syncstream/syncbuf/syncstream.syncbuf.cons/dtor.pass.cpp FAIL std/input.output/syncstream/syncbuf/syncstream.syncbuf.members/emit.pass.cpp FAIL -# GH-5345: : _Copy_vbool() mishandles vectors of size 32 and 64, revealed by constexpr Clang -std/algorithms/alg.modifying.operations/alg.copy/copy.pass.cpp:2 FAIL -std/algorithms/alg.modifying.operations/alg.move/move.pass.cpp:2 FAIL -std/algorithms/alg.nonmodifying/alg.equal/equal.pass.cpp:0 FAIL -std/algorithms/alg.nonmodifying/alg.equal/equal.pass.cpp:1 FAIL -std/algorithms/alg.nonmodifying/alg.equal/ranges.equal.pass.cpp:0 FAIL -std/algorithms/alg.nonmodifying/alg.equal/ranges.equal.pass.cpp:1 FAIL - # *** VCRUNTIME BUGS *** @@ -1068,6 +1060,7 @@ std/utilities/utility/mem.res/mem.poly.allocator.class/mem.poly.allocator.mem/co # Not analyzed, failing due to constexpr step limits. std/algorithms/alg.modifying.operations/alg.copy/ranges.copy_backward.pass.cpp:2 FAIL +std/algorithms/alg.modifying.operations/alg.move/move.pass.cpp:2 FAIL std/algorithms/alg.modifying.operations/alg.rotate/rotate.pass.cpp FAIL std/algorithms/alg.nonmodifying/alg.contains/ranges.contains_subrange.pass.cpp:2 FAIL std/algorithms/alg.nonmodifying/alg.count/count.pass.cpp FAIL @@ -1199,6 +1192,15 @@ std/containers/views/mdspan/mdspan/index_operator.pass.cpp:1 FAIL std/utilities/utility/utility.swap/swap_array.pass.cpp:0 FAIL std/utilities/utility/utility.swap/swap_array.pass.cpp:1 FAIL +# Not analyzed. MSVC constexpr ICE. +std/algorithms/alg.nonmodifying/alg.equal/equal.pass.cpp:0 FAIL +std/algorithms/alg.nonmodifying/alg.equal/equal.pass.cpp:1 FAIL +std/algorithms/alg.nonmodifying/alg.equal/ranges.equal.pass.cpp:0 FAIL +std/algorithms/alg.nonmodifying/alg.equal/ranges.equal.pass.cpp:1 FAIL + +# Not analyzed. Possible Clang constexpr bug involving the test's sized_allocator and our check for transposed ranges. +std/algorithms/alg.modifying.operations/alg.copy/copy.pass.cpp:2 FAIL + # Not analyzed. SKIPPED because this is x86-specific, fatal error C1060: compiler is out of heap space std/algorithms/alg.modifying.operations/alg.transform/ranges.transform.binary.iterator.pass.cpp:0 SKIPPED std/algorithms/alg.modifying.operations/alg.transform/ranges.transform.binary.iterator.pass.cpp:1 SKIPPED