//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23 // // template // constexpr R saturate_cast(T x) noexcept; // freestanding #include #include #include #include #include #include "test_macros.h" #include // Smaller to larger static_assert(noexcept(std::saturate_cast(std::numeric_limits::max()))); static_assert(noexcept(std::saturate_cast(std::numeric_limits::max()))); static_assert(noexcept(std::saturate_cast(std::numeric_limits::max()))); static_assert(noexcept(std::saturate_cast(std::numeric_limits::max()))); // Same type static_assert(noexcept(std::saturate_cast(std::numeric_limits::max()))); static_assert(noexcept(std::saturate_cast(std::numeric_limits::max()))); // Larger to smaller static_assert(noexcept(std::saturate_cast(std::numeric_limits::max()))); static_assert(noexcept(std::saturate_cast(std::numeric_limits::max()))); static_assert(noexcept(std::saturate_cast(std::numeric_limits::max()))); static_assert(noexcept(std::saturate_cast(std::numeric_limits::max()))); // Tests constexpr bool test() { // clang-format off #ifndef TEST_HAS_NO_INT128 using SIntT = __int128_t; using UIntT = __uint128_t; #else using SIntT = long long int; using UIntT = unsigned long long int; #endif // Constants the values of which depend on the context (platform) constexpr auto sBigMin = std::numeric_limits::min(); constexpr auto sZero = SIntT{0}; constexpr auto sBigMax = std::numeric_limits::max(); constexpr auto uZero = UIntT{0}; constexpr auto uBigMax = std::numeric_limits::max(); // Constants to avoid casting in place constexpr auto O_C = static_cast(0); constexpr auto O_UC = static_cast(0); constexpr auto O_S = static_cast(0); constexpr auto O_US = static_cast(0); // signed char // TODO(LLVM-20) remove [[maybe_unused]] and `{}` scope since all supported compilers support "Placeholder variables with no name", // here and below... { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(SCHAR_MAX); } assert(std::saturate_cast(SCHAR_MIN) == SCHAR_MIN); assert(std::saturate_cast( O_C) == O_C); assert(std::saturate_cast(SCHAR_MAX) == SCHAR_MAX); { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(UCHAR_MAX); } assert(std::saturate_cast( O_UC) == O_C); assert(std::saturate_cast(UCHAR_MAX) == SCHAR_MAX); { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(sBigMax); } assert(std::saturate_cast(sBigMin) == SCHAR_MIN); // saturated assert(std::saturate_cast( sZero) == O_C); assert(std::saturate_cast(sBigMax) == SCHAR_MAX); // saturated { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(uBigMax); } assert(std::saturate_cast( uZero) == O_C); assert(std::saturate_cast(uBigMax) == SCHAR_MAX); // saturated // short { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(SCHAR_MAX); } assert(std::saturate_cast(SCHAR_MIN) == static_cast(SCHAR_MIN)); assert(std::saturate_cast( O_C) == O_S); assert(std::saturate_cast(SCHAR_MAX) == static_cast(SCHAR_MAX)); { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(UCHAR_MAX); } assert(std::saturate_cast( O_UC) == O_S); assert(std::saturate_cast(UCHAR_MAX) == static_cast(UCHAR_MAX)); { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(SHRT_MAX); } assert(std::saturate_cast( SHRT_MIN) == SHRT_MIN); assert(std::saturate_cast( O_S) == O_S); assert(std::saturate_cast( SHRT_MAX) == SHRT_MAX); { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(USHRT_MAX); } assert(std::saturate_cast( O_US) == O_S); assert(std::saturate_cast(USHRT_MAX) == SHRT_MAX); // saturated { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(sBigMax); } assert(std::saturate_cast( sBigMin) == SHRT_MIN); // saturated assert(std::saturate_cast( sZero) == O_S); assert(std::saturate_cast( sBigMax) == SHRT_MAX); // saturated { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(uBigMax); } assert(std::saturate_cast( uZero) == O_S); assert(std::saturate_cast( uBigMax) == SHRT_MAX); // saturated // int { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(SCHAR_MAX); } assert(std::saturate_cast(SCHAR_MIN) == static_cast(SCHAR_MIN)); assert(std::saturate_cast( O_C) == 0); assert(std::saturate_cast(SCHAR_MAX) == static_cast(SCHAR_MAX)); { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(UCHAR_MAX); } assert(std::saturate_cast( O_UC) == 0); assert(std::saturate_cast(UCHAR_MAX) == static_cast(UCHAR_MAX)); { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(INT_MAX); } assert(std::saturate_cast( INT_MIN) == INT_MIN); assert(std::saturate_cast( 0) == 0); assert(std::saturate_cast( INT_MAX) == INT_MAX); { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(UINT_MAX); } assert(std::saturate_cast( 0) == 0); assert(std::saturate_cast(UINT_MAX) == INT_MAX); // saturated { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(sBigMax); } assert(std::saturate_cast( sBigMin) == INT_MIN); // saturated assert(std::saturate_cast( sZero) == 0); assert(std::saturate_cast( sBigMax) == INT_MAX); // saturated { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(uBigMax); } assert(std::saturate_cast( uZero) == 0); assert(std::saturate_cast( uBigMax) == INT_MAX); // saturated // long { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(SCHAR_MAX); } assert(std::saturate_cast(SCHAR_MIN) == static_cast(SCHAR_MIN)); assert(std::saturate_cast( O_C) == 0L); assert(std::saturate_cast(SCHAR_MAX) == static_cast(SCHAR_MAX)); { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(UCHAR_MAX); } assert(std::saturate_cast( O_UC) == 0L); assert(std::saturate_cast(UCHAR_MAX) == static_cast(UCHAR_MAX)); { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(LONG_MAX); } assert(std::saturate_cast( LONG_MIN) == LONG_MIN); assert(std::saturate_cast( 0L) == 0L); assert(std::saturate_cast( LONG_MAX) == LONG_MAX); { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(ULONG_MAX); } assert(std::saturate_cast( 0UL) == 0L); assert(std::saturate_cast(ULONG_MAX) == LONG_MAX); // saturated { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(sBigMax); } assert(std::saturate_cast( sBigMin) == LONG_MIN); // saturated assert(std::saturate_cast( sZero) == 0L); assert(std::saturate_cast( sBigMax) == LONG_MAX); // saturated { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(uBigMax); } assert(std::saturate_cast( uZero) == 0L); assert(std::saturate_cast( uBigMax) == LONG_MAX); // saturated // long long { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(SCHAR_MAX); } assert(std::saturate_cast(SCHAR_MIN) == static_cast(SCHAR_MIN)); assert(std::saturate_cast( 0LL) == 0LL); assert(std::saturate_cast(SCHAR_MAX) == static_cast(SCHAR_MAX)); { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(UCHAR_MAX); } assert(std::saturate_cast( O_UC) == 0LL); assert(std::saturate_cast(UCHAR_MAX) == static_cast(UCHAR_MAX)); { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(LLONG_MIN); } assert(std::saturate_cast(LLONG_MIN) == LLONG_MIN); assert(std::saturate_cast( 0LL) == 0LL); assert(std::saturate_cast(LLONG_MAX) == LLONG_MAX); { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(ULLONG_MAX); } assert(std::saturate_cast( 0ULL) == 0LL); assert(std::saturate_cast(ULLONG_MAX) == LLONG_MAX); // saturated #ifndef TEST_HAS_NO_INT128 { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(sBigMax); } assert(std::saturate_cast( sBigMin) == LLONG_MIN); // (128-bit) saturated assert(std::saturate_cast( sZero) == 0LL); assert(std::saturate_cast( sBigMax) == LLONG_MAX); // (128-bit) saturated { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(uBigMax); } assert(std::saturate_cast( uZero) == 0LL); assert(std::saturate_cast( uBigMax) == LLONG_MAX); // (128-bit) saturated { [[maybe_unused]] std::same_as<__int128_t> decltype(auto) _ = std::saturate_cast<__int128_t>(SCHAR_MAX); } assert(std::saturate_cast<__int128_t>(SCHAR_MIN) == static_cast<__int128_t>(SCHAR_MIN)); assert(std::saturate_cast<__int128_t>( O_C) == sZero); assert(std::saturate_cast<__int128_t>(SCHAR_MAX) == static_cast<__int128_t>(SCHAR_MAX)); { [[maybe_unused]] std::same_as<__int128_t> decltype(auto) _ = std::saturate_cast<__int128_t>(UCHAR_MAX); } assert(std::saturate_cast<__int128_t>( O_UC) == sZero); assert(std::saturate_cast<__int128_t>(UCHAR_MAX) == static_cast<__int128_t>(UCHAR_MAX)); { [[maybe_unused]] std::same_as<__int128_t> decltype(auto) _ = std::saturate_cast<__int128_t>(sBigMax); } assert(std::saturate_cast<__int128_t>( sBigMin) == sBigMin); assert(std::saturate_cast<__int128_t>( sZero) == sZero); assert(std::saturate_cast<__int128_t>( sBigMax) == sBigMax); { [[maybe_unused]] std::same_as<__int128_t> decltype(auto) _ = std::saturate_cast<__int128_t>(uBigMax); } assert(std::saturate_cast<__int128_t>( uZero) == sZero); assert(std::saturate_cast<__int128_t>( uBigMax) == sBigMax); // saturated #endif // unsigned char { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(SCHAR_MAX); } assert(std::saturate_cast(SCHAR_MIN) == O_UC); assert(std::saturate_cast( O_C) == O_UC); assert(std::saturate_cast(SCHAR_MAX) == static_cast(SCHAR_MAX)); { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(UCHAR_MAX); } assert(std::saturate_cast( O_UC) == O_UC); assert(std::saturate_cast(UCHAR_MAX) == UCHAR_MAX); { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(sBigMax); } assert(std::saturate_cast( sBigMin) == O_UC); // saturated assert(std::saturate_cast( sZero) == O_UC); assert(std::saturate_cast( sBigMax) == UCHAR_MAX); // saturated { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(uBigMax); } assert(std::saturate_cast( uZero) == O_UC); assert(std::saturate_cast( uBigMax) == UCHAR_MAX); // saturated // unsigned short { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(SCHAR_MAX); } assert(std::saturate_cast(SCHAR_MIN) == O_US); assert(std::saturate_cast( O_C) == O_US); assert(std::saturate_cast(SCHAR_MAX) == static_cast(SCHAR_MAX)); { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(UCHAR_MAX); } assert(std::saturate_cast( O_UC) == O_US); assert(std::saturate_cast(UCHAR_MAX) == static_cast(UCHAR_MAX)); { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(SCHAR_MIN); } assert(std::saturate_cast( SHRT_MIN) == O_US); assert(std::saturate_cast( O_S) == O_US); assert(std::saturate_cast( SHRT_MAX) == static_cast(SHRT_MAX)); { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(UCHAR_MAX); } assert(std::saturate_cast( O_US) == O_US); assert(std::saturate_cast(USHRT_MAX) == USHRT_MAX); { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(sBigMax); } assert(std::saturate_cast( sBigMin) == O_US); // saturated assert(std::saturate_cast( sZero) == O_US); assert(std::saturate_cast( sBigMax) == USHRT_MAX); // saturated { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(uBigMax); } assert(std::saturate_cast( uZero) == O_US); assert(std::saturate_cast( uBigMax) == USHRT_MAX); // saturated // unsigned int { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(SCHAR_MAX); } assert(std::saturate_cast(SCHAR_MIN) == O_US); assert(std::saturate_cast( O_UC) == 0U); assert(std::saturate_cast(SCHAR_MAX) == static_cast(SCHAR_MAX)); { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(UCHAR_MAX); } assert(std::saturate_cast( O_UC) == 0U); assert(std::saturate_cast(UCHAR_MAX) == static_cast(UCHAR_MAX)); { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(INT_MAX); } assert(std::saturate_cast( INT_MIN) == 0U); assert(std::saturate_cast( 0) == 0U); assert(std::saturate_cast( INT_MAX) == static_cast(INT_MAX)); { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(UINT_MAX); } assert(std::saturate_cast( 0U) == 0U); assert(std::saturate_cast( UINT_MAX) == UINT_MAX); { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(sBigMax); } assert(std::saturate_cast( sBigMin) == 0U); // saturated assert(std::saturate_cast( sZero) == 0U); assert(std::saturate_cast( sBigMax) == UINT_MAX); // saturated { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(uBigMax); } assert(std::saturate_cast( uZero) == 0U); assert(std::saturate_cast( uBigMax) == UINT_MAX); // saturated // unsigned long { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(SCHAR_MAX); } assert(std::saturate_cast(SCHAR_MIN) == 0UL); assert(std::saturate_cast( O_C) == 0UL); assert(std::saturate_cast(SCHAR_MAX) == static_cast(SCHAR_MAX)); { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(UCHAR_MAX); } assert(std::saturate_cast( O_UC) == 0UL); assert(std::saturate_cast(UCHAR_MAX) == static_cast(UCHAR_MAX)); { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(LONG_MAX); } assert(std::saturate_cast( LONG_MIN) == 0UL); assert(std::saturate_cast( 0L) == 0UL); assert(std::saturate_cast( LONG_MAX) == static_cast(LONG_MAX)); { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(ULONG_MAX); } assert(std::saturate_cast( 0UL) == 0UL); assert(std::saturate_cast(ULONG_MAX) == ULONG_MAX); { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(sBigMax); } assert(std::saturate_cast( sBigMin) == 0UL); // saturated assert(std::saturate_cast( sZero) == 0UL); assert(std::saturate_cast( sBigMax) == (sizeof(UIntT) > sizeof(unsigned long int) ? ULONG_MAX : LONG_MAX)); // saturated depending on underlying types { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(uBigMax); } assert(std::saturate_cast( uZero) == 0UL); assert(std::saturate_cast( uBigMax) == ULONG_MAX); // saturated // unsigned long long { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(SCHAR_MAX); } assert(std::saturate_cast( SCHAR_MIN) == 0ULL); assert(std::saturate_cast( O_C) == 0ULL); assert(std::saturate_cast( SCHAR_MAX) == static_cast(SCHAR_MAX)); { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(UCHAR_MAX); } assert(std::saturate_cast( O_UC) == 0ULL); assert(std::saturate_cast( UCHAR_MAX) == static_cast(UCHAR_MAX)); { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(LLONG_MAX); } assert(std::saturate_cast( LLONG_MIN) == 0ULL); assert(std::saturate_cast( 0LL) == 0ULL); assert(std::saturate_cast( LLONG_MAX) == static_cast(LLONG_MAX)); { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(ULLONG_MAX); } assert(std::saturate_cast( 0ULL) == 0ULL); assert(std::saturate_cast(ULLONG_MAX) == ULLONG_MAX); #ifndef TEST_HAS_NO_INT128 { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(sBigMax); } assert(std::saturate_cast( sBigMin) == 0ULL); // (128-bit) saturated assert(std::saturate_cast( sZero) == 0ULL); assert(std::saturate_cast( sBigMax) == ULLONG_MAX); // (128-bit) saturated { [[maybe_unused]] std::same_as decltype(auto) _ = std::saturate_cast(uBigMax); } assert(std::saturate_cast( uZero) == 0ULL); assert(std::saturate_cast( uBigMax) == ULLONG_MAX); // (128-bit) saturated { [[maybe_unused]] std::same_as<__uint128_t> decltype(auto) _ = std::saturate_cast<__uint128_t>(SCHAR_MIN); } assert(std::saturate_cast<__uint128_t>(SCHAR_MIN) == uZero); assert(std::saturate_cast<__uint128_t>( O_C) == uZero); assert(std::saturate_cast<__uint128_t>(SCHAR_MAX) == static_cast<__uint128_t>(SCHAR_MAX)); { [[maybe_unused]] std::same_as<__uint128_t> decltype(auto) _ = std::saturate_cast<__uint128_t>(UCHAR_MAX); } assert(std::saturate_cast<__uint128_t>( O_UC) == uZero); assert(std::saturate_cast<__uint128_t>(UCHAR_MAX) == static_cast<__uint128_t>(UCHAR_MAX)); { [[maybe_unused]] std::same_as<__uint128_t> decltype(auto) _ = std::saturate_cast<__uint128_t>(sBigMax); } assert(std::saturate_cast<__uint128_t>( sBigMin) == uZero); // saturated assert(std::saturate_cast<__uint128_t>( sZero) == uZero); assert(std::saturate_cast<__uint128_t>( sBigMax) == static_cast<__uint128_t>(sBigMax)); { [[maybe_unused]] std::same_as<__uint128_t> decltype(auto) _ = std::saturate_cast<__uint128_t>(uBigMax); } assert(std::saturate_cast<__uint128_t>( uZero) == uZero); assert(std::saturate_cast<__uint128_t>( uBigMax) == uBigMax); #endif // clang-format on return true; } int main(int, char**) { test(); static_assert(test()); return 0; }