On 12/17/25 22:11, Jonathan Wakely wrote:
On Wed, 17 Dec 2025 at 21:10, Jonathan Wakely <[email protected]> wrote:On Wed, 17 Dec 2025 at 20:52, Luc Grosheintz <[email protected]> wrote:On Solaris, same_as<int8_t, char> is true. Therefore, int8_t isn't a valid IndexType, because char is neither a signed nor an unsigned integer type. This commit fixes the tests by avoiding int8_t (and uint8_t) by using 'signed char' (and 'unsigned char'). PR libstdc++/123176 libstdc++-v3/ChangeLog: * testsuite/23_containers/mdspan/submdspan/submdspan_canonicalize_slices_neg.cc: Avoid int8_t with signed char. Signed-off-by: Luc Grosheintz <[email protected]> --- This fix is purely based on a theoretical understanding of the compiler messages reported in the bug report. Unfortunately, I don't have access to a Solaris machine; and therefore am not able to test on Solaris. I have tested on linux-x86_64. I've CC'ed Rainer Orth who reported the issue, maybe Rainer's willing and has time to test it on Solaris. .../submdspan_canonicalize_slices_neg.cc | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_canonicalize_slices_neg.cc b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_canonicalize_slices_neg.cc index 94bca183aa3..0098547d750 100644 --- a/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_canonicalize_slices_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/mdspan/submdspan/submdspan_canonicalize_slices_neg.cc @@ -8,9 +8,12 @@ constexpr size_t dyn = std::dynamic_extent; constexpr auto dyn_empty = std::extents<int32_t, dyn>{0}; constexpr auto sta_empty = std::extents<uint32_t, 0>{}; -constexpr auto dyn_uexts = std::extents<uint8_t, dyn>{5}; +// On Solaris same_as<int8_t, char> is true. Therefore, int8_t is not a signed +// or unsigned integer type and hence not a valid IndexType. We'll use signed +// char and unsigned char for int8_t throughout. +constexpr auto dyn_uexts = std::extents<unsigned char, dyn>{5}; constexpr auto sta_uexts = std::extents<uint16_t, 5>{5}; -constexpr auto dyn_sexts = std::extents<int8_t, dyn>{5}; +constexpr auto dyn_sexts = std::extents<signed char, dyn>{5}; constexpr auto sta_sexts = std::extents<int16_t, 5>{5}; constexpr bool @@ -69,7 +72,7 @@ template<typename Offset, typename Extent, typename Stride, typename Extents> return true; } -constexpr auto i8_1 = int8_t{1}; +constexpr auto i8_1 = (signed char){1}; static_assert(test_under2(-i8_1, 0, 1, dyn_uexts)); // { dg-error "expansion of" } static_assert(test_under2(0, -i8_1, 1, dyn_uexts)); // { dg-error "expansion of" } @@ -84,7 +87,7 @@ static_assert(test_under2(-i8_1, 0, 1, sta_sexts)); // { dg-error "expansion o static_assert(test_under2(0, -i8_1, 1, sta_sexts)); // { dg-error "expansion of" } static_assert(test_under2(0, 1, -i8_1, sta_sexts)); // { dg-error "expansion of" } -constexpr auto c_i8_m1 = std::cw<int8_t{-1}>; +constexpr auto c_i8_m1 = std::cw<(signed char){-1}>; constexpr auto c_i16_m1 = std::cw<int16_t{-1}>; constexpr auto c_i64_m1 = std::cw<int64_t{-1}>; @@ -109,8 +112,8 @@ template<typename Offset, typename Extent, typename Stride, typename Extents> return true; } -constexpr auto i8_6 = int8_t{6}; -constexpr auto c_i8_6 = std::cw<int8_t{6}>; +constexpr auto i8_6 = (signed char){6}; +constexpr auto c_i8_6 = std::cw<(signed char){6}>;Actually all these braces should be removed, so just: (signed char){6} not (signed char){6}, otherwise it's a C99 compound literal, which is not valid in C++ and will warn with -pedantic.Gah, pasted the wrong thing. I mean: (signed char)6 not (signed char){6}
I had to remove `-pedantic` due to:
libstdc++-v3/testsuite/23_containers/mdspan/extents/ctor_ints.cc:20: warning:
ISO C++ does not support '__int128' for 'type name' [-Wpedantic]
--------------------
Regarding your comment about fixing `int8_t` on Solaris. If we only fix the
testsuite, then code that uses
std::extents<int8_t>
will fail to compile on Solaris. On the one hand: that's correct, because
int8_t on Solaris isn't a signed or unsigned integer type. On the other
hand it's wrong because the standard states that int8_t is.
What we could consider is implementing the requirement that something
is a valid IndexType in mdspan as:
__is_signed_or_unsigned_integer<_IndexType>::value
|| same_as<_IndexType, int8_t>
|| same_as<_IndexType, uint8_t>;
we'd need to be more careful, because we can't blindly assume that
int8_t exists. The idea is that I can't remember anything in the
standard that requires us to fail if index_type == char and I can't
remember anything that would make 'char' problematic. Hence, we could
be lenient and allow char or int8_t.
I don't know if this is a good idea.
constexpr auto c2 = std::cw<2>; constexpr auto c4 = std::cw<4>; @@ -155,21 +158,22 @@ static_assert(test_over2(c2, c4, 1, sta_sexts)); // { dg-error "expansion of constexpr bool test_overflow1(auto o, auto e) { - auto exts = std::extents<uint8_t, dyn>{255}; + auto exts = std::extents<unsigned char, dyn>{std::numeric_limits<unsigned char>::max()}; auto slice = std::strided_slice{o, e, 1}; std::submdspan_canonicalize_slices(exts, slice); return true; } -static_assert(test_overflow1(128, 128)); // { dg-error "expansion of" } -static_assert(test_overflow1(std::cw<128>, 128)); // { dg-error "expansion of" } -static_assert(test_overflow1(128, std::cw<128>)); // { dg-error "expansion of" } -static_assert(test_overflow1(std::cw<128>, std::cw<128>)); // { dg-error "expansion of" } +constexpr int half_max = std::numeric_limits<unsigned char>::max() / 2 + 1; +static_assert(test_overflow1(half_max, half_max)); // { dg-error "expansion of" } +static_assert(test_overflow1(std::cw<half_max>, half_max)); // { dg-error "expansion of" } +static_assert(test_overflow1(half_max, std::cw<half_max>)); // { dg-error "expansion of" } +static_assert(test_overflow1(std::cw<half_max>, std::cw<half_max>)); // { dg-error "expansion of" } constexpr bool test_overflow2(auto b, auto e) { - auto exts = std::extents<uint8_t, dyn>{255}; + auto exts = std::extents<unsigned char, dyn>{std::numeric_limits<unsigned char>::max()}; auto slice = std::pair{b, e}; std::submdspan_canonicalize_slices(exts, slice); return true; @@ -180,8 +184,8 @@ static_assert(test_overflow2(std::cw<5>, 4)); // { dg-error "expansion static_assert(test_overflow2(5, std::cw<4>)); // { dg-error "expansion of" } static_assert(test_overflow2(std::cw<5>, std::cw<4>)); // { dg-error "expansion of" } -constexpr auto u8_4 = uint8_t{4}; -constexpr auto u8_5 = uint8_t{5}; +constexpr auto u8_4 = (unsigned char){4}; +constexpr auto u8_5 = (unsigned char){5}; static_assert(test_overflow2(u8_5, u8_4)); // { dg-error "expansion of" } static_assert(test_overflow2(std::cw<u8_5>, u8_4)); // { dg-error "expansion of" } static_assert(test_overflow2(u8_5, std::cw<u8_4>)); // { dg-error "expansion of" } -- 2.52.0
