xref: /openbsd-src/gnu/llvm/libcxx/utils/generate_feature_test_macro_components.py (revision 4bdff4bed0e3d54e55670334c7d0077db4170f86)
146035553Spatrick#!/usr/bin/env python
246035553Spatrick
346035553Spatrickimport os
476d0caaeSpatrickfrom builtins import range
546035553Spatrickfrom functools import reduce
646035553Spatrick
746035553Spatrickdef get_libcxx_paths():
846035553Spatrick  utils_path = os.path.dirname(os.path.abspath(__file__))
946035553Spatrick  script_name = os.path.basename(__file__)
1046035553Spatrick  assert os.path.exists(utils_path)
1146035553Spatrick  src_root = os.path.dirname(utils_path)
1246035553Spatrick  include_path = os.path.join(src_root, 'include')
1346035553Spatrick  assert os.path.exists(include_path)
1446035553Spatrick  docs_path = os.path.join(src_root, 'docs')
1546035553Spatrick  assert os.path.exists(docs_path)
1646035553Spatrick  macro_test_path = os.path.join(src_root, 'test', 'std', 'language.support',
1746035553Spatrick                            'support.limits', 'support.limits.general')
1846035553Spatrick  assert os.path.exists(macro_test_path)
19*4bdff4beSrobert  assert os.path.exists(os.path.join(macro_test_path, 'version.version.compile.pass.cpp'))
2046035553Spatrick  return script_name, src_root, include_path, docs_path, macro_test_path
2146035553Spatrick
2246035553Spatrickscript_name, source_root, include_path, docs_path, macro_test_path = get_libcxx_paths()
2346035553Spatrick
2446035553Spatrickdef has_header(h):
2546035553Spatrick  h_path = os.path.join(include_path, h)
2646035553Spatrick  return os.path.exists(h_path)
2746035553Spatrick
2846035553Spatrickdef add_version_header(tc):
2946035553Spatrick  tc["headers"].append("version")
3046035553Spatrick  return tc
3146035553Spatrick
3276d0caaeSpatrick# ================  ============================================================
3376d0caaeSpatrick# Field             Description
3476d0caaeSpatrick# ================  ============================================================
3576d0caaeSpatrick# name              The name of the feature-test macro.
3676d0caaeSpatrick# values            A dict whose keys are C++ versions and whose values are the
3776d0caaeSpatrick#                   value of the feature-test macro for that C++ version.
3876d0caaeSpatrick#                   (TODO: This isn't a very clean model for feature-test
3976d0caaeSpatrick#                   macros affected by multiple papers.)
4076d0caaeSpatrick# headers           An array with the headers that should provide the
4176d0caaeSpatrick#                   feature-test macro.
4276d0caaeSpatrick# test_suite_guard  An optional string field. When this field is provided,
4376d0caaeSpatrick#                   `libcxx_guard` must also be provided. This field is used
4476d0caaeSpatrick#                   only to generate the unit tests for the feature-test macros.
4576d0caaeSpatrick#                   It can't depend on macros defined in <__config> because the
4676d0caaeSpatrick#                   `test/std/` parts of the test suite are intended to be
4776d0caaeSpatrick#                   portable to any C++ standard library implementation, not
4876d0caaeSpatrick#                   just libc++. It may depend on
4976d0caaeSpatrick#                    * macros defined by the compiler itself, or
5076d0caaeSpatrick#                    * macros generated by CMake.
5176d0caaeSpatrick#                   In some cases we add
5276d0caaeSpatrick#                   `&& !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM_...)`
5376d0caaeSpatrick#                   in order to make libc++ pass the tests on OSX; see D94983.
5476d0caaeSpatrick# libcxx_guard      An optional string field. When this field is provided,
5576d0caaeSpatrick#                   `test_suite_guard` must also be provided. This field is used
5676d0caaeSpatrick#                   only to guard the feature-test macro in <version>. It may
5776d0caaeSpatrick#                   be the same as `test_suite_guard`, or it may depend on
5876d0caaeSpatrick#                   macros defined in <__config>.
5976d0caaeSpatrick# unimplemented     An optional Boolean field with the value `True`. This field
6076d0caaeSpatrick#                   is only used when a feature isn't fully implemented. Once
6176d0caaeSpatrick#                   you've fully implemented the feature, you should remove
6276d0caaeSpatrick#                   this field.
6376d0caaeSpatrick# ================  ============================================================
6476d0caaeSpatrickfeature_test_macros = [ add_version_header(x) for x in [
6576d0caaeSpatrick  {
66*4bdff4beSrobert    "name": "__cpp_lib_adaptor_iterator_pair_constructor",
67*4bdff4beSrobert    "values": { "c++2b": 202106 },
68*4bdff4beSrobert    "headers": ["queue", "stack"],
69*4bdff4beSrobert  }, {
7076d0caaeSpatrick    "name": "__cpp_lib_addressof_constexpr",
7176d0caaeSpatrick    "values": { "c++17": 201603 },
7246035553Spatrick    "headers": ["memory"],
73*4bdff4beSrobert  }, {
74*4bdff4beSrobert    "name": "__cpp_lib_allocate_at_least",
75*4bdff4beSrobert    "values": { "c++2b": 202106 },
76*4bdff4beSrobert    "headers": ["memory"],
7776d0caaeSpatrick  }, {
7876d0caaeSpatrick    "name": "__cpp_lib_allocator_traits_is_always_equal",
7976d0caaeSpatrick    "values": { "c++17": 201411 },
8076d0caaeSpatrick    "headers": ["deque", "forward_list", "list", "map", "memory", "scoped_allocator", "set", "string", "unordered_map", "unordered_set", "vector"],
8176d0caaeSpatrick  }, {
8276d0caaeSpatrick    "name": "__cpp_lib_any",
8376d0caaeSpatrick    "values": { "c++17": 201606 },
8446035553Spatrick    "headers": ["any"],
8576d0caaeSpatrick  }, {
8676d0caaeSpatrick    "name": "__cpp_lib_apply",
8776d0caaeSpatrick    "values": { "c++17": 201603 },
8876d0caaeSpatrick    "headers": ["tuple"],
8976d0caaeSpatrick  }, {
9076d0caaeSpatrick    "name": "__cpp_lib_array_constexpr",
9176d0caaeSpatrick    "values": { "c++17": 201603, "c++20": 201811 },
9276d0caaeSpatrick    "headers": ["array", "iterator"],
9376d0caaeSpatrick  }, {
9476d0caaeSpatrick    "name": "__cpp_lib_as_const",
9576d0caaeSpatrick    "values": { "c++17": 201510 },
9676d0caaeSpatrick    "headers": ["utility"],
9776d0caaeSpatrick  }, {
98*4bdff4beSrobert    "name": "__cpp_lib_associative_heterogeneous_erasure",
99*4bdff4beSrobert    "values": { "c++2b": 202110 },
100*4bdff4beSrobert    "headers": ["map", "set", "unordered_map", "unordered_set"],
101*4bdff4beSrobert    "unimplemented": True,
102*4bdff4beSrobert  }, {
10376d0caaeSpatrick    "name": "__cpp_lib_assume_aligned",
10476d0caaeSpatrick    "values": { "c++20": 201811 },
10546035553Spatrick    "headers": ["memory"],
10676d0caaeSpatrick  }, {
10776d0caaeSpatrick    "name": "__cpp_lib_atomic_flag_test",
10876d0caaeSpatrick    "values": { "c++20": 201907 },
10976d0caaeSpatrick    "headers": ["atomic"],
11076d0caaeSpatrick  }, {
11176d0caaeSpatrick    "name": "__cpp_lib_atomic_float",
11276d0caaeSpatrick    "values": { "c++20": 201711 },
11376d0caaeSpatrick    "headers": ["atomic"],
11476d0caaeSpatrick    "unimplemented": True,
11576d0caaeSpatrick  }, {
11676d0caaeSpatrick    "name": "__cpp_lib_atomic_is_always_lock_free",
11776d0caaeSpatrick    "values": { "c++17": 201603 },
11876d0caaeSpatrick    "headers": ["atomic"],
11976d0caaeSpatrick  }, {
12076d0caaeSpatrick    "name": "__cpp_lib_atomic_lock_free_type_aliases",
12176d0caaeSpatrick    "values": { "c++20": 201907 },
12276d0caaeSpatrick    "headers": ["atomic"],
12376d0caaeSpatrick  }, {
12476d0caaeSpatrick    "name": "__cpp_lib_atomic_ref",
12576d0caaeSpatrick    "values": { "c++20": 201806 },
12676d0caaeSpatrick    "headers": ["atomic"],
12776d0caaeSpatrick    "unimplemented": True,
12876d0caaeSpatrick  }, {
12976d0caaeSpatrick    "name": "__cpp_lib_atomic_shared_ptr",
13076d0caaeSpatrick    "values": { "c++20": 201711 },
13176d0caaeSpatrick    "headers": ["atomic"],
13276d0caaeSpatrick    "unimplemented": True,
13376d0caaeSpatrick  }, {
13476d0caaeSpatrick    "name": "__cpp_lib_atomic_value_initialization",
13576d0caaeSpatrick    "values": { "c++20": 201911 },
13676d0caaeSpatrick    "headers": ["atomic", "memory"],
13776d0caaeSpatrick  }, {
13876d0caaeSpatrick    "name": "__cpp_lib_atomic_wait",
13976d0caaeSpatrick    "values": { "c++20": 201907 },
14076d0caaeSpatrick    "headers": ["atomic"],
141*4bdff4beSrobert    "test_suite_guard": "!defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_atomic_wait)",
142*4bdff4beSrobert    "libcxx_guard": "!defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_atomic_wait)",
14376d0caaeSpatrick  }, {
14476d0caaeSpatrick    "name": "__cpp_lib_barrier",
14576d0caaeSpatrick    "values": { "c++20": 201907 },
14676d0caaeSpatrick    "headers": ["barrier"],
14776d0caaeSpatrick    "test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_barrier)",
14876d0caaeSpatrick    "libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_barrier)",
14976d0caaeSpatrick  }, {
150*4bdff4beSrobert    "name": "__cpp_lib_bind_back",
151*4bdff4beSrobert    "values": { "c++2b": 202202 },
152*4bdff4beSrobert    "headers": ["functional"],
153*4bdff4beSrobert    "unimplemented": True,
154*4bdff4beSrobert  }, {
15576d0caaeSpatrick    "name": "__cpp_lib_bind_front",
15676d0caaeSpatrick    "values": { "c++20": 201907 },
15776d0caaeSpatrick    "headers": ["functional"],
15876d0caaeSpatrick  }, {
15976d0caaeSpatrick    "name": "__cpp_lib_bit_cast",
16076d0caaeSpatrick    "values": { "c++20": 201806 },
16176d0caaeSpatrick    "headers": ["bit"],
16276d0caaeSpatrick  }, {
16376d0caaeSpatrick    "name": "__cpp_lib_bitops",
16476d0caaeSpatrick    "values": { "c++20": 201907 },
16576d0caaeSpatrick    "headers": ["bit"],
16676d0caaeSpatrick    "unimplemented": True,
16776d0caaeSpatrick  }, {
16876d0caaeSpatrick    "name": "__cpp_lib_bool_constant",
16976d0caaeSpatrick    "values": { "c++17": 201505 },
17076d0caaeSpatrick    "headers": ["type_traits"],
17176d0caaeSpatrick  }, {
17276d0caaeSpatrick    "name": "__cpp_lib_bounded_array_traits",
17376d0caaeSpatrick    "values": { "c++20": 201902 },
17476d0caaeSpatrick    "headers": ["type_traits"],
17576d0caaeSpatrick  }, {
17676d0caaeSpatrick    "name": "__cpp_lib_boyer_moore_searcher",
17776d0caaeSpatrick    "values": { "c++17": 201603 },
17876d0caaeSpatrick    "headers": ["functional"],
17976d0caaeSpatrick  }, {
18076d0caaeSpatrick    "name": "__cpp_lib_byte",
18176d0caaeSpatrick    "values": { "c++17": 201603 },
18276d0caaeSpatrick    "headers": ["cstddef"],
18376d0caaeSpatrick  }, {
184*4bdff4beSrobert    "name": "__cpp_lib_byteswap",
185*4bdff4beSrobert    "values": { "c++2b": 202110 },
186*4bdff4beSrobert    "headers": ["bit"],
187*4bdff4beSrobert  }, {
18876d0caaeSpatrick    "name": "__cpp_lib_char8_t",
189*4bdff4beSrobert    "values": { "c++20": 201907 },
19076d0caaeSpatrick    "headers": ["atomic", "filesystem", "istream", "limits", "locale", "ostream", "string", "string_view"],
19176d0caaeSpatrick    "test_suite_guard": "defined(__cpp_char8_t)",
19276d0caaeSpatrick    "libcxx_guard": "!defined(_LIBCPP_HAS_NO_CHAR8_T)",
19376d0caaeSpatrick  }, {
19476d0caaeSpatrick    "name": "__cpp_lib_chrono",
19576d0caaeSpatrick    "values": { "c++17": 201611 },
19676d0caaeSpatrick    "headers": ["chrono"],
19776d0caaeSpatrick  }, {
19876d0caaeSpatrick    "name": "__cpp_lib_chrono_udls",
19976d0caaeSpatrick    "values": { "c++14": 201304 },
20076d0caaeSpatrick    "headers": ["chrono"],
20176d0caaeSpatrick  }, {
20276d0caaeSpatrick    "name": "__cpp_lib_clamp",
20376d0caaeSpatrick    "values": { "c++17": 201603 },
20476d0caaeSpatrick    "headers": ["algorithm"],
20576d0caaeSpatrick  }, {
20676d0caaeSpatrick    "name": "__cpp_lib_complex_udls",
20776d0caaeSpatrick    "values": { "c++14": 201309 },
20876d0caaeSpatrick    "headers": ["complex"],
20976d0caaeSpatrick  }, {
21076d0caaeSpatrick    "name": "__cpp_lib_concepts",
21176d0caaeSpatrick    "values": { "c++20": 202002 },
21276d0caaeSpatrick    "headers": ["concepts"],
21376d0caaeSpatrick  }, {
21476d0caaeSpatrick    "name": "__cpp_lib_constexpr_algorithms",
21576d0caaeSpatrick    "values": { "c++20": 201806 },
216*4bdff4beSrobert    "headers": ["algorithm", "utility"],
217*4bdff4beSrobert  }, {
218*4bdff4beSrobert    "name": "__cpp_lib_constexpr_bitset",
219*4bdff4beSrobert    "values": { "c++2b": 202207 },
220*4bdff4beSrobert    "headers": ["bitset"],
221*4bdff4beSrobert  }, {
222*4bdff4beSrobert    "name": "__cpp_lib_constexpr_charconv",
223*4bdff4beSrobert    "values": { "c++2b": 202207 },
224*4bdff4beSrobert    "headers": ["charconv"],
225*4bdff4beSrobert  }, {
226*4bdff4beSrobert    "name": "__cpp_lib_constexpr_cmath",
227*4bdff4beSrobert    "values": { "c++2b": 202202 },
228*4bdff4beSrobert    "headers": ["cmath", "cstdlib"],
229*4bdff4beSrobert    "unimplemented": True,
23076d0caaeSpatrick  }, {
23176d0caaeSpatrick    "name": "__cpp_lib_constexpr_complex",
23276d0caaeSpatrick    "values": { "c++20": 201711 },
23376d0caaeSpatrick    "headers": ["complex"],
23476d0caaeSpatrick  }, {
23576d0caaeSpatrick    "name": "__cpp_lib_constexpr_dynamic_alloc",
23676d0caaeSpatrick    "values": { "c++20": 201907 },
23776d0caaeSpatrick    "headers": ["memory"],
23876d0caaeSpatrick  }, {
23976d0caaeSpatrick    "name": "__cpp_lib_constexpr_functional",
24076d0caaeSpatrick    "values": { "c++20": 201907 },
24176d0caaeSpatrick    "headers": ["functional"],
24276d0caaeSpatrick  }, {
24376d0caaeSpatrick    "name": "__cpp_lib_constexpr_iterator",
24476d0caaeSpatrick    "values": { "c++20": 201811 },
24576d0caaeSpatrick    "headers": ["iterator"],
24676d0caaeSpatrick  }, {
24776d0caaeSpatrick    "name": "__cpp_lib_constexpr_memory",
248*4bdff4beSrobert    "values": { "c++20": 201811, "c++2b": 202202 },
24976d0caaeSpatrick    "headers": ["memory"],
25076d0caaeSpatrick  }, {
25176d0caaeSpatrick    "name": "__cpp_lib_constexpr_numeric",
25276d0caaeSpatrick    "values": { "c++20": 201911 },
25376d0caaeSpatrick    "headers": ["numeric"],
25476d0caaeSpatrick  }, {
25576d0caaeSpatrick    "name": "__cpp_lib_constexpr_string",
256*4bdff4beSrobert    "values": { "c++20": 201907 },
25776d0caaeSpatrick    "headers": ["string"],
25876d0caaeSpatrick  }, {
25976d0caaeSpatrick    "name": "__cpp_lib_constexpr_string_view",
26076d0caaeSpatrick    "values": { "c++20": 201811 },
26176d0caaeSpatrick    "headers": ["string_view"],
26276d0caaeSpatrick  }, {
26376d0caaeSpatrick    "name": "__cpp_lib_constexpr_tuple",
26476d0caaeSpatrick    "values": { "c++20": 201811 },
26576d0caaeSpatrick    "headers": ["tuple"],
26676d0caaeSpatrick  }, {
267*4bdff4beSrobert    "name": "__cpp_lib_constexpr_typeinfo",
268*4bdff4beSrobert    "values": { "c++2b": 202106 },
269*4bdff4beSrobert    "headers": ["typeinfo"],
270*4bdff4beSrobert    "unimplemented": True,
271*4bdff4beSrobert  }, {
27276d0caaeSpatrick    "name": "__cpp_lib_constexpr_utility",
27376d0caaeSpatrick    "values": { "c++20": 201811 },
27476d0caaeSpatrick    "headers": ["utility"],
27576d0caaeSpatrick  }, {
27676d0caaeSpatrick    "name": "__cpp_lib_constexpr_vector",
27776d0caaeSpatrick    "values": { "c++20": 201907 },
27876d0caaeSpatrick    "headers": ["vector"],
27976d0caaeSpatrick  }, {
28076d0caaeSpatrick    "name": "__cpp_lib_coroutine",
28176d0caaeSpatrick    "values": { "c++20": 201902 },
28276d0caaeSpatrick    "headers": ["coroutine"],
28376d0caaeSpatrick  }, {
28476d0caaeSpatrick    "name": "__cpp_lib_destroying_delete",
28576d0caaeSpatrick    "values": { "c++20": 201806 },
28676d0caaeSpatrick    "headers": ["new"],
28776d0caaeSpatrick    "test_suite_guard": "TEST_STD_VER > 17 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L",
28876d0caaeSpatrick    "libcxx_guard": "_LIBCPP_STD_VER > 17 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L",
28976d0caaeSpatrick  }, {
29076d0caaeSpatrick    "name": "__cpp_lib_enable_shared_from_this",
29176d0caaeSpatrick    "values": { "c++17": 201603 },
29276d0caaeSpatrick    "headers": ["memory"],
29376d0caaeSpatrick  }, {
29476d0caaeSpatrick    "name": "__cpp_lib_endian",
29576d0caaeSpatrick    "values": { "c++20": 201907 },
29676d0caaeSpatrick    "headers": ["bit"],
29776d0caaeSpatrick  }, {
29876d0caaeSpatrick    "name": "__cpp_lib_erase_if",
29976d0caaeSpatrick    "values": { "c++20": 202002 },
30076d0caaeSpatrick    "headers": ["deque", "forward_list", "list", "map", "set", "string", "unordered_map", "unordered_set", "vector"],
30176d0caaeSpatrick  }, {
30276d0caaeSpatrick    "name": "__cpp_lib_exchange_function",
30376d0caaeSpatrick    "values": { "c++14": 201304 },
30476d0caaeSpatrick    "headers": ["utility"],
30576d0caaeSpatrick  }, {
30676d0caaeSpatrick    "name": "__cpp_lib_execution",
30776d0caaeSpatrick    "values": { "c++17": 201603, "c++20": 201902 },
30876d0caaeSpatrick    "headers": ["execution"],
30976d0caaeSpatrick    "unimplemented": True,
31076d0caaeSpatrick  }, {
311*4bdff4beSrobert    "name": "__cpp_lib_expected",
312*4bdff4beSrobert    "values": { "c++2b": 202202 },
313*4bdff4beSrobert    "headers": ["expected"],
314*4bdff4beSrobert  }, {
31576d0caaeSpatrick    "name": "__cpp_lib_filesystem",
31676d0caaeSpatrick    "values": { "c++17": 201703 },
31776d0caaeSpatrick    "headers": ["filesystem"],
31876d0caaeSpatrick    "test_suite_guard": "!defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem)",
31976d0caaeSpatrick    "libcxx_guard": "!defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem)"
32076d0caaeSpatrick  }, {
32176d0caaeSpatrick    "name": "__cpp_lib_format",
322*4bdff4beSrobert    "values": {
323*4bdff4beSrobert        # "c++20": 201907 Not implemented P1361R2 Integration of chrono with text formatting
324*4bdff4beSrobert        # "c++20": 202106 Fully implemented
325*4bdff4beSrobert        # "c++20": 202110 Not implemented P2372R3 Fixing locale handling in chrono formatters
326*4bdff4beSrobert        "c++20": 202106,
327*4bdff4beSrobert        # "c++23": 202207, Not implemented P2419R2 Clarify handling of encodings in localized formatting of chrono types
328*4bdff4beSrobert        },
32976d0caaeSpatrick    "headers": ["format"],
330*4bdff4beSrobert    "test_suite_guard": "!defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_format) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)",
331*4bdff4beSrobert    "libcxx_guard": "!defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_format) && !defined(_LIBCPP_HAS_NO_INCOMPLETE_FORMAT)",
33276d0caaeSpatrick    "unimplemented": True,
33376d0caaeSpatrick  }, {
334*4bdff4beSrobert    "name": "__cpp_lib_forward_like",
335*4bdff4beSrobert    "values": { "c++2b": 202207 },
336*4bdff4beSrobert    "headers": ["utility"],
337*4bdff4beSrobert  }, {
33876d0caaeSpatrick    "name": "__cpp_lib_gcd_lcm",
33976d0caaeSpatrick    "values": { "c++17": 201606 },
34076d0caaeSpatrick    "headers": ["numeric"],
34176d0caaeSpatrick  }, {
34276d0caaeSpatrick    "name": "__cpp_lib_generic_associative_lookup",
34376d0caaeSpatrick    "values": { "c++14": 201304 },
34476d0caaeSpatrick    "headers": ["map", "set"],
34576d0caaeSpatrick  }, {
34676d0caaeSpatrick    "name": "__cpp_lib_generic_unordered_lookup",
34776d0caaeSpatrick    "values": { "c++20": 201811 },
34876d0caaeSpatrick    "headers": ["unordered_map", "unordered_set"],
34976d0caaeSpatrick  }, {
35076d0caaeSpatrick    "name": "__cpp_lib_hardware_interference_size",
35176d0caaeSpatrick    "values": { "c++17": 201703 },
352*4bdff4beSrobert    "test_suite_guard": "defined(__GCC_DESTRUCTIVE_SIZE) && defined(__GCC_CONSTRUCTIVE_SIZE)",
353*4bdff4beSrobert    "libcxx_guard": "defined(__GCC_DESTRUCTIVE_SIZE) && defined(__GCC_CONSTRUCTIVE_SIZE)",
35476d0caaeSpatrick    "headers": ["new"],
35576d0caaeSpatrick  }, {
35676d0caaeSpatrick    "name": "__cpp_lib_has_unique_object_representations",
35776d0caaeSpatrick    "values": { "c++17": 201606 },
35876d0caaeSpatrick    "headers": ["type_traits"],
35976d0caaeSpatrick  }, {
36076d0caaeSpatrick    "name": "__cpp_lib_hypot",
36176d0caaeSpatrick    "values": { "c++17": 201603 },
36276d0caaeSpatrick    "headers": ["cmath"],
36376d0caaeSpatrick  }, {
36476d0caaeSpatrick    "name": "__cpp_lib_incomplete_container_elements",
36576d0caaeSpatrick    "values": { "c++17": 201505 },
36676d0caaeSpatrick    "headers": ["forward_list", "list", "vector"],
36776d0caaeSpatrick  }, {
36876d0caaeSpatrick    "name": "__cpp_lib_int_pow2",
36976d0caaeSpatrick    "values": { "c++20": 202002 },
37076d0caaeSpatrick    "headers": ["bit"],
37176d0caaeSpatrick  }, {
37276d0caaeSpatrick    "name": "__cpp_lib_integer_comparison_functions",
37376d0caaeSpatrick    "values": { "c++20": 202002 },
37476d0caaeSpatrick    "headers": ["utility"],
37576d0caaeSpatrick  }, {
37676d0caaeSpatrick    "name": "__cpp_lib_integer_sequence",
37776d0caaeSpatrick    "values": { "c++14": 201304 },
37876d0caaeSpatrick    "headers": ["utility"],
37976d0caaeSpatrick  }, {
38076d0caaeSpatrick    "name": "__cpp_lib_integral_constant_callable",
38176d0caaeSpatrick    "values": { "c++14": 201304 },
38276d0caaeSpatrick    "headers": ["type_traits"],
38376d0caaeSpatrick  }, {
38476d0caaeSpatrick    "name": "__cpp_lib_interpolate",
38576d0caaeSpatrick    "values": { "c++20": 201902 },
38676d0caaeSpatrick    "headers": ["cmath", "numeric"],
38776d0caaeSpatrick  }, {
38876d0caaeSpatrick    "name": "__cpp_lib_invoke",
38976d0caaeSpatrick    "values": { "c++17": 201411 },
39076d0caaeSpatrick    "headers": ["functional"],
39176d0caaeSpatrick  }, {
392*4bdff4beSrobert    "name": "__cpp_lib_invoke_r",
393*4bdff4beSrobert    "values": { "c++2b": 202106 },
394*4bdff4beSrobert    "headers": ["functional"],
395*4bdff4beSrobert    "unimplemented": True,
396*4bdff4beSrobert  }, {
39776d0caaeSpatrick    "name": "__cpp_lib_is_aggregate",
39876d0caaeSpatrick    "values": { "c++17": 201703 },
39976d0caaeSpatrick    "headers": ["type_traits"],
40076d0caaeSpatrick  }, {
40176d0caaeSpatrick    "name": "__cpp_lib_is_constant_evaluated",
40276d0caaeSpatrick    "values": { "c++20": 201811 },
40376d0caaeSpatrick    "headers": ["type_traits"],
40476d0caaeSpatrick  }, {
40576d0caaeSpatrick    "name": "__cpp_lib_is_final",
40676d0caaeSpatrick    "values": { "c++14": 201402 },
40776d0caaeSpatrick    "headers": ["type_traits"],
40876d0caaeSpatrick  }, {
40976d0caaeSpatrick    "name": "__cpp_lib_is_invocable",
41076d0caaeSpatrick    "values": { "c++17": 201703 },
41176d0caaeSpatrick    "headers": ["type_traits"],
41276d0caaeSpatrick  }, {
41376d0caaeSpatrick    "name": "__cpp_lib_is_layout_compatible",
41476d0caaeSpatrick    "values": { "c++20": 201907 },
41576d0caaeSpatrick    "headers": ["type_traits"],
41676d0caaeSpatrick    "unimplemented": True,
41776d0caaeSpatrick  }, {
41876d0caaeSpatrick    "name": "__cpp_lib_is_nothrow_convertible",
41976d0caaeSpatrick    "values": { "c++20": 201806 },
42076d0caaeSpatrick    "headers": ["type_traits"],
42176d0caaeSpatrick  }, {
42276d0caaeSpatrick    "name": "__cpp_lib_is_null_pointer",
42376d0caaeSpatrick    "values": { "c++14": 201309 },
42476d0caaeSpatrick    "headers": ["type_traits"],
42576d0caaeSpatrick  }, {
42676d0caaeSpatrick    "name": "__cpp_lib_is_pointer_interconvertible",
42776d0caaeSpatrick    "values": { "c++20": 201907 },
42876d0caaeSpatrick    "headers": ["type_traits"],
42976d0caaeSpatrick    "unimplemented": True,
43076d0caaeSpatrick  }, {
43176d0caaeSpatrick    "name": "__cpp_lib_is_scoped_enum",
43276d0caaeSpatrick    "values": { "c++2b": 202011 },
43376d0caaeSpatrick    "headers": ["type_traits"],
43476d0caaeSpatrick  }, {
43576d0caaeSpatrick    "name": "__cpp_lib_is_swappable",
43676d0caaeSpatrick    "values": { "c++17": 201603 },
43776d0caaeSpatrick    "headers": ["type_traits"],
43876d0caaeSpatrick  }, {
43976d0caaeSpatrick    "name": "__cpp_lib_jthread",
44076d0caaeSpatrick    "values": { "c++20": 201911 },
44176d0caaeSpatrick    "headers": ["stop_token", "thread"],
44276d0caaeSpatrick    "test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS)",
44376d0caaeSpatrick    "libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS)",
44476d0caaeSpatrick    "unimplemented": True,
44576d0caaeSpatrick  }, {
44676d0caaeSpatrick    "name": "__cpp_lib_latch",
44776d0caaeSpatrick    "values": { "c++20": 201907 },
44876d0caaeSpatrick    "headers": ["latch"],
44976d0caaeSpatrick    "test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_latch)",
45076d0caaeSpatrick    "libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_latch)",
45176d0caaeSpatrick  }, {
45276d0caaeSpatrick    "name": "__cpp_lib_launder",
45376d0caaeSpatrick    "values": { "c++17": 201606 },
45476d0caaeSpatrick    "headers": ["new"],
45576d0caaeSpatrick  }, {
45676d0caaeSpatrick    "name": "__cpp_lib_list_remove_return_type",
45776d0caaeSpatrick    "values": { "c++20": 201806 },
45876d0caaeSpatrick    "headers": ["forward_list", "list"],
45976d0caaeSpatrick  }, {
46076d0caaeSpatrick    "name": "__cpp_lib_logical_traits",
46176d0caaeSpatrick    "values": { "c++17": 201510 },
46276d0caaeSpatrick    "headers": ["type_traits"],
46376d0caaeSpatrick  }, {
46476d0caaeSpatrick    "name": "__cpp_lib_make_from_tuple",
46576d0caaeSpatrick    "values": { "c++17": 201606 },
46676d0caaeSpatrick    "headers": ["tuple"],
46776d0caaeSpatrick  }, {
46876d0caaeSpatrick    "name": "__cpp_lib_make_reverse_iterator",
46976d0caaeSpatrick    "values": { "c++14": 201402 },
47076d0caaeSpatrick    "headers": ["iterator"],
47176d0caaeSpatrick  }, {
47276d0caaeSpatrick    "name": "__cpp_lib_make_unique",
47376d0caaeSpatrick    "values": { "c++14": 201304 },
47476d0caaeSpatrick    "headers": ["memory"],
47576d0caaeSpatrick  }, {
47676d0caaeSpatrick    "name": "__cpp_lib_map_try_emplace",
47776d0caaeSpatrick    "values": { "c++17": 201411 },
47876d0caaeSpatrick    "headers": ["map"],
47976d0caaeSpatrick  }, {
48076d0caaeSpatrick    "name": "__cpp_lib_math_constants",
48176d0caaeSpatrick    "values": { "c++20": 201907 },
48276d0caaeSpatrick    "headers": ["numbers"],
48376d0caaeSpatrick  }, {
48476d0caaeSpatrick    "name": "__cpp_lib_math_special_functions",
48576d0caaeSpatrick    "values": { "c++17": 201603 },
48676d0caaeSpatrick    "headers": ["cmath"],
48776d0caaeSpatrick    "unimplemented": True,
48876d0caaeSpatrick  }, {
48976d0caaeSpatrick    "name": "__cpp_lib_memory_resource",
49076d0caaeSpatrick    "values": { "c++17": 201603 },
49146035553Spatrick    "headers": ["memory_resource"],
492*4bdff4beSrobert  }, {
493*4bdff4beSrobert    "name": "__cpp_lib_move_only_function",
494*4bdff4beSrobert    "values": { "c++2b": 202110 },
495*4bdff4beSrobert    "headers": ["functional"],
49646035553Spatrick    "unimplemented": True,
49776d0caaeSpatrick  }, {
49876d0caaeSpatrick    "name": "__cpp_lib_node_extract",
49976d0caaeSpatrick    "values": { "c++17": 201606 },
50076d0caaeSpatrick    "headers": ["map", "set", "unordered_map", "unordered_set"],
50176d0caaeSpatrick  }, {
50276d0caaeSpatrick    "name": "__cpp_lib_nonmember_container_access",
50376d0caaeSpatrick    "values": { "c++17": 201411 },
50476d0caaeSpatrick    "headers": ["array", "deque", "forward_list", "iterator", "list", "map", "regex", "set", "string", "unordered_map", "unordered_set", "vector"],
50576d0caaeSpatrick  }, {
50676d0caaeSpatrick    "name": "__cpp_lib_not_fn",
50776d0caaeSpatrick    "values": { "c++17": 201603 },
50846035553Spatrick    "headers": ["functional"],
50976d0caaeSpatrick  }, {
51076d0caaeSpatrick    "name": "__cpp_lib_null_iterators",
51176d0caaeSpatrick    "values": { "c++14": 201304 },
51276d0caaeSpatrick    "headers": ["iterator"],
51376d0caaeSpatrick  }, {
51476d0caaeSpatrick    "name": "__cpp_lib_optional",
515*4bdff4beSrobert    "values": { "c++17": 201606, "c++2b": 202110 },
51676d0caaeSpatrick    "headers": ["optional"],
51776d0caaeSpatrick  }, {
518*4bdff4beSrobert    "name": "__cpp_lib_out_ptr",
519*4bdff4beSrobert    "values": { "c++2b": 202106 },
520*4bdff4beSrobert    "headers": ["memory"],
521*4bdff4beSrobert    "unimplemented": True,
522*4bdff4beSrobert  }, {
52376d0caaeSpatrick    "name": "__cpp_lib_parallel_algorithm",
52476d0caaeSpatrick    "values": { "c++17": 201603 },
52546035553Spatrick    "headers": ["algorithm", "numeric"],
52646035553Spatrick    "unimplemented": True,
52776d0caaeSpatrick  }, {
52876d0caaeSpatrick    "name": "__cpp_lib_polymorphic_allocator",
52976d0caaeSpatrick    "values": { "c++20": 201902 },
530*4bdff4beSrobert    "headers": ["memory_resource"],
53176d0caaeSpatrick  }, {
53276d0caaeSpatrick    "name": "__cpp_lib_quoted_string_io",
53376d0caaeSpatrick    "values": { "c++14": 201304 },
53476d0caaeSpatrick    "headers": ["iomanip"],
53576d0caaeSpatrick  }, {
53676d0caaeSpatrick    "name": "__cpp_lib_ranges",
537*4bdff4beSrobert    "values": { "c++20": 202106 },
53846035553Spatrick    "headers": ["algorithm", "functional", "iterator", "memory", "ranges"],
539*4bdff4beSrobert  }, {
540*4bdff4beSrobert    "name": "__cpp_lib_ranges_as_rvalue",
541*4bdff4beSrobert    "values": { "c++2b": 202207 },
542*4bdff4beSrobert    "headers": ["ranges"],
543*4bdff4beSrobert  }, {
544*4bdff4beSrobert    "name": "__cpp_lib_ranges_chunk",
545*4bdff4beSrobert    "values": { "c++2b": 202202 },
546*4bdff4beSrobert    "headers": ["ranges"],
547*4bdff4beSrobert    "unimplemented": True,
548*4bdff4beSrobert  }, {
549*4bdff4beSrobert    "name": "__cpp_lib_ranges_chunk_by",
550*4bdff4beSrobert    "values": { "c++2b": 202202 },
551*4bdff4beSrobert    "headers": ["ranges"],
552*4bdff4beSrobert    "unimplemented": True,
553*4bdff4beSrobert  }, {
554*4bdff4beSrobert    "name": "__cpp_lib_ranges_iota",
555*4bdff4beSrobert    "values": { "c++2b": 202202 },
556*4bdff4beSrobert    "headers": ["numeric"],
557*4bdff4beSrobert    "unimplemented": True,
558*4bdff4beSrobert  }, {
559*4bdff4beSrobert    "name": "__cpp_lib_ranges_join_with",
560*4bdff4beSrobert    "values": { "c++2b": 202202 },
561*4bdff4beSrobert    "headers": ["ranges"],
562*4bdff4beSrobert    "unimplemented": True,
563*4bdff4beSrobert  }, {
564*4bdff4beSrobert    "name": "__cpp_lib_ranges_slide",
565*4bdff4beSrobert    "values": { "c++2b": 202202 },
566*4bdff4beSrobert    "headers": ["ranges"],
567*4bdff4beSrobert    "unimplemented": True,
568*4bdff4beSrobert  }, {
569*4bdff4beSrobert    "name": "__cpp_lib_ranges_starts_ends_with",
570*4bdff4beSrobert    "values": { "c++2b": 202106 },
571*4bdff4beSrobert    "headers": ["algorithm"],
572*4bdff4beSrobert    "unimplemented": True,
573*4bdff4beSrobert  }, {
574*4bdff4beSrobert    "name": "__cpp_lib_ranges_to_container",
575*4bdff4beSrobert    "values": { "c++2b": 202202 },
576*4bdff4beSrobert    "headers": ["deque", "forward_list", "list", "map", "priority_queue", "queue", "set", "stack", "string", "unordered_map", "unordered_set", "vector"],
577*4bdff4beSrobert    "unimplemented": True,
578*4bdff4beSrobert  }, {
579*4bdff4beSrobert    "name": "__cpp_lib_ranges_zip",
580*4bdff4beSrobert    "values": { "c++2b": 202110 },
581*4bdff4beSrobert    "headers": ["ranges", "tuple", "utility"],
58246035553Spatrick    "unimplemented": True,
58376d0caaeSpatrick  }, {
58476d0caaeSpatrick    "name": "__cpp_lib_raw_memory_algorithms",
58576d0caaeSpatrick    "values": { "c++17": 201606 },
58676d0caaeSpatrick    "headers": ["memory"],
58776d0caaeSpatrick  }, {
588*4bdff4beSrobert    "name": "__cpp_lib_reference_from_temporary",
589*4bdff4beSrobert    "values": { "c++2b": 202202 },
590*4bdff4beSrobert    "headers": ["type_traits"],
591*4bdff4beSrobert    "unimplemented": True,
592*4bdff4beSrobert  }, {
59376d0caaeSpatrick    "name": "__cpp_lib_remove_cvref",
59476d0caaeSpatrick    "values": { "c++20": 201711 },
59576d0caaeSpatrick    "headers": ["type_traits"],
59676d0caaeSpatrick  }, {
59776d0caaeSpatrick    "name": "__cpp_lib_result_of_sfinae",
59876d0caaeSpatrick    "values": { "c++14": 201210 },
59976d0caaeSpatrick    "headers": ["functional", "type_traits"],
60076d0caaeSpatrick  }, {
60176d0caaeSpatrick    "name": "__cpp_lib_robust_nonmodifying_seq_ops",
60276d0caaeSpatrick    "values": { "c++14": 201304 },
60376d0caaeSpatrick    "headers": ["algorithm"],
60476d0caaeSpatrick  }, {
60576d0caaeSpatrick    "name": "__cpp_lib_sample",
60676d0caaeSpatrick    "values": { "c++17": 201603 },
60776d0caaeSpatrick    "headers": ["algorithm"],
60876d0caaeSpatrick  }, {
60976d0caaeSpatrick    "name": "__cpp_lib_scoped_lock",
61076d0caaeSpatrick    "values": { "c++17": 201703 },
61176d0caaeSpatrick    "headers": ["mutex"],
61276d0caaeSpatrick  }, {
61376d0caaeSpatrick    "name": "__cpp_lib_semaphore",
61476d0caaeSpatrick    "values": { "c++20": 201907 },
61576d0caaeSpatrick    "headers": ["semaphore"],
61676d0caaeSpatrick    "test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_semaphore)",
61776d0caaeSpatrick    "libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_semaphore)",
61876d0caaeSpatrick  }, {
61976d0caaeSpatrick    "name": "__cpp_lib_shared_mutex",
62076d0caaeSpatrick    "values": { "c++17": 201505 },
62176d0caaeSpatrick    "headers": ["shared_mutex"],
62276d0caaeSpatrick    "test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_mutex)",
62376d0caaeSpatrick    "libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_mutex)",
62476d0caaeSpatrick  }, {
62576d0caaeSpatrick    "name": "__cpp_lib_shared_ptr_arrays",
626*4bdff4beSrobert    "values": { "c++17": 201611, "c++20": 201707 },
62776d0caaeSpatrick    "headers": ["memory"],
62876d0caaeSpatrick  }, {
62976d0caaeSpatrick    "name": "__cpp_lib_shared_ptr_weak_type",
63076d0caaeSpatrick    "values": { "c++17": 201606 },
63176d0caaeSpatrick    "headers": ["memory"],
63276d0caaeSpatrick  }, {
63376d0caaeSpatrick    "name": "__cpp_lib_shared_timed_mutex",
63476d0caaeSpatrick    "values": { "c++14": 201402 },
63576d0caaeSpatrick    "headers": ["shared_mutex"],
63676d0caaeSpatrick    "test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex)",
63776d0caaeSpatrick    "libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex)",
63876d0caaeSpatrick  }, {
63976d0caaeSpatrick    "name": "__cpp_lib_shift",
64076d0caaeSpatrick    "values": { "c++20": 201806 },
64176d0caaeSpatrick    "headers": ["algorithm"],
64276d0caaeSpatrick  }, {
64376d0caaeSpatrick    "name": "__cpp_lib_smart_ptr_for_overwrite",
64476d0caaeSpatrick    "values": { "c++20": 202002 },
64576d0caaeSpatrick    "headers": ["memory"],
64646035553Spatrick    "unimplemented": True,
64776d0caaeSpatrick  }, {
64876d0caaeSpatrick    "name": "__cpp_lib_source_location",
64976d0caaeSpatrick    "values": { "c++20": 201907 },
65076d0caaeSpatrick    "headers": ["source_location"],
651*4bdff4beSrobert    "test_suite_guard": "__has_builtin(__builtin_source_location) && !(defined(TEST_APPLE_CLANG_VER) && TEST_APPLE_CLANG_VER <= 1403)",
652*4bdff4beSrobert    "libcxx_guard": "__has_builtin(__builtin_source_location) && !(defined(_LIBCPP_APPLE_CLANG_VER) && _LIBCPP_APPLE_CLANG_VER <= 1403)",
65376d0caaeSpatrick  }, {
65476d0caaeSpatrick    "name": "__cpp_lib_span",
65576d0caaeSpatrick    "values": { "c++20": 202002 },
656037e7968Spatrick    "headers": ["span"],
65776d0caaeSpatrick  }, {
658*4bdff4beSrobert    "name": "__cpp_lib_spanstream",
659*4bdff4beSrobert    "values": { "c++2b": 202106 },
660*4bdff4beSrobert    "headers": ["spanstream"],
661*4bdff4beSrobert    "unimplemented": True,
662*4bdff4beSrobert  }, {
66376d0caaeSpatrick    "name": "__cpp_lib_ssize",
66476d0caaeSpatrick    "values": { "c++20": 201902 },
66576d0caaeSpatrick    "headers": ["iterator"],
66676d0caaeSpatrick  }, {
66776d0caaeSpatrick    "name": "__cpp_lib_stacktrace",
66876d0caaeSpatrick    "values": { "c++2b": 202011 },
66976d0caaeSpatrick    "headers": ["stacktrace"],
67076d0caaeSpatrick    "unimplemented": True,
67176d0caaeSpatrick  }, {
67276d0caaeSpatrick    "name": "__cpp_lib_starts_ends_with",
67376d0caaeSpatrick    "values": { "c++20": 201711 },
67476d0caaeSpatrick    "headers": ["string", "string_view"],
67576d0caaeSpatrick  }, {
67676d0caaeSpatrick    "name": "__cpp_lib_stdatomic_h",
67776d0caaeSpatrick    "values": { "c++2b": 202011 },
67876d0caaeSpatrick    "headers": ["stdatomic.h"],
67976d0caaeSpatrick  }, {
68076d0caaeSpatrick    "name": "__cpp_lib_string_contains",
68176d0caaeSpatrick    "values": { "c++2b": 202011 },
68276d0caaeSpatrick    "headers": ["string", "string_view"],
68376d0caaeSpatrick  }, {
684*4bdff4beSrobert    "name": "__cpp_lib_string_resize_and_overwrite",
685*4bdff4beSrobert    "values": { "c++2b": 202110 },
686*4bdff4beSrobert    "headers": ["string"],
687*4bdff4beSrobert  }, {
68876d0caaeSpatrick    "name": "__cpp_lib_string_udls",
68976d0caaeSpatrick    "values": { "c++14": 201304 },
69076d0caaeSpatrick    "headers": ["string"],
69176d0caaeSpatrick  }, {
69276d0caaeSpatrick    "name": "__cpp_lib_string_view",
69376d0caaeSpatrick    "values": { "c++17": 201606, "c++20": 201803 },
69476d0caaeSpatrick    "headers": ["string", "string_view"],
69576d0caaeSpatrick  }, {
69676d0caaeSpatrick    "name": "__cpp_lib_syncbuf",
69776d0caaeSpatrick    "values": { "c++20": 201803 },
69876d0caaeSpatrick    "headers": ["syncstream"],
69976d0caaeSpatrick    "unimplemented": True,
70076d0caaeSpatrick  }, {
70176d0caaeSpatrick    "name": "__cpp_lib_three_way_comparison",
70276d0caaeSpatrick    "values": { "c++20": 201907 },
70376d0caaeSpatrick    "headers": ["compare"],
70476d0caaeSpatrick    "unimplemented": True,
70576d0caaeSpatrick  }, {
70676d0caaeSpatrick    "name": "__cpp_lib_to_address",
70776d0caaeSpatrick    "values": { "c++20": 201711 },
70876d0caaeSpatrick    "headers": ["memory"],
70976d0caaeSpatrick  }, {
71076d0caaeSpatrick    "name": "__cpp_lib_to_array",
71176d0caaeSpatrick    "values": { "c++20": 201907 },
71276d0caaeSpatrick    "headers": ["array"],
71376d0caaeSpatrick  }, {
71476d0caaeSpatrick    "name": "__cpp_lib_to_chars",
71576d0caaeSpatrick    "values": { "c++17": 201611 },
716*4bdff4beSrobert    "headers": ["charconv"],
71776d0caaeSpatrick    "unimplemented": True,
71876d0caaeSpatrick  }, {
71976d0caaeSpatrick    "name": "__cpp_lib_to_underlying",
72076d0caaeSpatrick    "values": { "c++2b": 202102 },
72176d0caaeSpatrick    "headers": ["utility"],
72276d0caaeSpatrick  }, {
72376d0caaeSpatrick    "name": "__cpp_lib_transformation_trait_aliases",
72476d0caaeSpatrick    "values": { "c++14": 201304 },
72576d0caaeSpatrick    "headers": ["type_traits"],
72676d0caaeSpatrick  }, {
72776d0caaeSpatrick    "name": "__cpp_lib_transparent_operators",
72876d0caaeSpatrick    "values": { "c++14": 201210, "c++17": 201510 },
72976d0caaeSpatrick    "headers": ["functional", "memory"],
73076d0caaeSpatrick  }, {
73176d0caaeSpatrick    "name": "__cpp_lib_tuple_element_t",
73276d0caaeSpatrick    "values": { "c++14": 201402 },
73376d0caaeSpatrick    "headers": ["tuple"],
73476d0caaeSpatrick  }, {
73576d0caaeSpatrick    "name": "__cpp_lib_tuples_by_type",
73676d0caaeSpatrick    "values": { "c++14": 201304 },
73776d0caaeSpatrick    "headers": ["tuple", "utility"],
73876d0caaeSpatrick  }, {
739*4bdff4beSrobert    "name": "__cpp_lib_type_identity",
740*4bdff4beSrobert    "values": { "c++20": 201806 },
741*4bdff4beSrobert    "headers": ["type_traits"],
742*4bdff4beSrobert  }, {
74376d0caaeSpatrick    "name": "__cpp_lib_type_trait_variable_templates",
74476d0caaeSpatrick    "values": { "c++17": 201510 },
74576d0caaeSpatrick    "headers": ["type_traits"],
74676d0caaeSpatrick  }, {
74776d0caaeSpatrick    "name": "__cpp_lib_uncaught_exceptions",
74876d0caaeSpatrick    "values": { "c++17": 201411 },
74976d0caaeSpatrick    "headers": ["exception"],
75076d0caaeSpatrick  }, {
75176d0caaeSpatrick    "name": "__cpp_lib_unordered_map_try_emplace",
75276d0caaeSpatrick    "values": { "c++17": 201411 },
75376d0caaeSpatrick    "headers": ["unordered_map"],
75476d0caaeSpatrick  }, {
755*4bdff4beSrobert    "name": "__cpp_lib_unreachable",
756*4bdff4beSrobert    "values": { "c++2b": 202202 },
757*4bdff4beSrobert    "headers": ["utility"],
758*4bdff4beSrobert  }, {
75976d0caaeSpatrick    "name": "__cpp_lib_unwrap_ref",
76076d0caaeSpatrick    "values": { "c++20": 201811 },
76176d0caaeSpatrick    "headers": ["functional"],
76276d0caaeSpatrick  }, {
76376d0caaeSpatrick    "name": "__cpp_lib_variant",
76476d0caaeSpatrick    "values": { "c++17": 202102 },
76576d0caaeSpatrick    "headers": ["variant"],
76676d0caaeSpatrick  }, {
76776d0caaeSpatrick    "name": "__cpp_lib_void_t",
76876d0caaeSpatrick    "values": { "c++17": 201411 },
76976d0caaeSpatrick    "headers": ["type_traits"],
77076d0caaeSpatrick  }
77176d0caaeSpatrick]]
77276d0caaeSpatrick
77376d0caaeSpatrickassert feature_test_macros == sorted(feature_test_macros, key=lambda tc: tc["name"])
77476d0caaeSpatrickassert all(tc["headers"] == sorted(tc["headers"]) for tc in feature_test_macros)
77576d0caaeSpatrickassert all(("libcxx_guard" in tc) == ("test_suite_guard" in tc) for tc in feature_test_macros)
77676d0caaeSpatrickassert all(all(key in ["name", "values", "headers", "libcxx_guard", "test_suite_guard", "unimplemented"] for key in tc.keys()) for tc in feature_test_macros)
77776d0caaeSpatrick
77876d0caaeSpatrick# Map from each header to the Lit annotations that should be used for
77976d0caaeSpatrick# tests that include that header.
78076d0caaeSpatrick#
781*4bdff4beSrobert# For example, when threads are not supported, any test that includes
782*4bdff4beSrobert# <thread> should be marked as UNSUPPORTED, because including <thread>
783*4bdff4beSrobert# is a hard error in that case.
78476d0caaeSpatricklit_markup = {
785*4bdff4beSrobert  "barrier": ["UNSUPPORTED: no-threads"],
786*4bdff4beSrobert  "filesystem": ["UNSUPPORTED: no-filesystem"],
78776d0caaeSpatrick  "format": ["UNSUPPORTED: libcpp-has-no-incomplete-format"],
788*4bdff4beSrobert  "iomanip": ["UNSUPPORTED: no-localization"],
789*4bdff4beSrobert  "ios": ["UNSUPPORTED: no-localization"],
790*4bdff4beSrobert  "iostream": ["UNSUPPORTED: no-localization"],
791*4bdff4beSrobert  "istream": ["UNSUPPORTED: no-localization"],
792*4bdff4beSrobert  "latch": ["UNSUPPORTED: no-threads"],
793*4bdff4beSrobert  "locale": ["UNSUPPORTED: no-localization"],
794*4bdff4beSrobert  "mutex": ["UNSUPPORTED: no-threads"],
795*4bdff4beSrobert  "ostream": ["UNSUPPORTED: no-localization"],
796*4bdff4beSrobert  "regex": ["UNSUPPORTED: no-localization"],
797*4bdff4beSrobert  "semaphore": ["UNSUPPORTED: no-threads"],
798*4bdff4beSrobert  "shared_mutex": ["UNSUPPORTED: no-threads"],
799*4bdff4beSrobert  "stdatomic.h": ["UNSUPPORTED: no-threads"],
800*4bdff4beSrobert  "thread": ["UNSUPPORTED: no-threads"],
80176d0caaeSpatrick}
80246035553Spatrick
80346035553Spatrickdef get_std_dialects():
80476d0caaeSpatrick  std_dialects = ['c++14', 'c++17', 'c++20', 'c++2b']
80546035553Spatrick  return list(std_dialects)
80646035553Spatrick
80746035553Spatrickdef get_first_std(d):
80846035553Spatrick    for s in get_std_dialects():
80946035553Spatrick        if s in d.keys():
81046035553Spatrick            return s
81146035553Spatrick    return None
81246035553Spatrick
81346035553Spatrickdef get_last_std(d):
81446035553Spatrick  rev_dialects = get_std_dialects()
81546035553Spatrick  rev_dialects.reverse()
81646035553Spatrick  for s in rev_dialects:
81746035553Spatrick    if s in d.keys():
81846035553Spatrick      return s
81946035553Spatrick  return None
82046035553Spatrick
82146035553Spatrickdef get_std_before(d, std):
82246035553Spatrick  std_dialects = get_std_dialects()
82346035553Spatrick  candidates = std_dialects[0:std_dialects.index(std)]
82446035553Spatrick  candidates.reverse()
82546035553Spatrick  for cand in candidates:
82646035553Spatrick    if cand in d.keys():
82746035553Spatrick      return cand
82846035553Spatrick  return None
82946035553Spatrick
83046035553Spatrickdef get_value_before(d, std):
83146035553Spatrick  new_std = get_std_before(d, std)
83246035553Spatrick  if new_std is None:
83346035553Spatrick    return None
83446035553Spatrick  return d[new_std]
83546035553Spatrick
83646035553Spatrickdef get_for_std(d, std):
83746035553Spatrick  # This catches the C++11 case for which there should be no defined feature
83846035553Spatrick  # test macros.
83946035553Spatrick  std_dialects = get_std_dialects()
84046035553Spatrick  if std not in std_dialects:
84146035553Spatrick    return None
84246035553Spatrick  # Find the value for the newest C++ dialect between C++14 and std
84346035553Spatrick  std_list = list(std_dialects[0:std_dialects.index(std)+1])
84446035553Spatrick  std_list.reverse()
84546035553Spatrick  for s in std_list:
84646035553Spatrick    if s in d.keys():
84746035553Spatrick      return d[s]
84846035553Spatrick  return None
84946035553Spatrick
85076d0caaeSpatrickdef get_std_number(std):
85176d0caaeSpatrick    return std.replace('c++', '')
85246035553Spatrick
85346035553Spatrick"""
85446035553Spatrick  Functions to produce the <version> header
85546035553Spatrick"""
85646035553Spatrick
85746035553Spatrickdef produce_macros_definition_for_std(std):
85846035553Spatrick  result = ""
85976d0caaeSpatrick  indent = 55
86046035553Spatrick  for tc in feature_test_macros:
86146035553Spatrick    if std not in tc["values"]:
86246035553Spatrick      continue
86346035553Spatrick    inner_indent = 1
86476d0caaeSpatrick    if 'test_suite_guard' in tc.keys():
86576d0caaeSpatrick      result += "# if %s\n" % tc["libcxx_guard"]
86646035553Spatrick      inner_indent += 2
86746035553Spatrick    if get_value_before(tc["values"], std) is not None:
86876d0caaeSpatrick      assert 'test_suite_guard' not in tc.keys()
86946035553Spatrick      result += "# undef  %s\n" % tc["name"]
87046035553Spatrick    line = "#%sdefine %s" % ((" " * inner_indent), tc["name"])
87146035553Spatrick    line += " " * (indent - len(line))
87246035553Spatrick    line += " %sL" % tc["values"][std]
87346035553Spatrick    if 'unimplemented' in tc.keys():
87446035553Spatrick      line = "// " + line
87546035553Spatrick    result += line
87646035553Spatrick    result += "\n"
87776d0caaeSpatrick    if 'test_suite_guard' in tc.keys():
87846035553Spatrick      result += "# endif\n"
87976d0caaeSpatrick  return result.strip()
88076d0caaeSpatrick
88176d0caaeSpatrickdef produce_macros_definitions():
88276d0caaeSpatrick  macro_definition_template = """#if _LIBCPP_STD_VER > {previous_std_number}
88376d0caaeSpatrick{macro_definition}
88476d0caaeSpatrick#endif"""
88576d0caaeSpatrick
88676d0caaeSpatrick  macros_definitions = []
88776d0caaeSpatrick  previous_std_number = '11'
88876d0caaeSpatrick  for std in get_std_dialects():
88976d0caaeSpatrick    macros_definitions.append(
89076d0caaeSpatrick      macro_definition_template.format(previous_std_number=previous_std_number,
89176d0caaeSpatrick                                       macro_definition=produce_macros_definition_for_std(std)))
89276d0caaeSpatrick    previous_std_number = get_std_number(std)
89376d0caaeSpatrick
89476d0caaeSpatrick  return '\n\n'.join(macros_definitions)
89546035553Spatrick
89646035553Spatrickdef chunks(l, n):
89746035553Spatrick  """Yield successive n-sized chunks from l."""
89846035553Spatrick  for i in range(0, len(l), n):
89946035553Spatrick    yield l[i:i + n]
90046035553Spatrick
90146035553Spatrickdef produce_version_synopsis():
90246035553Spatrick  indent = 56
90346035553Spatrick  header_indent = 56 + len("20XXYYL ")
90446035553Spatrick  result = ""
90546035553Spatrick  def indent_to(s, val):
90646035553Spatrick    if len(s) >= val:
90746035553Spatrick      return s
90846035553Spatrick    s += " " * (val - len(s))
90946035553Spatrick    return s
91046035553Spatrick  line = indent_to("Macro name", indent) + "Value"
91146035553Spatrick  line = indent_to(line, header_indent) + "Headers"
91246035553Spatrick  result += line + "\n"
91346035553Spatrick  for tc in feature_test_macros:
91446035553Spatrick    prev_defined_std = get_last_std(tc["values"])
91546035553Spatrick    line = "{name: <{indent}}{value}L ".format(name=tc['name'], indent=indent,
91646035553Spatrick                                               value=tc["values"][prev_defined_std])
91746035553Spatrick    headers = list(tc["headers"])
91846035553Spatrick    headers.remove("version")
91946035553Spatrick    for chunk in chunks(headers, 3):
92046035553Spatrick      line = indent_to(line, header_indent)
92146035553Spatrick      chunk = ['<%s>' % header for header in chunk]
92246035553Spatrick      line += ' '.join(chunk)
92346035553Spatrick      result += line
92446035553Spatrick      result += "\n"
92546035553Spatrick      line = ""
92646035553Spatrick    while True:
92746035553Spatrick      prev_defined_std = get_std_before(tc["values"], prev_defined_std)
92846035553Spatrick      if prev_defined_std is None:
92946035553Spatrick        break
93046035553Spatrick      result += "%s%sL // %s\n" % (indent_to("", indent), tc["values"][prev_defined_std],
93146035553Spatrick                                prev_defined_std.replace("c++", "C++"))
93246035553Spatrick  return result
93346035553Spatrick
93446035553Spatrick
93546035553Spatrickdef produce_version_header():
93646035553Spatrick  template="""// -*- C++ -*-
937*4bdff4beSrobert//===----------------------------------------------------------------------===//
93846035553Spatrick//
93946035553Spatrick// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
94046035553Spatrick// See https://llvm.org/LICENSE.txt for license information.
94146035553Spatrick// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
94246035553Spatrick//
94346035553Spatrick//===----------------------------------------------------------------------===//
94446035553Spatrick
94546035553Spatrick#ifndef _LIBCPP_VERSIONH
94646035553Spatrick#define _LIBCPP_VERSIONH
94746035553Spatrick
94846035553Spatrick/*
94946035553Spatrick  version synopsis
95046035553Spatrick
95146035553Spatrick{synopsis}
95246035553Spatrick
95346035553Spatrick*/
95446035553Spatrick
955*4bdff4beSrobert#include <__assert> // all public C++ headers provide the assertion handler
95646035553Spatrick#include <__config>
95746035553Spatrick
95846035553Spatrick#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
95946035553Spatrick#  pragma GCC system_header
96046035553Spatrick#endif
96146035553Spatrick
96276d0caaeSpatrick// clang-format off
96346035553Spatrick
96476d0caaeSpatrick{cxx_macros}
96546035553Spatrick
96676d0caaeSpatrick// clang-format on
96746035553Spatrick
96846035553Spatrick#endif // _LIBCPP_VERSIONH
96946035553Spatrick"""
97076d0caaeSpatrick
97176d0caaeSpatrick  version_str = template.format(
97246035553Spatrick      synopsis=produce_version_synopsis().strip(),
97376d0caaeSpatrick      cxx_macros=produce_macros_definitions())
97476d0caaeSpatrick  version_header_path = os.path.join(include_path, 'version')
97576d0caaeSpatrick  with open(version_header_path, 'w', newline='\n') as f:
97676d0caaeSpatrick    f.write(version_str)
97776d0caaeSpatrick
97846035553Spatrick
97946035553Spatrick"""
98046035553Spatrick    Functions to produce test files
98146035553Spatrick"""
98246035553Spatrick
98346035553Spatricktest_types = {
98446035553Spatrick  "undefined": """
98546035553Spatrick# ifdef {name}
98646035553Spatrick#   error "{name} should not be defined before {std_first}"
98746035553Spatrick# endif
98846035553Spatrick""",
98946035553Spatrick
99076d0caaeSpatrick  "test_suite_guard": """
99176d0caaeSpatrick# if {test_suite_guard}
99246035553Spatrick#   ifndef {name}
99346035553Spatrick#     error "{name} should be defined in {std}"
99446035553Spatrick#   endif
99546035553Spatrick#   if {name} != {value}
99646035553Spatrick#     error "{name} should have the value {value} in {std}"
99746035553Spatrick#   endif
99846035553Spatrick# else
99946035553Spatrick#   ifdef {name}
1000*4bdff4beSrobert#     error "{name} should not be defined when the requirement '{test_suite_guard}' is not met!"
100146035553Spatrick#   endif
100246035553Spatrick# endif
100346035553Spatrick""",
100446035553Spatrick
100546035553Spatrick  "unimplemented": """
100646035553Spatrick# if !defined(_LIBCPP_VERSION)
100746035553Spatrick#   ifndef {name}
100846035553Spatrick#     error "{name} should be defined in {std}"
100946035553Spatrick#   endif
101046035553Spatrick#   if {name} != {value}
101146035553Spatrick#     error "{name} should have the value {value} in {std}"
101246035553Spatrick#   endif
101346035553Spatrick# else // _LIBCPP_VERSION
101446035553Spatrick#   ifdef {name}
101546035553Spatrick#     error "{name} should not be defined because it is unimplemented in libc++!"
101646035553Spatrick#   endif
101746035553Spatrick# endif
101846035553Spatrick""",
101946035553Spatrick
102046035553Spatrick  "defined": """
102146035553Spatrick# ifndef {name}
102246035553Spatrick#   error "{name} should be defined in {std}"
102346035553Spatrick# endif
102446035553Spatrick# if {name} != {value}
102546035553Spatrick#   error "{name} should have the value {value} in {std}"
102646035553Spatrick# endif
102746035553Spatrick"""
102846035553Spatrick}
102946035553Spatrick
103046035553Spatrickdef generate_std_test(test_list, std):
103146035553Spatrick  result = ""
103246035553Spatrick  for tc in test_list:
103346035553Spatrick    val = get_for_std(tc["values"], std)
103446035553Spatrick    if val is not None:
103546035553Spatrick      val = "%sL" % val
103646035553Spatrick    if val is None:
103746035553Spatrick      result += test_types["undefined"].format(name=tc["name"], std_first=get_first_std(tc["values"]))
103846035553Spatrick    elif 'unimplemented' in tc.keys():
103946035553Spatrick      result += test_types["unimplemented"].format(name=tc["name"], value=val, std=std)
104076d0caaeSpatrick    elif "test_suite_guard" in tc.keys():
104176d0caaeSpatrick      result += test_types["test_suite_guard"].format(name=tc["name"], value=val, std=std, test_suite_guard=tc["test_suite_guard"])
104246035553Spatrick    else:
104346035553Spatrick      result +=  test_types["defined"].format(name=tc["name"], value=val, std=std)
104476d0caaeSpatrick  return result.strip()
104576d0caaeSpatrick
104676d0caaeSpatrickdef generate_std_tests(test_list):
104776d0caaeSpatrick  std_tests_template = """#if TEST_STD_VER < {first_std_number}
104876d0caaeSpatrick
104976d0caaeSpatrick{pre_std_test}
105076d0caaeSpatrick
105176d0caaeSpatrick{other_std_tests}
105276d0caaeSpatrick
105376d0caaeSpatrick#elif TEST_STD_VER > {penultimate_std_number}
105476d0caaeSpatrick
105576d0caaeSpatrick{last_std_test}
105676d0caaeSpatrick
105776d0caaeSpatrick#endif // TEST_STD_VER > {penultimate_std_number}"""
105876d0caaeSpatrick
105976d0caaeSpatrick  std_dialects = get_std_dialects()
106076d0caaeSpatrick  assert not get_std_number(std_dialects[-1]).isnumeric()
106176d0caaeSpatrick
106276d0caaeSpatrick  other_std_tests = []
106376d0caaeSpatrick  for std in std_dialects[:-1]:
106476d0caaeSpatrick    other_std_tests.append('#elif TEST_STD_VER == ' + get_std_number(std))
106576d0caaeSpatrick    other_std_tests.append(generate_std_test(test_list, std))
106676d0caaeSpatrick
106776d0caaeSpatrick  std_tests = std_tests_template.format(first_std_number=get_std_number(std_dialects[0]),
106876d0caaeSpatrick                                        pre_std_test=generate_std_test(test_list, 'c++11'),
106976d0caaeSpatrick                                        other_std_tests='\n\n'.join(other_std_tests),
107076d0caaeSpatrick                                        penultimate_std_number=get_std_number(std_dialects[-2]),
107176d0caaeSpatrick                                        last_std_test=generate_std_test(test_list, std_dialects[-1]))
107276d0caaeSpatrick
107376d0caaeSpatrick  return std_tests
107446035553Spatrick
107546035553Spatrickdef generate_synopsis(test_list):
107646035553Spatrick    max_name_len = max([len(tc["name"]) for tc in test_list])
107746035553Spatrick    indent = max_name_len + 8
107846035553Spatrick    def mk_line(prefix, suffix):
107946035553Spatrick        return "{prefix: <{max_len}}{suffix}\n".format(prefix=prefix, suffix=suffix,
108046035553Spatrick        max_len=indent)
108146035553Spatrick    result = ""
108246035553Spatrick    result += mk_line("/*  Constant", "Value")
108346035553Spatrick    for tc in test_list:
108446035553Spatrick        prefix = "    %s" % tc["name"]
108546035553Spatrick        for std in [s for s in get_std_dialects() if s in tc["values"].keys()]:
108646035553Spatrick            result += mk_line(prefix, "%sL [%s]" % (tc["values"][std], std.replace("c++", "C++")))
108746035553Spatrick            prefix = ""
108846035553Spatrick    result += "*/"
108946035553Spatrick    return result
109046035553Spatrick
109146035553Spatrickdef produce_tests():
109246035553Spatrick  headers = set([h for tc in feature_test_macros for h in tc["headers"]])
109346035553Spatrick  for h in headers:
109446035553Spatrick    test_list = [tc for tc in feature_test_macros if h in tc["headers"]]
109546035553Spatrick    if not has_header(h):
109646035553Spatrick      for tc in test_list:
109746035553Spatrick        assert 'unimplemented' in tc.keys()
109846035553Spatrick      continue
109976d0caaeSpatrick    markup = '\n'.join('// ' + tag for tag in lit_markup.get(h, []))
110046035553Spatrick    test_body = \
110146035553Spatrick"""//===----------------------------------------------------------------------===//
110246035553Spatrick//
110346035553Spatrick// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
110446035553Spatrick// See https://llvm.org/LICENSE.txt for license information.
110546035553Spatrick// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
110646035553Spatrick//
110746035553Spatrick//===----------------------------------------------------------------------===//
110846035553Spatrick//
110946035553Spatrick// WARNING: This test was generated by {script_name}
111046035553Spatrick// and should not be edited manually.
111176d0caaeSpatrick//
111276d0caaeSpatrick// clang-format off
111376d0caaeSpatrick{markup}
111446035553Spatrick// <{header}>
111546035553Spatrick
111646035553Spatrick// Test the feature test macros defined by <{header}>
111746035553Spatrick
111846035553Spatrick{synopsis}
111946035553Spatrick
112046035553Spatrick#include <{header}>
112146035553Spatrick#include "test_macros.h"
112246035553Spatrick
112376d0caaeSpatrick{cxx_tests}
112446035553Spatrick
112546035553Spatrick""".format(script_name=script_name,
112646035553Spatrick           header=h,
112776d0caaeSpatrick           markup=('\n{}\n'.format(markup) if markup else ''),
112846035553Spatrick           synopsis=generate_synopsis(test_list),
112976d0caaeSpatrick           cxx_tests=generate_std_tests(test_list))
1130*4bdff4beSrobert    test_name = "{header}.version.compile.pass.cpp".format(header=h)
113146035553Spatrick    out_path = os.path.join(macro_test_path, test_name)
113276d0caaeSpatrick    with open(out_path, 'w', newline='\n') as f:
113346035553Spatrick      f.write(test_body)
113446035553Spatrick
113546035553Spatrick"""
113646035553Spatrick    Produce documentation for the feature test macros
113746035553Spatrick"""
113846035553Spatrick
113946035553Spatrickdef make_widths(grid):
114046035553Spatrick  widths = []
114146035553Spatrick  for i in range(0, len(grid[0])):
114246035553Spatrick    cell_width = 2 + max(reduce(lambda x,y: x+y, [[len(row[i])] for row in grid], []))
114346035553Spatrick    widths += [cell_width]
114446035553Spatrick  return widths
114546035553Spatrick
114646035553Spatrickdef create_table(grid, indent):
114746035553Spatrick  indent_str = ' '*indent
114846035553Spatrick  col_widths = make_widths(grid)
114976d0caaeSpatrick  result = [indent_str + add_divider(col_widths, 2)]
115046035553Spatrick  header_flag = 2
115146035553Spatrick  for row_i in range(0, len(grid)):
115246035553Spatrick    row = grid[row_i]
115376d0caaeSpatrick    line = indent_str + ' '.join([pad_cell(row[i], col_widths[i]) for i in range(0, len(row))])
115476d0caaeSpatrick    result.append(line.rstrip())
115546035553Spatrick    is_cxx_header = row[0].startswith('**')
115646035553Spatrick    if row_i == len(grid) - 1:
115746035553Spatrick      header_flag = 2
115876d0caaeSpatrick    separator = indent_str + add_divider(col_widths, 1 if is_cxx_header else header_flag)
115976d0caaeSpatrick    result.append(separator.rstrip())
116046035553Spatrick    header_flag = 0
116176d0caaeSpatrick  return '\n'.join(result)
116246035553Spatrick
116346035553Spatrickdef add_divider(widths, header_flag):
116446035553Spatrick  if header_flag == 2:
116576d0caaeSpatrick    return ' '.join(['='*w for w in widths])
116646035553Spatrick  if header_flag == 1:
116776d0caaeSpatrick    return '-'.join(['-'*w for w in widths])
116846035553Spatrick  else:
116976d0caaeSpatrick    return ' '.join(['-'*w for w in widths])
117046035553Spatrick
117146035553Spatrickdef pad_cell(s, length, left_align=True):
117246035553Spatrick  padding = ((length - len(s)) * ' ')
117346035553Spatrick  return s + padding
117446035553Spatrick
117546035553Spatrick
117646035553Spatrickdef get_status_table():
117746035553Spatrick  table = [["Macro Name", "Value"]]
117846035553Spatrick  for std in get_std_dialects():
117946035553Spatrick    table += [["**" + std.replace("c++", "C++ ") + "**", ""]]
118046035553Spatrick    for tc in feature_test_macros:
118146035553Spatrick      if std not in tc["values"].keys():
118246035553Spatrick        continue
118346035553Spatrick      value = "``%sL``" % tc["values"][std]
118446035553Spatrick      if 'unimplemented' in tc.keys():
118546035553Spatrick        value = '*unimplemented*'
118646035553Spatrick      table += [["``%s``" % tc["name"], value]]
118746035553Spatrick  return table
118846035553Spatrick
118946035553Spatrickdef produce_docs():
119046035553Spatrick  doc_str = """.. _FeatureTestMacroTable:
119146035553Spatrick
119246035553Spatrick==========================
119346035553SpatrickFeature Test Macro Support
119446035553Spatrick==========================
119546035553Spatrick
119646035553Spatrick.. contents::
119746035553Spatrick   :local:
119846035553Spatrick
119946035553SpatrickOverview
120046035553Spatrick========
120146035553Spatrick
120246035553SpatrickThis file documents the feature test macros currently supported by libc++.
120346035553Spatrick
120446035553Spatrick.. _feature-status:
120546035553Spatrick
120646035553SpatrickStatus
120746035553Spatrick======
120846035553Spatrick
120946035553Spatrick.. table:: Current Status
121046035553Spatrick    :name: feature-status-table
121146035553Spatrick    :widths: auto
121246035553Spatrick
121346035553Spatrick{status_tables}
121446035553Spatrick
121546035553Spatrick""".format(status_tables=create_table(get_status_table(), 4))
121646035553Spatrick
121746035553Spatrick  table_doc_path = os.path.join(docs_path, 'FeatureTestMacroTable.rst')
121876d0caaeSpatrick  with open(table_doc_path, 'w', newline='\n') as f:
121946035553Spatrick    f.write(doc_str)
122046035553Spatrick
122146035553Spatrickdef main():
122276d0caaeSpatrick  produce_version_header()
122346035553Spatrick  produce_tests()
122446035553Spatrick  produce_docs()
122546035553Spatrick
122646035553Spatrick
122746035553Spatrickif __name__ == '__main__':
122846035553Spatrick  main()
1229