From 4e1f8c3d6911b61789ab7fc8e1b23f934f3a2888 Mon Sep 17 00:00:00 2001 From: Mark de Wever 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 4488af3244dd9..2113cc6668096 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 fe175fd758726..fc29f0a85ec9e 100644 --- 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, @@ -2021,6 +2022,25 @@ class FtmHeaderTest: implemented: bool = None 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]]]: @@ -2030,6 +2050,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: @@ -2040,6 +2061,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 ( @@ -2058,6 +2080,7 @@ def get_ftms( entry[std] = last result[feature["name"]] = entry + validate_sorted("ftm names", list(result)) return result