Skip to content

Commit 74e70ba

Browse files
[libc++] Disallow character types being index types of extents (llvm#105832)
llvm#78086 provided the trait we want to use for this: `__libcpp_integer`. In some `libcxx/containers/views/mdspan` tests, improper uses of `char` are replaced with `signed char`. Fixes llvm#73715
1 parent ee764a2 commit 74e70ba

18 files changed

+114
-56
lines changed

libcxx/include/__mdspan/extents.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
#include <__assert>
2121
#include <__config>
22+
23+
#include <__concepts/arithmetic.h>
2224
#include <__type_traits/common_type.h>
2325
#include <__type_traits/is_convertible.h>
2426
#include <__type_traits/is_nothrow_constructible.h>
@@ -282,8 +284,7 @@ class extents {
282284
using size_type = make_unsigned_t<index_type>;
283285
using rank_type = size_t;
284286

285-
static_assert(is_integral<index_type>::value && !is_same<index_type, bool>::value,
286-
"extents::index_type must be a signed or unsigned integer type");
287+
static_assert(__libcpp_integer<index_type>, "extents::index_type must be a signed or unsigned integer type");
287288
static_assert(((__mdspan_detail::__is_representable_as<index_type>(_Extents) || (_Extents == dynamic_extent)) && ...),
288289
"extents ctor: arguments must be representable as index_type and nonnegative");
289290

libcxx/test/libcxx/containers/views/mdspan/extents/assert.conversion.pass.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ int main(int, char**) {
5050
}
5151
// value out of range
5252
{
53-
TEST_LIBCPP_ASSERT_FAILURE(([=] { std::extents<char, D, 5> e(arg); }()),
53+
TEST_LIBCPP_ASSERT_FAILURE(([=] { std::extents<signed char, D, 5> e(arg); }()),
5454
"extents ctor: arguments must be representable as index_type and nonnegative");
5555
}
5656
return 0;

libcxx/test/libcxx/containers/views/mdspan/extents/assert.ctor_from_array.pass.cpp

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,19 +51,13 @@ int main(int, char**) {
5151
}
5252
// value out of range
5353
{
54-
TEST_LIBCPP_ASSERT_FAILURE(
55-
([] {
56-
std::extents<char, D, 5> e1(std::array{1000, 5});
57-
}()),
58-
"extents ctor: arguments must be representable as index_type and nonnegative");
54+
TEST_LIBCPP_ASSERT_FAILURE(([] { std::extents<signed char, D, 5> e1(std::array{1000, 5}); }()),
55+
"extents ctor: arguments must be representable as index_type and nonnegative");
5956
}
6057
// negative value
6158
{
62-
TEST_LIBCPP_ASSERT_FAILURE(
63-
([] {
64-
std::extents<char, D, 5> e1(std::array{-1, 5});
65-
}()),
66-
"extents ctor: arguments must be representable as index_type and nonnegative");
59+
TEST_LIBCPP_ASSERT_FAILURE(([] { std::extents<signed char, D, 5> e1(std::array{-1, 5}); }()),
60+
"extents ctor: arguments must be representable as index_type and nonnegative");
6761
}
6862
return 0;
6963
}

libcxx/test/libcxx/containers/views/mdspan/extents/assert.ctor_from_integral.pass.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,12 @@ int main(int, char**) {
5050
}
5151
// value out of range
5252
{
53-
TEST_LIBCPP_ASSERT_FAILURE(([] { std::extents<char, D, 5> e1(1000, 5); }()),
53+
TEST_LIBCPP_ASSERT_FAILURE(([] { std::extents<signed char, D, 5> e1(1000, 5); }()),
5454
"extents ctor: arguments must be representable as index_type and nonnegative");
5555
}
5656
// negative value
5757
{
58-
TEST_LIBCPP_ASSERT_FAILURE(([] { std::extents<char, D, 5> e1(-1, 5); }()),
58+
TEST_LIBCPP_ASSERT_FAILURE(([] { std::extents<signed char, D, 5> e1(-1, 5); }()),
5959
"extents ctor: arguments must be representable as index_type and nonnegative");
6060
}
6161
return 0;

libcxx/test/libcxx/containers/views/mdspan/extents/assert.ctor_from_span.pass.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,13 @@ int main(int, char**) {
4949
// value out of range
5050
{
5151
std::array args{1000, 5};
52-
TEST_LIBCPP_ASSERT_FAILURE(([=] { std::extents<char, D, 5> e1(std::span{args}); }()),
52+
TEST_LIBCPP_ASSERT_FAILURE(([=] { std::extents<signed char, D, 5> e1(std::span{args}); }()),
5353
"extents ctor: arguments must be representable as index_type and nonnegative");
5454
}
5555
// negative value
5656
{
5757
std::array args{-1, 5};
58-
TEST_LIBCPP_ASSERT_FAILURE(([=] { std::extents<char, D, 5> e1(std::span{args}); }()),
58+
TEST_LIBCPP_ASSERT_FAILURE(([=] { std::extents<signed char, D, 5> e1(std::span{args}); }()),
5959
"extents ctor: arguments must be representable as index_type and nonnegative");
6060
}
6161
return 0;

libcxx/test/libcxx/containers/views/mdspan/layout_left/assert.conversion.pass.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,17 +42,20 @@ int main(int, char**) {
4242
}
4343
// non-representability of extents itself
4444
{
45-
TEST_LIBCPP_ASSERT_FAILURE(([=] { std::layout_left::mapping<std::extents<char, D>> m(
46-
std::layout_left::mapping<std::extents<int, D>>(std::extents<int, D>(500))); }()),
47-
"extents ctor: arguments must be representable as index_type and nonnegative");
45+
TEST_LIBCPP_ASSERT_FAILURE(
46+
([=] {
47+
std::layout_left::mapping<std::extents<signed char, D>> m(
48+
std::layout_left::mapping<std::extents<int, D>>(std::extents<int, D>(500)));
49+
}()),
50+
"extents ctor: arguments must be representable as index_type and nonnegative");
4851
}
4952
// required_span_size not representable, while individual extents are
5053
{
5154
// check extents would be constructible
52-
[[maybe_unused]] std::extents<char, D, 5> e(arg_exts);
55+
[[maybe_unused]] std::extents<signed char, D, 5> e(arg_exts);
5356
// but the product is not, so we can't use it for layout_left
5457
TEST_LIBCPP_ASSERT_FAILURE(
55-
([=] { std::layout_left::mapping<std::extents<char, D, 5>> m(arg); }()),
58+
([=] { std::layout_left::mapping<std::extents<signed char, D, 5>> m(arg); }()),
5659
"layout_left::mapping converting ctor: other.required_span_size() must be representable as index_type.");
5760
}
5861
return 0;

libcxx/test/libcxx/containers/views/mdspan/layout_left/assert.ctor.extents.pass.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313

1414
// <mdspan>
1515

16-
1716
// constexpr mapping(const extents_type& e) noexcept;
1817
//
1918
// Preconditions: The size of the multidimensional index space e is representable as a value of type index_type ([basic.fundamental]).
@@ -32,7 +31,7 @@ int main(int, char**) {
3231
{
3332
// the extents are representable but the product is not, so we can't use it for layout_left
3433
TEST_LIBCPP_ASSERT_FAILURE(
35-
([=] { std::layout_left::mapping<std::extents<char, D, 5>> m(std::extents<char, D, 5>(100)); }()),
34+
([=] { std::layout_left::mapping<std::extents<signed char, D, 5>> m(std::extents<signed char, D, 5>(100)); }()),
3635
"layout_left::mapping extents ctor: product of extents must be representable as index_type.");
3736
}
3837
return 0;

libcxx/test/libcxx/containers/views/mdspan/layout_left/assert.ctor.layout_right.pass.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,12 @@ int main(int, char**) {
4444
}
4545
// non-representability of extents itself
4646
{
47-
TEST_LIBCPP_ASSERT_FAILURE(([=] { std::layout_left::mapping<std::extents<char, D>> m(
48-
std::layout_right::mapping<std::extents<int, D>>(std::extents<int, D>(500))); }()),
49-
"extents ctor: arguments must be representable as index_type and nonnegative");
47+
TEST_LIBCPP_ASSERT_FAILURE(
48+
([=] {
49+
std::layout_left::mapping<std::extents<signed char, D>> m(
50+
std::layout_right::mapping<std::extents<int, D>>(std::extents<int, D>(500)));
51+
}()),
52+
"extents ctor: arguments must be representable as index_type and nonnegative");
5053
}
5154

5255
// Can't trigger required_span_size() representability assertion, since for rank-1 the above check will trigger first,

libcxx/test/libcxx/containers/views/mdspan/layout_left/assert.ctor.layout_stride.pass.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,14 @@ int main(int, char**) {
5454
// non-representability of extents itself
5555
{
5656
std::layout_stride::mapping arg(std::extents<int, D>(500), std::array<int, 1>{1});
57-
TEST_LIBCPP_ASSERT_FAILURE(([=] { std::layout_left::mapping<std::extents<char, D>> m(arg); }()),
57+
TEST_LIBCPP_ASSERT_FAILURE(([=] { std::layout_left::mapping<std::extents<signed char, D>> m(arg); }()),
5858
"extents ctor: arguments must be representable as index_type and nonnegative");
5959
}
6060
// non-representability of required span size
6161
{
6262
std::layout_stride::mapping arg(std::extents<int, D, D>(100, 3), std::array<int, 2>{1, 100});
6363
TEST_LIBCPP_ASSERT_FAILURE(
64-
([=] { std::layout_left::mapping<std::extents<char, D, D>> m(arg); }()),
64+
([=] { std::layout_left::mapping<std::extents<signed char, D, D>> m(arg); }()),
6565
"layout_left::mapping from layout_stride ctor: other.required_span_size() must be "
6666
"representable as index_type.");
6767
}

libcxx/test/libcxx/containers/views/mdspan/layout_right/assert.conversion.pass.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,17 +42,20 @@ int main(int, char**) {
4242
}
4343
// non-representability of extents itself
4444
{
45-
TEST_LIBCPP_ASSERT_FAILURE(([=] { std::layout_right::mapping<std::extents<char, D>> m(
46-
std::layout_right::mapping<std::extents<int, D>>(std::extents<int, D>(500))); }()),
47-
"extents ctor: arguments must be representable as index_type and nonnegative");
45+
TEST_LIBCPP_ASSERT_FAILURE(
46+
([=] {
47+
std::layout_right::mapping<std::extents<signed char, D>> m(
48+
std::layout_right::mapping<std::extents<int, D>>(std::extents<int, D>(500)));
49+
}()),
50+
"extents ctor: arguments must be representable as index_type and nonnegative");
4851
}
4952
// required_span_size not representable, while individual extents are
5053
{
5154
// check extents would be constructible
52-
[[maybe_unused]] std::extents<char, D, 5> e(arg_exts);
55+
[[maybe_unused]] std::extents<signed char, D, 5> e(arg_exts);
5356
// but the product is not, so we can't use it for layout_right
5457
TEST_LIBCPP_ASSERT_FAILURE(
55-
([=] { std::layout_right::mapping<std::extents<char, D, 5>> m(arg); }()),
58+
([=] { std::layout_right::mapping<std::extents<signed char, D, 5>> m(arg); }()),
5659
"layout_right::mapping converting ctor: other.required_span_size() must be representable as index_type.");
5760
}
5861
return 0;

0 commit comments

Comments
 (0)