//===----------------------------------------------------------------------===// // // Part of libcu++, the C++ Standard Library for your entire system, // 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 // SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. // //===----------------------------------------------------------------------===// #ifndef TEST_SUPPORT_LITERAL_H #define TEST_SUPPORT_LITERAL_H #include #include #include "test_macros.h" template [[nodiscard]] TEST_FUNC constexpr CharT _test_charlit_impl( [[maybe_unused]] char char_val, [[maybe_unused]] wchar_t wchar_val, #if _CCCL_HAS_CHAR8_T() [[maybe_unused]] char8_t char8_val, #endif // _CCCL_HAS_CHAR8_T() [[maybe_unused]] char16_t char16_val, [[maybe_unused]] char32_t char32_val) noexcept { if constexpr (cuda::std::is_same_v) { return char_val; } else if constexpr (cuda::std::is_same_v) { return wchar_val; } #if _CCCL_HAS_CHAR8_T() else if constexpr (cuda::std::is_same_v) { return char8_val; } #endif // _CCCL_HAS_CHAR8_T() else if constexpr (cuda::std::is_same_v) { return char16_val; } else if constexpr (cuda::std::is_same_v) { return char32_val; } else { static_assert(cuda::std::__always_false_v, "Unsupported character type. Supported types are char, wchar_t, char8_t, char16_t, and char32_t."); _CCCL_UNREACHABLE(); } } #if _CCCL_HAS_CHAR8_T() # define TEST_CHARLIT(CharT, val) _test_charlit_impl(val, L##val, u8##val, u##val, U##val) #else // _CCCL_HAS_CHAR8_T() # define TEST_CHARLIT(CharT, val) _test_charlit_impl(val, L##val, u##val, U##val) #endif // _CCCL_HAS_CHAR8_T() template [[nodiscard]] TEST_FUNC constexpr auto _test_strlit_impl( [[maybe_unused]] const char (&char_str)[N], [[maybe_unused]] const wchar_t (&wchar_str)[N], #if _CCCL_HAS_CHAR8_T() [[maybe_unused]] const char8_t (&char8_str)[N], #endif // _CCCL_HAS_CHAR8_T() [[maybe_unused]] const char16_t (&char16_str)[N], [[maybe_unused]] const char32_t (&char32_str)[N]) noexcept -> const CharT (&)[N] { if constexpr (cuda::std::is_same_v) { return char_str; } else if constexpr (cuda::std::is_same_v) { return wchar_str; } #if _CCCL_HAS_CHAR8_T() else if constexpr (cuda::std::is_same_v) { return char8_str; } #endif // _CCCL_HAS_CHAR8_T() else if constexpr (cuda::std::is_same_v) { return char16_str; } else if constexpr (cuda::std::is_same_v) { return char32_str; } else { static_assert(cuda::std::__always_false_v, "Unsupported character type. Supported types are char, wchar_t, char8_t, char16_t, and char32_t."); _CCCL_UNREACHABLE(); } } #if _CCCL_HAS_CHAR8_T() # define TEST_STRLIT(CharT, str) _test_strlit_impl(str, L##str, u8##str, u##str, U##str) #else // _CCCL_HAS_CHAR8_T() # define TEST_STRLIT(CharT, str) _test_strlit_impl(str, L##str, u##str, U##str) #endif // _CCCL_HAS_CHAR8_T() template struct _test_int_literal_impl_result { T value; bool invalid_character; bool overflow; }; template [[nodiscard]] TEST_FUNC constexpr bool _test_int_literal_char_to_digit(char c, int& value) { static_assert(Base >= 2 && Base <= 36, "Base must be between 2 and 36 inclusive."); if constexpr (Base <= 10) { if (c >= '0' && c < '0' + Base) { value = c - '0'; return true; } return false; } else { if (c >= '0' && c < '0' + 10) { value = c - '0'; return true; } else if (c >= 'A' && c < 'A' + (Base - 10)) { value = c - 'A' + 10; return true; } else if (c >= 'a' && c < 'a' + (Base - 10)) { value = c - 'a' + 10; return true; } return false; } } template [[nodiscard]] TEST_FUNC constexpr _test_int_literal_impl_result _test_int_literal_impl(const char* begin, const char* end) noexcept { using U = cuda::std::make_unsigned_t; constexpr U max = (~U{0}) >> cuda::std::is_signed_v; _test_int_literal_impl_result result{}; U value = 0; const char* it = begin; for (; it != end; ++it) { if (*it == '\'') { continue; } int digit{}; if (!_test_int_literal_char_to_digit(*it, digit)) { result.invalid_character = true; return result; } const U new_value = value * Base + digit; if (new_value < value || new_value > max) { result.overflow = true; return result; } value = new_value; } result.value = static_cast(value); return result; } template [[nodiscard]] TEST_FUNC constexpr _test_int_literal_impl_result _test_int_literal_impl(const char (&cs)[N]) noexcept { unsigned base = 10; SizeT offset = 0; if (N >= 2 && cs[0] == '0') { if (cs[1] == 'b' || cs[1] == 'B') { base = 2; offset = 2; } else if (cs[1] == 'x' || cs[1] == 'X') { base = 16; offset = 2; } else { for (SizeT i = 1; i < N; ++i) { base = 8; offset = 1; if (!(cs[i] >= '0' && cs[i] <= '7') && cs[i] != '\'') { base = 10; offset = 0; break; } } } } switch (base) { case 2: return _test_int_literal_impl(cs + offset, cs + N); case 8: return _test_int_literal_impl(cs + offset, cs + N); case 16: return _test_int_literal_impl(cs + offset, cs + N); case 10: default: return _test_int_literal_impl(cs + offset, cs + N); } } namespace test_integer_literals { // nvcc passes operator""_x to the host compiler as operator "" _x, which was deprecated in CWG 2521 (nvbug 5507437) // clang 20 already warns about this, so we need to suppress the warning here _CCCL_DIAG_PUSH #if _CCCL_COMPILER(CLANG, >=, 20) _CCCL_DIAG_SUPPRESS_CLANG("-Wdeprecated-literal-operator") #endif // _CCCL_COMPILER(CLANG, >=, 20) #if _CCCL_HAS_INT128() template [[nodiscard]] TEST_FUNC constexpr __int128_t operator""_i128() noexcept { constexpr char cs[]{Cs...}; constexpr auto result = _test_int_literal_impl<__int128_t>(cs); static_assert(!result.invalid_character, "Invalid character in integer literal."); static_assert(!result.overflow, "Integer literal overflow."); return result.value; } template [[nodiscard]] TEST_FUNC constexpr __uint128_t operator""_u128() noexcept { constexpr char cs[]{Cs...}; constexpr auto result = _test_int_literal_impl<__uint128_t>(cs); static_assert(!result.invalid_character, "Invalid character in integer literal."); static_assert(!result.overflow, "Integer literal overflow."); return result.value; } #endif // _CCCL_HAS_INT128() _CCCL_DIAG_POP } // namespace test_integer_literals #endif // TEST_SUPPORT_LITERAL_H