[PATCH v3 2/5] libstdc++: Check prerequisite of extents::extents.

Luc Grosheintz luc.grosheintz@gmail.com
Mon Jul 7 09:15:14 GMT 2025



On 7/7/25 11:13, Tomasz Kaminski wrote:
> On Mon, Jul 7, 2025 at 11:09 AM Jonathan Wakely <jwakely@redhat.com> wrote:
> 
>> On Fri, 4 Jul 2025 at 09:30, Luc Grosheintz <luc.grosheintz@gmail.com>
>> wrote:
>>>
>>> Previously the prerequisite of the extents ctors that
>>>
>>>      static_extent(i) == dynamic_extent || extent(i) == other.extent(i).
>>>
>>> was not checked. This commit adds the __glibcxx_assert and test them.
>>>
>>> libstdc++-v3/ChangeLog:
>>>
>>>          * include/std/mdspan (extents): Check prerequisite 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 prerequisite.
>>>
>>> Signed-off-by: Luc Grosheintz <luc.grosheintz@gmail.com>
>>> ---
>>>   libstdc++-v3/include/std/mdspan               | 13 +++++++
>>>   .../mdspan/extents/class_mandates_neg.cc      |  2 ++
>>>   .../mdspan/extents/extents_mismatch_neg.cc    | 35 +++++++++++++++++++
>>>   3 files changed, 50 insertions(+)
>>>   create mode 100644
>> libstdc++-v3/testsuite/23_containers/mdspan/extents/extents_mismatch_neg.cc
>>>
>>> diff --git a/libstdc++-v3/include/std/mdspan
>> b/libstdc++-v3/include/std/mdspan
>>> index cf20553aaa5..1d6cdc93d80 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
>>
>> Was this intended to be a static member function?
>>
> Yes, it should be. I will also adjust that locally.

Indeed it should have been. Thanks!

> 
>>
>>> +         {
>>> +           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..67d18feda96 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
>>> @@ -7,6 +7,8 @@ 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" }
>>> +
>>>   // { 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" }
>>> diff --git
>> a/libstdc++-v3/testsuite/23_containers/mdspan/extents/extents_mismatch_neg.cc
>> b/libstdc++-v3/testsuite/23_containers/mdspan/extents/extents_mismatch_neg.cc
>>> new file mode 100644
>>> index 00000000000..b35e5310d41
>>> --- /dev/null
>>> +++
>> b/libstdc++-v3/testsuite/23_containers/mdspan/extents/extents_mismatch_neg.cc
>>> @@ -0,0 +1,35 @@
>>> +// { dg-do compile { target c++23 } }
>>> +#include<mdspan>
>>> +
>>> +#include <cstdint>
>>> +
>>> +constexpr size_t dyn = std::dynamic_extent;
>>> +
>>> +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 "non-constant condition for static assertion" }
>>> +// { dg-prune-output "__glibcxx_assert" }
>>> --
>>> 2.49.0
>>>
>>
>>
> 



More information about the Libstdc++ mailing list