@@ -171,11 +171,14 @@ struct __maybe_static_array {
171
171
_TStatic __static_val = _StaticValues::__get (__i);
172
172
if (__static_val == _DynTag) {
173
173
__dyn_vals_[_DynamicIdxMap::__get (__i)] = __values[__i];
174
- }
175
- // Precondition check
176
- else
177
- _LIBCPP_ASSERT_UNCATEGORIZED (__values[__i] == static_cast <_TDynamic>(__static_val),
178
- " extents construction: mismatch of provided arguments with static extents." );
174
+ } else
175
+ // Not catching this could lead to out of bounds errors later
176
+ // e.g. using my_mdspan_t = mdspan<int, extents<int, 10>>; my_mdspan_t = m(new int[5], 5);
177
+ // Right-hand-side construction looks ok with allocation and size matching,
178
+ // but since (potentially elsewhere defined) my_mdspan_t has static size m now thinks its range is 10 not 5
179
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS (
180
+ __values[__i] == static_cast <_TDynamic>(__static_val),
181
+ " extents construction: mismatch of provided arguments with static extents." );
179
182
}
180
183
}
181
184
@@ -187,11 +190,14 @@ struct __maybe_static_array {
187
190
_TStatic __static_val = _StaticValues::__get (__i);
188
191
if (__static_val == _DynTag) {
189
192
__dyn_vals_[_DynamicIdxMap::__get (__i)] = static_cast <_TDynamic>(__vals[__i]);
190
- }
191
- // Precondition check
192
- else
193
- _LIBCPP_ASSERT_UNCATEGORIZED (static_cast <_TDynamic>(__vals[__i]) == static_cast <_TDynamic>(__static_val),
194
- " extents construction: mismatch of provided arguments with static extents." );
193
+ } else
194
+ // Not catching this could lead to out of bounds errors later
195
+ // e.g. using my_mdspan_t = mdspan<int, extents<int, 10>>; my_mdspan_t = m(new int[N], span<int,1>(&N));
196
+ // Right-hand-side construction looks ok with allocation and size matching,
197
+ // but since (potentially elsewhere defined) my_mdspan_t has static size m now thinks its range is 10 not N
198
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS (
199
+ static_cast <_TDynamic>(__vals[__i]) == static_cast <_TDynamic>(__static_val),
200
+ " extents construction: mismatch of provided arguments with static extents." );
195
201
}
196
202
}
197
203
@@ -310,8 +316,10 @@ class extents {
310
316
(sizeof ...(_OtherIndexTypes) == __rank_ || sizeof ...(_OtherIndexTypes) == __rank_dynamic_))
311
317
_LIBCPP_HIDE_FROM_ABI constexpr explicit extents (_OtherIndexTypes... __dynvals) noexcept
312
318
: __vals_(static_cast <index_type>(__dynvals)...) {
313
- _LIBCPP_ASSERT_UNCATEGORIZED (__mdspan_detail::__are_representable_as<index_type>(__dynvals...),
314
- " extents ctor: arguments must be representable as index_type and nonnegative" );
319
+ // Not catching this could lead to out of bounds errors later
320
+ // e.g. mdspan m(ptr, dextents<char, 1>(200u)); leads to an extent of -56 on m
321
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS (__mdspan_detail::__are_representable_as<index_type>(__dynvals...),
322
+ " extents ctor: arguments must be representable as index_type and nonnegative" );
315
323
}
316
324
317
325
template <class _OtherIndexType , size_t _Size>
@@ -321,8 +329,10 @@ class extents {
321
329
explicit (_Size != __rank_dynamic_)
322
330
_LIBCPP_HIDE_FROM_ABI constexpr extents (const array<_OtherIndexType, _Size>& __exts) noexcept
323
331
: __vals_(span(__exts)) {
324
- _LIBCPP_ASSERT_UNCATEGORIZED (__mdspan_detail::__are_representable_as<index_type>(span (__exts)),
325
- " extents ctor: arguments must be representable as index_type and nonnegative" );
332
+ // Not catching this could lead to out of bounds errors later
333
+ // e.g. mdspan m(ptr, dextents<char, 1>(array<unsigned,1>(200))); leads to an extent of -56 on m
334
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS (__mdspan_detail::__are_representable_as<index_type>(span (__exts)),
335
+ " extents ctor: arguments must be representable as index_type and nonnegative" );
326
336
}
327
337
328
338
template <class _OtherIndexType , size_t _Size>
@@ -332,8 +342,11 @@ class extents {
332
342
explicit (_Size != __rank_dynamic_)
333
343
_LIBCPP_HIDE_FROM_ABI constexpr extents (const span<_OtherIndexType, _Size>& __exts) noexcept
334
344
: __vals_(__exts) {
335
- _LIBCPP_ASSERT_UNCATEGORIZED (__mdspan_detail::__are_representable_as<index_type>(__exts),
336
- " extents ctor: arguments must be representable as index_type and nonnegative" );
345
+ // Not catching this could lead to out of bounds errors later
346
+ // e.g. array a{200u}; mdspan<int, dextents<char,1>> m(ptr, extents(span<unsigned,1>(a))); leads to an extent of -56
347
+ // on m
348
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS (__mdspan_detail::__are_representable_as<index_type>(__exts),
349
+ " extents ctor: arguments must be representable as index_type and nonnegative" );
337
350
}
338
351
339
352
private:
@@ -382,10 +395,16 @@ class extents {
382
395
for (size_t __r = 0 ; __r < rank (); __r++) {
383
396
if constexpr (static_cast <make_unsigned_t <index_type>>(numeric_limits<index_type>::max ()) <
384
397
static_cast <make_unsigned_t <_OtherIndexType>>(numeric_limits<_OtherIndexType>::max ())) {
385
- _LIBCPP_ASSERT_UNCATEGORIZED (__mdspan_detail::__is_representable_as<index_type>(__other.extent (__r)),
386
- " extents ctor: arguments must be representable as index_type and nonnegative" );
398
+ // Not catching this could lead to out of bounds errors later
399
+ // e.g. dextents<char,1>> e(dextents<unsigned,1>(200)) leads to an extent of -56 on e
400
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS (
401
+ __mdspan_detail::__is_representable_as<index_type>(__other.extent (__r)),
402
+ " extents ctor: arguments must be representable as index_type and nonnegative" );
387
403
}
388
- _LIBCPP_ASSERT_UNCATEGORIZED (
404
+ // Not catching this could lead to out of bounds errors later
405
+ // e.g. mdspan<int, extents<int, 10>> m = mdspan<int, dextents<int, 1>>(new int[5], 5);
406
+ // Right-hand-side construction was ok, but m now thinks its range is 10 not 5
407
+ _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS (
389
408
(_Values::__static_value (__r) == dynamic_extent) ||
390
409
(static_cast <index_type>(__other.extent (__r)) == static_cast <index_type>(_Values::__static_value (__r))),
391
410
" extents construction: mismatch of provided arguments with static extents." );
0 commit comments