[libcxx-commits] [libcxx] [libc++] Adds additional FTM imput validation. (PR #138462)

Mark de Wever via libcxx-commits libcxx-commits at lists.llvm.org
Sun May 4 10:11:05 PDT 2025


https://github.com/mordante created https://github.com/llvm/llvm-project/pull/138462

This ensure the input is properly sorted; when not gives a nice diagnostic.

>From 82e4bd27ae8f5d887b15f33dfdcfb5ae74c117df Mon Sep 17 00:00:00 2001
From: Mark de Wever <koraq at xs4all.nl>
Date: Sun, 4 May 2025 19:09:25 +0200
Subject: [PATCH] [libc++] Adds additional FTM imput validation.

This ensure the input is properly sorted; when not gives a nice
diagnostic.
---
 .../libcxx/feature_test_macro/invalid.sh.py   | 169 +++++++++++++++++-
 .../generate_feature_test_macro_components.py |  23 +++
 2 files changed, 191 insertions(+), 1 deletion(-)

diff --git a/libcxx/test/libcxx/feature_test_macro/invalid.sh.py b/libcxx/test/libcxx/feature_test_macro/invalid.sh.py
index ae457f6e1a545..588f6bec1521c 100644
--- a/libcxx/test/libcxx/feature_test_macro/invalid.sh.py
+++ b/libcxx/test/libcxx/feature_test_macro/invalid.sh.py
@@ -12,7 +12,7 @@
 import json
 
 sys.path.append(sys.argv[1])
-from generate_feature_test_macro_components import FeatureTestMacros
+from generate_feature_test_macro_components import FeatureTestMacros, DataNotSorted
 
 
 def test(output, expected):
@@ -106,3 +106,170 @@ def test_error(data, type, message):
     KeyError,
     "'implemented'",
 )
+
+test_error(
+    [
+        {
+            "name": "abc",
+            "values": {
+                "c++17": {
+                    "197001": [
+                        {
+                            "implemented": False,
+                        },
+                    ],
+                },
+            },
+            "headers": [],
+        },
+        {
+            "name": "ghi",
+            "values": {
+                "c++17": {
+                    "197001": [
+                        {
+                            "implemented": False,
+                        },
+                    ],
+                },
+            },
+            "headers": [],
+        },
+        { # This entry is in the wrong alphabetic order
+            "name": "def",
+            "values": {
+                "c++17": {
+                    "197001": [
+                        {
+                            "implemented": False,
+                        },
+                    ],
+                },
+            },
+            "headers": [],
+        },
+        {
+            "name": "jkl",
+            "values": {
+                "c++17": {
+                    "197001": [
+                        {
+                            "implemented": False,
+                        },
+                    ],
+                },
+            },
+            "headers": [],
+        },
+    ],
+    DataNotSorted,
+    """\
+The ftm names are not sorted.
+--- input data
++++ sorted data
+@@ -1,4 +1,4 @@
+ abc
++def
+ ghi
+-def
+ jkl
+""",
+)
+
+test_error(
+    [
+        {
+            "name": "abc",
+            "values": {
+                "c++14": {
+                    "197001": [
+                        {
+                            "implemented": False,
+                        },
+                    ],
+                },
+                "c++23": {
+                    "197001": [
+                        {
+                            "implemented": False,
+                        },
+                    ],
+                },
+                # This entry is in the wrong alphabetic order
+                # Note we don't use C++98, but C++03 instead so alphabetic order
+                # works this century.
+                "c++20": {
+                    "197001": [
+                        {
+                            "implemented": False,
+                        },
+                    ],
+                },
+            },
+            "headers": [],
+        },
+    ],
+    DataNotSorted,
+    """\
+The C++ standard version numbers of ftm 'abc' are not sorted.
+--- input data
++++ sorted data
+@@ -1,3 +1,3 @@
+ c++14
++c++20
+ c++23
+-c++20
+""",
+)
+
+test_error(
+    [
+        {
+            "name": "abc",
+            "values": {
+                "c++14": {
+                    "197001": [
+                        {
+                            "implemented": False,
+                        },
+                    ],
+                    "197002": [
+                        {
+                            "implemented": False,
+                        },
+                    ],
+                    "197004": [
+                        {
+                            "implemented": False,
+                        },
+                    ],
+                    # This entry is in the wrong alphabetic order
+                    "197003": [
+                        {
+                            "implemented": False,
+                        },
+                    ],
+                    "197005": [
+                        {
+                            "implemented": False,
+                        },
+                    ],
+                },
+            },
+            "headers": [],
+        },
+    ],
+    DataNotSorted,
+    """\
+The value of the fmt 'abc' in c++14 are not sorted.
+--- input data
++++ sorted data
+@@ -1,5 +1,5 @@
+ 197001
+ 197002
++197003
+ 197004
+-197003
+ 197005
+""",
+)
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index cb92dc17ba707..cf69b39b294a5 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 dataclasses import dataclass
+from difflib import unified_diff
 from functools import reduce
 from typing import (
     Any,
@@ -1987,6 +1988,25 @@ class VersionHeader:
     condition: str = None
 
 
+class DataNotSorted(Exception):
+    pass
+
+def validate_sorted(name:str, data: List[str]) -> None:
+    sorted_data = sorted(data)
+    if data != sorted_data:
+        raise DataNotSorted(
+            f"The {name} are not sorted.\n"
+            + "\n".join(
+                unified_diff(
+                    data,
+                    sorted_data,
+                    "input data",
+                    "sorted data",
+                    lineterm="",
+                )
+            ) + "\n"
+        )
+
 def get_ftms(
     data, std_dialects: List[Std], use_implemented_status: bool
 ) -> Dict[Ftm, Dict[Std, Optional[Value]]]:
@@ -1996,6 +2016,7 @@ def get_ftms(
         last = None
         entry = dict()
         implemented = True
+        validate_sorted(f"C++ standard version numbers of ftm '{feature['name']}'", list(feature["values"].keys()))
         for std in std_dialects:
             if std not in feature["values"].keys():
                 if last == None:
@@ -2006,6 +2027,7 @@ def get_ftms(
                 if implemented:
                     values = feature["values"][std]
                     assert len(values) > 0, f"{feature['name']}[{std}] has no entries"
+                    validate_sorted(f"value of the fmt '{feature['name']}' in {std}", list(values.keys()))
                     for value in values:
                         papers = list(values[value])
                         assert (
@@ -2024,6 +2046,7 @@ def get_ftms(
                     entry[std] = last
         result[feature["name"]] = entry
 
+    validate_sorted("ftm names", list(result))
     return result
 
 



More information about the libcxx-commits mailing list