xref: /llvm-project/libcxx/utils/generate_feature_test_macro_components.py (revision def50f701f6a2c1e0550bb341fd8b64bed299e72)
1508da415SEric Fiselier#!/usr/bin/env python
2508da415SEric Fiselier
3508da415SEric Fiselierimport os
4ff1b6f9fSArthur O'Dwyerfrom builtins import range
5fd02a468SLouis Dionnefrom functools import reduce
6d2dd4b55SMark de Weverfrom typing import Any, Dict, List  # Needed for python 3.8 compatibility.
7d2dd4b55SMark de Weverimport functools
8d2dd4b55SMark de Weverimport json
9508da415SEric Fiselier
107bfaa0f0STobias Hieta
11508da415SEric Fiselierdef get_libcxx_paths():
12508da415SEric Fiselier    utils_path = os.path.dirname(os.path.abspath(__file__))
13508da415SEric Fiselier    script_name = os.path.basename(__file__)
14508da415SEric Fiselier    assert os.path.exists(utils_path)
15508da415SEric Fiselier    src_root = os.path.dirname(utils_path)
167bfaa0f0STobias Hieta    include_path = os.path.join(src_root, "include")
17508da415SEric Fiselier    assert os.path.exists(include_path)
187bfaa0f0STobias Hieta    docs_path = os.path.join(src_root, "docs")
19508da415SEric Fiselier    assert os.path.exists(docs_path)
207bfaa0f0STobias Hieta    macro_test_path = os.path.join(
217bfaa0f0STobias Hieta        src_root,
227bfaa0f0STobias Hieta        "test",
237bfaa0f0STobias Hieta        "std",
247bfaa0f0STobias Hieta        "language.support",
257bfaa0f0STobias Hieta        "support.limits",
267bfaa0f0STobias Hieta        "support.limits.general",
277bfaa0f0STobias Hieta    )
28508da415SEric Fiselier    assert os.path.exists(macro_test_path)
297bfaa0f0STobias Hieta    assert os.path.exists(
307bfaa0f0STobias Hieta        os.path.join(macro_test_path, "version.version.compile.pass.cpp")
317bfaa0f0STobias Hieta    )
32508da415SEric Fiselier    return script_name, src_root, include_path, docs_path, macro_test_path
33508da415SEric Fiselier
347bfaa0f0STobias Hieta
35508da415SEric Fiselierscript_name, source_root, include_path, docs_path, macro_test_path = get_libcxx_paths()
36508da415SEric Fiselier
377bfaa0f0STobias Hieta
38508da415SEric Fiselierdef has_header(h):
39508da415SEric Fiselier    h_path = os.path.join(include_path, h)
40508da415SEric Fiselier    return os.path.exists(h_path)
41508da415SEric Fiselier
427bfaa0f0STobias Hieta
43508da415SEric Fiselierdef add_version_header(tc):
44508da415SEric Fiselier    tc["headers"].append("version")
45508da415SEric Fiselier    return tc
46508da415SEric Fiselier
477bfaa0f0STobias Hieta
48c2c68a59SMark de Wever# ================  ============================================================
49c2c68a59SMark de Wever# Field             Description
50c2c68a59SMark de Wever# ================  ============================================================
51c2c68a59SMark de Wever# name              The name of the feature-test macro.
52c2c68a59SMark de Wever# values            A dict whose keys are C++ versions and whose values are the
53c2c68a59SMark de Wever#                   value of the feature-test macro for that C++ version.
54c2c68a59SMark de Wever#                   (TODO: This isn't a very clean model for feature-test
55c2c68a59SMark de Wever#                   macros affected by multiple papers.)
56c2c68a59SMark de Wever# headers           An array with the headers that should provide the
57c2c68a59SMark de Wever#                   feature-test macro.
58c2c68a59SMark de Wever# test_suite_guard  An optional string field. When this field is provided,
59c2c68a59SMark de Wever#                   `libcxx_guard` must also be provided. This field is used
60c2c68a59SMark de Wever#                   only to generate the unit tests for the feature-test macros.
61c2c68a59SMark de Wever#                   It can't depend on macros defined in <__config> because the
62c2c68a59SMark de Wever#                   `test/std/` parts of the test suite are intended to be
63c2c68a59SMark de Wever#                   portable to any C++ standard library implementation, not
64c2c68a59SMark de Wever#                   just libc++. It may depend on
65c2c68a59SMark de Wever#                    * macros defined by the compiler itself, or
66c2c68a59SMark de Wever#                    * macros generated by CMake.
6704f01a2bSLouis Dionne#                   In some cases we add also depend on macros defined in
6804f01a2bSLouis Dionne#                   <__configuration/availability.h>.
69c2c68a59SMark de Wever# libcxx_guard      An optional string field. When this field is provided,
70c2c68a59SMark de Wever#                   `test_suite_guard` must also be provided. This field is used
71c2c68a59SMark de Wever#                   only to guard the feature-test macro in <version>. It may
72c2c68a59SMark de Wever#                   be the same as `test_suite_guard`, or it may depend on
73c2c68a59SMark de Wever#                   macros defined in <__config>.
74c2c68a59SMark de Wever# unimplemented     An optional Boolean field with the value `True`. This field
75c2c68a59SMark de Wever#                   is only used when a feature isn't fully implemented. Once
76c2c68a59SMark de Wever#                   you've fully implemented the feature, you should remove
77c2c68a59SMark de Wever#                   this field.
78c2c68a59SMark de Wever# ================  ============================================================
797bfaa0f0STobias Hietafeature_test_macros = [
807bfaa0f0STobias Hieta    add_version_header(x)
817bfaa0f0STobias Hieta    for x in [
827656dd33SLouis Dionne        {
83f3aed369SNikolas Klauser            "name": "__cpp_lib_adaptor_iterator_pair_constructor",
8471400505SMark de Wever            "values": {"c++23": 202106},
85f3aed369SNikolas Klauser            "headers": ["queue", "stack"],
867bfaa0f0STobias Hieta        },
877bfaa0f0STobias Hieta        {
887656dd33SLouis Dionne            "name": "__cpp_lib_addressof_constexpr",
89ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201603},
90508da415SEric Fiselier            "headers": ["memory"],
917bfaa0f0STobias Hieta        },
927bfaa0f0STobias Hieta        {
93855d7bedSArthur O'Dwyer            "name": "__cpp_lib_allocate_at_least",
943f05d044SMark de Wever            "values": {
953f05d044SMark de Wever                # Note LWG3887 Version macro for allocate_at_least
967d78ccf7SHristo Hristov                "c++23": 202302,  # P2652R2 Disallow User Specialization of allocator_traits
973f05d044SMark de Wever            },
98855d7bedSArthur O'Dwyer            "headers": ["memory"],
997bfaa0f0STobias Hieta        },
1007bfaa0f0STobias Hieta        {
1017656dd33SLouis Dionne            "name": "__cpp_lib_allocator_traits_is_always_equal",
102ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201411},
1037bfaa0f0STobias Hieta            "headers": [
1047bfaa0f0STobias Hieta                "deque",
1057bfaa0f0STobias Hieta                "forward_list",
1067bfaa0f0STobias Hieta                "list",
1077bfaa0f0STobias Hieta                "map",
1087bfaa0f0STobias Hieta                "memory",
1097bfaa0f0STobias Hieta                "scoped_allocator",
1107bfaa0f0STobias Hieta                "set",
1117bfaa0f0STobias Hieta                "string",
1127bfaa0f0STobias Hieta                "unordered_map",
1137bfaa0f0STobias Hieta                "unordered_set",
1147bfaa0f0STobias Hieta                "vector",
1157bfaa0f0STobias Hieta            ],
1167bfaa0f0STobias Hieta        },
1177bfaa0f0STobias Hieta        {
118ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_any",
119ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201606},
120ff1b6f9fSArthur O'Dwyer            "headers": ["any"],
1217bfaa0f0STobias Hieta        },
1227bfaa0f0STobias Hieta        {
123ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_apply",
124ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201603},
125ff1b6f9fSArthur O'Dwyer            "headers": ["tuple"],
1267bfaa0f0STobias Hieta        },
1277bfaa0f0STobias Hieta        {
1287656dd33SLouis Dionne            "name": "__cpp_lib_array_constexpr",
129ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201603, "c++20": 201811},
130ff1b6f9fSArthur O'Dwyer            "headers": ["array", "iterator"],
1317bfaa0f0STobias Hieta        },
1327bfaa0f0STobias Hieta        {
133ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_as_const",
134ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201510},
135737a4501SMichael Schellenberger Costa            "headers": ["utility"],
1367bfaa0f0STobias Hieta        },
1377bfaa0f0STobias Hieta        {
138855d7bedSArthur O'Dwyer            "name": "__cpp_lib_associative_heterogeneous_erasure",
13971400505SMark de Wever            "values": {"c++23": 202110},
140855d7bedSArthur O'Dwyer            "headers": ["map", "set", "unordered_map", "unordered_set"],
141855d7bedSArthur O'Dwyer            "unimplemented": True,
1427bfaa0f0STobias Hieta        },
1437bfaa0f0STobias Hieta        {
1443f05d044SMark de Wever            "name": "__cpp_lib_associative_heterogeneous_insertion",
145f49ccca8SMark de Wever            "values": {
146f49ccca8SMark de Wever                "c++26": 202306  # P2363R5 Extending associative containers with the remaining heterogeneous overloads
147f49ccca8SMark de Wever            },
1483f05d044SMark de Wever            "headers": ["map", "set", "unordered_map", "unordered_set"],
1493f05d044SMark de Wever            "unimplemented": True,
1503f05d044SMark de Wever        },
1513f05d044SMark de Wever        {
152466df171SArthur O'Dwyer            "name": "__cpp_lib_assume_aligned",
153466df171SArthur O'Dwyer            "values": {"c++20": 201811},
154466df171SArthur O'Dwyer            "headers": ["memory"],
1557bfaa0f0STobias Hieta        },
1567bfaa0f0STobias Hieta        {
1577656dd33SLouis Dionne            "name": "__cpp_lib_atomic_flag_test",
158ff1b6f9fSArthur O'Dwyer            "values": {"c++20": 201907},
159fc4bff0cSOlivier Giroux            "headers": ["atomic"],
1607bfaa0f0STobias Hieta        },
1617bfaa0f0STobias Hieta        {
1627656dd33SLouis Dionne            "name": "__cpp_lib_atomic_float",
163ff1b6f9fSArthur O'Dwyer            "values": {"c++20": 201711},
164fc4bff0cSOlivier Giroux            "headers": ["atomic"],
165ff1b6f9fSArthur O'Dwyer            "unimplemented": True,
1667bfaa0f0STobias Hieta        },
1677bfaa0f0STobias Hieta        {
168ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_atomic_is_always_lock_free",
169ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201603},
170ff1b6f9fSArthur O'Dwyer            "headers": ["atomic"],
1717bfaa0f0STobias Hieta        },
1727bfaa0f0STobias Hieta        {
173ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_atomic_lock_free_type_aliases",
174ff1b6f9fSArthur O'Dwyer            "values": {"c++20": 201907},
175ff1b6f9fSArthur O'Dwyer            "headers": ["atomic"],
1767bfaa0f0STobias Hieta        },
1777bfaa0f0STobias Hieta        {
178b699a9baSLouis Dionne            "name": "__cpp_lib_atomic_min_max",
179b699a9baSLouis Dionne            "values": {"c++26": 202403}, # P0493R5: Atomic minimum/maximum
180b699a9baSLouis Dionne            "headers": ["atomic"],
181b699a9baSLouis Dionne            "unimplemented": True,
182b699a9baSLouis Dionne        },
183b699a9baSLouis Dionne        {
184ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_atomic_ref",
185ff1b6f9fSArthur O'Dwyer            "values": {"c++20": 201806},
186ff1b6f9fSArthur O'Dwyer            "headers": ["atomic"],
1877bfaa0f0STobias Hieta        },
1887bfaa0f0STobias Hieta        {
1897656dd33SLouis Dionne            "name": "__cpp_lib_atomic_shared_ptr",
190ff1b6f9fSArthur O'Dwyer            "values": {"c++20": 201711},
191fc4bff0cSOlivier Giroux            "headers": ["atomic"],
192ff1b6f9fSArthur O'Dwyer            "unimplemented": True,
1937bfaa0f0STobias Hieta        },
1947bfaa0f0STobias Hieta        {
1957656dd33SLouis Dionne            "name": "__cpp_lib_atomic_value_initialization",
196ff1b6f9fSArthur O'Dwyer            "values": {"c++20": 201911},
197fc4bff0cSOlivier Giroux            "headers": ["atomic", "memory"],
1987bfaa0f0STobias Hieta        },
1997bfaa0f0STobias Hieta        {
200ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_atomic_wait",
201ff1b6f9fSArthur O'Dwyer            "values": {"c++20": 201907},
202ff1b6f9fSArthur O'Dwyer            "headers": ["atomic"],
20312563ea6Sphilnik777            "test_suite_guard": "!defined(_LIBCPP_VERSION) || _LIBCPP_AVAILABILITY_HAS_SYNC",
20412563ea6Sphilnik777            "libcxx_guard": "_LIBCPP_AVAILABILITY_HAS_SYNC",
2057bfaa0f0STobias Hieta        },
2067bfaa0f0STobias Hieta        {
207466df171SArthur O'Dwyer            "name": "__cpp_lib_barrier",
208466df171SArthur O'Dwyer            "values": {"c++20": 201907},
209466df171SArthur O'Dwyer            "headers": ["barrier"],
210c6f3b7bcSNikolas Klauser            "test_suite_guard": "!defined(_LIBCPP_VERSION) || (_LIBCPP_HAS_THREADS && _LIBCPP_AVAILABILITY_HAS_SYNC)",
211c6f3b7bcSNikolas Klauser            "libcxx_guard": "_LIBCPP_HAS_THREADS && _LIBCPP_AVAILABILITY_HAS_SYNC",
2127bfaa0f0STobias Hieta        },
2137bfaa0f0STobias Hieta        {
214a5b4479dSNikolas Klauser            "name": "__cpp_lib_bind_back",
2153f05d044SMark de Wever            "values": {
2163f05d044SMark de Wever                "c++23": 202202,
217c8917048SJakub Mazurkiewicz                # "c++26": 202306,  # P2714R1 Bind front and back to NTTP callables
2183f05d044SMark de Wever            },
219a5b4479dSNikolas Klauser            "headers": ["functional"],
2207bfaa0f0STobias Hieta        },
2217bfaa0f0STobias Hieta        {
222ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_bind_front",
2233f05d044SMark de Wever            "values": {
2243f05d044SMark de Wever                "c++20": 201907,
2253f05d044SMark de Wever                "c++26": 202306,  # P2714R1 Bind front and back to NTTP callables
2263f05d044SMark de Wever            },
227ff1b6f9fSArthur O'Dwyer            "headers": ["functional"],
2287bfaa0f0STobias Hieta        },
2297bfaa0f0STobias Hieta        {
230ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_bit_cast",
231ff1b6f9fSArthur O'Dwyer            "values": {"c++20": 201806},
232ff1b6f9fSArthur O'Dwyer            "headers": ["bit"],
2337bfaa0f0STobias Hieta        },
2347bfaa0f0STobias Hieta        {
235466df171SArthur O'Dwyer            "name": "__cpp_lib_bitops",
236466df171SArthur O'Dwyer            "values": {"c++20": 201907},
237466df171SArthur O'Dwyer            "headers": ["bit"],
2387bfaa0f0STobias Hieta        },
2397bfaa0f0STobias Hieta        {
2403f05d044SMark de Wever            "name": "__cpp_lib_bitset",
2413f05d044SMark de Wever            "values": {"c++26": 202306},  # P2697R1 Interfacing bitset with string_view
2423f05d044SMark de Wever            "headers": ["bitset"],
2433f05d044SMark de Wever        },
2443f05d044SMark de Wever        {
245ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_bool_constant",
246ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201505},
247ff1b6f9fSArthur O'Dwyer            "headers": ["type_traits"],
2487bfaa0f0STobias Hieta        },
2497bfaa0f0STobias Hieta        {
250466df171SArthur O'Dwyer            "name": "__cpp_lib_bounded_array_traits",
251466df171SArthur O'Dwyer            "values": {"c++20": 201902},
252466df171SArthur O'Dwyer            "headers": ["type_traits"],
2537bfaa0f0STobias Hieta        },
2547bfaa0f0STobias Hieta        {
255ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_boyer_moore_searcher",
256ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201603},
257ff1b6f9fSArthur O'Dwyer            "headers": ["functional"],
2587bfaa0f0STobias Hieta        },
2597bfaa0f0STobias Hieta        {
260ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_byte",
261ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201603},
262ff1b6f9fSArthur O'Dwyer            "headers": ["cstddef"],
2637bfaa0f0STobias Hieta        },
2647bfaa0f0STobias Hieta        {
2651dc62f26SNikolas Klauser            "name": "__cpp_lib_byteswap",
26671400505SMark de Wever            "values": {"c++23": 202110},
2671dc62f26SNikolas Klauser            "headers": ["bit"],
2687bfaa0f0STobias Hieta        },
2697bfaa0f0STobias Hieta        {
270ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_char8_t",
271309aed30SNikolas Klauser            "values": {"c++20": 201907},
2727bfaa0f0STobias Hieta            "headers": [
2737bfaa0f0STobias Hieta                "atomic",
2747bfaa0f0STobias Hieta                "filesystem",
2757bfaa0f0STobias Hieta                "istream",
2767bfaa0f0STobias Hieta                "limits",
2777bfaa0f0STobias Hieta                "locale",
2787bfaa0f0STobias Hieta                "ostream",
2797bfaa0f0STobias Hieta                "string",
2807bfaa0f0STobias Hieta                "string_view",
2817bfaa0f0STobias Hieta            ],
282c2c68a59SMark de Wever            "test_suite_guard": "defined(__cpp_char8_t)",
283ba87515fSNikolas Klauser            "libcxx_guard": "_LIBCPP_HAS_CHAR8_T",
2847bfaa0f0STobias Hieta        },
2857bfaa0f0STobias Hieta        {
286ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_chrono",
2873f05d044SMark de Wever            "values": {
2883f05d044SMark de Wever                "c++17": 201611,
2893f05d044SMark de Wever                # "c++26": 202306, # P2592R3 Hashing support for std::chrono value classes
2903f05d044SMark de Wever            },
291ff1b6f9fSArthur O'Dwyer            "headers": ["chrono"],
2927bfaa0f0STobias Hieta        },
2937bfaa0f0STobias Hieta        {
294ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_chrono_udls",
295ff1b6f9fSArthur O'Dwyer            "values": {"c++14": 201304},
296ff1b6f9fSArthur O'Dwyer            "headers": ["chrono"],
2977bfaa0f0STobias Hieta        },
2987bfaa0f0STobias Hieta        {
299ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_clamp",
300ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201603},
301ff1b6f9fSArthur O'Dwyer            "headers": ["algorithm"],
3027bfaa0f0STobias Hieta        },
3037bfaa0f0STobias Hieta        {
304ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_complex_udls",
305ff1b6f9fSArthur O'Dwyer            "values": {"c++14": 201309},
306ff1b6f9fSArthur O'Dwyer            "headers": ["complex"],
3077bfaa0f0STobias Hieta        },
3087bfaa0f0STobias Hieta        {
309ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_concepts",
310466df171SArthur O'Dwyer            "values": {"c++20": 202002},
311ff1b6f9fSArthur O'Dwyer            "headers": ["concepts"],
3127bfaa0f0STobias Hieta        },
3137bfaa0f0STobias Hieta        {
314466df171SArthur O'Dwyer            "name": "__cpp_lib_constexpr_algorithms",
3153f05d044SMark de Wever            "values": {
3163f05d044SMark de Wever                "c++20": 201806,
3173f05d044SMark de Wever                # "c++26": 202306, # P2562R1 constexpr Stable Sorting
3183f05d044SMark de Wever            },
3192b6ce25aSMark de Wever            "headers": ["algorithm", "utility"],
3207bfaa0f0STobias Hieta        },
3217bfaa0f0STobias Hieta        {
322f02120fbSNikolas Klauser            "name": "__cpp_lib_constexpr_bitset",
32371400505SMark de Wever            "values": {"c++23": 202207},
324f02120fbSNikolas Klauser            "headers": ["bitset"],
3257bfaa0f0STobias Hieta        },
3267bfaa0f0STobias Hieta        {
327a1e13a80SMark de Wever            "name": "__cpp_lib_constexpr_charconv",
32871400505SMark de Wever            "values": {"c++23": 202207},
329a1e13a80SMark de Wever            "headers": ["charconv"],
3307bfaa0f0STobias Hieta        },
3317bfaa0f0STobias Hieta        {
332a5b4479dSNikolas Klauser            "name": "__cpp_lib_constexpr_cmath",
33371400505SMark de Wever            "values": {"c++23": 202202},
334a5b4479dSNikolas Klauser            "headers": ["cmath", "cstdlib"],
335a5b4479dSNikolas Klauser            "unimplemented": True,
3367bfaa0f0STobias Hieta        },
3377bfaa0f0STobias Hieta        {
338466df171SArthur O'Dwyer            "name": "__cpp_lib_constexpr_complex",
339466df171SArthur O'Dwyer            "values": {"c++20": 201711},
340466df171SArthur O'Dwyer            "headers": ["complex"],
3417bfaa0f0STobias Hieta        },
3427bfaa0f0STobias Hieta        {
3437656dd33SLouis Dionne            "name": "__cpp_lib_constexpr_dynamic_alloc",
344ff1b6f9fSArthur O'Dwyer            "values": {"c++20": 201907},
345ff1b6f9fSArthur O'Dwyer            "headers": ["memory"],
3467bfaa0f0STobias Hieta        },
3477bfaa0f0STobias Hieta        {
348ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_constexpr_functional",
349ff1b6f9fSArthur O'Dwyer            "values": {"c++20": 201907},
350ff1b6f9fSArthur O'Dwyer            "headers": ["functional"],
3517bfaa0f0STobias Hieta        },
3527bfaa0f0STobias Hieta        {
353466df171SArthur O'Dwyer            "name": "__cpp_lib_constexpr_iterator",
354466df171SArthur O'Dwyer            "values": {"c++20": 201811},
355466df171SArthur O'Dwyer            "headers": ["iterator"],
3567bfaa0f0STobias Hieta        },
3577bfaa0f0STobias Hieta        {
358466df171SArthur O'Dwyer            "name": "__cpp_lib_constexpr_memory",
35971400505SMark de Wever            "values": {"c++20": 201811, "c++23": 202202},
360466df171SArthur O'Dwyer            "headers": ["memory"],
3617bfaa0f0STobias Hieta        },
3627bfaa0f0STobias Hieta        {
3632dadf8d7SMark de Wever            "name": "__cpp_lib_constexpr_new",
3642dadf8d7SMark de Wever            "values": {"c++26": 202406},  # P2747R2 constexpr placement new
3652dadf8d7SMark de Wever            "headers": ["new"],
3667808541fSA. Jiang            "test_suite_guard": "!defined(_LIBCPP_ABI_VCRUNTIME)",
3677808541fSA. Jiang            "libcxx_guard": "!defined(_LIBCPP_ABI_VCRUNTIME)",
3682dadf8d7SMark de Wever        },
3692dadf8d7SMark de Wever        {
370ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_constexpr_numeric",
371ff1b6f9fSArthur O'Dwyer            "values": {"c++20": 201911},
372ff1b6f9fSArthur O'Dwyer            "headers": ["numeric"],
3737bfaa0f0STobias Hieta        },
3747bfaa0f0STobias Hieta        {
375466df171SArthur O'Dwyer            "name": "__cpp_lib_constexpr_string",
376425620ccSNikolas Klauser            "values": {"c++20": 201907},
377466df171SArthur O'Dwyer            "headers": ["string"],
3787bfaa0f0STobias Hieta        },
3797bfaa0f0STobias Hieta        {
380466df171SArthur O'Dwyer            "name": "__cpp_lib_constexpr_string_view",
381466df171SArthur O'Dwyer            "values": {"c++20": 201811},
382466df171SArthur O'Dwyer            "headers": ["string_view"],
3837bfaa0f0STobias Hieta        },
3847bfaa0f0STobias Hieta        {
385466df171SArthur O'Dwyer            "name": "__cpp_lib_constexpr_tuple",
386466df171SArthur O'Dwyer            "values": {"c++20": 201811},
387466df171SArthur O'Dwyer            "headers": ["tuple"],
3887bfaa0f0STobias Hieta        },
3897bfaa0f0STobias Hieta        {
390855d7bedSArthur O'Dwyer            "name": "__cpp_lib_constexpr_typeinfo",
39171400505SMark de Wever            "values": {"c++23": 202106},
392855d7bedSArthur O'Dwyer            "headers": ["typeinfo"],
3937bfaa0f0STobias Hieta        },
3947bfaa0f0STobias Hieta        {
395ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_constexpr_utility",
396ff1b6f9fSArthur O'Dwyer            "values": {"c++20": 201811},
397ff1b6f9fSArthur O'Dwyer            "headers": ["utility"],
3987bfaa0f0STobias Hieta        },
3997bfaa0f0STobias Hieta        {
400466df171SArthur O'Dwyer            "name": "__cpp_lib_constexpr_vector",
401466df171SArthur O'Dwyer            "values": {"c++20": 201907},
402466df171SArthur O'Dwyer            "headers": ["vector"],
4037bfaa0f0STobias Hieta        },
4047bfaa0f0STobias Hieta        {
405b699a9baSLouis Dionne            "name": "__cpp_lib_constrained_equality",
406b699a9baSLouis Dionne            "values": {"c++26": 202403}, # P2944R3: Comparisons for reference_wrapper
407b699a9baSLouis Dionne            "headers": ["optional", "tuple", "utility", "variant"],
408b699a9baSLouis Dionne            "unimplemented": True,
409b699a9baSLouis Dionne        },
410b699a9baSLouis Dionne        {
411028f1b07Skrzysdz            "name": "__cpp_lib_containers_ranges",
412028f1b07Skrzysdz            "values": {"c++23": 202202},
413028f1b07Skrzysdz            "headers": [
414028f1b07Skrzysdz                "deque",
415028f1b07Skrzysdz                "forward_list",
416028f1b07Skrzysdz                "list",
417028f1b07Skrzysdz                "map",
418028f1b07Skrzysdz                "queue",
419028f1b07Skrzysdz                "set",
420028f1b07Skrzysdz                "stack",
421028f1b07Skrzysdz                "string",
422028f1b07Skrzysdz                "unordered_map",
423028f1b07Skrzysdz                "unordered_set",
424028f1b07Skrzysdz                "vector",
425028f1b07Skrzysdz            ],
426028f1b07Skrzysdz        },
427028f1b07Skrzysdz        {
4283f05d044SMark de Wever            "name": "__cpp_lib_copyable_function",
4293f05d044SMark de Wever            "values": {"c++26": 202306},  # P2548R6 copyable_function
4303f05d044SMark de Wever            "headers": ["functional"],
4313f05d044SMark de Wever            "unimplemented": True,
4323f05d044SMark de Wever        },
4333f05d044SMark de Wever        {
434466df171SArthur O'Dwyer            "name": "__cpp_lib_coroutine",
435466df171SArthur O'Dwyer            "values": {"c++20": 201902},
436466df171SArthur O'Dwyer            "headers": ["coroutine"],
4377bfaa0f0STobias Hieta        },
4387bfaa0f0STobias Hieta        {
439f49ccca8SMark de Wever            "name": "__cpp_lib_debugging",
440b699a9baSLouis Dionne            "values": {
441b699a9baSLouis Dionne                "c++26": 202311, # P2546R5 Debugging Support
442b699a9baSLouis Dionne                # "c++26": 202403, # P2810R4: is_debugger_present is_replaceable
443b699a9baSLouis Dionne            },
444f49ccca8SMark de Wever            "headers": ["debugging"],
445f49ccca8SMark de Wever            "unimplemented": True,
446f49ccca8SMark de Wever        },
447f49ccca8SMark de Wever        {
448b699a9baSLouis Dionne            "name": "__cpp_lib_default_template_type_for_algorithm_values",
449b699a9baSLouis Dionne            "values": {"c++26": 202403}, # P2248R8: Enabling list-initialization for algorithms
450b699a9baSLouis Dionne            "headers": ["algorithm", "deque", "forward_list", "list", "ranges", "string", "vector"],
451b699a9baSLouis Dionne            "unimplemented": True,
452b699a9baSLouis Dionne        },
453b699a9baSLouis Dionne        {
454ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_destroying_delete",
455ff1b6f9fSArthur O'Dwyer            "values": {"c++20": 201806},
456ff1b6f9fSArthur O'Dwyer            "headers": ["new"],
457c2c68a59SMark de Wever            "test_suite_guard": "TEST_STD_VER > 17 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L",
4584f15267dSNikolas Klauser            "libcxx_guard": "_LIBCPP_STD_VER >= 20 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L",
4597bfaa0f0STobias Hieta        },
4607bfaa0f0STobias Hieta        {
461ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_enable_shared_from_this",
462ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201603},
463ff1b6f9fSArthur O'Dwyer            "headers": ["memory"],
4647bfaa0f0STobias Hieta        },
4657bfaa0f0STobias Hieta        {
466ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_endian",
467ff1b6f9fSArthur O'Dwyer            "values": {"c++20": 201907},
468ff1b6f9fSArthur O'Dwyer            "headers": ["bit"],
4697bfaa0f0STobias Hieta        },
4707bfaa0f0STobias Hieta        {
471ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_erase_if",
472ff1b6f9fSArthur O'Dwyer            "values": {"c++20": 202002},
4737bfaa0f0STobias Hieta            "headers": [
4747bfaa0f0STobias Hieta                "deque",
4757bfaa0f0STobias Hieta                "forward_list",
4767bfaa0f0STobias Hieta                "list",
4777bfaa0f0STobias Hieta                "map",
4787bfaa0f0STobias Hieta                "set",
4797bfaa0f0STobias Hieta                "string",
4807bfaa0f0STobias Hieta                "unordered_map",
4817bfaa0f0STobias Hieta                "unordered_set",
4827bfaa0f0STobias Hieta                "vector",
4837bfaa0f0STobias Hieta            ],
4847bfaa0f0STobias Hieta        },
4857bfaa0f0STobias Hieta        {
486ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_exchange_function",
487ff1b6f9fSArthur O'Dwyer            "values": {"c++14": 201304},
488ff1b6f9fSArthur O'Dwyer            "headers": ["utility"],
4897bfaa0f0STobias Hieta        },
4907bfaa0f0STobias Hieta        {
491ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_execution",
492466df171SArthur O'Dwyer            "values": {"c++17": 201603, "c++20": 201902},
493ff1b6f9fSArthur O'Dwyer            "headers": ["execution"],
494ff1b6f9fSArthur O'Dwyer            "unimplemented": True,
4957bfaa0f0STobias Hieta        },
4967bfaa0f0STobias Hieta        {
497e356f681SHui Xie            "name": "__cpp_lib_expected",
49871400505SMark de Wever            "values": {"c++23": 202211},
499e356f681SHui Xie            "headers": ["expected"],
5007bfaa0f0STobias Hieta        },
5017bfaa0f0STobias Hieta        {
502ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_filesystem",
503ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201703},
504ff1b6f9fSArthur O'Dwyer            "headers": ["filesystem"],
505c6f3b7bcSNikolas Klauser            "test_suite_guard": "!defined(_LIBCPP_VERSION) || (_LIBCPP_HAS_FILESYSTEM && _LIBCPP_AVAILABILITY_HAS_FILESYSTEM_LIBRARY)",
506c6f3b7bcSNikolas Klauser            "libcxx_guard": "_LIBCPP_HAS_FILESYSTEM && _LIBCPP_AVAILABILITY_HAS_FILESYSTEM_LIBRARY",
5077bfaa0f0STobias Hieta        },
5087bfaa0f0STobias Hieta        {
509*def50f70SHui            "name": "__cpp_lib_flat_map",
510*def50f70SHui            "values": {"c++23": 202207},
511*def50f70SHui            "headers": ["flat_map"],
512*def50f70SHui        },
513*def50f70SHui        {
514*def50f70SHui            "name": "__cpp_lib_flat_set",
515*def50f70SHui            "values": {"c++23": 202207},
516*def50f70SHui            "headers": ["flat_set"],
517*def50f70SHui            "unimplemented": True,
518*def50f70SHui        },
519*def50f70SHui        {
520081c1db0SMark de Wever            "name": "__cpp_lib_format",
521b490c8a6SMark de Wever            "values": {
522deeb9368SMark de Wever                "c++20": 202110,
523b490c8a6SMark de Wever                # "c++23": 202207, Not implemented P2419R2 Clarify handling of encodings in localized formatting of chrono types
52427e67cdbSHristo Hristov                # "c++26": 202306, P2637R3 Member Visit (implemented)
52592d9f232SMark de Wever                # "c++26": 202311, P2918R2 Runtime format strings II (implemented)
526b490c8a6SMark de Wever            },
5273f05d044SMark de Wever            # Note these three papers are adopted at the June 2023 meeting and have sequential numbering
528a9e5773fSMark de Wever            # 202304 P2510R3 Formatting pointers (Implemented)
5293f05d044SMark de Wever            # 202305 P2757R3 Type-checking format args
5303f05d044SMark de Wever            # 202306 P2637R3 Member Visit
531081c1db0SMark de Wever            "headers": ["format"],
5327bfaa0f0STobias Hieta        },
5337bfaa0f0STobias Hieta        {
534b699a9baSLouis Dionne            "name": "__cpp_lib_format_path",
535a4bef0caSStephan T. Lavavej            "values": {"c++26": 202403},  # P2845R8: Formatting of std::filesystem::path
536b699a9baSLouis Dionne            "headers": ["filesystem"],
537b699a9baSLouis Dionne            "unimplemented": True,
538b699a9baSLouis Dionne        },
539b699a9baSLouis Dionne        {
540b2373540SMark de Wever            "name": "__cpp_lib_format_ranges",
54171400505SMark de Wever            "values": {"c++23": 202207},
542b2373540SMark de Wever            "headers": ["format"],
5437bfaa0f0STobias Hieta        },
5447bfaa0f0STobias Hieta        {
545f49ccca8SMark de Wever            "name": "__cpp_lib_format_uchar",
546f49ccca8SMark de Wever            "values": {
547f49ccca8SMark de Wever                "c++20": 202311  # DR P2909R4 Fix formatting of code units as integers
548f49ccca8SMark de Wever            },
5499c18f031SMark de Wever            "headers": [
5509c18f031SMark de Wever                "format"  # TODO verify this entry since the paper was underspecified.
5519c18f031SMark de Wever            ],
552f49ccca8SMark de Wever        },
553f49ccca8SMark de Wever        {
55488622aabSMark de Wever            "name": "__cpp_lib_formatters",
55571400505SMark de Wever            "values": {"c++23": 202302},
55688622aabSMark de Wever            "headers": ["stacktrace", "thread"],
55788622aabSMark de Wever            "unimplemented": True,
5587bfaa0f0STobias Hieta        },
5597bfaa0f0STobias Hieta        {
5603a49cffeSIgor Zhukov            "name": "__cpp_lib_forward_like",
56171400505SMark de Wever            "values": {"c++23": 202207},
5623a49cffeSIgor Zhukov            "headers": ["utility"],
5637bfaa0f0STobias Hieta        },
5647bfaa0f0STobias Hieta        {
565f49ccca8SMark de Wever            "name": "__cpp_lib_freestanding_algorithm",
566f49ccca8SMark de Wever            "values": {
567f49ccca8SMark de Wever                "c++26": 202311  # P2407R5 Freestanding Library: Partial Classes
568f49ccca8SMark de Wever            },
569f49ccca8SMark de Wever            "headers": ["algorithm"],
570f49ccca8SMark de Wever            "unimplemented": True,
571f49ccca8SMark de Wever        },
572f49ccca8SMark de Wever        {
573f49ccca8SMark de Wever            "name": "__cpp_lib_freestanding_array",
574f49ccca8SMark de Wever            "values": {
575f49ccca8SMark de Wever                "c++26": 202311  # P2407R5 Freestanding Library: Partial Classes
576f49ccca8SMark de Wever            },
577f49ccca8SMark de Wever            "headers": ["array"],
578f49ccca8SMark de Wever            "unimplemented": True,
579f49ccca8SMark de Wever        },
580f49ccca8SMark de Wever        {
581f49ccca8SMark de Wever            "name": "__cpp_lib_freestanding_cstring",
582f49ccca8SMark de Wever            "values": {
583f49ccca8SMark de Wever                "c++26": 202306  # P2338R4 Freestanding Library: Character primitives and the C library
584f49ccca8SMark de Wever                #        202311  # P2407R5 Freestanding Library: Partial Classes
585f49ccca8SMark de Wever            },
586f49ccca8SMark de Wever            "headers": ["cstring"],
587f49ccca8SMark de Wever            "unimplemented": True,
588f49ccca8SMark de Wever        },
589f49ccca8SMark de Wever        {
590f49ccca8SMark de Wever            "name": "__cpp_lib_freestanding_expected",
591f49ccca8SMark de Wever            "values": {
592f49ccca8SMark de Wever                "c++26": 202311  # P2833R2 Freestanding Library: inout expected span
593f49ccca8SMark de Wever            },
594f49ccca8SMark de Wever            "headers": ["expected"],
595f49ccca8SMark de Wever            "unimplemented": True,
596f49ccca8SMark de Wever        },
597f49ccca8SMark de Wever        {
598f49ccca8SMark de Wever            "name": "__cpp_lib_freestanding_mdspan",
599f49ccca8SMark de Wever            "values": {
600f49ccca8SMark de Wever                "c++26": 202311  # P2833R2 Freestanding Library: inout expected span
601f49ccca8SMark de Wever            },
602f49ccca8SMark de Wever            "headers": ["mdspan"],
603f49ccca8SMark de Wever            "unimplemented": True,
604f49ccca8SMark de Wever        },
605f49ccca8SMark de Wever        {
606f49ccca8SMark de Wever            "name": "__cpp_lib_freestanding_optional",
607f49ccca8SMark de Wever            "values": {
608f49ccca8SMark de Wever                "c++26": 202311  # P2407R5 Freestanding Library: Partial Classes
609f49ccca8SMark de Wever            },
610f49ccca8SMark de Wever            "headers": ["optional"],
611f49ccca8SMark de Wever            "unimplemented": True,
612f49ccca8SMark de Wever        },
613f49ccca8SMark de Wever        {
614f49ccca8SMark de Wever            "name": "__cpp_lib_freestanding_string_view",
615f49ccca8SMark de Wever            "values": {
616f49ccca8SMark de Wever                "c++26": 202311  # P2407R5 Freestanding Library: Partial Classes
617f49ccca8SMark de Wever            },
618f49ccca8SMark de Wever            "headers": ["string_view"],
619f49ccca8SMark de Wever            "unimplemented": True,
620f49ccca8SMark de Wever        },
621f49ccca8SMark de Wever        {
622f49ccca8SMark de Wever            "name": "__cpp_lib_freestanding_variant",
623f49ccca8SMark de Wever            "values": {
624f49ccca8SMark de Wever                "c++26": 202311  # P2407R5 Freestanding Library: Partial Classes
625f49ccca8SMark de Wever            },
626f49ccca8SMark de Wever            "headers": ["variant"],
627f49ccca8SMark de Wever            "unimplemented": True,
628f49ccca8SMark de Wever        },
629f49ccca8SMark de Wever        {
6303f05d044SMark de Wever            "name": "__cpp_lib_fstream_native_handle",
6313f05d044SMark de Wever            "values": {"c++26": 202306},  # P1759R6 Native handles and file streams
6323f05d044SMark de Wever            "headers": ["fstream"],
633c6f3b7bcSNikolas Klauser            "test_suite_guard": "!defined(_LIBCPP_VERSION) || (_LIBCPP_HAS_FILESYSTEM && _LIBCPP_HAS_LOCALIZATION)",
634c6f3b7bcSNikolas Klauser            "libcxx_guard": "_LIBCPP_HAS_FILESYSTEM && _LIBCPP_HAS_LOCALIZATION",
6353f05d044SMark de Wever        },
6363f05d044SMark de Wever        {
6373f05d044SMark de Wever            "name": "__cpp_lib_function_ref",
638f49ccca8SMark de Wever            "values": {
639f49ccca8SMark de Wever                "c++26": 202306  # P0792R14 function_ref: a type-erased callable reference
640f49ccca8SMark de Wever            },
6413f05d044SMark de Wever            "headers": ["functional"],
6423f05d044SMark de Wever            "unimplemented": True,
6433f05d044SMark de Wever        },
6443f05d044SMark de Wever        {
645ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_gcd_lcm",
646ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201606},
647ff1b6f9fSArthur O'Dwyer            "headers": ["numeric"],
6487bfaa0f0STobias Hieta        },
6497bfaa0f0STobias Hieta        {
650b699a9baSLouis Dionne            "name": "__cpp_lib_generate_random",
651b699a9baSLouis Dionne            "values": {"c++26": 202403}, # P1068R11: Vector API for random number generation
652b699a9baSLouis Dionne            "headers": ["random"],
653b699a9baSLouis Dionne            "unimplemented": True,
654b699a9baSLouis Dionne        },
655b699a9baSLouis Dionne        {
656ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_generic_associative_lookup",
657ff1b6f9fSArthur O'Dwyer            "values": {"c++14": 201304},
658ff1b6f9fSArthur O'Dwyer            "headers": ["map", "set"],
6597bfaa0f0STobias Hieta        },
6607bfaa0f0STobias Hieta        {
661ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_generic_unordered_lookup",
662ff1b6f9fSArthur O'Dwyer            "values": {"c++20": 201811},
663ff1b6f9fSArthur O'Dwyer            "headers": ["unordered_map", "unordered_set"],
6647bfaa0f0STobias Hieta        },
6657bfaa0f0STobias Hieta        {
666ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_hardware_interference_size",
667ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201703},
6688f018d3cSStephan T. Lavavej            "test_suite_guard": "!defined(_LIBCPP_VERSION) || (defined(__GCC_DESTRUCTIVE_SIZE) && defined(__GCC_CONSTRUCTIVE_SIZE))",
66956a33ba3SNikolas Klauser            "libcxx_guard": "defined(__GCC_DESTRUCTIVE_SIZE) && defined(__GCC_CONSTRUCTIVE_SIZE)",
670ff1b6f9fSArthur O'Dwyer            "headers": ["new"],
6717bfaa0f0STobias Hieta        },
6727bfaa0f0STobias Hieta        {
673ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_has_unique_object_representations",
674ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201606},
675ff1b6f9fSArthur O'Dwyer            "headers": ["type_traits"],
6767bfaa0f0STobias Hieta        },
6777bfaa0f0STobias Hieta        {
6783f05d044SMark de Wever            "name": "__cpp_lib_hazard_pointer",
6793f05d044SMark de Wever            "values": {"c++26": 202306},  # P2530R3 Hazard Pointers for C++26
680f49ccca8SMark de Wever            "headers": [
681f49ccca8SMark de Wever                "hazard_pointer"  # TODO verify this entry since the paper was underspecified.
682f49ccca8SMark de Wever            ],
6833f05d044SMark de Wever            "unimplemented": True,
6843f05d044SMark de Wever        },
6853f05d044SMark de Wever        {
686ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_hypot",
687ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201603},
688ff1b6f9fSArthur O'Dwyer            "headers": ["cmath"],
6897bfaa0f0STobias Hieta        },
6907bfaa0f0STobias Hieta        {
691ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_incomplete_container_elements",
692ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201505},
693ff1b6f9fSArthur O'Dwyer            "headers": ["forward_list", "list", "vector"],
6947bfaa0f0STobias Hieta        },
6957bfaa0f0STobias Hieta        {
6962dadf8d7SMark de Wever            "name": "__cpp_lib_inplace_vector",
6972dadf8d7SMark de Wever            "values": {"c++26": 202406},  # P0843R14 inplace_vector
6982dadf8d7SMark de Wever            "headers": ["inplace_vector"],
6992dadf8d7SMark de Wever            "unimplemented": True,
7002dadf8d7SMark de Wever        },
7012dadf8d7SMark de Wever        {
702ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_int_pow2",
703ff1b6f9fSArthur O'Dwyer            "values": {"c++20": 202002},
704ff1b6f9fSArthur O'Dwyer            "headers": ["bit"],
7057bfaa0f0STobias Hieta        },
7067bfaa0f0STobias Hieta        {
707466df171SArthur O'Dwyer            "name": "__cpp_lib_integer_comparison_functions",
708466df171SArthur O'Dwyer            "values": {"c++20": 202002},
709466df171SArthur O'Dwyer            "headers": ["utility"],
7107bfaa0f0STobias Hieta        },
7117bfaa0f0STobias Hieta        {
712ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_integer_sequence",
713ff1b6f9fSArthur O'Dwyer            "values": {"c++14": 201304},
714ff1b6f9fSArthur O'Dwyer            "headers": ["utility"],
7157bfaa0f0STobias Hieta        },
7167bfaa0f0STobias Hieta        {
717ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_integral_constant_callable",
718ff1b6f9fSArthur O'Dwyer            "values": {"c++14": 201304},
719ff1b6f9fSArthur O'Dwyer            "headers": ["type_traits"],
7207bfaa0f0STobias Hieta        },
7217bfaa0f0STobias Hieta        {
722ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_interpolate",
723ff1b6f9fSArthur O'Dwyer            "values": {"c++20": 201902},
724466df171SArthur O'Dwyer            "headers": ["cmath", "numeric"],
7257bfaa0f0STobias Hieta        },
7267bfaa0f0STobias Hieta        {
727ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_invoke",
728ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201411},
729ff1b6f9fSArthur O'Dwyer            "headers": ["functional"],
7307bfaa0f0STobias Hieta        },
7317bfaa0f0STobias Hieta        {
732855d7bedSArthur O'Dwyer            "name": "__cpp_lib_invoke_r",
73371400505SMark de Wever            "values": {"c++23": 202106},
734855d7bedSArthur O'Dwyer            "headers": ["functional"],
7357bfaa0f0STobias Hieta        },
7367bfaa0f0STobias Hieta        {
737a3f17ba3SPragmaTwice            "name": "__cpp_lib_ios_noreplace",
738a3f17ba3SPragmaTwice            "values": {"c++23": 202207},
739a3f17ba3SPragmaTwice            "headers": ["ios"],
740a3f17ba3SPragmaTwice        },
741a3f17ba3SPragmaTwice        {
742ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_is_aggregate",
743ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201703},
744ff1b6f9fSArthur O'Dwyer            "headers": ["type_traits"],
7457bfaa0f0STobias Hieta        },
7467bfaa0f0STobias Hieta        {
747ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_is_constant_evaluated",
748ff1b6f9fSArthur O'Dwyer            "values": {"c++20": 201811},
749ff1b6f9fSArthur O'Dwyer            "headers": ["type_traits"],
7507bfaa0f0STobias Hieta        },
7517bfaa0f0STobias Hieta        {
752ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_is_final",
753ff1b6f9fSArthur O'Dwyer            "values": {"c++14": 201402},
754ff1b6f9fSArthur O'Dwyer            "headers": ["type_traits"],
7557bfaa0f0STobias Hieta        },
7567bfaa0f0STobias Hieta        {
757a06591b4SHristo Hristov            "name": "__cpp_lib_is_implicit_lifetime",
758a06591b4SHristo Hristov            "values": {"c++23": 202302},
759a06591b4SHristo Hristov            "headers": ["type_traits"],
760a06591b4SHristo Hristov            "test_suite_guard": "__has_builtin(__builtin_is_implicit_lifetime)",
761a06591b4SHristo Hristov            "libcxx_guard": "__has_builtin(__builtin_is_implicit_lifetime)",
762a06591b4SHristo Hristov        },
763a06591b4SHristo Hristov        {
764ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_is_invocable",
765ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201703},
766ff1b6f9fSArthur O'Dwyer            "headers": ["type_traits"],
7677bfaa0f0STobias Hieta        },
7687bfaa0f0STobias Hieta        {
769466df171SArthur O'Dwyer            "name": "__cpp_lib_is_layout_compatible",
770466df171SArthur O'Dwyer            "values": {"c++20": 201907},
771466df171SArthur O'Dwyer            "headers": ["type_traits"],
772466df171SArthur O'Dwyer            "unimplemented": True,
7737bfaa0f0STobias Hieta        },
7747bfaa0f0STobias Hieta        {
775466df171SArthur O'Dwyer            "name": "__cpp_lib_is_nothrow_convertible",
776466df171SArthur O'Dwyer            "values": {"c++20": 201806},
777466df171SArthur O'Dwyer            "headers": ["type_traits"],
7787bfaa0f0STobias Hieta        },
7797bfaa0f0STobias Hieta        {
780ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_is_null_pointer",
781ff1b6f9fSArthur O'Dwyer            "values": {"c++14": 201309},
782ff1b6f9fSArthur O'Dwyer            "headers": ["type_traits"],
7837bfaa0f0STobias Hieta        },
7847bfaa0f0STobias Hieta        {
785466df171SArthur O'Dwyer            "name": "__cpp_lib_is_pointer_interconvertible",
786466df171SArthur O'Dwyer            "values": {"c++20": 201907},
787466df171SArthur O'Dwyer            "headers": ["type_traits"],
788466df171SArthur O'Dwyer            "unimplemented": True,
7897bfaa0f0STobias Hieta        },
7907bfaa0f0STobias Hieta        {
79195729f95SMarek Kurdej            "name": "__cpp_lib_is_scoped_enum",
79271400505SMark de Wever            "values": {"c++23": 202011},
79395729f95SMarek Kurdej            "headers": ["type_traits"],
7947bfaa0f0STobias Hieta        },
7957bfaa0f0STobias Hieta        {
796ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_is_swappable",
797ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201603},
798ff1b6f9fSArthur O'Dwyer            "headers": ["type_traits"],
7997bfaa0f0STobias Hieta        },
8007bfaa0f0STobias Hieta        {
8012dadf8d7SMark de Wever            "name": "__cpp_lib_is_virtual_base_of",
8022dadf8d7SMark de Wever            "values": {
8032dadf8d7SMark de Wever                "c++26": 202406  # P2985R0 A type trait for detecting virtual base classes
8042dadf8d7SMark de Wever            },
8052dadf8d7SMark de Wever            "headers": ["type_traits"],
8061c48c9ccSLouis Dionne            "test_suite_guard": "__has_builtin(__builtin_is_virtual_base_of)",
8071c48c9ccSLouis Dionne            "libcxx_guard": "__has_builtin(__builtin_is_virtual_base_of)",
8082dadf8d7SMark de Wever        },
8092dadf8d7SMark de Wever        {
8108f711aa3SMital Ashok            "name": "__cpp_lib_is_within_lifetime",
8118f711aa3SMital Ashok            # Note this name was changed from "__cpp_lib_within_lifetime" when the paper was adopted
8128f711aa3SMital Ashok            # https://github.com/cplusplus/draft/commit/0facada4cadd97e1ba15bfaea76a804f1dc5c309
8138f711aa3SMital Ashok            "values": {
8148f711aa3SMital Ashok                "c++26": 202306  # P2641R4 Checking if a union alternative is active
8158f711aa3SMital Ashok            },
8168f711aa3SMital Ashok            "headers": ["type_traits"],
8178f711aa3SMital Ashok            "unimplemented": True,
8188f711aa3SMital Ashok        },
8198f711aa3SMital Ashok        {
820466df171SArthur O'Dwyer            "name": "__cpp_lib_jthread",
821466df171SArthur O'Dwyer            "values": {"c++20": 201911},
822466df171SArthur O'Dwyer            "headers": ["stop_token", "thread"],
823c6f3b7bcSNikolas Klauser            "test_suite_guard": "!defined(_LIBCPP_VERSION) || (_LIBCPP_HAS_THREADS && _LIBCPP_AVAILABILITY_HAS_SYNC)",
824c6f3b7bcSNikolas Klauser            "libcxx_guard": "_LIBCPP_HAS_THREADS && _LIBCPP_AVAILABILITY_HAS_SYNC",
8257bfaa0f0STobias Hieta        },
8267bfaa0f0STobias Hieta        {
827466df171SArthur O'Dwyer            "name": "__cpp_lib_latch",
828466df171SArthur O'Dwyer            "values": {"c++20": 201907},
829466df171SArthur O'Dwyer            "headers": ["latch"],
830c6f3b7bcSNikolas Klauser            "test_suite_guard": "!defined(_LIBCPP_VERSION) || (_LIBCPP_HAS_THREADS && _LIBCPP_AVAILABILITY_HAS_SYNC)",
831c6f3b7bcSNikolas Klauser            "libcxx_guard": "_LIBCPP_HAS_THREADS && _LIBCPP_AVAILABILITY_HAS_SYNC",
8327bfaa0f0STobias Hieta        },
8337bfaa0f0STobias Hieta        {
834ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_launder",
835ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201606},
836ff1b6f9fSArthur O'Dwyer            "headers": ["new"],
8377bfaa0f0STobias Hieta        },
8387bfaa0f0STobias Hieta        {
839f49ccca8SMark de Wever            "name": "__cpp_lib_linalg",
840f49ccca8SMark de Wever            "values": {
841f49ccca8SMark de Wever                "c++26": 202311  # P1673 A free function linear algebra interface based on the BLAS
842f49ccca8SMark de Wever            },
843f49ccca8SMark de Wever            "headers": ["linalg"],
844f49ccca8SMark de Wever            "unimplemented": True,
845f49ccca8SMark de Wever        },
846f49ccca8SMark de Wever        {
847ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_list_remove_return_type",
848ff1b6f9fSArthur O'Dwyer            "values": {"c++20": 201806},
849ff1b6f9fSArthur O'Dwyer            "headers": ["forward_list", "list"],
8507bfaa0f0STobias Hieta        },
8517bfaa0f0STobias Hieta        {
852ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_logical_traits",
853ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201510},
854ff1b6f9fSArthur O'Dwyer            "headers": ["type_traits"],
8557bfaa0f0STobias Hieta        },
8567bfaa0f0STobias Hieta        {
857ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_make_from_tuple",
858ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201606},
859ff1b6f9fSArthur O'Dwyer            "headers": ["tuple"],
8607bfaa0f0STobias Hieta        },
8617bfaa0f0STobias Hieta        {
862ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_make_reverse_iterator",
863ff1b6f9fSArthur O'Dwyer            "values": {"c++14": 201402},
864ff1b6f9fSArthur O'Dwyer            "headers": ["iterator"],
8657bfaa0f0STobias Hieta        },
8667bfaa0f0STobias Hieta        {
867ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_make_unique",
868ff1b6f9fSArthur O'Dwyer            "values": {"c++14": 201304},
869ff1b6f9fSArthur O'Dwyer            "headers": ["memory"],
8707bfaa0f0STobias Hieta        },
8717bfaa0f0STobias Hieta        {
872ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_map_try_emplace",
873ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201411},
874ff1b6f9fSArthur O'Dwyer            "headers": ["map"],
8757bfaa0f0STobias Hieta        },
8767bfaa0f0STobias Hieta        {
877ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_math_constants",
878ff1b6f9fSArthur O'Dwyer            "values": {"c++20": 201907},
879ff1b6f9fSArthur O'Dwyer            "headers": ["numbers"],
8807bfaa0f0STobias Hieta        },
8817bfaa0f0STobias Hieta        {
882ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_math_special_functions",
883ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201603},
884ff1b6f9fSArthur O'Dwyer            "headers": ["cmath"],
885ff1b6f9fSArthur O'Dwyer            "unimplemented": True,
8867bfaa0f0STobias Hieta        },
8877bfaa0f0STobias Hieta        {
888fcaccf81SChristian Trott            "name": "__cpp_lib_mdspan",
8892dadf8d7SMark de Wever            "values": {
8902dadf8d7SMark de Wever                "c++23": 202207,
8914e338dceSXiaoyang Liu                "c++26": 202406,  # P2389R2 dextents Index Type Parameter
8922dadf8d7SMark de Wever            },
893fcaccf81SChristian Trott            "headers": ["mdspan"],
8947bfaa0f0STobias Hieta        },
8957bfaa0f0STobias Hieta        {
896ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_memory_resource",
897ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201603},
898ff1b6f9fSArthur O'Dwyer            "headers": ["memory_resource"],
89912563ea6Sphilnik777            "test_suite_guard": "!defined(_LIBCPP_VERSION) || _LIBCPP_AVAILABILITY_HAS_PMR",
90012563ea6Sphilnik777            "libcxx_guard": "_LIBCPP_AVAILABILITY_HAS_PMR",
9017bfaa0f0STobias Hieta        },
9027bfaa0f0STobias Hieta        {
903759fb590SMark de Wever            "name": "__cpp_lib_modules",
904759fb590SMark de Wever            "values": {"c++23": 202207},
905759fb590SMark de Wever            "headers": [],
906759fb590SMark de Wever        },
907759fb590SMark de Wever        {
908813e1da9SShivam kunwar            "name": "__cpp_lib_move_iterator_concept",
909813e1da9SShivam kunwar            "values": {"c++20": 202207},
910813e1da9SShivam kunwar            "headers": ["iterator"],
9117bfaa0f0STobias Hieta        },
9127bfaa0f0STobias Hieta        {
913855d7bedSArthur O'Dwyer            "name": "__cpp_lib_move_only_function",
91471400505SMark de Wever            "values": {"c++23": 202110},
915855d7bedSArthur O'Dwyer            "headers": ["functional"],
916855d7bedSArthur O'Dwyer            "unimplemented": True,
9177bfaa0f0STobias Hieta        },
9187bfaa0f0STobias Hieta        {
919ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_node_extract",
920ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201606},
921ff1b6f9fSArthur O'Dwyer            "headers": ["map", "set", "unordered_map", "unordered_set"],
9227bfaa0f0STobias Hieta        },
9237bfaa0f0STobias Hieta        {
924ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_nonmember_container_access",
925ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201411},
9267bfaa0f0STobias Hieta            "headers": [
9277bfaa0f0STobias Hieta                "array",
9287bfaa0f0STobias Hieta                "deque",
9297bfaa0f0STobias Hieta                "forward_list",
9307bfaa0f0STobias Hieta                "iterator",
9317bfaa0f0STobias Hieta                "list",
9327bfaa0f0STobias Hieta                "map",
9337bfaa0f0STobias Hieta                "regex",
9347bfaa0f0STobias Hieta                "set",
9357bfaa0f0STobias Hieta                "string",
9367bfaa0f0STobias Hieta                "unordered_map",
9377bfaa0f0STobias Hieta                "unordered_set",
9387bfaa0f0STobias Hieta                "vector",
9397bfaa0f0STobias Hieta            ],
9407bfaa0f0STobias Hieta        },
9417bfaa0f0STobias Hieta        {
942ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_not_fn",
9433f05d044SMark de Wever            "values": {
9443f05d044SMark de Wever                "c++17": 201603,
945c91d805eSJakub Mazurkiewicz                "c++26": 202306,  # P2714R1 Bind front and back to NTTP callables
9463f05d044SMark de Wever            },
947ff1b6f9fSArthur O'Dwyer            "headers": ["functional"],
9487bfaa0f0STobias Hieta        },
9497bfaa0f0STobias Hieta        {
950ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_null_iterators",
951ff1b6f9fSArthur O'Dwyer            "values": {"c++14": 201304},
952ff1b6f9fSArthur O'Dwyer            "headers": ["iterator"],
9537bfaa0f0STobias Hieta        },
9547bfaa0f0STobias Hieta        {
955ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_optional",
956cae351f3SA. Jiang            "values": {
957cae351f3SA. Jiang                "c++17": 201606,
958cae351f3SA. Jiang                "c++20": 202106,  # P2231R1 Missing constexpr in std::optional and std::variant
959cae351f3SA. Jiang                "c++23": 202110,  # P0798R8 Monadic operations for std::optional + LWG3621 Remove feature-test macro __cpp_lib_monadic_optional
960cae351f3SA. Jiang            },
961ff1b6f9fSArthur O'Dwyer            "headers": ["optional"],
9627bfaa0f0STobias Hieta        },
9637bfaa0f0STobias Hieta        {
9642dadf8d7SMark de Wever            "name": "__cpp_lib_optional_range_support",
9652dadf8d7SMark de Wever            "values": {"c++26": 202406},  # P3168R2 Give std::optional Range Support
9662dadf8d7SMark de Wever            "headers": ["optional"],
9672dadf8d7SMark de Wever            "unimplemented": True,
9682dadf8d7SMark de Wever        },
9692dadf8d7SMark de Wever        {
970855d7bedSArthur O'Dwyer            "name": "__cpp_lib_out_ptr",
971f49ccca8SMark de Wever            "values": {
972f49ccca8SMark de Wever                "c++23": 202106,
973f49ccca8SMark de Wever                "c++26": 202311,  # P2833R2 Freestanding Library: inout expected span
974f49ccca8SMark de Wever            },
975855d7bedSArthur O'Dwyer            "headers": ["memory"],
9767bfaa0f0STobias Hieta        },
9777bfaa0f0STobias Hieta        {
978ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_parallel_algorithm",
979ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201603},
980ff1b6f9fSArthur O'Dwyer            "headers": ["algorithm", "numeric"],
981ff1b6f9fSArthur O'Dwyer            "unimplemented": True,
9827bfaa0f0STobias Hieta        },
9837bfaa0f0STobias Hieta        {
9842dadf8d7SMark de Wever            "name": "__cpp_lib_philox_engine",
9852dadf8d7SMark de Wever            "values": {
9862dadf8d7SMark de Wever                "c++26": 202406
9872dadf8d7SMark de Wever            },  # P2075R6 Philox as an extension of the C++ RNG engines
9882dadf8d7SMark de Wever            # Note the paper mentions 202310L as value, which differs from the typical procedure.
9892dadf8d7SMark de Wever            "headers": ["random"],
9902dadf8d7SMark de Wever            "unimplemented": True,
9912dadf8d7SMark de Wever        },
9922dadf8d7SMark de Wever        {
993466df171SArthur O'Dwyer            "name": "__cpp_lib_polymorphic_allocator",
994466df171SArthur O'Dwyer            "values": {"c++20": 201902},
9955d78fef6SArthur O'Dwyer            "headers": ["memory_resource"],
99612563ea6Sphilnik777            "test_suite_guard": "!defined(_LIBCPP_VERSION) || _LIBCPP_AVAILABILITY_HAS_PMR",
99712563ea6Sphilnik777            "libcxx_guard": "_LIBCPP_AVAILABILITY_HAS_PMR",
9987bfaa0f0STobias Hieta        },
9997bfaa0f0STobias Hieta        {
10003f65f718SMark de Wever            "name": "__cpp_lib_print",
1001b699a9baSLouis Dionne            "values": {
1002b699a9baSLouis Dionne                "c++23": 202207,
1003b699a9baSLouis Dionne                # "c++26": 202403, # P3107R5: Permit an efficient implementation of std::print
10042dadf8d7SMark de Wever                # "c++26": 202406, # P3235R3 std::print more types faster with less memory
1005b699a9baSLouis Dionne            },
10063f65f718SMark de Wever            "headers": ["ostream", "print"],
10073f65f718SMark de Wever        },
10083f65f718SMark de Wever        {
1009ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_quoted_string_io",
1010ff1b6f9fSArthur O'Dwyer            "values": {"c++14": 201304},
1011ff1b6f9fSArthur O'Dwyer            "headers": ["iomanip"],
1012c6f3b7bcSNikolas Klauser            "test_suite_guard": "!defined(_LIBCPP_VERSION) || _LIBCPP_HAS_LOCALIZATION",
1013c6f3b7bcSNikolas Klauser            "libcxx_guard": "_LIBCPP_HAS_LOCALIZATION",
10147bfaa0f0STobias Hieta        },
10157bfaa0f0STobias Hieta        {
1016ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_ranges",
10172dadf8d7SMark de Wever            "values": {
1018026210e8SA. Jiang                "c++20": 202110,  # P2415R2 What is a view?
1019026210e8SA. Jiang                "c++23": 202406,  # P2997R1 Removing the common reference requirement from the indirectly invocable concepts (implemented as a DR against C++20)
10202dadf8d7SMark de Wever            },
1021ff1b6f9fSArthur O'Dwyer            "headers": ["algorithm", "functional", "iterator", "memory", "ranges"],
10227bfaa0f0STobias Hieta        },
10237bfaa0f0STobias Hieta        {
1024f49ccca8SMark de Wever            "name": "__cpp_lib_ranges_as_const",
1025f49ccca8SMark de Wever            "values": {
1026f49ccca8SMark de Wever                "c++23": 202207  # P2278R4 cbegin should always return a constant iterator
1027f49ccca8SMark de Wever                #        202311  # DR P2836R1 std::basic_const_iterator should follow its underlying type’s convertibility
1028f49ccca8SMark de Wever            },
1029f49ccca8SMark de Wever            "headers": ["ranges"],
1030f49ccca8SMark de Wever            "unimplemented": True,
1031f49ccca8SMark de Wever        },
1032f49ccca8SMark de Wever        {
10333d4b7a6fSNikolas Klauser            "name": "__cpp_lib_ranges_as_rvalue",
103471400505SMark de Wever            "values": {"c++23": 202207},
10353d4b7a6fSNikolas Klauser            "headers": ["ranges"],
10367bfaa0f0STobias Hieta        },
10377bfaa0f0STobias Hieta        {
1038a5b4479dSNikolas Klauser            "name": "__cpp_lib_ranges_chunk",
103971400505SMark de Wever            "values": {"c++23": 202202},
1040a5b4479dSNikolas Klauser            "headers": ["ranges"],
1041a5b4479dSNikolas Klauser            "unimplemented": True,
10427bfaa0f0STobias Hieta        },
10437bfaa0f0STobias Hieta        {
1044a5b4479dSNikolas Klauser            "name": "__cpp_lib_ranges_chunk_by",
104571400505SMark de Wever            "values": {"c++23": 202202},
1046a5b4479dSNikolas Klauser            "headers": ["ranges"],
10477bfaa0f0STobias Hieta        },
10487bfaa0f0STobias Hieta        {
1049b699a9baSLouis Dionne            "name": "__cpp_lib_ranges_concat",
1050b699a9baSLouis Dionne            "values": {"c++26": 202403}, # P2542R8: views::concat
1051b699a9baSLouis Dionne            "headers": ["ranges"],
1052b699a9baSLouis Dionne            "unimplemented": True,
1053b699a9baSLouis Dionne        },
1054b699a9baSLouis Dionne        {
10557d7d4752SZijunZhaoCCK            "name": "__cpp_lib_ranges_contains",
10567d7d4752SZijunZhaoCCK            "values": {"c++23": 202207},
10577d7d4752SZijunZhaoCCK            "headers": ["algorithm"],
10587d7d4752SZijunZhaoCCK        },
10597d7d4752SZijunZhaoCCK        {
106004760bfaSnicole mazzuca            "name": "__cpp_lib_ranges_find_last",
106104760bfaSnicole mazzuca            "values": {"c++23": 202207},
106204760bfaSnicole mazzuca            "headers": ["algorithm"],
106304760bfaSnicole mazzuca        },
106404760bfaSnicole mazzuca        {
1065a5b4479dSNikolas Klauser            "name": "__cpp_lib_ranges_iota",
106671400505SMark de Wever            "values": {"c++23": 202202},
1067a5b4479dSNikolas Klauser            "headers": ["numeric"],
1068a5b4479dSNikolas Klauser            "unimplemented": True,
10697bfaa0f0STobias Hieta        },
10707bfaa0f0STobias Hieta        {
1071a5b4479dSNikolas Klauser            "name": "__cpp_lib_ranges_join_with",
107271400505SMark de Wever            "values": {"c++23": 202202},
1073a5b4479dSNikolas Klauser            "headers": ["ranges"],
1074a5b4479dSNikolas Klauser            "unimplemented": True,
10757bfaa0f0STobias Hieta        },
10767bfaa0f0STobias Hieta        {
1077a2160dd3Syrong            "name": "__cpp_lib_ranges_repeat",
1078a2160dd3Syrong            "values": {"c++23": 202207},
1079a2160dd3Syrong            "headers": ["ranges"],
1080a2160dd3Syrong        },
1081a2160dd3Syrong        {
1082a5b4479dSNikolas Klauser            "name": "__cpp_lib_ranges_slide",
108371400505SMark de Wever            "values": {"c++23": 202202},
1084a5b4479dSNikolas Klauser            "headers": ["ranges"],
1085a5b4479dSNikolas Klauser            "unimplemented": True,
10867bfaa0f0STobias Hieta        },
10877bfaa0f0STobias Hieta        {
1088855d7bedSArthur O'Dwyer            "name": "__cpp_lib_ranges_starts_ends_with",
108971400505SMark de Wever            "values": {"c++23": 202106},
1090855d7bedSArthur O'Dwyer            "headers": ["algorithm"],
10917bfaa0f0STobias Hieta        },
10927bfaa0f0STobias Hieta        {
1093a5b4479dSNikolas Klauser            "name": "__cpp_lib_ranges_to_container",
109471400505SMark de Wever            "values": {"c++23": 202202},
1095028f1b07Skrzysdz            "headers": ["ranges"],
10967bfaa0f0STobias Hieta        },
10977bfaa0f0STobias Hieta        {
1098855d7bedSArthur O'Dwyer            "name": "__cpp_lib_ranges_zip",
109971400505SMark de Wever            "values": {"c++23": 202110},
1100855d7bedSArthur O'Dwyer            "headers": ["ranges", "tuple", "utility"],
1101855d7bedSArthur O'Dwyer            "unimplemented": True,
11027bfaa0f0STobias Hieta        },
11037bfaa0f0STobias Hieta        {
11043f05d044SMark de Wever            "name": "__cpp_lib_ratio",
11053f05d044SMark de Wever            "values": {"c++26": 202306},  # P2734R0 Adding the new SI prefixes
11063f05d044SMark de Wever            "headers": ["ratio"],
11073f05d044SMark de Wever        },
11083f05d044SMark de Wever        {
1109ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_raw_memory_algorithms",
1110ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201606},
1111ff1b6f9fSArthur O'Dwyer            "headers": ["memory"],
11127bfaa0f0STobias Hieta        },
11137bfaa0f0STobias Hieta        {
11143f05d044SMark de Wever            "name": "__cpp_lib_rcu",
11153f05d044SMark de Wever            "values": {"c++26": 202306},  # P2545R4 Read-Copy Update (RCU)
1116f49ccca8SMark de Wever            "headers": [
1117f49ccca8SMark de Wever                "rcu"  # TODO verify this entry since the paper was underspecified.
1118f49ccca8SMark de Wever            ],
11193f05d044SMark de Wever            "unimplemented": True,
11203f05d044SMark de Wever        },
11213f05d044SMark de Wever        {
1122a5b4479dSNikolas Klauser            "name": "__cpp_lib_reference_from_temporary",
112371400505SMark de Wever            "values": {"c++23": 202202},
1124a5b4479dSNikolas Klauser            "headers": ["type_traits"],
1125a5b4479dSNikolas Klauser            "unimplemented": True,
11267bfaa0f0STobias Hieta        },
11277bfaa0f0STobias Hieta        {
1128b699a9baSLouis Dionne            "name": "__cpp_lib_reference_wrapper",
1129b699a9baSLouis Dionne            "values": {"c++26": 202403}, # P2944R3: Comparisons for reference_wrapper
1130b699a9baSLouis Dionne            "headers": ["functional"],
1131b699a9baSLouis Dionne        },
1132b699a9baSLouis Dionne        {
1133466df171SArthur O'Dwyer            "name": "__cpp_lib_remove_cvref",
1134466df171SArthur O'Dwyer            "values": {"c++20": 201711},
1135466df171SArthur O'Dwyer            "headers": ["type_traits"],
11367bfaa0f0STobias Hieta        },
11377bfaa0f0STobias Hieta        {
1138ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_result_of_sfinae",
1139ff1b6f9fSArthur O'Dwyer            "values": {"c++14": 201210},
1140ff1b6f9fSArthur O'Dwyer            "headers": ["functional", "type_traits"],
11417bfaa0f0STobias Hieta        },
11427bfaa0f0STobias Hieta        {
1143ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_robust_nonmodifying_seq_ops",
1144ff1b6f9fSArthur O'Dwyer            "values": {"c++14": 201304},
1145ff1b6f9fSArthur O'Dwyer            "headers": ["algorithm"],
11467bfaa0f0STobias Hieta        },
11477bfaa0f0STobias Hieta        {
1148ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_sample",
1149ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201603},
1150ff1b6f9fSArthur O'Dwyer            "headers": ["algorithm"],
11517bfaa0f0STobias Hieta        },
11527bfaa0f0STobias Hieta        {
1153f49ccca8SMark de Wever            "name": "__cpp_lib_saturation_arithmetic",
1154f49ccca8SMark de Wever            "values": {"c++26": 202311},  # P0543R3 Saturation arithmetic
115503c19e91SHristo Hristov            "headers": ["numeric"],
1156f49ccca8SMark de Wever        },
1157f49ccca8SMark de Wever        {
1158ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_scoped_lock",
1159ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201703},
1160ff1b6f9fSArthur O'Dwyer            "headers": ["mutex"],
1161c6f3b7bcSNikolas Klauser            "test_suite_guard": "!defined(_LIBCPP_VERSION) || _LIBCPP_HAS_THREADS",
1162c6f3b7bcSNikolas Klauser            "libcxx_guard": "_LIBCPP_HAS_THREADS",
11637bfaa0f0STobias Hieta        },
11647bfaa0f0STobias Hieta        {
1165466df171SArthur O'Dwyer            "name": "__cpp_lib_semaphore",
1166466df171SArthur O'Dwyer            "values": {"c++20": 201907},
1167466df171SArthur O'Dwyer            "headers": ["semaphore"],
1168c6f3b7bcSNikolas Klauser            "test_suite_guard": "!defined(_LIBCPP_VERSION) || (_LIBCPP_HAS_THREADS && _LIBCPP_AVAILABILITY_HAS_SYNC)",
1169c6f3b7bcSNikolas Klauser            "libcxx_guard": "_LIBCPP_HAS_THREADS && _LIBCPP_AVAILABILITY_HAS_SYNC",
11707bfaa0f0STobias Hieta        },
11717bfaa0f0STobias Hieta        {
11722dadf8d7SMark de Wever            "name": "__cpp_lib_senders",
11732dadf8d7SMark de Wever            "values": {"c++26": 202406},  # P2300R10 std::execution
11742dadf8d7SMark de Wever            "headers": ["execution"],
11752dadf8d7SMark de Wever            "unimplemented": True,
11762dadf8d7SMark de Wever        },
11772dadf8d7SMark de Wever        {
1178ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_shared_mutex",
1179ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201505},
1180ff1b6f9fSArthur O'Dwyer            "headers": ["shared_mutex"],
1181c6f3b7bcSNikolas Klauser            "test_suite_guard": "_LIBCPP_HAS_THREADS",
1182c6f3b7bcSNikolas Klauser            "libcxx_guard": "_LIBCPP_HAS_THREADS",
11837bfaa0f0STobias Hieta        },
11847bfaa0f0STobias Hieta        {
1185ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_shared_ptr_arrays",
1186e27a122bSLouis Dionne            "values": {"c++17": 201611, "c++20": 201707},
1187ff1b6f9fSArthur O'Dwyer            "headers": ["memory"],
11887bfaa0f0STobias Hieta        },
11897bfaa0f0STobias Hieta        {
1190ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_shared_ptr_weak_type",
1191ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201606},
1192ff1b6f9fSArthur O'Dwyer            "headers": ["memory"],
11937bfaa0f0STobias Hieta        },
11947bfaa0f0STobias Hieta        {
1195ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_shared_timed_mutex",
1196ff1b6f9fSArthur O'Dwyer            "values": {"c++14": 201402},
1197ff1b6f9fSArthur O'Dwyer            "headers": ["shared_mutex"],
1198c6f3b7bcSNikolas Klauser            "test_suite_guard": "_LIBCPP_HAS_THREADS",
1199c6f3b7bcSNikolas Klauser            "libcxx_guard": "_LIBCPP_HAS_THREADS",
12007bfaa0f0STobias Hieta        },
12017bfaa0f0STobias Hieta        {
1202466df171SArthur O'Dwyer            "name": "__cpp_lib_shift",
1203466df171SArthur O'Dwyer            "values": {"c++20": 201806},
1204466df171SArthur O'Dwyer            "headers": ["algorithm"],
12057bfaa0f0STobias Hieta        },
12067bfaa0f0STobias Hieta        {
1207466df171SArthur O'Dwyer            "name": "__cpp_lib_smart_ptr_for_overwrite",
1208466df171SArthur O'Dwyer            "values": {"c++20": 202002},
1209466df171SArthur O'Dwyer            "headers": ["memory"],
12107bfaa0f0STobias Hieta        },
12117bfaa0f0STobias Hieta        {
12123f05d044SMark de Wever            "name": "__cpp_lib_smart_ptr_owner_equality",
1213f49ccca8SMark de Wever            "values": {
1214f49ccca8SMark de Wever                "c++26": 202306  # P1901R2 Enabling the Use of weak_ptr as Keys in Unordered Associative Containers
1215f49ccca8SMark de Wever            },
12163f05d044SMark de Wever            "headers": ["memory"],
12173f05d044SMark de Wever            "unimplemented": True,
12183f05d044SMark de Wever        },
12193f05d044SMark de Wever        {
1220466df171SArthur O'Dwyer            "name": "__cpp_lib_source_location",
1221466df171SArthur O'Dwyer            "values": {"c++20": 201907},
1222466df171SArthur O'Dwyer            "headers": ["source_location"],
12237bfaa0f0STobias Hieta        },
12247bfaa0f0STobias Hieta        {
1225ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_span",
1226f49ccca8SMark de Wever            "values": {
1227f49ccca8SMark de Wever                "c++20": 202002,
1228f49ccca8SMark de Wever                # "c++26": 202311,  # P2821R5 span.at()
1229f49ccca8SMark de Wever                #          202311   # P2833R2 Freestanding Library: inout expected span
1230f49ccca8SMark de Wever            },
1231ff1b6f9fSArthur O'Dwyer            "headers": ["span"],
12327bfaa0f0STobias Hieta        },
12337bfaa0f0STobias Hieta        {
1234a72ab9c1SHristo Hristov            "name": "__cpp_lib_span_at",
1235a72ab9c1SHristo Hristov            "values": {"c++26": 202311},  # P2821R3 span.at()
1236a72ab9c1SHristo Hristov            "headers": ["span"],
1237a72ab9c1SHristo Hristov        },
1238a72ab9c1SHristo Hristov        {
1239f49ccca8SMark de Wever            "name": "__cpp_lib_span_initializer_list",
1240f49ccca8SMark de Wever            "values": {"c++26": 202311},  # P2447R6 std::span over an initializer list
1241f49ccca8SMark de Wever            "headers": ["span"],
1242f49ccca8SMark de Wever        },
1243f49ccca8SMark de Wever        {
1244855d7bedSArthur O'Dwyer            "name": "__cpp_lib_spanstream",
124571400505SMark de Wever            "values": {"c++23": 202106},
1246855d7bedSArthur O'Dwyer            "headers": ["spanstream"],
1247855d7bedSArthur O'Dwyer            "unimplemented": True,
12487bfaa0f0STobias Hieta        },
12497bfaa0f0STobias Hieta        {
1250466df171SArthur O'Dwyer            "name": "__cpp_lib_ssize",
1251466df171SArthur O'Dwyer            "values": {"c++20": 201902},
1252466df171SArthur O'Dwyer            "headers": ["iterator"],
12537bfaa0f0STobias Hieta        },
12547bfaa0f0STobias Hieta        {
12553f05d044SMark de Wever            "name": "__cpp_lib_sstream_from_string_view",
1256f49ccca8SMark de Wever            "values": {
1257f49ccca8SMark de Wever                "c++26": 202306  # P2495R3 Interfacing stringstreams with string_view
1258f49ccca8SMark de Wever            },
12593f05d044SMark de Wever            "headers": ["sstream"],
12603f05d044SMark de Wever        },
12613f05d044SMark de Wever        {
126295729f95SMarek Kurdej            "name": "__cpp_lib_stacktrace",
126371400505SMark de Wever            "values": {"c++23": 202011},
126495729f95SMarek Kurdej            "headers": ["stacktrace"],
126595729f95SMarek Kurdej            "unimplemented": True,
12667bfaa0f0STobias Hieta        },
12677bfaa0f0STobias Hieta        {
1268466df171SArthur O'Dwyer            "name": "__cpp_lib_starts_ends_with",
1269466df171SArthur O'Dwyer            "values": {"c++20": 201711},
1270466df171SArthur O'Dwyer            "headers": ["string", "string_view"],
12717bfaa0f0STobias Hieta        },
12727bfaa0f0STobias Hieta        {
127395729f95SMarek Kurdej            "name": "__cpp_lib_stdatomic_h",
127471400505SMark de Wever            "values": {"c++23": 202011},
127595729f95SMarek Kurdej            "headers": ["stdatomic.h"],
12767bfaa0f0STobias Hieta        },
12777bfaa0f0STobias Hieta        {
127895729f95SMarek Kurdej            "name": "__cpp_lib_string_contains",
127971400505SMark de Wever            "values": {"c++23": 202011},
128095729f95SMarek Kurdej            "headers": ["string", "string_view"],
12817bfaa0f0STobias Hieta        },
12827bfaa0f0STobias Hieta        {
1283bec50db2SNikolas Klauser            "name": "__cpp_lib_string_resize_and_overwrite",
128471400505SMark de Wever            "values": {"c++23": 202110},
1285bec50db2SNikolas Klauser            "headers": ["string"],
12867bfaa0f0STobias Hieta        },
12877bfaa0f0STobias Hieta        {
1288ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_string_udls",
1289ff1b6f9fSArthur O'Dwyer            "values": {"c++14": 201304},
1290ff1b6f9fSArthur O'Dwyer            "headers": ["string"],
12917bfaa0f0STobias Hieta        },
12927bfaa0f0STobias Hieta        {
1293ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_string_view",
1294b699a9baSLouis Dionne            "values": {
1295b699a9baSLouis Dionne                "c++17": 201606,
1296b699a9baSLouis Dionne                "c++20": 201803,
12974a19be5dSHristo Hristov                "c++26": 202403,  # P2591R5: Concatenation of strings and string views
1298b699a9baSLouis Dionne            },
1299ff1b6f9fSArthur O'Dwyer            "headers": ["string", "string_view"],
13007bfaa0f0STobias Hieta        },
13017bfaa0f0STobias Hieta        {
13023f05d044SMark de Wever            "name": "__cpp_lib_submdspan",
1303b699a9baSLouis Dionne            "values": {
1304b699a9baSLouis Dionne                "c++26": 202306, # P2630R4: submdspan
1305b699a9baSLouis Dionne                # "c++26": 202403, # P2642R6: Padded mdspan layouts
1306b699a9baSLouis Dionne            },
13073f05d044SMark de Wever            "headers": ["mdspan"],
13083f05d044SMark de Wever            "unimplemented": True,
13093f05d044SMark de Wever        },
13103f05d044SMark de Wever        {
1311466df171SArthur O'Dwyer            "name": "__cpp_lib_syncbuf",
1312466df171SArthur O'Dwyer            "values": {"c++20": 201803},
1313466df171SArthur O'Dwyer            "headers": ["syncstream"],
131424e70e39SNikolas Klauser            "test_suite_guard": "!defined(_LIBCPP_VERSION) || _LIBCPP_HAS_EXPERIMENTAL_SYNCSTREAM",
131524e70e39SNikolas Klauser            "libcxx_guard": "_LIBCPP_HAS_EXPERIMENTAL_SYNCSTREAM",
13167bfaa0f0STobias Hieta        },
13177bfaa0f0STobias Hieta        {
13183f05d044SMark de Wever            "name": "__cpp_lib_text_encoding",
1319f49ccca8SMark de Wever            "values": {
1320f49ccca8SMark de Wever                "c++26": 202306  # P1885R12 Naming Text Encodings to Demystify Them
1321f49ccca8SMark de Wever            },
13223f05d044SMark de Wever            "headers": ["text_encoding"],
13233f05d044SMark de Wever            "unimplemented": True,
13243f05d044SMark de Wever        },
13253f05d044SMark de Wever        {
1326ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_three_way_comparison",
13273ce6f68eSMark de Wever            "values": {"c++20": 201907},
1328ff1b6f9fSArthur O'Dwyer            "headers": ["compare"],
13297bfaa0f0STobias Hieta        },
13307bfaa0f0STobias Hieta        {
1331466df171SArthur O'Dwyer            "name": "__cpp_lib_to_address",
1332466df171SArthur O'Dwyer            "values": {"c++20": 201711},
1333466df171SArthur O'Dwyer            "headers": ["memory"],
13347bfaa0f0STobias Hieta        },
13357bfaa0f0STobias Hieta        {
1336ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_to_array",
1337ff1b6f9fSArthur O'Dwyer            "values": {"c++20": 201907},
1338ff1b6f9fSArthur O'Dwyer            "headers": ["array"],
13397bfaa0f0STobias Hieta        },
13407bfaa0f0STobias Hieta        {
1341ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_to_chars",
13423f05d044SMark de Wever            "values": {
13433f05d044SMark de Wever                "c++17": 201611,
134492ac3600SMark de Wever                "c++26": 202306,  # P2497R0 Testing for success or failure of <charconv> functions
13453f05d044SMark de Wever            },
1346e0f58444SLouis Dionne            "headers": ["charconv"],
1347ff1b6f9fSArthur O'Dwyer            "unimplemented": True,
13487bfaa0f0STobias Hieta        },
13497bfaa0f0STobias Hieta        {
13503f05d044SMark de Wever            "name": "__cpp_lib_to_string",
1351a4bef0caSStephan T. Lavavej            "values": {"c++26": 202306},  # P2587R3 to_string or not to_string
13523f05d044SMark de Wever            "headers": ["string"],
13533f05d044SMark de Wever            "unimplemented": True,
13543f05d044SMark de Wever        },
13553f05d044SMark de Wever        {
135643e42141SMarek Kurdej            "name": "__cpp_lib_to_underlying",
135771400505SMark de Wever            "values": {"c++23": 202102},
135843e42141SMarek Kurdej            "headers": ["utility"],
13597bfaa0f0STobias Hieta        },
13607bfaa0f0STobias Hieta        {
1361ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_transformation_trait_aliases",
1362ff1b6f9fSArthur O'Dwyer            "values": {"c++14": 201304},
1363ff1b6f9fSArthur O'Dwyer            "headers": ["type_traits"],
13647bfaa0f0STobias Hieta        },
13657bfaa0f0STobias Hieta        {
1366ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_transparent_operators",
1367ff1b6f9fSArthur O'Dwyer            "values": {"c++14": 201210, "c++17": 201510},
1368466df171SArthur O'Dwyer            "headers": ["functional", "memory"],
13697bfaa0f0STobias Hieta        },
13707bfaa0f0STobias Hieta        {
1371ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_tuple_element_t",
1372ff1b6f9fSArthur O'Dwyer            "values": {"c++14": 201402},
1373ff1b6f9fSArthur O'Dwyer            "headers": ["tuple"],
13747bfaa0f0STobias Hieta        },
13757bfaa0f0STobias Hieta        {
1376f49ccca8SMark de Wever            "name": "__cpp_lib_tuple_like",
1377f49ccca8SMark de Wever            "values": {
1378f49ccca8SMark de Wever                "c++23": 202207,  # P2165R4 Compatibility between tuple, pair and tuple-like objects
13792ea5d167SHristo Hristov                "c++26": 202311,  # P2819R2 Add tuple protocol to complex (implemented)
1380f49ccca8SMark de Wever            },
1381f49ccca8SMark de Wever            "headers": ["map", "tuple", "unordered_map", "utility"],
1382f49ccca8SMark de Wever            "unimplemented": True,
1383f49ccca8SMark de Wever        },
1384f49ccca8SMark de Wever        {
1385ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_tuples_by_type",
1386ff1b6f9fSArthur O'Dwyer            "values": {"c++14": 201304},
1387ff1b6f9fSArthur O'Dwyer            "headers": ["tuple", "utility"],
13887bfaa0f0STobias Hieta        },
13897bfaa0f0STobias Hieta        {
1390855d7bedSArthur O'Dwyer            "name": "__cpp_lib_type_identity",
1391855d7bedSArthur O'Dwyer            "values": {"c++20": 201806},
1392855d7bedSArthur O'Dwyer            "headers": ["type_traits"],
13937bfaa0f0STobias Hieta        },
13947bfaa0f0STobias Hieta        {
1395ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_type_trait_variable_templates",
1396ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201510},
1397ff1b6f9fSArthur O'Dwyer            "headers": ["type_traits"],
13987bfaa0f0STobias Hieta        },
13997bfaa0f0STobias Hieta        {
1400ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_uncaught_exceptions",
1401ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201411},
1402ff1b6f9fSArthur O'Dwyer            "headers": ["exception"],
14037bfaa0f0STobias Hieta        },
14047bfaa0f0STobias Hieta        {
1405ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_unordered_map_try_emplace",
1406ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201411},
1407ff1b6f9fSArthur O'Dwyer            "headers": ["unordered_map"],
14087bfaa0f0STobias Hieta        },
14097bfaa0f0STobias Hieta        {
1410a5b4479dSNikolas Klauser            "name": "__cpp_lib_unreachable",
141171400505SMark de Wever            "values": {"c++23": 202202},
1412a5b4479dSNikolas Klauser            "headers": ["utility"],
14137bfaa0f0STobias Hieta        },
14147bfaa0f0STobias Hieta        {
1415466df171SArthur O'Dwyer            "name": "__cpp_lib_unwrap_ref",
1416466df171SArthur O'Dwyer            "values": {"c++20": 201811},
1417466df171SArthur O'Dwyer            "headers": ["functional"],
14187bfaa0f0STobias Hieta        },
14197bfaa0f0STobias Hieta        {
1420ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_variant",
14213412bc76SHristo Hristov            "values": {
14223412bc76SHristo Hristov                "c++17": 202102,  # std::visit for classes derived from std::variant
1423cae351f3SA. Jiang                "c++20": 202106,  # P2231R1 Missing constexpr in std::optional and std::variant
1424cae351f3SA. Jiang                "c++26": 202306,  # P2637R3 Member visit
14253412bc76SHristo Hristov            },
1426ff1b6f9fSArthur O'Dwyer            "headers": ["variant"],
14277bfaa0f0STobias Hieta        },
14287bfaa0f0STobias Hieta        {
1429ff1b6f9fSArthur O'Dwyer            "name": "__cpp_lib_void_t",
1430ff1b6f9fSArthur O'Dwyer            "values": {"c++17": 201411},
1431ff1b6f9fSArthur O'Dwyer            "headers": ["type_traits"],
14327bfaa0f0STobias Hieta        },
14337bfaa0f0STobias Hieta    ]
14347bfaa0f0STobias Hieta]
1435ff1b6f9fSArthur O'Dwyer
1436ff1b6f9fSArthur O'Dwyerassert feature_test_macros == sorted(feature_test_macros, key=lambda tc: tc["name"])
1437b699a9baSLouis Dionnefor tc in feature_test_macros:
1438b699a9baSLouis Dionne    assert tc["headers"] == sorted(tc["headers"]), tc
1439b699a9baSLouis Dionne    assert ("libcxx_guard" in tc) == ("test_suite_guard" in tc), tc
1440b699a9baSLouis Dionne    valid_keys = ["name", "values", "headers", "libcxx_guard", "test_suite_guard", "unimplemented"]
1441b699a9baSLouis Dionne    assert all(key in valid_keys for key in tc.keys()), tc
1442508da415SEric Fiselier
1443c2279b26SLouis Dionne# Map from each header to the Lit annotations that should be used for
1444c2279b26SLouis Dionne# tests that include that header.
1445c2279b26SLouis Dionne#
1446e1ce3dabSLouis Dionne# For example, when threads are not supported, any test that includes
1447e1ce3dabSLouis Dionne# <thread> should be marked as UNSUPPORTED, because including <thread>
1448e1ce3dabSLouis Dionne# is a hard error in that case.
1449c2279b26SLouis Dionnelit_markup = {
1450a7f9895cSLouis Dionne    "barrier": ["UNSUPPORTED: no-threads"],
1451a7f9895cSLouis Dionne    "filesystem": ["UNSUPPORTED: no-filesystem"],
14523f05d044SMark de Wever    "fstream": ["UNSUPPORTED: no-localization"],
1453a7f9895cSLouis Dionne    "iomanip": ["UNSUPPORTED: no-localization"],
1454a7f9895cSLouis Dionne    "ios": ["UNSUPPORTED: no-localization"],
1455a7f9895cSLouis Dionne    "iostream": ["UNSUPPORTED: no-localization"],
1456a7f9895cSLouis Dionne    "istream": ["UNSUPPORTED: no-localization"],
1457a7f9895cSLouis Dionne    "latch": ["UNSUPPORTED: no-threads"],
1458a7f9895cSLouis Dionne    "locale": ["UNSUPPORTED: no-localization"],
1459a7f9895cSLouis Dionne    "mutex": ["UNSUPPORTED: no-threads"],
1460a7f9895cSLouis Dionne    "ostream": ["UNSUPPORTED: no-localization"],
14611cf970dbSKonstantin Varlamov    "print": ["UNSUPPORTED: no-filesystem"],
1462a7f9895cSLouis Dionne    "regex": ["UNSUPPORTED: no-localization"],
1463a7f9895cSLouis Dionne    "semaphore": ["UNSUPPORTED: no-threads"],
1464a7f9895cSLouis Dionne    "shared_mutex": ["UNSUPPORTED: no-threads"],
14653f05d044SMark de Wever    "sstream": ["UNSUPPORTED: no-localization"],
14667cc72a0aSMark de Wever    "syncstream": ["UNSUPPORTED: no-localization"],
1467a7f9895cSLouis Dionne    "stdatomic.h": ["UNSUPPORTED: no-threads"],
1468b77e50e6SHui    "stop_token": ["UNSUPPORTED: no-threads"],
1469a7f9895cSLouis Dionne    "thread": ["UNSUPPORTED: no-threads"],
1470c2279b26SLouis Dionne}
1471c2279b26SLouis Dionne
14727bfaa0f0STobias Hieta
1473508da415SEric Fiselierdef get_std_dialects():
14747bfaa0f0STobias Hieta    std_dialects = ["c++14", "c++17", "c++20", "c++23", "c++26"]
1475508da415SEric Fiselier    return list(std_dialects)
1476508da415SEric Fiselier
14777bfaa0f0STobias Hieta
1478508da415SEric Fiselierdef get_first_std(d):
1479508da415SEric Fiselier    for s in get_std_dialects():
1480508da415SEric Fiselier        if s in d.keys():
1481508da415SEric Fiselier            return s
1482508da415SEric Fiselier    return None
1483508da415SEric Fiselier
14847bfaa0f0STobias Hieta
1485508da415SEric Fiselierdef get_last_std(d):
1486508da415SEric Fiselier    rev_dialects = get_std_dialects()
1487508da415SEric Fiselier    rev_dialects.reverse()
1488508da415SEric Fiselier    for s in rev_dialects:
1489508da415SEric Fiselier        if s in d.keys():
1490508da415SEric Fiselier            return s
1491508da415SEric Fiselier    return None
1492508da415SEric Fiselier
14937bfaa0f0STobias Hieta
1494508da415SEric Fiselierdef get_std_before(d, std):
1495508da415SEric Fiselier    std_dialects = get_std_dialects()
1496508da415SEric Fiselier    candidates = std_dialects[0 : std_dialects.index(std)]
1497508da415SEric Fiselier    candidates.reverse()
1498508da415SEric Fiselier    for cand in candidates:
1499508da415SEric Fiselier        if cand in d.keys():
1500508da415SEric Fiselier            return cand
1501508da415SEric Fiselier    return None
1502508da415SEric Fiselier
15037bfaa0f0STobias Hieta
1504508da415SEric Fiselierdef get_value_before(d, std):
1505508da415SEric Fiselier    new_std = get_std_before(d, std)
1506508da415SEric Fiselier    if new_std is None:
1507508da415SEric Fiselier        return None
1508508da415SEric Fiselier    return d[new_std]
1509508da415SEric Fiselier
15107bfaa0f0STobias Hieta
1511508da415SEric Fiselierdef get_for_std(d, std):
1512508da415SEric Fiselier    # This catches the C++11 case for which there should be no defined feature
1513508da415SEric Fiselier    # test macros.
1514508da415SEric Fiselier    std_dialects = get_std_dialects()
1515508da415SEric Fiselier    if std not in std_dialects:
1516508da415SEric Fiselier        return None
1517508da415SEric Fiselier    # Find the value for the newest C++ dialect between C++14 and std
1518508da415SEric Fiselier    std_list = list(std_dialects[0 : std_dialects.index(std) + 1])
1519508da415SEric Fiselier    std_list.reverse()
1520508da415SEric Fiselier    for s in std_list:
1521508da415SEric Fiselier        if s in d.keys():
1522508da415SEric Fiselier            return d[s]
1523508da415SEric Fiselier    return None
1524508da415SEric Fiselier
15257bfaa0f0STobias Hieta
15262776be43SWim Lefleredef get_std_number(std):
15277bfaa0f0STobias Hieta    return std.replace("c++", "")
15287bfaa0f0STobias Hieta
1529508da415SEric Fiselier
1530508da415SEric Fiselier"""
1531508da415SEric Fiselier  Functions to produce the <version> header
1532508da415SEric Fiselier"""
1533508da415SEric Fiselier
15347bfaa0f0STobias Hieta
1535508da415SEric Fiselierdef produce_macros_definition_for_std(std):
1536508da415SEric Fiselier    result = ""
1537eb37d354SArthur O'Dwyer    indent = 55
1538508da415SEric Fiselier    for tc in feature_test_macros:
1539508da415SEric Fiselier        if std not in tc["values"]:
1540508da415SEric Fiselier            continue
1541508da415SEric Fiselier        inner_indent = 1
15427bfaa0f0STobias Hieta        if "test_suite_guard" in tc.keys():
1543c2c68a59SMark de Wever            result += "# if %s\n" % tc["libcxx_guard"]
1544508da415SEric Fiselier            inner_indent += 2
1545508da415SEric Fiselier        if get_value_before(tc["values"], std) is not None:
15467bfaa0f0STobias Hieta            assert "test_suite_guard" not in tc.keys()
1547508da415SEric Fiselier            result += "# undef  %s\n" % tc["name"]
1548508da415SEric Fiselier        line = "#%sdefine %s" % ((" " * inner_indent), tc["name"])
1549508da415SEric Fiselier        line += " " * (indent - len(line))
1550508da415SEric Fiselier        line += " %sL" % tc["values"][std]
15517bfaa0f0STobias Hieta        if "unimplemented" in tc.keys():
1552508da415SEric Fiselier            line = "// " + line
1553508da415SEric Fiselier        result += line
1554508da415SEric Fiselier        result += "\n"
15557bfaa0f0STobias Hieta        if "test_suite_guard" in tc.keys():
1556508da415SEric Fiselier            result += "# endif\n"
15572776be43SWim Leflere    return result.strip()
15582776be43SWim Leflere
15597bfaa0f0STobias Hieta
15602776be43SWim Lefleredef produce_macros_definitions():
15614f15267dSNikolas Klauser    macro_definition_template = """#if _LIBCPP_STD_VER >= {std_number}
15622776be43SWim Leflere{macro_definition}
15632776be43SWim Leflere#endif"""
15642776be43SWim Leflere
15652776be43SWim Leflere    macros_definitions = []
15662776be43SWim Leflere    for std in get_std_dialects():
15672776be43SWim Leflere        macros_definitions.append(
15687bfaa0f0STobias Hieta            macro_definition_template.format(
15697bfaa0f0STobias Hieta                std_number=get_std_number(std),
15707bfaa0f0STobias Hieta                macro_definition=produce_macros_definition_for_std(std),
15717bfaa0f0STobias Hieta            )
15727bfaa0f0STobias Hieta        )
15732776be43SWim Leflere
15747bfaa0f0STobias Hieta    return "\n\n".join(macros_definitions)
15757bfaa0f0STobias Hieta
1576508da415SEric Fiselier
1577508da415SEric Fiselierdef chunks(l, n):
1578508da415SEric Fiselier    """Yield successive n-sized chunks from l."""
1579508da415SEric Fiselier    for i in range(0, len(l), n):
1580508da415SEric Fiselier        yield l[i : i + n]
1581508da415SEric Fiselier
15827bfaa0f0STobias Hieta
1583508da415SEric Fiselierdef produce_version_synopsis():
1584508da415SEric Fiselier    indent = 56
1585508da415SEric Fiselier    header_indent = 56 + len("20XXYYL ")
1586508da415SEric Fiselier    result = ""
15877bfaa0f0STobias Hieta
1588508da415SEric Fiselier    def indent_to(s, val):
1589508da415SEric Fiselier        if len(s) >= val:
1590508da415SEric Fiselier            return s
1591508da415SEric Fiselier        s += " " * (val - len(s))
1592508da415SEric Fiselier        return s
15937bfaa0f0STobias Hieta
1594508da415SEric Fiselier    line = indent_to("Macro name", indent) + "Value"
1595508da415SEric Fiselier    line = indent_to(line, header_indent) + "Headers"
1596508da415SEric Fiselier    result += line + "\n"
1597508da415SEric Fiselier    for tc in feature_test_macros:
1598508da415SEric Fiselier        prev_defined_std = get_last_std(tc["values"])
15997bfaa0f0STobias Hieta        line = "{name: <{indent}}{value}L ".format(
16007bfaa0f0STobias Hieta            name=tc["name"], indent=indent, value=tc["values"][prev_defined_std]
16017bfaa0f0STobias Hieta        )
1602508da415SEric Fiselier        headers = list(tc["headers"])
1603508da415SEric Fiselier        headers.remove("version")
1604508da415SEric Fiselier        for chunk in chunks(headers, 3):
1605508da415SEric Fiselier            line = indent_to(line, header_indent)
16067bfaa0f0STobias Hieta            chunk = ["<%s>" % header for header in chunk]
16077bfaa0f0STobias Hieta            line += " ".join(chunk)
1608508da415SEric Fiselier            result += line
1609508da415SEric Fiselier            result += "\n"
1610508da415SEric Fiselier            line = ""
1611508da415SEric Fiselier        while True:
1612508da415SEric Fiselier            prev_defined_std = get_std_before(tc["values"], prev_defined_std)
1613508da415SEric Fiselier            if prev_defined_std is None:
1614508da415SEric Fiselier                break
16157bfaa0f0STobias Hieta            result += "%s%sL // %s\n" % (
16167bfaa0f0STobias Hieta                indent_to("", indent),
16177bfaa0f0STobias Hieta                tc["values"][prev_defined_std],
16187bfaa0f0STobias Hieta                prev_defined_std.replace("c++", "C++"),
16197bfaa0f0STobias Hieta            )
1620508da415SEric Fiselier    return result
1621508da415SEric Fiselier
1622508da415SEric Fiselier
1623508da415SEric Fiselierdef produce_version_header():
16242a6b99d5SArthur O'Dwyer    template = """// -*- C++ -*-
16252e934531SLouis Dionne//===----------------------------------------------------------------------===//
1626508da415SEric Fiselier//
1627508da415SEric Fiselier// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
1628508da415SEric Fiselier// See https://llvm.org/LICENSE.txt for license information.
1629508da415SEric Fiselier// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
1630508da415SEric Fiselier//
1631508da415SEric Fiselier//===----------------------------------------------------------------------===//
1632508da415SEric Fiselier
1633508da415SEric Fiselier#ifndef _LIBCPP_VERSIONH
1634508da415SEric Fiselier#define _LIBCPP_VERSIONH
1635508da415SEric Fiselier
1636508da415SEric Fiselier/*
1637508da415SEric Fiselier  version synopsis
1638508da415SEric Fiselier
1639508da415SEric Fiselier{synopsis}
1640508da415SEric Fiselier
1641508da415SEric Fiselier*/
1642508da415SEric Fiselier
1643b9a2658aSNikolas Klauser#if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
1644b9a2658aSNikolas Klauser#  include <__cxx03/version>
1645b9a2658aSNikolas Klauser#else
1646508da415SEric Fiselier#  include <__config>
1647508da415SEric Fiselier
1648508da415SEric Fiselier#  if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1649508da415SEric Fiselier#    pragma GCC system_header
1650508da415SEric Fiselier#  endif
1651508da415SEric Fiselier
1652bcb5a124SMarek Kurdej// clang-format off
1653bcb5a124SMarek Kurdej
16542776be43SWim Leflere{cxx_macros}
165595729f95SMarek Kurdej
1656b9a2658aSNikolas Klauser#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
1657b9a2658aSNikolas Klauser
1658bcb5a124SMarek Kurdej// clang-format on
1659bcb5a124SMarek Kurdej
1660508da415SEric Fiselier#endif // _LIBCPP_VERSIONH
16612a6b99d5SArthur O'Dwyer"""
1662647fb6b3SLouis Dionne
1663647fb6b3SLouis Dionne    version_str = template.format(
1664508da415SEric Fiselier        synopsis=produce_version_synopsis().strip(),
16657bfaa0f0STobias Hieta        cxx_macros=produce_macros_definitions(),
16667bfaa0f0STobias Hieta    )
16677bfaa0f0STobias Hieta    version_header_path = os.path.join(include_path, "version")
16687bfaa0f0STobias Hieta    with open(version_header_path, "w", newline="\n") as f:
1669647fb6b3SLouis Dionne        f.write(version_str)
1670647fb6b3SLouis Dionne
1671647fb6b3SLouis Dionne
1672508da415SEric Fiselier"""
1673508da415SEric Fiselier    Functions to produce test files
1674508da415SEric Fiselier"""
1675508da415SEric Fiselier
1676508da415SEric Fiseliertest_types = {
1677508da415SEric Fiselier    "undefined": """
1678508da415SEric Fiselier# ifdef {name}
1679508da415SEric Fiselier#   error "{name} should not be defined before {std_first}"
1680508da415SEric Fiselier# endif
1681508da415SEric Fiselier""",
1682c2c68a59SMark de Wever    "test_suite_guard": """
1683c2c68a59SMark de Wever# if {test_suite_guard}
1684508da415SEric Fiselier#   ifndef {name}
1685508da415SEric Fiselier#     error "{name} should be defined in {std}"
1686508da415SEric Fiselier#   endif
1687508da415SEric Fiselier#   if {name} != {value}
1688508da415SEric Fiselier#     error "{name} should have the value {value} in {std}"
1689508da415SEric Fiselier#   endif
1690508da415SEric Fiselier# else
1691508da415SEric Fiselier#   ifdef {name}
1692a72f6b03SMark de Wever#     error "{name} should not be defined when the requirement '{test_suite_guard}' is not met!"
1693508da415SEric Fiselier#   endif
1694508da415SEric Fiselier# endif
1695508da415SEric Fiselier""",
1696508da415SEric Fiselier    "unimplemented": """
1697508da415SEric Fiselier# if !defined(_LIBCPP_VERSION)
1698508da415SEric Fiselier#   ifndef {name}
1699508da415SEric Fiselier#     error "{name} should be defined in {std}"
1700508da415SEric Fiselier#   endif
1701508da415SEric Fiselier#   if {name} != {value}
1702508da415SEric Fiselier#     error "{name} should have the value {value} in {std}"
1703508da415SEric Fiselier#   endif
1704508da415SEric Fiselier# else // _LIBCPP_VERSION
1705508da415SEric Fiselier#   ifdef {name}
1706508da415SEric Fiselier#     error "{name} should not be defined because it is unimplemented in libc++!"
1707508da415SEric Fiselier#   endif
1708508da415SEric Fiselier# endif
1709508da415SEric Fiselier""",
1710508da415SEric Fiselier    "defined": """
1711508da415SEric Fiselier# ifndef {name}
1712508da415SEric Fiselier#   error "{name} should be defined in {std}"
1713508da415SEric Fiselier# endif
1714508da415SEric Fiselier# if {name} != {value}
1715508da415SEric Fiselier#   error "{name} should have the value {value} in {std}"
1716508da415SEric Fiselier# endif
17177bfaa0f0STobias Hieta""",
1718508da415SEric Fiselier}
1719508da415SEric Fiselier
17207bfaa0f0STobias Hieta
1721508da415SEric Fiselierdef generate_std_test(test_list, std):
1722508da415SEric Fiselier    result = ""
1723508da415SEric Fiselier    for tc in test_list:
1724508da415SEric Fiselier        val = get_for_std(tc["values"], std)
1725508da415SEric Fiselier        if val is not None:
1726508da415SEric Fiselier            val = "%sL" % val
1727508da415SEric Fiselier        if val is None:
17287bfaa0f0STobias Hieta            result += test_types["undefined"].format(
17297bfaa0f0STobias Hieta                name=tc["name"], std_first=get_first_std(tc["values"])
17307bfaa0f0STobias Hieta            )
17317bfaa0f0STobias Hieta        elif "unimplemented" in tc.keys():
17327bfaa0f0STobias Hieta            result += test_types["unimplemented"].format(
17337bfaa0f0STobias Hieta                name=tc["name"], value=val, std=std
17347bfaa0f0STobias Hieta            )
1735c2c68a59SMark de Wever        elif "test_suite_guard" in tc.keys():
17367bfaa0f0STobias Hieta            result += test_types["test_suite_guard"].format(
17377bfaa0f0STobias Hieta                name=tc["name"],
17387bfaa0f0STobias Hieta                value=val,
17397bfaa0f0STobias Hieta                std=std,
17407bfaa0f0STobias Hieta                test_suite_guard=tc["test_suite_guard"],
17417bfaa0f0STobias Hieta            )
1742508da415SEric Fiselier        else:
1743508da415SEric Fiselier            result += test_types["defined"].format(name=tc["name"], value=val, std=std)
17442776be43SWim Leflere    return result.strip()
17452776be43SWim Leflere
17467bfaa0f0STobias Hieta
17472776be43SWim Lefleredef generate_std_tests(test_list):
17482776be43SWim Leflere    std_tests_template = """#if TEST_STD_VER < {first_std_number}
17492776be43SWim Leflere
17502776be43SWim Leflere{pre_std_test}
17512776be43SWim Leflere
17522776be43SWim Leflere{other_std_tests}
17532776be43SWim Leflere
17542776be43SWim Leflere#elif TEST_STD_VER > {penultimate_std_number}
17552776be43SWim Leflere
17562776be43SWim Leflere{last_std_test}
17572776be43SWim Leflere
17582776be43SWim Leflere#endif // TEST_STD_VER > {penultimate_std_number}"""
17592776be43SWim Leflere
17602776be43SWim Leflere    std_dialects = get_std_dialects()
17612776be43SWim Leflere
17622776be43SWim Leflere    other_std_tests = []
17632776be43SWim Leflere    for std in std_dialects[:-1]:
17647bfaa0f0STobias Hieta        other_std_tests.append("#elif TEST_STD_VER == " + get_std_number(std))
17652776be43SWim Leflere        other_std_tests.append(generate_std_test(test_list, std))
17662776be43SWim Leflere
17677bfaa0f0STobias Hieta    std_tests = std_tests_template.format(
17687bfaa0f0STobias Hieta        first_std_number=get_std_number(std_dialects[0]),
17697bfaa0f0STobias Hieta        pre_std_test=generate_std_test(test_list, "c++11"),
17707bfaa0f0STobias Hieta        other_std_tests="\n\n".join(other_std_tests),
17712776be43SWim Leflere        penultimate_std_number=get_std_number(std_dialects[-2]),
17727bfaa0f0STobias Hieta        last_std_test=generate_std_test(test_list, std_dialects[-1]),
17737bfaa0f0STobias Hieta    )
17742776be43SWim Leflere
17752776be43SWim Leflere    return std_tests
1776508da415SEric Fiselier
17777bfaa0f0STobias Hieta
1778508da415SEric Fiselierdef generate_synopsis(test_list):
1779508da415SEric Fiselier    max_name_len = max([len(tc["name"]) for tc in test_list])
1780508da415SEric Fiselier    indent = max_name_len + 8
17817bfaa0f0STobias Hieta
1782508da415SEric Fiselier    def mk_line(prefix, suffix):
17837bfaa0f0STobias Hieta        return "{prefix: <{max_len}}{suffix}\n".format(
17847bfaa0f0STobias Hieta            prefix=prefix, suffix=suffix, max_len=indent
17857bfaa0f0STobias Hieta        )
17867bfaa0f0STobias Hieta
1787508da415SEric Fiselier    result = ""
1788508da415SEric Fiselier    result += mk_line("/*  Constant", "Value")
1789508da415SEric Fiselier    for tc in test_list:
1790508da415SEric Fiselier        prefix = "    %s" % tc["name"]
1791508da415SEric Fiselier        for std in [s for s in get_std_dialects() if s in tc["values"].keys()]:
17927bfaa0f0STobias Hieta            result += mk_line(
17937bfaa0f0STobias Hieta                prefix, "%sL [%s]" % (tc["values"][std], std.replace("c++", "C++"))
17947bfaa0f0STobias Hieta            )
1795508da415SEric Fiselier            prefix = ""
1796508da415SEric Fiselier    result += "*/"
1797508da415SEric Fiselier    return result
1798508da415SEric Fiselier
17997bfaa0f0STobias Hieta
1800508da415SEric Fiselierdef produce_tests():
1801508da415SEric Fiselier    headers = set([h for tc in feature_test_macros for h in tc["headers"]])
1802508da415SEric Fiselier    for h in headers:
1803508da415SEric Fiselier        test_list = [tc for tc in feature_test_macros if h in tc["headers"]]
1804508da415SEric Fiselier        if not has_header(h):
1805508da415SEric Fiselier            for tc in test_list:
18067bfaa0f0STobias Hieta                assert "unimplemented" in tc.keys()
1807508da415SEric Fiselier            continue
18087bfaa0f0STobias Hieta        markup = "\n".join("// " + tag for tag in lit_markup.get(h, []))
18097bfaa0f0STobias Hieta        test_body = """//===----------------------------------------------------------------------===//
1810508da415SEric Fiselier//
1811508da415SEric Fiselier// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
1812508da415SEric Fiselier// See https://llvm.org/LICENSE.txt for license information.
1813508da415SEric Fiselier// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
1814508da415SEric Fiselier//
1815508da415SEric Fiselier//===----------------------------------------------------------------------===//
1816508da415SEric Fiselier//
1817508da415SEric Fiselier// WARNING: This test was generated by {script_name}
1818508da415SEric Fiselier// and should not be edited manually.
181930a7d430SMarek Kurdej//
182030a7d430SMarek Kurdej// clang-format off
1821c2279b26SLouis Dionne{markup}
1822508da415SEric Fiselier// <{header}>
1823508da415SEric Fiselier
1824508da415SEric Fiselier// Test the feature test macros defined by <{header}>
1825508da415SEric Fiselier
1826508da415SEric Fiselier{synopsis}
1827508da415SEric Fiselier
1828508da415SEric Fiselier#include <{header}>
1829508da415SEric Fiselier#include "test_macros.h"
1830508da415SEric Fiselier
18312776be43SWim Leflere{cxx_tests}
1832508da415SEric Fiselier
18337bfaa0f0STobias Hieta""".format(
18347bfaa0f0STobias Hieta            script_name=script_name,
1835508da415SEric Fiselier            header=h,
18367bfaa0f0STobias Hieta            markup=("\n{}\n".format(markup) if markup else ""),
1837508da415SEric Fiselier            synopsis=generate_synopsis(test_list),
18387bfaa0f0STobias Hieta            cxx_tests=generate_std_tests(test_list),
18397bfaa0f0STobias Hieta        )
18402c6217f2SLouis Dionne        test_name = "{header}.version.compile.pass.cpp".format(header=h)
1841508da415SEric Fiselier        out_path = os.path.join(macro_test_path, test_name)
18427bfaa0f0STobias Hieta        with open(out_path, "w", newline="\n") as f:
1843508da415SEric Fiselier            f.write(test_body)
1844508da415SEric Fiselier
18457bfaa0f0STobias Hieta
1846508da415SEric Fiselier"""
1847508da415SEric Fiselier    Produce documentation for the feature test macros
1848508da415SEric Fiselier"""
1849508da415SEric Fiselier
18507bfaa0f0STobias Hieta
1851508da415SEric Fiselierdef make_widths(grid):
1852508da415SEric Fiselier    widths = []
1853508da415SEric Fiselier    for i in range(0, len(grid[0])):
18547bfaa0f0STobias Hieta        cell_width = 2 + max(
18557bfaa0f0STobias Hieta            reduce(lambda x, y: x + y, [[len(row[i])] for row in grid], [])
18567bfaa0f0STobias Hieta        )
1857508da415SEric Fiselier        widths += [cell_width]
1858508da415SEric Fiselier    return widths
1859508da415SEric Fiselier
18607bfaa0f0STobias Hieta
1861508da415SEric Fiselierdef create_table(grid, indent):
18627bfaa0f0STobias Hieta    indent_str = " " * indent
1863508da415SEric Fiselier    col_widths = make_widths(grid)
18640451ed96SLouis Dionne    result = [indent_str + add_divider(col_widths, 2)]
1865508da415SEric Fiselier    header_flag = 2
1866fd02a468SLouis Dionne    for row_i in range(0, len(grid)):
1867508da415SEric Fiselier        row = grid[row_i]
18687bfaa0f0STobias Hieta        line = indent_str + " ".join(
18697bfaa0f0STobias Hieta            [pad_cell(row[i], col_widths[i]) for i in range(0, len(row))]
18707bfaa0f0STobias Hieta        )
18710451ed96SLouis Dionne        result.append(line.rstrip())
1872508da415SEric Fiselier        if row_i == len(grid) - 1:
1873508da415SEric Fiselier            header_flag = 2
18747bfaa0f0STobias Hieta        if row[0].startswith("**"):
187500c97cbcSMark de Wever            header_flag += 1
187600c97cbcSMark de Wever        separator = indent_str + add_divider(col_widths, header_flag)
18770451ed96SLouis Dionne        result.append(separator.rstrip())
1878508da415SEric Fiselier        header_flag = 0
18797bfaa0f0STobias Hieta    return "\n".join(result)
18807bfaa0f0STobias Hieta
1881508da415SEric Fiselier
1882508da415SEric Fiselierdef add_divider(widths, header_flag):
188300c97cbcSMark de Wever    if header_flag == 3:
18847bfaa0f0STobias Hieta        return "=".join(["=" * w for w in widths])
1885508da415SEric Fiselier    if header_flag == 2:
18867bfaa0f0STobias Hieta        return " ".join(["=" * w for w in widths])
1887508da415SEric Fiselier    if header_flag == 1:
18887bfaa0f0STobias Hieta        return "-".join(["-" * w for w in widths])
1889508da415SEric Fiselier    else:
18907bfaa0f0STobias Hieta        return " ".join(["-" * w for w in widths])
18917bfaa0f0STobias Hieta
1892508da415SEric Fiselier
1893508da415SEric Fiselierdef pad_cell(s, length, left_align=True):
18947bfaa0f0STobias Hieta    padding = (length - len(s)) * " "
1895508da415SEric Fiselier    return s + padding
1896508da415SEric Fiselier
1897508da415SEric Fiselier
1898508da415SEric Fiselierdef get_status_table():
1899508da415SEric Fiselier    table = [["Macro Name", "Value"]]
1900508da415SEric Fiselier    for std in get_std_dialects():
1901508da415SEric Fiselier        table += [["**" + std.replace("c++", "C++") + "**", ""]]
1902508da415SEric Fiselier        for tc in feature_test_macros:
1903508da415SEric Fiselier            if std not in tc["values"].keys():
1904508da415SEric Fiselier                continue
1905508da415SEric Fiselier            value = "``%sL``" % tc["values"][std]
19067bfaa0f0STobias Hieta            if "unimplemented" in tc.keys():
19077bfaa0f0STobias Hieta                value = "*unimplemented*"
1908508da415SEric Fiselier            table += [["``%s``" % tc["name"], value]]
1909508da415SEric Fiselier    return table
1910508da415SEric Fiselier
19117bfaa0f0STobias Hieta
1912508da415SEric Fiselierdef produce_docs():
1913508da415SEric Fiselier    doc_str = """.. _FeatureTestMacroTable:
1914508da415SEric Fiselier
1915508da415SEric Fiselier==========================
1916508da415SEric FiselierFeature Test Macro Support
1917508da415SEric Fiselier==========================
1918508da415SEric Fiselier
1919508da415SEric Fiselier.. contents::
1920508da415SEric Fiselier   :local:
1921508da415SEric Fiselier
1922508da415SEric FiselierOverview
1923508da415SEric Fiselier========
1924508da415SEric Fiselier
1925508da415SEric FiselierThis file documents the feature test macros currently supported by libc++.
1926508da415SEric Fiselier
1927508da415SEric Fiselier.. _feature-status:
1928508da415SEric Fiselier
1929508da415SEric FiselierStatus
1930508da415SEric Fiselier======
1931508da415SEric Fiselier
1932508da415SEric Fiselier.. table:: Current Status
1933508da415SEric Fiselier    :name: feature-status-table
1934508da415SEric Fiselier    :widths: auto
1935508da415SEric Fiselier
1936508da415SEric Fiselier{status_tables}
1937508da415SEric Fiselier
19387bfaa0f0STobias Hieta""".format(
19397bfaa0f0STobias Hieta        status_tables=create_table(get_status_table(), 4)
19407bfaa0f0STobias Hieta    )
1941508da415SEric Fiselier
19427bfaa0f0STobias Hieta    table_doc_path = os.path.join(docs_path, "FeatureTestMacroTable.rst")
19437bfaa0f0STobias Hieta    with open(table_doc_path, "w", newline="\n") as f:
1944508da415SEric Fiselier        f.write(doc_str)
1945508da415SEric Fiselier
19467bfaa0f0STobias Hieta
1947d2dd4b55SMark de Weverdef get_ftms(
1948d2dd4b55SMark de Wever    data, std_dialects: List[str], use_implemented_status: bool
1949d2dd4b55SMark de Wever) -> Dict[str, Dict[str, Any]]:
1950d2dd4b55SMark de Wever    """Impementation for FeatureTestMacros.(standard|implemented)_ftms()."""
1951d2dd4b55SMark de Wever    result = dict()
1952d2dd4b55SMark de Wever    for feature in data:
1953d2dd4b55SMark de Wever        last = None
1954d2dd4b55SMark de Wever        entry = dict()
1955d2dd4b55SMark de Wever        implemented = True
1956d2dd4b55SMark de Wever        for std in std_dialects:
1957d2dd4b55SMark de Wever            if std not in feature["values"].keys():
1958d2dd4b55SMark de Wever                if last == None:
1959d2dd4b55SMark de Wever                    continue
1960d2dd4b55SMark de Wever                else:
1961d2dd4b55SMark de Wever                    entry[std] = last
1962d2dd4b55SMark de Wever            else:
1963d2dd4b55SMark de Wever                if implemented:
1964d2dd4b55SMark de Wever                    values = feature["values"][std]
1965d2dd4b55SMark de Wever                    assert len(values) > 0, f"{feature['name']}[{std}] has no entries"
1966d2dd4b55SMark de Wever                    for value in values:
1967d2dd4b55SMark de Wever                        papers = list(values[value])
1968d2dd4b55SMark de Wever                        assert (
1969d2dd4b55SMark de Wever                            len(papers) > 0
1970d2dd4b55SMark de Wever                        ), f"{feature['name']}[{std}][{value}] has no entries"
1971d2dd4b55SMark de Wever                        for paper in papers:
1972d2dd4b55SMark de Wever                            if use_implemented_status and not paper["implemented"]:
1973d2dd4b55SMark de Wever                                implemented = False
1974d2dd4b55SMark de Wever                                break
1975d2dd4b55SMark de Wever                        if implemented:
1976d2dd4b55SMark de Wever                            last = f"{value}L"
1977d2dd4b55SMark de Wever                        else:
1978d2dd4b55SMark de Wever                            break
1979d2dd4b55SMark de Wever
1980d2dd4b55SMark de Wever                entry[std] = last
1981d2dd4b55SMark de Wever        result[feature["name"]] = entry
1982d2dd4b55SMark de Wever
1983d2dd4b55SMark de Wever    return result
1984d2dd4b55SMark de Wever
1985d2dd4b55SMark de Wever
1986879640cbSMark de Weverdef generate_version_header_dialect_block(data: Dict[str, Any]) -> str:
1987879640cbSMark de Wever    """Generates the contents of the version header for a dialect.
1988879640cbSMark de Wever
1989879640cbSMark de Wever    This generates the contents of a
1990879640cbSMark de Wever      #if  _LIBCPP_STD_VER >= XY
1991879640cbSMark de Wever      #endif // _LIBCPP_STD_VER >= XY
1992879640cbSMark de Wever    block.
1993879640cbSMark de Wever    """
1994879640cbSMark de Wever    result = ""
1995879640cbSMark de Wever    for element in data:
1996879640cbSMark de Wever        for ftm, entry in element.items():
1997879640cbSMark de Wever            if not entry["implemented"]:
1998879640cbSMark de Wever                # When a FTM is not implemented don't add the guards
1999879640cbSMark de Wever                # or undefine the (possibly) defined macro.
2000879640cbSMark de Wever                result += f'// define {ftm} {entry["value"]}\n'
2001879640cbSMark de Wever            else:
2002879640cbSMark de Wever                need_undef = entry["need_undef"]
2003879640cbSMark de Wever                if entry["condition"]:
2004879640cbSMark de Wever                    result += f'#  if {entry["condition"]}\n'
2005879640cbSMark de Wever                    if entry["need_undef"]:
2006879640cbSMark de Wever                        result += f"#    undef {ftm}\n"
2007879640cbSMark de Wever                    result += f'#    define {ftm} {entry["value"]}\n'
2008879640cbSMark de Wever                    result += f"#  endif\n"
2009879640cbSMark de Wever                else:
2010879640cbSMark de Wever                    if entry["need_undef"]:
2011879640cbSMark de Wever                        result += f"#  undef {ftm}\n"
2012879640cbSMark de Wever                    result += f'#  define {ftm} {entry["value"]}\n'
2013879640cbSMark de Wever
2014879640cbSMark de Wever    return result
2015879640cbSMark de Wever
2016879640cbSMark de Wever
2017879640cbSMark de Weverdef generate_version_header_implementation(data: Dict[str, Dict[str, Any]]) -> str:
2018879640cbSMark de Wever    """Generates the body of the version header."""
2019879640cbSMark de Wever
2020879640cbSMark de Wever    template = """#if _LIBCPP_STD_VER >= {dialect}
2021879640cbSMark de Wever{feature_test_macros}#endif // _LIBCPP_STD_VER >= {dialect}"""
2022879640cbSMark de Wever
2023879640cbSMark de Wever    result = []
2024879640cbSMark de Wever    for std, ftms in data.items():
2025879640cbSMark de Wever        result.append(
2026879640cbSMark de Wever            template.format(
2027879640cbSMark de Wever                dialect=std,
2028879640cbSMark de Wever                feature_test_macros=generate_version_header_dialect_block(ftms),
2029879640cbSMark de Wever            )
2030879640cbSMark de Wever        )
2031879640cbSMark de Wever
2032879640cbSMark de Wever    return "\n\n".join(result)
2033879640cbSMark de Wever
2034879640cbSMark de Wever
2035d2dd4b55SMark de Weverclass FeatureTestMacros:
2036d2dd4b55SMark de Wever    """Provides all feature-test macro (FTM) output components.
2037d2dd4b55SMark de Wever
2038d2dd4b55SMark de Wever    The class has several generators to use the feature-test macros in libc++:
2039d2dd4b55SMark de Wever    - FTM status page
2040d2dd4b55SMark de Wever    - The version header and its tests
2041d2dd4b55SMark de Wever
2042d2dd4b55SMark de Wever    This class is not intended to duplicate
2043d2dd4b55SMark de Wever    https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations#library-feature-test-macros
2044d2dd4b55SMark de Wever    SD-FeatureTest: Feature-Test Macros and Policies
2045d2dd4b55SMark de Wever
2046d2dd4b55SMark de Wever    Historically libc++ did not list all papers affecting a FTM, the new data
2047d2dd4b55SMark de Wever    structure is able to do that. However there is no intention to add the
2048d2dd4b55SMark de Wever    historical data. After papers have been implemented this information can be
2049d2dd4b55SMark de Wever    removed. For example, __cpp_lib_format's value 201907 requires 3 papers,
2050d2dd4b55SMark de Wever    once implemented it can be reduced to 1 paper and remove the paper number
2051d2dd4b55SMark de Wever    and title. This would reduce the size of the data.
2052d2dd4b55SMark de Wever
2053d2dd4b55SMark de Wever    The input data is stored in the following JSON format:
2054d2dd4b55SMark de Wever    [ # A list with multiple feature-test macro entries.
2055d2dd4b55SMark de Wever      {
2056d2dd4b55SMark de Wever        # required
2057d2dd4b55SMark de Wever        # The name of the feature test macro. These names should be unique and
2058d2dd4b55SMark de Wever        # sorted in the list.
2059d2dd4b55SMark de Wever        "name": "__cpp_lib_any",
2060d2dd4b55SMark de Wever
2061d2dd4b55SMark de Wever        # required
2062d2dd4b55SMark de Wever        # A map with the value of the FTM based on the language standard. Only
2063d2dd4b55SMark de Wever        # the versions in which the value of the FTM changes are listed. For
2064d2dd4b55SMark de Wever        # example, this macro's value does not change in C++20 so it does not
2065d2dd4b55SMark de Wever        # list C++20. If it changes in C++26, it will have entries for C++17 and
2066d2dd4b55SMark de Wever        # C++26.
2067d2dd4b55SMark de Wever        "values": {
2068d2dd4b55SMark de Wever
2069d2dd4b55SMark de Wever          # required
2070d2dd4b55SMark de Wever          # The language standard, also named dialect in this class.
2071d2dd4b55SMark de Wever          "c++17": {
2072d2dd4b55SMark de Wever
2073d2dd4b55SMark de Wever            # required
2074d2dd4b55SMark de Wever            # The value of the feature test macro. This contains an array with
2075d2dd4b55SMark de Wever            # one or more papers that need to be implemented before this value
2076d2dd4b55SMark de Wever            # is considered implemented.
2077d2dd4b55SMark de Wever            "201606": [
2078d2dd4b55SMark de Wever              {
2079d2dd4b55SMark de Wever                # optional
2080d2dd4b55SMark de Wever                # Contains the paper number that is part of the FTM version.
2081d2dd4b55SMark de Wever                "number": "P0220R1",
2082d2dd4b55SMark de Wever
2083d2dd4b55SMark de Wever                # optional
2084d2dd4b55SMark de Wever                # Contains the title of the paper that is part of the FTM
2085d2dd4b55SMark de Wever                # version.
2086d2dd4b55SMark de Wever                "title": "Adopt Library Fundamentals V1 TS Components for C++17"
2087d2dd4b55SMark de Wever
2088d2dd4b55SMark de Wever                # required
2089d2dd4b55SMark de Wever                # The implementation status of the paper.
2090d2dd4b55SMark de Wever                "implemented": true
2091d2dd4b55SMark de Wever              }
2092d2dd4b55SMark de Wever            ]
2093d2dd4b55SMark de Wever          }
2094d2dd4b55SMark de Wever        },
2095d2dd4b55SMark de Wever
2096d2dd4b55SMark de Wever        # required
2097d2dd4b55SMark de Wever        # A sorted list of headers that should provide the FTM. The header
2098d2dd4b55SMark de Wever        # <version> is automatically added to this list. This list could be
2099d2dd4b55SMark de Wever        # empty. For example, __cpp_lib_modules is only present in version.
2100d2dd4b55SMark de Wever        # Requiring the field makes it easier to detect accidental omission.
2101d2dd4b55SMark de Wever        "headers": [
2102d2dd4b55SMark de Wever          "any"
2103d2dd4b55SMark de Wever        ],
2104d2dd4b55SMark de Wever
2105d2dd4b55SMark de Wever        # optional, required when libcxx_guard is present
2106d2dd4b55SMark de Wever        # This field is used only to generate the unit tests for the
2107d2dd4b55SMark de Wever        # feature-test macros. It can't depend on macros defined in <__config>
2108d2dd4b55SMark de Wever        # because the `test/std/` parts of the test suite are intended to be
2109d2dd4b55SMark de Wever        # portable to any C++ standard library implementation, not just libc++.
2110d2dd4b55SMark de Wever        # It may depend on
2111d2dd4b55SMark de Wever        # * macros defined by the compiler itself, or
2112d2dd4b55SMark de Wever        # * macros generated by CMake.
2113d2dd4b55SMark de Wever        # In some cases we add also depend on macros defined in
2114d2dd4b55SMark de Wever        # <__availability>.
2115d2dd4b55SMark de Wever        "test_suite_guard": "!defined(_LIBCPP_VERSION) || _LIBCPP_AVAILABILITY_HAS_PMR"
2116d2dd4b55SMark de Wever
2117d2dd4b55SMark de Wever        # optional, required when test_suite_guard is present
2118d2dd4b55SMark de Wever        # This field is used only to guard the feature-test macro in
2119d2dd4b55SMark de Wever        # <version>. It may be the same as `test_suite_guard`, or it may
2120d2dd4b55SMark de Wever        # depend on macros defined in <__config>.
2121d2dd4b55SMark de Wever        "libcxx_guard": "_LIBCPP_AVAILABILITY_HAS_PMR"
2122d2dd4b55SMark de Wever      },
2123d2dd4b55SMark de Wever    ]
2124d2dd4b55SMark de Wever    """
2125d2dd4b55SMark de Wever
2126d2dd4b55SMark de Wever    # The JSON data structure.
2127d2dd4b55SMark de Wever    __data = None
2128d2dd4b55SMark de Wever
2129d2dd4b55SMark de Wever    def __init__(self, filename: str):
2130d2dd4b55SMark de Wever        """Initializes the class with the JSON data in the file 'filename'."""
2131c4a42f61SLouis Dionne        with open(filename) as f:
2132c4a42f61SLouis Dionne            self.__data = json.load(f)
2133d2dd4b55SMark de Wever
2134d2dd4b55SMark de Wever    @functools.cached_property
2135d2dd4b55SMark de Wever    def std_dialects(self) -> List[str]:
2136d2dd4b55SMark de Wever        """Returns the C++ dialects avaiable.
2137d2dd4b55SMark de Wever
2138d2dd4b55SMark de Wever        The available dialects are based on the 'c++xy' keys found the 'values'
2139d2dd4b55SMark de Wever        entries in '__data'. So when WG21 starts to feature-test macros for a
2140d2dd4b55SMark de Wever        future C++ Standard this dialect will automatically be available.
2141d2dd4b55SMark de Wever
2142d2dd4b55SMark de Wever        The return value is a sorted list with the C++ dialects used. Since FTM
2143d2dd4b55SMark de Wever        were added in C++14 the list will not contain C++03 or C++11.
2144d2dd4b55SMark de Wever        """
2145d2dd4b55SMark de Wever        dialects = set()
2146d2dd4b55SMark de Wever        for feature in self.__data:
2147d2dd4b55SMark de Wever            keys = feature["values"].keys()
2148d2dd4b55SMark de Wever            assert len(keys) > 0, "'values' is empty"
2149d2dd4b55SMark de Wever            dialects |= keys
2150d2dd4b55SMark de Wever
2151d2dd4b55SMark de Wever        return sorted(list(dialects))
2152d2dd4b55SMark de Wever
2153d2dd4b55SMark de Wever    @functools.cached_property
2154d2dd4b55SMark de Wever    def standard_ftms(self) -> Dict[str, Dict[str, Any]]:
2155d2dd4b55SMark de Wever        """Returns the FTM versions per dialect in the Standard.
2156d2dd4b55SMark de Wever
2157d2dd4b55SMark de Wever        This function does not use the 'implemented' flag. The output contains
2158d2dd4b55SMark de Wever        the versions used in the Standard. When a FTM in libc++ is not
2159d2dd4b55SMark de Wever        implemented according to the Standard to output may opt to show the
2160d2dd4b55SMark de Wever        expected value.
2161d2dd4b55SMark de Wever
2162d2dd4b55SMark de Wever        The result is a dict with the following content
2163d2dd4b55SMark de Wever        - key: Name of the feature test macro.
2164d2dd4b55SMark de Wever        - value: A dict with the following content:
2165d2dd4b55SMark de Wever          * key: The version of the C++ dialect.
2166d2dd4b55SMark de Wever          * value: The value of the feature-test macro.
2167d2dd4b55SMark de Wever        """
2168d2dd4b55SMark de Wever        return get_ftms(self.__data, self.std_dialects, False)
2169d2dd4b55SMark de Wever
2170d2dd4b55SMark de Wever    @functools.cached_property
2171d2dd4b55SMark de Wever    def implemented_ftms(self) -> Dict[str, Dict[str, Any]]:
2172d2dd4b55SMark de Wever        """Returns the FTM versions per dialect implemented in libc++.
2173d2dd4b55SMark de Wever
2174d2dd4b55SMark de Wever        Unlike `get_std_dialect_versions` this function uses the 'implemented'
2175d2dd4b55SMark de Wever        flag. This returns the actual implementation status in libc++.
2176d2dd4b55SMark de Wever
2177d2dd4b55SMark de Wever        The result is a dict with the following content
2178d2dd4b55SMark de Wever        - key: Name of the feature test macro.
2179d2dd4b55SMark de Wever        - value: A dict with the following content:
2180d2dd4b55SMark de Wever          * key: The version of the C++ dialect.
2181d2dd4b55SMark de Wever          * value: The value of the feature-test macro. When a feature-test
2182d2dd4b55SMark de Wever            macro is not implemented its value is None.
2183d2dd4b55SMark de Wever        """
2184d2dd4b55SMark de Wever
2185d2dd4b55SMark de Wever        return get_ftms(self.__data, self.std_dialects, True)
2186d2dd4b55SMark de Wever
2187879640cbSMark de Wever    @functools.cached_property
2188879640cbSMark de Wever    def ftm_metadata(self) -> Dict[str, Dict[str, Any]]:
2189879640cbSMark de Wever        """Returns the metadata of the FTMs defined in the Standard.
2190879640cbSMark de Wever
2191879640cbSMark de Wever        The metadata does not depend on the C++ dialect used.
2192879640cbSMark de Wever        The result is a dict with the following contents:
2193879640cbSMark de Wever        - key: Name of the feature test macro.
2194879640cbSMark de Wever        - value: A dict with the following content:
2195879640cbSMark de Wever          * headers: The list of headers that should provide the FTM
2196879640cbSMark de Wever          * test_suite_guard: The condition for testing the FTM in the test suite.
2197879640cbSMark de Wever          * test_suite_guard: The condition for testing the FTM in the version header.
2198879640cbSMark de Wever        """
2199879640cbSMark de Wever        result = dict()
2200879640cbSMark de Wever        for feature in self.__data:
2201879640cbSMark de Wever            entry = dict()
2202879640cbSMark de Wever            entry["headers"] = feature["headers"]
2203879640cbSMark de Wever            entry["test_suite_guard"] = feature.get("test_suite_guard", None)
2204879640cbSMark de Wever            entry["libcxx_guard"] = feature.get("libcxx_guard", None)
2205879640cbSMark de Wever            result[feature["name"]] = entry
2206879640cbSMark de Wever
2207879640cbSMark de Wever        return result
2208879640cbSMark de Wever
2209879640cbSMark de Wever    @property
2210879640cbSMark de Wever    def version_header_implementation(self) -> Dict[str, List[Dict[str, Any]]]:
2211879640cbSMark de Wever        """Generates the body of the version header."""
2212879640cbSMark de Wever        result = dict()
2213879640cbSMark de Wever        for std in self.std_dialects:
2214879640cbSMark de Wever            result[get_std_number(std)] = list()
2215879640cbSMark de Wever
2216879640cbSMark de Wever        for ftm, values in self.standard_ftms.items():
2217879640cbSMark de Wever            last_value = None
2218c4a42f61SLouis Dionne            last_entry = None
2219879640cbSMark de Wever            for std, value in values.items():
2220879640cbSMark de Wever                # When a newer Standard does not change the value of the macro
2221879640cbSMark de Wever                # there is no need to redefine it with the same value.
2222879640cbSMark de Wever                if last_value and value == last_value:
2223879640cbSMark de Wever                    continue
2224879640cbSMark de Wever                last_value = value
2225879640cbSMark de Wever
2226879640cbSMark de Wever                entry = dict()
2227879640cbSMark de Wever                entry["value"] = value
2228c4a42f61SLouis Dionne                entry["implemented"] = self.implemented_ftms[ftm][std] == self.standard_ftms[ftm][std]
2229c4a42f61SLouis Dionne                entry["need_undef"] = last_entry is not None and last_entry["implemented"] and entry["implemented"]
2230879640cbSMark de Wever                entry["condition"] = self.ftm_metadata[ftm]["libcxx_guard"]
2231879640cbSMark de Wever
2232c4a42f61SLouis Dionne                last_entry = entry
2233879640cbSMark de Wever                result[get_std_number(std)].append(dict({ftm: entry}))
2234879640cbSMark de Wever
2235879640cbSMark de Wever        return result
2236879640cbSMark de Wever
2237879640cbSMark de Wever    @property
2238879640cbSMark de Wever    def version_header(self) -> str:
2239879640cbSMark de Wever        """Generates the version header."""
2240879640cbSMark de Wever        template = """// -*- C++ -*-
2241879640cbSMark de Wever//===----------------------------------------------------------------------===//
2242879640cbSMark de Wever//
2243879640cbSMark de Wever// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
2244879640cbSMark de Wever// See https://llvm.org/LICENSE.txt for license information.
2245879640cbSMark de Wever// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2246879640cbSMark de Wever//
2247879640cbSMark de Wever//===----------------------------------------------------------------------===//
2248879640cbSMark de Wever
22497b2d592aSLouis Dionne#ifndef _LIBCPP_VERSIONH
22507b2d592aSLouis Dionne#define _LIBCPP_VERSIONH
2251879640cbSMark de Wever
2252879640cbSMark de Wever#include <__config>
2253879640cbSMark de Wever
2254879640cbSMark de Wever#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
2255879640cbSMark de Wever#  pragma GCC system_header
2256879640cbSMark de Wever#endif
2257879640cbSMark de Wever
2258879640cbSMark de Wever{feature_test_macros}
2259879640cbSMark de Wever
22607b2d592aSLouis Dionne#endif // _LIBCPP_VERSIONH
2261879640cbSMark de Wever"""
2262879640cbSMark de Wever        return template.format(
2263879640cbSMark de Wever            feature_test_macros=generate_version_header_implementation(
2264879640cbSMark de Wever                self.version_header_implementation
2265879640cbSMark de Wever            )
2266879640cbSMark de Wever        )
2267879640cbSMark de Wever
2268d2dd4b55SMark de Wever
2269508da415SEric Fiselierdef main():
2270647fb6b3SLouis Dionne    produce_version_header()
2271508da415SEric Fiselier    produce_tests()
2272508da415SEric Fiselier    produce_docs()
2273508da415SEric Fiselier
2274879640cbSMark de Wever    # Example how to use the new version header generation function to generate
2275879640cbSMark de Wever    # the file.
2276879640cbSMark de Wever    if False:
2277879640cbSMark de Wever        ftm = FeatureTestMacros(
2278879640cbSMark de Wever            os.path.join(
2279879640cbSMark de Wever                source_root, "test", "libcxx", "feature_test_macro", "test_data.json"
2280879640cbSMark de Wever            )
2281879640cbSMark de Wever        )
2282879640cbSMark de Wever        version_header_path = os.path.join(include_path, "version")
2283879640cbSMark de Wever        with open(version_header_path, "w", newline="\n") as f:
2284879640cbSMark de Wever            f.write(ftm.version_header)
2285879640cbSMark de Wever
2286508da415SEric Fiselier
22877bfaa0f0STobias Hietaif __name__ == "__main__":
2288508da415SEric Fiselier    main()
2289