//===----------------------------------------------------------------------===// // // 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 // UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME // // basic_format_arg get(size_t i) const noexcept; #include #include #include #include #include "test_macros.h" #include "make_string.h" template void test(From value) { auto store = std::make_format_args(value); const std::basic_format_args format_args{store}; auto visitor = [v = To(value)](auto a) { if constexpr (std::is_same_v) assert(v == a); else assert(false); }; #if TEST_STD_VER >= 26 && defined(TEST_HAS_EXPLICIT_THIS_PARAMETER) format_args.get(0).visit(visitor); #else std::visit_format_arg(visitor, format_args.get(0)); #endif } // Some types, as an extension, are stored in the variant. The Standard // requires them to be observed as a handle. template void test_handle(T value) { auto store = std::make_format_args(value); std::basic_format_args format_args{store}; auto visitor = [](auto a) { assert((std::is_same_v::handle>)); }; #if TEST_STD_VER >= 26 && defined(TEST_HAS_EXPLICIT_THIS_PARAMETER) format_args.get(0).visit(visitor); #else std::visit_format_arg(visitor, format_args.get(0)); #endif } // Test specific for string and string_view. // // Since both result in a string_view there's no need to pass this as a // template argument. template void test_string_view(From value) { auto store = std::make_format_args(value); const std::basic_format_args format_args{store}; using CharT = typename Context::char_type; using To = std::basic_string_view; using V = std::basic_string; auto visitor = [v = V(value.begin(), value.end())](auto a) { if constexpr (std::is_same_v) assert(v == a); else assert(false); }; #if TEST_STD_VER >= 26 && defined(TEST_HAS_EXPLICIT_THIS_PARAMETER) format_args.get(0).visit(visitor); #else std::visit_format_arg(visitor, format_args.get(0)); #endif } template void test() { using Context = std::basic_format_context; using char_type = typename Context::char_type; std::basic_string empty; std::basic_string str = MAKE_STRING(char_type, "abc"); // Test boolean types. test(true); test(false); // Test char_type types. test('a'); test('z'); test('0'); test('9'); // Test char types. if (std::is_same_v) { // char to char -> char test('a'); test('z'); test('0'); test('9'); } else { if (std::is_same_v) { // char to wchar_t -> wchar_t test('a'); test('z'); test('0'); test('9'); } else if (std::is_signed_v) { // char to char_type -> int // This happens when Context::char_type is a char8_t, char16_t, or // char32_t and char is a signed type. // Note if sizeof(char_type) > sizeof(int) this test fails. If there are // platforms where that occurs extra tests need to be added for char32_t // testing it against a long long. test('a'); test('z'); test('0'); test('9'); } else { // char to char_type -> unsigned // This happens when Context::char_type is a char8_t, char16_t, or // char32_t and char is an unsigned type. // Note if sizeof(char_type) > sizeof(unsigned) this test fails. If there // are platforms where that occurs extra tests need to be added for // char32_t testing it against an unsigned long long. test('a'); test('z'); test('0'); test('9'); } } // Test signed integer types. test(std::numeric_limits::min()); test(0); test(std::numeric_limits::max()); test(std::numeric_limits::min()); test(std::numeric_limits::min()); test(0); test(std::numeric_limits::max()); test(std::numeric_limits::max()); test(std::numeric_limits::min()); test(std::numeric_limits::min()); test(std::numeric_limits::min()); test(0); test(std::numeric_limits::max()); test(std::numeric_limits::max()); test(std::numeric_limits::max()); using LongToType = std::conditional_t; test(std::numeric_limits::min()); test(std::numeric_limits::min()); test(std::numeric_limits::min()); test(std::numeric_limits::min()); test(0); test(std::numeric_limits::max()); test(std::numeric_limits::max()); test(std::numeric_limits::max()); test(std::numeric_limits::max()); test(std::numeric_limits::min()); test(std::numeric_limits::min()); test(std::numeric_limits::min()); test(std::numeric_limits::min()); test(std::numeric_limits::min()); test(0); test(std::numeric_limits::max()); test(std::numeric_limits::max()); test(std::numeric_limits::max()); test(std::numeric_limits::max()); test(std::numeric_limits::max()); #ifndef TEST_HAS_NO_INT128 test_handle(0); #endif // TEST_HAS_NO_INT128 // Test unsigned integer types. test(0); test( std::numeric_limits::max()); test(0); test( std::numeric_limits::max()); test( std::numeric_limits::max()); test(0); test(std::numeric_limits::max()); test(std::numeric_limits::max()); test(std::numeric_limits::max()); using UnsignedLongToType = std::conditional_t; test(0); test( std::numeric_limits::max()); test( std::numeric_limits::max()); test( std::numeric_limits::max()); test( std::numeric_limits::max()); test(0); test( std::numeric_limits::max()); test( std::numeric_limits::max()); test( std::numeric_limits::max()); test( std::numeric_limits::max()); test( std::numeric_limits::max()); #ifndef TEST_HAS_NO_INT128 test_handle(0); #endif // TEST_HAS_NO_INT128 // Test floating point types. test(-std::numeric_limits::max()); test(-std::numeric_limits::min()); test(-0.0); test(0.0); test(std::numeric_limits::min()); test(std::numeric_limits::max()); test(-std::numeric_limits::max()); test(-std::numeric_limits::min()); test(-0.0); test(0.0); test(std::numeric_limits::min()); test(std::numeric_limits::max()); test( -std::numeric_limits::max()); test( -std::numeric_limits::min()); test(-0.0); test(0.0); test( std::numeric_limits::min()); test( std::numeric_limits::max()); // Test const char_type pointer types. test(empty.c_str()); test(str.c_str()); // Test string_view types. test>( std::basic_string_view()); test, std::basic_string_view>(empty); test, std::basic_string_view>(str); // Test string types. test>( std::basic_string()); test, std::basic_string>(empty); test, std::basic_string>(str); // Test pointer types. test(nullptr); } void test() { test(); #ifndef TEST_HAS_NO_WIDE_CHARACTERS test(); #endif } int main(int, char**) { test(); return 0; }