• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2
3import os
4from builtins import range
5from functools import reduce
6
7
8def get_libcxx_paths():
9    utils_path = os.path.dirname(os.path.abspath(__file__))
10    script_name = os.path.basename(__file__)
11    assert os.path.exists(utils_path)
12    src_root = os.path.dirname(utils_path)
13    include_path = os.path.join(src_root, "include")
14    assert os.path.exists(include_path)
15    docs_path = os.path.join(src_root, "docs")
16    assert os.path.exists(docs_path)
17    macro_test_path = os.path.join(
18        src_root,
19        "test",
20        "std",
21        "language.support",
22        "support.limits",
23        "support.limits.general",
24    )
25    assert os.path.exists(macro_test_path)
26    assert os.path.exists(
27        os.path.join(macro_test_path, "version.version.compile.pass.cpp")
28    )
29    return script_name, src_root, include_path, docs_path, macro_test_path
30
31
32script_name, source_root, include_path, docs_path, macro_test_path = get_libcxx_paths()
33
34
35def has_header(h):
36    h_path = os.path.join(include_path, h)
37    return os.path.exists(h_path)
38
39
40def add_version_header(tc):
41    tc["headers"].append("version")
42    return tc
43
44
45# ================  ============================================================
46# Field             Description
47# ================  ============================================================
48# name              The name of the feature-test macro.
49# values            A dict whose keys are C++ versions and whose values are the
50#                   value of the feature-test macro for that C++ version.
51#                   (TODO: This isn't a very clean model for feature-test
52#                   macros affected by multiple papers.)
53# headers           An array with the headers that should provide the
54#                   feature-test macro.
55# test_suite_guard  An optional string field. When this field is provided,
56#                   `libcxx_guard` must also be provided. This field is used
57#                   only to generate the unit tests for the feature-test macros.
58#                   It can't depend on macros defined in <__config> because the
59#                   `test/std/` parts of the test suite are intended to be
60#                   portable to any C++ standard library implementation, not
61#                   just libc++. It may depend on
62#                    * macros defined by the compiler itself, or
63#                    * macros generated by CMake.
64#                   In some cases we add also depend on macros defined in <__availability>.
65# libcxx_guard      An optional string field. When this field is provided,
66#                   `test_suite_guard` must also be provided. This field is used
67#                   only to guard the feature-test macro in <version>. It may
68#                   be the same as `test_suite_guard`, or it may depend on
69#                   macros defined in <__config>.
70# unimplemented     An optional Boolean field with the value `True`. This field
71#                   is only used when a feature isn't fully implemented. Once
72#                   you've fully implemented the feature, you should remove
73#                   this field.
74# ================  ============================================================
75feature_test_macros = [
76    add_version_header(x)
77    for x in [
78        {
79            "name": "__cpp_lib_adaptor_iterator_pair_constructor",
80            "values": {"c++23": 202106},
81            "headers": ["queue", "stack"],
82        },
83        {
84            "name": "__cpp_lib_addressof_constexpr",
85            "values": {"c++17": 201603},
86            "headers": ["memory"],
87        },
88        {
89            "name": "__cpp_lib_allocate_at_least",
90            "values": {
91                "c++23": 202106,
92                # Note LWG3887 Version macro for allocate_at_least
93                # "c++26": 202302, # P2652R2 Disallow User Specialization of allocator_traits
94            },
95            "headers": ["memory"],
96        },
97        {
98            "name": "__cpp_lib_allocator_traits_is_always_equal",
99            "values": {"c++17": 201411},
100            "headers": [
101                "deque",
102                "forward_list",
103                "list",
104                "map",
105                "memory",
106                "scoped_allocator",
107                "set",
108                "string",
109                "unordered_map",
110                "unordered_set",
111                "vector",
112            ],
113        },
114        {
115            "name": "__cpp_lib_any",
116            "values": {"c++17": 201606},
117            "headers": ["any"],
118        },
119        {
120            "name": "__cpp_lib_apply",
121            "values": {"c++17": 201603},
122            "headers": ["tuple"],
123        },
124        {
125            "name": "__cpp_lib_array_constexpr",
126            "values": {"c++17": 201603, "c++20": 201811},
127            "headers": ["array", "iterator"],
128        },
129        {
130            "name": "__cpp_lib_as_const",
131            "values": {"c++17": 201510},
132            "headers": ["utility"],
133        },
134        {
135            "name": "__cpp_lib_associative_heterogeneous_erasure",
136            "values": {"c++23": 202110},
137            "headers": ["map", "set", "unordered_map", "unordered_set"],
138            "unimplemented": True,
139        },
140        {
141            "name": "__cpp_lib_associative_heterogeneous_insertion",
142            "values": {
143                "c++26": 202306  # P2363R5 Extending associative containers with the remaining heterogeneous overloads
144            },
145            "headers": ["map", "set", "unordered_map", "unordered_set"],
146            "unimplemented": True,
147        },
148        {
149            "name": "__cpp_lib_assume_aligned",
150            "values": {"c++20": 201811},
151            "headers": ["memory"],
152        },
153        {
154            "name": "__cpp_lib_atomic_flag_test",
155            "values": {"c++20": 201907},
156            "headers": ["atomic"],
157        },
158        {
159            "name": "__cpp_lib_atomic_float",
160            "values": {"c++20": 201711},
161            "headers": ["atomic"],
162            "unimplemented": True,
163        },
164        {
165            "name": "__cpp_lib_atomic_is_always_lock_free",
166            "values": {"c++17": 201603},
167            "headers": ["atomic"],
168        },
169        {
170            "name": "__cpp_lib_atomic_lock_free_type_aliases",
171            "values": {"c++20": 201907},
172            "headers": ["atomic"],
173        },
174        {
175            "name": "__cpp_lib_atomic_ref",
176            "values": {"c++20": 201806},
177            "headers": ["atomic"],
178            "unimplemented": True,
179        },
180        {
181            "name": "__cpp_lib_atomic_shared_ptr",
182            "values": {"c++20": 201711},
183            "headers": ["atomic"],
184            "unimplemented": True,
185        },
186        {
187            "name": "__cpp_lib_atomic_value_initialization",
188            "values": {"c++20": 201911},
189            "headers": ["atomic", "memory"],
190        },
191        {
192            "name": "__cpp_lib_atomic_wait",
193            "values": {"c++20": 201907},
194            "headers": ["atomic"],
195            "test_suite_guard": "!defined(_LIBCPP_VERSION) || _LIBCPP_AVAILABILITY_HAS_SYNC",
196            "libcxx_guard": "_LIBCPP_AVAILABILITY_HAS_SYNC",
197        },
198        {
199            "name": "__cpp_lib_barrier",
200            "values": {"c++20": 201907},
201            "headers": ["barrier"],
202            "test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && (!defined(_LIBCPP_VERSION) || _LIBCPP_AVAILABILITY_HAS_SYNC)",
203            "libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && _LIBCPP_AVAILABILITY_HAS_SYNC",
204        },
205        {
206            "name": "__cpp_lib_bind_back",
207            "values": {
208                "c++23": 202202,
209                "c++26": 202306,  # P2714R1 Bind front and back to NTTP callables
210            },
211            "headers": ["functional"],
212            "unimplemented": True,
213        },
214        {
215            "name": "__cpp_lib_bind_front",
216            "values": {
217                "c++20": 201907,
218                "c++26": 202306,  # P2714R1 Bind front and back to NTTP callables
219            },
220            "headers": ["functional"],
221        },
222        {
223            "name": "__cpp_lib_bit_cast",
224            "values": {"c++20": 201806},
225            "headers": ["bit"],
226        },
227        {
228            "name": "__cpp_lib_bitops",
229            "values": {"c++20": 201907},
230            "headers": ["bit"],
231        },
232        {
233            "name": "__cpp_lib_bitset",
234            "values": {"c++26": 202306},  # P2697R1 Interfacing bitset with string_view
235            "headers": ["bitset"],
236        },
237        {
238            "name": "__cpp_lib_bool_constant",
239            "values": {"c++17": 201505},
240            "headers": ["type_traits"],
241        },
242        {
243            "name": "__cpp_lib_bounded_array_traits",
244            "values": {"c++20": 201902},
245            "headers": ["type_traits"],
246        },
247        {
248            "name": "__cpp_lib_boyer_moore_searcher",
249            "values": {"c++17": 201603},
250            "headers": ["functional"],
251        },
252        {
253            "name": "__cpp_lib_byte",
254            "values": {"c++17": 201603},
255            "headers": ["cstddef"],
256        },
257        {
258            "name": "__cpp_lib_byteswap",
259            "values": {"c++23": 202110},
260            "headers": ["bit"],
261        },
262        {
263            "name": "__cpp_lib_char8_t",
264            "values": {"c++20": 201907},
265            "headers": [
266                "atomic",
267                "filesystem",
268                "istream",
269                "limits",
270                "locale",
271                "ostream",
272                "string",
273                "string_view",
274            ],
275            "test_suite_guard": "defined(__cpp_char8_t)",
276            "libcxx_guard": "!defined(_LIBCPP_HAS_NO_CHAR8_T)",
277        },
278        {
279            "name": "__cpp_lib_chrono",
280            "values": {
281                "c++17": 201611,
282                # "c++26": 202306, # P2592R3 Hashing support for std::chrono value classes
283            },
284            "headers": ["chrono"],
285        },
286        {
287            "name": "__cpp_lib_chrono_udls",
288            "values": {"c++14": 201304},
289            "headers": ["chrono"],
290        },
291        {
292            "name": "__cpp_lib_clamp",
293            "values": {"c++17": 201603},
294            "headers": ["algorithm"],
295        },
296        {
297            "name": "__cpp_lib_complex_udls",
298            "values": {"c++14": 201309},
299            "headers": ["complex"],
300        },
301        {
302            "name": "__cpp_lib_concepts",
303            "values": {"c++20": 202002},
304            "headers": ["concepts"],
305        },
306        {
307            "name": "__cpp_lib_constexpr_algorithms",
308            "values": {
309                "c++20": 201806,
310                # "c++26": 202306, # P2562R1 constexpr Stable Sorting
311            },
312            "headers": ["algorithm", "utility"],
313        },
314        {
315            "name": "__cpp_lib_constexpr_bitset",
316            "values": {"c++23": 202207},
317            "headers": ["bitset"],
318        },
319        {
320            "name": "__cpp_lib_constexpr_charconv",
321            "values": {"c++23": 202207},
322            "headers": ["charconv"],
323        },
324        {
325            "name": "__cpp_lib_constexpr_cmath",
326            "values": {"c++23": 202202},
327            "headers": ["cmath", "cstdlib"],
328            "unimplemented": True,
329        },
330        {
331            "name": "__cpp_lib_constexpr_complex",
332            "values": {"c++20": 201711},
333            "headers": ["complex"],
334        },
335        {
336            "name": "__cpp_lib_constexpr_dynamic_alloc",
337            "values": {"c++20": 201907},
338            "headers": ["memory"],
339        },
340        {
341            "name": "__cpp_lib_constexpr_functional",
342            "values": {"c++20": 201907},
343            "headers": ["functional"],
344        },
345        {
346            "name": "__cpp_lib_constexpr_iterator",
347            "values": {"c++20": 201811},
348            "headers": ["iterator"],
349        },
350        {
351            "name": "__cpp_lib_constexpr_memory",
352            "values": {"c++20": 201811, "c++23": 202202},
353            "headers": ["memory"],
354        },
355        {
356            "name": "__cpp_lib_constexpr_numeric",
357            "values": {"c++20": 201911},
358            "headers": ["numeric"],
359        },
360        {
361            "name": "__cpp_lib_constexpr_string",
362            "values": {"c++20": 201907},
363            "headers": ["string"],
364        },
365        {
366            "name": "__cpp_lib_constexpr_string_view",
367            "values": {"c++20": 201811},
368            "headers": ["string_view"],
369        },
370        {
371            "name": "__cpp_lib_constexpr_tuple",
372            "values": {"c++20": 201811},
373            "headers": ["tuple"],
374        },
375        {
376            "name": "__cpp_lib_constexpr_typeinfo",
377            "values": {"c++23": 202106},
378            "headers": ["typeinfo"],
379        },
380        {
381            "name": "__cpp_lib_constexpr_utility",
382            "values": {"c++20": 201811},
383            "headers": ["utility"],
384        },
385        {
386            "name": "__cpp_lib_constexpr_vector",
387            "values": {"c++20": 201907},
388            "headers": ["vector"],
389        },
390        {
391            "name": "__cpp_lib_copyable_function",
392            "values": {"c++26": 202306},  # P2548R6 copyable_function
393            "headers": ["functional"],
394            "unimplemented": True,
395        },
396        {
397            "name": "__cpp_lib_coroutine",
398            "values": {"c++20": 201902},
399            "headers": ["coroutine"],
400        },
401        {
402            "name": "__cpp_lib_debugging",
403            "values": {"c++26": 202311},  # P2546R5 Debugging Support
404            "headers": ["debugging"],
405            "unimplemented": True,
406        },
407        {
408            "name": "__cpp_lib_destroying_delete",
409            "values": {"c++20": 201806},
410            "headers": ["new"],
411            "test_suite_guard": "TEST_STD_VER > 17 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L",
412            "libcxx_guard": "_LIBCPP_STD_VER >= 20 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L",
413        },
414        {
415            "name": "__cpp_lib_enable_shared_from_this",
416            "values": {"c++17": 201603},
417            "headers": ["memory"],
418        },
419        {
420            "name": "__cpp_lib_endian",
421            "values": {"c++20": 201907},
422            "headers": ["bit"],
423        },
424        {
425            "name": "__cpp_lib_erase_if",
426            "values": {"c++20": 202002},
427            "headers": [
428                "deque",
429                "forward_list",
430                "list",
431                "map",
432                "set",
433                "string",
434                "unordered_map",
435                "unordered_set",
436                "vector",
437            ],
438        },
439        {
440            "name": "__cpp_lib_exchange_function",
441            "values": {"c++14": 201304},
442            "headers": ["utility"],
443        },
444        {
445            "name": "__cpp_lib_execution",
446            "values": {"c++17": 201603, "c++20": 201902},
447            "headers": ["execution"],
448            "unimplemented": True,
449        },
450        {
451            "name": "__cpp_lib_expected",
452            "values": {"c++23": 202211},
453            "headers": ["expected"],
454        },
455        {
456            "name": "__cpp_lib_filesystem",
457            "values": {"c++17": 201703},
458            "headers": ["filesystem"],
459            "test_suite_guard": "!defined(_LIBCPP_VERSION) || _LIBCPP_AVAILABILITY_HAS_FILESYSTEM_LIBRARY",
460            "libcxx_guard": "_LIBCPP_AVAILABILITY_HAS_FILESYSTEM_LIBRARY",
461        },
462        {
463            "name": "__cpp_lib_format",
464            "values": {
465                # "c++20": 201907 Not implemented P1361R2 Integration of chrono with text formatting
466                # "c++20": 202106 Fully implemented
467                # "c++20": 202110 Not implemented P2372R3 Fixing locale handling in chrono formatters
468                "c++20": 202106,
469                # "c++23": 202207, Not implemented P2419R2 Clarify handling of encodings in localized formatting of chrono types
470                # "c++26": 202311, P2918R2 Runtime format strings II (implemented)
471            },
472            # Note these three papers are adopted at the June 2023 meeting and have sequential numbering
473            # 202304 P2510R3 Formatting pointers (Implemented)
474            # 202305 P2757R3 Type-checking format args
475            # 202306 P2637R3 Member Visit
476            "headers": ["format"],
477            "unimplemented": True,
478        },
479        {
480            "name": "__cpp_lib_format_ranges",
481            "values": {"c++23": 202207},
482            "headers": ["format"],
483        },
484        {
485            "name": "__cpp_lib_format_uchar",
486            "values": {
487                "c++20": 202311  # DR P2909R4 Fix formatting of code units as integers
488            },
489            "headers": [""],  # Note not in format
490        },
491        {
492            "name": "__cpp_lib_formatters",
493            "values": {"c++23": 202302},
494            "headers": ["stacktrace", "thread"],
495            "unimplemented": True,
496        },
497        {
498            "name": "__cpp_lib_forward_like",
499            "values": {"c++23": 202207},
500            "headers": ["utility"],
501        },
502        {
503            "name": "__cpp_lib_freestanding_algorithm",
504            "values": {
505                "c++26": 202311  # P2407R5 Freestanding Library: Partial Classes
506            },
507            "headers": ["algorithm"],
508            "unimplemented": True,
509        },
510        {
511            "name": "__cpp_lib_freestanding_array",
512            "values": {
513                "c++26": 202311  # P2407R5 Freestanding Library: Partial Classes
514            },
515            "headers": ["array"],
516            "unimplemented": True,
517        },
518        {
519            "name": "__cpp_lib_freestanding_cstring",
520            "values": {
521                "c++26": 202306  # P2338R4 Freestanding Library: Character primitives and the C library
522                #        202311  # P2407R5 Freestanding Library: Partial Classes
523            },
524            "headers": ["cstring"],
525            "unimplemented": True,
526        },
527        {
528            "name": "__cpp_lib_freestanding_expected",
529            "values": {
530                "c++26": 202311  # P2833R2 Freestanding Library: inout expected span
531            },
532            "headers": ["expected"],
533            "unimplemented": True,
534        },
535        {
536            "name": "__cpp_lib_freestanding_mdspan",
537            "values": {
538                "c++26": 202311  # P2833R2 Freestanding Library: inout expected span
539            },
540            "headers": ["mdspan"],
541            "unimplemented": True,
542        },
543        {
544            "name": "__cpp_lib_freestanding_optional",
545            "values": {
546                "c++26": 202311  # P2407R5 Freestanding Library: Partial Classes
547            },
548            "headers": ["optional"],
549            "unimplemented": True,
550        },
551        {
552            "name": "__cpp_lib_freestanding_string_view",
553            "values": {
554                "c++26": 202311  # P2407R5 Freestanding Library: Partial Classes
555            },
556            "headers": ["string_view"],
557            "unimplemented": True,
558        },
559        {
560            "name": "__cpp_lib_freestanding_variant",
561            "values": {
562                "c++26": 202311  # P2407R5 Freestanding Library: Partial Classes
563            },
564            "headers": ["variant"],
565            "unimplemented": True,
566        },
567        {
568            "name": "__cpp_lib_fstream_native_handle",
569            "values": {"c++26": 202306},  # P1759R6 Native handles and file streams
570            "headers": ["fstream"],
571            "unimplemented": True,
572        },
573        {
574            "name": "__cpp_lib_function_ref",
575            "values": {
576                "c++26": 202306  # P0792R14 function_ref: a type-erased callable reference
577            },
578            "headers": ["functional"],
579            "unimplemented": True,
580        },
581        {
582            "name": "__cpp_lib_gcd_lcm",
583            "values": {"c++17": 201606},
584            "headers": ["numeric"],
585        },
586        {
587            "name": "__cpp_lib_generic_associative_lookup",
588            "values": {"c++14": 201304},
589            "headers": ["map", "set"],
590        },
591        {
592            "name": "__cpp_lib_generic_unordered_lookup",
593            "values": {"c++20": 201811},
594            "headers": ["unordered_map", "unordered_set"],
595        },
596        {
597            "name": "__cpp_lib_hardware_interference_size",
598            "values": {"c++17": 201703},
599            "test_suite_guard": "!defined(_LIBCPP_VERSION) || (defined(__GCC_DESTRUCTIVE_SIZE) && defined(__GCC_CONSTRUCTIVE_SIZE))",
600            "libcxx_guard": "defined(__GCC_DESTRUCTIVE_SIZE) && defined(__GCC_CONSTRUCTIVE_SIZE)",
601            "headers": ["new"],
602        },
603        {
604            "name": "__cpp_lib_has_unique_object_representations",
605            "values": {"c++17": 201606},
606            "headers": ["type_traits"],
607        },
608        {
609            "name": "__cpp_lib_hazard_pointer",
610            "values": {"c++26": 202306},  # P2530R3 Hazard Pointers for C++26
611            "headers": [
612                "hazard_pointer"  # TODO verify this entry since the paper was underspecified.
613            ],
614            "unimplemented": True,
615        },
616        {
617            "name": "__cpp_lib_hypot",
618            "values": {"c++17": 201603},
619            "headers": ["cmath"],
620        },
621        {
622            "name": "__cpp_lib_incomplete_container_elements",
623            "values": {"c++17": 201505},
624            "headers": ["forward_list", "list", "vector"],
625        },
626        {
627            "name": "__cpp_lib_int_pow2",
628            "values": {"c++20": 202002},
629            "headers": ["bit"],
630        },
631        {
632            "name": "__cpp_lib_integer_comparison_functions",
633            "values": {"c++20": 202002},
634            "headers": ["utility"],
635        },
636        {
637            "name": "__cpp_lib_integer_sequence",
638            "values": {"c++14": 201304},
639            "headers": ["utility"],
640        },
641        {
642            "name": "__cpp_lib_integral_constant_callable",
643            "values": {"c++14": 201304},
644            "headers": ["type_traits"],
645        },
646        {
647            "name": "__cpp_lib_interpolate",
648            "values": {"c++20": 201902},
649            "headers": ["cmath", "numeric"],
650        },
651        {
652            "name": "__cpp_lib_invoke",
653            "values": {"c++17": 201411},
654            "headers": ["functional"],
655        },
656        {
657            "name": "__cpp_lib_invoke_r",
658            "values": {"c++23": 202106},
659            "headers": ["functional"],
660        },
661        {
662            "name": "__cpp_lib_ios_noreplace",
663            "values": { "c++23": 202207 },
664            "headers": ["ios"],
665        },
666        {
667            "name": "__cpp_lib_is_aggregate",
668            "values": {"c++17": 201703},
669            "headers": ["type_traits"],
670        },
671        {
672            "name": "__cpp_lib_is_constant_evaluated",
673            "values": {"c++20": 201811},
674            "headers": ["type_traits"],
675        },
676        {
677            "name": "__cpp_lib_is_final",
678            "values": {"c++14": 201402},
679            "headers": ["type_traits"],
680        },
681        {
682            "name": "__cpp_lib_is_invocable",
683            "values": {"c++17": 201703},
684            "headers": ["type_traits"],
685        },
686        {
687            "name": "__cpp_lib_is_layout_compatible",
688            "values": {"c++20": 201907},
689            "headers": ["type_traits"],
690            "unimplemented": True,
691        },
692        {
693            "name": "__cpp_lib_is_nothrow_convertible",
694            "values": {"c++20": 201806},
695            "headers": ["type_traits"],
696        },
697        {
698            "name": "__cpp_lib_is_null_pointer",
699            "values": {"c++14": 201309},
700            "headers": ["type_traits"],
701        },
702        {
703            "name": "__cpp_lib_is_pointer_interconvertible",
704            "values": {"c++20": 201907},
705            "headers": ["type_traits"],
706            "unimplemented": True,
707        },
708        {
709            "name": "__cpp_lib_is_scoped_enum",
710            "values": {"c++23": 202011},
711            "headers": ["type_traits"],
712        },
713        {
714            "name": "__cpp_lib_is_swappable",
715            "values": {"c++17": 201603},
716            "headers": ["type_traits"],
717        },
718        {
719            "name": "__cpp_lib_jthread",
720            "values": {"c++20": 201911},
721            "headers": ["stop_token", "thread"],
722            "test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) && (!defined(_LIBCPP_VERSION) || _LIBCPP_AVAILABILITY_HAS_SYNC)",
723            "libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_HAS_NO_EXPERIMENTAL_STOP_TOKEN) && _LIBCPP_AVAILABILITY_HAS_SYNC",
724        },
725        {
726            "name": "__cpp_lib_latch",
727            "values": {"c++20": 201907},
728            "headers": ["latch"],
729            "test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && (!defined(_LIBCPP_VERSION) || _LIBCPP_AVAILABILITY_HAS_SYNC)",
730            "libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && _LIBCPP_AVAILABILITY_HAS_SYNC",
731        },
732        {
733            "name": "__cpp_lib_launder",
734            "values": {"c++17": 201606},
735            "headers": ["new"],
736        },
737        {
738            "name": "__cpp_lib_linalg",
739            "values": {
740                "c++26": 202311  # P1673 A free function linear algebra interface based on the BLAS
741            },
742            "headers": ["linalg"],
743            "unimplemented": True,
744        },
745        {
746            "name": "__cpp_lib_list_remove_return_type",
747            "values": {"c++20": 201806},
748            "headers": ["forward_list", "list"],
749        },
750        {
751            "name": "__cpp_lib_logical_traits",
752            "values": {"c++17": 201510},
753            "headers": ["type_traits"],
754        },
755        {
756            "name": "__cpp_lib_make_from_tuple",
757            "values": {"c++17": 201606},
758            "headers": ["tuple"],
759        },
760        {
761            "name": "__cpp_lib_make_reverse_iterator",
762            "values": {"c++14": 201402},
763            "headers": ["iterator"],
764        },
765        {
766            "name": "__cpp_lib_make_unique",
767            "values": {"c++14": 201304},
768            "headers": ["memory"],
769        },
770        {
771            "name": "__cpp_lib_map_try_emplace",
772            "values": {"c++17": 201411},
773            "headers": ["map"],
774        },
775        {
776            "name": "__cpp_lib_math_constants",
777            "values": {"c++20": 201907},
778            "headers": ["numbers"],
779        },
780        {
781            "name": "__cpp_lib_math_special_functions",
782            "values": {"c++17": 201603},
783            "headers": ["cmath"],
784            "unimplemented": True,
785        },
786        {
787            "name": "__cpp_lib_mdspan",
788            "values": {"c++23": 202207},
789            "headers": ["mdspan"],
790        },
791        {
792            "name": "__cpp_lib_memory_resource",
793            "values": {"c++17": 201603},
794            "headers": ["memory_resource"],
795            "test_suite_guard": "!defined(_LIBCPP_VERSION) || _LIBCPP_AVAILABILITY_HAS_PMR",
796            "libcxx_guard": "_LIBCPP_AVAILABILITY_HAS_PMR",
797        },
798        {
799            "name": "__cpp_lib_move_iterator_concept",
800            "values": {"c++20": 202207},
801            "headers": ["iterator"],
802        },
803        {
804            "name": "__cpp_lib_move_only_function",
805            "values": {"c++23": 202110},
806            "headers": ["functional"],
807            "unimplemented": True,
808        },
809        {
810            "name": "__cpp_lib_node_extract",
811            "values": {"c++17": 201606},
812            "headers": ["map", "set", "unordered_map", "unordered_set"],
813        },
814        {
815            "name": "__cpp_lib_nonmember_container_access",
816            "values": {"c++17": 201411},
817            "headers": [
818                "array",
819                "deque",
820                "forward_list",
821                "iterator",
822                "list",
823                "map",
824                "regex",
825                "set",
826                "string",
827                "unordered_map",
828                "unordered_set",
829                "vector",
830            ],
831        },
832        {
833            "name": "__cpp_lib_not_fn",
834            "values": {
835                "c++17": 201603,
836                # "c++26": 202306, # P2714R1 Bind front and back to NTTP callables
837            },
838            "headers": ["functional"],
839        },
840        {
841            "name": "__cpp_lib_null_iterators",
842            "values": {"c++14": 201304},
843            "headers": ["iterator"],
844        },
845        {
846            "name": "__cpp_lib_optional",
847            "values": {"c++17": 201606, "c++23": 202110},
848            "headers": ["optional"],
849        },
850        {
851            "name": "__cpp_lib_out_ptr",
852            "values": {
853                "c++23": 202106,
854                "c++26": 202311,  # P2833R2 Freestanding Library: inout expected span
855            },
856            "headers": ["memory"],
857            "unimplemented": True,
858        },
859        {
860            "name": "__cpp_lib_parallel_algorithm",
861            "values": {"c++17": 201603},
862            "headers": ["algorithm", "numeric"],
863            "unimplemented": True,
864        },
865        {
866            "name": "__cpp_lib_polymorphic_allocator",
867            "values": {"c++20": 201902},
868            "headers": ["memory_resource"],
869            "test_suite_guard": "!defined(_LIBCPP_VERSION) || _LIBCPP_AVAILABILITY_HAS_PMR",
870            "libcxx_guard": "_LIBCPP_AVAILABILITY_HAS_PMR",
871        },
872        {
873            "name": "__cpp_lib_print",
874            "values": {"c++23": 202207},
875            "headers": ["ostream", "print"],
876            "unimplemented": True,
877        },
878        {
879            "name": "__cpp_lib_quoted_string_io",
880            "values": {"c++14": 201304},
881            "headers": ["iomanip"],
882        },
883        {
884            "name": "__cpp_lib_ranges",
885            "values": {"c++20": 202207},
886            "headers": ["algorithm", "functional", "iterator", "memory", "ranges"],
887        },
888        {
889            "name": "__cpp_lib_ranges_as_const",
890            "values": {
891                "c++23": 202207  # P2278R4 cbegin should always return a constant iterator
892                #        202311  # DR P2836R1 std::basic_const_iterator should follow its underlying type’s convertibility
893            },
894            "headers": ["ranges"],
895            "unimplemented": True,
896        },
897        {
898            "name": "__cpp_lib_ranges_as_rvalue",
899            "values": {"c++23": 202207},
900            "headers": ["ranges"],
901        },
902        {
903            "name": "__cpp_lib_ranges_chunk",
904            "values": {"c++23": 202202},
905            "headers": ["ranges"],
906            "unimplemented": True,
907        },
908        {
909            "name": "__cpp_lib_ranges_chunk_by",
910            "values": {"c++23": 202202},
911            "headers": ["ranges"],
912        },
913        {
914            "name": "__cpp_lib_ranges_iota",
915            "values": {"c++23": 202202},
916            "headers": ["numeric"],
917            "unimplemented": True,
918        },
919        {
920            "name": "__cpp_lib_ranges_join_with",
921            "values": {"c++23": 202202},
922            "headers": ["ranges"],
923            "unimplemented": True,
924        },
925        {
926            "name": "__cpp_lib_ranges_repeat",
927            "values": {"c++23": 202207},
928            "headers": ["ranges"],
929        },
930        {
931            "name": "__cpp_lib_ranges_slide",
932            "values": {"c++23": 202202},
933            "headers": ["ranges"],
934            "unimplemented": True,
935        },
936        {
937            "name": "__cpp_lib_ranges_starts_ends_with",
938            "values": {"c++23": 202106},
939            "headers": ["algorithm"],
940            "unimplemented": True,
941        },
942        {
943            "name": "__cpp_lib_ranges_to_container",
944            "values": {"c++23": 202202},
945            "headers": [
946                "deque",
947                "forward_list",
948                "list",
949                "map",
950                "queue",
951                "ranges",
952                "set",
953                "stack",
954                "string",
955                "unordered_map",
956                "unordered_set",
957                "vector",
958            ],
959        },
960        {
961            "name": "__cpp_lib_ranges_zip",
962            "values": {"c++23": 202110},
963            "headers": ["ranges", "tuple", "utility"],
964            "unimplemented": True,
965        },
966        {
967            "name": "__cpp_lib_ratio",
968            "values": {"c++26": 202306},  # P2734R0 Adding the new SI prefixes
969            "headers": ["ratio"],
970        },
971        {
972            "name": "__cpp_lib_raw_memory_algorithms",
973            "values": {"c++17": 201606},
974            "headers": ["memory"],
975        },
976        {
977            "name": "__cpp_lib_rcu",
978            "values": {"c++26": 202306},  # P2545R4 Read-Copy Update (RCU)
979            "headers": [
980                "rcu"  # TODO verify this entry since the paper was underspecified.
981            ],
982            "unimplemented": True,
983        },
984        {
985            "name": "__cpp_lib_reference_from_temporary",
986            "values": {"c++23": 202202},
987            "headers": ["type_traits"],
988            "unimplemented": True,
989        },
990        {
991            "name": "__cpp_lib_remove_cvref",
992            "values": {"c++20": 201711},
993            "headers": ["type_traits"],
994        },
995        {
996            "name": "__cpp_lib_result_of_sfinae",
997            "values": {"c++14": 201210},
998            "headers": ["functional", "type_traits"],
999        },
1000        {
1001            "name": "__cpp_lib_robust_nonmodifying_seq_ops",
1002            "values": {"c++14": 201304},
1003            "headers": ["algorithm"],
1004        },
1005        {
1006            "name": "__cpp_lib_sample",
1007            "values": {"c++17": 201603},
1008            "headers": ["algorithm"],
1009        },
1010        {
1011            "name": "__cpp_lib_saturation_arithmetic",
1012            "values": {"c++26": 202311},  # P0543R3 Saturation arithmetic
1013            "headers": [""],  # Note not in <numerics>
1014            "unimplemented": True,
1015        },
1016        {
1017            "name": "__cpp_lib_scoped_lock",
1018            "values": {"c++17": 201703},
1019            "headers": ["mutex"],
1020        },
1021        {
1022            "name": "__cpp_lib_semaphore",
1023            "values": {"c++20": 201907},
1024            "headers": ["semaphore"],
1025            "test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && (!defined(_LIBCPP_VERSION) || _LIBCPP_AVAILABILITY_HAS_SYNC)",
1026            "libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && _LIBCPP_AVAILABILITY_HAS_SYNC",
1027        },
1028        {
1029            "name": "__cpp_lib_shared_mutex",
1030            "values": {"c++17": 201505},
1031            "headers": ["shared_mutex"],
1032            "test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS)",
1033            "libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS)",
1034        },
1035        {
1036            "name": "__cpp_lib_shared_ptr_arrays",
1037            "values": {"c++17": 201611, "c++20": 201707},
1038            "headers": ["memory"],
1039        },
1040        {
1041            "name": "__cpp_lib_shared_ptr_weak_type",
1042            "values": {"c++17": 201606},
1043            "headers": ["memory"],
1044        },
1045        {
1046            "name": "__cpp_lib_shared_timed_mutex",
1047            "values": {"c++14": 201402},
1048            "headers": ["shared_mutex"],
1049            "test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS)",
1050            "libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS)",
1051        },
1052        {
1053            "name": "__cpp_lib_shift",
1054            "values": {"c++20": 201806},
1055            "headers": ["algorithm"],
1056        },
1057        {
1058            "name": "__cpp_lib_smart_ptr_for_overwrite",
1059            "values": {"c++20": 202002},
1060            "headers": ["memory"],
1061            "unimplemented": True,
1062        },
1063        {
1064            "name": "__cpp_lib_smart_ptr_owner_equality",
1065            "values": {
1066                "c++26": 202306  # P1901R2 Enabling the Use of weak_ptr as Keys in Unordered Associative Containers
1067            },
1068            "headers": ["memory"],
1069            "unimplemented": True,
1070        },
1071        {
1072            "name": "__cpp_lib_source_location",
1073            "values": {"c++20": 201907},
1074            "headers": ["source_location"],
1075            "test_suite_guard": "__has_builtin(__builtin_source_location) && !(defined(TEST_APPLE_CLANG_VER) && TEST_APPLE_CLANG_VER <= 1403)",
1076            "libcxx_guard": "__has_builtin(__builtin_source_location) && !(defined(_LIBCPP_APPLE_CLANG_VER) && _LIBCPP_APPLE_CLANG_VER <= 1403)",
1077        },
1078        {
1079            "name": "__cpp_lib_span",
1080            "values": {
1081                "c++20": 202002,
1082                # "c++26": 202311,  # P2821R5 span.at()
1083                #          202311   # P2833R2 Freestanding Library: inout expected span
1084            },
1085            "headers": ["span"],
1086        },
1087        {
1088            "name": "__cpp_lib_span_initializer_list",
1089            "values": {"c++26": 202311},  # P2447R6 std::span over an initializer list
1090            "headers": ["span"],
1091            "unimplemented": True,
1092        },
1093        {
1094            "name": "__cpp_lib_spanstream",
1095            "values": {"c++23": 202106},
1096            "headers": ["spanstream"],
1097            "unimplemented": True,
1098        },
1099        {
1100            "name": "__cpp_lib_ssize",
1101            "values": {"c++20": 201902},
1102            "headers": ["iterator"],
1103        },
1104        {
1105            "name": "__cpp_lib_sstream_from_string_view",
1106            "values": {
1107                "c++26": 202306  # P2495R3 Interfacing stringstreams with string_view
1108            },
1109            "headers": ["sstream"],
1110            "unimplemented": True,
1111        },
1112        {
1113            "name": "__cpp_lib_stacktrace",
1114            "values": {"c++23": 202011},
1115            "headers": ["stacktrace"],
1116            "unimplemented": True,
1117        },
1118        {
1119            "name": "__cpp_lib_starts_ends_with",
1120            "values": {"c++20": 201711},
1121            "headers": ["string", "string_view"],
1122        },
1123        {
1124            "name": "__cpp_lib_stdatomic_h",
1125            "values": {"c++23": 202011},
1126            "headers": ["stdatomic.h"],
1127        },
1128        {
1129            "name": "__cpp_lib_string_contains",
1130            "values": {"c++23": 202011},
1131            "headers": ["string", "string_view"],
1132        },
1133        {
1134            "name": "__cpp_lib_string_resize_and_overwrite",
1135            "values": {"c++23": 202110},
1136            "headers": ["string"],
1137        },
1138        {
1139            "name": "__cpp_lib_string_udls",
1140            "values": {"c++14": 201304},
1141            "headers": ["string"],
1142        },
1143        {
1144            "name": "__cpp_lib_string_view",
1145            "values": {"c++17": 201606, "c++20": 201803},
1146            "headers": ["string", "string_view"],
1147        },
1148        {
1149            "name": "__cpp_lib_submdspan",
1150            "values": {"c++26": 202306},  # P2630R4 submdspan
1151            "headers": ["mdspan"],
1152            "unimplemented": True,
1153        },
1154        {
1155            "name": "__cpp_lib_syncbuf",
1156            "values": {"c++20": 201803},
1157            "headers": ["syncstream"],
1158            "test_suite_guard": "!defined(_LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM)",
1159            "libcxx_guard": "!defined(_LIBCPP_HAS_NO_EXPERIMENTAL_SYNCSTREAM)",
1160        },
1161        {
1162            "name": "__cpp_lib_text_encoding",
1163            "values": {
1164                "c++26": 202306  # P1885R12 Naming Text Encodings to Demystify Them
1165            },
1166            "headers": ["text_encoding"],
1167            "unimplemented": True,
1168        },
1169        {
1170            "name": "__cpp_lib_three_way_comparison",
1171            "values": {"c++20": 201907},
1172            "headers": ["compare"],
1173            "unimplemented": True,
1174        },
1175        {
1176            "name": "__cpp_lib_to_address",
1177            "values": {"c++20": 201711},
1178            "headers": ["memory"],
1179        },
1180        {
1181            "name": "__cpp_lib_to_array",
1182            "values": {"c++20": 201907},
1183            "headers": ["array"],
1184        },
1185        {
1186            "name": "__cpp_lib_to_chars",
1187            "values": {
1188                "c++17": 201611,
1189                "c++26": 202306,  # P2497R0 Testing for success or failure of <charconv> functions
1190            },
1191            "headers": ["charconv"],
1192            "unimplemented": True,
1193        },
1194        {
1195            "name": "__cpp_lib_to_string",
1196            "values": {"c++23": 202306},  # P2587R3 to_string or not to_string
1197            "headers": ["string"],
1198            "unimplemented": True,
1199        },
1200        {
1201            "name": "__cpp_lib_to_underlying",
1202            "values": {"c++23": 202102},
1203            "headers": ["utility"],
1204        },
1205        {
1206            "name": "__cpp_lib_transformation_trait_aliases",
1207            "values": {"c++14": 201304},
1208            "headers": ["type_traits"],
1209        },
1210        {
1211            "name": "__cpp_lib_transparent_operators",
1212            "values": {"c++14": 201210, "c++17": 201510},
1213            "headers": ["functional", "memory"],
1214        },
1215        {
1216            "name": "__cpp_lib_tuple_element_t",
1217            "values": {"c++14": 201402},
1218            "headers": ["tuple"],
1219        },
1220        {
1221            "name": "__cpp_lib_tuple_like",
1222            "values": {
1223                "c++23": 202207,  # P2165R4 Compatibility between tuple, pair and tuple-like objects
1224                "c++26": 202311,  # P2819R2 Add tuple protocol to complex
1225            },
1226            "headers": ["map", "tuple", "unordered_map", "utility"],
1227            "unimplemented": True,
1228        },
1229        {
1230            "name": "__cpp_lib_tuples_by_type",
1231            "values": {"c++14": 201304},
1232            "headers": ["tuple", "utility"],
1233        },
1234        {
1235            "name": "__cpp_lib_type_identity",
1236            "values": {"c++20": 201806},
1237            "headers": ["type_traits"],
1238        },
1239        {
1240            "name": "__cpp_lib_type_trait_variable_templates",
1241            "values": {"c++17": 201510},
1242            "headers": ["type_traits"],
1243        },
1244        {
1245            "name": "__cpp_lib_uncaught_exceptions",
1246            "values": {"c++17": 201411},
1247            "headers": ["exception"],
1248        },
1249        {
1250            "name": "__cpp_lib_unordered_map_try_emplace",
1251            "values": {"c++17": 201411},
1252            "headers": ["unordered_map"],
1253        },
1254        {
1255            "name": "__cpp_lib_unreachable",
1256            "values": {"c++23": 202202},
1257            "headers": ["utility"],
1258        },
1259        {
1260            "name": "__cpp_lib_unwrap_ref",
1261            "values": {"c++20": 201811},
1262            "headers": ["functional"],
1263        },
1264        {
1265            "name": "__cpp_lib_variant",
1266            "values": {"c++17": 202102},
1267            "headers": ["variant"],
1268        },
1269        {
1270            "name": "__cpp_lib_void_t",
1271            "values": {"c++17": 201411},
1272            "headers": ["type_traits"],
1273        },
1274        {
1275            "name": "__cpp_lib_within_lifetime",
1276            "values": {
1277                "c++26": 202306  # P2641R4 Checking if a union alternative is active
1278            },
1279            "headers": ["type_traits"],
1280            "unimplemented": True,
1281        },
1282    ]
1283]
1284
1285assert feature_test_macros == sorted(feature_test_macros, key=lambda tc: tc["name"])
1286assert all(tc["headers"] == sorted(tc["headers"]) for tc in feature_test_macros)
1287assert all(
1288    ("libcxx_guard" in tc) == ("test_suite_guard" in tc) for tc in feature_test_macros
1289)
1290assert all(
1291    all(
1292        key
1293        in [
1294            "name",
1295            "values",
1296            "headers",
1297            "libcxx_guard",
1298            "test_suite_guard",
1299            "unimplemented",
1300        ]
1301        for key in tc.keys()
1302    )
1303    for tc in feature_test_macros
1304)
1305
1306# Map from each header to the Lit annotations that should be used for
1307# tests that include that header.
1308#
1309# For example, when threads are not supported, any test that includes
1310# <thread> should be marked as UNSUPPORTED, because including <thread>
1311# is a hard error in that case.
1312lit_markup = {
1313    "barrier": ["UNSUPPORTED: no-threads"],
1314    "filesystem": ["UNSUPPORTED: no-filesystem"],
1315    "fstream": ["UNSUPPORTED: no-localization"],
1316    "iomanip": ["UNSUPPORTED: no-localization"],
1317    "ios": ["UNSUPPORTED: no-localization"],
1318    "iostream": ["UNSUPPORTED: no-localization"],
1319    "istream": ["UNSUPPORTED: no-localization"],
1320    "latch": ["UNSUPPORTED: no-threads"],
1321    "locale": ["UNSUPPORTED: no-localization"],
1322    "mutex": ["UNSUPPORTED: no-threads"],
1323    "ostream": ["UNSUPPORTED: no-localization"],
1324    "print": ["UNSUPPORTED: no-filesystem"],
1325    "regex": ["UNSUPPORTED: no-localization"],
1326    "semaphore": ["UNSUPPORTED: no-threads"],
1327    "shared_mutex": ["UNSUPPORTED: no-threads"],
1328    "sstream": ["UNSUPPORTED: no-localization"],
1329    "syncstream": ["UNSUPPORTED: no-localization"],
1330    "stdatomic.h": ["UNSUPPORTED: no-threads"],
1331    "stop_token": ["UNSUPPORTED: no-threads"],
1332    "thread": ["UNSUPPORTED: no-threads"],
1333}
1334
1335
1336def get_std_dialects():
1337    std_dialects = ["c++14", "c++17", "c++20", "c++23", "c++26"]
1338    return list(std_dialects)
1339
1340
1341def get_first_std(d):
1342    for s in get_std_dialects():
1343        if s in d.keys():
1344            return s
1345    return None
1346
1347
1348def get_last_std(d):
1349    rev_dialects = get_std_dialects()
1350    rev_dialects.reverse()
1351    for s in rev_dialects:
1352        if s in d.keys():
1353            return s
1354    return None
1355
1356
1357def get_std_before(d, std):
1358    std_dialects = get_std_dialects()
1359    candidates = std_dialects[0 : std_dialects.index(std)]
1360    candidates.reverse()
1361    for cand in candidates:
1362        if cand in d.keys():
1363            return cand
1364    return None
1365
1366
1367def get_value_before(d, std):
1368    new_std = get_std_before(d, std)
1369    if new_std is None:
1370        return None
1371    return d[new_std]
1372
1373
1374def get_for_std(d, std):
1375    # This catches the C++11 case for which there should be no defined feature
1376    # test macros.
1377    std_dialects = get_std_dialects()
1378    if std not in std_dialects:
1379        return None
1380    # Find the value for the newest C++ dialect between C++14 and std
1381    std_list = list(std_dialects[0 : std_dialects.index(std) + 1])
1382    std_list.reverse()
1383    for s in std_list:
1384        if s in d.keys():
1385            return d[s]
1386    return None
1387
1388
1389def get_std_number(std):
1390    return std.replace("c++", "")
1391
1392
1393"""
1394  Functions to produce the <version> header
1395"""
1396
1397
1398def produce_macros_definition_for_std(std):
1399    result = ""
1400    indent = 55
1401    for tc in feature_test_macros:
1402        if std not in tc["values"]:
1403            continue
1404        inner_indent = 1
1405        if "test_suite_guard" in tc.keys():
1406            result += "# if %s\n" % tc["libcxx_guard"]
1407            inner_indent += 2
1408        if get_value_before(tc["values"], std) is not None:
1409            assert "test_suite_guard" not in tc.keys()
1410            result += "# undef  %s\n" % tc["name"]
1411        line = "#%sdefine %s" % ((" " * inner_indent), tc["name"])
1412        line += " " * (indent - len(line))
1413        line += " %sL" % tc["values"][std]
1414        if "unimplemented" in tc.keys():
1415            line = "// " + line
1416        result += line
1417        result += "\n"
1418        if "test_suite_guard" in tc.keys():
1419            result += "# endif\n"
1420    return result.strip()
1421
1422
1423def produce_macros_definitions():
1424    macro_definition_template = """#if _LIBCPP_STD_VER >= {std_number}
1425{macro_definition}
1426#endif"""
1427
1428    macros_definitions = []
1429    for std in get_std_dialects():
1430        macros_definitions.append(
1431            macro_definition_template.format(
1432                std_number=get_std_number(std),
1433                macro_definition=produce_macros_definition_for_std(std),
1434            )
1435        )
1436
1437    return "\n\n".join(macros_definitions)
1438
1439
1440def chunks(l, n):
1441    """Yield successive n-sized chunks from l."""
1442    for i in range(0, len(l), n):
1443        yield l[i : i + n]
1444
1445
1446def produce_version_synopsis():
1447    indent = 56
1448    header_indent = 56 + len("20XXYYL ")
1449    result = ""
1450
1451    def indent_to(s, val):
1452        if len(s) >= val:
1453            return s
1454        s += " " * (val - len(s))
1455        return s
1456
1457    line = indent_to("Macro name", indent) + "Value"
1458    line = indent_to(line, header_indent) + "Headers"
1459    result += line + "\n"
1460    for tc in feature_test_macros:
1461        prev_defined_std = get_last_std(tc["values"])
1462        line = "{name: <{indent}}{value}L ".format(
1463            name=tc["name"], indent=indent, value=tc["values"][prev_defined_std]
1464        )
1465        headers = list(tc["headers"])
1466        headers.remove("version")
1467        for chunk in chunks(headers, 3):
1468            line = indent_to(line, header_indent)
1469            chunk = ["<%s>" % header for header in chunk]
1470            line += " ".join(chunk)
1471            result += line
1472            result += "\n"
1473            line = ""
1474        while True:
1475            prev_defined_std = get_std_before(tc["values"], prev_defined_std)
1476            if prev_defined_std is None:
1477                break
1478            result += "%s%sL // %s\n" % (
1479                indent_to("", indent),
1480                tc["values"][prev_defined_std],
1481                prev_defined_std.replace("c++", "C++"),
1482            )
1483    return result
1484
1485
1486def produce_version_header():
1487    template = """// -*- C++ -*-
1488//===----------------------------------------------------------------------===//
1489//
1490// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
1491// See https://llvm.org/LICENSE.txt for license information.
1492// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
1493//
1494//===----------------------------------------------------------------------===//
1495
1496#ifndef _LIBCPP_VERSIONH
1497#define _LIBCPP_VERSIONH
1498
1499/*
1500  version synopsis
1501
1502{synopsis}
1503
1504*/
1505
1506#include <__assert> // all public C++ headers provide the assertion handler
1507#include <__availability>
1508#include <__config>
1509
1510#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1511#  pragma GCC system_header
1512#endif
1513
1514// clang-format off
1515
1516{cxx_macros}
1517
1518// clang-format on
1519
1520#endif // _LIBCPP_VERSIONH
1521"""
1522
1523    version_str = template.format(
1524        synopsis=produce_version_synopsis().strip(),
1525        cxx_macros=produce_macros_definitions(),
1526    )
1527    version_header_path = os.path.join(include_path, "version")
1528    with open(version_header_path, "w", newline="\n") as f:
1529        f.write(version_str)
1530
1531
1532"""
1533    Functions to produce test files
1534"""
1535
1536test_types = {
1537    "undefined": """
1538# ifdef {name}
1539#   error "{name} should not be defined before {std_first}"
1540# endif
1541""",
1542    "test_suite_guard": """
1543# if {test_suite_guard}
1544#   ifndef {name}
1545#     error "{name} should be defined in {std}"
1546#   endif
1547#   if {name} != {value}
1548#     error "{name} should have the value {value} in {std}"
1549#   endif
1550# else
1551#   ifdef {name}
1552#     error "{name} should not be defined when the requirement '{test_suite_guard}' is not met!"
1553#   endif
1554# endif
1555""",
1556    "unimplemented": """
1557# if !defined(_LIBCPP_VERSION)
1558#   ifndef {name}
1559#     error "{name} should be defined in {std}"
1560#   endif
1561#   if {name} != {value}
1562#     error "{name} should have the value {value} in {std}"
1563#   endif
1564# else // _LIBCPP_VERSION
1565#   ifdef {name}
1566#     error "{name} should not be defined because it is unimplemented in libc++!"
1567#   endif
1568# endif
1569""",
1570    "defined": """
1571# ifndef {name}
1572#   error "{name} should be defined in {std}"
1573# endif
1574# if {name} != {value}
1575#   error "{name} should have the value {value} in {std}"
1576# endif
1577""",
1578}
1579
1580
1581def generate_std_test(test_list, std):
1582    result = ""
1583    for tc in test_list:
1584        val = get_for_std(tc["values"], std)
1585        if val is not None:
1586            val = "%sL" % val
1587        if val is None:
1588            result += test_types["undefined"].format(
1589                name=tc["name"], std_first=get_first_std(tc["values"])
1590            )
1591        elif "unimplemented" in tc.keys():
1592            result += test_types["unimplemented"].format(
1593                name=tc["name"], value=val, std=std
1594            )
1595        elif "test_suite_guard" in tc.keys():
1596            result += test_types["test_suite_guard"].format(
1597                name=tc["name"],
1598                value=val,
1599                std=std,
1600                test_suite_guard=tc["test_suite_guard"],
1601            )
1602        else:
1603            result += test_types["defined"].format(name=tc["name"], value=val, std=std)
1604    return result.strip()
1605
1606
1607def generate_std_tests(test_list):
1608    std_tests_template = """#if TEST_STD_VER < {first_std_number}
1609
1610{pre_std_test}
1611
1612{other_std_tests}
1613
1614#elif TEST_STD_VER > {penultimate_std_number}
1615
1616{last_std_test}
1617
1618#endif // TEST_STD_VER > {penultimate_std_number}"""
1619
1620    std_dialects = get_std_dialects()
1621
1622    other_std_tests = []
1623    for std in std_dialects[:-1]:
1624        other_std_tests.append("#elif TEST_STD_VER == " + get_std_number(std))
1625        other_std_tests.append(generate_std_test(test_list, std))
1626
1627    std_tests = std_tests_template.format(
1628        first_std_number=get_std_number(std_dialects[0]),
1629        pre_std_test=generate_std_test(test_list, "c++11"),
1630        other_std_tests="\n\n".join(other_std_tests),
1631        penultimate_std_number=get_std_number(std_dialects[-2]),
1632        last_std_test=generate_std_test(test_list, std_dialects[-1]),
1633    )
1634
1635    return std_tests
1636
1637
1638def generate_synopsis(test_list):
1639    max_name_len = max([len(tc["name"]) for tc in test_list])
1640    indent = max_name_len + 8
1641
1642    def mk_line(prefix, suffix):
1643        return "{prefix: <{max_len}}{suffix}\n".format(
1644            prefix=prefix, suffix=suffix, max_len=indent
1645        )
1646
1647    result = ""
1648    result += mk_line("/*  Constant", "Value")
1649    for tc in test_list:
1650        prefix = "    %s" % tc["name"]
1651        for std in [s for s in get_std_dialects() if s in tc["values"].keys()]:
1652            result += mk_line(
1653                prefix, "%sL [%s]" % (tc["values"][std], std.replace("c++", "C++"))
1654            )
1655            prefix = ""
1656    result += "*/"
1657    return result
1658
1659
1660def produce_tests():
1661    headers = set([h for tc in feature_test_macros for h in tc["headers"]])
1662    for h in headers:
1663        test_list = [tc for tc in feature_test_macros if h in tc["headers"]]
1664        if not has_header(h):
1665            for tc in test_list:
1666                assert "unimplemented" in tc.keys()
1667            continue
1668        markup = "\n".join("// " + tag for tag in lit_markup.get(h, []))
1669        test_body = """//===----------------------------------------------------------------------===//
1670//
1671// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
1672// See https://llvm.org/LICENSE.txt for license information.
1673// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
1674//
1675//===----------------------------------------------------------------------===//
1676//
1677// WARNING: This test was generated by {script_name}
1678// and should not be edited manually.
1679//
1680// clang-format off
1681{markup}
1682// <{header}>
1683
1684// Test the feature test macros defined by <{header}>
1685
1686{synopsis}
1687
1688#include <{header}>
1689#include "test_macros.h"
1690
1691{cxx_tests}
1692
1693""".format(
1694            script_name=script_name,
1695            header=h,
1696            markup=("\n{}\n".format(markup) if markup else ""),
1697            synopsis=generate_synopsis(test_list),
1698            cxx_tests=generate_std_tests(test_list),
1699        )
1700        test_name = "{header}.version.compile.pass.cpp".format(header=h)
1701        out_path = os.path.join(macro_test_path, test_name)
1702        with open(out_path, "w", newline="\n") as f:
1703            f.write(test_body)
1704
1705
1706"""
1707    Produce documentation for the feature test macros
1708"""
1709
1710
1711def make_widths(grid):
1712    widths = []
1713    for i in range(0, len(grid[0])):
1714        cell_width = 2 + max(
1715            reduce(lambda x, y: x + y, [[len(row[i])] for row in grid], [])
1716        )
1717        widths += [cell_width]
1718    return widths
1719
1720
1721def create_table(grid, indent):
1722    indent_str = " " * indent
1723    col_widths = make_widths(grid)
1724    result = [indent_str + add_divider(col_widths, 2)]
1725    header_flag = 2
1726    for row_i in range(0, len(grid)):
1727        row = grid[row_i]
1728        line = indent_str + " ".join(
1729            [pad_cell(row[i], col_widths[i]) for i in range(0, len(row))]
1730        )
1731        result.append(line.rstrip())
1732        if row_i == len(grid) - 1:
1733            header_flag = 2
1734        if row[0].startswith("**"):
1735            header_flag += 1
1736        separator = indent_str + add_divider(col_widths, header_flag)
1737        result.append(separator.rstrip())
1738        header_flag = 0
1739    return "\n".join(result)
1740
1741
1742def add_divider(widths, header_flag):
1743    if header_flag == 3:
1744        return "=".join(["=" * w for w in widths])
1745    if header_flag == 2:
1746        return " ".join(["=" * w for w in widths])
1747    if header_flag == 1:
1748        return "-".join(["-" * w for w in widths])
1749    else:
1750        return " ".join(["-" * w for w in widths])
1751
1752
1753def pad_cell(s, length, left_align=True):
1754    padding = (length - len(s)) * " "
1755    return s + padding
1756
1757
1758def get_status_table():
1759    table = [["Macro Name", "Value"]]
1760    for std in get_std_dialects():
1761        table += [["**" + std.replace("c++", "C++ ") + "**", ""]]
1762        for tc in feature_test_macros:
1763            if std not in tc["values"].keys():
1764                continue
1765            value = "``%sL``" % tc["values"][std]
1766            if "unimplemented" in tc.keys():
1767                value = "*unimplemented*"
1768            table += [["``%s``" % tc["name"], value]]
1769    return table
1770
1771
1772def produce_docs():
1773    doc_str = """.. _FeatureTestMacroTable:
1774
1775==========================
1776Feature Test Macro Support
1777==========================
1778
1779.. contents::
1780   :local:
1781
1782Overview
1783========
1784
1785This file documents the feature test macros currently supported by libc++.
1786
1787.. _feature-status:
1788
1789Status
1790======
1791
1792.. table:: Current Status
1793    :name: feature-status-table
1794    :widths: auto
1795
1796{status_tables}
1797
1798""".format(
1799        status_tables=create_table(get_status_table(), 4)
1800    )
1801
1802    table_doc_path = os.path.join(docs_path, "FeatureTestMacroTable.rst")
1803    with open(table_doc_path, "w", newline="\n") as f:
1804        f.write(doc_str)
1805
1806
1807def main():
1808    produce_version_header()
1809    produce_tests()
1810    produce_docs()
1811
1812
1813if __name__ == "__main__":
1814    main()
1815