blob: 96860c2118c22d5beeca52ebbfbac94bb2f9a755 [file] [log] [blame]
Eric Fiselier32784a72019-01-16 01:37:43 +00001#!/usr/bin/env python
2
3import os
4import tempfile
Louis Dionnefd02a462019-11-06 16:44:14 +00005from builtins import int, range
6from functools import reduce
Eric Fiselier32784a72019-01-16 01:37:43 +00007
8def get_libcxx_paths():
Eric Fiselier508da412019-02-02 23:13:49 +00009 utils_path = os.path.dirname(os.path.abspath(__file__))
Eric Fiselier973eab82019-01-16 05:43:02 +000010 script_name = os.path.basename(__file__)
Eric Fiselier508da412019-02-02 23:13:49 +000011 assert os.path.exists(utils_path)
12 src_root = os.path.dirname(utils_path)
Eric Fiselier32784a72019-01-16 01:37:43 +000013 include_path = os.path.join(src_root, 'include')
14 assert os.path.exists(include_path)
15 docs_path = os.path.join(src_root, 'docs')
16 assert os.path.exists(docs_path)
Eric Fiselier508da412019-02-02 23:13:49 +000017 macro_test_path = os.path.join(src_root, 'test', 'std', 'language.support',
18 'support.limits', 'support.limits.general')
19 assert os.path.exists(macro_test_path)
20 assert os.path.exists(os.path.join(macro_test_path, 'version.version.pass.cpp'))
21 return script_name, src_root, include_path, docs_path, macro_test_path
Eric Fiselier32784a72019-01-16 01:37:43 +000022
23
Eric Fiselier508da412019-02-02 23:13:49 +000024script_name, source_root, include_path, docs_path, macro_test_path = get_libcxx_paths()
Eric Fiselier32784a72019-01-16 01:37:43 +000025
26def has_header(h):
27 h_path = os.path.join(include_path, h)
28 return os.path.exists(h_path)
29
30def add_version_header(tc):
31 tc["headers"].append("version")
32 return tc
33
34feature_test_macros = sorted([ add_version_header(x) for x in [
35 # C++14 macros
36 {"name": "__cpp_lib_integer_sequence",
37 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +000038 "c++14": int(201304)
Eric Fiselier32784a72019-01-16 01:37:43 +000039 },
40 "headers": ["utility"],
41 },
42 {"name": "__cpp_lib_exchange_function",
43 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +000044 "c++14": int(201304)
Eric Fiselier32784a72019-01-16 01:37:43 +000045 },
46 "headers": ["utility"],
47 },
48 {"name": "__cpp_lib_tuples_by_type",
49 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +000050 "c++14": int(201304)
Eric Fiselier32784a72019-01-16 01:37:43 +000051 },
52 "headers": ["utility", "tuple"],
53 },
54 {"name": "__cpp_lib_tuple_element_t",
55 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +000056 "c++14": int(201402)
Eric Fiselier32784a72019-01-16 01:37:43 +000057 },
58 "headers": ["tuple"],
59 },
60 {"name": "__cpp_lib_make_unique",
61 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +000062 "c++14": int(201304)
Eric Fiselier32784a72019-01-16 01:37:43 +000063 },
64 "headers": ["memory"],
65 },
66 {"name": "__cpp_lib_transparent_operators",
67 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +000068 "c++14": int(201210),
69 "c++17": int(201510),
Eric Fiselier32784a72019-01-16 01:37:43 +000070 },
71 "headers": ["functional"],
72 },
73 {"name": "__cpp_lib_integral_constant_callable",
74 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +000075 "c++14": int(201304)
Eric Fiselier32784a72019-01-16 01:37:43 +000076 },
77 "headers": ["type_traits"],
78 },
79 {"name": "__cpp_lib_transformation_trait_aliases",
80 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +000081 "c++14": int(201304),
Eric Fiselier32784a72019-01-16 01:37:43 +000082 },
83 "headers": ["type_traits"]
84 },
85 {"name": "__cpp_lib_result_of_sfinae",
86 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +000087 "c++14": int(201210),
Eric Fiselier32784a72019-01-16 01:37:43 +000088 },
89 "headers": ["functional", "type_traits"]
90 },
91 {"name": "__cpp_lib_is_final",
92 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +000093 "c++14": int(201402),
Eric Fiselier32784a72019-01-16 01:37:43 +000094 },
95 "headers": ["type_traits"]
96 },
97 {"name": "__cpp_lib_is_null_pointer",
98 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +000099 "c++14": int(201309),
Eric Fiselier32784a72019-01-16 01:37:43 +0000100 },
101 "headers": ["type_traits"]
102 },
103 {"name": "__cpp_lib_chrono_udls",
104 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000105 "c++14": int(201304),
Eric Fiselier32784a72019-01-16 01:37:43 +0000106 },
107 "headers": ["chrono"]
108 },
109 {"name": "__cpp_lib_string_udls",
110 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000111 "c++14": int(201304),
Eric Fiselier32784a72019-01-16 01:37:43 +0000112 },
113 "headers": ["string"]
114 },
115 {"name": "__cpp_lib_generic_associative_lookup",
116 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000117 "c++14": int(201304),
Eric Fiselier32784a72019-01-16 01:37:43 +0000118 },
119 "headers": ["map", "set"]
120 },
121 {"name": "__cpp_lib_null_iterators",
122 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000123 "c++14": int(201304),
Eric Fiselier32784a72019-01-16 01:37:43 +0000124 },
125 "headers": ["iterator"]
126 },
127 {"name": "__cpp_lib_make_reverse_iterator",
128 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000129 "c++14": int(201402),
Eric Fiselier32784a72019-01-16 01:37:43 +0000130 },
131 "headers": ["iterator"]
132 },
133 {"name": "__cpp_lib_robust_nonmodifying_seq_ops",
134 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000135 "c++14": int(201304),
Eric Fiselier32784a72019-01-16 01:37:43 +0000136 },
137 "headers": ["algorithm"]
138 },
139 {"name": "__cpp_lib_complex_udls",
140 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000141 "c++14": int(201309),
Eric Fiselier32784a72019-01-16 01:37:43 +0000142 },
143 "headers": ["complex"]
144 },
145 {"name": "__cpp_lib_quoted_string_io",
146 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000147 "c++14": int(201304),
Eric Fiselier32784a72019-01-16 01:37:43 +0000148 },
149 "headers": ["iomanip"]
150 },
151 {"name": "__cpp_lib_shared_timed_mutex",
152 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000153 "c++14": int(201402),
Eric Fiselier32784a72019-01-16 01:37:43 +0000154 },
Eric Fiselier05019eb2019-01-16 02:10:28 +0000155 "headers": ["shared_mutex"],
156 "depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
157 "internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
Eric Fiselier32784a72019-01-16 01:37:43 +0000158 },
159 # C++17 macros
160 {"name": "__cpp_lib_atomic_is_always_lock_free",
161 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000162 "c++17": int(201603),
Eric Fiselier32784a72019-01-16 01:37:43 +0000163 },
Eric Fiselier05019eb2019-01-16 02:10:28 +0000164 "headers": ["atomic"],
165 "depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
166 "internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
Eric Fiselier32784a72019-01-16 01:37:43 +0000167 },
168 {"name": "__cpp_lib_filesystem",
169 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000170 "c++17": int(201703),
Eric Fiselier32784a72019-01-16 01:37:43 +0000171 },
172 "headers": ["filesystem"]
173 },
174 {"name": "__cpp_lib_invoke",
175 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000176 "c++17": int(201411),
Eric Fiselier32784a72019-01-16 01:37:43 +0000177 },
178 "headers": ["functional"]
179 },
180 {"name": "__cpp_lib_void_t",
181 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000182 "c++17": int(201411),
Eric Fiselier32784a72019-01-16 01:37:43 +0000183 },
184 "headers": ["type_traits"]
185 },
186 {"name": "__cpp_lib_node_extract",
187 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000188 "c++17": int(201606),
Eric Fiselier32784a72019-01-16 01:37:43 +0000189 },
190 "headers": ["map", "set", "unordered_map", "unordered_set"]
191 },
192 {"name": "__cpp_lib_byte",
193 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000194 "c++17": int(201603),
Eric Fiselier32784a72019-01-16 01:37:43 +0000195 },
196 "headers": ["cstddef"],
197 },
198 {"name": "__cpp_lib_hardware_interference_size",
199 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000200 "c++17": int(201703),
Eric Fiselier32784a72019-01-16 01:37:43 +0000201 },
202 "headers": ["new"],
203 },
204 {"name": "__cpp_lib_launder",
205 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000206 "c++17": int(201606),
Eric Fiselier32784a72019-01-16 01:37:43 +0000207 },
208 "headers": ["new"],
209 },
210 {"name": "__cpp_lib_uncaught_exceptions",
211 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000212 "c++17": int(201411),
Eric Fiselier32784a72019-01-16 01:37:43 +0000213 },
214 "headers": ["exception"],
215 },
216 {"name": "__cpp_lib_as_const",
217 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000218 "c++17": int(201510),
Eric Fiselier32784a72019-01-16 01:37:43 +0000219 },
220 "headers": ["utility"],
221 },
222 {"name": "__cpp_lib_make_from_tuple",
223 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000224 "c++17": int(201606),
Eric Fiselier32784a72019-01-16 01:37:43 +0000225 },
226 "headers": ["tuple"],
227 },
228 {"name": "__cpp_lib_apply",
229 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000230 "c++17": int(201603),
Eric Fiselier32784a72019-01-16 01:37:43 +0000231 },
232 "headers": ["tuple"],
233 },
234 {"name": "__cpp_lib_optional",
235 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000236 "c++17": int(201606),
Eric Fiselier32784a72019-01-16 01:37:43 +0000237 },
238 "headers": ["optional"],
239 },
240 {"name": "__cpp_lib_variant",
241 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000242 "c++17": int(201606),
Eric Fiselier32784a72019-01-16 01:37:43 +0000243 },
244 "headers": ["variant"],
245 },
246 {"name": "__cpp_lib_any",
247 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000248 "c++17": int(201606),
Eric Fiselier32784a72019-01-16 01:37:43 +0000249 },
250 "headers": ["any"],
251 },
252 {"name": "__cpp_lib_addressof_constexpr",
253 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000254 "c++17": int(201603),
Eric Fiselier32784a72019-01-16 01:37:43 +0000255 },
256 "headers": ["memory"],
257 "depends": "TEST_HAS_BUILTIN(__builtin_addressof) || TEST_GCC_VER >= 700",
258 "internal_depends": "!defined(_LIBCPP_HAS_NO_BUILTIN_ADDRESSOF)",
259 },
260 {"name": "__cpp_lib_raw_memory_algorithms",
261 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000262 "c++17": int(201606),
Eric Fiselier32784a72019-01-16 01:37:43 +0000263 },
264 "headers": ["memory"],
265 },
266 {"name": "__cpp_lib_enable_shared_from_this",
267 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000268 "c++17": int(201603),
Eric Fiselier32784a72019-01-16 01:37:43 +0000269 },
270 "headers": ["memory"],
271 },
272 {"name": "__cpp_lib_shared_ptr_weak_type",
273 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000274 "c++17": int(201606),
Eric Fiselier32784a72019-01-16 01:37:43 +0000275 },
276 "headers": ["memory"],
277 },
278 {"name": "__cpp_lib_shared_ptr_arrays",
279 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000280 "c++17": int(201611),
Eric Fiselier32784a72019-01-16 01:37:43 +0000281 },
282 "headers": ["memory"],
283 "unimplemented": True,
284 },
285 {"name": "__cpp_lib_memory_resource",
286 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000287 "c++17": int(201603),
Eric Fiselier32784a72019-01-16 01:37:43 +0000288 },
289 "headers": ["memory_resource"],
290 "unimplemented": True,
291 },
292 {"name": "__cpp_lib_boyer_moore_searcher",
293 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000294 "c++17": int(201603),
Eric Fiselier32784a72019-01-16 01:37:43 +0000295 },
296 "headers": ["functional"],
297 "unimplemented": True,
298 },
299 {"name": "__cpp_lib_not_fn",
300 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000301 "c++17": int(201603),
Eric Fiselier32784a72019-01-16 01:37:43 +0000302 },
303 "headers": ["functional"],
304 },
305 {"name": "__cpp_lib_bool_constant",
306 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000307 "c++17": int(201505),
Eric Fiselier32784a72019-01-16 01:37:43 +0000308 },
309 "headers": ["type_traits"],
310 },
311 {"name": "__cpp_lib_type_trait_variable_templates",
312 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000313 "c++17": int(201510),
Eric Fiselier32784a72019-01-16 01:37:43 +0000314 },
315 "headers": ["type_traits"],
316 },
317 {"name": "__cpp_lib_logical_traits",
318 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000319 "c++17": int(201510),
Eric Fiselier32784a72019-01-16 01:37:43 +0000320 },
321 "headers": ["type_traits"],
322 },
323 {"name": "__cpp_lib_is_swappable",
324 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000325 "c++17": int(201603),
Eric Fiselier32784a72019-01-16 01:37:43 +0000326 },
327 "headers": ["type_traits"],
328 },
329 {"name": "__cpp_lib_is_invocable",
330 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000331 "c++17": int(201703),
Eric Fiselier32784a72019-01-16 01:37:43 +0000332 },
333 "headers": ["type_traits"],
334 },
335 {"name": "__cpp_lib_has_unique_object_representations",
336 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000337 "c++17": int(201606),
Eric Fiselier32784a72019-01-16 01:37:43 +0000338 },
339 "headers": ["type_traits"],
340 "depends": "TEST_HAS_BUILTIN_IDENTIFIER(__has_unique_object_representations) || TEST_GCC_VER >= 700",
341 "internal_depends": "defined(_LIBCPP_HAS_UNIQUE_OBJECT_REPRESENTATIONS)",
342 },
343 {"name": "__cpp_lib_is_aggregate",
344 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000345 "c++17": int(201703),
Eric Fiselier32784a72019-01-16 01:37:43 +0000346 },
347 "headers": ["type_traits"],
348 "depends": "TEST_HAS_BUILTIN_IDENTIFIER(__is_aggregate) || TEST_GCC_VER_NEW >= 7001",
349 "internal_depends": "!defined(_LIBCPP_HAS_NO_IS_AGGREGATE)",
350 },
351 {"name": "__cpp_lib_chrono",
352 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000353 "c++17": int(201611),
Eric Fiselier32784a72019-01-16 01:37:43 +0000354 },
355 "headers": ["chrono"],
356 },
357 {"name": "__cpp_lib_execution",
358 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000359 "c++17": int(201603),
Eric Fiselier32784a72019-01-16 01:37:43 +0000360 },
361 "headers": ["execution"],
362 "unimplemented": True
363 },
364 {"name": "__cpp_lib_parallel_algorithm",
365 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000366 "c++17": int(201603),
Eric Fiselier32784a72019-01-16 01:37:43 +0000367 },
368 "headers": ["algorithm", "numeric"],
369 "unimplemented": True,
370 },
371 {"name": "__cpp_lib_to_chars",
372 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000373 "c++17": int(201611),
Eric Fiselier32784a72019-01-16 01:37:43 +0000374 },
375 "headers": ["utility"],
376 "unimplemented": True,
377 },
378 {"name": "__cpp_lib_string_view",
379 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000380 "c++17": int(201606),
Eric Fiselier32784a72019-01-16 01:37:43 +0000381 },
382 "headers": ["string", "string_view"],
383 },
384 {"name": "__cpp_lib_allocator_traits_is_always_equal",
385 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000386 "c++17": int(201411),
Eric Fiselier32784a72019-01-16 01:37:43 +0000387 },
388 "headers": ["memory", "scoped_allocator", "string", "deque", "forward_list", "list", "vector", "map", "set", "unordered_map", "unordered_set"],
389 },
390 {"name": "__cpp_lib_incomplete_container_elements",
391 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000392 "c++17": int(201505),
Eric Fiselier32784a72019-01-16 01:37:43 +0000393 },
394 "headers": ["forward_list", "list", "vector"],
395 },
396 {"name": "__cpp_lib_map_try_emplace",
397 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000398 "c++17": int(201411),
Eric Fiselier32784a72019-01-16 01:37:43 +0000399 },
400 "headers": ["map"],
401 },
402 {"name": "__cpp_lib_unordered_map_try_emplace",
403 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000404 "c++17": int(201411),
Eric Fiselier32784a72019-01-16 01:37:43 +0000405 },
406 "headers": ["unordered_map"],
407 },
408 {"name": "__cpp_lib_array_constexpr",
409 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000410 "c++17": int(201603),
Eric Fiselier32784a72019-01-16 01:37:43 +0000411 },
412 "headers": ["iterator", "array"],
413 },
414 {"name": "__cpp_lib_nonmember_container_access",
415 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000416 "c++17": int(201411),
Eric Fiselier32784a72019-01-16 01:37:43 +0000417 },
418 "headers": ["iterator", "array", "deque", "forward_list", "list", "map", "regex",
419 "set", "string", "unordered_map", "unordered_set", "vector"],
420 },
421 {"name": "__cpp_lib_sample",
422 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000423 "c++17": int(201603),
Eric Fiselier32784a72019-01-16 01:37:43 +0000424 },
425 "headers": ["algorithm"],
426 },
427 {"name": "__cpp_lib_clamp",
428 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000429 "c++17": int(201603),
Eric Fiselier32784a72019-01-16 01:37:43 +0000430 },
431 "headers": ["algorithm"],
432 },
433 {"name": "__cpp_lib_gcd_lcm",
434 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000435 "c++17": int(201606),
Eric Fiselier32784a72019-01-16 01:37:43 +0000436 },
437 "headers": ["numeric"],
438 },
439 {"name": "__cpp_lib_hypot",
440 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000441 "c++17": int(201603),
Eric Fiselier32784a72019-01-16 01:37:43 +0000442 },
443 "headers": ["cmath"],
444 },
445 {"name": "__cpp_lib_math_special_functions",
446 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000447 "c++17": int(201603),
Eric Fiselier32784a72019-01-16 01:37:43 +0000448 },
449 "headers": ["cmath"],
450 "unimplemented": True,
451 },
452 {"name": "__cpp_lib_shared_mutex",
453 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000454 "c++17": int(201505),
Eric Fiselier32784a72019-01-16 01:37:43 +0000455 },
456 "headers": ["shared_mutex"],
Eric Fiselier05019eb2019-01-16 02:10:28 +0000457 "depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
458 "internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
Eric Fiselier32784a72019-01-16 01:37:43 +0000459 },
460 {"name": "__cpp_lib_scoped_lock",
461 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000462 "c++17": int(201703),
Eric Fiselier32784a72019-01-16 01:37:43 +0000463 },
464 "headers": ["mutex"],
465 },
466 # C++2a
467 {"name": "__cpp_lib_char8_t",
468 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000469 "c++2a": int(201811),
Eric Fiselier32784a72019-01-16 01:37:43 +0000470 },
471 "headers": ["atomic", "filesystem", "istream", "limits", "locale", "ostream",
472 "string", "string_view"],
473 "depends": "defined(__cpp_char8_t)",
474 "internal_depends": "!defined(_LIBCPP_NO_HAS_CHAR8_T)",
475 },
476 {"name": "__cpp_lib_erase_if",
477 "values": {
Marek Kurdej3e895082020-05-02 13:58:03 +0200478 "c++2a": int(202002),
Eric Fiselier32784a72019-01-16 01:37:43 +0000479 },
480 "headers": ["string", "deque", "forward_list", "list", "vector", "map",
481 "set", "unordered_map", "unordered_set"]
482 },
483 {"name": "__cpp_lib_destroying_delete",
484 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000485 "c++2a": int(201806),
Eric Fiselier32784a72019-01-16 01:37:43 +0000486 },
487 "headers": ["new"],
Eric Fiselierae02e892019-05-23 23:46:44 +0000488 "depends":
489 "TEST_STD_VER > 17"
490 " && defined(__cpp_impl_destroying_delete)"
491 " && __cpp_impl_destroying_delete >= 201806L",
492 "internal_depends":
493 "_LIBCPP_STD_VER > 17"
494 " && defined(__cpp_impl_destroying_delete)"
495 " && __cpp_impl_destroying_delete >= 201806L",
Eric Fiselier32784a72019-01-16 01:37:43 +0000496 },
497 {"name": "__cpp_lib_three_way_comparison",
498 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000499 "c++2a": int(201711),
Eric Fiselier32784a72019-01-16 01:37:43 +0000500 },
501 "headers": ["compare"],
502 "unimplemented": True,
503 },
504 {"name": "__cpp_lib_concepts",
505 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000506 "c++2a": int(201806),
Eric Fiselier32784a72019-01-16 01:37:43 +0000507 },
508 "headers": ["concepts"],
509 "unimplemented": True,
510 },
511 {"name": "__cpp_lib_constexpr_swap_algorithms",
512 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000513 "c++2a": int(201806),
Eric Fiselier32784a72019-01-16 01:37:43 +0000514 },
515 "headers": ["algorithm"],
516 "unimplemented": True,
517 },
518 {"name": "__cpp_lib_constexpr_misc",
519 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000520 "c++2a": int(201811),
Eric Fiselier32784a72019-01-16 01:37:43 +0000521 },
522 "headers": ["array", "functional", "iterator", "string_view", "tuple", "utility"],
523 "unimplemented": True,
524 },
525 {"name": "__cpp_lib_bind_front",
526 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000527 "c++2a": int(201811),
Eric Fiselier32784a72019-01-16 01:37:43 +0000528 },
529 "headers": ["functional"],
530 "unimplemented": True,
531 },
532 {"name": "__cpp_lib_is_constant_evaluated",
533 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000534 "c++2a": int(201811),
Eric Fiselier32784a72019-01-16 01:37:43 +0000535 },
536 "headers": ["type_traits"],
Eric Fiselier2fc5a782019-04-24 17:54:25 +0000537 "depends": "TEST_HAS_BUILTIN(__builtin_is_constant_evaluated) || TEST_GCC_VER >= 900",
538 "internal_depends": "!defined(_LIBCPP_HAS_NO_BUILTIN_IS_CONSTANT_EVALUATED)",
Eric Fiselier32784a72019-01-16 01:37:43 +0000539 },
540 {"name": "__cpp_lib_list_remove_return_type",
541 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000542 "c++2a": int(201806),
Eric Fiselier32784a72019-01-16 01:37:43 +0000543 },
544 "headers": ["forward_list", "list"],
Eric Fiselier32784a72019-01-16 01:37:43 +0000545 },
546 {"name": "__cpp_lib_generic_unordered_lookup",
547 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000548 "c++2a": int(201811),
Eric Fiselier32784a72019-01-16 01:37:43 +0000549 },
550 "headers": ["unordered_map", "unordered_set"],
551 "unimplemented": True,
552 },
553 {"name": "__cpp_lib_ranges",
554 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000555 "c++2a": int(201811),
Eric Fiselier32784a72019-01-16 01:37:43 +0000556 },
557 "headers": ["algorithm", "functional", "iterator", "memory", "ranges"],
558 "unimplemented": True,
559 },
560 {"name": "__cpp_lib_bit_cast",
561 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000562 "c++2a": int(201806),
Eric Fiselier32784a72019-01-16 01:37:43 +0000563 },
564 "headers": ["bit"],
565 "unimplemented": True,
566 },
567 {"name": "__cpp_lib_atomic_ref",
568 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000569 "c++2a": int(201806),
Eric Fiselier32784a72019-01-16 01:37:43 +0000570 },
571 "headers": ["atomic"],
572 "unimplemented": True,
Eric Fiselier05019eb2019-01-16 02:10:28 +0000573 "depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
574 "internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
Eric Fiselier32784a72019-01-16 01:37:43 +0000575 },
Marshall Clowd3d0ecb2019-04-25 12:11:43 +0000576 {"name": "__cpp_lib_interpolate",
577 "values": {
Louis Dionnefd02a462019-11-06 16:44:14 +0000578 "c++2a": int(201902),
Marshall Clowd3d0ecb2019-04-25 12:11:43 +0000579 },
580 "headers": ["numeric"],
581 },
Louis Dionne8b77a3a2019-11-14 08:54:23 -0500582 {"name": "__cpp_lib_endian",
583 "values": {
584 "c++2a": int(201907),
585 },
586 "headers": ["bit"],
587 },
Marek Kurdeje93e58c2020-01-30 13:27:35 +0100588 {"name": "__cpp_lib_to_array",
589 "values": {
Marek Kurdej3e895082020-05-02 13:58:03 +0200590 "c++2a": int(201907),
Marek Kurdeje93e58c2020-01-30 13:27:35 +0100591 },
592 "headers": ["array"],
593 },
Eric Fiselier32784a72019-01-16 01:37:43 +0000594]], key=lambda tc: tc["name"])
595
596def get_std_dialects():
597 std_dialects = ['c++14', 'c++17', 'c++2a']
598 return list(std_dialects)
599
600def get_first_std(d):
601 for s in get_std_dialects():
602 if s in d.keys():
603 return s
604 return None
605
606def get_last_std(d):
607 rev_dialects = get_std_dialects()
608 rev_dialects.reverse()
609 for s in rev_dialects:
610 if s in d.keys():
611 return s
612 return None
613
614def get_std_before(d, std):
615 std_dialects = get_std_dialects()
616 candidates = std_dialects[0:std_dialects.index(std)]
617 candidates.reverse()
618 for cand in candidates:
619 if cand in d.keys():
620 return cand
621 return None
622
623def get_value_before(d, std):
624 new_std = get_std_before(d, std)
625 if new_std is None:
626 return None
627 return d[new_std]
628
629def get_for_std(d, std):
630 # This catches the C++11 case for which there should be no defined feature
631 # test macros.
632 std_dialects = get_std_dialects()
633 if std not in std_dialects:
634 return None
635 # Find the value for the newest C++ dialect between C++14 and std
636 std_list = list(std_dialects[0:std_dialects.index(std)+1])
637 std_list.reverse()
638 for s in std_list:
639 if s in d.keys():
640 return d[s]
641 return None
642
643
644"""
645 Functions to produce the <version> header
646"""
647
648def produce_macros_definition_for_std(std):
649 result = ""
650 indent = 56
651 for tc in feature_test_macros:
652 if std not in tc["values"]:
653 continue
654 inner_indent = 1
655 if 'depends' in tc.keys():
656 assert 'internal_depends' in tc.keys()
657 result += "# if %s\n" % tc["internal_depends"]
658 inner_indent += 2
659 if get_value_before(tc["values"], std) is not None:
660 assert 'depends' not in tc.keys()
661 result += "# undef %s\n" % tc["name"]
662 line = "#%sdefine %s" % ((" " * inner_indent), tc["name"])
663 line += " " * (indent - len(line))
664 line += "%sL" % tc["values"][std]
665 if 'unimplemented' in tc.keys():
666 line = "// " + line
667 result += line
668 result += "\n"
669 if 'depends' in tc.keys():
670 result += "# endif\n"
671 return result
672
673def chunks(l, n):
674 """Yield successive n-sized chunks from l."""
675 for i in range(0, len(l), n):
676 yield l[i:i + n]
677
678def produce_version_synopsis():
679 indent = 56
680 header_indent = 56 + len("20XXYYL ")
681 result = ""
682 def indent_to(s, val):
683 if len(s) >= val:
684 return s
685 s += " " * (val - len(s))
686 return s
687 line = indent_to("Macro name", indent) + "Value"
688 line = indent_to(line, header_indent) + "Headers"
689 result += line + "\n"
690 for tc in feature_test_macros:
691 prev_defined_std = get_last_std(tc["values"])
692 line = "{name: <{indent}}{value}L ".format(name=tc['name'], indent=indent,
693 value=tc["values"][prev_defined_std])
694 headers = list(tc["headers"])
695 headers.remove("version")
696 for chunk in chunks(headers, 3):
697 line = indent_to(line, header_indent)
698 chunk = ['<%s>' % header for header in chunk]
699 line += ' '.join(chunk)
700 result += line
701 result += "\n"
702 line = ""
703 while True:
704 prev_defined_std = get_std_before(tc["values"], prev_defined_std)
705 if prev_defined_std is None:
706 break
707 result += "%s%sL // %s\n" % (indent_to("", indent), tc["values"][prev_defined_std],
708 prev_defined_std.replace("c++", "C++"))
709 return result
710
711
712def produce_version_header():
713 template="""// -*- C++ -*-
714//===--------------------------- version ----------------------------------===//
715//
Chandler Carruth57b08b02019-01-19 10:56:40 +0000716// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
717// See https://llvm.org/LICENSE.txt for license information.
718// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Eric Fiselier32784a72019-01-16 01:37:43 +0000719//
720//===----------------------------------------------------------------------===//
721
722#ifndef _LIBCPP_VERSIONH
723#define _LIBCPP_VERSIONH
724
725/*
726 version synopsis
727
728{synopsis}
729
730*/
731
732#include <__config>
733
734#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
735#pragma GCC system_header
736#endif
737
738#if _LIBCPP_STD_VER > 11
739{cxx14_macros}
740#endif
741
742#if _LIBCPP_STD_VER > 14
743{cxx17_macros}
744#endif
745
746#if _LIBCPP_STD_VER > 17
747{cxx2a_macros}
748#endif
749
750#endif // _LIBCPP_VERSIONH
751"""
752 return template.format(
753 synopsis=produce_version_synopsis().strip(),
754 cxx14_macros=produce_macros_definition_for_std('c++14').strip(),
755 cxx17_macros=produce_macros_definition_for_std('c++17').strip(),
756 cxx2a_macros=produce_macros_definition_for_std('c++2a').strip())
757
758"""
759 Functions to produce test files
760"""
761
762test_types = {
763 "undefined": """
764# ifdef {name}
765# error "{name} should not be defined before {std_first}"
766# endif
767""",
768
769 "depends": """
770# if {depends}
771# ifndef {name}
772# error "{name} should be defined in {std}"
773# endif
774# if {name} != {value}
775# error "{name} should have the value {value} in {std}"
776# endif
777# else
778# ifdef {name}
779# error "{name} should not be defined when {depends} is not defined!"
780# endif
781# endif
782""",
783
784 "unimplemented": """
785# if !defined(_LIBCPP_VERSION)
786# ifndef {name}
787# error "{name} should be defined in {std}"
788# endif
789# if {name} != {value}
790# error "{name} should have the value {value} in {std}"
791# endif
792# else // _LIBCPP_VERSION
793# ifdef {name}
794# error "{name} should not be defined because it is unimplemented in libc++!"
795# endif
796# endif
797""",
798
799 "defined":"""
800# ifndef {name}
801# error "{name} should be defined in {std}"
802# endif
803# if {name} != {value}
804# error "{name} should have the value {value} in {std}"
805# endif
806"""
807}
808
809def generate_std_test(test_list, std):
810 result = ""
811 for tc in test_list:
812 val = get_for_std(tc["values"], std)
813 if val is not None:
814 val = "%sL" % val
815 if val is None:
816 result += test_types["undefined"].format(name=tc["name"], std_first=get_first_std(tc["values"]))
817 elif 'unimplemented' in tc.keys():
818 result += test_types["unimplemented"].format(name=tc["name"], value=val, std=std)
819 elif "depends" in tc.keys():
820 result += test_types["depends"].format(name=tc["name"], value=val, std=std, depends=tc["depends"])
821 else:
822 result += test_types["defined"].format(name=tc["name"], value=val, std=std)
823 return result
824
825def generate_synopsis(test_list):
826 max_name_len = max([len(tc["name"]) for tc in test_list])
827 indent = max_name_len + 8
828 def mk_line(prefix, suffix):
829 return "{prefix: <{max_len}}{suffix}\n".format(prefix=prefix, suffix=suffix,
830 max_len=indent)
831 result = ""
832 result += mk_line("/* Constant", "Value")
833 for tc in test_list:
834 prefix = " %s" % tc["name"]
835 for std in [s for s in get_std_dialects() if s in tc["values"].keys()]:
836 result += mk_line(prefix, "%sL [%s]" % (tc["values"][std], std.replace("c++", "C++")))
837 prefix = ""
838 result += "*/"
839 return result
840
Eric Fiselier05019eb2019-01-16 02:10:28 +0000841def is_threading_header_unsafe_to_include(h):
842 # NOTE: "<mutex>" does not blow up when included without threads.
843 return h in ['atomic', 'shared_mutex']
844
Eric Fiselier32784a72019-01-16 01:37:43 +0000845def produce_tests():
846 headers = set([h for tc in feature_test_macros for h in tc["headers"]])
847 for h in headers:
848 test_list = [tc for tc in feature_test_macros if h in tc["headers"]]
849 if not has_header(h):
850 for tc in test_list:
851 assert 'unimplemented' in tc.keys()
852 continue
Eric Fiselier05019eb2019-01-16 02:10:28 +0000853 test_tags = ""
854 if is_threading_header_unsafe_to_include(h):
855 test_tags += '\n// UNSUPPORTED: libcpp-has-no-threads\n'
Eric Fiselier32784a72019-01-16 01:37:43 +0000856 test_body = \
857"""//===----------------------------------------------------------------------===//
858//
Chandler Carruthb3ee4192019-01-19 11:38:40 +0000859// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
860// See https://llvm.org/LICENSE.txt for license information.
861// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Eric Fiselier32784a72019-01-16 01:37:43 +0000862//
863//===----------------------------------------------------------------------===//
864//
Eric Fiselier973eab82019-01-16 05:43:02 +0000865// WARNING: This test was generated by {script_name}
866// and should not be edited manually.
Eric Fiselier05019eb2019-01-16 02:10:28 +0000867{test_tags}
Eric Fiselier32784a72019-01-16 01:37:43 +0000868// <{header}>
869
870// Test the feature test macros defined by <{header}>
871
872{synopsis}
873
874#include <{header}>
875#include "test_macros.h"
876
877#if TEST_STD_VER < 14
878
879{cxx11_tests}
880
881#elif TEST_STD_VER == 14
882
883{cxx14_tests}
884
885#elif TEST_STD_VER == 17
886
887{cxx17_tests}
888
889#elif TEST_STD_VER > 17
890
891{cxx2a_tests}
892
893#endif // TEST_STD_VER > 17
894
JF Bastien73f49972019-02-05 05:34:12 +0000895int main(int, char**) {{ return 0; }}
Eric Fiselier973eab82019-01-16 05:43:02 +0000896""".format(script_name=script_name,
897 header=h,
Eric Fiselier05019eb2019-01-16 02:10:28 +0000898 test_tags=test_tags,
Eric Fiselier32784a72019-01-16 01:37:43 +0000899 synopsis=generate_synopsis(test_list),
900 cxx11_tests=generate_std_test(test_list, 'c++11').strip(),
901 cxx14_tests=generate_std_test(test_list, 'c++14').strip(),
902 cxx17_tests=generate_std_test(test_list, 'c++17').strip(),
903 cxx2a_tests=generate_std_test(test_list, 'c++2a').strip())
904 test_name = "{header}.version.pass.cpp".format(header=h)
Eric Fiselier508da412019-02-02 23:13:49 +0000905 out_path = os.path.join(macro_test_path, test_name)
Eric Fiselier32784a72019-01-16 01:37:43 +0000906 with open(out_path, 'w') as f:
907 f.write(test_body)
908
909"""
910 Produce documentation for the feature test macros
911"""
912
913def make_widths(grid):
914 widths = []
915 for i in range(0, len(grid[0])):
916 cell_width = 2 + max(reduce(lambda x,y: x+y, [[len(row[i])] for row in grid], []))
917 widths += [cell_width]
918 return widths
919
920def create_table(grid, indent):
921 indent_str = ' '*indent
922 col_widths = make_widths(grid)
923 num_cols = len(grid[0])
924 result = indent_str + add_divider(col_widths, 2)
925 header_flag = 2
Louis Dionnefd02a462019-11-06 16:44:14 +0000926 for row_i in range(0, len(grid)):
Eric Fiselier32784a72019-01-16 01:37:43 +0000927 row = grid[row_i]
928 result = result + indent_str + ' '.join([pad_cell(row[i], col_widths[i]) for i in range(0, len(row))]) + '\n'
929 is_cxx_header = row[0].startswith('**')
930 if row_i == len(grid) - 1:
931 header_flag = 2
932 result = result + indent_str + add_divider(col_widths, 1 if is_cxx_header else header_flag)
933 header_flag = 0
934 return result
935
936def add_divider(widths, header_flag):
937 if header_flag == 2:
938 return ' '.join(['='*w for w in widths]) + '\n'
939 if header_flag == 1:
940 return '-'.join(['-'*w for w in widths]) + '\n'
941 else:
942 return ' '.join(['-'*w for w in widths]) + '\n'
943
944def pad_cell(s, length, left_align=True):
945 padding = ((length - len(s)) * ' ')
946 return s + padding
947
948
949def get_status_table():
950 table = [["Macro Name", "Value"]]
951 for std in get_std_dialects():
952 table += [["**" + std.replace("c++", "C++ ") + "**", ""]]
953 for tc in feature_test_macros:
954 if std not in tc["values"].keys():
955 continue
956 value = "``%sL``" % tc["values"][std]
957 if 'unimplemented' in tc.keys():
958 value = '*unimplemented*'
959 table += [["``%s``" % tc["name"], value]]
960 return table
961
962def produce_docs():
963 doc_str = """.. _FeatureTestMacroTable:
964
965==========================
966Feature Test Macro Support
967==========================
968
969.. contents::
970 :local:
971
972Overview
973========
974
975This file documents the feature test macros currently supported by libc++.
976
977.. _feature-status:
978
979Status
980======
981
982.. table:: Current Status
983 :name: feature-status-table
984 :widths: auto
Louis Dionnefd02a462019-11-06 16:44:14 +0000985
Eric Fiselier32784a72019-01-16 01:37:43 +0000986{status_tables}
987
988""".format(status_tables=create_table(get_status_table(), 4))
989
990 table_doc_path = os.path.join(docs_path, 'FeatureTestMacroTable.rst')
991 with open(table_doc_path, 'w') as f:
992 f.write(doc_str)
993
994def main():
995 with tempfile.NamedTemporaryFile(mode='w', prefix='version.', delete=False) as tmp_file:
996 print("producing new <version> header as %s" % tmp_file.name)
997 tmp_file.write(produce_version_header())
998 produce_tests()
999 produce_docs()
1000
1001
1002if __name__ == '__main__':
1003 main()