[libcxx-commits] [libcxx] b12d68e - [libc++] Implements the new FTM header test generator. (#134542)
via libcxx-commits
libcxx-commits at lists.llvm.org
Sun May 18 09:21:24 PDT 2025
Author: Mark de Wever
Date: 2025-05-18T18:21:20+02:00
New Revision: b12d68e0b253b4dc6c3fd9d99ee8421605e274aa
URL: https://github.com/llvm/llvm-project/commit/b12d68e0b253b4dc6c3fd9d99ee8421605e274aa
DIFF: https://github.com/llvm/llvm-project/commit/b12d68e0b253b4dc6c3fd9d99ee8421605e274aa.diff
LOG: [libc++] Implements the new FTM header test generator. (#134542)
This generator has almost identical output to the existing script.
Notable differences are
- conditionally include headers that are not implemented yet
- removes the synopsis
- uses 2 spaces indent in `# if`
There are a few more test macros added that triggered bugs in existing
FTM.
Added:
libcxx/test/libcxx/feature_test_macro/generate_header_test.sh.py
libcxx/test/libcxx/feature_test_macro/standard_library_headers.sh.py
Modified:
libcxx/test/libcxx/feature_test_macro/ftm_metadata.sh.py
libcxx/test/libcxx/feature_test_macro/implemented_ftms.sh.py
libcxx/test/libcxx/feature_test_macro/invalid.sh.py
libcxx/test/libcxx/feature_test_macro/is_implemented.sh.py
libcxx/test/libcxx/feature_test_macro/standard_ftms.sh.py
libcxx/test/libcxx/feature_test_macro/std_dialects.sh.py
libcxx/test/libcxx/feature_test_macro/test_data.json
libcxx/test/libcxx/feature_test_macro/version_header.sh.py
libcxx/test/libcxx/feature_test_macro/version_header_implementation.sh.py
libcxx/utils/generate_feature_test_macro_components.py
Removed:
################################################################################
diff --git a/libcxx/test/libcxx/feature_test_macro/ftm_metadata.sh.py b/libcxx/test/libcxx/feature_test_macro/ftm_metadata.sh.py
index 52696d8bc3605..f727f9a2d9e0e 100644
--- a/libcxx/test/libcxx/feature_test_macro/ftm_metadata.sh.py
+++ b/libcxx/test/libcxx/feature_test_macro/ftm_metadata.sh.py
@@ -21,32 +21,58 @@
class Test(unittest.TestCase):
def setUp(self):
- self.ftm = FeatureTestMacros(TEST_DATA)
+ self.ftm = FeatureTestMacros(TEST_DATA, ["charconv"])
self.maxDiff = None # This causes the
diff to be printed when the test fails
def test_implementation(self):
expected = {
"__cpp_lib_any": Metadata(
- headers=["any"], test_suite_guard=None, libcxx_guard=None
+ headers=["any"],
+ available_since="c++17",
+ test_suite_guard=None,
+ libcxx_guard=None,
),
"__cpp_lib_barrier": Metadata(
headers=["barrier"],
+ available_since="c++20",
test_suite_guard="!defined(_LIBCPP_VERSION) || (_LIBCPP_HAS_THREADS && _LIBCPP_AVAILABILITY_HAS_SYNC)",
libcxx_guard="_LIBCPP_HAS_THREADS && _LIBCPP_AVAILABILITY_HAS_SYNC",
),
+ "__cpp_lib_clamp": Metadata(
+ headers=["algorithm"],
+ available_since="c++17",
+ test_suite_guard=None,
+ libcxx_guard=None,
+ ),
"__cpp_lib_format": Metadata(
- headers=["format"], test_suite_guard=None, libcxx_guard=None
+ headers=["format"],
+ available_since="c++20",
+ test_suite_guard=None,
+ libcxx_guard=None,
),
"__cpp_lib_parallel_algorithm": Metadata(
headers=["algorithm", "numeric"],
+ available_since="c++17",
+ test_suite_guard=None,
+ libcxx_guard=None,
+ ),
+ "__cpp_lib_to_chars": Metadata(
+ headers=["charconv"],
+ available_since="c++17",
test_suite_guard=None,
libcxx_guard=None,
),
"__cpp_lib_variant": Metadata(
- headers=["variant"], test_suite_guard=None, libcxx_guard=None
+ headers=["variant"],
+ available_since="c++17",
+ test_suite_guard=None,
+ libcxx_guard=None,
),
- "__cpp_lib_missing_FTM_in_older_standard": Metadata(
- headers=[], test_suite_guard=None, libcxx_guard=None
+ "__cpp_lib_zz_missing_FTM_in_older_standard": Metadata(
+ headers=[],
+ available_since="c++17",
+ test_suite_guard=None,
+ libcxx_guard=None,
),
}
self.assertEqual(self.ftm.ftm_metadata, expected)
diff --git a/libcxx/test/libcxx/feature_test_macro/generate_header_test.sh.py b/libcxx/test/libcxx/feature_test_macro/generate_header_test.sh.py
new file mode 100644
index 0000000000000..98acfeacd0181
--- /dev/null
+++ b/libcxx/test/libcxx/feature_test_macro/generate_header_test.sh.py
@@ -0,0 +1,636 @@
+# ===----------------------------------------------------------------------===##
+#
+# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+# See https://llvm.org/LICENSE.txt for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+# ===----------------------------------------------------------------------===##
+
+# RUN: %{python} %s %{libcxx-dir}/utils %{libcxx-dir}/test/libcxx/feature_test_macro/test_data.json %t/tests
+
+import os
+import sys
+import unittest
+
+UTILS = sys.argv[1]
+TEST_DATA = sys.argv[2]
+OUTPUT_PATH = sys.argv[3]
+del sys.argv[1:4]
+
+sys.path.append(UTILS)
+from generate_feature_test_macro_components import FeatureTestMacros
+
+
+class Test(unittest.TestCase):
+ def setUp(self):
+ self.ftm = FeatureTestMacros(TEST_DATA, ["charconv"])
+ self.maxDiff = None # This causes the
diff to be printed when the test fails
+
+ self.expected = dict(
+ {
+ "algorithm": """\
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// WARNING: This test was generated by generate_feature_test_macro_components.py
+// and should not be edited manually.
+
+// <algorithm>
+
+// Test the feature test macros defined by <algorithm>
+
+// clang-format off
+
+#include <algorithm>
+#include "test_macros.h"
+
+#if TEST_STD_VER < 17
+
+# ifdef __cpp_lib_clamp
+# error "__cpp_lib_clamp should not be defined before c++17"
+# endif
+
+# ifdef __cpp_lib_parallel_algorithm
+# error "__cpp_lib_parallel_algorithm should not be defined before c++17"
+# endif
+
+#elif TEST_STD_VER == 17
+
+# ifndef __cpp_lib_clamp
+# error "__cpp_lib_clamp should be defined in c++17"
+# endif
+# if __cpp_lib_clamp != 201603L
+# error "__cpp_lib_clamp should have the value 201603L in c++17"
+# endif
+
+# ifndef __cpp_lib_parallel_algorithm
+# error "__cpp_lib_parallel_algorithm should be defined in c++17"
+# endif
+# if __cpp_lib_parallel_algorithm != 201603L
+# error "__cpp_lib_parallel_algorithm should have the value 201603L in c++17"
+# endif
+
+#elif TEST_STD_VER == 20
+
+# ifndef __cpp_lib_clamp
+# error "__cpp_lib_clamp should be defined in c++20"
+# endif
+# if __cpp_lib_clamp != 201603L
+# error "__cpp_lib_clamp should have the value 201603L in c++20"
+# endif
+
+# ifndef __cpp_lib_parallel_algorithm
+# error "__cpp_lib_parallel_algorithm should be defined in c++20"
+# endif
+# if __cpp_lib_parallel_algorithm != 201603L
+# error "__cpp_lib_parallel_algorithm should have the value 201603L in c++20"
+# endif
+
+#elif TEST_STD_VER == 23
+
+# ifndef __cpp_lib_clamp
+# error "__cpp_lib_clamp should be defined in c++23"
+# endif
+# if __cpp_lib_clamp != 201603L
+# error "__cpp_lib_clamp should have the value 201603L in c++23"
+# endif
+
+# ifndef __cpp_lib_parallel_algorithm
+# error "__cpp_lib_parallel_algorithm should be defined in c++23"
+# endif
+# if __cpp_lib_parallel_algorithm != 201603L
+# error "__cpp_lib_parallel_algorithm should have the value 201603L in c++23"
+# endif
+
+#elif TEST_STD_VER > 23
+
+# ifndef __cpp_lib_clamp
+# error "__cpp_lib_clamp should be defined in c++26"
+# endif
+# if __cpp_lib_clamp != 201603L
+# error "__cpp_lib_clamp should have the value 201603L in c++26"
+# endif
+
+# ifndef __cpp_lib_parallel_algorithm
+# error "__cpp_lib_parallel_algorithm should be defined in c++26"
+# endif
+# if __cpp_lib_parallel_algorithm != 201603L
+# error "__cpp_lib_parallel_algorithm should have the value 201603L in c++26"
+# endif
+
+#endif // TEST_STD_VER > 23
+
+// clang-format on
+
+""",
+ "any": """\
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// WARNING: This test was generated by generate_feature_test_macro_components.py
+// and should not be edited manually.
+
+// <any>
+
+// Test the feature test macros defined by <any>
+
+// clang-format off
+
+#include <any>
+#include "test_macros.h"
+
+#if TEST_STD_VER < 17
+
+# ifdef __cpp_lib_any
+# error "__cpp_lib_any should not be defined before c++17"
+# endif
+
+#elif TEST_STD_VER == 17
+
+# ifndef __cpp_lib_any
+# error "__cpp_lib_any should be defined in c++17"
+# endif
+# if __cpp_lib_any != 201606L
+# error "__cpp_lib_any should have the value 201606L in c++17"
+# endif
+
+#elif TEST_STD_VER == 20
+
+# ifndef __cpp_lib_any
+# error "__cpp_lib_any should be defined in c++20"
+# endif
+# if __cpp_lib_any != 201606L
+# error "__cpp_lib_any should have the value 201606L in c++20"
+# endif
+
+#elif TEST_STD_VER == 23
+
+# ifndef __cpp_lib_any
+# error "__cpp_lib_any should be defined in c++23"
+# endif
+# if __cpp_lib_any != 201606L
+# error "__cpp_lib_any should have the value 201606L in c++23"
+# endif
+
+#elif TEST_STD_VER > 23
+
+# ifndef __cpp_lib_any
+# error "__cpp_lib_any should be defined in c++26"
+# endif
+# if __cpp_lib_any != 201606L
+# error "__cpp_lib_any should have the value 201606L in c++26"
+# endif
+
+#endif // TEST_STD_VER > 23
+
+// clang-format on
+
+""",
+ "barrier": """\
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// WARNING: This test was generated by generate_feature_test_macro_components.py
+// and should not be edited manually.
+
+// UNSUPPORTED: no-threads
+
+// <barrier>
+
+// Test the feature test macros defined by <barrier>
+
+// clang-format off
+
+#include <barrier>
+#include "test_macros.h"
+
+#if TEST_STD_VER < 17
+
+# ifdef __cpp_lib_barrier
+# error "__cpp_lib_barrier should not be defined before c++20"
+# endif
+
+#elif TEST_STD_VER == 17
+
+# ifdef __cpp_lib_barrier
+# error "__cpp_lib_barrier should not be defined before c++20"
+# endif
+
+#elif TEST_STD_VER == 20
+
+# if !defined(_LIBCPP_VERSION) || (_LIBCPP_HAS_THREADS && _LIBCPP_AVAILABILITY_HAS_SYNC)
+# ifndef __cpp_lib_barrier
+# error "__cpp_lib_barrier should be defined in c++20"
+# endif
+# if __cpp_lib_barrier != 201907L
+# error "__cpp_lib_barrier should have the value 201907L in c++20"
+# endif
+# else
+# ifdef __cpp_lib_barrier
+# error "__cpp_lib_barrier should not be defined when the requirement '!defined(_LIBCPP_VERSION) || (_LIBCPP_HAS_THREADS && _LIBCPP_AVAILABILITY_HAS_SYNC)' is not met!"
+# endif
+# endif
+
+#elif TEST_STD_VER == 23
+
+# if !defined(_LIBCPP_VERSION) || (_LIBCPP_HAS_THREADS && _LIBCPP_AVAILABILITY_HAS_SYNC)
+# ifndef __cpp_lib_barrier
+# error "__cpp_lib_barrier should be defined in c++23"
+# endif
+# if __cpp_lib_barrier != 201907L
+# error "__cpp_lib_barrier should have the value 201907L in c++23"
+# endif
+# else
+# ifdef __cpp_lib_barrier
+# error "__cpp_lib_barrier should not be defined when the requirement '!defined(_LIBCPP_VERSION) || (_LIBCPP_HAS_THREADS && _LIBCPP_AVAILABILITY_HAS_SYNC)' is not met!"
+# endif
+# endif
+
+#elif TEST_STD_VER > 23
+
+# if !defined(_LIBCPP_VERSION) || (_LIBCPP_HAS_THREADS && _LIBCPP_AVAILABILITY_HAS_SYNC)
+# ifndef __cpp_lib_barrier
+# error "__cpp_lib_barrier should be defined in c++26"
+# endif
+# if __cpp_lib_barrier != 299900L
+# error "__cpp_lib_barrier should have the value 299900L in c++26"
+# endif
+# else
+# ifdef __cpp_lib_barrier
+# error "__cpp_lib_barrier should not be defined when the requirement '!defined(_LIBCPP_VERSION) || (_LIBCPP_HAS_THREADS && _LIBCPP_AVAILABILITY_HAS_SYNC)' is not met!"
+# endif
+# endif
+
+#endif // TEST_STD_VER > 23
+
+// clang-format on
+
+""",
+ "charconv": """\
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// WARNING: This test was generated by generate_feature_test_macro_components.py
+// and should not be edited manually.
+
+// <charconv>
+
+// Test the feature test macros defined by <charconv>
+
+// clang-format off
+
+#if !defined(_WIN32) && __has_include(<charconv>)
+# include <charconv>
+#endif
+#include "test_macros.h"
+
+#if TEST_STD_VER < 17
+
+# ifdef __cpp_lib_to_chars
+# error "__cpp_lib_to_chars should not be defined before c++17"
+# endif
+
+#elif TEST_STD_VER == 17
+
+# if !defined(_LIBCPP_VERSION)
+# ifndef __cpp_lib_to_chars
+# error "__cpp_lib_to_chars should be defined in c++17"
+# endif
+# if __cpp_lib_to_chars != 201611L
+# error "__cpp_lib_to_chars should have the value 201611L in c++17"
+# endif
+# else
+# ifdef __cpp_lib_to_chars
+# error "__cpp_lib_to_chars should not be defined because it is unimplemented in libc++!"
+# endif
+# endif
+
+#elif TEST_STD_VER == 20
+
+# if !defined(_LIBCPP_VERSION)
+# ifndef __cpp_lib_to_chars
+# error "__cpp_lib_to_chars should be defined in c++20"
+# endif
+# if __cpp_lib_to_chars != 201611L
+# error "__cpp_lib_to_chars should have the value 201611L in c++20"
+# endif
+# else
+# ifdef __cpp_lib_to_chars
+# error "__cpp_lib_to_chars should not be defined because it is unimplemented in libc++!"
+# endif
+# endif
+
+#elif TEST_STD_VER == 23
+
+# if !defined(_LIBCPP_VERSION)
+# ifndef __cpp_lib_to_chars
+# error "__cpp_lib_to_chars should be defined in c++23"
+# endif
+# if __cpp_lib_to_chars != 201611L
+# error "__cpp_lib_to_chars should have the value 201611L in c++23"
+# endif
+# else
+# ifdef __cpp_lib_to_chars
+# error "__cpp_lib_to_chars should not be defined because it is unimplemented in libc++!"
+# endif
+# endif
+
+#elif TEST_STD_VER > 23
+
+# if !defined(_LIBCPP_VERSION)
+# ifndef __cpp_lib_to_chars
+# error "__cpp_lib_to_chars should be defined in c++26"
+# endif
+# if __cpp_lib_to_chars != 201611L
+# error "__cpp_lib_to_chars should have the value 201611L in c++26"
+# endif
+# else
+# ifdef __cpp_lib_to_chars
+# error "__cpp_lib_to_chars should not be defined because it is unimplemented in libc++!"
+# endif
+# endif
+
+#endif // TEST_STD_VER > 23
+
+// clang-format on
+
+""",
+ "format": """\
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// WARNING: This test was generated by generate_feature_test_macro_components.py
+// and should not be edited manually.
+
+// <format>
+
+// Test the feature test macros defined by <format>
+
+// clang-format off
+
+#include <format>
+#include "test_macros.h"
+
+#if TEST_STD_VER < 17
+
+# ifdef __cpp_lib_format
+# error "__cpp_lib_format should not be defined before c++20"
+# endif
+
+#elif TEST_STD_VER == 17
+
+# ifdef __cpp_lib_format
+# error "__cpp_lib_format should not be defined before c++20"
+# endif
+
+#elif TEST_STD_VER == 20
+
+# if !defined(_LIBCPP_VERSION)
+# ifndef __cpp_lib_format
+# error "__cpp_lib_format should be defined in c++20"
+# endif
+# if __cpp_lib_format != 202110L
+# error "__cpp_lib_format should have the value 202110L in c++20"
+# endif
+# else
+# ifdef __cpp_lib_format
+# error "__cpp_lib_format should not be defined because it is unimplemented in libc++!"
+# endif
+# endif
+
+#elif TEST_STD_VER == 23
+
+# if !defined(_LIBCPP_VERSION)
+# ifndef __cpp_lib_format
+# error "__cpp_lib_format should be defined in c++23"
+# endif
+# if __cpp_lib_format != 202207L
+# error "__cpp_lib_format should have the value 202207L in c++23"
+# endif
+# else
+# ifdef __cpp_lib_format
+# error "__cpp_lib_format should not be defined because it is unimplemented in libc++!"
+# endif
+# endif
+
+#elif TEST_STD_VER > 23
+
+# if !defined(_LIBCPP_VERSION)
+# ifndef __cpp_lib_format
+# error "__cpp_lib_format should be defined in c++26"
+# endif
+# if __cpp_lib_format != 202311L
+# error "__cpp_lib_format should have the value 202311L in c++26"
+# endif
+# else
+# ifdef __cpp_lib_format
+# error "__cpp_lib_format should not be defined because it is unimplemented in libc++!"
+# endif
+# endif
+
+#endif // TEST_STD_VER > 23
+
+// clang-format on
+
+""",
+ "numeric": """\
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// WARNING: This test was generated by generate_feature_test_macro_components.py
+// and should not be edited manually.
+
+// <numeric>
+
+// Test the feature test macros defined by <numeric>
+
+// clang-format off
+
+#include <numeric>
+#include "test_macros.h"
+
+#if TEST_STD_VER < 17
+
+# ifdef __cpp_lib_parallel_algorithm
+# error "__cpp_lib_parallel_algorithm should not be defined before c++17"
+# endif
+
+#elif TEST_STD_VER == 17
+
+# ifndef __cpp_lib_parallel_algorithm
+# error "__cpp_lib_parallel_algorithm should be defined in c++17"
+# endif
+# if __cpp_lib_parallel_algorithm != 201603L
+# error "__cpp_lib_parallel_algorithm should have the value 201603L in c++17"
+# endif
+
+#elif TEST_STD_VER == 20
+
+# ifndef __cpp_lib_parallel_algorithm
+# error "__cpp_lib_parallel_algorithm should be defined in c++20"
+# endif
+# if __cpp_lib_parallel_algorithm != 201603L
+# error "__cpp_lib_parallel_algorithm should have the value 201603L in c++20"
+# endif
+
+#elif TEST_STD_VER == 23
+
+# ifndef __cpp_lib_parallel_algorithm
+# error "__cpp_lib_parallel_algorithm should be defined in c++23"
+# endif
+# if __cpp_lib_parallel_algorithm != 201603L
+# error "__cpp_lib_parallel_algorithm should have the value 201603L in c++23"
+# endif
+
+#elif TEST_STD_VER > 23
+
+# ifndef __cpp_lib_parallel_algorithm
+# error "__cpp_lib_parallel_algorithm should be defined in c++26"
+# endif
+# if __cpp_lib_parallel_algorithm != 201603L
+# error "__cpp_lib_parallel_algorithm should have the value 201603L in c++26"
+# endif
+
+#endif // TEST_STD_VER > 23
+
+// clang-format on
+
+""",
+ "variant": """\
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// WARNING: This test was generated by generate_feature_test_macro_components.py
+// and should not be edited manually.
+
+// <variant>
+
+// Test the feature test macros defined by <variant>
+
+// clang-format off
+
+#include <variant>
+#include "test_macros.h"
+
+#if TEST_STD_VER < 17
+
+# ifdef __cpp_lib_variant
+# error "__cpp_lib_variant should not be defined before c++17"
+# endif
+
+#elif TEST_STD_VER == 17
+
+# ifndef __cpp_lib_variant
+# error "__cpp_lib_variant should be defined in c++17"
+# endif
+# if __cpp_lib_variant != 202102L
+# error "__cpp_lib_variant should have the value 202102L in c++17"
+# endif
+
+#elif TEST_STD_VER == 20
+
+# if !defined(_LIBCPP_VERSION)
+# ifndef __cpp_lib_variant
+# error "__cpp_lib_variant should be defined in c++20"
+# endif
+# if __cpp_lib_variant != 202106L
+# error "__cpp_lib_variant should have the value 202106L in c++20"
+# endif
+# else
+# ifdef __cpp_lib_variant
+# error "__cpp_lib_variant should not be defined because it is unimplemented in libc++!"
+# endif
+# endif
+
+#elif TEST_STD_VER == 23
+
+# if !defined(_LIBCPP_VERSION)
+# ifndef __cpp_lib_variant
+# error "__cpp_lib_variant should be defined in c++23"
+# endif
+# if __cpp_lib_variant != 202106L
+# error "__cpp_lib_variant should have the value 202106L in c++23"
+# endif
+# else
+# ifdef __cpp_lib_variant
+# error "__cpp_lib_variant should not be defined because it is unimplemented in libc++!"
+# endif
+# endif
+
+#elif TEST_STD_VER > 23
+
+# if !defined(_LIBCPP_VERSION)
+# ifndef __cpp_lib_variant
+# error "__cpp_lib_variant should be defined in c++26"
+# endif
+# if __cpp_lib_variant != 202306L
+# error "__cpp_lib_variant should have the value 202306L in c++26"
+# endif
+# else
+# ifdef __cpp_lib_variant
+# error "__cpp_lib_variant should not be defined because it is unimplemented in libc++!"
+# endif
+# endif
+
+#endif // TEST_STD_VER > 23
+
+// clang-format on
+
+""",
+ }
+ )
+
+ def test_implementation(self):
+ # Generate the output
+ self.ftm.generate_header_test_directory(OUTPUT_PATH)
+
+ for key, value in self.expected.items():
+ # Test whether the per header generate function generates the proper output.
+ self.assertEqual(self.ftm.generate_header_test_file(key), value)
+
+ # Test whether all header generate function generates the proper output.
+ with open(
+ os.path.join(OUTPUT_PATH, f"{key}.version.compile.pass.cpp"),
+ "r",
+ newline="\n",
+ ) as f:
+ self.assertEqual(f.read(), value)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/libcxx/test/libcxx/feature_test_macro/implemented_ftms.sh.py b/libcxx/test/libcxx/feature_test_macro/implemented_ftms.sh.py
index 4f445d55c883c..2ca639e95e986 100644
--- a/libcxx/test/libcxx/feature_test_macro/implemented_ftms.sh.py
+++ b/libcxx/test/libcxx/feature_test_macro/implemented_ftms.sh.py
@@ -21,7 +21,7 @@
class Test(unittest.TestCase):
def setUp(self):
- self.ftm = FeatureTestMacros(TEST_DATA)
+ self.ftm = FeatureTestMacros(TEST_DATA, ["charconv"])
self.maxDiff = None # This causes the
diff to be printed when the test fails
def test_implementation(self):
@@ -38,6 +38,12 @@ def test_implementation(self):
"c++23": "201907L",
"c++26": "299900L",
},
+ "__cpp_lib_clamp": {
+ "c++17": "201603L",
+ "c++20": "201603L",
+ "c++23": "201603L",
+ "c++26": "201603L",
+ },
"__cpp_lib_format": {},
"__cpp_lib_parallel_algorithm": {
"c++17": "201603L",
@@ -45,13 +51,14 @@ def test_implementation(self):
"c++23": "201603L",
"c++26": "201603L",
},
+ "__cpp_lib_to_chars": {},
"__cpp_lib_variant": {
"c++17": "202102L",
"c++20": "202102L",
"c++23": "202102L",
"c++26": "202102L",
},
- "__cpp_lib_missing_FTM_in_older_standard": {},
+ "__cpp_lib_zz_missing_FTM_in_older_standard": {},
}
self.assertEqual(self.ftm.implemented_ftms, expected)
diff --git a/libcxx/test/libcxx/feature_test_macro/invalid.sh.py b/libcxx/test/libcxx/feature_test_macro/invalid.sh.py
index ae457f6e1a545..4488af3244dd9 100644
--- a/libcxx/test/libcxx/feature_test_macro/invalid.sh.py
+++ b/libcxx/test/libcxx/feature_test_macro/invalid.sh.py
@@ -23,7 +23,7 @@ def test_error(data, type, message):
tmp = sys.argv[2]
with open(tmp, "w") as file:
file.write(json.dumps(data))
- ftm = FeatureTestMacros(tmp)
+ ftm = FeatureTestMacros(tmp, ["charconv"])
try:
ftm.implemented_ftms
except type as error:
diff --git a/libcxx/test/libcxx/feature_test_macro/is_implemented.sh.py b/libcxx/test/libcxx/feature_test_macro/is_implemented.sh.py
index 0414722b89a76..1ccba5ea74ec4 100644
--- a/libcxx/test/libcxx/feature_test_macro/is_implemented.sh.py
+++ b/libcxx/test/libcxx/feature_test_macro/is_implemented.sh.py
@@ -21,7 +21,7 @@
class Test(unittest.TestCase):
def setUp(self):
- self.ftm = FeatureTestMacros(TEST_DATA)
+ self.ftm = FeatureTestMacros(TEST_DATA, ["charconv"])
self.maxDiff = None # This causes the
diff to be printed when the test fails
def test_implementation(self):
diff --git a/libcxx/test/libcxx/feature_test_macro/standard_ftms.sh.py b/libcxx/test/libcxx/feature_test_macro/standard_ftms.sh.py
index ac3e284261d03..1a8d4437faa0a 100644
--- a/libcxx/test/libcxx/feature_test_macro/standard_ftms.sh.py
+++ b/libcxx/test/libcxx/feature_test_macro/standard_ftms.sh.py
@@ -21,7 +21,7 @@
class Test(unittest.TestCase):
def setUp(self):
- self.ftm = FeatureTestMacros(TEST_DATA)
+ self.ftm = FeatureTestMacros(TEST_DATA, ["charconv"])
self.maxDiff = None # This causes the
diff to be printed when the test fails
def test_implementation(self):
@@ -37,6 +37,12 @@ def test_implementation(self):
"c++23": "201907L",
"c++26": "299900L",
},
+ "__cpp_lib_clamp": {
+ "c++17": "201603L",
+ "c++20": "201603L",
+ "c++23": "201603L",
+ "c++26": "201603L",
+ },
"__cpp_lib_format": {
"c++20": "202110L",
"c++23": "202207L",
@@ -48,13 +54,19 @@ def test_implementation(self):
"c++23": "201603L",
"c++26": "201603L",
},
+ "__cpp_lib_to_chars": {
+ "c++17": "201611L",
+ "c++20": "201611L",
+ "c++23": "201611L",
+ "c++26": "201611L",
+ },
"__cpp_lib_variant": {
"c++17": "202102L",
"c++20": "202106L",
"c++23": "202106L",
"c++26": "202306L",
},
- "__cpp_lib_missing_FTM_in_older_standard": {
+ "__cpp_lib_zz_missing_FTM_in_older_standard": {
"c++17": "2017L",
"c++20": "2020L",
"c++23": "2020L",
diff --git a/libcxx/test/libcxx/feature_test_macro/standard_library_headers.sh.py b/libcxx/test/libcxx/feature_test_macro/standard_library_headers.sh.py
new file mode 100644
index 0000000000000..27a2953a2e321
--- /dev/null
+++ b/libcxx/test/libcxx/feature_test_macro/standard_library_headers.sh.py
@@ -0,0 +1,44 @@
+# ===----------------------------------------------------------------------===##
+#
+# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+# See https://llvm.org/LICENSE.txt for license information.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+# ===----------------------------------------------------------------------===##
+
+# RUN: %{python} %s %{libcxx-dir}/utils %{libcxx-dir}/test/libcxx/feature_test_macro/test_data.json
+
+import sys
+
+import unittest
+
+UTILS = sys.argv[1]
+TEST_DATA = sys.argv[2]
+del sys.argv[1:3]
+
+sys.path.append(UTILS)
+from generate_feature_test_macro_components import FeatureTestMacros, Metadata
+
+
+class Test(unittest.TestCase):
+ def setUp(self):
+ self.ftm = FeatureTestMacros(TEST_DATA, ["charconv"])
+ self.maxDiff = None # This causes the
diff to be printed when the test fails
+
+ def test_implementation(self):
+ self.assertEqual(
+ sorted(self.ftm.standard_library_headers),
+ [
+ "algorithm",
+ "any",
+ "barrier",
+ "charconv",
+ "format",
+ "numeric",
+ "variant",
+ ],
+ )
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/libcxx/test/libcxx/feature_test_macro/std_dialects.sh.py b/libcxx/test/libcxx/feature_test_macro/std_dialects.sh.py
index e3cca860f9ce6..f01dcb2f3c45c 100644
--- a/libcxx/test/libcxx/feature_test_macro/std_dialects.sh.py
+++ b/libcxx/test/libcxx/feature_test_macro/std_dialects.sh.py
@@ -21,7 +21,7 @@
class Test(unittest.TestCase):
def setUp(self):
- self.ftm = FeatureTestMacros(TEST_DATA)
+ self.ftm = FeatureTestMacros(TEST_DATA, ["charconv"])
self.maxDiff = None # This causes the
diff to be printed when the test fails
def test_implementation(self):
diff --git a/libcxx/test/libcxx/feature_test_macro/test_data.json b/libcxx/test/libcxx/feature_test_macro/test_data.json
index fd698c08b2daa..b0122163f714f 100644
--- a/libcxx/test/libcxx/feature_test_macro/test_data.json
+++ b/libcxx/test/libcxx/feature_test_macro/test_data.json
@@ -38,6 +38,19 @@
"test_suite_guard": "!defined(_LIBCPP_VERSION) || (_LIBCPP_HAS_THREADS && _LIBCPP_AVAILABILITY_HAS_SYNC)",
"libcxx_guard": "_LIBCPP_HAS_THREADS && _LIBCPP_AVAILABILITY_HAS_SYNC"
},
+ {
+ "name": "__cpp_lib_clamp",
+ "values": {
+ "c++17": {
+ "201603": [
+ {
+ "implemented": true
+ }
+ ]
+ }
+ },
+ "headers": ["algorithm"]
+ },
{
"name": "__cpp_lib_format",
"values": {
@@ -120,6 +133,19 @@
"numeric"
]
},
+ {
+ "name": "__cpp_lib_to_chars",
+ "values": {
+ "c++17": {
+ "201611": [
+ {
+ "implemented": false
+ }
+ ]
+ }
+ },
+ "headers": ["charconv"]
+ },
{
"name": "__cpp_lib_variant",
"values": {
@@ -155,7 +181,7 @@
]
},
{
- "name": "__cpp_lib_missing_FTM_in_older_standard",
+ "name": "__cpp_lib_zz_missing_FTM_in_older_standard",
"values": {
"c++17": {
"2017": [
diff --git a/libcxx/test/libcxx/feature_test_macro/version_header.sh.py b/libcxx/test/libcxx/feature_test_macro/version_header.sh.py
index e3053c18a5211..fa645c735f0bc 100644
--- a/libcxx/test/libcxx/feature_test_macro/version_header.sh.py
+++ b/libcxx/test/libcxx/feature_test_macro/version_header.sh.py
@@ -21,7 +21,7 @@
class Test(unittest.TestCase):
def setUp(self):
- self.ftm = FeatureTestMacros(TEST_DATA)
+ self.ftm = FeatureTestMacros(TEST_DATA, ["charconv"])
self.maxDiff = None # This causes the
diff to be printed when the test fails
def test_implementeation(self):
@@ -45,9 +45,11 @@ def test_implementeation(self):
#if _LIBCPP_STD_VER >= 17
# define __cpp_lib_any 201606L
+# define __cpp_lib_clamp 201603L
# define __cpp_lib_parallel_algorithm 201603L
+// define __cpp_lib_to_chars 201611L
# define __cpp_lib_variant 202102L
-// define __cpp_lib_missing_FTM_in_older_standard 2017L
+// define __cpp_lib_zz_missing_FTM_in_older_standard 2017L
#endif // _LIBCPP_STD_VER >= 17
#if _LIBCPP_STD_VER >= 20
@@ -56,7 +58,7 @@ def test_implementeation(self):
# endif
// define __cpp_lib_format 202110L
// define __cpp_lib_variant 202106L
-// define __cpp_lib_missing_FTM_in_older_standard 2020L
+// define __cpp_lib_zz_missing_FTM_in_older_standard 2020L
#endif // _LIBCPP_STD_VER >= 20
#if _LIBCPP_STD_VER >= 23
@@ -70,7 +72,7 @@ def test_implementeation(self):
# endif
// define __cpp_lib_format 202311L
// define __cpp_lib_variant 202306L
-// define __cpp_lib_missing_FTM_in_older_standard 2026L
+// define __cpp_lib_zz_missing_FTM_in_older_standard 2026L
#endif // _LIBCPP_STD_VER >= 26
#endif // _LIBCPP_VERSIONH
diff --git a/libcxx/test/libcxx/feature_test_macro/version_header_implementation.sh.py b/libcxx/test/libcxx/feature_test_macro/version_header_implementation.sh.py
index 2ab6a9be7339b..6118a65b78357 100644
--- a/libcxx/test/libcxx/feature_test_macro/version_header_implementation.sh.py
+++ b/libcxx/test/libcxx/feature_test_macro/version_header_implementation.sh.py
@@ -21,7 +21,7 @@
class Test(unittest.TestCase):
def setUp(self):
- self.ftm = FeatureTestMacros(TEST_DATA)
+ self.ftm = FeatureTestMacros(TEST_DATA, ["charconv"])
self.maxDiff = None # This causes the
diff to be printed when the test fails
def test_implementation(self):
@@ -35,6 +35,14 @@ def test_implementation(self):
condition=None,
),
},
+ {
+ "__cpp_lib_clamp": VersionHeader(
+ value="201603L",
+ implemented=True,
+ need_undef=False,
+ condition=None,
+ )
+ },
{
"__cpp_lib_parallel_algorithm": VersionHeader(
value="201603L",
@@ -43,6 +51,14 @@ def test_implementation(self):
condition=None,
),
},
+ {
+ "__cpp_lib_to_chars": VersionHeader(
+ value="201611L",
+ implemented=False,
+ need_undef=False,
+ condition=None,
+ ),
+ },
{
"__cpp_lib_variant": VersionHeader(
value="202102L",
@@ -52,7 +68,7 @@ def test_implementation(self):
),
},
{
- "__cpp_lib_missing_FTM_in_older_standard": VersionHeader(
+ "__cpp_lib_zz_missing_FTM_in_older_standard": VersionHeader(
value="2017L",
implemented=False,
need_undef=False,
@@ -86,7 +102,7 @@ def test_implementation(self):
),
},
{
- "__cpp_lib_missing_FTM_in_older_standard": VersionHeader(
+ "__cpp_lib_zz_missing_FTM_in_older_standard": VersionHeader(
value="2020L",
implemented=False,
need_undef=False,
@@ -130,7 +146,7 @@ def test_implementation(self):
),
},
{
- "__cpp_lib_missing_FTM_in_older_standard": VersionHeader(
+ "__cpp_lib_zz_missing_FTM_in_older_standard": VersionHeader(
value="2026L",
implemented=False,
need_undef=False,
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index cb92dc17ba707..2b7f6fa8a48a9 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -10,6 +10,7 @@
List, # Needed for python 3.8 compatibility.
NewType,
Optional,
+ Set,
)
import functools
import json
@@ -1975,6 +1976,7 @@ def produce_docs():
@dataclass
class Metadata:
headers: List[str] = None
+ available_since: Std = None
test_suite_guard: str = None
libcxx_guard: str = None
@@ -1987,6 +1989,12 @@ class VersionHeader:
condition: str = None
+ at dataclass
+class FtmHeaderTest:
+ value: Value = None
+ implemented: bool = None
+ condition: str = None
+
def get_ftms(
data, std_dialects: List[Std], use_implemented_status: bool
) -> Dict[Ftm, Dict[Std, Optional[Value]]]:
@@ -2077,6 +2085,55 @@ def generate_version_header_implementation(
return "\n\n".join(result)
+#
+# The templates used to create a FTM test file
+#
+
+
+ftm_header_test_file_contents = """//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// WARNING: This test was generated by {script_name}
+// and should not be edited manually.
+
+{lit_markup}// <{header}>
+
+// Test the feature test macros defined by <{header}>
+
+// clang-format off
+
+{include}
+#include "test_macros.h"
+{data}
+
+// clang-format on
+
+"""
+
+
+ftm_header_test_file_include_unconditional = """\
+#include <{header}>\
+"""
+
+# On Windows the Windows SDK is on the include path, that means the MSVC STL
+# headers can be found as well, tricking __has_include into thinking that
+# libc++ provides the header. This means the test is also not executed when
+# using this test with MSVC and MSVC STL.
+ftm_header_test_file_include_conditional = """\
+#if !defined(_WIN32) && __has_include(<{header}>)
+# include <{header}>
+#endif\
+"""
+
+ftm_header_test_file_dialect_block = """
+#{pp_if} TEST_STD_VER {operator} {dialect}
+{tests}\
+"""
class FeatureTestMacros:
"""Provides all feature-test macro (FTM) output components.
@@ -2171,12 +2228,21 @@ class FeatureTestMacros:
# The JSON data structure.
__data = None
-
- def __init__(self, filename: str):
+ # The headers not available in libc++.
+ #
+ # This could be detected based on FTM status, however that gives some odd
+ # results. For example, at the moment __cpp_lib_constexpr_cmath is not
+ # implemented, which flags `<cstdlib>` as not implemented. The availability
+ # of headers is maintained for the C++ Standard Library modules.
+ __unavailable_headers = None
+
+ def __init__(self, filename: str, unavailable_headers: List[str]):
"""Initializes the class with the JSON data in the file 'filename'."""
with open(filename) as f:
self.__data = json.load(f)
+ self.__unavailable_headers = set(unavailable_headers)
+
@functools.cached_property
def std_dialects(self) -> List[Std]:
"""Returns the C++ dialects avaiable.
@@ -2207,6 +2273,17 @@ def standard_ftms(self) -> Dict[Ftm, Dict[Std, Optional[Value]]]:
"""
return get_ftms(self.__data, self.std_dialects, False)
+ @functools.cached_property
+ def standard_library_headers(self) -> Set[str]:
+ """Returns a list of headers that contain at least one FTM."""
+
+ result = set()
+ for value in self.ftm_metadata.values():
+ for header in value.headers:
+ result.add(header)
+
+ return list(result)
+
@functools.cached_property
def implemented_ftms(self) -> Dict[Ftm, Dict[Std, Optional[Value]]]:
"""Returns the FTM versions per dialect implemented in libc++.
@@ -2217,6 +2294,7 @@ def implemented_ftms(self) -> Dict[Ftm, Dict[Std, Optional[Value]]]:
return get_ftms(self.__data, self.std_dialects, True)
+
def is_implemented(self, ftm: Ftm, std: Std) -> bool:
"""Has the FTM `ftm` been implemented in the dialect `std`?"""
@@ -2228,7 +2306,6 @@ def is_implemented(self, ftm: Ftm, std: Std) -> bool:
return self.implemented_ftms[ftm][std] == self.standard_ftms[ftm][std]
-
@functools.cached_property
def ftm_metadata(self) -> Dict[Ftm, Metadata]:
"""Returns the metadata of the FTMs defined in the Standard.
@@ -2239,6 +2316,7 @@ def ftm_metadata(self) -> Dict[Ftm, Metadata]:
for feature in self.__data:
result[feature["name"]] = Metadata(
feature["headers"],
+ list(feature["values"])[0],
feature.get("test_suite_guard", None),
feature.get("libcxx_guard", None),
)
@@ -2306,24 +2384,205 @@ def version_header(self) -> str:
)
)
+ def header_ftm_data(self, header: str) -> Dict[Std, List[Dict[Ftm, FtmHeaderTest]]]:
+ """Generates the FTM information for a `header`."""
+
+ result = dict()
+ for std in self.std_dialects:
+ result[get_std_number(std)] = list()
+
+ for ftm, values in self.standard_ftms.items():
+ if not header in self.ftm_metadata[ftm].headers:
+ continue
+
+ last_value = None
+ last_entry = None
+
+ for std in self.std_dialects:
+ if not std in values.keys():
+ result[get_std_number(std)].append({ftm: None})
+ continue
+
+ result[get_std_number(std)].append(
+ {
+ ftm: FtmHeaderTest(
+ values[std],
+ self.is_implemented(ftm, std),
+ self.ftm_metadata[ftm].test_suite_guard,
+ )
+ }
+ )
+
+ return result
+
+
+ def generate_ftm_test(self, std: Std, ftm: Ftm, value: FtmHeaderTest) -> str:
+ """Adds a single `ftm` test for C++ `std` based on the status information in `value`.
+
+ When std == None this test is generating the TEST_STD_VER < MIN. Where
+ MIN is the minimum version that has a FTM defined. (In the real data
+ this is 14, since FTM have been introduced in C++14.)
+ """
+
+ ftm_unavailable_in_dialect = """
+# ifdef {ftm}
+# error "{ftm} should not be defined before {dialect}"
+# endif
+"""
+
+ ftm_not_implemented = """
+# if !defined(_LIBCPP_VERSION)
+# ifndef {ftm}
+# error "{ftm} should be defined in {dialect}"
+# endif
+# if {ftm} != {value}
+# error "{ftm} should have the value {value} in {dialect}"
+# endif
+# else
+# ifdef {ftm}
+# error "{ftm} should not be defined because it is unimplemented in libc++!"
+# endif
+# endif
+"""
+
+ ftm_conditionally_implemented = """
+# if {condition}
+# ifndef {ftm}
+# error "{ftm} should be defined in {dialect}"
+# endif
+# if {ftm} != {value}
+# error "{ftm} should have the value {value} in {dialect}"
+# endif
+# else
+# ifdef {ftm}
+# error "{ftm} should not be defined when the requirement '{condition}' is not met!"
+# endif
+# endif
+"""
+
+ ftm_implemented = """
+# ifndef {ftm}
+# error "{ftm} should be defined in {dialect}"
+# endif
+# if {ftm} != {value}
+# error "{ftm} should have the value {value} in {dialect}"
+# endif
+"""
+
+ if std == None or value == None:
+ return ftm_unavailable_in_dialect.format(
+ ftm=ftm, dialect=self.ftm_metadata[ftm].available_since
+ )
+
+ if not value.implemented:
+ return ftm_not_implemented.format(
+ ftm=ftm, value=value.value, dialect=std
+ )
+
+ if self.ftm_metadata[ftm].test_suite_guard:
+ return ftm_conditionally_implemented.format(
+ ftm=ftm,
+ value=value.value,
+ dialect=std,
+ condition=self.ftm_metadata[ftm].test_suite_guard,
+ )
+
+ return ftm_implemented.format(ftm=ftm, value=value.value, dialect=std)
+
+ def generate_header_test_dialect(
+ self, std: Std, data: List[Dict[Ftm, FtmHeaderTest]]
+ ) -> str:
+ """Returns the body a single `std` for the FTM test of a `header`."""
+ return "".join(
+ self.generate_ftm_test(std, ftm, value)
+ for element in data
+ for ftm, value in element.items()
+ )
+
+ def generate_lit_markup(self, header:str) -> str:
+ if not header in lit_markup.keys():
+ return ""
+
+ return "\n".join(f"// {markup}" for markup in lit_markup[header]) + "\n\n"
+
+ def generate_header_test_file(self, header: str) -> str:
+ """Returns the body for the FTM test of a `header`."""
+
+ # FTM block before the first Standard that introduced them.
+ # This test the macros are not available before this version.
+ data = ftm_header_test_file_dialect_block.format(
+ pp_if="if",
+ operator="<",
+ dialect=get_std_number(self.std_dialects[0]),
+ tests=self.generate_header_test_dialect(
+ None, next(iter(self.header_ftm_data(header).values()))
+ ),
+ )
+
+ # FTM for all Standards that have FTM defined.
+ # Note in libc++ the TEST_STD_VER contains 99 for the Standard
+ # in development, therefore the last entry uses a
diff erent #elif.
+ data += "".join(
+ ftm_header_test_file_dialect_block.format(
+ pp_if="elif",
+ operator="==" if std != get_std_number(self.std_dialects[-1]) else ">",
+ dialect=std
+ if std != get_std_number(self.std_dialects[-1])
+ else get_std_number(self.std_dialects[-2]),
+ tests=self.generate_header_test_dialect(f"c++{std}", values),
+ )
+ for std, values in self.header_ftm_data(header).items()
+ )
+
+ # The final #endif for the last #elif block.
+ data += f"\n#endif // TEST_STD_VER > {get_std_number(self.std_dialects[-2])}"
+
+ # Generate the test for the requested header.
+ return ftm_header_test_file_contents.format(
+ script_name=script_name,
+ lit_markup=self.generate_lit_markup(header),
+ header=header,
+ include=(
+ ftm_header_test_file_include_conditional.format(header=header)
+ if header in self.__unavailable_headers
+ else ftm_header_test_file_include_unconditional.format(header=header)
+ ),
+ data=data
+ )
+
+ def generate_header_test_directory(self, path: os.path) -> None:
+ """Generates all FTM tests in the directory `path`."""
+
+ if not os.path.exists(path):
+ os.makedirs(path)
+
+ for header in self.standard_library_headers:
+ with open(
+ os.path.join(path, f"{header}.version.compile.pass.cpp"),
+ "w",
+ newline="\n",
+ ) as f:
+ f.write(self.generate_header_test_file(header))
+
def main():
produce_version_header()
produce_tests()
produce_docs()
- # Example how to use the new version header generation function to generate
- # the file.
+ # Example how to use the new generator to generate the output.
if False:
ftm = FeatureTestMacros(
os.path.join(
source_root, "test", "libcxx", "feature_test_macro", "test_data.json"
- )
+ ), headers_not_available
)
version_header_path = os.path.join(include_path, "version")
with open(version_header_path, "w", newline="\n") as f:
f.write(ftm.version_header)
+ ftm.generate_header_test_directory(macro_test_path)
+
if __name__ == "__main__":
main()
More information about the libcxx-commits
mailing list