[libcxx-commits] [libcxx] 8d5b81a - [libc++] Make it possible to mark a gen-test as UNSUPPORTED (#156737)

via libcxx-commits libcxx-commits at lists.llvm.org
Thu Sep 4 08:26:04 PDT 2025


Author: Louis Dionne
Date: 2025-09-04T11:26:00-04:00
New Revision: 8d5b81ae9bde06dcc80f9bcc2111663da7183d63

URL: https://github.com/llvm/llvm-project/commit/8d5b81ae9bde06dcc80f9bcc2111663da7183d63
DIFF: https://github.com/llvm/llvm-project/commit/8d5b81ae9bde06dcc80f9bcc2111663da7183d63.diff

LOG: [libc++] Make it possible to mark a gen-test as UNSUPPORTED (#156737)

Previously, only the tests that are generated by the gen-test could be
marked as UNSUPPORTED. After this patch, the gen-test itself can be
marked as UNSUPPORTED, which makes it possible to add RUN lines that
would be an error when unsupported to the gen-test itself.

Added: 
    libcxx/test/selftest/gen.cpp/unsupported.gen.cpp

Modified: 
    libcxx/test/extensions/clang/clang_modules_include.gen.py
    libcxx/test/extensions/posix/xopen_source.gen.py
    libcxx/test/libcxx-03/clang_tidy.gen.py
    libcxx/test/libcxx/clang_tidy.gen.py
    libcxx/test/libcxx/transitive_includes.gen.py
    libcxx/test/std/double_include.gen.py
    libcxx/test/std/header_inclusions.gen.py
    libcxx/test/std/iterators/iterator.range/mandatory_inclusions.gen.py
    libcxx/utils/libcxx/test/format.py

Removed: 
    


################################################################################
diff  --git a/libcxx/test/extensions/clang/clang_modules_include.gen.py b/libcxx/test/extensions/clang/clang_modules_include.gen.py
index 379ac22c8f47f..28661049d6e85 100644
--- a/libcxx/test/extensions/clang/clang_modules_include.gen.py
+++ b/libcxx/test/extensions/clang/clang_modules_include.gen.py
@@ -10,9 +10,32 @@
 # This is important notably because the LLDB data formatters use
 # libc++ headers with modules enabled.
 
-# RUN: %{python} %s %{libcxx-dir}/utils
+# Older macOS SDKs were not properly modularized, which causes issues with localization.
+# This feature should instead be based on the SDK version.
+# UNSUPPORTED: stdlib=system && target={{.+}}-apple-macosx13{{.*}}
+
+# GCC doesn't support -fcxx-modules
+# UNSUPPORTED: gcc
+
+# The Windows headers don't appear to be compatible with modules
+# UNSUPPORTED: windows
+# UNSUPPORTED: buildhost=windows
+
+# The Android headers don't appear to be compatible with modules yet
+# UNSUPPORTED: LIBCXX-ANDROID-FIXME
+
+# TODO: Investigate this failure
+# UNSUPPORTED: LIBCXX-FREEBSD-FIXME
+
+# TODO: Investigate why this doesn't work on Picolibc once the locale base API is refactored
+# UNSUPPORTED: LIBCXX-PICOLIBC-FIXME
+
+# TODO: Fix seemingly circular inclusion or <wchar.h> on AIX
+# UNSUPPORTED: LIBCXX-AIX-FIXME
 
-# block Lit from interpreting a RUN/XFAIL/etc inside the generation script
+# UNSUPPORTED: FROZEN-CXX03-HEADERS-FIXME
+
+# RUN: %{python} %s %{libcxx-dir}/utils
 # END.
 
 import sys
@@ -29,31 +52,6 @@
 //--- {header}.compile.pass.cpp
 // RUN: %{{cxx}} %s %{{flags}} %{{compile_flags}} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only
 
-// Older macOS SDKs were not properly modularized, which causes issues with localization.
-// This feature should instead be based on the SDK version.
-// UNSUPPORTED: stdlib=system && target={{{{.+}}}}-apple-macosx13{{{{.*}}}}
-
-// GCC doesn't support -fcxx-modules
-// UNSUPPORTED: gcc
-
-// The Windows headers don't appear to be compatible with modules
-// UNSUPPORTED: windows
-// UNSUPPORTED: buildhost=windows
-
-// The Android headers don't appear to be compatible with modules yet
-// UNSUPPORTED: LIBCXX-ANDROID-FIXME
-
-// TODO: Investigate this failure
-// UNSUPPORTED: LIBCXX-FREEBSD-FIXME
-
-// TODO: Investigate why this doesn't work on Picolibc once the locale base API is refactored
-// UNSUPPORTED: LIBCXX-PICOLIBC-FIXME
-
-// TODO: Fix seemingly circular inclusion or <wchar.h> on AIX
-// UNSUPPORTED: LIBCXX-AIX-FIXME
-
-// UNSUPPORTED: FROZEN-CXX03-HEADERS-FIXME
-
 {lit_header_restrictions.get(header, '')}
 {lit_header_undeprecations.get(header, '')}
 
@@ -68,30 +66,6 @@
 
 // REQUIRES: clang-modules-build
 
-// Older macOS SDKs were not properly modularized, which causes issues with localization.
-// This feature should instead be based on the SDK version.
-// UNSUPPORTED: stdlib=system && target={{{{.+}}}}-apple-macosx13{{{{.*}}}}
-
-// GCC doesn't support -fcxx-modules
-// UNSUPPORTED: gcc
-
-// The Windows headers don't appear to be compatible with modules
-// UNSUPPORTED: windows
-// UNSUPPORTED: buildhost=windows
-
-// The Android headers don't appear to be compatible with modules yet
-// UNSUPPORTED: LIBCXX-ANDROID-FIXME
-
-// TODO: Investigate this failure
-// UNSUPPORTED: LIBCXX-FREEBSD-FIXME
-
-// TODO: Investigate why this doesn't work on Picolibc once the locale base API is refactored
-// UNSUPPORTED: LIBCXX-PICOLIBC-FIXME
-
-// TODO: Fix seemingly circular inclusion or <wchar.h> on AIX
-// UNSUPPORTED: LIBCXX-AIX-FIXME
-
 @import std;
-
 """
 )

diff  --git a/libcxx/test/extensions/posix/xopen_source.gen.py b/libcxx/test/extensions/posix/xopen_source.gen.py
index 9d8c623379823..ec0d981d67b2b 100644
--- a/libcxx/test/extensions/posix/xopen_source.gen.py
+++ b/libcxx/test/extensions/posix/xopen_source.gen.py
@@ -12,6 +12,18 @@
 #
 # https://llvm.org/PR117630
 
+# Some parts of the code like <fstream> use non-standard functions in their implementation,
+# and these functions are not provided when _XOPEN_SOURCE is set to older values. This
+# breaks when building with modules even when we don't use the offending headers directly.
+# UNSUPPORTED: clang-modules-build
+
+# The AIX localization support uses some functions as part of their headers that require a
+# recent value of _XOPEN_SOURCE.
+# UNSUPPORTED: LIBCXX-AIX-FIXME
+
+# This test fails on FreeBSD for an unknown reason.
+# UNSUPPORTED: LIBCXX-FREEBSD-FIXME
+
 # RUN: %{python} %s %{libcxx-dir}/utils
 # END.
 
@@ -33,19 +45,6 @@
         print(
             f"""\
 //--- {header}.xopen_source_{version}.compile.pass.cpp
-
-// Some parts of the code like <fstream> use non-standard functions in their implementation,
-// and these functions are not provided when _XOPEN_SOURCE is set to older values. This
-// breaks when building with modules even when we don't use the offending headers directly.
-// UNSUPPORTED: clang-modules-build
-
-// The AIX localization support uses some functions as part of their headers that require a
-// recent value of _XOPEN_SOURCE.
-// UNSUPPORTED: LIBCXX-AIX-FIXME
-
-// This test fails on FreeBSD for an unknown reason.
-// UNSUPPORTED: LIBCXX-FREEBSD-FIXME
-
 {lit_header_restrictions.get(header, '')}
 {lit_header_undeprecations.get(header, '')}
 

diff  --git a/libcxx/test/libcxx-03/clang_tidy.gen.py b/libcxx/test/libcxx-03/clang_tidy.gen.py
index dbab2875e3126..5926f521e780e 100644
--- a/libcxx/test/libcxx-03/clang_tidy.gen.py
+++ b/libcxx/test/libcxx-03/clang_tidy.gen.py
@@ -6,12 +6,17 @@
 #
 # ===----------------------------------------------------------------------===##
 
-
 # Run our custom libc++ clang-tidy checks on all public headers.
 
-# RUN: %{python} %s %{libcxx-dir}/utils
+# REQUIRES: has-clang-tidy
+
+# The frozen headers should not be updated to the latest libc++ style, so don't test.
+# UNSUPPORTED: FROZEN-CXX03-HEADERS-FIXME
 
-# block Lit from interpreting a RUN/XFAIL/etc inside the generation script
+# The GCC compiler flags are not always compatible with clang-tidy.
+# UNSUPPORTED: gcc
+
+# RUN: %{python} %s %{libcxx-dir}/utils
 # END.
 
 import sys
@@ -21,15 +26,6 @@
 for header in public_headers:
   print(f"""\
 //--- {header}.sh.cpp
-
-// REQUIRES: has-clang-tidy
-
-// The frozen headers should not be updated to the latest libc++ style, so don't test.
-// UNSUPPORTED: FROZEN-CXX03-HEADERS-FIXME
-
-// The GCC compiler flags are not always compatible with clang-tidy.
-// UNSUPPORTED: gcc
-
 {lit_header_restrictions.get(header, '')}
 {lit_header_undeprecations.get(header, '')}
 

diff  --git a/libcxx/test/libcxx/clang_tidy.gen.py b/libcxx/test/libcxx/clang_tidy.gen.py
index 1663f5c396bbf..16c90c3ef7130 100644
--- a/libcxx/test/libcxx/clang_tidy.gen.py
+++ b/libcxx/test/libcxx/clang_tidy.gen.py
@@ -6,12 +6,14 @@
 #
 # ===----------------------------------------------------------------------===##
 
-
 # Run our custom libc++ clang-tidy checks on all public headers.
 
-# RUN: %{python} %s %{libcxx-dir}/utils
+# REQUIRES: has-clang-tidy
 
-# block Lit from interpreting a RUN/XFAIL/etc inside the generation script
+# The GCC compiler flags are not always compatible with clang-tidy.
+# UNSUPPORTED: gcc
+
+# RUN: %{python} %s %{libcxx-dir}/utils
 # END.
 
 import sys
@@ -21,12 +23,6 @@
 for header in public_headers:
   print(f"""\
 //--- {header}.sh.cpp
-
-// REQUIRES: has-clang-tidy
-
-// The GCC compiler flags are not always compatible with clang-tidy.
-// UNSUPPORTED: gcc
-
 {lit_header_restrictions.get(header, '')}
 {lit_header_undeprecations.get(header, '')}
 

diff  --git a/libcxx/test/libcxx/transitive_includes.gen.py b/libcxx/test/libcxx/transitive_includes.gen.py
index f01dbac26a8e8..6ed35af7e275e 100644
--- a/libcxx/test/libcxx/transitive_includes.gen.py
+++ b/libcxx/test/libcxx/transitive_includes.gen.py
@@ -17,8 +17,6 @@
 # to avoid breaking users at every release.
 
 # RUN: %{python} %s %{libcxx-dir}/utils
-
-# block Lit from interpreting a RUN/XFAIL/etc inside the generation script
 # END.
 
 import sys

diff  --git a/libcxx/test/selftest/gen.cpp/unsupported.gen.cpp b/libcxx/test/selftest/gen.cpp/unsupported.gen.cpp
new file mode 100644
index 0000000000000..6f35939f22582
--- /dev/null
+++ b/libcxx/test/selftest/gen.cpp/unsupported.gen.cpp
@@ -0,0 +1,18 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// Make sure we can mark a gen-test as UNSUPPORTED
+
+// We use C++03 as a random feature that we know exists. The goal is to make
+// this test always unsupported.
+// UNSUPPORTED: c++03
+// REQUIRES: c++03
+
+// Note that an unsupported gen-test should still contain some commands, otherwise
+// what are we generating? They are never executed, though.
+// RUN: something-definitely-invalid

diff  --git a/libcxx/test/std/double_include.gen.py b/libcxx/test/std/double_include.gen.py
index fcf3b9a8fa2e0..f019710be55b2 100644
--- a/libcxx/test/std/double_include.gen.py
+++ b/libcxx/test/std/double_include.gen.py
@@ -8,9 +8,10 @@
 
 # Test that we can include each header in two TU's and link them together.
 
-# RUN: %{python} %s %{libcxx-dir}/utils
+# We're using compiler-specific flags in this test
+# REQUIRES: (gcc || clang)
 
-# Block Lit from interpreting a RUN/XFAIL/etc inside the generation script.
+# RUN: %{python} %s %{libcxx-dir}/utils
 # END.
 
 import sys
@@ -28,9 +29,6 @@
 {lit_header_restrictions.get(header, '')}
 {lit_header_undeprecations.get(header, '')}
 
-// We're using compiler-specific flags in this test
-// REQUIRES: (gcc || clang)
-
 // RUN: %{{cxx}} -c %s -o %t.first.o %{{flags}} %{{compile_flags}}
 // RUN: %{{cxx}} -c %s -o %t.second.o -DWITH_MAIN %{{flags}} %{{compile_flags}}
 // RUN: %{{cxx}} -o %t.exe %t.first.o %t.second.o %{{flags}} %{{link_flags}}

diff  --git a/libcxx/test/std/header_inclusions.gen.py b/libcxx/test/std/header_inclusions.gen.py
index 8ff93810069fa..cebff94fdd1ab 100644
--- a/libcxx/test/std/header_inclusions.gen.py
+++ b/libcxx/test/std/header_inclusions.gen.py
@@ -9,6 +9,11 @@
 # Test that all headers include all the other headers they're supposed to, as
 # prescribed by the Standard.
 
+# UNSUPPORTED: FROZEN-CXX03-HEADERS-FIXME
+
+# TODO: This is currently a libc++-specific way of testing the includes, but is a requirement for all implementation
+# REQUIRES: stdlib=libc++
+
 # RUN: %{python} %s %{libcxx-dir}/utils
 # END.
 
@@ -46,11 +51,6 @@
     print(
         f"""\
 //--- {header}.compile.pass.cpp
-// UNSUPPORTED: FROZEN-CXX03-HEADERS-FIXME
-
-// TODO: This is currently a libc++-specific way of testing the includes, but is a requirement for all implementation
-// REQUIRES: stdlib=libc++
-
 {lit_header_restrictions.get(header, '')}
 {lit_header_undeprecations.get(header, '')}
 

diff  --git a/libcxx/test/std/iterators/iterator.range/mandatory_inclusions.gen.py b/libcxx/test/std/iterators/iterator.range/mandatory_inclusions.gen.py
index 46290b1ed52a0..34ede107e5ed6 100644
--- a/libcxx/test/std/iterators/iterator.range/mandatory_inclusions.gen.py
+++ b/libcxx/test/std/iterators/iterator.range/mandatory_inclusions.gen.py
@@ -12,6 +12,8 @@
 # <list>, <map>, <regex>, <set>, <span>, <string>, <string_view>, <unordered_map>,
 # <unordered_set>, <vector>.
 
+# UNSUPPORTED: c++03
+
 # RUN: %{python} %s %{libcxx-dir}/utils
 # END.
 
@@ -53,7 +55,6 @@
 //--- {header}.pass.cpp
 {lit_header_restrictions.get(header, '')}
 {lit_header_undeprecations.get(header, '')}
-// UNSUPPORTED: c++03
 
 #include <{header}>
 #include <cassert>

diff  --git a/libcxx/utils/libcxx/test/format.py b/libcxx/utils/libcxx/test/format.py
index 59d0fffd37819..a0b7b5bdb5b9f 100644
--- a/libcxx/utils/libcxx/test/format.py
+++ b/libcxx/utils/libcxx/test/format.py
@@ -34,11 +34,14 @@ def _checkBaseSubstitutions(substitutions):
 
 def _executeScriptInternal(test, litConfig, commands):
     """
-    Returns (stdout, stderr, exitCode, timeoutInfo, parsedCommands)
+    Returns (stdout, stderr, exitCode, timeoutInfo, parsedCommands), or an appropriate lit.Test.Result
+    in case of an error while parsing the script.
 
     TODO: This really should be easier to access from Lit itself
     """
     parsedCommands = parseScript(test, preamble=commands)
+    if isinstance(parsedCommands, lit.Test.Result):
+        return parsedCommands
 
     _, tmpBase = _getTempPaths(test)
     execDir = os.path.dirname(test.getExecPath())
@@ -65,7 +68,8 @@ def parseScript(test, preamble):
     """
     Extract the script from a test, with substitutions applied.
 
-    Returns a list of commands ready to be executed.
+    Returns a list of commands ready to be executed, or an appropriate lit.Test.Result in case of error
+    while parsing the script (this includes the script being unsupported).
 
     - test
         The lit.Test to parse.
@@ -350,6 +354,8 @@ def execute(self, test, litConfig):
             if "enable-benchmarks=run" in test.config.available_features:
                 steps += ["%dbg(EXECUTED AS) %{exec} %t.exe --benchmark_out=%T/benchmark-result.json --benchmark_out_format=json"]
             return self._executeShTest(test, litConfig, steps)
+        elif re.search('[.]gen[.][^.]+$', filename): # This only happens when a generator test is not supported
+            return self._executeShTest(test, litConfig, [])
         else:
             return lit.Test.Result(
                 lit.Test.UNRESOLVED, "Unknown test suffix for '{}'".format(filename)
@@ -381,11 +387,19 @@ def _generateGenTest(self, testSuite, pathInSuite, litConfig, localConfig):
         generatorExecDir = os.path.dirname(testSuite.getExecPath(pathInSuite))
         os.makedirs(generatorExecDir, exist_ok=True)
 
-        # Run the generator test
+        # Run the generator test. It's possible for this to fail for two reasons: the generator test
+        # is unsupported or the generator ran but failed at runtime -- handle both. In the first case,
+        # we return the generator test itself, since it should produce the same result when run after
+        # test suite generation. In the second case, it's a true error so we report it.
         steps = [] # Steps must already be in the script
-        (out, err, exitCode, _, _) = _executeScriptInternal(generator, litConfig, steps)
+        result = _executeScriptInternal(generator, litConfig, steps)
+        if isinstance(result, lit.Test.Result):
+            yield generator
+            return
+
+        (out, err, exitCode, _, _) = result
         if exitCode != 0:
-            raise RuntimeError(f"Error while trying to generate gen test\nstdout:\n{out}\n\nstderr:\n{err}")
+            raise RuntimeError(f"Error while trying to generate gen test {'/'.join(pathInSuite)}\nstdout:\n{out}\n\nstderr:\n{err}")
 
         # Split the generated output into multiple files and generate one test for each file
         for subfile, content in self._splitFile(out):


        


More information about the libcxx-commits mailing list