[NFC][RemoveDIs] Prefer iterators over inst-pointers in InstCombine
[llvm-project.git] / libcxx / utils / generate_feature_test_macro_components.py
blobac342aff0beb70107686e93ad3191cadc774668e
1 #!/usr/bin/env python
3 import os
4 from builtins import range
5 from functools import reduce
8 def 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",
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")
29 return script_name, src_root, include_path, docs_path, macro_test_path
32 script_name, source_root, include_path, docs_path, macro_test_path = get_libcxx_paths()
35 def has_header(h):
36 h_path = os.path.join(include_path, h)
37 return os.path.exists(h_path)
40 def add_version_header(tc):
41 tc["headers"].append("version")
42 return tc
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 # ================ ============================================================
75 feature_test_macros = [
76 add_version_header(x)
77 for x in [
79 "name": "__cpp_lib_adaptor_iterator_pair_constructor",
80 "values": {"c++23": 202106},
81 "headers": ["queue", "stack"],
84 "name": "__cpp_lib_addressof_constexpr",
85 "values": {"c++17": 201603},
86 "headers": ["memory"],
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
95 "headers": ["memory"],
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",
115 "name": "__cpp_lib_any",
116 "values": {"c++17": 201606},
117 "headers": ["any"],
120 "name": "__cpp_lib_apply",
121 "values": {"c++17": 201603},
122 "headers": ["tuple"],
125 "name": "__cpp_lib_array_constexpr",
126 "values": {"c++17": 201603, "c++20": 201811},
127 "headers": ["array", "iterator"],
130 "name": "__cpp_lib_as_const",
131 "values": {"c++17": 201510},
132 "headers": ["utility"],
135 "name": "__cpp_lib_associative_heterogeneous_erasure",
136 "values": {"c++23": 202110},
137 "headers": ["map", "set", "unordered_map", "unordered_set"],
138 "unimplemented": True,
141 "name": "__cpp_lib_associative_heterogeneous_insertion",
142 "values": {"c++26": 202306}, # P2363R5 Extending associative containers with the remaining heterogeneous overloads
143 "headers": ["map", "set", "unordered_map", "unordered_set"],
144 "unimplemented": True,
147 "name": "__cpp_lib_assume_aligned",
148 "values": {"c++20": 201811},
149 "headers": ["memory"],
152 "name": "__cpp_lib_atomic_flag_test",
153 "values": {"c++20": 201907},
154 "headers": ["atomic"],
157 "name": "__cpp_lib_atomic_float",
158 "values": {"c++20": 201711},
159 "headers": ["atomic"],
160 "unimplemented": True,
163 "name": "__cpp_lib_atomic_is_always_lock_free",
164 "values": {"c++17": 201603},
165 "headers": ["atomic"],
168 "name": "__cpp_lib_atomic_lock_free_type_aliases",
169 "values": {"c++20": 201907},
170 "headers": ["atomic"],
173 "name": "__cpp_lib_atomic_ref",
174 "values": {"c++20": 201806},
175 "headers": ["atomic"],
176 "unimplemented": True,
179 "name": "__cpp_lib_atomic_shared_ptr",
180 "values": {"c++20": 201711},
181 "headers": ["atomic"],
182 "unimplemented": True,
185 "name": "__cpp_lib_atomic_value_initialization",
186 "values": {"c++20": 201911},
187 "headers": ["atomic", "memory"],
190 "name": "__cpp_lib_atomic_wait",
191 "values": {"c++20": 201907},
192 "headers": ["atomic"],
193 "test_suite_guard": "!defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)",
194 "libcxx_guard": "!defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)",
197 "name": "__cpp_lib_barrier",
198 "values": {"c++20": 201907},
199 "headers": ["barrier"],
200 "test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)",
201 "libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)",
204 "name": "__cpp_lib_bind_back",
205 "values": {
206 "c++23": 202202,
207 "c++26": 202306, # P2714R1 Bind front and back to NTTP callables
209 "headers": ["functional"],
210 "unimplemented": True,
213 "name": "__cpp_lib_bind_front",
214 "values": {
215 "c++20": 201907,
216 "c++26": 202306, # P2714R1 Bind front and back to NTTP callables
218 "headers": ["functional"],
221 "name": "__cpp_lib_bit_cast",
222 "values": {"c++20": 201806},
223 "headers": ["bit"],
226 "name": "__cpp_lib_bitops",
227 "values": {"c++20": 201907},
228 "headers": ["bit"],
231 "name": "__cpp_lib_bitset",
232 "values": {"c++26": 202306}, # P2697R1 Interfacing bitset with string_view
233 "headers": ["bitset"],
236 "name": "__cpp_lib_bool_constant",
237 "values": {"c++17": 201505},
238 "headers": ["type_traits"],
241 "name": "__cpp_lib_bounded_array_traits",
242 "values": {"c++20": 201902},
243 "headers": ["type_traits"],
246 "name": "__cpp_lib_boyer_moore_searcher",
247 "values": {"c++17": 201603},
248 "headers": ["functional"],
251 "name": "__cpp_lib_byte",
252 "values": {"c++17": 201603},
253 "headers": ["cstddef"],
256 "name": "__cpp_lib_byteswap",
257 "values": {"c++23": 202110},
258 "headers": ["bit"],
261 "name": "__cpp_lib_char8_t",
262 "values": {"c++20": 201907},
263 "headers": [
264 "atomic",
265 "filesystem",
266 "istream",
267 "limits",
268 "locale",
269 "ostream",
270 "string",
271 "string_view",
273 "test_suite_guard": "defined(__cpp_char8_t)",
274 "libcxx_guard": "!defined(_LIBCPP_HAS_NO_CHAR8_T)",
277 "name": "__cpp_lib_chrono",
278 "values": {
279 "c++17": 201611,
280 #"c++26": 202306, # P2592R3 Hashing support for std::chrono value classes
282 "headers": ["chrono"],
285 "name": "__cpp_lib_chrono_udls",
286 "values": {"c++14": 201304},
287 "headers": ["chrono"],
290 "name": "__cpp_lib_clamp",
291 "values": {"c++17": 201603},
292 "headers": ["algorithm"],
295 "name": "__cpp_lib_complex_udls",
296 "values": {"c++14": 201309},
297 "headers": ["complex"],
300 "name": "__cpp_lib_concepts",
301 "values": {"c++20": 202002},
302 "headers": ["concepts"],
305 "name": "__cpp_lib_constexpr_algorithms",
306 "values": {
307 "c++20": 201806,
308 #"c++26": 202306, # P2562R1 constexpr Stable Sorting
310 "headers": ["algorithm", "utility"],
313 "name": "__cpp_lib_constexpr_bitset",
314 "values": {"c++23": 202207},
315 "headers": ["bitset"],
318 "name": "__cpp_lib_constexpr_charconv",
319 "values": {"c++23": 202207},
320 "headers": ["charconv"],
323 "name": "__cpp_lib_constexpr_cmath",
324 "values": {"c++23": 202202},
325 "headers": ["cmath", "cstdlib"],
326 "unimplemented": True,
329 "name": "__cpp_lib_constexpr_complex",
330 "values": {"c++20": 201711},
331 "headers": ["complex"],
334 "name": "__cpp_lib_constexpr_dynamic_alloc",
335 "values": {"c++20": 201907},
336 "headers": ["memory"],
339 "name": "__cpp_lib_constexpr_functional",
340 "values": {"c++20": 201907},
341 "headers": ["functional"],
344 "name": "__cpp_lib_constexpr_iterator",
345 "values": {"c++20": 201811},
346 "headers": ["iterator"],
349 "name": "__cpp_lib_constexpr_memory",
350 "values": {"c++20": 201811, "c++23": 202202},
351 "headers": ["memory"],
354 "name": "__cpp_lib_constexpr_numeric",
355 "values": {"c++20": 201911},
356 "headers": ["numeric"],
359 "name": "__cpp_lib_constexpr_string",
360 "values": {"c++20": 201907},
361 "headers": ["string"],
364 "name": "__cpp_lib_constexpr_string_view",
365 "values": {"c++20": 201811},
366 "headers": ["string_view"],
369 "name": "__cpp_lib_constexpr_tuple",
370 "values": {"c++20": 201811},
371 "headers": ["tuple"],
374 "name": "__cpp_lib_constexpr_typeinfo",
375 "values": {"c++23": 202106},
376 "headers": ["typeinfo"],
379 "name": "__cpp_lib_constexpr_utility",
380 "values": {"c++20": 201811},
381 "headers": ["utility"],
384 "name": "__cpp_lib_constexpr_vector",
385 "values": {"c++20": 201907},
386 "headers": ["vector"],
389 "name": "__cpp_lib_copyable_function",
390 "values": {"c++26": 202306}, # P2548R6 copyable_function
391 "headers": ["functional"],
392 "unimplemented": True,
395 "name": "__cpp_lib_coroutine",
396 "values": {"c++20": 201902},
397 "headers": ["coroutine"],
400 "name": "__cpp_lib_destroying_delete",
401 "values": {"c++20": 201806},
402 "headers": ["new"],
403 "test_suite_guard": "TEST_STD_VER > 17 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L",
404 "libcxx_guard": "_LIBCPP_STD_VER >= 20 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L",
407 "name": "__cpp_lib_enable_shared_from_this",
408 "values": {"c++17": 201603},
409 "headers": ["memory"],
412 "name": "__cpp_lib_endian",
413 "values": {"c++20": 201907},
414 "headers": ["bit"],
417 "name": "__cpp_lib_erase_if",
418 "values": {"c++20": 202002},
419 "headers": [
420 "deque",
421 "forward_list",
422 "list",
423 "map",
424 "set",
425 "string",
426 "unordered_map",
427 "unordered_set",
428 "vector",
432 "name": "__cpp_lib_exchange_function",
433 "values": {"c++14": 201304},
434 "headers": ["utility"],
437 "name": "__cpp_lib_execution",
438 "values": {"c++17": 201603, "c++20": 201902},
439 "headers": ["execution"],
440 "unimplemented": True,
443 "name": "__cpp_lib_expected",
444 "values": {"c++23": 202211},
445 "headers": ["expected"],
448 "name": "__cpp_lib_filesystem",
449 "values": {"c++17": 201703},
450 "headers": ["filesystem"],
451 "test_suite_guard": "!defined(_LIBCPP_AVAILABILITY_HAS_NO_FILESYSTEM_LIBRARY)",
452 "libcxx_guard": "!defined(_LIBCPP_AVAILABILITY_HAS_NO_FILESYSTEM_LIBRARY)",
455 "name": "__cpp_lib_format",
456 "values": {
457 # "c++20": 201907 Not implemented P1361R2 Integration of chrono with text formatting
458 # "c++20": 202106 Fully implemented
459 # "c++20": 202110 Not implemented P2372R3 Fixing locale handling in chrono formatters
460 "c++20": 202106,
461 # "c++23": 202207, Not implemented P2419R2 Clarify handling of encodings in localized formatting of chrono types
463 # Note these three papers are adopted at the June 2023 meeting and have sequential numbering
464 # 202304 P2510R3 Formatting pointers (Implemented)
465 # 202305 P2757R3 Type-checking format args
466 # 202306 P2637R3 Member Visit
467 "headers": ["format"],
468 "unimplemented": True,
471 "name": "__cpp_lib_format_ranges",
472 "values": {"c++23": 202207},
473 "headers": ["format"],
476 "name": "__cpp_lib_formatters",
477 "values": {"c++23": 202302},
478 "headers": ["stacktrace", "thread"],
479 "unimplemented": True,
482 "name": "__cpp_lib_forward_like",
483 "values": {"c++23": 202207},
484 "headers": ["utility"],
487 "name": "__cpp_lib_fstream_native_handle",
488 "values": {"c++26": 202306}, # P1759R6 Native handles and file streams
489 "headers": ["fstream"],
490 "unimplemented": True,
493 "name": "__cpp_lib_function_ref",
494 "values": {"c++26": 202306}, # P0792R14 function_ref: a type-erased callable reference
495 "headers": ["functional"],
496 "unimplemented": True,
499 "name": "__cpp_lib_gcd_lcm",
500 "values": {"c++17": 201606},
501 "headers": ["numeric"],
504 "name": "__cpp_lib_generic_associative_lookup",
505 "values": {"c++14": 201304},
506 "headers": ["map", "set"],
509 "name": "__cpp_lib_generic_unordered_lookup",
510 "values": {"c++20": 201811},
511 "headers": ["unordered_map", "unordered_set"],
514 "name": "__cpp_lib_hardware_interference_size",
515 "values": {"c++17": 201703},
516 "test_suite_guard": "defined(__GCC_DESTRUCTIVE_SIZE) && defined(__GCC_CONSTRUCTIVE_SIZE)",
517 "libcxx_guard": "defined(__GCC_DESTRUCTIVE_SIZE) && defined(__GCC_CONSTRUCTIVE_SIZE)",
518 "headers": ["new"],
521 "name": "__cpp_lib_has_unique_object_representations",
522 "values": {"c++17": 201606},
523 "headers": ["type_traits"],
526 "name": "__cpp_lib_hazard_pointer",
527 "values": {"c++26": 202306}, # P2530R3 Hazard Pointers for C++26
528 "headers": ["hazard_pointer"],# TODO verify this entry since the paper was underspecified.
529 "unimplemented": True,
532 "name": "__cpp_lib_hypot",
533 "values": {"c++17": 201603},
534 "headers": ["cmath"],
537 "name": "__cpp_lib_incomplete_container_elements",
538 "values": {"c++17": 201505},
539 "headers": ["forward_list", "list", "vector"],
542 "name": "__cpp_lib_int_pow2",
543 "values": {"c++20": 202002},
544 "headers": ["bit"],
547 "name": "__cpp_lib_integer_comparison_functions",
548 "values": {"c++20": 202002},
549 "headers": ["utility"],
552 "name": "__cpp_lib_integer_sequence",
553 "values": {"c++14": 201304},
554 "headers": ["utility"],
557 "name": "__cpp_lib_integral_constant_callable",
558 "values": {"c++14": 201304},
559 "headers": ["type_traits"],
562 "name": "__cpp_lib_interpolate",
563 "values": {"c++20": 201902},
564 "headers": ["cmath", "numeric"],
567 "name": "__cpp_lib_invoke",
568 "values": {"c++17": 201411},
569 "headers": ["functional"],
572 "name": "__cpp_lib_invoke_r",
573 "values": {"c++23": 202106},
574 "headers": ["functional"],
577 "name": "__cpp_lib_is_aggregate",
578 "values": {"c++17": 201703},
579 "headers": ["type_traits"],
582 "name": "__cpp_lib_is_constant_evaluated",
583 "values": {"c++20": 201811},
584 "headers": ["type_traits"],
587 "name": "__cpp_lib_is_final",
588 "values": {"c++14": 201402},
589 "headers": ["type_traits"],
592 "name": "__cpp_lib_is_invocable",
593 "values": {"c++17": 201703},
594 "headers": ["type_traits"],
597 "name": "__cpp_lib_is_layout_compatible",
598 "values": {"c++20": 201907},
599 "headers": ["type_traits"],
600 "unimplemented": True,
603 "name": "__cpp_lib_is_nothrow_convertible",
604 "values": {"c++20": 201806},
605 "headers": ["type_traits"],
608 "name": "__cpp_lib_is_null_pointer",
609 "values": {"c++14": 201309},
610 "headers": ["type_traits"],
613 "name": "__cpp_lib_is_pointer_interconvertible",
614 "values": {"c++20": 201907},
615 "headers": ["type_traits"],
616 "unimplemented": True,
619 "name": "__cpp_lib_is_scoped_enum",
620 "values": {"c++23": 202011},
621 "headers": ["type_traits"],
624 "name": "__cpp_lib_is_swappable",
625 "values": {"c++17": 201603},
626 "headers": ["type_traits"],
629 "name": "__cpp_lib_jthread",
630 "values": {"c++20": 201911},
631 "headers": ["stop_token", "thread"],
632 "test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS)",
633 "libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS)",
634 "unimplemented": True,
637 "name": "__cpp_lib_latch",
638 "values": {"c++20": 201907},
639 "headers": ["latch"],
640 "test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)",
641 "libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)",
644 "name": "__cpp_lib_launder",
645 "values": {"c++17": 201606},
646 "headers": ["new"],
649 "name": "__cpp_lib_list_remove_return_type",
650 "values": {"c++20": 201806},
651 "headers": ["forward_list", "list"],
654 "name": "__cpp_lib_logical_traits",
655 "values": {"c++17": 201510},
656 "headers": ["type_traits"],
659 "name": "__cpp_lib_make_from_tuple",
660 "values": {"c++17": 201606},
661 "headers": ["tuple"],
664 "name": "__cpp_lib_make_reverse_iterator",
665 "values": {"c++14": 201402},
666 "headers": ["iterator"],
669 "name": "__cpp_lib_make_unique",
670 "values": {"c++14": 201304},
671 "headers": ["memory"],
674 "name": "__cpp_lib_map_try_emplace",
675 "values": {"c++17": 201411},
676 "headers": ["map"],
679 "name": "__cpp_lib_math_constants",
680 "values": {"c++20": 201907},
681 "headers": ["numbers"],
684 "name": "__cpp_lib_math_special_functions",
685 "values": {"c++17": 201603},
686 "headers": ["cmath"],
687 "unimplemented": True,
690 "name": "__cpp_lib_mdspan",
691 "values": {"c++23": 202207},
692 "headers": ["mdspan"],
693 "unimplemented": True,
696 "name": "__cpp_lib_memory_resource",
697 "values": {"c++17": 201603},
698 "headers": ["memory_resource"],
699 "test_suite_guard": "!defined(_LIBCPP_AVAILABILITY_HAS_NO_PMR)",
700 "libcxx_guard": "!defined(_LIBCPP_AVAILABILITY_HAS_NO_PMR)",
703 "name": "__cpp_lib_move_iterator_concept",
704 "values": {"c++20": 202207},
705 "headers": ["iterator"],
708 "name": "__cpp_lib_move_only_function",
709 "values": {"c++23": 202110},
710 "headers": ["functional"],
711 "unimplemented": True,
714 "name": "__cpp_lib_node_extract",
715 "values": {"c++17": 201606},
716 "headers": ["map", "set", "unordered_map", "unordered_set"],
719 "name": "__cpp_lib_nonmember_container_access",
720 "values": {"c++17": 201411},
721 "headers": [
722 "array",
723 "deque",
724 "forward_list",
725 "iterator",
726 "list",
727 "map",
728 "regex",
729 "set",
730 "string",
731 "unordered_map",
732 "unordered_set",
733 "vector",
737 "name": "__cpp_lib_not_fn",
738 "values": {
739 "c++17": 201603,
740 #"c++26": 202306, # P2714R1 Bind front and back to NTTP callables
742 "headers": ["functional"],
745 "name": "__cpp_lib_null_iterators",
746 "values": {"c++14": 201304},
747 "headers": ["iterator"],
750 "name": "__cpp_lib_optional",
751 "values": {"c++17": 201606, "c++23": 202110},
752 "headers": ["optional"],
755 "name": "__cpp_lib_out_ptr",
756 "values": {"c++23": 202106},
757 "headers": ["memory"],
758 "unimplemented": True,
761 "name": "__cpp_lib_parallel_algorithm",
762 "values": {"c++17": 201603},
763 "headers": ["algorithm", "numeric"],
764 "unimplemented": True,
767 "name": "__cpp_lib_polymorphic_allocator",
768 "values": {"c++20": 201902},
769 "headers": ["memory_resource"],
770 "test_suite_guard": "!defined(_LIBCPP_AVAILABILITY_HAS_NO_PMR)",
771 "libcxx_guard": "!defined(_LIBCPP_AVAILABILITY_HAS_NO_PMR)",
774 "name": "__cpp_lib_print",
775 "values": {"c++23": 202207},
776 "headers": ["ostream", "print"],
777 "unimplemented": True,
780 "name": "__cpp_lib_quoted_string_io",
781 "values": {"c++14": 201304},
782 "headers": ["iomanip"],
785 "name": "__cpp_lib_ranges",
786 "values": {"c++20": 202207},
787 "headers": ["algorithm", "functional", "iterator", "memory", "ranges"],
790 "name": "__cpp_lib_ranges_as_rvalue",
791 "values": {"c++23": 202207},
792 "headers": ["ranges"],
795 "name": "__cpp_lib_ranges_chunk",
796 "values": {"c++23": 202202},
797 "headers": ["ranges"],
798 "unimplemented": True,
801 "name": "__cpp_lib_ranges_chunk_by",
802 "values": {"c++23": 202202},
803 "headers": ["ranges"],
806 "name": "__cpp_lib_ranges_iota",
807 "values": {"c++23": 202202},
808 "headers": ["numeric"],
809 "unimplemented": True,
812 "name": "__cpp_lib_ranges_join_with",
813 "values": {"c++23": 202202},
814 "headers": ["ranges"],
815 "unimplemented": True,
818 "name": "__cpp_lib_ranges_repeat",
819 "values": { "c++23": 202207},
820 "headers": ["ranges"],
823 "name": "__cpp_lib_ranges_slide",
824 "values": {"c++23": 202202},
825 "headers": ["ranges"],
826 "unimplemented": True,
829 "name": "__cpp_lib_ranges_starts_ends_with",
830 "values": {"c++23": 202106},
831 "headers": ["algorithm"],
832 "unimplemented": True,
835 "name": "__cpp_lib_ranges_to_container",
836 "values": {"c++23": 202202},
837 "headers": [
838 "deque",
839 "forward_list",
840 "list",
841 "map",
842 "queue",
843 "ranges",
844 "set",
845 "stack",
846 "string",
847 "unordered_map",
848 "unordered_set",
849 "vector",
853 "name": "__cpp_lib_ranges_zip",
854 "values": {"c++23": 202110},
855 "headers": ["ranges", "tuple", "utility"],
856 "unimplemented": True,
859 "name": "__cpp_lib_ratio",
860 "values": {"c++26": 202306}, # P2734R0 Adding the new SI prefixes
861 "headers": ["ratio"],
864 "name": "__cpp_lib_raw_memory_algorithms",
865 "values": {"c++17": 201606},
866 "headers": ["memory"],
869 "name": "__cpp_lib_rcu",
870 "values": {"c++26": 202306}, # P2545R4 Read-Copy Update (RCU)
871 "headers": ["rcu"], # TODO verify this entry since the paper was underspecified.
872 "unimplemented": True,
875 "name": "__cpp_lib_reference_from_temporary",
876 "values": {"c++23": 202202},
877 "headers": ["type_traits"],
878 "unimplemented": True,
881 "name": "__cpp_lib_remove_cvref",
882 "values": {"c++20": 201711},
883 "headers": ["type_traits"],
886 "name": "__cpp_lib_result_of_sfinae",
887 "values": {"c++14": 201210},
888 "headers": ["functional", "type_traits"],
891 "name": "__cpp_lib_robust_nonmodifying_seq_ops",
892 "values": {"c++14": 201304},
893 "headers": ["algorithm"],
896 "name": "__cpp_lib_sample",
897 "values": {"c++17": 201603},
898 "headers": ["algorithm"],
901 "name": "__cpp_lib_scoped_lock",
902 "values": {"c++17": 201703},
903 "headers": ["mutex"],
906 "name": "__cpp_lib_semaphore",
907 "values": {"c++20": 201907},
908 "headers": ["semaphore"],
909 "test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)",
910 "libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SYNC)",
913 "name": "__cpp_lib_shared_mutex",
914 "values": {"c++17": 201505},
915 "headers": ["shared_mutex"],
916 "test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SHARED_MUTEX)",
917 "libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SHARED_MUTEX)",
920 "name": "__cpp_lib_shared_ptr_arrays",
921 "values": {"c++17": 201611, "c++20": 201707},
922 "headers": ["memory"],
925 "name": "__cpp_lib_shared_ptr_weak_type",
926 "values": {"c++17": 201606},
927 "headers": ["memory"],
930 "name": "__cpp_lib_shared_timed_mutex",
931 "values": {"c++14": 201402},
932 "headers": ["shared_mutex"],
933 "test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SHARED_MUTEX)",
934 "libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_HAS_NO_SHARED_MUTEX)",
937 "name": "__cpp_lib_shift",
938 "values": {"c++20": 201806},
939 "headers": ["algorithm"],
942 "name": "__cpp_lib_smart_ptr_for_overwrite",
943 "values": {"c++20": 202002},
944 "headers": ["memory"],
945 "unimplemented": True,
948 "name": "__cpp_lib_smart_ptr_owner_equality",
949 "values": {"c++26": 202306}, # P1901R2 Enabling the Use of weak_ptr as Keys in Unordered Associative Containers
950 "headers": ["memory"],
951 "unimplemented": True,
954 "name": "__cpp_lib_source_location",
955 "values": {"c++20": 201907},
956 "headers": ["source_location"],
957 "test_suite_guard": "__has_builtin(__builtin_source_location) && !(defined(TEST_APPLE_CLANG_VER) && TEST_APPLE_CLANG_VER <= 1403)",
958 "libcxx_guard": "__has_builtin(__builtin_source_location) && !(defined(_LIBCPP_APPLE_CLANG_VER) && _LIBCPP_APPLE_CLANG_VER <= 1403)",
961 "name": "__cpp_lib_span",
962 "values": {"c++20": 202002},
963 "headers": ["span"],
966 "name": "__cpp_lib_spanstream",
967 "values": {"c++23": 202106},
968 "headers": ["spanstream"],
969 "unimplemented": True,
972 "name": "__cpp_lib_ssize",
973 "values": {"c++20": 201902},
974 "headers": ["iterator"],
977 "name": "__cpp_lib_sstream_from_string_view",
978 "values": {"c++26": 202306}, # P2495R3 Interfacing stringstreams with string_view
979 "headers": ["sstream"],
980 "unimplemented": True,
983 "name": "__cpp_lib_stacktrace",
984 "values": {"c++23": 202011},
985 "headers": ["stacktrace"],
986 "unimplemented": True,
989 "name": "__cpp_lib_starts_ends_with",
990 "values": {"c++20": 201711},
991 "headers": ["string", "string_view"],
994 "name": "__cpp_lib_stdatomic_h",
995 "values": {"c++23": 202011},
996 "headers": ["stdatomic.h"],
999 "name": "__cpp_lib_string_contains",
1000 "values": {"c++23": 202011},
1001 "headers": ["string", "string_view"],
1004 "name": "__cpp_lib_string_resize_and_overwrite",
1005 "values": {"c++23": 202110},
1006 "headers": ["string"],
1009 "name": "__cpp_lib_string_udls",
1010 "values": {"c++14": 201304},
1011 "headers": ["string"],
1014 "name": "__cpp_lib_string_view",
1015 "values": {"c++17": 201606, "c++20": 201803},
1016 "headers": ["string", "string_view"],
1019 "name": "__cpp_lib_submdspan",
1020 "values": {"c++26": 202306}, # P2630R4 submdspan
1021 "headers": ["mdspan"],
1022 "unimplemented": True,
1025 "name": "__cpp_lib_syncbuf",
1026 "values": {"c++20": 201803},
1027 "headers": ["syncstream"],
1028 "unimplemented": True,
1031 "name": "__cpp_lib_text_encoding",
1032 "values": {"c++26": 202306}, # P1885R12 Naming Text Encodings to Demystify Them
1033 "headers": ["text_encoding"],
1034 "unimplemented": True,
1037 "name": "__cpp_lib_three_way_comparison",
1038 "values": {"c++20": 201907},
1039 "headers": ["compare"],
1040 "unimplemented": True,
1043 "name": "__cpp_lib_to_address",
1044 "values": {"c++20": 201711},
1045 "headers": ["memory"],
1048 "name": "__cpp_lib_to_array",
1049 "values": {"c++20": 201907},
1050 "headers": ["array"],
1053 "name": "__cpp_lib_to_chars",
1054 "values": {
1055 "c++17": 201611,
1056 "c++26": 202306, # P2497R0 Testing for success or failure of <charconv> functions
1058 "headers": ["charconv"],
1059 "unimplemented": True,
1062 "name": "__cpp_lib_to_string",
1063 "values": {"c++23": 202306}, # P2587R3 to_string or not to_string
1064 "headers": ["string"],
1065 "unimplemented": True,
1068 "name": "__cpp_lib_to_underlying",
1069 "values": {"c++23": 202102},
1070 "headers": ["utility"],
1073 "name": "__cpp_lib_transformation_trait_aliases",
1074 "values": {"c++14": 201304},
1075 "headers": ["type_traits"],
1078 "name": "__cpp_lib_transparent_operators",
1079 "values": {"c++14": 201210, "c++17": 201510},
1080 "headers": ["functional", "memory"],
1083 "name": "__cpp_lib_tuple_element_t",
1084 "values": {"c++14": 201402},
1085 "headers": ["tuple"],
1088 "name": "__cpp_lib_tuples_by_type",
1089 "values": {"c++14": 201304},
1090 "headers": ["tuple", "utility"],
1093 "name": "__cpp_lib_type_identity",
1094 "values": {"c++20": 201806},
1095 "headers": ["type_traits"],
1098 "name": "__cpp_lib_type_trait_variable_templates",
1099 "values": {"c++17": 201510},
1100 "headers": ["type_traits"],
1103 "name": "__cpp_lib_uncaught_exceptions",
1104 "values": {"c++17": 201411},
1105 "headers": ["exception"],
1108 "name": "__cpp_lib_unordered_map_try_emplace",
1109 "values": {"c++17": 201411},
1110 "headers": ["unordered_map"],
1113 "name": "__cpp_lib_unreachable",
1114 "values": {"c++23": 202202},
1115 "headers": ["utility"],
1118 "name": "__cpp_lib_unwrap_ref",
1119 "values": {"c++20": 201811},
1120 "headers": ["functional"],
1123 "name": "__cpp_lib_variant",
1124 "values": {"c++17": 202102},
1125 "headers": ["variant"],
1128 "name": "__cpp_lib_void_t",
1129 "values": {"c++17": 201411},
1130 "headers": ["type_traits"],
1133 "name": "__cpp_lib_within_lifetime",
1134 "values": {"c++26": 202306}, # P2641R4 Checking if a union alternative is active
1135 "headers": ["type_traits"],
1136 "unimplemented": True,
1141 assert feature_test_macros == sorted(feature_test_macros, key=lambda tc: tc["name"])
1142 assert all(tc["headers"] == sorted(tc["headers"]) for tc in feature_test_macros)
1143 assert all(
1144 ("libcxx_guard" in tc) == ("test_suite_guard" in tc) for tc in feature_test_macros
1146 assert all(
1147 all(
1149 in [
1150 "name",
1151 "values",
1152 "headers",
1153 "libcxx_guard",
1154 "test_suite_guard",
1155 "unimplemented",
1157 for key in tc.keys()
1159 for tc in feature_test_macros
1162 # Map from each header to the Lit annotations that should be used for
1163 # tests that include that header.
1165 # For example, when threads are not supported, any test that includes
1166 # <thread> should be marked as UNSUPPORTED, because including <thread>
1167 # is a hard error in that case.
1168 lit_markup = {
1169 "barrier": ["UNSUPPORTED: no-threads"],
1170 "filesystem": ["UNSUPPORTED: no-filesystem"],
1171 "fstream": ["UNSUPPORTED: no-localization"],
1172 "iomanip": ["UNSUPPORTED: no-localization"],
1173 "ios": ["UNSUPPORTED: no-localization"],
1174 "iostream": ["UNSUPPORTED: no-localization"],
1175 "istream": ["UNSUPPORTED: no-localization"],
1176 "latch": ["UNSUPPORTED: no-threads"],
1177 "locale": ["UNSUPPORTED: no-localization"],
1178 "mutex": ["UNSUPPORTED: no-threads"],
1179 "ostream": ["UNSUPPORTED: no-localization"],
1180 "print": ["UNSUPPORTED: no-filesystem"],
1181 "regex": ["UNSUPPORTED: no-localization"],
1182 "semaphore": ["UNSUPPORTED: no-threads"],
1183 "shared_mutex": ["UNSUPPORTED: no-threads"],
1184 "sstream": ["UNSUPPORTED: no-localization"],
1185 "stdatomic.h": ["UNSUPPORTED: no-threads"],
1186 "stop_token": ["UNSUPPORTED: no-threads"],
1187 "thread": ["UNSUPPORTED: no-threads"],
1191 def get_std_dialects():
1192 std_dialects = ["c++14", "c++17", "c++20", "c++23", "c++26"]
1193 return list(std_dialects)
1196 def get_first_std(d):
1197 for s in get_std_dialects():
1198 if s in d.keys():
1199 return s
1200 return None
1203 def get_last_std(d):
1204 rev_dialects = get_std_dialects()
1205 rev_dialects.reverse()
1206 for s in rev_dialects:
1207 if s in d.keys():
1208 return s
1209 return None
1212 def get_std_before(d, std):
1213 std_dialects = get_std_dialects()
1214 candidates = std_dialects[0 : std_dialects.index(std)]
1215 candidates.reverse()
1216 for cand in candidates:
1217 if cand in d.keys():
1218 return cand
1219 return None
1222 def get_value_before(d, std):
1223 new_std = get_std_before(d, std)
1224 if new_std is None:
1225 return None
1226 return d[new_std]
1229 def get_for_std(d, std):
1230 # This catches the C++11 case for which there should be no defined feature
1231 # test macros.
1232 std_dialects = get_std_dialects()
1233 if std not in std_dialects:
1234 return None
1235 # Find the value for the newest C++ dialect between C++14 and std
1236 std_list = list(std_dialects[0 : std_dialects.index(std) + 1])
1237 std_list.reverse()
1238 for s in std_list:
1239 if s in d.keys():
1240 return d[s]
1241 return None
1244 def get_std_number(std):
1245 return std.replace("c++", "")
1249 Functions to produce the <version> header
1253 def produce_macros_definition_for_std(std):
1254 result = ""
1255 indent = 55
1256 for tc in feature_test_macros:
1257 if std not in tc["values"]:
1258 continue
1259 inner_indent = 1
1260 if "test_suite_guard" in tc.keys():
1261 result += "# if %s\n" % tc["libcxx_guard"]
1262 inner_indent += 2
1263 if get_value_before(tc["values"], std) is not None:
1264 assert "test_suite_guard" not in tc.keys()
1265 result += "# undef %s\n" % tc["name"]
1266 line = "#%sdefine %s" % ((" " * inner_indent), tc["name"])
1267 line += " " * (indent - len(line))
1268 line += " %sL" % tc["values"][std]
1269 if "unimplemented" in tc.keys():
1270 line = "// " + line
1271 result += line
1272 result += "\n"
1273 if "test_suite_guard" in tc.keys():
1274 result += "# endif\n"
1275 return result.strip()
1278 def produce_macros_definitions():
1279 macro_definition_template = """#if _LIBCPP_STD_VER >= {std_number}
1280 {macro_definition}
1281 #endif"""
1283 macros_definitions = []
1284 for std in get_std_dialects():
1285 macros_definitions.append(
1286 macro_definition_template.format(
1287 std_number=get_std_number(std),
1288 macro_definition=produce_macros_definition_for_std(std),
1292 return "\n\n".join(macros_definitions)
1295 def chunks(l, n):
1296 """Yield successive n-sized chunks from l."""
1297 for i in range(0, len(l), n):
1298 yield l[i : i + n]
1301 def produce_version_synopsis():
1302 indent = 56
1303 header_indent = 56 + len("20XXYYL ")
1304 result = ""
1306 def indent_to(s, val):
1307 if len(s) >= val:
1308 return s
1309 s += " " * (val - len(s))
1310 return s
1312 line = indent_to("Macro name", indent) + "Value"
1313 line = indent_to(line, header_indent) + "Headers"
1314 result += line + "\n"
1315 for tc in feature_test_macros:
1316 prev_defined_std = get_last_std(tc["values"])
1317 line = "{name: <{indent}}{value}L ".format(
1318 name=tc["name"], indent=indent, value=tc["values"][prev_defined_std]
1320 headers = list(tc["headers"])
1321 headers.remove("version")
1322 for chunk in chunks(headers, 3):
1323 line = indent_to(line, header_indent)
1324 chunk = ["<%s>" % header for header in chunk]
1325 line += " ".join(chunk)
1326 result += line
1327 result += "\n"
1328 line = ""
1329 while True:
1330 prev_defined_std = get_std_before(tc["values"], prev_defined_std)
1331 if prev_defined_std is None:
1332 break
1333 result += "%s%sL // %s\n" % (
1334 indent_to("", indent),
1335 tc["values"][prev_defined_std],
1336 prev_defined_std.replace("c++", "C++"),
1338 return result
1341 def produce_version_header():
1342 template = """// -*- C++ -*-
1343 //===----------------------------------------------------------------------===//
1345 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
1346 // See https://llvm.org/LICENSE.txt for license information.
1347 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
1349 //===----------------------------------------------------------------------===//
1351 #ifndef _LIBCPP_VERSIONH
1352 #define _LIBCPP_VERSIONH
1355 version synopsis
1357 {synopsis}
1361 #include <__assert> // all public C++ headers provide the assertion handler
1362 #include <__config>
1364 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1365 # pragma GCC system_header
1366 #endif
1368 // clang-format off
1370 {cxx_macros}
1372 // clang-format on
1374 #endif // _LIBCPP_VERSIONH
1377 version_str = template.format(
1378 synopsis=produce_version_synopsis().strip(),
1379 cxx_macros=produce_macros_definitions(),
1381 version_header_path = os.path.join(include_path, "version")
1382 with open(version_header_path, "w", newline="\n") as f:
1383 f.write(version_str)
1387 Functions to produce test files
1390 test_types = {
1391 "undefined": """
1392 # ifdef {name}
1393 # error "{name} should not be defined before {std_first}"
1394 # endif
1395 """,
1396 "test_suite_guard": """
1397 # if {test_suite_guard}
1398 # ifndef {name}
1399 # error "{name} should be defined in {std}"
1400 # endif
1401 # if {name} != {value}
1402 # error "{name} should have the value {value} in {std}"
1403 # endif
1404 # else
1405 # ifdef {name}
1406 # error "{name} should not be defined when the requirement '{test_suite_guard}' is not met!"
1407 # endif
1408 # endif
1409 """,
1410 "unimplemented": """
1411 # if !defined(_LIBCPP_VERSION)
1412 # ifndef {name}
1413 # error "{name} should be defined in {std}"
1414 # endif
1415 # if {name} != {value}
1416 # error "{name} should have the value {value} in {std}"
1417 # endif
1418 # else // _LIBCPP_VERSION
1419 # ifdef {name}
1420 # error "{name} should not be defined because it is unimplemented in libc++!"
1421 # endif
1422 # endif
1423 """,
1424 "defined": """
1425 # ifndef {name}
1426 # error "{name} should be defined in {std}"
1427 # endif
1428 # if {name} != {value}
1429 # error "{name} should have the value {value} in {std}"
1430 # endif
1431 """,
1435 def generate_std_test(test_list, std):
1436 result = ""
1437 for tc in test_list:
1438 val = get_for_std(tc["values"], std)
1439 if val is not None:
1440 val = "%sL" % val
1441 if val is None:
1442 result += test_types["undefined"].format(
1443 name=tc["name"], std_first=get_first_std(tc["values"])
1445 elif "unimplemented" in tc.keys():
1446 result += test_types["unimplemented"].format(
1447 name=tc["name"], value=val, std=std
1449 elif "test_suite_guard" in tc.keys():
1450 result += test_types["test_suite_guard"].format(
1451 name=tc["name"],
1452 value=val,
1453 std=std,
1454 test_suite_guard=tc["test_suite_guard"],
1456 else:
1457 result += test_types["defined"].format(name=tc["name"], value=val, std=std)
1458 return result.strip()
1461 def generate_std_tests(test_list):
1462 std_tests_template = """#if TEST_STD_VER < {first_std_number}
1464 {pre_std_test}
1466 {other_std_tests}
1468 #elif TEST_STD_VER > {penultimate_std_number}
1470 {last_std_test}
1472 #endif // TEST_STD_VER > {penultimate_std_number}"""
1474 std_dialects = get_std_dialects()
1476 other_std_tests = []
1477 for std in std_dialects[:-1]:
1478 other_std_tests.append("#elif TEST_STD_VER == " + get_std_number(std))
1479 other_std_tests.append(generate_std_test(test_list, std))
1481 std_tests = std_tests_template.format(
1482 first_std_number=get_std_number(std_dialects[0]),
1483 pre_std_test=generate_std_test(test_list, "c++11"),
1484 other_std_tests="\n\n".join(other_std_tests),
1485 penultimate_std_number=get_std_number(std_dialects[-2]),
1486 last_std_test=generate_std_test(test_list, std_dialects[-1]),
1489 return std_tests
1492 def generate_synopsis(test_list):
1493 max_name_len = max([len(tc["name"]) for tc in test_list])
1494 indent = max_name_len + 8
1496 def mk_line(prefix, suffix):
1497 return "{prefix: <{max_len}}{suffix}\n".format(
1498 prefix=prefix, suffix=suffix, max_len=indent
1501 result = ""
1502 result += mk_line("/* Constant", "Value")
1503 for tc in test_list:
1504 prefix = " %s" % tc["name"]
1505 for std in [s for s in get_std_dialects() if s in tc["values"].keys()]:
1506 result += mk_line(
1507 prefix, "%sL [%s]" % (tc["values"][std], std.replace("c++", "C++"))
1509 prefix = ""
1510 result += "*/"
1511 return result
1514 def produce_tests():
1515 headers = set([h for tc in feature_test_macros for h in tc["headers"]])
1516 for h in headers:
1517 test_list = [tc for tc in feature_test_macros if h in tc["headers"]]
1518 if not has_header(h):
1519 for tc in test_list:
1520 assert "unimplemented" in tc.keys()
1521 continue
1522 markup = "\n".join("// " + tag for tag in lit_markup.get(h, []))
1523 test_body = """//===----------------------------------------------------------------------===//
1525 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
1526 // See https://llvm.org/LICENSE.txt for license information.
1527 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
1529 //===----------------------------------------------------------------------===//
1531 // WARNING: This test was generated by {script_name}
1532 // and should not be edited manually.
1534 // clang-format off
1535 {markup}
1536 // <{header}>
1538 // Test the feature test macros defined by <{header}>
1540 {synopsis}
1542 #include <{header}>
1543 #include "test_macros.h"
1545 {cxx_tests}
1547 """.format(
1548 script_name=script_name,
1549 header=h,
1550 markup=("\n{}\n".format(markup) if markup else ""),
1551 synopsis=generate_synopsis(test_list),
1552 cxx_tests=generate_std_tests(test_list),
1554 test_name = "{header}.version.compile.pass.cpp".format(header=h)
1555 out_path = os.path.join(macro_test_path, test_name)
1556 with open(out_path, "w", newline="\n") as f:
1557 f.write(test_body)
1561 Produce documentation for the feature test macros
1565 def make_widths(grid):
1566 widths = []
1567 for i in range(0, len(grid[0])):
1568 cell_width = 2 + max(
1569 reduce(lambda x, y: x + y, [[len(row[i])] for row in grid], [])
1571 widths += [cell_width]
1572 return widths
1575 def create_table(grid, indent):
1576 indent_str = " " * indent
1577 col_widths = make_widths(grid)
1578 result = [indent_str + add_divider(col_widths, 2)]
1579 header_flag = 2
1580 for row_i in range(0, len(grid)):
1581 row = grid[row_i]
1582 line = indent_str + " ".join(
1583 [pad_cell(row[i], col_widths[i]) for i in range(0, len(row))]
1585 result.append(line.rstrip())
1586 if row_i == len(grid) - 1:
1587 header_flag = 2
1588 if row[0].startswith("**"):
1589 header_flag += 1
1590 separator = indent_str + add_divider(col_widths, header_flag)
1591 result.append(separator.rstrip())
1592 header_flag = 0
1593 return "\n".join(result)
1596 def add_divider(widths, header_flag):
1597 if header_flag == 3:
1598 return "=".join(["=" * w for w in widths])
1599 if header_flag == 2:
1600 return " ".join(["=" * w for w in widths])
1601 if header_flag == 1:
1602 return "-".join(["-" * w for w in widths])
1603 else:
1604 return " ".join(["-" * w for w in widths])
1607 def pad_cell(s, length, left_align=True):
1608 padding = (length - len(s)) * " "
1609 return s + padding
1612 def get_status_table():
1613 table = [["Macro Name", "Value"]]
1614 for std in get_std_dialects():
1615 table += [["**" + std.replace("c++", "C++ ") + "**", ""]]
1616 for tc in feature_test_macros:
1617 if std not in tc["values"].keys():
1618 continue
1619 value = "``%sL``" % tc["values"][std]
1620 if "unimplemented" in tc.keys():
1621 value = "*unimplemented*"
1622 table += [["``%s``" % tc["name"], value]]
1623 return table
1626 def produce_docs():
1627 doc_str = """.. _FeatureTestMacroTable:
1629 ==========================
1630 Feature Test Macro Support
1631 ==========================
1633 .. contents::
1634 :local:
1636 Overview
1637 ========
1639 This file documents the feature test macros currently supported by libc++.
1641 .. _feature-status:
1643 Status
1644 ======
1646 .. table:: Current Status
1647 :name: feature-status-table
1648 :widths: auto
1650 {status_tables}
1652 """.format(
1653 status_tables=create_table(get_status_table(), 4)
1656 table_doc_path = os.path.join(docs_path, "FeatureTestMacroTable.rst")
1657 with open(table_doc_path, "w", newline="\n") as f:
1658 f.write(doc_str)
1661 def main():
1662 produce_version_header()
1663 produce_tests()
1664 produce_docs()
1667 if __name__ == "__main__":
1668 main()