1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 10 11 // This test uses std::filesystem::path, which is not always available 12 // XFAIL: availability-filesystem-missing 13 14 // <format> 15 16 // template<class T, class charT> 17 // concept formattable = ... 18 19 #include <array> 20 #include <bitset> 21 #include <bitset> 22 #include <chrono> 23 #include <complex> 24 #include <concepts> 25 #include <deque> 26 #include <filesystem> 27 #include <flat_map> 28 #include <format> 29 #include <forward_list> 30 #include <list> 31 #include <map> 32 #include <memory> 33 #include <optional> 34 #include <queue> 35 #include <set> 36 #include <span> 37 #include <stack> 38 #include <system_error> 39 #include <tuple> 40 #include <type_traits> 41 #include <unordered_map> 42 #include <unordered_set> 43 #include <valarray> 44 #include <variant> 45 46 #include "test_macros.h" 47 #include "min_allocator.h" 48 49 #ifndef TEST_HAS_NO_LOCALIZATION 50 # include <regex> 51 #endif 52 #ifndef TEST_HAS_NO_THREADS 53 # include <thread> 54 #endif 55 56 template <class T, class CharT> 57 void assert_is_not_formattable() { 58 // clang-format off 59 static_assert(!std::formattable< T , CharT>); 60 static_assert(!std::formattable< T& , CharT>); 61 static_assert(!std::formattable< T&& , CharT>); 62 static_assert(!std::formattable<const T , CharT>); 63 static_assert(!std::formattable<const T& , CharT>); 64 static_assert(!std::formattable<const T&& , CharT>); 65 // clang-format on 66 } 67 68 template <class T, class CharT> 69 void assert_is_formattable() { 70 // Only formatters for CharT == char || CharT == wchar_t are enabled for the 71 // standard formatters. When CharT is a different type the formatter should 72 // be disabled. 73 if constexpr (std::same_as<CharT, char> 74 #ifndef TEST_HAS_NO_WIDE_CHARACTERS 75 || std::same_as<CharT, wchar_t> 76 #endif 77 ) { 78 // clang-format off 79 static_assert(std::formattable< T , CharT>); 80 static_assert(std::formattable< T& , CharT>); 81 static_assert(std::formattable< T&& , CharT>); 82 static_assert(std::formattable<const T , CharT>); 83 static_assert(std::formattable<const T& , CharT>); 84 static_assert(std::formattable<const T&& , CharT>); 85 // clang-format on 86 } else 87 assert_is_not_formattable<T, CharT>(); 88 } 89 90 // Tests for P0645 Text Formatting 91 template <class CharT> 92 void test_P0645() { 93 #ifndef TEST_HAS_NO_WIDE_CHARACTERS 94 // Tests the special formatter that converts a char to a wchar_t. 95 assert_is_formattable<char, wchar_t>(); 96 #endif 97 assert_is_formattable<CharT, CharT>(); 98 99 assert_is_formattable<CharT*, CharT>(); 100 assert_is_formattable<const CharT*, CharT>(); 101 assert_is_formattable<CharT[42], CharT>(); 102 if constexpr (!std::same_as<CharT, int>) { // string and string_view only work with proper character types 103 assert_is_formattable<std::basic_string<CharT>, CharT>(); 104 assert_is_formattable<std::basic_string_view<CharT>, CharT>(); 105 } 106 107 assert_is_formattable<bool, CharT>(); 108 109 assert_is_formattable<signed char, CharT>(); 110 assert_is_formattable<signed short, CharT>(); 111 assert_is_formattable<signed int, CharT>(); 112 assert_is_formattable<signed long, CharT>(); 113 assert_is_formattable<signed long long, CharT>(); 114 #ifndef TEST_HAS_NO_INT128 115 assert_is_formattable<__int128_t, CharT>(); 116 #endif 117 118 assert_is_formattable<unsigned char, CharT>(); 119 assert_is_formattable<unsigned short, CharT>(); 120 assert_is_formattable<unsigned int, CharT>(); 121 assert_is_formattable<unsigned long, CharT>(); 122 assert_is_formattable<unsigned long long, CharT>(); 123 #ifndef TEST_HAS_NO_INT128 124 assert_is_formattable<__uint128_t, CharT>(); 125 #endif 126 127 // floating-point types are tested in concept.formattable.float.compile.pass.cpp 128 129 assert_is_formattable<std::nullptr_t, CharT>(); 130 assert_is_formattable<void*, CharT>(); 131 assert_is_formattable<const void*, CharT>(); 132 } 133 134 // Tests for P1361 Integration of chrono with text formatting 135 // 136 // Some tests are commented out since these types haven't been implemented in 137 // chrono yet. After P1361 has been implemented these formatters should be all 138 // enabled. 139 template <class CharT> 140 void test_P1361() { 141 // The chrono formatters require localization support. 142 // [time.format]/7 143 // If the chrono-specs is omitted, the chrono object is formatted as if by 144 // streaming it to std::ostringstream os with the formatting 145 // locale imbued and copying os.str() through the output iterator of the 146 // context with additional padding and adjustments as specified by the format 147 // specifiers. 148 // In libc++ std:::ostringstream requires localization support. 149 #ifndef TEST_HAS_NO_LOCALIZATION 150 151 assert_is_formattable<std::chrono::microseconds, CharT>(); 152 153 assert_is_formattable<std::chrono::sys_time<std::chrono::microseconds>, CharT>(); 154 # if !defined(TEST_HAS_NO_EXPERIMENTAL_TZDB) && !defined(TEST_HAS_NO_TIME_ZONE_DATABASE) && \ 155 !defined(TEST_HAS_NO_FILESYSTEM) 156 assert_is_formattable<std::chrono::utc_time<std::chrono::microseconds>, CharT>(); 157 //assert_is_formattable<std::chrono::tai_time<std::chrono::microseconds>, CharT>(); 158 //assert_is_formattable<std::chrono::gps_time<std::chrono::microseconds>, CharT>(); 159 160 # endif // !defined(TEST_HAS_NO_EXPERIMENTAL_TZDB) && !defined(TEST_HAS_NO_TIME_ZONE_DATABASE) && 161 // !defined(TEST_HAS_NO_FILESYSTEM) 162 163 assert_is_formattable<std::chrono::file_time<std::chrono::microseconds>, CharT>(); 164 assert_is_formattable<std::chrono::local_time<std::chrono::microseconds>, CharT>(); 165 166 assert_is_formattable<std::chrono::day, CharT>(); 167 assert_is_formattable<std::chrono::month, CharT>(); 168 assert_is_formattable<std::chrono::year, CharT>(); 169 170 assert_is_formattable<std::chrono::weekday, CharT>(); 171 assert_is_formattable<std::chrono::weekday_indexed, CharT>(); 172 assert_is_formattable<std::chrono::weekday_last, CharT>(); 173 174 assert_is_formattable<std::chrono::month_day, CharT>(); 175 assert_is_formattable<std::chrono::month_day_last, CharT>(); 176 assert_is_formattable<std::chrono::month_weekday, CharT>(); 177 assert_is_formattable<std::chrono::month_weekday_last, CharT>(); 178 179 assert_is_formattable<std::chrono::year_month, CharT>(); 180 assert_is_formattable<std::chrono::year_month_day, CharT>(); 181 assert_is_formattable<std::chrono::year_month_day_last, CharT>(); 182 assert_is_formattable<std::chrono::year_month_weekday, CharT>(); 183 assert_is_formattable<std::chrono::year_month_weekday_last, CharT>(); 184 185 assert_is_formattable<std::chrono::hh_mm_ss<std::chrono::microseconds>, CharT>(); 186 187 # if !defined(TEST_HAS_NO_EXPERIMENTAL_TZDB) 188 assert_is_formattable<std::chrono::sys_info, CharT>(); 189 assert_is_formattable<std::chrono::local_info, CharT>(); 190 191 //assert_is_formattable<std::chrono::zoned_time, CharT>(); 192 # endif // !defined(TEST_HAS_NO_EXPERIMENTAL_TZDB) 193 194 #endif // TEST_HAS_NO_LOCALIZATION 195 } 196 197 // Tests for P1636 Formatters for library types 198 // 199 // The paper hasn't been voted in so currently all formatters are disabled. 200 // Note the paper has been abandoned, the types are kept since other papers may 201 // introduce these formatters. 202 template <class CharT> 203 void test_P1636() { 204 assert_is_not_formattable<std::basic_streambuf<CharT>, CharT>(); 205 assert_is_not_formattable<std::bitset<42>, CharT>(); 206 assert_is_not_formattable<std::complex<double>, CharT>(); 207 assert_is_not_formattable<std::error_code, CharT>(); 208 assert_is_not_formattable<std::filesystem::path, CharT>(); 209 assert_is_not_formattable<std::shared_ptr<int>, CharT>(); 210 #ifndef TEST_HAS_NO_LOCALIZATION 211 if constexpr (!std::same_as<CharT, int>) // sub_match only works with proper character types 212 assert_is_not_formattable<std::sub_match<CharT*>, CharT>(); 213 #endif 214 #ifndef TEST_HAS_NO_THREADS 215 assert_is_formattable<std::thread::id, CharT>(); 216 #endif 217 assert_is_not_formattable<std::unique_ptr<int>, CharT>(); 218 } 219 220 template <class CharT, class Vector> 221 void test_P2286_vector_bool() { 222 assert_is_formattable<Vector, CharT>(); 223 assert_is_formattable<typename Vector::reference, CharT>(); 224 225 // The const_reference shall be a bool. 226 // However libc++ uses a __bit_const_reference<vector> when 227 // _LIBCPP_ABI_BITSET_VECTOR_BOOL_CONST_SUBSCRIPT_RETURN_BOOL is defined. 228 assert_is_formattable<const Vector&, CharT>(); 229 assert_is_formattable<typename Vector::const_reference, CharT>(); 230 } 231 232 // Tests for P2286 Formatting ranges 233 template <class CharT> 234 void test_P2286() { 235 assert_is_formattable<std::array<int, 42>, CharT>(); 236 assert_is_formattable<std::vector<int>, CharT>(); 237 assert_is_formattable<std::deque<int>, CharT>(); 238 assert_is_formattable<std::forward_list<int>, CharT>(); 239 assert_is_formattable<std::list<int>, CharT>(); 240 241 assert_is_formattable<std::set<int>, CharT>(); 242 assert_is_formattable<std::map<int, int>, CharT>(); 243 assert_is_formattable<std::multiset<int>, CharT>(); 244 assert_is_formattable<std::multimap<int, int>, CharT>(); 245 246 #if TEST_STD_VER >= 23 247 // assert_is_formattable<std::flat_set<int>, CharT>(); 248 assert_is_formattable<std::flat_map<int, int>, CharT>(); 249 // assert_is_formattable<std::flat_multiset<int>, CharT>(); 250 assert_is_formattable<std::flat_multimap<int, int>, CharT>(); 251 #endif // TEST_STD_VER >= 2 252 253 assert_is_formattable<std::unordered_set<int>, CharT>(); 254 assert_is_formattable<std::unordered_map<int, int>, CharT>(); 255 assert_is_formattable<std::unordered_multiset<int>, CharT>(); 256 assert_is_formattable<std::unordered_multimap<int, int>, CharT>(); 257 258 assert_is_formattable<std::stack<int>, CharT>(); 259 assert_is_formattable<std::queue<int>, CharT>(); 260 assert_is_formattable<std::priority_queue<int>, CharT>(); 261 262 assert_is_formattable<std::span<int>, CharT>(); 263 264 assert_is_formattable<std::valarray<int>, CharT>(); 265 266 assert_is_formattable<std::pair<int, int>, CharT>(); 267 assert_is_formattable<std::tuple<int>, CharT>(); 268 269 test_P2286_vector_bool<CharT, std::vector<bool>>(); 270 test_P2286_vector_bool<CharT, std::vector<bool, std::allocator<bool>>>(); 271 test_P2286_vector_bool<CharT, std::vector<bool, min_allocator<bool>>>(); 272 } 273 274 // Tests volatile qualified objects are no longer formattable. 275 template <class CharT> 276 void test_LWG3631() { 277 assert_is_not_formattable<volatile CharT, CharT>(); 278 279 assert_is_not_formattable<volatile bool, CharT>(); 280 281 assert_is_not_formattable<volatile signed int, CharT>(); 282 assert_is_not_formattable<volatile unsigned int, CharT>(); 283 284 assert_is_not_formattable<volatile std::chrono::microseconds, CharT>(); 285 assert_is_not_formattable<volatile std::chrono::sys_time<std::chrono::microseconds>, CharT>(); 286 assert_is_not_formattable<volatile std::chrono::day, CharT>(); 287 288 assert_is_not_formattable<std::array<volatile int, 42>, CharT>(); 289 290 assert_is_not_formattable<std::pair<volatile int, int>, CharT>(); 291 assert_is_not_formattable<std::pair<int, volatile int>, CharT>(); 292 assert_is_not_formattable<std::pair<volatile int, volatile int>, CharT>(); 293 } 294 295 class c { 296 void f(); 297 void fc() const; 298 static void sf(); 299 }; 300 enum e { a }; 301 enum class ec { a }; 302 template <class CharT> 303 void test_disabled() { 304 #ifndef TEST_HAS_NO_WIDE_CHARACTERS 305 assert_is_not_formattable<const char*, wchar_t>(); 306 #endif 307 assert_is_not_formattable<const char*, char8_t>(); 308 assert_is_not_formattable<const char*, char16_t>(); 309 assert_is_not_formattable<const char*, char32_t>(); 310 311 assert_is_not_formattable<c, CharT>(); 312 assert_is_not_formattable<const c, CharT>(); 313 assert_is_not_formattable<volatile c, CharT>(); 314 assert_is_not_formattable<const volatile c, CharT>(); 315 316 assert_is_not_formattable<e, CharT>(); 317 assert_is_not_formattable<const e, CharT>(); 318 assert_is_not_formattable<volatile e, CharT>(); 319 assert_is_not_formattable<const volatile e, CharT>(); 320 321 assert_is_not_formattable<ec, CharT>(); 322 assert_is_not_formattable<const ec, CharT>(); 323 assert_is_not_formattable<volatile ec, CharT>(); 324 assert_is_not_formattable<const volatile ec, CharT>(); 325 326 assert_is_not_formattable<int*, CharT>(); 327 assert_is_not_formattable<const int*, CharT>(); 328 assert_is_not_formattable<volatile int*, CharT>(); 329 assert_is_not_formattable<const volatile int*, CharT>(); 330 331 assert_is_not_formattable<c*, CharT>(); 332 assert_is_not_formattable<const c*, CharT>(); 333 assert_is_not_formattable<volatile c*, CharT>(); 334 assert_is_not_formattable<const volatile c*, CharT>(); 335 336 assert_is_not_formattable<e*, CharT>(); 337 assert_is_not_formattable<const e*, CharT>(); 338 assert_is_not_formattable<volatile e*, CharT>(); 339 assert_is_not_formattable<const volatile e*, CharT>(); 340 341 assert_is_not_formattable<ec*, CharT>(); 342 assert_is_not_formattable<const ec*, CharT>(); 343 assert_is_not_formattable<volatile ec*, CharT>(); 344 assert_is_not_formattable<const volatile ec*, CharT>(); 345 346 assert_is_not_formattable<void (*)(), CharT>(); 347 assert_is_not_formattable<void (c::*)(), CharT>(); 348 assert_is_not_formattable<void (c::*)() const, CharT>(); 349 350 assert_is_not_formattable<std::optional<int>, CharT>(); 351 assert_is_not_formattable<std::variant<int>, CharT>(); 352 353 assert_is_not_formattable<std::shared_ptr<c>, CharT>(); 354 assert_is_not_formattable<std::unique_ptr<c>, CharT>(); 355 356 assert_is_not_formattable<std::array<c, 42>, CharT>(); 357 assert_is_not_formattable<std::vector<c>, CharT>(); 358 assert_is_not_formattable<std::deque<c>, CharT>(); 359 assert_is_not_formattable<std::forward_list<c>, CharT>(); 360 assert_is_not_formattable<std::list<c>, CharT>(); 361 362 assert_is_not_formattable<std::set<c>, CharT>(); 363 assert_is_not_formattable<std::map<c, int>, CharT>(); 364 assert_is_not_formattable<std::multiset<c>, CharT>(); 365 assert_is_not_formattable<std::multimap<c, int>, CharT>(); 366 367 assert_is_not_formattable<std::unordered_set<c>, CharT>(); 368 assert_is_not_formattable<std::unordered_map<c, int>, CharT>(); 369 assert_is_not_formattable<std::unordered_multiset<c>, CharT>(); 370 assert_is_not_formattable<std::unordered_multimap<c, int>, CharT>(); 371 372 assert_is_not_formattable<std::stack<c>, CharT>(); 373 assert_is_not_formattable<std::queue<c>, CharT>(); 374 assert_is_not_formattable<std::priority_queue<c>, CharT>(); 375 376 assert_is_not_formattable<std::span<c>, CharT>(); 377 378 assert_is_not_formattable<std::valarray<c>, CharT>(); 379 380 assert_is_not_formattable<std::pair<c, int>, CharT>(); 381 assert_is_not_formattable<std::tuple<c>, CharT>(); 382 383 assert_is_not_formattable<std::optional<c>, CharT>(); 384 assert_is_not_formattable<std::variant<c>, CharT>(); 385 } 386 387 struct abstract { 388 virtual ~abstract() = 0; 389 }; 390 391 template <class CharT> 392 requires std::same_as<CharT, char> 393 #ifndef TEST_HAS_NO_WIDE_CHARACTERS 394 || std::same_as<CharT, wchar_t> 395 #endif 396 struct std::formatter<abstract, CharT> { 397 template <class ParseContext> 398 constexpr typename ParseContext::iterator parse(ParseContext& parse_ctx) { 399 return parse_ctx.begin(); 400 } 401 402 template <class FormatContext> 403 typename FormatContext::iterator format(const abstract&, FormatContext& ctx) const { 404 return ctx.out(); 405 } 406 }; 407 408 template <class CharT> 409 void test_abstract_class() { 410 assert_is_formattable<abstract, CharT>(); 411 } 412 413 template <class CharT> 414 void test() { 415 test_P0645<CharT>(); 416 test_P1361<CharT>(); 417 test_P1636<CharT>(); 418 test_P2286<CharT>(); 419 test_LWG3631<CharT>(); 420 test_abstract_class<CharT>(); 421 test_disabled<CharT>(); 422 } 423 424 void test() { 425 test<char>(); 426 #ifndef TEST_HAS_NO_WIDE_CHARACTERS 427 test<wchar_t>(); 428 #endif 429 test<char8_t>(); 430 test<char16_t>(); 431 test<char32_t>(); 432 } 433