Skip to content

[libc++] Fix the declarative generation of FTMs #108843

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 1 commit into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions libcxx/test/libcxx/feature_test_macro/ftm_metadata.sh.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,10 @@ def test(output, expected):
"test_suite_guard": None,
"libcxx_guard": None,
},
"__cpp_lib_missing_FTM_in_older_standard": {
"headers": [],
"test_suite_guard": None,
"libcxx_guard": None,
},
},
)
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,10 @@ def test(output, expected):
"c++23": "202102L",
"c++26": "202102L",
},
"__cpp_lib_missing_FTM_in_older_standard": {
"c++17": None,
"c++20": None,
"c++26": None,
},
},
)
6 changes: 6 additions & 0 deletions libcxx/test/libcxx/feature_test_macro/standard_ftms.sh.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,11 @@ def test(output, expected):
"c++23": "202106L",
"c++26": "202306L",
},
"__cpp_lib_missing_FTM_in_older_standard": {
"c++17": "2017L",
"c++20": "2020L",
"c++23": "2020L",
"c++26": "2026L",
},
},
)
30 changes: 30 additions & 0 deletions libcxx/test/libcxx/feature_test_macro/test_data.json
Original file line number Diff line number Diff line change
Expand Up @@ -154,5 +154,35 @@
"headers": [
"variant"
]
},
{
"name": "__cpp_lib_missing_FTM_in_older_standard",
"values": {
"c++17": {
"2017": [
{
"title": "Some FTM missing a paper in an older Standard mode, which should result in the FTM never being defined.",
"implemented": false
}
]
},
"c++20": {
"2020": [
{
"title": "",
"implemented": true
}
]
},
"c++26": {
"2026": [
{
"title": "",
"implemented": true
}
]
}
},
"headers": []
}
]
9 changes: 5 additions & 4 deletions libcxx/test/libcxx/feature_test_macro/version_header.sh.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,16 @@ def test(output, expected):
# define __cpp_lib_any 201606L
# define __cpp_lib_parallel_algorithm 201603L
# define __cpp_lib_variant 202102L
// define __cpp_lib_missing_FTM_in_older_standard 2017L
#endif // _LIBCPP_STD_VER >= 17

#if _LIBCPP_STD_VER >= 20
# if !defined(_LIBCPP_HAS_NO_THREADS) && _LIBCPP_AVAILABILITY_HAS_SYNC
# define __cpp_lib_barrier 201907L
# endif
// define __cpp_lib_format 202110L
# undef __cpp_lib_variant
# define __cpp_lib_variant 202106L
// define __cpp_lib_variant 202106L
Copy link
Member Author

Choose a reason for hiding this comment

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

@cpplearner I think that is what your comment was about. Does this make more sense?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, this is correct.

// define __cpp_lib_missing_FTM_in_older_standard 2020L
#endif // _LIBCPP_STD_VER >= 20

#if _LIBCPP_STD_VER >= 23
Expand All @@ -64,8 +65,8 @@ def test(output, expected):
# define __cpp_lib_barrier 299900L
# endif
// define __cpp_lib_format 202311L
# undef __cpp_lib_variant
# define __cpp_lib_variant 202306L
// define __cpp_lib_variant 202306L
// define __cpp_lib_missing_FTM_in_older_standard 2026L
#endif // _LIBCPP_STD_VER >= 26

#endif // _LIBCPP_VERSION
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,106 +9,137 @@
# RUN: %{python} %s %{libcxx-dir}/utils %{libcxx-dir}/test/libcxx/feature_test_macro/test_data.json

import sys
import unittest

sys.path.append(sys.argv[1])
from generate_feature_test_macro_components import FeatureTestMacros

UTILS = sys.argv[1]
TEST_DATA = sys.argv[2]
del sys.argv[1:3]

def test(output, expected):
assert output == expected, f"expected\n{expected}\n\noutput\n{output}"
sys.path.append(UTILS)
from generate_feature_test_macro_components import FeatureTestMacros

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

ftm = FeatureTestMacros(sys.argv[2])
test(
ftm.version_header_implementation,
{
"17": [
{
"__cpp_lib_any": {
"value": "201606L",
"implemented": True,
"need_undef": False,
"condition": None,
def test_implementation(self):
expected = {
"17": [
{
"__cpp_lib_any": {
"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": {
"value": "201603L",
"implemented": True,
"need_undef": False,
"condition": None,
{
"__cpp_lib_variant": {
"value": "202102L",
"implemented": True,
"need_undef": False,
"condition": None,
},
},
},
{
"__cpp_lib_variant": {
"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,
},
},
},
],
"20": [
{
"__cpp_lib_barrier": {
"value": "201907L",
"implemented": True,
"need_undef": False,
"condition": "!defined(_LIBCPP_HAS_NO_THREADS) && _LIBCPP_AVAILABILITY_HAS_SYNC",
],
"20": [
{
"__cpp_lib_barrier": {
"value": "201907L",
"implemented": True,
"need_undef": False,
"condition": "!defined(_LIBCPP_HAS_NO_THREADS) && _LIBCPP_AVAILABILITY_HAS_SYNC",
},
},
},
{
"__cpp_lib_format": {
"value": "202110L",
"implemented": False,
"need_undef": False,
"condition": None,
{
"__cpp_lib_format": {
"value": "202110L",
"implemented": False,
"need_undef": False,
"condition": None,
},
},
},
{
"__cpp_lib_variant": {
"value": "202106L",
"implemented": True,
"need_undef": True,
"condition": None,
{
"__cpp_lib_variant": {
"value": "202106L",
"implemented": False,
"need_undef": False,
"condition": None,
},
},
},
],
"23": [
{
"__cpp_lib_format": {
"value": "202207L",
"implemented": False,
"need_undef": False,
"condition": None,
{
"__cpp_lib_missing_FTM_in_older_standard": {
"value": "2020L",
"implemented": False,
"need_undef": False,
"condition": None,
},
},
},
],
"26": [
{
"__cpp_lib_barrier": {
"value": "299900L",
"implemented": True,
"need_undef": True,
"condition": "!defined(_LIBCPP_HAS_NO_THREADS) && _LIBCPP_AVAILABILITY_HAS_SYNC",
],
"23": [
{
"__cpp_lib_format": {
"value": "202207L",
"implemented": False,
"need_undef": False,
"condition": None,
},
},
},
{
"__cpp_lib_format": {
"value": "202311L",
"implemented": False,
"need_undef": False,
"condition": None,
],
"26": [
{
"__cpp_lib_barrier": {
"value": "299900L",
"implemented": True,
"need_undef": True,
"condition": "!defined(_LIBCPP_HAS_NO_THREADS) && _LIBCPP_AVAILABILITY_HAS_SYNC",
},
},
},
{
"__cpp_lib_variant": {
"value": "202306L",
"implemented": True,
"need_undef": True,
"condition": None,
{
"__cpp_lib_format": {
"value": "202311L",
"implemented": False,
"need_undef": False,
"condition": None,
},
},
},
],
},
)
{
"__cpp_lib_variant": {
"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,
},
},
],
}

self.assertEqual(self.ftm.version_header_implementation, expected)

if __name__ == '__main__':
unittest.main()
12 changes: 6 additions & 6 deletions libcxx/utils/generate_feature_test_macro_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -2102,7 +2102,8 @@ class FeatureTestMacros:

def __init__(self, filename: str):
"""Initializes the class with the JSON data in the file 'filename'."""
self.__data = json.load(open(filename))
with open(filename) as f:
self.__data = json.load(f)

@functools.cached_property
def std_dialects(self) -> List[str]:
Expand Down Expand Up @@ -2187,8 +2188,8 @@ def version_header_implementation(self) -> Dict[str, List[Dict[str, Any]]]:
result[get_std_number(std)] = list()

for ftm, values in self.standard_ftms.items():
need_undef = False
last_value = None
last_entry = None
for std, value in values.items():
# When a newer Standard does not change the value of the macro
# there is no need to redefine it with the same value.
Expand All @@ -2198,12 +2199,11 @@ def version_header_implementation(self) -> Dict[str, List[Dict[str, Any]]]:

entry = dict()
entry["value"] = value
entry["implemented"] = self.implemented_ftms[ftm][std] != None
entry["need_undef"] = need_undef
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"]

need_undef = entry["implemented"]

last_entry = entry
result[get_std_number(std)].append(dict({ftm: entry}))

return result
Expand Down
Loading