Skip to content

Commit c4a42f6

Browse files
authored
[libc++] Fix the declarative generation of FTMs (#108843)
We were incorrectly computing whether a FTM has been implemented. Instead of checking whether any version of the FTM is implemented for the current Standard, we need to make sure that the correct version of the FTM has been implemented. As a drive-by fix, also correctly close the file that we load JSON from, which was forgotten.
1 parent 1ebe16b commit c4a42f6

7 files changed

+177
-99
lines changed

libcxx/test/libcxx/feature_test_macro/ftm_metadata.sh.py

+5
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,10 @@ def test(output, expected):
4747
"test_suite_guard": None,
4848
"libcxx_guard": None,
4949
},
50+
"__cpp_lib_missing_FTM_in_older_standard": {
51+
"headers": [],
52+
"test_suite_guard": None,
53+
"libcxx_guard": None,
54+
},
5055
},
5156
)

libcxx/test/libcxx/feature_test_macro/implemented_ftms.sh.py

+5
Original file line numberDiff line numberDiff line change
@@ -50,5 +50,10 @@ def test(output, expected):
5050
"c++23": "202102L",
5151
"c++26": "202102L",
5252
},
53+
"__cpp_lib_missing_FTM_in_older_standard": {
54+
"c++17": None,
55+
"c++20": None,
56+
"c++26": None,
57+
},
5358
},
5459
)

libcxx/test/libcxx/feature_test_macro/standard_ftms.sh.py

+6
Original file line numberDiff line numberDiff line change
@@ -50,5 +50,11 @@ def test(output, expected):
5050
"c++23": "202106L",
5151
"c++26": "202306L",
5252
},
53+
"__cpp_lib_missing_FTM_in_older_standard": {
54+
"c++17": "2017L",
55+
"c++20": "2020L",
56+
"c++23": "2020L",
57+
"c++26": "2026L",
58+
},
5359
},
5460
)

libcxx/test/libcxx/feature_test_macro/test_data.json

+30
Original file line numberDiff line numberDiff line change
@@ -154,5 +154,35 @@
154154
"headers": [
155155
"variant"
156156
]
157+
},
158+
{
159+
"name": "__cpp_lib_missing_FTM_in_older_standard",
160+
"values": {
161+
"c++17": {
162+
"2017": [
163+
{
164+
"title": "Some FTM missing a paper in an older Standard mode, which should result in the FTM never being defined.",
165+
"implemented": false
166+
}
167+
]
168+
},
169+
"c++20": {
170+
"2020": [
171+
{
172+
"title": "",
173+
"implemented": true
174+
}
175+
]
176+
},
177+
"c++26": {
178+
"2026": [
179+
{
180+
"title": "",
181+
"implemented": true
182+
}
183+
]
184+
}
185+
},
186+
"headers": []
157187
}
158188
]

libcxx/test/libcxx/feature_test_macro/version_header.sh.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,16 @@ def test(output, expected):
4343
# define __cpp_lib_any 201606L
4444
# define __cpp_lib_parallel_algorithm 201603L
4545
# define __cpp_lib_variant 202102L
46+
// define __cpp_lib_missing_FTM_in_older_standard 2017L
4647
#endif // _LIBCPP_STD_VER >= 17
4748
4849
#if _LIBCPP_STD_VER >= 20
4950
# if !defined(_LIBCPP_HAS_NO_THREADS) && _LIBCPP_AVAILABILITY_HAS_SYNC
5051
# define __cpp_lib_barrier 201907L
5152
# endif
5253
// define __cpp_lib_format 202110L
53-
# undef __cpp_lib_variant
54-
# define __cpp_lib_variant 202106L
54+
// define __cpp_lib_variant 202106L
55+
// define __cpp_lib_missing_FTM_in_older_standard 2020L
5556
#endif // _LIBCPP_STD_VER >= 20
5657
5758
#if _LIBCPP_STD_VER >= 23
@@ -64,8 +65,8 @@ def test(output, expected):
6465
# define __cpp_lib_barrier 299900L
6566
# endif
6667
// define __cpp_lib_format 202311L
67-
# undef __cpp_lib_variant
68-
# define __cpp_lib_variant 202306L
68+
// define __cpp_lib_variant 202306L
69+
// define __cpp_lib_missing_FTM_in_older_standard 2026L
6970
#endif // _LIBCPP_STD_VER >= 26
7071
7172
#endif // _LIBCPP_VERSION

libcxx/test/libcxx/feature_test_macro/version_header_implementation.sh.py

+120-89
Original file line numberDiff line numberDiff line change
@@ -9,106 +9,137 @@
99
# RUN: %{python} %s %{libcxx-dir}/utils %{libcxx-dir}/test/libcxx/feature_test_macro/test_data.json
1010

1111
import sys
12+
import unittest
1213

13-
sys.path.append(sys.argv[1])
14-
from generate_feature_test_macro_components import FeatureTestMacros
15-
14+
UTILS = sys.argv[1]
15+
TEST_DATA = sys.argv[2]
16+
del sys.argv[1:3]
1617

17-
def test(output, expected):
18-
assert output == expected, f"expected\n{expected}\n\noutput\n{output}"
18+
sys.path.append(UTILS)
19+
from generate_feature_test_macro_components import FeatureTestMacros
1920

21+
class Test(unittest.TestCase):
22+
def setUp(self):
23+
self.ftm = FeatureTestMacros(TEST_DATA)
24+
self.maxDiff = None # This causes the diff to be printed when the test fails
2025

21-
ftm = FeatureTestMacros(sys.argv[2])
22-
test(
23-
ftm.version_header_implementation,
24-
{
25-
"17": [
26-
{
27-
"__cpp_lib_any": {
28-
"value": "201606L",
29-
"implemented": True,
30-
"need_undef": False,
31-
"condition": None,
26+
def test_implementation(self):
27+
expected = {
28+
"17": [
29+
{
30+
"__cpp_lib_any": {
31+
"value": "201606L",
32+
"implemented": True,
33+
"need_undef": False,
34+
"condition": None,
35+
},
36+
},
37+
{
38+
"__cpp_lib_parallel_algorithm": {
39+
"value": "201603L",
40+
"implemented": True,
41+
"need_undef": False,
42+
"condition": None,
43+
},
3244
},
33-
},
34-
{
35-
"__cpp_lib_parallel_algorithm": {
36-
"value": "201603L",
37-
"implemented": True,
38-
"need_undef": False,
39-
"condition": None,
45+
{
46+
"__cpp_lib_variant": {
47+
"value": "202102L",
48+
"implemented": True,
49+
"need_undef": False,
50+
"condition": None,
51+
},
4052
},
41-
},
42-
{
43-
"__cpp_lib_variant": {
44-
"value": "202102L",
45-
"implemented": True,
46-
"need_undef": False,
47-
"condition": None,
53+
{
54+
"__cpp_lib_missing_FTM_in_older_standard": {
55+
"value": "2017L",
56+
"implemented": False,
57+
"need_undef": False,
58+
"condition": None,
59+
},
4860
},
49-
},
50-
],
51-
"20": [
52-
{
53-
"__cpp_lib_barrier": {
54-
"value": "201907L",
55-
"implemented": True,
56-
"need_undef": False,
57-
"condition": "!defined(_LIBCPP_HAS_NO_THREADS) && _LIBCPP_AVAILABILITY_HAS_SYNC",
61+
],
62+
"20": [
63+
{
64+
"__cpp_lib_barrier": {
65+
"value": "201907L",
66+
"implemented": True,
67+
"need_undef": False,
68+
"condition": "!defined(_LIBCPP_HAS_NO_THREADS) && _LIBCPP_AVAILABILITY_HAS_SYNC",
69+
},
5870
},
59-
},
60-
{
61-
"__cpp_lib_format": {
62-
"value": "202110L",
63-
"implemented": False,
64-
"need_undef": False,
65-
"condition": None,
71+
{
72+
"__cpp_lib_format": {
73+
"value": "202110L",
74+
"implemented": False,
75+
"need_undef": False,
76+
"condition": None,
77+
},
6678
},
67-
},
68-
{
69-
"__cpp_lib_variant": {
70-
"value": "202106L",
71-
"implemented": True,
72-
"need_undef": True,
73-
"condition": None,
79+
{
80+
"__cpp_lib_variant": {
81+
"value": "202106L",
82+
"implemented": False,
83+
"need_undef": False,
84+
"condition": None,
85+
},
7486
},
75-
},
76-
],
77-
"23": [
78-
{
79-
"__cpp_lib_format": {
80-
"value": "202207L",
81-
"implemented": False,
82-
"need_undef": False,
83-
"condition": None,
87+
{
88+
"__cpp_lib_missing_FTM_in_older_standard": {
89+
"value": "2020L",
90+
"implemented": False,
91+
"need_undef": False,
92+
"condition": None,
93+
},
8494
},
85-
},
86-
],
87-
"26": [
88-
{
89-
"__cpp_lib_barrier": {
90-
"value": "299900L",
91-
"implemented": True,
92-
"need_undef": True,
93-
"condition": "!defined(_LIBCPP_HAS_NO_THREADS) && _LIBCPP_AVAILABILITY_HAS_SYNC",
95+
],
96+
"23": [
97+
{
98+
"__cpp_lib_format": {
99+
"value": "202207L",
100+
"implemented": False,
101+
"need_undef": False,
102+
"condition": None,
103+
},
94104
},
95-
},
96-
{
97-
"__cpp_lib_format": {
98-
"value": "202311L",
99-
"implemented": False,
100-
"need_undef": False,
101-
"condition": None,
105+
],
106+
"26": [
107+
{
108+
"__cpp_lib_barrier": {
109+
"value": "299900L",
110+
"implemented": True,
111+
"need_undef": True,
112+
"condition": "!defined(_LIBCPP_HAS_NO_THREADS) && _LIBCPP_AVAILABILITY_HAS_SYNC",
113+
},
102114
},
103-
},
104-
{
105-
"__cpp_lib_variant": {
106-
"value": "202306L",
107-
"implemented": True,
108-
"need_undef": True,
109-
"condition": None,
115+
{
116+
"__cpp_lib_format": {
117+
"value": "202311L",
118+
"implemented": False,
119+
"need_undef": False,
120+
"condition": None,
121+
},
110122
},
111-
},
112-
],
113-
},
114-
)
123+
{
124+
"__cpp_lib_variant": {
125+
"value": "202306L",
126+
"implemented": False,
127+
"need_undef": False,
128+
"condition": None,
129+
},
130+
},
131+
{
132+
"__cpp_lib_missing_FTM_in_older_standard": {
133+
"value": "2026L",
134+
"implemented": False,
135+
"need_undef": False,
136+
"condition": None,
137+
},
138+
},
139+
],
140+
}
141+
142+
self.assertEqual(self.ftm.version_header_implementation, expected)
143+
144+
if __name__ == '__main__':
145+
unittest.main()

libcxx/utils/generate_feature_test_macro_components.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -2102,7 +2102,8 @@ class FeatureTestMacros:
21022102

21032103
def __init__(self, filename: str):
21042104
"""Initializes the class with the JSON data in the file 'filename'."""
2105-
self.__data = json.load(open(filename))
2105+
with open(filename) as f:
2106+
self.__data = json.load(f)
21062107

21072108
@functools.cached_property
21082109
def std_dialects(self) -> List[str]:
@@ -2187,8 +2188,8 @@ def version_header_implementation(self) -> Dict[str, List[Dict[str, Any]]]:
21872188
result[get_std_number(std)] = list()
21882189

21892190
for ftm, values in self.standard_ftms.items():
2190-
need_undef = False
21912191
last_value = None
2192+
last_entry = None
21922193
for std, value in values.items():
21932194
# When a newer Standard does not change the value of the macro
21942195
# there is no need to redefine it with the same value.
@@ -2198,12 +2199,11 @@ def version_header_implementation(self) -> Dict[str, List[Dict[str, Any]]]:
21982199

21992200
entry = dict()
22002201
entry["value"] = value
2201-
entry["implemented"] = self.implemented_ftms[ftm][std] != None
2202-
entry["need_undef"] = need_undef
2202+
entry["implemented"] = self.implemented_ftms[ftm][std] == self.standard_ftms[ftm][std]
2203+
entry["need_undef"] = last_entry is not None and last_entry["implemented"] and entry["implemented"]
22032204
entry["condition"] = self.ftm_metadata[ftm]["libcxx_guard"]
22042205

2205-
need_undef = entry["implemented"]
2206-
2206+
last_entry = entry
22072207
result[get_std_number(std)].append(dict({ftm: entry}))
22082208

22092209
return result

0 commit comments

Comments
 (0)