diff options
Diffstat (limited to 'contrib/llvm-project/libcxx/include/__mdspan/extents.h')
-rw-r--r-- | contrib/llvm-project/libcxx/include/__mdspan/extents.h | 63 |
1 files changed, 42 insertions, 21 deletions
diff --git a/contrib/llvm-project/libcxx/include/__mdspan/extents.h b/contrib/llvm-project/libcxx/include/__mdspan/extents.h index 42355678d60c..a510220d4096 100644 --- a/contrib/llvm-project/libcxx/include/__mdspan/extents.h +++ b/contrib/llvm-project/libcxx/include/__mdspan/extents.h @@ -171,11 +171,14 @@ public: _TStatic __static_val = _StaticValues::__get(__i); if (__static_val == _DynTag) { __dyn_vals_[_DynamicIdxMap::__get(__i)] = __values[__i]; - } - // Precondition check - else - _LIBCPP_ASSERT_UNCATEGORIZED(__values[__i] == static_cast<_TDynamic>(__static_val), - "extents construction: mismatch of provided arguments with static extents."); + } else + // Not catching this could lead to out of bounds errors later + // e.g. using my_mdspan_t = mdspan<int, extents<int, 10>>; my_mdspan_t = m(new int[5], 5); + // Right-hand-side construction looks ok with allocation and size matching, + // but since (potentially elsewhere defined) my_mdspan_t has static size m now thinks its range is 10 not 5 + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + __values[__i] == static_cast<_TDynamic>(__static_val), + "extents construction: mismatch of provided arguments with static extents."); } } @@ -187,11 +190,14 @@ public: _TStatic __static_val = _StaticValues::__get(__i); if (__static_val == _DynTag) { __dyn_vals_[_DynamicIdxMap::__get(__i)] = static_cast<_TDynamic>(__vals[__i]); - } - // Precondition check - else - _LIBCPP_ASSERT_UNCATEGORIZED(static_cast<_TDynamic>(__vals[__i]) == static_cast<_TDynamic>(__static_val), - "extents construction: mismatch of provided arguments with static extents."); + } else + // Not catching this could lead to out of bounds errors later + // e.g. using my_mdspan_t = mdspan<int, extents<int, 10>>; my_mdspan_t = m(new int[N], span<int,1>(&N)); + // Right-hand-side construction looks ok with allocation and size matching, + // but since (potentially elsewhere defined) my_mdspan_t has static size m now thinks its range is 10 not N + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + static_cast<_TDynamic>(__vals[__i]) == static_cast<_TDynamic>(__static_val), + "extents construction: mismatch of provided arguments with static extents."); } } @@ -310,28 +316,37 @@ public: (sizeof...(_OtherIndexTypes) == __rank_ || sizeof...(_OtherIndexTypes) == __rank_dynamic_)) _LIBCPP_HIDE_FROM_ABI constexpr explicit extents(_OtherIndexTypes... __dynvals) noexcept : __vals_(static_cast<index_type>(__dynvals)...) { - _LIBCPP_ASSERT_UNCATEGORIZED(__mdspan_detail::__are_representable_as<index_type>(__dynvals...), - "extents ctor: arguments must be representable as index_type and nonnegative"); + // Not catching this could lead to out of bounds errors later + // e.g. mdspan m(ptr, dextents<char, 1>(200u)); leads to an extent of -56 on m + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__mdspan_detail::__are_representable_as<index_type>(__dynvals...), + "extents ctor: arguments must be representable as index_type and nonnegative"); } template <class _OtherIndexType, size_t _Size> - requires(is_convertible_v<_OtherIndexType, index_type> && is_nothrow_constructible_v<index_type, _OtherIndexType> && + requires(is_convertible_v<const _OtherIndexType&, index_type> && + is_nothrow_constructible_v<index_type, const _OtherIndexType&> && (_Size == __rank_ || _Size == __rank_dynamic_)) explicit(_Size != __rank_dynamic_) _LIBCPP_HIDE_FROM_ABI constexpr extents(const array<_OtherIndexType, _Size>& __exts) noexcept : __vals_(span(__exts)) { - _LIBCPP_ASSERT_UNCATEGORIZED(__mdspan_detail::__are_representable_as<index_type>(span(__exts)), - "extents ctor: arguments must be representable as index_type and nonnegative"); + // Not catching this could lead to out of bounds errors later + // e.g. mdspan m(ptr, dextents<char, 1>(array<unsigned,1>(200))); leads to an extent of -56 on m + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__mdspan_detail::__are_representable_as<index_type>(span(__exts)), + "extents ctor: arguments must be representable as index_type and nonnegative"); } template <class _OtherIndexType, size_t _Size> - requires(is_convertible_v<_OtherIndexType, index_type> && is_nothrow_constructible_v<index_type, _OtherIndexType> && + requires(is_convertible_v<const _OtherIndexType&, index_type> && + is_nothrow_constructible_v<index_type, const _OtherIndexType&> && (_Size == __rank_ || _Size == __rank_dynamic_)) explicit(_Size != __rank_dynamic_) _LIBCPP_HIDE_FROM_ABI constexpr extents(const span<_OtherIndexType, _Size>& __exts) noexcept : __vals_(__exts) { - _LIBCPP_ASSERT_UNCATEGORIZED(__mdspan_detail::__are_representable_as<index_type>(__exts), - "extents ctor: arguments must be representable as index_type and nonnegative"); + // Not catching this could lead to out of bounds errors later + // e.g. array a{200u}; mdspan<int, dextents<char,1>> m(ptr, extents(span<unsigned,1>(a))); leads to an extent of -56 + // on m + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__mdspan_detail::__are_representable_as<index_type>(__exts), + "extents ctor: arguments must be representable as index_type and nonnegative"); } private: @@ -380,10 +395,16 @@ public: for (size_t __r = 0; __r < rank(); __r++) { if constexpr (static_cast<make_unsigned_t<index_type>>(numeric_limits<index_type>::max()) < static_cast<make_unsigned_t<_OtherIndexType>>(numeric_limits<_OtherIndexType>::max())) { - _LIBCPP_ASSERT_UNCATEGORIZED(__mdspan_detail::__is_representable_as<index_type>(__other.extent(__r)), - "extents ctor: arguments must be representable as index_type and nonnegative"); + // Not catching this could lead to out of bounds errors later + // e.g. dextents<char,1>> e(dextents<unsigned,1>(200)) leads to an extent of -56 on e + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( + __mdspan_detail::__is_representable_as<index_type>(__other.extent(__r)), + "extents ctor: arguments must be representable as index_type and nonnegative"); } - _LIBCPP_ASSERT_UNCATEGORIZED( + // Not catching this could lead to out of bounds errors later + // e.g. mdspan<int, extents<int, 10>> m = mdspan<int, dextents<int, 1>>(new int[5], 5); + // Right-hand-side construction was ok, but m now thinks its range is 10 not 5 + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( (_Values::__static_value(__r) == dynamic_extent) || (static_cast<index_type>(__other.extent(__r)) == static_cast<index_type>(_Values::__static_value(__r))), "extents construction: mismatch of provided arguments with static extents."); |