On Fri, Jun 27, 2025 at 11:29 AM Luc Grosheintz <luc.groshei...@gmail.com> wrote:
> Previously the prerequite of the extents ctors that > > static_extent(i) == dynamic_extent || extent(i) == other.extent(i). > > was not checked. This commit add the __glibcxx_assert and test it. > > libstdc++-v3/ChangeLog: > > * include/std/mdspan (extents): Check prerequite of the ctor that > static_extent(i) == dynamic_extent || extent(i) == other.extent(i). > * testsuite/23_containers/mdspan/extents/class_mandates_neg.cc: > Test the implemented prerequite. > > Signed-off-by: Luc Grosheintz <luc.groshei...@gmail.com> > --- > LGTM. As in case of mdspan, I would put the constexpr _neg test in other file. > libstdc++-v3/include/std/mdspan | 13 ++++++++ > .../mdspan/extents/class_mandates_neg.cc | 31 +++++++++++++++++++ > 2 files changed, 44 insertions(+) > > diff --git a/libstdc++-v3/include/std/mdspan > b/libstdc++-v3/include/std/mdspan > index 39d02ac08df..e198d65bba3 100644 > --- a/libstdc++-v3/include/std/mdspan > +++ b/libstdc++-v3/include/std/mdspan > @@ -110,10 +110,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > return __se; > } > > + template<size_t _OtherRank, typename _GetOtherExtent> > + constexpr bool > + _S_is_compatible_extents(_GetOtherExtent __get_extent) noexcept > + { > + if constexpr (_OtherRank == _S_rank) > + for (size_t __i = 0; __i < _S_rank; ++__i) > + if (_Extents[__i] != dynamic_extent > + && !cmp_equal(_Extents[__i], > _S_int_cast(__get_extent(__i)))) > + return false; > + return true; > + } > + > template<size_t _OtherRank, typename _GetOtherExtent> > constexpr void > _M_init_dynamic_extents(_GetOtherExtent __get_extent) noexcept > { > + > __glibcxx_assert(_S_is_compatible_extents<_OtherRank>(__get_extent)); > for (size_t __i = 0; __i < _S_rank_dynamic; ++__i) > { > size_t __di = __i; > diff --git > a/libstdc++-v3/testsuite/23_containers/mdspan/extents/class_mandates_neg.cc > b/libstdc++-v3/testsuite/23_containers/mdspan/extents/class_mandates_neg.cc > index f9c1c019666..8179ff39962 100644 > --- > a/libstdc++-v3/testsuite/23_containers/mdspan/extents/class_mandates_neg.cc > +++ > b/libstdc++-v3/testsuite/23_containers/mdspan/extents/class_mandates_neg.cc > @@ -3,10 +3,41 @@ > > #include <cstdint> > > +constexpr size_t dyn = std::dynamic_extent; > + > std::extents<uint8_t, size_t(1) << 9> e1; // { dg-error "from here" } > std::extents<char, 1> e2; // { dg-error "from here" } > std::extents<bool, 1> e3; // { dg-error "from here" } > std::extents<double, 1> e4; // { dg-error "from here" } > + > +constexpr bool > +test_dyn2sta_extents_mismatch_00() > +{ > + auto e0 = std::extents<int, dyn>{1}; > + [[maybe_unused]] auto e1 = std::extents<int, 2>{e0}; // { > dg-error "expansion of" } > + return true; > +} > +static_assert(test_dyn2sta_extents_mismatch_00()); // { > dg-error "expansion of" } > + > +constexpr bool > +test_dyn2sta_extents_mismatch_01() > +{ > + [[maybe_unused]] auto e = std::extents<int, 1, dyn>{2, 2}; // { > dg-error "expansion of" } > + return true; > +} > +static_assert(test_dyn2sta_extents_mismatch_01()); // { > dg-error "expansion of" } > + > +constexpr bool > +test_dyn2sta_extents_mismatch_02() > +{ > + std::array<int, 2> exts{2, 2}; > + [[maybe_unused]] auto e = std::extents<int, 1, dyn>{exts}; // { > dg-error "expansion of" } > + return true; > +} > +static_assert(test_dyn2sta_extents_mismatch_02()); // { > dg-error "expansion of" } > + > // { dg-prune-output "dynamic or representable as IndexType" } > // { dg-prune-output "signed or unsigned integer" } > // { dg-prune-output "invalid use of incomplete type" } > +// { dg-prune-output "non-constant condition for static assertion" } > +// { dg-prune-output "__glibcxx_assert" } > -- > 2.49.0 > >