[libcxx-commits] [libcxx] 5b9e6c7 - [libc++] Improves type-safety in generator script. (#101880)

via libcxx-commits libcxx-commits at lists.llvm.org
Mon Feb 10 09:03:47 PST 2025


Author: Mark de Wever
Date: 2025-02-10T18:03:44+01:00
New Revision: 5b9e6c7993359c16b4d645c851bb7fe2fd7b78c7

URL: https://github.com/llvm/llvm-project/commit/5b9e6c7993359c16b4d645c851bb7fe2fd7b78c7
DIFF: https://github.com/llvm/llvm-project/commit/5b9e6c7993359c16b4d645c851bb7fe2fd7b78c7.diff

LOG: [libc++] Improves type-safety in generator script. (#101880)

This changes the code to use dataclasses instead of dict entries. It
also adds type aliases to use in the typing information and updates the
typing information.

Added: 
    

Modified: 
    libcxx/test/libcxx/feature_test_macro/ftm_metadata.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 541447a5916c0c5..4f23773f9a0a586 100644
--- a/libcxx/test/libcxx/feature_test_macro/ftm_metadata.sh.py
+++ b/libcxx/test/libcxx/feature_test_macro/ftm_metadata.sh.py
@@ -11,7 +11,7 @@
 import sys
 
 sys.path.append(sys.argv[1])
-from generate_feature_test_macro_components import FeatureTestMacros
+from generate_feature_test_macro_components import FeatureTestMacros, Metadata
 
 
 def test(output, expected):
@@ -19,38 +19,29 @@ def test(output, expected):
 
 
 ftm = FeatureTestMacros(sys.argv[2])
+
 test(
     ftm.ftm_metadata,
     {
-        "__cpp_lib_any": {
-            "headers": ["any"],
-            "test_suite_guard": None,
-            "libcxx_guard": None,
-        },
-        "__cpp_lib_barrier": {
-            "headers": ["barrier"],
-            "test_suite_guard": "!defined(_LIBCPP_VERSION) || (_LIBCPP_HAS_THREADS && _LIBCPP_AVAILABILITY_HAS_SYNC)",
-            "libcxx_guard": "_LIBCPP_HAS_THREADS && _LIBCPP_AVAILABILITY_HAS_SYNC",
-        },
-        "__cpp_lib_format": {
-            "headers": ["format"],
-            "test_suite_guard": None,
-            "libcxx_guard": None,
-        },
-        "__cpp_lib_parallel_algorithm": {
-            "headers": ["algorithm", "numeric"],
-            "test_suite_guard": None,
-            "libcxx_guard": None,
-        },
-        "__cpp_lib_variant": {
-            "headers": ["variant"],
-            "test_suite_guard": None,
-            "libcxx_guard": None,
-        },
-        "__cpp_lib_missing_FTM_in_older_standard": {
-            "headers": [],
-            "test_suite_guard": None,
-            "libcxx_guard": None,
-        },
+        "__cpp_lib_any": Metadata(
+            headers=["any"], test_suite_guard=None, libcxx_guard=None
+        ),
+        "__cpp_lib_barrier": Metadata(
+            headers=["barrier"],
+            test_suite_guard="!defined(_LIBCPP_VERSION) || (_LIBCPP_HAS_THREADS && _LIBCPP_AVAILABILITY_HAS_SYNC)",
+            libcxx_guard="_LIBCPP_HAS_THREADS && _LIBCPP_AVAILABILITY_HAS_SYNC",
+        ),
+        "__cpp_lib_format": Metadata(
+            headers=["format"], test_suite_guard=None, libcxx_guard=None
+        ),
+        "__cpp_lib_parallel_algorithm": Metadata(
+            headers=["algorithm", "numeric"], test_suite_guard=None, libcxx_guard=None
+        ),
+        "__cpp_lib_variant": Metadata(
+            headers=["variant"], test_suite_guard=None, libcxx_guard=None
+        ),
+        "__cpp_lib_missing_FTM_in_older_standard": Metadata(
+            headers=[], test_suite_guard=None, libcxx_guard=None
+        ),
     },
 )

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 b9e087c2107672d..2771a2f7d8abf01 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
@@ -16,7 +16,7 @@
 del sys.argv[1:3]
 
 sys.path.append(UTILS)
-from generate_feature_test_macro_components import FeatureTestMacros
+from generate_feature_test_macro_components import FeatureTestMacros, VersionHeader
 
 class Test(unittest.TestCase):
     def setUp(self):
@@ -27,114 +27,114 @@ def test_implementation(self):
         expected = {
             "17": [
                 {
-                    "__cpp_lib_any": {
-                        "value": "201606L",
-                        "implemented": True,
-                        "need_undef": False,
-                        "condition": None,
-                    },
+                    "__cpp_lib_any": VersionHeader(
+                        value="201606L",
+                        implemented=True,
+                        need_undef=False,
+                        condition=None,
+                    ),
                 },
                 {
-                    "__cpp_lib_parallel_algorithm": {
-                        "value": "201603L",
-                        "implemented": True,
-                        "need_undef": False,
-                        "condition": None,
-                    },
+                    "__cpp_lib_parallel_algorithm": VersionHeader(
+                        value="201603L",
+                        implemented=True,
+                        need_undef=False,
+                        condition=None,
+                    ),
                 },
                 {
-                    "__cpp_lib_variant": {
-                        "value": "202102L",
-                        "implemented": True,
-                        "need_undef": False,
-                        "condition": None,
-                    },
+                    "__cpp_lib_variant": VersionHeader(
+                        value="202102L",
+                        implemented=True,
+                        need_undef=False,
+                        condition=None,
+                    ),
                 },
                 {
-                    "__cpp_lib_missing_FTM_in_older_standard": {
-                        "value": "2017L",
-                        "implemented": False,
-                        "need_undef": False,
-                        "condition": None,
-                    },
+                    "__cpp_lib_missing_FTM_in_older_standard" : VersionHeader(
+                        value = "2017L",
+                        implemented = False,
+                        need_undef = False,
+                        condition = None,
+                    ),
                 },
             ],
             "20": [
                 {
-                    "__cpp_lib_barrier": {
-                        "value": "201907L",
-                        "implemented": True,
-                        "need_undef": False,
-                        "condition": "_LIBCPP_HAS_THREADS && _LIBCPP_AVAILABILITY_HAS_SYNC",
-                    },
+                    "__cpp_lib_barrier": VersionHeader(
+                        value="201907L",
+                        implemented=True,
+                        need_undef=False,
+                        condition="_LIBCPP_HAS_THREADS && _LIBCPP_AVAILABILITY_HAS_SYNC",
+                    ),
                 },
                 {
-                    "__cpp_lib_format": {
-                        "value": "202110L",
-                        "implemented": False,
-                        "need_undef": False,
-                        "condition": None,
-                    },
+                    "__cpp_lib_format": VersionHeader(
+                        value="202110L",
+                        implemented=False,
+                        need_undef=False,
+                        condition=None,
+                    ),
                 },
                 {
-                    "__cpp_lib_variant": {
-                        "value": "202106L",
-                        "implemented": False,
-                        "need_undef": False,
-                        "condition": None,
-                    },
+                    "__cpp_lib_variant": VersionHeader(
+                        value="202106L",
+                        implemented=False,
+                        need_undef=False,
+                        condition=None,
+                    ),
                 },
                 {
-                    "__cpp_lib_missing_FTM_in_older_standard": {
-                        "value": "2020L",
-                        "implemented": False,
-                        "need_undef": False,
-                        "condition": None,
-                    },
+                    "__cpp_lib_missing_FTM_in_older_standard" : VersionHeader(
+                        value = "2020L",
+                        implemented = False,
+                        need_undef = False,
+                        condition = None,
+                    ),
                 },
             ],
             "23": [
                 {
-                    "__cpp_lib_format": {
-                        "value": "202207L",
-                        "implemented": False,
-                        "need_undef": False,
-                        "condition": None,
-                    },
+                    "__cpp_lib_format": VersionHeader(
+                        value="202207L",
+                        implemented=False,
+                        need_undef=False,
+                        condition=None,
+                    ),
                 },
             ],
             "26": [
                 {
-                    "__cpp_lib_barrier": {
-                        "value": "299900L",
-                        "implemented": True,
-                        "need_undef": True,
-                        "condition": "_LIBCPP_HAS_THREADS && _LIBCPP_AVAILABILITY_HAS_SYNC",
-                    },
+                    "__cpp_lib_barrier": VersionHeader(
+                        value="299900L",
+                        implemented=True,
+                        need_undef=True,
+                        condition="_LIBCPP_HAS_THREADS && _LIBCPP_AVAILABILITY_HAS_SYNC",
+                    ),
                 },
                 {
-                    "__cpp_lib_format": {
-                        "value": "202311L",
-                        "implemented": False,
-                        "need_undef": False,
-                        "condition": None,
-                    },
+                    "__cpp_lib_format": VersionHeader(
+                        value="202311L",
+                        implemented=False,
+                        need_undef=False,
+                        condition=None,
+                    ),
                 },
                 {
-                    "__cpp_lib_variant": {
-                        "value": "202306L",
-                        "implemented": False,
-                        "need_undef": False,
-                        "condition": None,
-                    },
+                    "__cpp_lib_variant": VersionHeader(
+                        value="202306L",
+                        implemented=False,
+                        need_undef=False,
+                        condition=None,
+                    ),
                 },
                 {
-                    "__cpp_lib_missing_FTM_in_older_standard": {
-                        "value": "2026L",
-                        "implemented": False,
-                        "need_undef": False,
-                        "condition": None,
-                    },
+                    "__cpp_lib_missing_FTM_in_older_standard" : VersionHeader(
+                        value = "2026L",
+                        implemented = False,
+                        need_undef = False,
+                        condition = None,
+                    ),
                 },
             ],
         }

diff  --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index 58ecd79cf7469c7..e9e531733abb506 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -2,8 +2,15 @@
 
 import os
 from builtins import range
+from dataclasses import dataclass
 from functools import reduce
-from typing import Any, Dict, List  # Needed for python 3.8 compatibility.
+from typing import (
+    Any,
+    Dict,
+    List,  # Needed for python 3.8 compatibility.
+    NewType,
+    Optional,
+)
 import functools
 import json
 
@@ -1944,9 +1951,28 @@ def produce_docs():
         f.write(doc_str)
 
 
+Std = NewType("Std", str)  # Standard version number
+Ftm = NewType("Ftm", str)  # The name of a feature test macro
+Value = NewType("Value", str)  # The value of a feature test macro including the L suffix
+
+ at dataclass
+class Metadata:
+    headers: list[str] = None
+    test_suite_guard: str = None
+    libcxx_guard: str = None
+
+
+ at dataclass
+class VersionHeader:
+    value: Value = None
+    implemented: bool = None
+    need_undef: bool = None
+    condition: str = None
+
+
 def get_ftms(
-    data, std_dialects: List[str], use_implemented_status: bool
-) -> Dict[str, Dict[str, Any]]:
+    data, std_dialects: List[Std], use_implemented_status: bool
+) -> Dict[Ftm, Dict[Std, Optional[Value]]]:
     """Impementation for FeatureTestMacros.(standard|implemented)_ftms()."""
     result = dict()
     for feature in data:
@@ -1983,7 +2009,7 @@ def get_ftms(
     return result
 
 
-def generate_version_header_dialect_block(data: Dict[str, Any]) -> str:
+def generate_version_header_dialect_block(data: Dict[Ftm, VersionHeader]) -> str:
     """Generates the contents of the version header for a dialect.
 
     This generates the contents of a
@@ -1994,27 +2020,29 @@ def generate_version_header_dialect_block(data: Dict[str, Any]) -> str:
     result = ""
     for element in data:
         for ftm, entry in element.items():
-            if not entry["implemented"]:
+            if not entry.implemented:
                 # When a FTM is not implemented don't add the guards
                 # or undefine the (possibly) defined macro.
-                result += f'// define {ftm} {entry["value"]}\n'
+                result += f"// define {ftm} {entry.value}\n"
             else:
-                need_undef = entry["need_undef"]
-                if entry["condition"]:
-                    result += f'#  if {entry["condition"]}\n'
-                    if entry["need_undef"]:
+                need_undef = entry.need_undef
+                if entry.condition:
+                    result += f"#  if {entry.condition}\n"
+                    if entry.need_undef:
                         result += f"#    undef {ftm}\n"
-                    result += f'#    define {ftm} {entry["value"]}\n'
+                    result += f"#    define {ftm} {entry.value}\n"
                     result += f"#  endif\n"
                 else:
-                    if entry["need_undef"]:
+                    if entry.need_undef:
                         result += f"#  undef {ftm}\n"
-                    result += f'#  define {ftm} {entry["value"]}\n'
+                    result += f"#  define {ftm} {entry.value}\n"
 
     return result
 
 
-def generate_version_header_implementation(data: Dict[str, Dict[str, Any]]) -> str:
+def generate_version_header_implementation(
+    data: Dict[Std, Dict[Ftm, VersionHeader]]
+) -> str:
     """Generates the body of the version header."""
 
     template = """#if _LIBCPP_STD_VER >= {dialect}
@@ -2132,7 +2160,7 @@ def __init__(self, filename: str):
             self.__data = json.load(f)
 
     @functools.cached_property
-    def std_dialects(self) -> List[str]:
+    def std_dialects(self) -> List[Std]:
         """Returns the C++ dialects avaiable.
 
         The available dialects are based on the 'c++xy' keys found the 'values'
@@ -2151,63 +2179,44 @@ def std_dialects(self) -> List[str]:
         return sorted(list(dialects))
 
     @functools.cached_property
-    def standard_ftms(self) -> Dict[str, Dict[str, Any]]:
+    def standard_ftms(self) -> Dict[Ftm, Dict[Std, Optional[Value]]]:
         """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.
         """
         return get_ftms(self.__data, self.std_dialects, False)
 
     @functools.cached_property
-    def implemented_ftms(self) -> Dict[str, Dict[str, Any]]:
+    def implemented_ftms(self) -> Dict[Ftm, Dict[Std, Optional[Value]]]:
         """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.
         """
 
         return get_ftms(self.__data, self.std_dialects, True)
 
     @functools.cached_property
-    def ftm_metadata(self) -> Dict[str, Dict[str, Any]]:
+    def ftm_metadata(self) -> Dict[Ftm, Metadata]:
         """Returns the metadata of the FTMs defined in the Standard.
 
         The metadata does not depend on the C++ dialect used.
-        The result is a dict with the following contents:
-        - key: Name of the feature test macro.
-        - value: A dict with the following content:
-          * headers: The list of headers that should provide the FTM
-          * test_suite_guard: The condition for testing the FTM in the test suite.
-          * test_suite_guard: The condition for testing the FTM in the version header.
         """
         result = dict()
         for feature in self.__data:
-            entry = dict()
-            entry["headers"] = feature["headers"]
-            entry["test_suite_guard"] = feature.get("test_suite_guard", None)
-            entry["libcxx_guard"] = feature.get("libcxx_guard", None)
-            result[feature["name"]] = entry
+            result[feature["name"]] = Metadata(
+                feature["headers"],
+                feature.get("test_suite_guard", None),
+                feature.get("libcxx_guard", None),
+            )
 
         return result
 
     @property
-    def version_header_implementation(self) -> Dict[str, List[Dict[str, Any]]]:
+    def version_header_implementation(self) -> Dict[Std, Dict[Ftm, VersionHeader]]:
         """Generates the body of the version header."""
         result = dict()
         for std in self.std_dialects:
@@ -2223,11 +2232,13 @@ def version_header_implementation(self) -> Dict[str, List[Dict[str, Any]]]:
                     continue
                 last_value = value
 
-                entry = dict()
-                entry["value"] = value
-                entry["implemented"] = self.implemented_ftms[ftm][std] == self.standard_ftms[ftm][std]
-                entry["need_undef"] = last_entry is not None and last_entry["implemented"] and entry["implemented"]
-                entry["condition"] = self.ftm_metadata[ftm]["libcxx_guard"]
+                implemented = self.implemented_ftms[ftm][std] == self.standard_ftms[ftm][std]
+                entry = VersionHeader(
+                    value,
+                    implemented,
+                    last_entry is not None and last_entry.implemented and implemented,
+                    self.ftm_metadata[ftm].libcxx_guard,
+                )
 
                 last_entry = entry
                 result[get_std_number(std)].append(dict({ftm: entry}))


        


More information about the libcxx-commits mailing list