176d0caaeSpatrick#!/usr/bin/env python 276d0caaeSpatrick 376d0caaeSpatrickimport os 476d0caaeSpatrick 576d0caaeSpatrick 676d0caaeSpatrickdef get_libcxx_paths(): 776d0caaeSpatrick utils_path = os.path.dirname(os.path.abspath(__file__)) 876d0caaeSpatrick script_name = os.path.basename(__file__) 976d0caaeSpatrick assert os.path.exists(utils_path) 1076d0caaeSpatrick src_root = os.path.dirname(utils_path) 1176d0caaeSpatrick test_path = os.path.join(src_root, 'test', 'libcxx', 'inclusions') 1276d0caaeSpatrick assert os.path.exists(test_path) 1376d0caaeSpatrick assert os.path.exists(os.path.join(test_path, 'algorithm.inclusions.compile.pass.cpp')) 1476d0caaeSpatrick return script_name, src_root, test_path 1576d0caaeSpatrick 1676d0caaeSpatrick 1776d0caaeSpatrickscript_name, source_root, test_path = get_libcxx_paths() 1876d0caaeSpatrick 1976d0caaeSpatrick 2076d0caaeSpatrick# This table was produced manually, by grepping the TeX source of the Standard's 2176d0caaeSpatrick# library clauses for the string "#include". Each header's synopsis contains 2276d0caaeSpatrick# explicit "#include" directives for its mandatory inclusions. 2376d0caaeSpatrick# For example, [algorithm.syn] contains "#include <initializer_list>". 2476d0caaeSpatrick# 2576d0caaeSpatrickmandatory_inclusions = { 2676d0caaeSpatrick "algorithm": ["initializer_list"], 2776d0caaeSpatrick "array": ["compare", "initializer_list"], 2876d0caaeSpatrick "bitset": ["iosfwd", "string"], 2976d0caaeSpatrick "chrono": ["compare"], 3076d0caaeSpatrick "cinttypes": ["cstdint"], 3176d0caaeSpatrick "complex.h": ["complex"], 32*4bdff4beSrobert "coroutine": ["compare"], 3376d0caaeSpatrick "deque": ["compare", "initializer_list"], 3476d0caaeSpatrick "filesystem": ["compare"], 3576d0caaeSpatrick "forward_list": ["compare", "initializer_list"], 3676d0caaeSpatrick "ios": ["iosfwd"], 3776d0caaeSpatrick "iostream": ["ios", "istream", "ostream", "streambuf"], 3876d0caaeSpatrick "iterator": ["compare", "concepts"], 3976d0caaeSpatrick "list": ["compare", "initializer_list"], 4076d0caaeSpatrick "map": ["compare", "initializer_list"], 4176d0caaeSpatrick "memory": ["compare"], 4276d0caaeSpatrick "optional": ["compare"], 4376d0caaeSpatrick "queue": ["compare", "initializer_list"], 4476d0caaeSpatrick "random": ["initializer_list"], 4576d0caaeSpatrick "ranges": ["compare", "initializer_list", "iterator"], 4676d0caaeSpatrick "regex": ["compare", "initializer_list"], 4776d0caaeSpatrick "set": ["compare", "initializer_list"], 4876d0caaeSpatrick "stack": ["compare", "initializer_list"], 4976d0caaeSpatrick "string_view": ["compare"], 5076d0caaeSpatrick "string": ["compare", "initializer_list"], 5176d0caaeSpatrick # TODO "syncstream": ["ostream"], 5276d0caaeSpatrick "system_error": ["compare"], 5376d0caaeSpatrick "tgmath.h": ["cmath", "complex"], 5476d0caaeSpatrick "thread": ["compare"], 5576d0caaeSpatrick "tuple": ["compare"], 5676d0caaeSpatrick "typeindex": ["compare"], 5776d0caaeSpatrick "unordered_map": ["compare", "initializer_list"], 5876d0caaeSpatrick "unordered_set": ["compare", "initializer_list"], 5976d0caaeSpatrick "utility": ["compare", "initializer_list"], 6076d0caaeSpatrick "valarray": ["initializer_list"], 6176d0caaeSpatrick "variant": ["compare"], 6276d0caaeSpatrick "vector": ["compare", "initializer_list"], 6376d0caaeSpatrick} 6476d0caaeSpatrick 6576d0caaeSpatricknew_in_version = { 6676d0caaeSpatrick "chrono": "11", 6776d0caaeSpatrick "compare": "20", 6876d0caaeSpatrick "concepts": "20", 6976d0caaeSpatrick "coroutine": "20", 70*4bdff4beSrobert "cuchar": "11", 71*4bdff4beSrobert "expected": "23", 7276d0caaeSpatrick "filesystem": "17", 7376d0caaeSpatrick "initializer_list": "11", 7476d0caaeSpatrick "optional": "17", 7576d0caaeSpatrick "ranges": "20", 7676d0caaeSpatrick "string_view": "17", 7776d0caaeSpatrick "syncstream": "20", 7876d0caaeSpatrick "system_error": "11", 7976d0caaeSpatrick "thread": "11", 8076d0caaeSpatrick "tuple": "11", 81*4bdff4beSrobert "uchar.h": "11", 8276d0caaeSpatrick "unordered_map": "11", 8376d0caaeSpatrick "unordered_set": "11", 8476d0caaeSpatrick "variant": "17", 8576d0caaeSpatrick} 8676d0caaeSpatrick 8776d0caaeSpatrickassert all(v == sorted(v) for k, v in mandatory_inclusions.items()) 8876d0caaeSpatrick 8976d0caaeSpatrick# Map from each header to the Lit annotations that should be used for 9076d0caaeSpatrick# tests that include that header. 9176d0caaeSpatrick# 92*4bdff4beSrobert# For example, when threads are not supported, any test that includes 93*4bdff4beSrobert# <thread> should be marked as UNSUPPORTED, because including <thread> 94*4bdff4beSrobert# is a hard error in that case. 9576d0caaeSpatricklit_markup = { 96*4bdff4beSrobert "barrier": ["UNSUPPORTED: no-threads"], 97*4bdff4beSrobert "filesystem": ["UNSUPPORTED: no-filesystem"], 9876d0caaeSpatrick "format": ["UNSUPPORTED: libcpp-has-no-incomplete-format"], 99*4bdff4beSrobert "iomanip": ["UNSUPPORTED: no-localization"], 100*4bdff4beSrobert "ios": ["UNSUPPORTED: no-localization"], 101*4bdff4beSrobert "iostream": ["UNSUPPORTED: no-localization"], 102*4bdff4beSrobert "istream": ["UNSUPPORTED: no-localization"], 103*4bdff4beSrobert "latch": ["UNSUPPORTED: no-threads"], 104*4bdff4beSrobert "locale": ["UNSUPPORTED: no-localization"], 105*4bdff4beSrobert "mutex": ["UNSUPPORTED: no-threads"], 106*4bdff4beSrobert "ostream": ["UNSUPPORTED: no-localization"], 107*4bdff4beSrobert "regex": ["UNSUPPORTED: no-localization"], 108*4bdff4beSrobert "semaphore": ["UNSUPPORTED: no-threads"], 109*4bdff4beSrobert "shared_mutex": ["UNSUPPORTED: no-threads"], 110*4bdff4beSrobert "thread": ["UNSUPPORTED: no-threads"] 11176d0caaeSpatrick} 11276d0caaeSpatrick 11376d0caaeSpatrick 11476d0caaeSpatrickdef get_std_ver_test(includee): 11576d0caaeSpatrick v = new_in_version.get(includee, "03") 11676d0caaeSpatrick if v == "03": 11776d0caaeSpatrick return '' 11876d0caaeSpatrick versions = ["03", "11", "14", "17", "20"] 11976d0caaeSpatrick return 'TEST_STD_VER > {} && '.format(max(i for i in versions if i < v)) 12076d0caaeSpatrick 12176d0caaeSpatrick 12276d0caaeSpatrickdef get_unsupported_line(includee): 12376d0caaeSpatrick v = new_in_version.get(includee, "03") 12476d0caaeSpatrick return { 12576d0caaeSpatrick "03": [], 12676d0caaeSpatrick "11": ['UNSUPPORTED: c++03'], 12776d0caaeSpatrick "14": ['UNSUPPORTED: c++03, c++11'], 12876d0caaeSpatrick "17": ['UNSUPPORTED: c++03, c++11, c++14'], 12976d0caaeSpatrick "20": ['UNSUPPORTED: c++03, c++11, c++14, c++17'], 13076d0caaeSpatrick "2b": ['UNSUPPORTED: c++03, c++11, c++14, c++17, c++20'], 13176d0caaeSpatrick }[v] 13276d0caaeSpatrick 13376d0caaeSpatrick 13476d0caaeSpatrickdef get_libcpp_header_symbol(header_name): 13576d0caaeSpatrick return '_LIBCPP_' + header_name.upper().replace('.', '_') 13676d0caaeSpatrick 13776d0caaeSpatrick 13876d0caaeSpatrickdef get_includer_symbol_test(includer): 13976d0caaeSpatrick symbol = get_libcpp_header_symbol(includer) 14076d0caaeSpatrick return """ 14176d0caaeSpatrick#if !defined({symbol}) 14276d0caaeSpatrick # error "{message}" 14376d0caaeSpatrick#endif 14476d0caaeSpatrick """.strip().format( 14576d0caaeSpatrick symbol=symbol, 14676d0caaeSpatrick message="<{}> was expected to define {}".format(includer, symbol), 14776d0caaeSpatrick ) 14876d0caaeSpatrick 14976d0caaeSpatrick 15076d0caaeSpatrickdef get_ifdef(includer, includee): 15176d0caaeSpatrick version = max(new_in_version.get(h, "03") for h in [includer, includee]) 15276d0caaeSpatrick symbol = get_libcpp_header_symbol(includee) 15376d0caaeSpatrick return """ 15476d0caaeSpatrick#if {includee_test}!defined({symbol}) 15576d0caaeSpatrick # error "{message}" 15676d0caaeSpatrick#endif 15776d0caaeSpatrick """.strip().format( 15876d0caaeSpatrick includee_test=get_std_ver_test(includee), 15976d0caaeSpatrick symbol=symbol, 16076d0caaeSpatrick message="<{}> should include <{}> in C++{} and later".format(includer, includee, version) 16176d0caaeSpatrick ) 16276d0caaeSpatrick 16376d0caaeSpatrick 16476d0caaeSpatricktest_body_template = """ 16576d0caaeSpatrick//===----------------------------------------------------------------------===// 16676d0caaeSpatrick// 16776d0caaeSpatrick// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 16876d0caaeSpatrick// See https://llvm.org/LICENSE.txt for license information. 16976d0caaeSpatrick// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 17076d0caaeSpatrick// 17176d0caaeSpatrick//===----------------------------------------------------------------------===// 17276d0caaeSpatrick// 17376d0caaeSpatrick// WARNING: This test was generated by {script_name} 17476d0caaeSpatrick// and should not be edited manually. 17576d0caaeSpatrick// 17676d0caaeSpatrick// clang-format off 17776d0caaeSpatrick{markup} 17876d0caaeSpatrick// <{header}> 17976d0caaeSpatrick 18076d0caaeSpatrick// Test that <{header}> includes all the other headers it's supposed to. 18176d0caaeSpatrick 18276d0caaeSpatrick#include <{header}> 18376d0caaeSpatrick#include "test_macros.h" 18476d0caaeSpatrick 18576d0caaeSpatrick{test_includers_symbol} 18676d0caaeSpatrick{test_per_includee} 18776d0caaeSpatrick""".strip() 18876d0caaeSpatrick 18976d0caaeSpatrick 19076d0caaeSpatrickdef produce_tests(): 19176d0caaeSpatrick for includer, includees in mandatory_inclusions.items(): 19276d0caaeSpatrick markup_tags = get_unsupported_line(includer) + lit_markup.get(includer, []) 19376d0caaeSpatrick test_body = test_body_template.format( 19476d0caaeSpatrick script_name=script_name, 19576d0caaeSpatrick header=includer, 19676d0caaeSpatrick markup=('\n' + '\n'.join('// ' + m for m in markup_tags) + '\n') if markup_tags else '', 19776d0caaeSpatrick test_includers_symbol=get_includer_symbol_test(includer), 19876d0caaeSpatrick test_per_includee='\n'.join(get_ifdef(includer, includee) for includee in includees), 19976d0caaeSpatrick ) 20076d0caaeSpatrick test_name = "{header}.inclusions.compile.pass.cpp".format(header=includer) 20176d0caaeSpatrick out_path = os.path.join(test_path, test_name) 20276d0caaeSpatrick with open(out_path, 'w', newline='\n') as f: 20376d0caaeSpatrick f.write(test_body + '\n') 20476d0caaeSpatrick 20576d0caaeSpatrick 20676d0caaeSpatrickif __name__ == '__main__': 20776d0caaeSpatrick produce_tests() 208