diff --git a/stl/inc/vector b/stl/inc/vector index 0e1f93e18d0..6d4811a8d5e 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -3738,7 +3738,11 @@ _NODISCARD _CONSTEXPR20 _VbIt _Find_vbool(_VbIt _First, const _VbIt _Last, const const auto _SourceMask = _FirstSourceMask & _LastSourceMask; const auto _SelectVal = (_Val ? *_VbFirst : ~*_VbFirst) & _SourceMask; const auto _Count = _Countr_zero(_SelectVal); - return _Count == _VBITS ? _Last : _First + static_cast<_Iter_diff_t<_VbIt>>(_Count - _First._Myoff); + if (_Count == _VBITS) { + return _Last; + } else { + return _First + static_cast<_Iter_diff_t<_VbIt>>(_Count - _First._Myoff); + } } const auto _FirstVal = (_Val ? *_VbFirst : ~*_VbFirst) & _FirstSourceMask; 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 c16091f24c2..c75796a0714 100644 --- a/tests/std/tests/GH_000625_vector_bool_optimization/test.cpp +++ b/tests/std/tests/GH_000625_vector_bool_optimization/test.cpp @@ -12,6 +12,12 @@ #include #include +#if _HAS_CXX20 +#define CONSTEXPR20 constexpr +#else +#define CONSTEXPR20 inline +#endif + #pragma warning(disable : 4365) // conversion from 'unsigned __int64' to 'const __int64', signed/unsigned mismatch using namespace std; @@ -20,7 +26,7 @@ constexpr int blockSize = 32; static_assert(blockSize == _VBITS, "Invalid block size"); // This test data is not random, but irregular enough to ensure confidence in the tests -const vector source = { // +constexpr bool source_raw[] = { // true, false, true, false, true, true, true, false, // true, false, true, false, true, true, true, false, // true, false, true, false, true, true, true, false, // @@ -39,8 +45,7 @@ const vector source = { // true, false, true, false, true, true, true, false, // true, false, true, false, true, true, true, false}; - -void test_fill_helper(const size_t length) { +CONSTEXPR20 void test_fill_helper(const size_t length) { // No offset { vector result_true(length, true); @@ -102,7 +107,7 @@ void test_fill_helper(const size_t length) { } } -bool test_fill() { +CONSTEXPR20 bool test_fill() { // Empty test_fill_helper(0); @@ -126,7 +131,7 @@ bool test_fill() { return true; } -void test_find_helper(const size_t length) { +CONSTEXPR20 void test_find_helper(const size_t length) { // No offset { vector input_true(length + 3, false); @@ -160,7 +165,7 @@ void test_find_helper(const size_t length) { } } -bool test_find() { +CONSTEXPR20 bool test_find() { // Empty range test_find_helper(0); @@ -178,10 +183,11 @@ bool test_find() { return true; } -void test_count_helper(const ptrdiff_t length) { +CONSTEXPR20 void test_count_helper(const ptrdiff_t length) { + const vector source(begin(source_raw), end(source_raw)); const int counts_true[] = {0, 1, 1, 2, 2, 3, 4, 5}; const int counts_false[] = {0, 0, 1, 1, 2, 2, 2, 2}; - const auto expected = div(static_cast(length), 8); + const div_t expected = {static_cast(length) / 8, static_cast(length) % 8}; // No offset { const auto result_true = static_cast(count(source.cbegin(), next(source.cbegin(), length), true)); @@ -203,7 +209,7 @@ void test_count_helper(const ptrdiff_t length) { } } -bool test_count() { +CONSTEXPR20 bool test_count() { // Empty range test_count_helper(0); @@ -259,7 +265,7 @@ void test_huge_vector_bool() { assert(count(v.begin(), v.end(), false) == large_bit_diff - 3); } -void test_copy_no_offset(const size_t length) { +CONSTEXPR20 void test_copy_no_offset(const size_t length) { vector result; switch (length) { case 3: @@ -304,6 +310,8 @@ void test_copy_no_offset(const size_t length) { assert(false); } + const vector source(begin(source_raw), end(source_raw)); + { vector dest(length, false); const auto res_copy = copy(source.begin(), next(source.begin(), length), dest.begin()); @@ -341,7 +349,7 @@ void test_copy_no_offset(const size_t length) { } } -void test_copy_offset_source(const size_t length) { +CONSTEXPR20 void test_copy_offset_source(const size_t length) { vector result; switch (length) { case 3: @@ -389,6 +397,8 @@ void test_copy_offset_source(const size_t length) { assert(false); } + const vector source(begin(source_raw), end(source_raw)); + { vector dest(length, false); const auto res_copy = copy(next(source.begin()), next(source.begin(), length + 1), dest.begin()); @@ -427,7 +437,7 @@ void test_copy_offset_source(const size_t length) { } } -void test_copy_offset_dest(const size_t length) { +CONSTEXPR20 void test_copy_offset_dest(const size_t length) { vector result; switch (length) { case 3: @@ -480,6 +490,8 @@ void test_copy_offset_dest(const size_t length) { assert(false); } + const vector source(begin(source_raw), end(source_raw)); + { vector dest(length + 1, false); const auto res_copy = copy(source.begin(), next(source.begin(), length), next(dest.begin())); @@ -517,7 +529,7 @@ void test_copy_offset_dest(const size_t length) { } } -void test_copy_offset_match(const size_t length) { +CONSTEXPR20 void test_copy_offset_match(const size_t length) { vector result; switch (length) { case 3: @@ -570,6 +582,8 @@ void test_copy_offset_match(const size_t length) { assert(false); } + const vector source(begin(source_raw), end(source_raw)); + { vector dest(length, false); const auto res_copy = copy(next(source.begin()), next(source.begin(), length), next(dest.begin())); @@ -608,7 +622,7 @@ void test_copy_offset_match(const size_t length) { } } -void test_copy_offset_mismatch_leftshift(const size_t length) { +CONSTEXPR20 void test_copy_offset_mismatch_leftshift(const size_t length) { vector result; switch (length) { case 3: @@ -661,6 +675,8 @@ void test_copy_offset_mismatch_leftshift(const size_t length) { assert(false); } + const vector source(begin(source_raw), end(source_raw)); + { vector dest(length + 1, false); const auto res_copy = copy(next(source.begin()), next(source.begin(), length), next(dest.begin(), 2)); @@ -699,7 +715,7 @@ void test_copy_offset_mismatch_leftshift(const size_t length) { } } -void test_copy_offset_mismatch_rightshift(const size_t length) { +CONSTEXPR20 void test_copy_offset_mismatch_rightshift(const size_t length) { vector result; switch (length) { case 3: @@ -754,6 +770,8 @@ void test_copy_offset_mismatch_rightshift(const size_t length) { assert(false); } + const vector source(begin(source_raw), end(source_raw)); + { vector dest(length, false); const auto res_copy = copy(next(source.begin(), 2), next(source.begin(), length + 1), next(dest.begin())); @@ -792,7 +810,7 @@ void test_copy_offset_mismatch_rightshift(const size_t length) { } } -void test_copy_offset_aligned(const size_t length) { +CONSTEXPR20 void test_copy_offset_aligned(const size_t length) { vector result; switch (length) { case 3: @@ -845,6 +863,8 @@ void test_copy_offset_aligned(const size_t length) { assert(false); } + const vector source(begin(source_raw), end(source_raw)); + { vector dest(length, false); const auto res_copy = copy(next(source.begin(), 9), next(source.begin(), length + 8), next(dest.begin())); @@ -883,7 +903,9 @@ void test_copy_offset_aligned(const size_t length) { } } -void test_copy_sub_char() { +CONSTEXPR20 void test_copy_sub_char() { + const vector source(begin(source_raw), end(source_raw)); + { // sub char copy unaligned const vector result = {false, false, true, false, true, false, false, false}; @@ -1092,7 +1114,7 @@ void test_copy_sub_char() { } } -void test_copy_regression() { +CONSTEXPR20 void test_copy_regression() { // This specific case was found by the randomized coverage below. const vector src = {0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, @@ -1115,7 +1137,8 @@ void test_copy_regression() { assert(dst == correct); } -bool test_copy() { +// Test copy() in multiple parts to stay within constexpr step limits. +CONSTEXPR20 bool test_copy_part_1() { test_copy_no_offset(3); test_copy_no_offset(8); test_copy_no_offset(22); @@ -1144,6 +1167,10 @@ bool test_copy() { test_copy_offset_match(32); test_copy_offset_match(67); + return true; +} + +CONSTEXPR20 bool test_copy_part_2() { test_copy_offset_mismatch_leftshift(3); test_copy_offset_mismatch_leftshift(8); test_copy_offset_mismatch_leftshift(22); @@ -1354,13 +1381,23 @@ 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>()); + +static_assert(test_fill()); +static_assert(test_find()); +static_assert(test_count()); + +#if defined(__clang__) || defined(__EDG__) // TRANSITION, VSO-2574489 +static_assert(test_copy_part_1()); +static_assert(test_copy_part_2()); +#endif // ^^^ no workaround ^^^ #endif // _HAS_CXX20 int main() { test_fill(); test_find(); test_count(); - test_copy(); + test_copy_part_1(); + test_copy_part_2(); test_huge_vector_bool();