Skip to content

Commit c2c68a5

Browse files
committed
[libc++] Improve generate_feature_test_macro_components.py.
This improves the naming of the fields `depends`/`internal_depends`. It also adds the documentation for this script. The changes are based on D99290 and its review comments. Differential Revision: https://reviews.llvm.org/D99615
1 parent e92d2b8 commit c2c68a5

File tree

1 file changed

+87
-54
lines changed

1 file changed

+87
-54
lines changed

libcxx/utils/generate_feature_test_macro_components.py

Lines changed: 87 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,45 @@ def add_version_header(tc):
2929
tc["headers"].append("version")
3030
return tc
3131

32+
# ================ ============================================================
33+
# Field Description
34+
# ================ ============================================================
35+
# name The name of the feature-test macro.
36+
# values A dict whose keys are C++ versions and whose values are the
37+
# value of the feature-test macro for that C++ version.
38+
# (TODO: This isn't a very clean model for feature-test
39+
# macros affected by multiple papers.)
40+
# headers An array with the headers that should provide the
41+
# feature-test macro.
42+
# test_suite_guard An optional string field. When this field is provided,
43+
# `libcxx_guard` must also be provided. This field is used
44+
# only to generate the unit tests for the feature-test macros.
45+
# It can't depend on macros defined in <__config> because the
46+
# `test/std/` parts of the test suite are intended to be
47+
# portable to any C++ standard library implementation, not
48+
# just libc++. It may depend on
49+
# * macros defined by the compiler itself, or
50+
# * macros generated by CMake.
51+
# In some cases we add
52+
# `&& !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM_...)`
53+
# in order to make libc++ pass the tests on OSX; see D94983.
54+
# libcxx_guard An optional string field. When this field is provided,
55+
# `test_suite_guard` must also be provided. This field is used
56+
# only to guard the feature-test macro in <version>. It may
57+
# be the same as `test_suite_guard`, or it may depend on
58+
# macros defined in <__config>.
59+
# unimplemented An optional Boolean field with the value `True`. This field
60+
# is only used when a feature isn't fully implemented. Once
61+
# you've fully implemented the feature, you should remove
62+
# this field.
63+
# ================ ============================================================
3264
feature_test_macros = [ add_version_header(x) for x in [
3365
{
3466
"name": "__cpp_lib_addressof_constexpr",
3567
"values": { "c++17": 201603 },
3668
"headers": ["memory"],
37-
"depends": "TEST_HAS_BUILTIN(__builtin_addressof) || TEST_GCC_VER >= 700",
38-
"internal_depends": "!defined(_LIBCPP_HAS_NO_BUILTIN_ADDRESSOF)",
69+
"test_suite_guard": "TEST_HAS_BUILTIN(__builtin_addressof) || TEST_GCC_VER >= 700",
70+
"libcxx_guard": "!defined(_LIBCPP_HAS_NO_BUILTIN_ADDRESSOF)",
3971
}, {
4072
"name": "__cpp_lib_allocator_traits_is_always_equal",
4173
"values": { "c++17": 201411 },
@@ -65,60 +97,60 @@ def add_version_header(tc):
6597
"name": "__cpp_lib_atomic_flag_test",
6698
"values": { "c++20": 201907 },
6799
"headers": ["atomic"],
68-
"depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
69-
"internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
100+
"test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS)",
101+
"libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS)",
70102
}, {
71103
"name": "__cpp_lib_atomic_float",
72104
"values": { "c++20": 201711 },
73105
"headers": ["atomic"],
74-
"depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
75-
"internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
106+
"test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS)",
107+
"libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS)",
76108
"unimplemented": True,
77109
}, {
78110
"name": "__cpp_lib_atomic_is_always_lock_free",
79111
"values": { "c++17": 201603 },
80112
"headers": ["atomic"],
81-
"depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
82-
"internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
113+
"test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS)",
114+
"libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS)",
83115
}, {
84116
"name": "__cpp_lib_atomic_lock_free_type_aliases",
85117
"values": { "c++20": 201907 },
86118
"headers": ["atomic"],
87-
"depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
88-
"internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
119+
"test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS)",
120+
"libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS)",
89121
}, {
90122
"name": "__cpp_lib_atomic_ref",
91123
"values": { "c++20": 201806 },
92124
"headers": ["atomic"],
93-
"depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
94-
"internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
125+
"test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS)",
126+
"libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS)",
95127
"unimplemented": True,
96128
}, {
97129
"name": "__cpp_lib_atomic_shared_ptr",
98130
"values": { "c++20": 201711 },
99131
"headers": ["atomic"],
100-
"depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
101-
"internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
132+
"test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS)",
133+
"libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS)",
102134
"unimplemented": True,
103135
}, {
104136
"name": "__cpp_lib_atomic_value_initialization",
105137
"values": { "c++20": 201911 },
106138
"headers": ["atomic", "memory"],
107-
"depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
108-
"internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
139+
"test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS)",
140+
"libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS)",
109141
"unimplemented": True,
110142
}, {
111143
"name": "__cpp_lib_atomic_wait",
112144
"values": { "c++20": 201907 },
113145
"headers": ["atomic"],
114-
"depends": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_atomic_wait)",
115-
"internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_atomic_wait)",
146+
"test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_atomic_wait)",
147+
"libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_atomic_wait)",
116148
}, {
117149
"name": "__cpp_lib_barrier",
118150
"values": { "c++20": 201907 },
119151
"headers": ["barrier"],
120-
"depends": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_barrier)",
121-
"internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_barrier)",
152+
"test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_barrier)",
153+
"libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_barrier)",
122154
}, {
123155
"name": "__cpp_lib_bind_front",
124156
"values": { "c++20": 201907 },
@@ -154,8 +186,8 @@ def add_version_header(tc):
154186
"name": "__cpp_lib_char8_t",
155187
"values": { "c++20": 201811 },
156188
"headers": ["atomic", "filesystem", "istream", "limits", "locale", "ostream", "string", "string_view"],
157-
"depends": "defined(__cpp_char8_t)",
158-
"internal_depends": "!defined(_LIBCPP_NO_HAS_CHAR8_T)",
189+
"test_suite_guard": "defined(__cpp_char8_t)",
190+
"libcxx_guard": "!defined(_LIBCPP_NO_HAS_CHAR8_T)",
159191
}, {
160192
"name": "__cpp_lib_chrono",
161193
"values": { "c++17": 201611 },
@@ -236,8 +268,8 @@ def add_version_header(tc):
236268
"name": "__cpp_lib_destroying_delete",
237269
"values": { "c++20": 201806 },
238270
"headers": ["new"],
239-
"depends": "TEST_STD_VER > 17 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L",
240-
"internal_depends": "_LIBCPP_STD_VER > 17 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L",
271+
"test_suite_guard": "TEST_STD_VER > 17 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L",
272+
"libcxx_guard": "_LIBCPP_STD_VER > 17 && defined(__cpp_impl_destroying_delete) && __cpp_impl_destroying_delete >= 201806L",
241273
}, {
242274
"name": "__cpp_lib_enable_shared_from_this",
243275
"values": { "c++17": 201603 },
@@ -263,8 +295,8 @@ def add_version_header(tc):
263295
"name": "__cpp_lib_filesystem",
264296
"values": { "c++17": 201703 },
265297
"headers": ["filesystem"],
266-
"depends": "!defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem)",
267-
"internal_depends": "!defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem)"
298+
"test_suite_guard": "!defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem)",
299+
"libcxx_guard": "!defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_filesystem)"
268300
}, {
269301
"name": "__cpp_lib_format",
270302
"values": { "c++20": 201907 },
@@ -291,8 +323,8 @@ def add_version_header(tc):
291323
"name": "__cpp_lib_has_unique_object_representations",
292324
"values": { "c++17": 201606 },
293325
"headers": ["type_traits"],
294-
"depends": "TEST_HAS_BUILTIN_IDENTIFIER(__has_unique_object_representations) || TEST_GCC_VER >= 700",
295-
"internal_depends": "defined(_LIBCPP_HAS_UNIQUE_OBJECT_REPRESENTATIONS)",
326+
"test_suite_guard": "TEST_HAS_BUILTIN_IDENTIFIER(__has_unique_object_representations) || TEST_GCC_VER >= 700",
327+
"libcxx_guard": "defined(_LIBCPP_HAS_UNIQUE_OBJECT_REPRESENTATIONS)",
296328
}, {
297329
"name": "__cpp_lib_hypot",
298330
"values": { "c++17": 201603 },
@@ -330,14 +362,14 @@ def add_version_header(tc):
330362
"name": "__cpp_lib_is_aggregate",
331363
"values": { "c++17": 201703 },
332364
"headers": ["type_traits"],
333-
"depends": "TEST_HAS_BUILTIN_IDENTIFIER(__is_aggregate) || TEST_GCC_VER_NEW >= 7001",
334-
"internal_depends": "!defined(_LIBCPP_HAS_NO_IS_AGGREGATE)",
365+
"test_suite_guard": "TEST_HAS_BUILTIN_IDENTIFIER(__is_aggregate) || TEST_GCC_VER_NEW >= 7001",
366+
"libcxx_guard": "!defined(_LIBCPP_HAS_NO_IS_AGGREGATE)",
335367
}, {
336368
"name": "__cpp_lib_is_constant_evaluated",
337369
"values": { "c++20": 201811 },
338370
"headers": ["type_traits"],
339-
"depends": "TEST_HAS_BUILTIN(__builtin_is_constant_evaluated) || TEST_GCC_VER >= 900",
340-
"internal_depends": "!defined(_LIBCPP_HAS_NO_BUILTIN_IS_CONSTANT_EVALUATED)",
371+
"test_suite_guard": "TEST_HAS_BUILTIN(__builtin_is_constant_evaluated) || TEST_GCC_VER >= 900",
372+
"libcxx_guard": "!defined(_LIBCPP_HAS_NO_BUILTIN_IS_CONSTANT_EVALUATED)",
341373
}, {
342374
"name": "__cpp_lib_is_final",
343375
"values": { "c++14": 201402 },
@@ -376,15 +408,15 @@ def add_version_header(tc):
376408
"name": "__cpp_lib_jthread",
377409
"values": { "c++20": 201911 },
378410
"headers": ["stop_token", "thread"],
379-
"depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
380-
"internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
411+
"test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS)",
412+
"libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS)",
381413
"unimplemented": True,
382414
}, {
383415
"name": "__cpp_lib_latch",
384416
"values": { "c++20": 201907 },
385417
"headers": ["latch"],
386-
"depends": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_latch)",
387-
"internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_latch)",
418+
"test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_latch)",
419+
"libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_latch)",
388420
}, {
389421
"name": "__cpp_lib_launder",
390422
"values": { "c++17": 201606 },
@@ -417,8 +449,8 @@ def add_version_header(tc):
417449
"name": "__cpp_lib_math_constants",
418450
"values": { "c++20": 201907 },
419451
"headers": ["numbers"],
420-
"depends": "defined(__cpp_concepts) && __cpp_concepts >= 201907L",
421-
"internal_depends": "!defined(_LIBCPP_HAS_NO_CONCEPTS)",
452+
"test_suite_guard": "defined(__cpp_concepts) && __cpp_concepts >= 201907L",
453+
"libcxx_guard": "!defined(_LIBCPP_HAS_NO_CONCEPTS)",
422454
}, {
423455
"name": "__cpp_lib_math_special_functions",
424456
"values": { "c++17": 201603 },
@@ -496,14 +528,14 @@ def add_version_header(tc):
496528
"name": "__cpp_lib_semaphore",
497529
"values": { "c++20": 201907 },
498530
"headers": ["semaphore"],
499-
"depends": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_semaphore)",
500-
"internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_semaphore)",
531+
"test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_semaphore)",
532+
"libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_semaphore)",
501533
}, {
502534
"name": "__cpp_lib_shared_mutex",
503535
"values": { "c++17": 201505 },
504536
"headers": ["shared_mutex"],
505-
"depends": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_mutex)",
506-
"internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_mutex)",
537+
"test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_mutex)",
538+
"libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_mutex)",
507539
}, {
508540
"name": "__cpp_lib_shared_ptr_arrays",
509541
"values": { "c++17": 201611 },
@@ -516,8 +548,8 @@ def add_version_header(tc):
516548
"name": "__cpp_lib_shared_timed_mutex",
517549
"values": { "c++14": 201402 },
518550
"headers": ["shared_mutex"],
519-
"depends": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex)",
520-
"internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex)",
551+
"test_suite_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex)",
552+
"libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && !defined(_LIBCPP_AVAILABILITY_DISABLE_FTM___cpp_lib_shared_timed_mutex)",
521553
}, {
522554
"name": "__cpp_lib_shift",
523555
"values": { "c++20": 201806 },
@@ -638,6 +670,8 @@ def add_version_header(tc):
638670

639671
assert feature_test_macros == sorted(feature_test_macros, key=lambda tc: tc["name"])
640672
assert all(tc["headers"] == sorted(tc["headers"]) for tc in feature_test_macros)
673+
assert all(("libcxx_guard" in tc) == ("test_suite_guard" in tc) for tc in feature_test_macros)
674+
assert all(all(key in ["name", "values", "headers", "libcxx_guard", "test_suite_guard", "unimplemented"] for key in tc.keys()) for tc in feature_test_macros)
641675

642676
# Map from each header to the Lit annotations that should be used for
643677
# tests that include that header.
@@ -721,12 +755,11 @@ def produce_macros_definition_for_std(std):
721755
if std not in tc["values"]:
722756
continue
723757
inner_indent = 1
724-
if 'depends' in tc.keys():
725-
assert 'internal_depends' in tc.keys()
726-
result += "# if %s\n" % tc["internal_depends"]
758+
if 'test_suite_guard' in tc.keys():
759+
result += "# if %s\n" % tc["libcxx_guard"]
727760
inner_indent += 2
728761
if get_value_before(tc["values"], std) is not None:
729-
assert 'depends' not in tc.keys()
762+
assert 'test_suite_guard' not in tc.keys()
730763
result += "# undef %s\n" % tc["name"]
731764
line = "#%sdefine %s" % ((" " * inner_indent), tc["name"])
732765
line += " " * (indent - len(line))
@@ -735,7 +768,7 @@ def produce_macros_definition_for_std(std):
735768
line = "// " + line
736769
result += line
737770
result += "\n"
738-
if 'depends' in tc.keys():
771+
if 'test_suite_guard' in tc.keys():
739772
result += "# endif\n"
740773
return result.strip()
741774

@@ -847,8 +880,8 @@ def produce_version_header():
847880
# endif
848881
""",
849882

850-
"depends": """
851-
# if {depends}
883+
"test_suite_guard": """
884+
# if {test_suite_guard}
852885
# ifndef {name}
853886
# error "{name} should be defined in {std}"
854887
# endif
@@ -857,7 +890,7 @@ def produce_version_header():
857890
# endif
858891
# else
859892
# ifdef {name}
860-
# error "{name} should not be defined when {depends} is not defined!"
893+
# error "{name} should not be defined when {test_suite_guard} is not defined!"
861894
# endif
862895
# endif
863896
""",
@@ -897,8 +930,8 @@ def generate_std_test(test_list, std):
897930
result += test_types["undefined"].format(name=tc["name"], std_first=get_first_std(tc["values"]))
898931
elif 'unimplemented' in tc.keys():
899932
result += test_types["unimplemented"].format(name=tc["name"], value=val, std=std)
900-
elif "depends" in tc.keys():
901-
result += test_types["depends"].format(name=tc["name"], value=val, std=std, depends=tc["depends"])
933+
elif "test_suite_guard" in tc.keys():
934+
result += test_types["test_suite_guard"].format(name=tc["name"], value=val, std=std, test_suite_guard=tc["test_suite_guard"])
902935
else:
903936
result += test_types["defined"].format(name=tc["name"], value=val, std=std)
904937
return result.strip()

0 commit comments

Comments
 (0)