diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -659,7 +659,7 @@ } def get_std_dialects(): - std_dialects = ['c++14', 'c++17', 'c++20', 'c++2b'] + std_dialects = ['c++11','c++14', 'c++17', 'c++20', 'c++2b'] return list(std_dialects) def get_first_std(d): @@ -705,6 +705,8 @@ return d[s] return None +def get_std_nr(std): + return std.replace('c++', '') """ Functions to produce the header @@ -733,7 +735,22 @@ result += "\n" if 'depends' in tc.keys(): result += "# endif\n" - return result + return result.strip() + +def produce_macros_definitions(): + macro_definition_template = """#if _LIBCPP_STD_VER > {previous_std_nr} +{macro_definition} +#endif""" + + std_dialects = get_std_dialects() + + macros_definitions = [] + for previous, current in zip(std_dialects, std_dialects[1:]): + macros_definitions.append( + macro_definition_template.format(previous_std_nr=get_std_nr(previous), + macro_definition=produce_macros_definition_for_std(current))) + + return '\n\n'.join(macros_definitions) def chunks(l, n): """Yield successive n-sized chunks from l.""" @@ -800,31 +817,14 @@ #pragma GCC system_header #endif -#if _LIBCPP_STD_VER > 11 -{cxx14_macros} -#endif - -#if _LIBCPP_STD_VER > 14 -{cxx17_macros} -#endif - -#if _LIBCPP_STD_VER > 17 -{cxx20_macros} -#endif - -#if _LIBCPP_STD_VER > 20 -{cxx2b_macros} -#endif +{cxx_macros} #endif // _LIBCPP_VERSIONH """ version_str = template.format( synopsis=produce_version_synopsis().strip(), - cxx14_macros=produce_macros_definition_for_std('c++14').strip(), - cxx17_macros=produce_macros_definition_for_std('c++17').strip(), - cxx20_macros=produce_macros_definition_for_std('c++20').strip(), - cxx2b_macros=produce_macros_definition_for_std('c++2b').strip()) + cxx_macros=produce_macros_definitions()) version_header_path = os.path.join(include_path, 'version') with open(version_header_path, 'w', newline='\n') as f: f.write(version_str) @@ -895,7 +895,36 @@ result += test_types["depends"].format(name=tc["name"], value=val, std=std, depends=tc["depends"]) else: result += test_types["defined"].format(name=tc["name"], value=val, std=std) - return result + return result.strip() + +def generate_std_tests(test_list): + std_tests_template = """#if TEST_STD_VER < {second_std_nr} + +{first_std_test} + +{other_std_tests} + +#elif TEST_STD_VER > {penultimate_std_nr} + +{last_std_test} + +#endif // TEST_STD_VER > {penultimate_std_nr}""" + + std_dialects = get_std_dialects() + assert not get_std_nr(std_dialects[-1]).isnumeric() + + other_std_tests = [] + for std in std_dialects[1:-1]: + other_std_tests.append('#elif TEST_STD_VER == ' + get_std_nr(std)) + other_std_tests.append(generate_std_test(test_list, std)) + + std_tests = std_tests_template.format(second_std_nr=get_std_nr(std_dialects[1]), + first_std_test=generate_std_test(test_list, std_dialects[0]), + other_std_tests='\n\n'.join(other_std_tests), + penultimate_std_nr=get_std_nr(std_dialects[-2]), + last_std_test=generate_std_test(test_list, std_dialects[-1])) + + return std_tests def generate_synopsis(test_list): max_name_len = max([len(tc["name"]) for tc in test_list]) @@ -943,38 +972,14 @@ #include <{header}> #include "test_macros.h" -#if TEST_STD_VER < 14 - -{cxx11_tests} - -#elif TEST_STD_VER == 14 - -{cxx14_tests} - -#elif TEST_STD_VER == 17 - -{cxx17_tests} - -#elif TEST_STD_VER == 20 - -{cxx20_tests} - -#elif TEST_STD_VER > 20 - -{cxx2b_tests} - -#endif // TEST_STD_VER > 20 +{cxx_tests} int main(int, char**) {{ return 0; }} """.format(script_name=script_name, header=h, markup=('\n{}\n'.format(markup) if markup else ''), synopsis=generate_synopsis(test_list), - cxx11_tests=generate_std_test(test_list, 'c++11').strip(), - cxx14_tests=generate_std_test(test_list, 'c++14').strip(), - cxx17_tests=generate_std_test(test_list, 'c++17').strip(), - cxx20_tests=generate_std_test(test_list, 'c++20').strip(), - cxx2b_tests=generate_std_test(test_list, 'c++2b').strip()) + cxx_tests=generate_std_tests(test_list)) test_name = "{header}.version.pass.cpp".format(header=h) out_path = os.path.join(macro_test_path, test_name) with open(out_path, 'w', newline='\n') as f: @@ -1023,7 +1028,7 @@ def get_status_table(): table = [["Macro Name", "Value"]] - for std in get_std_dialects(): + for std in get_std_dialects()[1:]: table += [["**" + std.replace("c++", "C++ ") + "**", ""]] for tc in feature_test_macros: if std not in tc["values"].keys():