From: Luc Grosheintz Date: Fri, 4 Jul 2025 08:29:43 +0000 (+0200) Subject: libstdc++: Check prerequisites of layout_*::operator(). X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4d86e4cda01aa3ab60de164a8492a99bc9ca1f70;p=thirdparty%2Fgcc.git libstdc++: Check prerequisites of layout_*::operator(). Previously, the prerequisite that the arguments passed to operator() are a multi-dimensional index (of extents()) was not checked. Both mapping::operator() and mdspan::operator[] have the same prerequisite. Since, mdspan must check the prerequisite for user-defined layout mappings, the preference is to check in mdspan. Because out-of-bounds accesses are very common it's nevertheless useful to check the prerequisite in mapping::operator(). This is relevant for cases where the layout mappings are used without mdspan. This commit checks the prerequisites via _GLIBCXX_DEBUG_ASSERTs and adds the required tests. More discussion in the email chain starting at: https://gcc.gnu.org/pipermail/libstdc++/2025-July/062265.html libstdc++-v3/ChangeLog: * include/std/mdspan: Check prerequisites of layout_*::operator() with _GLIBCXX_DEBUG_ASSERTs. * testsuite/23_containers/mdspan/layouts/debug/out_of_bounds_neg.cc: Add tests for prerequisites. Reviewed-by: Tomasz KamiƄski Signed-off-by: Luc Grosheintz --- diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan index 4a06fb2d3a8..1fdcae63441 100644 --- a/libstdc++-v3/include/std/mdspan +++ b/libstdc++-v3/include/std/mdspan @@ -441,6 +441,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _IndexType __mult = 1; auto __update = [&, __pos = 0u](_IndexType __idx) mutable { + _GLIBCXX_DEBUG_ASSERT(cmp_less(__idx, __exts.extent(__pos))); __res += __idx * __mult; __mult *= __exts.extent(__pos); ++__pos; @@ -651,6 +652,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION auto __update = [&, __pos = __exts.rank()](_IndexType) mutable { --__pos; + _GLIBCXX_DEBUG_ASSERT(cmp_less(__ind_arr[__pos], + __exts.extent(__pos))); __res += __ind_arr[__pos] * __mult; __mult *= __exts.extent(__pos); }; @@ -822,6 +825,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { auto __update = [&, __pos = 0u](_IndexType __idx) mutable { + _GLIBCXX_DEBUG_ASSERT(cmp_less(__idx, + __m.extents().extent(__pos))); __res += __idx * __m.stride(__pos++); }; (__update(__indices), ...); diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/layouts/debug/out_of_bounds_neg.cc b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/debug/out_of_bounds_neg.cc new file mode 100644 index 00000000000..fb8ff01e8aa --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/mdspan/layouts/debug/out_of_bounds_neg.cc @@ -0,0 +1,30 @@ +// { dg-do compile { target c++23 } } +// { dg-require-debug-mode "" } +#include + +template + constexpr bool + test_out_of_bounds_1d() + { + auto m = typename Layout::mapping>{}; + (void) m(0); // { dg-error "expansion of" } + return true; + } +static_assert(test_out_of_bounds_1d()); // { dg-error "expansion of" } +static_assert(test_out_of_bounds_1d()); // { dg-error "expansion of" } +static_assert(test_out_of_bounds_1d()); // { dg-error "expansion of" } + +template + constexpr bool + test_out_of_bounds_3d() + { + auto m = typename Layout::mapping>{}; + (void) m(2, 5, 5); // { dg-error "expansion of" } + return true; + } +static_assert(test_out_of_bounds_3d()); // { dg-error "expansion of" } +static_assert(test_out_of_bounds_3d()); // { dg-error "expansion of" } +static_assert(test_out_of_bounds_3d()); // { dg-error "expansion of" } + +// { dg-prune-output "non-constant condition for static assertion" } +// { dg-prune-output "__glibcxx_assert" }