From da9aad99a1865968f41423f0691abe545229aba9 Mon Sep 17 00:00:00 2001 From: Jakub Mazurkiewicz Date: Sun, 14 May 2023 23:15:56 +0200 Subject: [PATCH 1/2] New checks! --- stl/inc/mdspan | 23 +++++++++++++++++++ .../test.cpp | 7 ++++++ .../test.cpp | 7 ++++++ .../test.cpp | 7 ++++++ 4 files changed, 44 insertions(+) diff --git a/stl/inc/mdspan b/stl/inc/mdspan index 670f641c47e..fbd4574c0e0 100644 --- a/stl/inc/mdspan +++ b/stl/inc/mdspan @@ -256,6 +256,17 @@ public: return true; } } + + template + _NODISCARD constexpr bool _Contains_multidimensional_index( + index_sequence<_Seq...>, _IndexTypes... _Indices) const noexcept { + _STL_INTERNAL_STATIC_ASSERT((same_as<_IndexTypes, index_type> && ...)); + if constexpr (unsigned_integral) { + return ((_Indices < extent(_Seq)) && ...); + } else { + return ((0 <= _Indices && _Indices < extent(_Seq)) && ...); + } + } }; template @@ -379,6 +390,10 @@ public: requires (sizeof...(_IndexTypes) == extents_type::rank()) && (is_convertible_v<_IndexTypes, index_type> && ...) && (is_nothrow_constructible_v && ...) _NODISCARD constexpr index_type operator()(_IndexTypes... _Indices) const noexcept { + _STL_VERIFY(_Exts._Contains_multidimensional_index( + make_index_sequence{}, static_cast(_Indices)...), + "Value of extents_type::index-cast(i) must be a multidimensional index in extents_ (N4950 " + "[mdspan.layout.left.obs]/3)."); return _Index_impl(make_index_sequence{}, static_cast(_Indices)...); } @@ -512,6 +527,10 @@ public: requires (sizeof...(_IndexTypes) == extents_type::rank()) && (is_convertible_v<_IndexTypes, index_type> && ...) && (is_nothrow_constructible_v && ...) _NODISCARD constexpr index_type operator()(_IndexTypes... _Indices) const noexcept { + _STL_VERIFY(_Exts._Contains_multidimensional_index( + make_index_sequence{}, static_cast(_Indices)...), + "Value of extents_type::index-cast(i) must be a multidimensional index in extents_ (N4950 " + "[mdspan.layout.right.obs]/3)."); return _Index_impl(make_index_sequence{}, static_cast(_Indices)...); } @@ -698,6 +717,10 @@ public: requires (sizeof...(_IndexTypes) == extents_type::rank()) && (is_convertible_v<_IndexTypes, index_type> && ...) && (is_nothrow_constructible_v && ...) _NODISCARD constexpr index_type operator()(_IndexTypes... _Indices) const noexcept { + _STL_VERIFY(_Exts._Contains_multidimensional_index( + make_index_sequence{}, static_cast(_Indices)...), + "Value of extents_type::index-cast(i) must be a multidimensional index in extents_ (N4950 " + "[mdspan.layout.stride.obs]/3)."); return _Index_impl(make_index_sequence{}, static_cast(_Indices)...); } diff --git a/tests/std/tests/P0009R18_mdspan_layout_left_death/test.cpp b/tests/std/tests/P0009R18_mdspan_layout_left_death/test.cpp index 90425880ec9..4ffb2d8d6b0 100644 --- a/tests/std/tests/P0009R18_mdspan_layout_left_death/test.cpp +++ b/tests/std/tests/P0009R18_mdspan_layout_left_death/test.cpp @@ -38,6 +38,12 @@ void test_construction_from_other_stride_mapping_2() { layout_left::mapping> m2{m1}; } +void test_call_operator() { + layout_left::mapping> m; + // Value of extents_type::index-cast(i) must be a multidimensional index in extents_ + (void) m(2, 3, 5); +} + void test_stride_function() { layout_left::mapping> m; // Value of i must be less than extents_type::rank() @@ -52,6 +58,7 @@ int main(int argc, char* argv[]) { test_construction_from_other_right_mapping, test_construction_from_other_stride_mapping_1, test_construction_from_other_stride_mapping_2, + test_call_operator, test_stride_function, }); return exec.run(argc, argv); diff --git a/tests/std/tests/P0009R18_mdspan_layout_right_death/test.cpp b/tests/std/tests/P0009R18_mdspan_layout_right_death/test.cpp index aed180045f9..254ea565805 100644 --- a/tests/std/tests/P0009R18_mdspan_layout_right_death/test.cpp +++ b/tests/std/tests/P0009R18_mdspan_layout_right_death/test.cpp @@ -38,6 +38,12 @@ void test_construction_from_other_stride_mapping_2() { layout_right::mapping> m2{m1}; } +void test_call_operator() { + layout_right::mapping> m; + // Value of extents_type::index-cast(i) must be a multidimensional index in extents_ + (void) m(4, 3, 3); +} + void test_stride_function() { layout_right::mapping> m; // Value of i must be less than extents_type::rank() @@ -52,6 +58,7 @@ int main(int argc, char* argv[]) { test_construction_from_other_left_mapping, test_construction_from_other_stride_mapping_1, test_construction_from_other_stride_mapping_2, + test_call_operator, test_stride_function, }); return exec.run(argc, argv); diff --git a/tests/std/tests/P0009R18_mdspan_layout_stride_death/test.cpp b/tests/std/tests/P0009R18_mdspan_layout_stride_death/test.cpp index eadd0d3a499..25325067306 100644 --- a/tests/std/tests/P0009R18_mdspan_layout_stride_death/test.cpp +++ b/tests/std/tests/P0009R18_mdspan_layout_stride_death/test.cpp @@ -27,6 +27,12 @@ void test_construction_from_strided_layout_mapping() { [[maybe_unused]] layout_stride::mapping> m2{m1}; } +void test_call_operator() { + layout_stride::mapping> m; + // Value of extents_type::index-cast(i) must be a multidimensional index in extents_ + (void) m(4, 3, 3); +} + int main(int argc, char* argv[]) { std_testing::death_test_executive exec; exec.add_death_tests({ @@ -34,6 +40,7 @@ int main(int argc, char* argv[]) { test_construction_from_extents_and_array, test_construction_from_extents_and_span, test_construction_from_strided_layout_mapping, + test_call_operator, }); return exec.run(argc, argv); } From dbb1a61ca35de9b2a068bbe383b87c99855d55a5 Mon Sep 17 00:00:00 2001 From: Jakub Mazurkiewicz Date: Sun, 14 May 2023 23:49:23 +0200 Subject: [PATCH 2/2] New checks detected a bug in the tests! --- tests/std/tests/P0009R18_mdspan_layout_left/test.cpp | 2 +- tests/std/tests/P0009R18_mdspan_layout_right/test.cpp | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/std/tests/P0009R18_mdspan_layout_left/test.cpp b/tests/std/tests/P0009R18_mdspan_layout_left/test.cpp index 5b77ab17606..19304710319 100644 --- a/tests/std/tests/P0009R18_mdspan_layout_left/test.cpp +++ b/tests/std/tests/P0009R18_mdspan_layout_left/test.cpp @@ -330,7 +330,7 @@ constexpr void check_correctness() { assert(tensor(2, 0, 0) == 2); assert(tensor(1, 1, 1) == 10); assert(tensor(0, 0, 3) == 18); - assert(tensor(2, 2, 2) == 20); + assert(tensor(2, 1, 2) == 17); assert(tensor(2, 1, 3) == 23); } diff --git a/tests/std/tests/P0009R18_mdspan_layout_right/test.cpp b/tests/std/tests/P0009R18_mdspan_layout_right/test.cpp index 64f2e77f2ca..a80d1b80808 100644 --- a/tests/std/tests/P0009R18_mdspan_layout_right/test.cpp +++ b/tests/std/tests/P0009R18_mdspan_layout_right/test.cpp @@ -51,8 +51,7 @@ constexpr void check_members(const extents& ext, index_se using Ext2 = extents; using Mapping2 = layout_right::mapping; -#pragma warning(push) // TRANSITION, "/analyze:only" BUG? -#pragma warning(disable : 28020) // The expression '0<=_Param_(1)&&_Param_(1)<=1-1' is not true at this call +#ifndef __clang__ // FIXME, Clang suddenly cannot digest this { // Check construction from other layout_right::mapping Mapping m1{ext}; Mapping2 m2{m1}; @@ -60,6 +59,7 @@ constexpr void check_members(const extents& ext, index_se static_assert(is_nothrow_constructible_v); // Other tests are defined in 'check_construction_from_other_right_mapping' function } +#endif { // Check construction from layout_left::mapping using LeftMapping = layout_left::mapping; @@ -82,7 +82,10 @@ constexpr void check_members(const extents& ext, index_se if constexpr (Ext::rank() > 0) { strides.back() = 1; for (size_t i = Ext::rank() - 1; i-- > 0;) { +#pragma warning(push) +#pragma warning(disable : 28020) // TRANSITION, DevCom-923103 strides[i] = static_cast(strides[i + 1] * ext.extent(i + 1)); +#pragma warning(pop) } } @@ -140,7 +143,6 @@ constexpr void check_members(const extents& ext, index_se assert(!(m != m)); // Other tests are defined in 'check_comparisons' function } -#pragma warning(pop) // TRANSITION, "/analyze:only" BUG? } constexpr void check_construction_from_other_right_mapping() {