Skip to content

[libc++] Adds is_implemented function for new ftm generator. #134538

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 11, 2025

Conversation

mordante
Copy link
Member

@mordante mordante commented Apr 6, 2025

At the moment the ftm macro for __cpp_lib_to_chars will have the following values:

standard_ftms: {
"c++17": "201611L",
"c++20": "201611L",
"c++23": "201611L",
"c++26": "201611L",
}

implemented_ftms: {
"c++17": None,
}

This is an issue with the test whether the FTM is implemented it does:
self.implemented_ftms[ftm][std] == self.standard_ftms[ftm][std]
This will fail in C++20 since implemented_ftms[ftm] does not have the key c++20. This adds a new helper function and removes the None entries when a FTM is not implemented.

@mordante mordante requested a review from a team as a code owner April 6, 2025 13:35
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Apr 6, 2025
@llvmbot
Copy link
Member

llvmbot commented Apr 6, 2025

@llvm/pr-subscribers-libcxx

Author: Mark de Wever (mordante)

Changes

At the moment the ftm macro for __cpp_lib_to_chars will have the following values:

standard_ftms: {
"c++17": "201611L",
"c++20": "201611L",
"c++23": "201611L",
"c++26": "201611L",
}

implemented_ftms: {
"c++17": None,
}

This is an issue with the test whether the FTM is implemented it does:
self.implemented_ftms[ftm][std] == self.standard_ftms[ftm][std]
This will fail in C++20 since implemented_ftms[ftm] does not have the key c++20. This adds a new helper function and removes the None entries when a FTM is not implemented.


Full diff: https://github.com/llvm/llvm-project/pull/134538.diff

3 Files Affected:

  • (modified) libcxx/test/libcxx/feature_test_macro/implemented_ftms.sh.py (+2-10)
  • (added) libcxx/test/libcxx/feature_test_macro/is_implemented.sh.py (+39)
  • (modified) libcxx/utils/generate_feature_test_macro_components.py (+17-2)
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 92e14757ddd49..4f445d55c883c 100644
--- a/libcxx/test/libcxx/feature_test_macro/implemented_ftms.sh.py
+++ b/libcxx/test/libcxx/feature_test_macro/implemented_ftms.sh.py
@@ -38,11 +38,7 @@ def test_implementation(self):
                 "c++23": "201907L",
                 "c++26": "299900L",
             },
-            "__cpp_lib_format": {
-                "c++20": None,
-                "c++23": None,
-                "c++26": None,
-            },
+            "__cpp_lib_format": {},
             "__cpp_lib_parallel_algorithm": {
                 "c++17": "201603L",
                 "c++20": "201603L",
@@ -55,11 +51,7 @@ def test_implementation(self):
                 "c++23": "202102L",
                 "c++26": "202102L",
             },
-            "__cpp_lib_missing_FTM_in_older_standard": {
-                "c++17": None,
-                "c++20": None,
-                "c++26": None,
-            },
+            "__cpp_lib_missing_FTM_in_older_standard": {},
         }
 
         self.assertEqual(self.ftm.implemented_ftms, expected)
diff --git a/libcxx/test/libcxx/feature_test_macro/is_implemented.sh.py b/libcxx/test/libcxx/feature_test_macro/is_implemented.sh.py
new file mode 100644
index 0000000000000..0414722b89a76
--- /dev/null
+++ b/libcxx/test/libcxx/feature_test_macro/is_implemented.sh.py
@@ -0,0 +1,39 @@
+# ===----------------------------------------------------------------------===##
+#
+# 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)
+        self.maxDiff = None  # This causes the diff to be printed when the test fails
+
+    def test_implementation(self):
+        # FTM not available in C++14.
+        self.assertEqual(self.ftm.is_implemented("__cpp_lib_any", "c++14"), False)
+        self.assertEqual(self.ftm.is_implemented("__cpp_lib_any", "c++17"), True)
+
+        self.assertEqual(self.ftm.is_implemented("__cpp_lib_format", "c++20"), False)
+
+        # FTM C++20 202106L, libc++ has 202102L
+        self.assertEqual(self.ftm.is_implemented("__cpp_lib_variant", "c++20"), False)
+
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index 53252d5e2d673..ecf31f5af7fb2 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -2012,7 +2012,8 @@ def get_ftms(
                         else:
                             break
 
-                entry[std] = last
+                if last:
+                    entry[std] = last
         result[feature["name"]] = entry
 
     return result
@@ -2208,6 +2209,20 @@ 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`?"""
+
+        # When a paper for C++20 has not been implemented in libc++, then there will be no
+        # FTM entry in implemented_ftms for C++23 and later.
+        #
+        # Typically standard_ftms is not used with invalid values in the code, but
+        # guard just in case.
+        if not std in self.implemented_ftms[ftm].keys() or not std in self.standard_ftms[ftm].keys():
+            return False
+
+        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.
@@ -2241,7 +2256,7 @@ def version_header_implementation(self) -> Dict[Std, Dict[Ftm, VersionHeader]]:
                     continue
                 last_value = value
 
-                implemented = self.implemented_ftms[ftm][std] == self.standard_ftms[ftm][std]
+                implemented = self.is_implemented(ftm, std)
                 entry = VersionHeader(
                     value,
                     implemented,

Copy link

github-actions bot commented Apr 6, 2025

⚠️ Python code formatter, darker found issues in your code. ⚠️

You can test this locally with the following command:
darker --check --diff -r HEAD~1...HEAD libcxx/test/libcxx/feature_test_macro/is_implemented.sh.py libcxx/test/libcxx/feature_test_macro/implemented_ftms.sh.py libcxx/utils/generate_feature_test_macro_components.py
View the diff from darker here.
--- utils/generate_feature_test_macro_components.py	2025-04-08 17:41:00.000000 +0000
+++ utils/generate_feature_test_macro_components.py	2025-04-08 17:43:20.359813 +0000
@@ -2211,15 +2211,17 @@
         """Has the FTM `ftm` been implemented in the dialect `std`?"""
 
         # When a paper for C++20 has not been implemented in libc++, then there will be no
         # FTM entry in implemented_ftms for C++23 and later. Similarly, a paper like <format>
         # has no entry in standard_ftms for e.g. C++11.
-        if not std in self.implemented_ftms[ftm].keys() or not std in self.standard_ftms[ftm].keys():
+        if (
+            not std in self.implemented_ftms[ftm].keys()
+            or not std in self.standard_ftms[ftm].keys()
+        ):
             return False
 
         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.
 

Copy link
Member

@ldionne ldionne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with comment rewording.

Base automatically changed from users/mordante/ftm/refactor_tests to main April 8, 2025 17:38
mordante and others added 2 commits April 8, 2025 19:41
At the moment the ftm macro for __cpp_lib_to_chars will have the
following values:

standard_ftms: {
    "c++17": "201611L",
    "c++20": "201611L",
    "c++23": "201611L",
    "c++26": "201611L",
}

implemented_ftms: {
    "c++17": None,
}

This is an issue with the test whether the FTM is implemented it does:
  self.implemented_ftms[ftm][std] == self.standard_ftms[ftm][std]
This will fail in C++20 since implemented_ftms[ftm] does not have the
key c++20. This adds a new helper function and removes the None entries
when a FTM is not implemented.
@mordante mordante force-pushed the users/mordante/ftm/is_implemented branch from 14c5af3 to fa5cbcf Compare April 8, 2025 17:41
@mordante mordante merged commit df579ce into main Apr 11, 2025
76 of 84 checks passed
@mordante mordante deleted the users/mordante/ftm/is_implemented branch April 11, 2025 18:27
var-const pushed a commit to ldionne/llvm-project that referenced this pull request Apr 17, 2025
…4538)

At the moment the ftm macro for __cpp_lib_to_chars will have the
following values:

standard_ftms: {
    "c++17": "201611L",
    "c++20": "201611L",
    "c++23": "201611L",
    "c++26": "201611L",
}

implemented_ftms: {
    "c++17": None,
}

This is an issue with the test whether the FTM is implemented it does:
  self.implemented_ftms[ftm][std] == self.standard_ftms[ftm][std]
This will fail in C++20 since implemented_ftms[ftm] does not have the
key c++20. This adds a new helper function and removes the None entries
when a FTM is not implemented.

---------

Co-authored-by: Louis Dionne <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants