[libcxx-commits] [libcxx] [libc++] Adds a new feature-test macro generator class. (PR #90889)
Mark de Wever via libcxx-commits
libcxx-commits at lists.llvm.org
Thu May 9 09:38:16 PDT 2024
https://github.com/mordante updated https://github.com/llvm/llvm-project/pull/90889
>From f5c591c4b92371671f687c4a2041c3edcedf1b78 Mon Sep 17 00:00:00 2001
From: Mark de Wever <koraq at xs4all.nl>
Date: Mon, 8 Apr 2024 21:46:06 +0200
Subject: [PATCH 1/2] [RFC][libc++] Testing feature test macro script.
This is a proof-of-concept how we can test the script. Instead of storing
the data in the script it's stored in a JSON file so a different file can
be used for testing.
This is related to the RFC https://github.com/llvm/llvm-project/pull/89499
---
.../test/libcxx/feature_test_macro_csv.sh.py | 35 +++++
.../data/feature_test_macros/test_data.json | 136 ++++++++++++++++++
.../generate_feature_test_macro_components.py | 33 +++++
3 files changed, 204 insertions(+)
create mode 100644 libcxx/test/libcxx/feature_test_macro_csv.sh.py
create mode 100644 libcxx/utils/data/feature_test_macros/test_data.json
diff --git a/libcxx/test/libcxx/feature_test_macro_csv.sh.py b/libcxx/test/libcxx/feature_test_macro_csv.sh.py
new file mode 100644
index 0000000000000..2d80bfad63c85
--- /dev/null
+++ b/libcxx/test/libcxx/feature_test_macro_csv.sh.py
@@ -0,0 +1,35 @@
+# RUN: %{python} %s %{libcxx-dir}/utils %{libcxx-dir}/utils/data/feature_test_macros/test_data.json
+
+import sys
+import json
+
+sys.path.append(sys.argv[1])
+from generate_feature_test_macro_components import get_table
+
+
+data = json.load(open(f"{sys.argv[2]}"))
+table = get_table(data)
+
+expected = {
+ "__cpp_lib_any": {
+ "c++17": "201606L",
+ "c++20": "201606L",
+ "c++23": "201606L",
+ "c++26": "201606L",
+ },
+ "__cpp_lib_barrier": {"c++20": "201907L", "c++23": "201907L", "c++26": "201907L"},
+ "__cpp_lib_format": {
+ "c++20": "",
+ "c++23": "",
+ "c++26": "",
+ },
+ "__cpp_lib_variant": {
+ "c++17": "202102L",
+ "c++20": "202102L",
+ "c++23": "202102L",
+ "c++26": "202102L",
+ },
+}
+
+
+assert table == expected, f"expected\n{expected}\n\nresult\n{table}"
diff --git a/libcxx/utils/data/feature_test_macros/test_data.json b/libcxx/utils/data/feature_test_macros/test_data.json
new file mode 100644
index 0000000000000..5a98fba6403c0
--- /dev/null
+++ b/libcxx/utils/data/feature_test_macros/test_data.json
@@ -0,0 +1,136 @@
+[
+ {
+ "name": "__cpp_lib_any",
+ "values": {
+ "c++17": {
+ "201606": [
+ {
+ "implemented": true
+ }
+ ]
+ }
+ },
+ "headers": [
+ "any"
+ ]
+ },
+ {
+ "name": "__cpp_lib_barrier",
+ "values": {
+ "c++20": {
+ "201907": [
+ {
+ "implemented": true
+ }
+ ]
+ }
+ },
+ "headers": [
+ "barrier"
+ ],
+ "test_suite_guard":
+ "!defined(_LIBCPP_HAS_NO_THREADS) && (!defined(_LIBCPP_VERSION) || _LIBCPP_AVAILABILITY_HAS_SYNC)",
+ "libcxx_guard": "!defined(_LIBCPP_HAS_NO_THREADS) && _LIBCPP_AVAILABILITY_HAS_SYNC"
+ },
+ {
+ "name": "__cpp_lib_format",
+ "values": {
+ "c++20": {
+ "201907": [
+ {
+ "number": "P0645R10",
+ "title": "Text Formatting",
+ "implemented": true
+ },
+ {
+ "number": "P1361R2",
+ "title": "Integration of chrono with text formatting",
+ "implemented": false
+ }
+ ],
+ "202106": [
+ {
+ "number": "P2216R3",
+ "title": "std::format improvements",
+ "implemented": true
+ }
+ ],
+ "202110": [
+ {
+ "number": "P2372R3",
+ "title": "Fixing locale handling in chrono formatters",
+ "implemented": false
+ },
+ {
+ "number": "P2418R2",
+ "title": "FAdd support for std::generator-like types to std::format",
+ "implemented": true
+ }
+ ]
+ },
+ "c++23": {
+ "202207": [
+ {
+ "number": "P2419R2",
+ "title": "Clarify handling of encodings in localized formatting of chrono types",
+ "implemented": false
+ }
+ ]
+ },
+ "c++26": {
+ "202306": [
+ {
+ "number": "P2637R3",
+ "title": "Member Visit",
+ "implemented": true
+ }
+ ],
+ "202311": [
+ {
+ "number": "P2918R2",
+ "title": "Runtime format strings II",
+ "implemented": true
+ }
+ ]
+ }
+ },
+ "headers": [
+ "format"
+ ]
+ },
+ {
+ "name": "__cpp_lib_variant",
+ "values": {
+ "c++17": {
+ "202102": [
+ {
+ "number": "",
+ "title": "``std::visit`` for classes derived from ``std::variant``",
+ "implemented": true
+ }
+ ]
+ },
+ "c++20": {
+ "202106": [
+ {
+ "number": "",
+ "title": "Fully constexpr ``std::variant``",
+ "implemented": false
+ }
+ ]
+ },
+ "c++26": {
+ "202306": [
+ {
+ "number": "",
+ "title": "Member visit",
+ "implemented": true
+ }
+ ]
+ }
+ },
+ "headers": [
+ "variant"
+ ]
+ }
+]
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index f2b8d55c0e11b..04a8a8786b1a3 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -3,6 +3,7 @@
import os
from builtins import range
from functools import reduce
+import json
def get_libcxx_paths():
@@ -1857,6 +1858,38 @@ def produce_docs():
f.write(doc_str)
+def get_table(data):
+ result = dict()
+ for feature in data:
+ last = None
+ entry = dict()
+ implemented = True
+ for std in get_std_dialects():
+ if std not in feature["values"].keys():
+ if last == None:
+ continue
+ else:
+ entry[std] = last
+ else:
+ if last == None:
+ last = ""
+ if implemented:
+ for value in feature["values"][std]:
+ for paper in list(feature["values"][std][value]):
+ if not paper["implemented"]:
+ implemented = False
+ break
+ if implemented:
+ last = f"{value}L"
+ else:
+ break
+
+ entry[std] = last
+ result[feature["name"]] = entry
+
+ return result
+
+
def main():
produce_version_header()
produce_tests()
>From b820528915b2a5ed29fa7893d35a727ac85bd7d9 Mon Sep 17 00:00:00 2001
From: Mark de Wever <koraq at xs4all.nl>
Date: Mon, 8 Apr 2024 21:46:06 +0200
Subject: [PATCH 2/2] Addresses review comments.
---
.../get_dialect_versions.sh.py | 53 +++++
.../get_std_dialect_versions.sh.py | 53 +++++
.../feature_test_macro/get_std_dialects.sh.py | 29 +++
.../libcxx/feature_test_macro/invalid.sh.py | 107 ++++++++++
.../test/libcxx/feature_test_macro_csv.sh.py | 35 ----
.../data/feature_test_macros/test_data.json | 17 +-
.../generate_feature_test_macro_components.py | 191 +++++++++++++++++-
7 files changed, 442 insertions(+), 43 deletions(-)
create mode 100644 libcxx/test/libcxx/feature_test_macro/get_dialect_versions.sh.py
create mode 100644 libcxx/test/libcxx/feature_test_macro/get_std_dialect_versions.sh.py
create mode 100644 libcxx/test/libcxx/feature_test_macro/get_std_dialects.sh.py
create mode 100644 libcxx/test/libcxx/feature_test_macro/invalid.sh.py
delete mode 100644 libcxx/test/libcxx/feature_test_macro_csv.sh.py
diff --git a/libcxx/test/libcxx/feature_test_macro/get_dialect_versions.sh.py b/libcxx/test/libcxx/feature_test_macro/get_dialect_versions.sh.py
new file mode 100644
index 0000000000000..fffe0ddc6e6a7
--- /dev/null
+++ b/libcxx/test/libcxx/feature_test_macro/get_dialect_versions.sh.py
@@ -0,0 +1,53 @@
+# RUN: %{python} %s %{libcxx-dir}/utils %{libcxx-dir}/utils/data/feature_test_macros/test_data.json
+# ===----------------------------------------------------------------------===##
+#
+# 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
+#
+# ===----------------------------------------------------------------------===##
+
+import sys
+
+sys.path.append(sys.argv[1])
+from generate_feature_test_macro_components import feature_test_macros
+
+
+def test(output, expected):
+ assert output == expected, f"expected\n{expected}\n\noutput\n{output}"
+
+
+fmt = feature_test_macros(sys.argv[2])
+test(
+ fmt.get_dialect_versions(),
+ {
+ "__cpp_lib_any": {
+ "c++17": "201606L",
+ "c++20": "201606L",
+ "c++23": "201606L",
+ "c++26": "201606L",
+ },
+ "__cpp_lib_barrier": {
+ "c++20": "201907L",
+ "c++23": "201907L",
+ "c++26": "201907L",
+ },
+ "__cpp_lib_format": {
+ "c++20": None,
+ "c++23": None,
+ "c++26": None,
+ },
+ "__cpp_lib_parallel_algorithm": {
+ "c++17": "201603L",
+ "c++20": "201603L",
+ "c++23": "201603L",
+ "c++26": "201603L",
+ },
+ "__cpp_lib_variant": {
+ "c++17": "202102L",
+ "c++20": "202102L",
+ "c++23": "202102L",
+ "c++26": "202102L",
+ },
+ },
+)
diff --git a/libcxx/test/libcxx/feature_test_macro/get_std_dialect_versions.sh.py b/libcxx/test/libcxx/feature_test_macro/get_std_dialect_versions.sh.py
new file mode 100644
index 0000000000000..5c438da601921
--- /dev/null
+++ b/libcxx/test/libcxx/feature_test_macro/get_std_dialect_versions.sh.py
@@ -0,0 +1,53 @@
+# RUN: %{python} %s %{libcxx-dir}/utils %{libcxx-dir}/utils/data/feature_test_macros/test_data.json
+# ===----------------------------------------------------------------------===##
+#
+# 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
+#
+# ===----------------------------------------------------------------------===##
+
+import sys
+
+sys.path.append(sys.argv[1])
+from generate_feature_test_macro_components import feature_test_macros
+
+
+def test(output, expected):
+ assert output == expected, f"expected\n{expected}\n\noutput\n{output}"
+
+
+fmt = feature_test_macros(sys.argv[2])
+test(
+ fmt.get_std_dialect_versions(),
+ {
+ "__cpp_lib_any": {
+ "c++17": "201606L",
+ "c++20": "201606L",
+ "c++23": "201606L",
+ "c++26": "201606L",
+ },
+ "__cpp_lib_barrier": {
+ "c++20": "201907L",
+ "c++23": "201907L",
+ "c++26": "201907L",
+ },
+ "__cpp_lib_format": {
+ "c++20": "202110L",
+ "c++23": "202207L",
+ "c++26": "202311L",
+ },
+ "__cpp_lib_parallel_algorithm": {
+ "c++17": "201603L",
+ "c++20": "201603L",
+ "c++23": "201603L",
+ "c++26": "201603L",
+ },
+ "__cpp_lib_variant": {
+ "c++17": "202102L",
+ "c++20": "202106L",
+ "c++23": "202106L",
+ "c++26": "202306L",
+ },
+ },
+)
diff --git a/libcxx/test/libcxx/feature_test_macro/get_std_dialects.sh.py b/libcxx/test/libcxx/feature_test_macro/get_std_dialects.sh.py
new file mode 100644
index 0000000000000..af93f94cbfbe7
--- /dev/null
+++ b/libcxx/test/libcxx/feature_test_macro/get_std_dialects.sh.py
@@ -0,0 +1,29 @@
+# RUN: %{python} %s %{libcxx-dir}/utils %{libcxx-dir}/utils/data/feature_test_macros/test_data.json
+# ===----------------------------------------------------------------------===##
+#
+# 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
+#
+# ===----------------------------------------------------------------------===##
+
+import sys
+
+sys.path.append(sys.argv[1])
+from generate_feature_test_macro_components import feature_test_macros
+
+
+def test(output, expected):
+ assert output == expected, f"expected\n{expected}\n\noutput\n{output}"
+
+
+fmt = feature_test_macros(sys.argv[2])
+test(
+ fmt.get_std_dialects(),
+ [
+ "c++17",
+ "c++20",
+ "c++23",
+ "c++26",
+ ],
+)
diff --git a/libcxx/test/libcxx/feature_test_macro/invalid.sh.py b/libcxx/test/libcxx/feature_test_macro/invalid.sh.py
new file mode 100644
index 0000000000000..ed65242ccc750
--- /dev/null
+++ b/libcxx/test/libcxx/feature_test_macro/invalid.sh.py
@@ -0,0 +1,107 @@
+# RUN: %{python} %s %{libcxx-dir}/utils %t
+# ===----------------------------------------------------------------------===##
+#
+# 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
+#
+# ===----------------------------------------------------------------------===##
+
+import sys
+import json
+
+sys.path.append(sys.argv[1])
+from generate_feature_test_macro_components import feature_test_macros
+
+
+def test(output, expected):
+ assert output == expected, f"expected\n{expected}\n\noutput\n{output}"
+
+
+def test_error(data, type, message):
+ tmp = sys.argv[2]
+ with open(tmp, "w") as file:
+ file.write(json.dumps(data))
+ fmt = feature_test_macros(tmp)
+ try:
+ fmt.get_dialect_versions()
+ except type as error:
+ test(str(error), message)
+ else:
+ assert False, "no exception was thrown"
+
+
+test_error(
+ [
+ {
+ "values": {
+ "c++17": {
+ "197001": [
+ {
+ "implemented": False,
+ },
+ ],
+ },
+ },
+ "headers": [],
+ },
+ ],
+ KeyError,
+ "'name'",
+)
+
+test_error(
+ [
+ {
+ "name": "a",
+ "headers": [],
+ },
+ ],
+ KeyError,
+ "'values'",
+)
+
+test_error(
+ [
+ {
+ "name": "a",
+ "values": {},
+ "headers": [],
+ },
+ ],
+ AssertionError,
+ "'values' is empty",
+)
+
+
+test_error(
+ [
+ {
+ "name": "a",
+ "values": {
+ "c++17": {},
+ },
+ "headers": [],
+ },
+ ],
+ AssertionError,
+ "a[c++17] has no entries",
+)
+
+test_error(
+ [
+ {
+ "name": "a",
+ "values": {
+ "c++17": {
+ "197001": [
+ {},
+ ],
+ },
+ },
+ "headers": [],
+ },
+ ],
+ KeyError,
+ "'implemented'",
+)
diff --git a/libcxx/test/libcxx/feature_test_macro_csv.sh.py b/libcxx/test/libcxx/feature_test_macro_csv.sh.py
deleted file mode 100644
index 2d80bfad63c85..0000000000000
--- a/libcxx/test/libcxx/feature_test_macro_csv.sh.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# RUN: %{python} %s %{libcxx-dir}/utils %{libcxx-dir}/utils/data/feature_test_macros/test_data.json
-
-import sys
-import json
-
-sys.path.append(sys.argv[1])
-from generate_feature_test_macro_components import get_table
-
-
-data = json.load(open(f"{sys.argv[2]}"))
-table = get_table(data)
-
-expected = {
- "__cpp_lib_any": {
- "c++17": "201606L",
- "c++20": "201606L",
- "c++23": "201606L",
- "c++26": "201606L",
- },
- "__cpp_lib_barrier": {"c++20": "201907L", "c++23": "201907L", "c++26": "201907L"},
- "__cpp_lib_format": {
- "c++20": "",
- "c++23": "",
- "c++26": "",
- },
- "__cpp_lib_variant": {
- "c++17": "202102L",
- "c++20": "202102L",
- "c++23": "202102L",
- "c++26": "202102L",
- },
-}
-
-
-assert table == expected, f"expected\n{expected}\n\nresult\n{table}"
diff --git a/libcxx/utils/data/feature_test_macros/test_data.json b/libcxx/utils/data/feature_test_macros/test_data.json
index 5a98fba6403c0..1f8bbe5d769b5 100644
--- a/libcxx/utils/data/feature_test_macros/test_data.json
+++ b/libcxx/utils/data/feature_test_macros/test_data.json
@@ -98,13 +98,28 @@
"format"
]
},
+ {
+ "name": "__cpp_lib_parallel_algorithm",
+ "values": {
+ "c++17": {
+ "201603": [
+ {
+ "implemented": true
+ }
+ ]
+ }
+ },
+ "headers": [
+ "algorithm",
+ "numeric"
+ ]
+ },
{
"name": "__cpp_lib_variant",
"values": {
"c++17": {
"202102": [
{
- "number": "",
"title": "``std::visit`` for classes derived from ``std::variant``",
"implemented": true
}
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index 04a8a8786b1a3..2556faa00b2e8 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -1858,25 +1858,41 @@ def produce_docs():
f.write(doc_str)
-def get_table(data):
+def get_std_dialects(data):
+ """Impementation for feature_test_macros.get_std_dialects()."""
+ dialects = set()
+ for feature in data:
+ keys = feature["values"].keys()
+ assert len(keys) > 0, "'values' is empty"
+ dialects |= keys
+
+ return sorted(dialects)
+
+
+def get_dialect_versions(data, std_dialects, use_implemented_status):
+ """Impementation for feature_test_macros.get_(std_|)dialect_versions()."""
result = dict()
for feature in data:
last = None
entry = dict()
implemented = True
- for std in get_std_dialects():
+ for std in std_dialects:
if std not in feature["values"].keys():
if last == None:
continue
else:
entry[std] = last
else:
- if last == None:
- last = ""
if implemented:
- for value in feature["values"][std]:
- for paper in list(feature["values"][std][value]):
- if not paper["implemented"]:
+ values = feature["values"][std]
+ assert len(values) > 0, f"{feature['name']}[{std}] has no entries"
+ for value in values:
+ papers = list(values[value])
+ assert (
+ len(papers) > 0
+ ), f"{feature['name']}[{std}][{value}] has no entries"
+ for paper in papers:
+ if use_implemented_status and not paper["implemented"]:
implemented = False
break
if implemented:
@@ -1890,6 +1906,167 @@ def get_table(data):
return result
+class feature_test_macros:
+ """Provides all feature-test macro (FMT) output components.
+
+ The class has several generators to use the feature-test macros in libc++:
+ - FTM status page
+ - The version header and its tests
+
+ This class is not intended to duplicate
+ https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations#library-feature-test-macros
+ SD-FeatureTest: Feature-Test Macros and Policies
+
+ Historically libc++ did not list all papers affecting a FTM, the new data
+ structure is able to do that. However there is no intention to add the
+ historical data. After papers have been implemented this information can be
+ removed. For example, __cpp_lib_format's value 201907 requires 3 papers,
+ once implemented it can be reduced to 1 paper and remove the paper number
+ and title. This would reduce the size of the data.
+
+ The input data is stored in the following JSON format:
+ [ # A list with multiple feature-test macro entries.
+ {
+ # required
+ # The name of the feature test macro. These names should be unique and
+ # sorted in the list.
+ "name": "__cpp_lib_any",
+
+ # required
+ # A map with the value of the FTM based on the language standard. Only
+ # the versions in which the value of the FTM changes are listed. For
+ # example, this macro's value does not change in C++20 so it does not
+ # list C++20. If it changes in C++26, it will have entries for C++17 and
+ # C++26.
+ "values": {
+
+ # required
+ # The language standard, also named dialect in this class.
+ "c++17": {
+
+ # required
+ # The value of the feature test macro. This contains an array with
+ # one or more papers that need to be implemented before this value
+ # is considered implemented.
+ "201606": [
+ {
+ # optional
+ # Contains the paper number that is part of the FTM version.
+ "number": "P0220R1",
+
+ # optional
+ # Contains the title of the paper that is part of the FTM
+ # version.
+ "title": "Adopt Library Fundamentals V1 TS Components for C++17"
+
+ # required
+ # The implementation status of the paper.
+ "implemented": true
+ }
+ ]
+ }
+ },
+
+ # required
+ # A sorted list of headers that should provide the FTM. The header
+ # <version> is automatically added to this list. This list could be
+ # empty. For example, __cpp_lib_modules is only present in version.
+ # Requiring the field makes it easier to detect accidental omission.
+ "headers": [
+ "any"
+ ],
+
+ # optional, required when libcxx_guard is present
+ # This field is used only to generate the unit tests for the
+ # feature-test macros. It can't depend on macros defined in <__config>
+ # because the `test/std/` parts of the test suite are intended to be
+ # portable to any C++ standard library implementation, not just libc++.
+ # It may depend on
+ # * macros defined by the compiler itself, or
+ # * macros generated by CMake.
+ # In some cases we add also depend on macros defined in
+ # <__availability>.
+ "test_suite_guard": "!defined(_LIBCPP_VERSION) || _LIBCPP_AVAILABILITY_HAS_PMR"
+
+ # optional, required when test_suite_guard is present
+ # This field is used only to guard the feature-test macro in
+ # <version>. It may be the same as `test_suite_guard`, or it may
+ # depend on macros defined in <__config>.
+ "libcxx_guard": "_LIBCPP_AVAILABILITY_HAS_PMR"
+ },
+ ]
+ """
+
+ # The JSON data structor.
+ __data = None
+
+ # These values are used internally multiple times. They are lazily loaded
+ # and cached. Values that are expected to be used once are not cached.
+ __std_dialects = None
+ __std_dialect_versions = None
+ __dialect_versions = None
+
+ def __init__(self, filename):
+ """Initializes the class with the JSON data in the file 'filename'."""
+ self.__data = json.load(open(filename))
+
+ def get_std_dialects(self):
+ """Returns the C++ dialects avaiable.
+
+ The available dialects are based on the 'c++xy' keys found the 'values'
+ entries in '__data'. So when WG21 starts to feature-test macros for a
+ future C++ Standard this dialect will automatically be available.
+
+ The return value is a sorted list with the C++ dialects used. Since FTM
+ were added in C++14 the list will not contain C++98 or C++11.
+ """
+ if not self.__std_dialects:
+ self.__std_dialects = get_std_dialects(self.__data)
+
+ return self.__std_dialects
+
+ def get_std_dialect_versions(self):
+ """Returns the FTM versions per dialect in the Standard.
+
+ This function does not use the 'implemented' flag. The output contains
+ the versions used in the Standard. When a FTM in libc++ is not
+ implemented according to the Standard to output may opt to show the
+ expected value.
+
+ The result is a dict with the following content
+ - key: Name of the feature test macro.
+ - value: A dict with the following content:
+ * key: The version of the C++ dialect.
+ * value: The value of the feature-test macro.
+ """
+ if not self.__std_dialect_versions:
+ self.__std_dialect_versions = get_dialect_versions(
+ self.__data, self.get_std_dialects(), False
+ )
+
+ return self.__std_dialect_versions
+
+ def get_dialect_versions(self):
+ """Returns the FTM versions per dialect implemented in libc++.
+
+ Unlike `get_std_dialect_versions` this function uses the 'implemented'
+ flag. This returns the actual implementation status in libc++.
+
+ The result is a dict with the following content
+ - key: Name of the feature test macro.
+ - value: A dict with the following content:
+ * key: The version of the C++ dialect.
+ * value: The value of the feature-test macro. When a feature-test
+ macro is not implemented its value is None.
+ """
+ if not self.__dialect_versions:
+ self.__dialect_versions = get_dialect_versions(
+ self.__data, self.get_std_dialects(), True
+ )
+
+ return self.__dialect_versions
+
+
def main():
produce_version_header()
produce_tests()
More information about the libcxx-commits
mailing list