c80ebb11e679bdac7448971b11ed4c296681bb1e
[llvm-toolchain-8.git] /
1 #!/usr/bin/env python
2
3 import os
4 import tempfile
5
6 def get_libcxx_paths():
7   script_path = os.path.dirname(os.path.abspath(__file__))
8   script_name = os.path.basename(__file__)
9   assert os.path.exists(script_path)
10   depth = 5
11   src_root = script_path
12   for _ in xrange(0, 5):
13     src_root = os.path.dirname(src_root)
14   include_path = os.path.join(src_root, 'include')
15   assert os.path.exists(include_path)
16   docs_path = os.path.join(src_root, 'docs')
17   assert os.path.exists(docs_path)
18   return script_path, script_name, src_root, include_path, docs_path
19
20
21 script_path, script_name, source_root, include_path, docs_path = get_libcxx_paths()
22
23 def has_header(h):
24   h_path = os.path.join(include_path, h)
25   return os.path.exists(h_path)
26
27 def add_version_header(tc):
28     tc["headers"].append("version")
29     return tc
30
31 feature_test_macros = sorted([ add_version_header(x) for x in [
32   # C++14 macros
33   {"name": "__cpp_lib_integer_sequence",
34    "values": {
35       "c++14": 201304L
36     },
37     "headers": ["utility"],
38   },
39   {"name": "__cpp_lib_exchange_function",
40    "values": {
41      "c++14": 201304L
42    },
43    "headers": ["utility"],
44   },
45   {"name": "__cpp_lib_tuples_by_type",
46    "values": {
47      "c++14": 201304L
48    },
49    "headers": ["utility", "tuple"],
50   },
51   {"name": "__cpp_lib_tuple_element_t",
52    "values": {
53      "c++14": 201402L
54    },
55    "headers": ["tuple"],
56   },
57   {"name": "__cpp_lib_make_unique",
58    "values": {
59      "c++14": 201304L
60    },
61    "headers": ["memory"],
62   },
63   {"name": "__cpp_lib_transparent_operators",
64    "values": {
65      "c++14": 201210L,
66      "c++17": 201510L,
67    },
68    "headers": ["functional"],
69   },
70   {"name": "__cpp_lib_integral_constant_callable",
71    "values": {
72      "c++14": 201304L
73    },
74    "headers": ["type_traits"],
75   },
76   {"name": "__cpp_lib_transformation_trait_aliases",
77    "values": {
78      "c++14": 201304L,
79    },
80    "headers": ["type_traits"]
81   },
82   {"name": "__cpp_lib_result_of_sfinae",
83    "values": {
84      "c++14": 201210L,
85    },
86    "headers": ["functional", "type_traits"]
87   },
88   {"name": "__cpp_lib_is_final",
89    "values": {
90      "c++14": 201402L,
91    },
92    "headers": ["type_traits"]
93   },
94   {"name": "__cpp_lib_is_null_pointer",
95    "values": {
96      "c++14": 201309L,
97    },
98    "headers": ["type_traits"]
99   },
100   {"name": "__cpp_lib_chrono_udls",
101    "values": {
102      "c++14": 201304L,
103    },
104    "headers": ["chrono"]
105   },
106   {"name": "__cpp_lib_string_udls",
107    "values": {
108      "c++14": 201304L,
109    },
110    "headers": ["string"]
111   },
112   {"name": "__cpp_lib_generic_associative_lookup",
113    "values": {
114      "c++14": 201304L,
115    },
116    "headers": ["map", "set"]
117   },
118   {"name": "__cpp_lib_null_iterators",
119    "values": {
120      "c++14": 201304L,
121    },
122    "headers": ["iterator"]
123   },
124   {"name": "__cpp_lib_make_reverse_iterator",
125    "values": {
126      "c++14": 201402L,
127    },
128    "headers": ["iterator"]
129   },
130   {"name": "__cpp_lib_robust_nonmodifying_seq_ops",
131    "values": {
132      "c++14": 201304L,
133    },
134    "headers": ["algorithm"]
135   },
136   {"name": "__cpp_lib_complex_udls",
137    "values": {
138      "c++14": 201309L,
139    },
140    "headers": ["complex"]
141   },
142   {"name": "__cpp_lib_quoted_string_io",
143    "values": {
144      "c++14": 201304L,
145    },
146    "headers": ["iomanip"]
147   },
148   {"name": "__cpp_lib_shared_timed_mutex",
149    "values": {
150      "c++14": 201402L,
151    },
152    "headers": ["shared_mutex"],
153    "depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
154    "internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
155   },
156   # C++17 macros
157   {"name": "__cpp_lib_atomic_is_always_lock_free",
158    "values": {
159      "c++17": 201603L,
160    },
161    "headers": ["atomic"],
162    "depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
163    "internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
164   },
165   {"name": "__cpp_lib_filesystem",
166    "values": {
167      "c++17": 201703L,
168    },
169    "headers": ["filesystem"]
170   },
171   {"name": "__cpp_lib_invoke",
172    "values": {
173      "c++17": 201411L,
174    },
175    "headers": ["functional"]
176   },
177   {"name": "__cpp_lib_void_t",
178    "values": {
179      "c++17": 201411L,
180    },
181    "headers": ["type_traits"]
182   },
183   {"name": "__cpp_lib_node_extract",
184    "values": {
185      "c++17": 201606L,
186    },
187    "headers": ["map", "set", "unordered_map", "unordered_set"]
188   },
189   {"name": "__cpp_lib_byte",
190    "values": {
191      "c++17": 201603L,
192    },
193    "headers": ["cstddef"],
194    },
195   {"name": "__cpp_lib_hardware_interference_size",
196    "values": {
197      "c++17": 201703L,
198    },
199    "headers": ["new"],
200    },
201   {"name": "__cpp_lib_launder",
202    "values": {
203      "c++17": 201606L,
204    },
205    "headers": ["new"],
206    },
207   {"name": "__cpp_lib_uncaught_exceptions",
208    "values": {
209      "c++17": 201411L,
210    },
211    "headers": ["exception"],
212    },
213   {"name": "__cpp_lib_as_const",
214    "values": {
215      "c++17": 201510L,
216    },
217    "headers": ["utility"],
218    },
219   {"name": "__cpp_lib_make_from_tuple",
220    "values": {
221      "c++17": 201606L,
222    },
223    "headers": ["tuple"],
224    },
225   {"name": "__cpp_lib_apply",
226    "values": {
227      "c++17": 201603L,
228    },
229    "headers": ["tuple"],
230    },
231   {"name": "__cpp_lib_optional",
232    "values": {
233      "c++17": 201606L,
234    },
235    "headers": ["optional"],
236    },
237   {"name": "__cpp_lib_variant",
238    "values": {
239      "c++17": 201606L,
240    },
241    "headers": ["variant"],
242    },
243   {"name": "__cpp_lib_any",
244    "values": {
245      "c++17": 201606L,
246    },
247    "headers": ["any"],
248    },
249   {"name": "__cpp_lib_addressof_constexpr",
250    "values": {
251      "c++17": 201603L,
252    },
253    "headers": ["memory"],
254    "depends": "TEST_HAS_BUILTIN(__builtin_addressof) || TEST_GCC_VER >= 700",
255    "internal_depends": "!defined(_LIBCPP_HAS_NO_BUILTIN_ADDRESSOF)",
256    },
257   {"name": "__cpp_lib_raw_memory_algorithms",
258    "values": {
259      "c++17": 201606L,
260    },
261    "headers": ["memory"],
262    },
263   {"name": "__cpp_lib_enable_shared_from_this",
264    "values": {
265      "c++17": 201603L,
266    },
267    "headers": ["memory"],
268    },
269   {"name": "__cpp_lib_shared_ptr_weak_type",
270    "values": {
271      "c++17": 201606L,
272    },
273    "headers": ["memory"],
274    },
275   {"name": "__cpp_lib_shared_ptr_arrays",
276    "values": {
277      "c++17": 201611L,
278    },
279    "headers": ["memory"],
280    "unimplemented": True,
281    },
282   {"name": "__cpp_lib_memory_resource",
283    "values": {
284      "c++17": 201603L,
285    },
286    "headers": ["memory_resource"],
287    "unimplemented": True,
288    },
289   {"name": "__cpp_lib_boyer_moore_searcher",
290    "values": {
291      "c++17": 201603L,
292    },
293    "headers": ["functional"],
294    "unimplemented": True,
295    },
296   {"name": "__cpp_lib_not_fn",
297    "values": {
298      "c++17": 201603L,
299    },
300    "headers": ["functional"],
301    },
302   {"name": "__cpp_lib_bool_constant",
303    "values": {
304      "c++17": 201505L,
305    },
306    "headers": ["type_traits"],
307    },
308   {"name": "__cpp_lib_type_trait_variable_templates",
309    "values": {
310      "c++17": 201510L,
311    },
312    "headers": ["type_traits"],
313    },
314   {"name": "__cpp_lib_logical_traits",
315    "values": {
316      "c++17": 201510L,
317    },
318    "headers": ["type_traits"],
319    },
320   {"name": "__cpp_lib_is_swappable",
321    "values": {
322      "c++17": 201603L,
323    },
324    "headers": ["type_traits"],
325    },
326   {"name": "__cpp_lib_is_invocable",
327    "values": {
328      "c++17": 201703L,
329    },
330    "headers": ["type_traits"],
331    },
332   {"name": "__cpp_lib_has_unique_object_representations",
333    "values": {
334      "c++17": 201606L,
335    },
336    "headers": ["type_traits"],
337    "depends": "TEST_HAS_BUILTIN_IDENTIFIER(__has_unique_object_representations) || TEST_GCC_VER >= 700",
338    "internal_depends": "defined(_LIBCPP_HAS_UNIQUE_OBJECT_REPRESENTATIONS)",
339    },
340   {"name": "__cpp_lib_is_aggregate",
341    "values": {
342      "c++17": 201703L,
343    },
344    "headers": ["type_traits"],
345    "depends": "TEST_HAS_BUILTIN_IDENTIFIER(__is_aggregate) || TEST_GCC_VER_NEW >= 7001",
346    "internal_depends": "!defined(_LIBCPP_HAS_NO_IS_AGGREGATE)",
347    },
348   {"name": "__cpp_lib_chrono",
349    "values": {
350      "c++17": 201611L,
351    },
352    "headers": ["chrono"],
353    },
354   {"name": "__cpp_lib_execution",
355    "values": {
356      "c++17": 201603L,
357    },
358    "headers": ["execution"],
359    "unimplemented": True
360    },
361   {"name": "__cpp_lib_parallel_algorithm",
362    "values": {
363      "c++17": 201603L,
364    },
365    "headers": ["algorithm", "numeric"],
366    "unimplemented": True,
367    },
368   {"name": "__cpp_lib_to_chars",
369    "values": {
370      "c++17": 201611L,
371    },
372    "headers": ["utility"],
373    "unimplemented": True,
374    },
375   {"name": "__cpp_lib_string_view",
376    "values": {
377      "c++17": 201606L,
378    },
379    "headers": ["string", "string_view"],
380    },
381   {"name": "__cpp_lib_allocator_traits_is_always_equal",
382    "values": {
383      "c++17": 201411L,
384    },
385    "headers": ["memory", "scoped_allocator", "string", "deque", "forward_list", "list", "vector", "map", "set", "unordered_map", "unordered_set"],
386    },
387   {"name": "__cpp_lib_incomplete_container_elements",
388    "values": {
389      "c++17": 201505L,
390    },
391    "headers": ["forward_list", "list", "vector"],
392    },
393   {"name": "__cpp_lib_map_try_emplace",
394    "values": {
395      "c++17": 201411L,
396    },
397    "headers": ["map"],
398    },
399   {"name": "__cpp_lib_unordered_map_try_emplace",
400    "values": {
401      "c++17": 201411L,
402    },
403    "headers": ["unordered_map"],
404    },
405   {"name": "__cpp_lib_array_constexpr",
406    "values": {
407      "c++17": 201603L,
408    },
409    "headers": ["iterator", "array"],
410    },
411   {"name": "__cpp_lib_nonmember_container_access",
412    "values": {
413      "c++17": 201411L,
414    },
415    "headers": ["iterator", "array", "deque", "forward_list", "list", "map", "regex",
416                "set", "string", "unordered_map", "unordered_set", "vector"],
417    },
418   {"name": "__cpp_lib_sample",
419    "values": {
420      "c++17": 201603L,
421    },
422    "headers": ["algorithm"],
423    },
424   {"name": "__cpp_lib_clamp",
425    "values": {
426      "c++17": 201603L,
427    },
428    "headers": ["algorithm"],
429    },
430   {"name": "__cpp_lib_gcd_lcm",
431    "values": {
432      "c++17": 201606L,
433    },
434    "headers": ["numeric"],
435    },
436   {"name": "__cpp_lib_hypot",
437    "values": {
438      "c++17": 201603L,
439    },
440    "headers": ["cmath"],
441    },
442   {"name": "__cpp_lib_math_special_functions",
443    "values": {
444      "c++17": 201603L,
445    },
446    "headers": ["cmath"],
447    "unimplemented": True,
448    },
449   {"name": "__cpp_lib_shared_mutex",
450    "values": {
451      "c++17": 201505L,
452    },
453    "headers": ["shared_mutex"],
454    "depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
455    "internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
456    },
457   {"name": "__cpp_lib_scoped_lock",
458    "values": {
459      "c++17": 201703L,
460    },
461    "headers": ["mutex"],
462    },
463   # C++2a
464   {"name": "__cpp_lib_char8_t",
465    "values": {
466      "c++2a": 201811L,
467    },
468    "headers": ["atomic", "filesystem", "istream", "limits", "locale", "ostream",
469                "string", "string_view"],
470    "depends": "defined(__cpp_char8_t)",
471    "internal_depends": "!defined(_LIBCPP_NO_HAS_CHAR8_T)",
472    },
473   {"name": "__cpp_lib_erase_if",
474    "values": {
475      "c++2a": 201811L,
476    },
477    "headers": ["string", "deque", "forward_list", "list", "vector", "map",
478                "set", "unordered_map", "unordered_set"]
479   },
480   {"name": "__cpp_lib_destroying_delete",
481    "values": {
482      "c++2a": 201806L,
483    },
484    "headers": ["new"],
485    "unimplemented": True,
486    },
487   {"name": "__cpp_lib_three_way_comparison",
488    "values": {
489      "c++2a": 201711L,
490    },
491    "headers": ["compare"],
492    "unimplemented": True,
493    },
494   {"name": "__cpp_lib_concepts",
495    "values": {
496      "c++2a": 201806L,
497    },
498    "headers": ["concepts"],
499    "unimplemented": True,
500    },
501   {"name": "__cpp_lib_constexpr_swap_algorithms",
502    "values": {
503      "c++2a": 201806L,
504    },
505    "headers": ["algorithm"],
506    "unimplemented": True,
507    },
508   {"name": "__cpp_lib_constexpr_misc",
509    "values": {
510      "c++2a": 201811L,
511    },
512    "headers": ["array", "functional", "iterator", "string_view", "tuple", "utility"],
513    "unimplemented": True,
514    },
515   {"name": "__cpp_lib_bind_front",
516    "values": {
517      "c++2a": 201811L,
518    },
519    "headers": ["functional"],
520    "unimplemented": True,
521    },
522   {"name": "__cpp_lib_is_constant_evaluated",
523    "values": {
524      "c++2a": 201811L,
525    },
526    "headers": ["type_traits"],
527    "unimplemented": True,
528    },
529   {"name": "__cpp_lib_list_remove_return_type",
530    "values": {
531      "c++2a": 201806L,
532    },
533    "headers": ["forward_list", "list"],
534    "unimplemented": True,
535    },
536   {"name": "__cpp_lib_generic_unordered_lookup",
537    "values": {
538      "c++2a": 201811L,
539    },
540    "headers": ["unordered_map", "unordered_set"],
541    "unimplemented": True,
542    },
543   {"name": "__cpp_lib_ranges",
544    "values": {
545      "c++2a": 201811L,
546    },
547    "headers": ["algorithm", "functional", "iterator", "memory", "ranges"],
548    "unimplemented": True,
549    },
550   {"name": "__cpp_lib_bit_cast",
551    "values": {
552      "c++2a": 201806L,
553    },
554    "headers": ["bit"],
555    "unimplemented": True,
556    },
557   {"name": "__cpp_lib_atomic_ref",
558    "values": {
559      "c++2a": 201806L,
560    },
561    "headers": ["atomic"],
562    "unimplemented": True,
563    "depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
564    "internal_depends": "!defined(_LIBCPP_HAS_NO_THREADS)",
565    },
566 ]], key=lambda tc: tc["name"])
567
568 def get_std_dialects():
569   std_dialects = ['c++14', 'c++17', 'c++2a']
570   return list(std_dialects)
571
572 def get_first_std(d):
573     for s in get_std_dialects():
574         if s in d.keys():
575             return s
576     return None
577
578 def get_last_std(d):
579   rev_dialects = get_std_dialects()
580   rev_dialects.reverse()
581   for s in rev_dialects:
582     if s in d.keys():
583       return s
584   return None
585
586 def get_std_before(d, std):
587   std_dialects = get_std_dialects()
588   candidates = std_dialects[0:std_dialects.index(std)]
589   candidates.reverse()
590   for cand in candidates:
591     if cand in d.keys():
592       return cand
593   return None
594
595 def get_value_before(d, std):
596   new_std = get_std_before(d, std)
597   if new_std is None:
598     return None
599   return d[new_std]
600
601 def get_for_std(d, std):
602   # This catches the C++11 case for which there should be no defined feature
603   # test macros.
604   std_dialects = get_std_dialects()
605   if std not in std_dialects:
606     return None
607   # Find the value for the newest C++ dialect between C++14 and std
608   std_list = list(std_dialects[0:std_dialects.index(std)+1])
609   std_list.reverse()
610   for s in std_list:
611     if s in d.keys():
612       return d[s]
613   return None
614
615
616 """
617   Functions to produce the <version> header
618 """
619
620 def produce_macros_definition_for_std(std):
621   result = ""
622   indent = 56
623   for tc in feature_test_macros:
624     if std not in tc["values"]:
625       continue
626     inner_indent = 1
627     if 'depends' in tc.keys():
628       assert 'internal_depends' in tc.keys()
629       result += "# if %s\n" % tc["internal_depends"]
630       inner_indent += 2
631     if get_value_before(tc["values"], std) is not None:
632       assert 'depends' not in tc.keys()
633       result += "# undef  %s\n" % tc["name"]
634     line = "#%sdefine %s" % ((" " * inner_indent), tc["name"])
635     line += " " * (indent - len(line))
636     line += "%sL" % tc["values"][std]
637     if 'unimplemented' in tc.keys():
638       line = "// " + line
639     result += line
640     result += "\n"
641     if 'depends' in tc.keys():
642       result += "# endif\n"
643   return result
644
645 def chunks(l, n):
646   """Yield successive n-sized chunks from l."""
647   for i in range(0, len(l), n):
648     yield l[i:i + n]
649
650 def produce_version_synopsis():
651   indent = 56
652   header_indent = 56 + len("20XXYYL ")
653   result = ""
654   def indent_to(s, val):
655     if len(s) >= val:
656       return s
657     s += " " * (val - len(s))
658     return s
659   line = indent_to("Macro name", indent) + "Value"
660   line = indent_to(line, header_indent) + "Headers"
661   result += line + "\n"
662   for tc in feature_test_macros:
663     prev_defined_std = get_last_std(tc["values"])
664     line = "{name: <{indent}}{value}L ".format(name=tc['name'], indent=indent,
665                                                value=tc["values"][prev_defined_std])
666     headers = list(tc["headers"])
667     headers.remove("version")
668     for chunk in chunks(headers, 3):
669       line = indent_to(line, header_indent)
670       chunk = ['<%s>' % header for header in chunk]
671       line += ' '.join(chunk)
672       result += line
673       result += "\n"
674       line = ""
675     while True:
676       prev_defined_std = get_std_before(tc["values"], prev_defined_std)
677       if prev_defined_std is None:
678         break
679       result += "%s%sL // %s\n" % (indent_to("", indent), tc["values"][prev_defined_std],
680                                 prev_defined_std.replace("c++", "C++"))
681   return result
682
683
684 def produce_version_header():
685   template="""// -*- C++ -*-
686 //===--------------------------- version ----------------------------------===//
687 //
688 //                     The LLVM Compiler Infrastructure
689 //
690 // This file is dual licensed under the MIT and the University of Illinois Open
691 // Source Licenses. See LICENSE.TXT for details.
692 //
693 //===----------------------------------------------------------------------===//
694
695 #ifndef _LIBCPP_VERSIONH
696 #define _LIBCPP_VERSIONH
697
698 /*
699   version synopsis
700
701 {synopsis}
702
703 */
704
705 #include <__config>
706
707 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
708 #pragma GCC system_header
709 #endif
710
711 #if _LIBCPP_STD_VER > 11
712 {cxx14_macros}
713 #endif
714
715 #if _LIBCPP_STD_VER > 14
716 {cxx17_macros}
717 #endif
718
719 #if _LIBCPP_STD_VER > 17
720 {cxx2a_macros}
721 #endif
722
723 #endif // _LIBCPP_VERSIONH
724 """
725   return template.format(
726       synopsis=produce_version_synopsis().strip(),
727       cxx14_macros=produce_macros_definition_for_std('c++14').strip(),
728       cxx17_macros=produce_macros_definition_for_std('c++17').strip(),
729       cxx2a_macros=produce_macros_definition_for_std('c++2a').strip())
730
731 """
732     Functions to produce test files
733 """
734
735 test_types = {
736   "undefined": """
737 # ifdef {name}
738 #   error "{name} should not be defined before {std_first}"
739 # endif
740 """,
741
742   "depends": """
743 # if {depends}
744 #   ifndef {name}
745 #     error "{name} should be defined in {std}"
746 #   endif
747 #   if {name} != {value}
748 #     error "{name} should have the value {value} in {std}"
749 #   endif
750 # else
751 #   ifdef {name}
752 #     error "{name} should not be defined when {depends} is not defined!"
753 #   endif
754 # endif
755 """,
756
757   "unimplemented": """
758 # if !defined(_LIBCPP_VERSION)
759 #   ifndef {name}
760 #     error "{name} should be defined in {std}"
761 #   endif
762 #   if {name} != {value}
763 #     error "{name} should have the value {value} in {std}"
764 #   endif
765 # else // _LIBCPP_VERSION
766 #   ifdef {name}
767 #     error "{name} should not be defined because it is unimplemented in libc++!"
768 #   endif
769 # endif
770 """,
771
772   "defined":"""
773 # ifndef {name}
774 #   error "{name} should be defined in {std}"
775 # endif
776 # if {name} != {value}
777 #   error "{name} should have the value {value} in {std}"
778 # endif
779 """
780 }
781
782 def generate_std_test(test_list, std):
783   result = ""
784   for tc in test_list:
785     val = get_for_std(tc["values"], std)
786     if val is not None:
787       val = "%sL" % val
788     if val is None:
789       result += test_types["undefined"].format(name=tc["name"], std_first=get_first_std(tc["values"]))
790     elif 'unimplemented' in tc.keys():
791       result += test_types["unimplemented"].format(name=tc["name"], value=val, std=std)
792     elif "depends" in tc.keys():
793       result += test_types["depends"].format(name=tc["name"], value=val, std=std, depends=tc["depends"])
794     else:
795       result +=  test_types["defined"].format(name=tc["name"], value=val, std=std)
796   return result
797
798 def generate_synopsis(test_list):
799     max_name_len = max([len(tc["name"]) for tc in test_list])
800     indent = max_name_len + 8
801     def mk_line(prefix, suffix):
802         return "{prefix: <{max_len}}{suffix}\n".format(prefix=prefix, suffix=suffix,
803         max_len=indent)
804     result = ""
805     result += mk_line("/*  Constant", "Value")
806     for tc in test_list:
807         prefix = "    %s" % tc["name"]
808         for std in [s for s in get_std_dialects() if s in tc["values"].keys()]:
809             result += mk_line(prefix, "%sL [%s]" % (tc["values"][std], std.replace("c++", "C++")))
810             prefix = ""
811     result += "*/"
812     return result
813
814 def is_threading_header_unsafe_to_include(h):
815   # NOTE: "<mutex>" does not blow up when included without threads.
816   return h in ['atomic', 'shared_mutex']
817
818 def produce_tests():
819   headers = set([h for tc in feature_test_macros for h in tc["headers"]])
820   for h in headers:
821     test_list = [tc for tc in feature_test_macros if h in tc["headers"]]
822     if not has_header(h):
823       for tc in test_list:
824         assert 'unimplemented' in tc.keys()
825       continue
826     test_tags = ""
827     if is_threading_header_unsafe_to_include(h):
828       test_tags += '\n// UNSUPPORTED: libcpp-has-no-threads\n'
829     test_body = \
830 """//===----------------------------------------------------------------------===//
831 //
832 //                     The LLVM Compiler Infrastructure
833 //
834 // This file is dual licensed under the MIT and the University of Illinois Open
835 // Source Licenses. See LICENSE.TXT for details.
836 //
837 //===----------------------------------------------------------------------===//
838 //
839 // WARNING: This test was generated by {script_name}
840 // and should not be edited manually.
841 {test_tags}
842 // <{header}>
843
844 // Test the feature test macros defined by <{header}>
845
846 {synopsis}
847
848 #include <{header}>
849 #include "test_macros.h"
850
851 #if TEST_STD_VER < 14
852
853 {cxx11_tests}
854
855 #elif TEST_STD_VER == 14
856
857 {cxx14_tests}
858
859 #elif TEST_STD_VER == 17
860
861 {cxx17_tests}
862
863 #elif TEST_STD_VER > 17
864
865 {cxx2a_tests}
866
867 #endif // TEST_STD_VER > 17
868
869 int main() {{}}
870 """.format(script_name=script_name,
871            header=h,
872            test_tags=test_tags,
873            synopsis=generate_synopsis(test_list),
874            cxx11_tests=generate_std_test(test_list, 'c++11').strip(),
875            cxx14_tests=generate_std_test(test_list, 'c++14').strip(),
876            cxx17_tests=generate_std_test(test_list, 'c++17').strip(),
877            cxx2a_tests=generate_std_test(test_list, 'c++2a').strip())
878     test_name = "{header}.version.pass.cpp".format(header=h)
879     out_path = os.path.join(script_path, test_name)
880     with open(out_path, 'w') as f:
881       f.write(test_body)
882
883 """
884     Produce documentation for the feature test macros
885 """
886
887 def make_widths(grid):
888   widths = []
889   for i in range(0, len(grid[0])):
890     cell_width = 2 + max(reduce(lambda x,y: x+y, [[len(row[i])] for row in grid], []))
891     widths += [cell_width]
892   return widths
893
894 def create_table(grid, indent):
895   indent_str = ' '*indent
896   col_widths = make_widths(grid)
897   num_cols = len(grid[0])
898   result = indent_str + add_divider(col_widths, 2)
899   header_flag = 2
900   for row_i in xrange(0, len(grid)):
901     row = grid[row_i]
902     result = result + indent_str + ' '.join([pad_cell(row[i], col_widths[i]) for i in range(0, len(row))]) + '\n'
903     is_cxx_header = row[0].startswith('**')
904     if row_i == len(grid) - 1:
905       header_flag = 2
906     result = result + indent_str + add_divider(col_widths, 1 if is_cxx_header else header_flag)
907     header_flag = 0
908   return result
909
910 def add_divider(widths, header_flag):
911   if header_flag == 2:
912     return ' '.join(['='*w for w in widths]) + '\n'
913   if header_flag == 1:
914     return '-'.join(['-'*w for w in widths]) + '\n'
915   else:
916     return ' '.join(['-'*w for w in widths]) + '\n'
917
918 def pad_cell(s, length, left_align=True):
919   padding = ((length - len(s)) * ' ')
920   return s + padding
921
922
923 def get_status_table():
924   table = [["Macro Name", "Value"]]
925   for std in get_std_dialects():
926     table += [["**" + std.replace("c++", "C++ ") + "**", ""]]
927     for tc in feature_test_macros:
928       if std not in tc["values"].keys():
929         continue
930       value = "``%sL``" % tc["values"][std]
931       if 'unimplemented' in tc.keys():
932         value = '*unimplemented*'
933       table += [["``%s``" % tc["name"], value]]
934   return table
935
936 def produce_docs():
937   doc_str = """.. _FeatureTestMacroTable:
938
939 ==========================
940 Feature Test Macro Support
941 ==========================
942
943 .. contents::
944    :local:
945
946 Overview
947 ========
948
949 This file documents the feature test macros currently supported by libc++.
950
951 .. _feature-status:
952
953 Status
954 ======
955
956 .. table:: Current Status
957      :name: feature-status-table
958      :widths: auto
959      
960 {status_tables}
961
962 """.format(status_tables=create_table(get_status_table(), 4))
963
964   table_doc_path = os.path.join(docs_path, 'FeatureTestMacroTable.rst')
965   with open(table_doc_path, 'w') as f:
966     f.write(doc_str)
967
968 def main():
969   with tempfile.NamedTemporaryFile(mode='w', prefix='version.', delete=False) as tmp_file:
970     print("producing new <version> header as %s" % tmp_file.name)
971     tmp_file.write(produce_version_header())
972   produce_tests()
973   produce_docs()
974
975
976 if __name__ == '__main__':
977   main()