https://github.com/ldionne updated 
https://github.com/llvm/llvm-project/pull/214820

>From f4809a4a11e405f68f6258b308ebffd14770839e Mon Sep 17 00:00:00 2001
From: Louis Dionne <[email protected]>
Date: Fri, 7 Aug 2026 14:18:17 -0400
Subject: [PATCH 1/5] [libc++] Harden the test suite for running against older
 libc++ versions

When running against older libc++ versions, the test suite had problems
when sniffing carve-out macros. Since we changed from e.g. 
_LIBCPP_HAS_NO_LOCALIZATION
to _LIBCPP_HAS_LOCALIZATION == 0|1, we would mis-detect the absence of
_LIBCPP_HAS_NO_LOCALIZATION being defined for localization being supported.

Fix this by explicitly handling checks for older versions. Note that this
also simplifies how we deal with the C++03 frozen headers, since in most
cases the same handling covers both the frozen headers and older versions
of the library.

Also, move the detection of Lit features for carve-outs from ad-hoc Python
checks to using <test_macros.h> directly, since that centralizes the
logic in a single place. This requires making "test_macros.h" available
to libunwind tests, which previously didn't have the proper include path.
---
 libcxx/test/support/test_macros.h             | 64 +++++++++++--------
 libcxx/utils/libcxx/test/dsl.py               | 54 +++++++++++-----
 libcxx/utils/libcxx/test/features/__init__.py | 11 +++-
 .../utils/libcxx/test/features/carveouts.py   | 34 ++++++++++
 .../libcxx/test/features/libcxx_macros.py     |  7 --
 .../libcxx/test/features/localization.py      |  9 +--
 libcxx/utils/libcxx/test/features/misc.py     |  1 +
 .../configs/apple-libunwind-system.cfg.in     |  2 +-
 .../configs/armv7m-picolibc-libunwind.cfg.in  |  2 +-
 libunwind/test/configs/cmake-bridge.cfg.in    |  1 +
 .../test/configs/ibm-libunwind-shared.cfg.in  |  2 +-
 .../test/configs/llvm-libunwind-merged.cfg.in |  2 +-
 .../llvm-libunwind-shared-mingw.cfg.in        |  2 +-
 .../test/configs/llvm-libunwind-shared.cfg.in |  2 +-
 .../llvm-libunwind-static-mingw.cfg.in        |  2 +-
 .../test/configs/llvm-libunwind-static.cfg.in |  2 +-
 16 files changed, 137 insertions(+), 60 deletions(-)
 create mode 100644 libcxx/utils/libcxx/test/features/carveouts.py

diff --git a/libcxx/test/support/test_macros.h 
b/libcxx/test/support/test_macros.h
index 82975a38884f0..9c07f08b7d573 100644
--- a/libcxx/test/support/test_macros.h
+++ b/libcxx/test/support/test_macros.h
@@ -229,11 +229,9 @@
 #  define TEST_IS_EXECUTED_IN_A_SLOW_ENVIRONMENT
 #endif
 
-#ifdef _LIBCPP_USE_FROZEN_CXX03_HEADERS
-#  ifdef _LIBCPP_HAS_NO_ALIGNED_ALLOCATION
-#    define TEST_HAS_NO_ALIGNED_ALLOCATION
-#  endif
-#elif defined(_LIBCPP_VERSION) && !_LIBCPP_HAS_ALIGNED_ALLOCATION
+#if defined(_LIBCPP_VERSION) && defined(_LIBCPP_HAS_ALIGNED_ALLOCATION) && 
!_LIBCPP_HAS_ALIGNED_ALLOCATION
+#  define TEST_HAS_NO_ALIGNED_ALLOCATION
+#elif defined(_LIBCPP_VERSION) && defined(_LIBCPP_HAS_NO_ALIGNED_ALLOCATION) 
/* old libc++ version */
 #  define TEST_HAS_NO_ALIGNED_ALLOCATION
 #elif TEST_STD_VER < 17 && (!defined(__cpp_aligned_new) || __cpp_aligned_new < 
201606L)
 #  define TEST_HAS_NO_ALIGNED_ALLOCATION
@@ -287,9 +285,12 @@
 
 #define TEST_IGNORE_NODISCARD (void)
 
-#ifdef _LIBCPP_USE_FROZEN_CXX03_HEADERS
-// from-chars is a C++17 feature, so it's never available anyways
-#elif !defined(_LIBCPP_VERSION) || 
_LIBCPP_AVAILABILITY_HAS_FROM_CHARS_FLOATING_POINT
+#if defined(_LIBCPP_VERSION) && 
defined(_LIBCPP_AVAILABILITY_HAS_FROM_CHARS_FLOATING_POINT) &&                  
       \
+    !_LIBCPP_AVAILABILITY_HAS_FROM_CHARS_FLOATING_POINT
+// not available
+#elif defined(_LIBCPP_VERSION) && 
!defined(_LIBCPP_AVAILABILITY_HAS_FROM_CHARS_FLOATING_POINT) /* old libc++ 
version */
+// not available
+#else
 #  define TEST_HAS_FROM_CHARS_FLOATING_POINT
 #endif
 
@@ -420,11 +421,13 @@ inline Tp const& DoNotOptimize(Tp const& value) {
 #endif
 
 // Support for carving out parts of the test suite, like removing wide 
characters, etc.
-#if defined(_LIBCPP_VERSION) && !_LIBCPP_HAS_WIDE_CHARACTERS
+#if defined(_LIBCPP_VERSION) && defined(_LIBCPP_HAS_WIDE_CHARACTERS) && 
!_LIBCPP_HAS_WIDE_CHARACTERS
+#  define TEST_HAS_NO_WIDE_CHARACTERS
+#elif defined(_LIBCPP_VERSION) && defined(_LIBCPP_HAS_NO_WIDE_CHARACTERS) /* 
old libc++ version */
 #  define TEST_HAS_NO_WIDE_CHARACTERS
 #endif
 
-#if defined(_LIBCPP_VERSION) && !_LIBCPP_HAS_UNICODE
+#if defined(_LIBCPP_VERSION) && defined(_LIBCPP_HAS_UNICODE) && 
!_LIBCPP_HAS_UNICODE
 #  define TEST_HAS_NO_UNICODE
 #elif defined(_MSVC_EXECUTION_CHARACTER_SET) && _MSVC_EXECUTION_CHARACTER_SET 
!= 65001
 #  define TEST_HAS_NO_UNICODE
@@ -434,7 +437,7 @@ inline Tp const& DoNotOptimize(Tp const& value) {
 #  ifdef _LIBCPP_HAS_OPEN_WITH_WCHAR
 #    define TEST_HAS_OPEN_WITH_WCHAR
 #  endif
-#elif defined(_LIBCPP_VERSION) && _LIBCPP_HAS_OPEN_WITH_WCHAR
+#elif defined(_LIBCPP_VERSION) && defined(_LIBCPP_HAS_OPEN_WITH_WCHAR) && 
_LIBCPP_HAS_OPEN_WITH_WCHAR
 #  define TEST_HAS_OPEN_WITH_WCHAR
 #endif
 
@@ -442,11 +445,17 @@ inline Tp const& DoNotOptimize(Tp const& value) {
 #  ifdef _LIBCPP_HAS_NO_INT128
 #    define TEST_HAS_NO_INT128
 #  endif
-#elif (defined(_LIBCPP_VERSION) && !_LIBCPP_HAS_INT128) || 
defined(_MSVC_STL_VERSION)
+#elif defined(_LIBCPP_VERSION) && (defined(_LIBCPP_HAS_INT128) && 
!_LIBCPP_HAS_INT128)
+#  define TEST_HAS_NO_INT128
+#elif defined(_LIBCPP_VERSION) && defined(_LIBCPP_HAS_NO_INT128) /* old libc++ 
version */
+#  define TEST_HAS_NO_INT128
+#elif defined(_MSVC_STL_VERSION)
 #  define TEST_HAS_NO_INT128
 #endif
 
-#if defined(_LIBCPP_VERSION) && !_LIBCPP_HAS_LOCALIZATION
+#if defined(_LIBCPP_VERSION) && defined(_LIBCPP_HAS_LOCALIZATION) && 
!_LIBCPP_HAS_LOCALIZATION
+#  define TEST_HAS_NO_LOCALIZATION
+#elif defined(_LIBCPP_VERSION) && defined(_LIBCPP_HAS_NO_LOCALIZATION) /* old 
libc++ version */
 #  define TEST_HAS_NO_LOCALIZATION
 #endif
 
@@ -454,34 +463,39 @@ inline Tp const& DoNotOptimize(Tp const& value) {
 #  define TEST_HAS_NO_CHAR8_T
 #endif
 
-#if defined(_LIBCPP_VERSION) && !_LIBCPP_HAS_THREADS
+#if defined(_LIBCPP_VERSION) && defined(_LIBCPP_HAS_THREADS) && 
!_LIBCPP_HAS_THREADS
+#  define TEST_HAS_NO_THREADS
+#elif defined(_LIBCPP_VERSION) && defined(_LIBCPP_HAS_NO_THREADS) /* old 
libc++ version */
 #  define TEST_HAS_NO_THREADS
 #endif
 
-#if defined(_LIBCPP_VERSION) && !_LIBCPP_HAS_FILESYSTEM
+#if defined(_LIBCPP_VERSION) && defined(_LIBCPP_HAS_FILESYSTEM) && 
!_LIBCPP_HAS_FILESYSTEM
+#  define TEST_HAS_NO_FILESYSTEM
+#elif defined(_LIBCPP_VERSION) && defined(_LIBCPP_HAS_NO_FILESYSTEM) /* old 
libc++ version */
 #  define TEST_HAS_NO_FILESYSTEM
 #endif
 
-#ifdef _LIBCPP_USE_FROZEN_CXX03_HEADERS
-#  ifdef _LIBCPP_HAS_NO_C8RTOMB_MBRTOC8
-#    define TEST_HAS_NO_C8RTOMB_MBRTOC8
-#  endif
-#elif defined(_LIBCPP_VERSION) && !_LIBCPP_HAS_C8RTOMB_MBRTOC8
+#if defined(_LIBCPP_VERSION) && defined(_LIBCPP_HAS_C8RTOMB_MBRTOC8) && 
!_LIBCPP_HAS_C8RTOMB_MBRTOC8
+#  define TEST_HAS_NO_C8RTOMB_MBRTOC8
+#elif defined(_LIBCPP_VERSION) && defined(_LIBCPP_HAS_NO_C8RTOMB_MBRTOC8) /* 
old libc++ version */
 #  define TEST_HAS_NO_C8RTOMB_MBRTOC8
 #endif
 
-#if defined(_LIBCPP_VERSION) && !_LIBCPP_HAS_RANDOM_DEVICE
+#if defined(_LIBCPP_VERSION) && defined(_LIBCPP_HAS_RANDOM_DEVICE) && 
!_LIBCPP_HAS_RANDOM_DEVICE
+#  define TEST_HAS_NO_RANDOM_DEVICE
+#elif defined(_LIBCPP_VERSION) && defined(_LIBCPP_HAS_NO_RANDOM_DEVICE) /* old 
libc++ version */
 #  define TEST_HAS_NO_RANDOM_DEVICE
 #endif
 
-#ifdef _LIBCPP_USE_FROZEN_CXX03_HEADERS
-// This is a C++20 feature, so it's never available anyways
+#if defined(_LIBCPP_VERSION) && defined(_LIBCPP_HAS_EXPERIMENTAL_TZDB) && 
!_LIBCPP_HAS_EXPERIMENTAL_TZDB
 #  define TEST_HAS_NO_EXPERIMENTAL_TZDB
-#elif defined(_LIBCPP_VERSION) && !_LIBCPP_HAS_EXPERIMENTAL_TZDB
+#elif defined(_LIBCPP_VERSION) && !defined(_LIBCPP_HAS_EXPERIMENTAL_TZDB) /* 
old libc++ version */
 #  define TEST_HAS_NO_EXPERIMENTAL_TZDB
 #endif
 
-#if defined(_LIBCPP_VERSION) && !_LIBCPP_HAS_TIME_ZONE_DATABASE
+#if defined(_LIBCPP_VERSION) && defined(_LIBCPP_HAS_TIME_ZONE_DATABASE) && 
!_LIBCPP_HAS_TIME_ZONE_DATABASE
+#  define TEST_HAS_NO_TIME_ZONE_DATABASE
+#elif defined(_LIBCPP_VERSION) && defined(_LIBCPP_HAS_NO_TIME_ZONE_DATABASE) 
/* old libc++ version */
 #  define TEST_HAS_NO_TIME_ZONE_DATABASE
 #endif
 
diff --git a/libcxx/utils/libcxx/test/dsl.py b/libcxx/utils/libcxx/test/dsl.py
index c7db35fd629b6..d44752278c0a9 100644
--- a/libcxx/utils/libcxx/test/dsl.py
+++ b/libcxx/utils/libcxx/test/dsl.py
@@ -307,7 +307,8 @@ def hasAnyLocale(config, locales):
     program = (
         """
     #include <stddef.h>
-    #if defined(_LIBCPP_VERSION) && !_LIBCPP_HAS_LOCALIZATION
+    #include <test_macros.h>
+    #ifdef TEST_HAS_NO_LOCALIZATION
       int main(int, char**) { return 1; }
     #else
       #include <locale.h>
@@ -330,32 +331,22 @@ def hasAnyLocale(config, locales):
     return programSucceeds(config, program)
 
 
-@_memoizeExpensiveOperation(lambda c, flags="": (c.substitutions, 
c.environment, flags))
-def compilerMacros(config, flags=""):
+def _macrosFromSource(config, source, flags=""):
     """
-    Return a dictionary of predefined compiler macros.
+    Preprocess the given source and return a dictionary of the macros it 
defines.
 
     The keys are strings representing macros, and the values are strings
     representing what each macro is defined to.
-
-    If the optional `flags` argument (a string) is provided, these flags will
-    be added to the compiler invocation when generating the macros.
     """
     with _makeConfigTest(config) as test:
         with open(test.getSourcePath(), "w") as sourceFile:
-            sourceFile.write(
-                """
-      #if __has_include(<__config>)
-      #  include <__config>
-      #endif
-      """
-            )
+            sourceFile.write(source)
         unparsedOutput, err, exitCode, _, cmd, _ = _executeWithFakeConfig(
             test, ["%{{cxx}} %s -dM -E %{{flags}} %{{compile_flags}} 
{}".format(flags)]
         )
         if exitCode != 0:
             raise ConfigurationCompilationError(
-                "Failed to retrieve compiler macros, compiler invocation 
is:\n{}\nstderr is:\n{}".format(
+                "Failed to retrieve macros, compiler invocation 
is:\n{}\nstderr is:\n{}".format(
                     cmd, err
                 )
             )
@@ -370,6 +361,39 @@ def compilerMacros(config, flags=""):
         return parsedMacros
 
 
+@_memoizeExpensiveOperation(lambda c, flags="": (c.substitutions, 
c.environment, flags))
+def compilerMacros(config, flags=""):
+    """
+    Return a dictionary of predefined compiler macros.
+
+    The keys are strings representing macros, and the values are strings
+    representing what each macro is defined to.
+
+    If the optional `flags` argument (a string) is provided, these flags will
+    be added to the compiler invocation when generating the macros.
+    """
+    source = """
+    #if __has_include(<__config>)
+    #  include <__config>
+    #endif
+    """
+    return _macrosFromSource(config, source, flags)
+
+
+@_memoizeExpensiveOperation(lambda c, flags="": (c.substitutions, 
c.environment, flags))
+def testMacros(config, flags=""):
+    """
+    Return a dictionary of the macros defined by the test suite's 
<test_macros.h>.
+
+    The keys are strings representing macros, and the values are strings
+    representing what each macro is defined to.
+
+    If the optional `flags` argument (a string) is provided, these flags will
+    be added to the compiler invocation when generating the macros.
+    """
+    return _macrosFromSource(config, "#include <test_macros.h>\n", flags)
+
+
 def featureTestMacros(config, flags=""):
     """
     Return a dictionary of feature test macros.
diff --git a/libcxx/utils/libcxx/test/features/__init__.py 
b/libcxx/utils/libcxx/test/features/__init__.py
index 8e9bc0e97b2d6..7516f4fc2f188 100644
--- a/libcxx/utils/libcxx/test/features/__init__.py
+++ b/libcxx/utils/libcxx/test/features/__init__.py
@@ -6,7 +6,15 @@
 #
 # 
===----------------------------------------------------------------------===##
 
-from . import availability, compiler, gdb, hardening, libcxx_macros, 
localization, misc, platform
+from . import availability
+from . import carveouts
+from . import compiler
+from . import gdb
+from . import hardening
+from . import libcxx_macros
+from . import localization
+from . import misc
+from . import platform
 
 # Lit features are evaluated in order. Some features depend on other features, 
so
 # we are careful to define them in the correct order. For example, several 
features
@@ -14,6 +22,7 @@
 DEFAULT_FEATURES = []
 DEFAULT_FEATURES += compiler.features
 DEFAULT_FEATURES += libcxx_macros.features
+DEFAULT_FEATURES += carveouts.features
 DEFAULT_FEATURES += platform.features
 DEFAULT_FEATURES += localization.features
 DEFAULT_FEATURES += gdb.features
diff --git a/libcxx/utils/libcxx/test/features/carveouts.py 
b/libcxx/utils/libcxx/test/features/carveouts.py
new file mode 100644
index 0000000000000..f485b15cdf464
--- /dev/null
+++ b/libcxx/utils/libcxx/test/features/carveouts.py
@@ -0,0 +1,34 @@
+# 
===----------------------------------------------------------------------===##
+#
+# 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
+#
+# 
===----------------------------------------------------------------------===##
+
+from libcxx.test.dsl import Feature, testMacros
+
+features = []
+
+# Features describing parts of the library that can be carved out, like 
localization
+# or threading support.
+#
+# These are detected by asking <test_macros.h> whether it considers the 
carve-out to be
+# in effect. This keeps the logic for determining whether a carve-out applies 
in a single
+# place, and it guarantees that these Lit features agree with what the tests 
use.
+carveouts = {
+    "TEST_HAS_NO_FILESYSTEM": "no-filesystem",
+    "TEST_HAS_NO_LOCALIZATION": "no-localization",
+    "TEST_HAS_NO_RANDOM_DEVICE": "no-random-device",
+    "TEST_HAS_NO_THREADS": "no-threads",
+    "TEST_HAS_NO_TIME_ZONE_DATABASE": "no-tzdb",
+    "TEST_HAS_NO_UNICODE": "libcpp-has-no-unicode",
+    "TEST_HAS_NO_WIDE_CHARACTERS": "no-wide-characters",
+}
+for macro, feature in carveouts.items():
+    features.append(
+        Feature(
+            name=feature,
+            when=lambda cfg, m=macro: m in testMacros(cfg),
+        )
+    )
diff --git a/libcxx/utils/libcxx/test/features/libcxx_macros.py 
b/libcxx/utils/libcxx/test/features/libcxx_macros.py
index ec149bef1a40e..9ac22e07c549c 100644
--- a/libcxx/utils/libcxx/test/features/libcxx_macros.py
+++ b/libcxx/utils/libcxx/test/features/libcxx_macros.py
@@ -60,15 +60,8 @@
     )
 
 inverted_macros = {
-    "_LIBCPP_HAS_TIME_ZONE_DATABASE": "no-tzdb",
-    "_LIBCPP_HAS_FILESYSTEM": "no-filesystem",
-    "_LIBCPP_HAS_LOCALIZATION": "no-localization",
-    "_LIBCPP_HAS_THREADS": "no-threads",
     "_LIBCPP_HAS_MONOTONIC_CLOCK": "no-monotonic-clock",
-    "_LIBCPP_HAS_WIDE_CHARACTERS": "no-wide-characters",
     "_LIBCPP_HAS_VENDOR_AVAILABILITY_ANNOTATIONS": 
"libcpp-has-no-availability-markup",
-    "_LIBCPP_HAS_RANDOM_DEVICE": "no-random-device",
-    "_LIBCPP_HAS_UNICODE": "libcpp-has-no-unicode",
 }
 for macro, feature in inverted_macros.items():
     features.append(
diff --git a/libcxx/utils/libcxx/test/features/localization.py 
b/libcxx/utils/libcxx/test/features/localization.py
index 95e1bb5c1afa4..b45c0bf5fd8c0 100644
--- a/libcxx/utils/libcxx/test/features/localization.py
+++ b/libcxx/utils/libcxx/test/features/localization.py
@@ -6,7 +6,7 @@
 #
 # 
===----------------------------------------------------------------------===##
 
-from libcxx.test.dsl import compilerMacros, Feature, programSucceeds, 
hasAnyLocale, programOutput, AddSubstitution
+from libcxx.test.dsl import Feature, programSucceeds, hasAnyLocale, 
programOutput, testMacros, AddSubstitution
 import re
 
 features = [
@@ -23,8 +23,10 @@
               #include <locale.h>
             #endif
 
+            #include "test_macros.h"
+
               int main(int, char**) {
-            #if __has_include(<locale.h>) && 
(!defined(_LIBCPP_HAS_LOCALIZATION) || _LIBCPP_HAS_LOCALIZATION == 1)
+            #if __has_include(<locale.h>) && !defined(TEST_HAS_NO_LOCALIZATION)
                 setlocale(LC_ALL, "ru_RU.UTF-8");
                 return strcmp(localeconv()->mon_decimal_point, ".") == 0 ? 
EXIT_SUCCESS : EXIT_FAILURE;
             #else
@@ -63,8 +65,7 @@
                 cfg, locale, alts, _provide_locale_conversions[locale]
             )
             if locale in _provide_locale_conversions
-            and ("_LIBCPP_HAS_WIDE_CHARACTERS" not in compilerMacros(cfg) or
-                 compilerMacros(cfg)["_LIBCPP_HAS_WIDE_CHARACTERS"] == "1")
+            and "TEST_HAS_NO_WIDE_CHARACTERS" not in testMacros(cfg)
             else [],
         ),
     )
diff --git a/libcxx/utils/libcxx/test/features/misc.py 
b/libcxx/utils/libcxx/test/features/misc.py
index 3701498f595dc..4b74ec7c0d6f4 100644
--- a/libcxx/utils/libcxx/test/features/misc.py
+++ b/libcxx/utils/libcxx/test/features/misc.py
@@ -121,6 +121,7 @@ def _mingwSupportsModules(cfg):
     # Check for a Windows UCRT bug (fixed in UCRT/Windows 10.0.20348.0):
     # 
https://developercommunity.visualstudio.com/t/utf-8-locales-break-ctype-functions-for-wchar-type/1653678
     Feature(
+        # TODO: Update once https://github.com/llvm/llvm-project/pull/214797 
has been merged
         name="win32-broken-utf8-wchar-ctype",
         when=lambda cfg: not "_LIBCPP_HAS_LOCALIZATION" in compilerMacros(cfg)
         or compilerMacros(cfg)["_LIBCPP_HAS_LOCALIZATION"] == "1"
diff --git a/libunwind/test/configs/apple-libunwind-system.cfg.in 
b/libunwind/test/configs/apple-libunwind-system.cfg.in
index 2349ca394b58b..d0465d5550fdc 100644
--- a/libunwind/test/configs/apple-libunwind-system.cfg.in
+++ b/libunwind/test/configs/apple-libunwind-system.cfg.in
@@ -13,7 +13,7 @@ config.substitutions.append(('%{flags}',
     '-isysroot {}'.format('@CMAKE_OSX_SYSROOT@') if '@CMAKE_OSX_SYSROOT@' else 
''
 ))
 
-compile_flags = ['-nostdinc++', '-I', '%{include}']
+compile_flags = ['-nostdinc++', '-I', '%{include}', '-I', 
'%{libcxx}/test/support']
 if @HAVE_CFI_SET_RA_STATE@:
     compile_flags.append('-DHAVE_CFI_SET_RA_STATE')
 
diff --git a/libunwind/test/configs/armv7m-picolibc-libunwind.cfg.in 
b/libunwind/test/configs/armv7m-picolibc-libunwind.cfg.in
index 6ffdd70c6177e..11a0f61f5720e 100644
--- a/libunwind/test/configs/armv7m-picolibc-libunwind.cfg.in
+++ b/libunwind/test/configs/armv7m-picolibc-libunwind.cfg.in
@@ -5,7 +5,7 @@ libc_linker_script = '@CMAKE_INSTALL_PREFIX@/lib/picolibcpp.ld'
 config.substitutions.append(('%{flags}', '--sysroot=@CMAKE_INSTALL_PREFIX@'))
 
 config.substitutions.append(('%{compile_flags}',
-    '-nostdinc++ -I %{include}'
+    '-nostdinc++ -I %{include} -I %{libcxx}/test/support'
 ))
 config.substitutions.append(('%{link_flags}',
     '-fuse-ld=lld -nostdlib -nostdlib++ -L %{lib} -lunwind'
diff --git a/libunwind/test/configs/cmake-bridge.cfg.in 
b/libunwind/test/configs/cmake-bridge.cfg.in
index 09bd92ab9fee2..ed0b2afbc0c0d 100644
--- a/libunwind/test/configs/cmake-bridge.cfg.in
+++ b/libunwind/test/configs/cmake-bridge.cfg.in
@@ -41,6 +41,7 @@ if _norm_triple != config.target_triple:
     config.available_features.add('target={}'.format(_norm_triple))
 
 # Add substitutions for bootstrapping the test suite configuration
+config.substitutions.append(('%{libcxx}', '@LIBUNWIND_LIBCXX_PATH@'))
 config.substitutions.append(('%{install-prefix}', 
'@LIBUNWIND_TESTING_INSTALL_PREFIX@'))
 config.substitutions.append(('%{include}', 
'@LIBUNWIND_TESTING_INSTALL_PREFIX@/include'))
 config.substitutions.append(('%{lib}', 
'@LIBUNWIND_TESTING_INSTALL_PREFIX@/@LIBUNWIND_INSTALL_LIBRARY_DIR@'))
diff --git a/libunwind/test/configs/ibm-libunwind-shared.cfg.in 
b/libunwind/test/configs/ibm-libunwind-shared.cfg.in
index 99f4a9061d19a..6848bf9dbbc45 100644
--- a/libunwind/test/configs/ibm-libunwind-shared.cfg.in
+++ b/libunwind/test/configs/ibm-libunwind-shared.cfg.in
@@ -11,7 +11,7 @@ if lit.util.isAIXTriple(config.target_triple):
 
 config.substitutions.append(('%{flags}', ''))
 config.substitutions.append(('%{compile_flags}',
-    '-nostdinc++ -I %{include}'
+    '-nostdinc++ -I %{include} -I %{libcxx}/test/support'
 ))
 config.substitutions.append(('%{link_flags}',
     '-nostdlib++ -L %{lib} -lunwind -ldl -Wl,-bbigtoc'
diff --git a/libunwind/test/configs/llvm-libunwind-merged.cfg.in 
b/libunwind/test/configs/llvm-libunwind-merged.cfg.in
index 231849f5c4e56..b05a55e40559b 100644
--- a/libunwind/test/configs/llvm-libunwind-merged.cfg.in
+++ b/libunwind/test/configs/llvm-libunwind-merged.cfg.in
@@ -38,7 +38,7 @@ config.substitutions.append(('%{flags}',
     '-isysroot {}'.format(local_sysroot) if local_sysroot else ''
 ))
 config.substitutions.append(('%{compile_flags}',
-    '-nostdinc++ -I %{{include}} {}'.format(' '.join(compile_flags))
+    '-nostdinc++ -I %{{include}} -I %{{libcxx}}/test/support {}'.format(' 
'.join(compile_flags))
 ))
 config.substitutions.append(('%{link_flags}',
     '-L %{{lib}} -Wl,-rpath,%{{lib}} -lc++ {}'.format(' '.join(link_flags))
diff --git a/libunwind/test/configs/llvm-libunwind-shared-mingw.cfg.in 
b/libunwind/test/configs/llvm-libunwind-shared-mingw.cfg.in
index 1e77638b8cee3..de3029d579921 100644
--- a/libunwind/test/configs/llvm-libunwind-shared-mingw.cfg.in
+++ b/libunwind/test/configs/llvm-libunwind-shared-mingw.cfg.in
@@ -5,7 +5,7 @@ lit_config.load_config(config, 
'@CMAKE_CURRENT_BINARY_DIR@/cmake-bridge.cfg')
 
 config.substitutions.append(('%{flags}', ''))
 config.substitutions.append(('%{compile_flags}',
-    '-nostdinc++ -I %{include} -funwind-tables'
+    '-nostdinc++ -I %{include} -I %{libcxx}/test/support -funwind-tables'
 ))
 config.substitutions.append(('%{link_flags}',
     '-L %{lib} -lunwind'
diff --git a/libunwind/test/configs/llvm-libunwind-shared.cfg.in 
b/libunwind/test/configs/llvm-libunwind-shared.cfg.in
index 0a7a24eb08c5e..8ae618fd7f6ae 100644
--- a/libunwind/test/configs/llvm-libunwind-shared.cfg.in
+++ b/libunwind/test/configs/llvm-libunwind-shared.cfg.in
@@ -37,7 +37,7 @@ config.substitutions.append(('%{flags}',
     '-isysroot {}'.format(local_sysroot) if local_sysroot else ''
 ))
 config.substitutions.append(('%{compile_flags}',
-    '-nostdinc++ -I %{{include}} {}'.format(' '.join(compile_flags))
+    '-nostdinc++ -I %{{include}} -I %{{libcxx}}/test/support {}'.format(' 
'.join(compile_flags))
 ))
 config.substitutions.append(('%{link_flags}',
     '-L %{{lib}} -Wl,-rpath,%{{lib}} -lunwind {}'.format(' '.join(link_flags))
diff --git a/libunwind/test/configs/llvm-libunwind-static-mingw.cfg.in 
b/libunwind/test/configs/llvm-libunwind-static-mingw.cfg.in
index 37d20a7c9a449..47921e9c32a36 100644
--- a/libunwind/test/configs/llvm-libunwind-static-mingw.cfg.in
+++ b/libunwind/test/configs/llvm-libunwind-static-mingw.cfg.in
@@ -5,7 +5,7 @@ lit_config.load_config(config, 
'@CMAKE_CURRENT_BINARY_DIR@/cmake-bridge.cfg')
 
 config.substitutions.append(('%{flags}', ''))
 config.substitutions.append(('%{compile_flags}',
-    '-nostdinc++ -I %{include} -funwind-tables'
+    '-nostdinc++ -I %{include} -I %{libcxx}/test/support -funwind-tables'
 ))
 config.substitutions.append(('%{link_flags}',
     '-L %{lib} -lunwind'
diff --git a/libunwind/test/configs/llvm-libunwind-static.cfg.in 
b/libunwind/test/configs/llvm-libunwind-static.cfg.in
index f831c74948579..f4b8e1b03b9b5 100644
--- a/libunwind/test/configs/llvm-libunwind-static.cfg.in
+++ b/libunwind/test/configs/llvm-libunwind-static.cfg.in
@@ -40,7 +40,7 @@ config.substitutions.append(('%{flags}',
     '-isysroot {}'.format(local_sysroot) if local_sysroot else ''
 ))
 config.substitutions.append(('%{compile_flags}',
-    '-nostdinc++ -I %{{include}} {}'.format(' '.join(compile_flags))
+    '-nostdinc++ -I %{{include}} -I %{{libcxx}}/test/support {}'.format(' 
'.join(compile_flags))
 ))
 config.substitutions.append(('%{link_flags}',
     '%{{lib}}/libunwind.a {}'.format(' '.join(link_flags))

>From 3fc8b3fa6acb8fbdd4e0cc2f4c8f918a6918ab1e Mon Sep 17 00:00:00 2001
From: Louis Dionne <[email protected]>
Date: Fri, 7 Aug 2026 14:44:51 -0400
Subject: [PATCH 2/5] Redundant parens

---
 libcxx/test/support/test_macros.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/test/support/test_macros.h 
b/libcxx/test/support/test_macros.h
index 9c07f08b7d573..1c5447a772f3f 100644
--- a/libcxx/test/support/test_macros.h
+++ b/libcxx/test/support/test_macros.h
@@ -445,7 +445,7 @@ inline Tp const& DoNotOptimize(Tp const& value) {
 #  ifdef _LIBCPP_HAS_NO_INT128
 #    define TEST_HAS_NO_INT128
 #  endif
-#elif defined(_LIBCPP_VERSION) && (defined(_LIBCPP_HAS_INT128) && 
!_LIBCPP_HAS_INT128)
+#elif defined(_LIBCPP_VERSION) && defined(_LIBCPP_HAS_INT128) && 
!_LIBCPP_HAS_INT128
 #  define TEST_HAS_NO_INT128
 #elif defined(_LIBCPP_VERSION) && defined(_LIBCPP_HAS_NO_INT128) /* old libc++ 
version */
 #  define TEST_HAS_NO_INT128

>From fc174a9d0fd07821eed4601f91f972def90af08d Mon Sep 17 00:00:00 2001
From: Louis Dionne <[email protected]>
Date: Mon, 10 Aug 2026 08:48:26 -0400
Subject: [PATCH 3/5] Handle no unicode

---
 libcxx/test/support/test_macros.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/libcxx/test/support/test_macros.h 
b/libcxx/test/support/test_macros.h
index 1c5447a772f3f..a06826104a324 100644
--- a/libcxx/test/support/test_macros.h
+++ b/libcxx/test/support/test_macros.h
@@ -429,6 +429,8 @@ inline Tp const& DoNotOptimize(Tp const& value) {
 
 #if defined(_LIBCPP_VERSION) && defined(_LIBCPP_HAS_UNICODE) && 
!_LIBCPP_HAS_UNICODE
 #  define TEST_HAS_NO_UNICODE
+#elif defined(_LIBCPP_VERSION) && defined(_LIBCPP_HAS_NO_UNICODE) /* old 
libc++ version */
+#  define TEST_HAS_NO_UNICODE
 #elif defined(_MSVC_EXECUTION_CHARACTER_SET) && _MSVC_EXECUTION_CHARACTER_SET 
!= 65001
 #  define TEST_HAS_NO_UNICODE
 #endif

>From 07fe5f025ddac0a2b150dda097a5634196fc6758 Mon Sep 17 00:00:00 2001
From: Louis Dionne <[email protected]>
Date: Mon, 10 Aug 2026 08:49:39 -0400
Subject: [PATCH 4/5] Handle no <ciso646> being available

---
 libcxx/test/support/test_macros.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/test/support/test_macros.h 
b/libcxx/test/support/test_macros.h
index a06826104a324..de6fa29234106 100644
--- a/libcxx/test/support/test_macros.h
+++ b/libcxx/test/support/test_macros.h
@@ -13,7 +13,7 @@
 #ifdef __has_include
 #  if __has_include(<version>)
 #    include <version>
-#  else
+#  elif __has_include(<ciso646>)
 #    include <ciso646>
 #  endif
 #else

>From f8b4eeffe33cb6e515b92c7b340d09e71eae244a Mon Sep 17 00:00:00 2001
From: Louis Dionne <[email protected]>
Date: Mon, 10 Aug 2026 09:01:39 -0400
Subject: [PATCH 5/5] Adjust after landing win32-broken-utf8-wchar-ctype
 simplification

---
 libcxx/utils/libcxx/test/dsl.py           | 4 +++-
 libcxx/utils/libcxx/test/features/misc.py | 5 +++--
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/libcxx/utils/libcxx/test/dsl.py b/libcxx/utils/libcxx/test/dsl.py
index d44752278c0a9..bc65c9b74219f 100644
--- a/libcxx/utils/libcxx/test/dsl.py
+++ b/libcxx/utils/libcxx/test/dsl.py
@@ -307,7 +307,9 @@ def hasAnyLocale(config, locales):
     program = (
         """
     #include <stddef.h>
-    #include <test_macros.h>
+
+    #include "test_macros.h"
+
     #ifdef TEST_HAS_NO_LOCALIZATION
       int main(int, char**) { return 1; }
     #else
diff --git a/libcxx/utils/libcxx/test/features/misc.py 
b/libcxx/utils/libcxx/test/features/misc.py
index df53d006ed66d..1f4b808e40820 100644
--- a/libcxx/utils/libcxx/test/features/misc.py
+++ b/libcxx/utils/libcxx/test/features/misc.py
@@ -121,7 +121,6 @@ def _mingwSupportsModules(cfg):
     # Check for a Windows UCRT bug (fixed in UCRT/Windows 10.0.20348.0):
     # 
https://developercommunity.visualstudio.com/t/utf-8-locales-break-ctype-functions-for-wchar-type/1653678
     Feature(
-        # TODO: Update once https://github.com/llvm/llvm-project/pull/214797 
has been merged
         name="win32-broken-utf8-wchar-ctype",
         when=lambda cfg: "_WIN32" in compilerMacros(cfg)
         and programSucceeds(
@@ -133,8 +132,10 @@ def _mingwSupportsModules(cfg):
             #include <stdlib.h>
             #include <wctype.h>
 
+            #include "test_macros.h"
+
             int main(int, char**) {
-            #if !defined(_LIBCPP_VERSION) || 
(defined(_LIBCPP_HAS_LOCALIZATION) && _LIBCPP_HAS_LOCALIZATION)
+            #ifndef TEST_HAS_NO_LOCALIZATION
               setlocale(LC_ALL, "en_US.UTF-8");
               return towlower(L'\\xDA') == L'\\xFA' ? EXIT_FAILURE : 
EXIT_SUCCESS;
             #else

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to