[compiler-rt] [libcxx] [libcxxabi] [libunwind] [llvm] for ohos llvm libcxx (PR #208390)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 9 01:17:03 PDT 2026
https://github.com/huihui15537226823 updated https://github.com/llvm/llvm-project/pull/208390
>From 70e8ac839667f8aba4aa74a2dd19614426f9754f Mon Sep 17 00:00:00 2001
From: hu1hu1 <fanyaohui at huawei.com>
Date: Wed, 24 Jun 2026 09:47:00 +0800
Subject: [PATCH 1/6] Add OHOS HDC runtimes CI support
---
cmake/Modules/GetToolchainDirs.cmake | 37 +-
.../cmake/Modules/CompilerRTUtils.cmake | 8 +-
compiler-rt/cmake/builtin-config-ix.cmake | 2 +-
compiler-rt/cmake/crt-config-ix.cmake | 2 +-
compiler-rt/lib/builtins/crtbegin.c | 9 +
compiler-rt/lib/builtins/emutls.c | 8 +-
libcxx/CMakeLists.txt | 10 +-
libcxx/cmake/config-ix.cmake | 2 +
libcxx/include/__config | 5 +-
libcxx/include/__cxx03/__config | 5 +-
.../__cxx03/__locale_dir/locale_base_api.h | 2 +-
libcxx/include/__locale_dir/locale_base_api.h | 2 +-
libcxx/src/include/config_elast.h | 2 +
libcxx/test/configs/llvm-libc++-ohos.cfg.in | 48 ++
libcxx/utils/ci/buildkite-pipeline.yml | 27 +
libcxx/utils/ci/run-buildbot | 87 ++++
libcxx/utils/ci/vendor/ohos/hdc_run.py | 472 ++++++++++++++++++
libcxx/utils/ci/vendor/ohos/hdc_run_test.py | 115 +++++
libcxxabi/CMakeLists.txt | 7 +-
.../test/configs/llvm-libc++abi-ohos.cfg.in | 30 ++
libunwind/CMakeLists.txt | 7 +-
.../test/configs/llvm-libunwind-ohos.cfg.in | 55 ++
22 files changed, 910 insertions(+), 32 deletions(-)
create mode 100644 libcxx/test/configs/llvm-libc++-ohos.cfg.in
create mode 100755 libcxx/utils/ci/vendor/ohos/hdc_run.py
create mode 100644 libcxx/utils/ci/vendor/ohos/hdc_run_test.py
create mode 100644 libcxxabi/test/configs/llvm-libc++abi-ohos.cfg.in
create mode 100644 libunwind/test/configs/llvm-libunwind-ohos.cfg.in
diff --git a/cmake/Modules/GetToolchainDirs.cmake b/cmake/Modules/GetToolchainDirs.cmake
index 7568734e3f25d..1e8a3e4e015ca 100644
--- a/cmake/Modules/GetToolchainDirs.cmake
+++ b/cmake/Modules/GetToolchainDirs.cmake
@@ -79,7 +79,15 @@ function(get_runtimes_target_libdir_common default_target_triple arch variable)
string(FIND "${default_target_triple}" "-" dash_index)
string(SUBSTRING "${default_target_triple}" "${dash_index}" -1 triple_suffix)
string(SUBSTRING "${default_target_triple}" 0 "${dash_index}" triple_cpu)
- if(ANDROID AND "${arch}" STREQUAL "i386")
+ if("${triple_suffix}" MATCHES "linux-ohos")
+ if("${arch}" STREQUAL "i386")
+ set(target "i686-linux-ohos")
+ elseif("${arch}" MATCHES "^arm")
+ set(target "arm-linux-ohos")
+ else()
+ set(target "${arch}-linux-ohos")
+ endif()
+ elseif(ANDROID AND "${arch}" STREQUAL "i386")
set(target "i686${triple_suffix}")
elseif("${arch}" STREQUAL "amd64")
set(target "x86_64${triple_suffix}")
@@ -125,25 +133,26 @@ function(get_runtimes_target_libdir_common default_target_triple arch variable)
set("${variable}" "${target}" PARENT_SCOPE)
endfunction()
-
-# Corresponds to Clang's ToolChain::getRuntimePath().
-function (get_toolchain_target_dirname outvar)
- string(FIND "${LLVM_TARGET_TRIPLE}" "-" dash_index)
+function(get_runtimes_target_dirname default_target_triple variable)
+ string(FIND "${default_target_triple}" "-" dash_index)
if (dash_index EQUAL "-1")
- # This means LLVM_TARGET_TRIPLE is not set and we cannot derive the dirname
- # from it. The proper behavior here would be to emit an error since we have
- # no target we can build for. However, compiler-rt uses
- # COMPILER_RT_DEFAULT_TARGET_TRIPLE instead and ignores LLVM_TARGET_TRIPLE.
- # To not break the build when building only compiler-rt, we skip the triple
- # subdirectory.
set(target "")
else ()
- string(SUBSTRING "${LLVM_TARGET_TRIPLE}" 0 "${dash_index}" triple_cpu)
+ string(SUBSTRING "${default_target_triple}" 0 "${dash_index}" triple_cpu)
set(arch "${triple_cpu}")
if("${arch}" MATCHES "^i.86$")
set(arch "i386")
endif()
- get_runtimes_target_libdir_common("${LLVM_TARGET_TRIPLE}" "${arch}" target)
- endif ()
+ get_runtimes_target_libdir_common("${default_target_triple}" "${arch}" target)
+ endif()
+ set("${variable}" "${target}" PARENT_SCOPE)
+endfunction()
+
+
+# Corresponds to Clang's ToolChain::getRuntimePath().
+function (get_toolchain_target_dirname outvar)
+ # If LLVM_TARGET_TRIPLE is unset, this intentionally returns an empty
+ # directory to preserve the historical compiler-rt-only behavior.
+ get_runtimes_target_dirname("${LLVM_TARGET_TRIPLE}" target)
set("${outvar}" "${target}" PARENT_SCOPE)
endfunction()
diff --git a/compiler-rt/cmake/Modules/CompilerRTUtils.cmake b/compiler-rt/cmake/Modules/CompilerRTUtils.cmake
index 75216ed704bce..af55b2166de60 100644
--- a/compiler-rt/cmake/Modules/CompilerRTUtils.cmake
+++ b/compiler-rt/cmake/Modules/CompilerRTUtils.cmake
@@ -491,8 +491,12 @@ endfunction()
function(get_compiler_rt_target arch variable)
if(COMPILER_RT_DEFAULT_TARGET_ONLY)
- # Use exact spelling when building only for the target specified to CMake.
- set(target "${COMPILER_RT_DEFAULT_TARGET_TRIPLE}")
+ if(CMAKE_SYSTEM_NAME STREQUAL "OHOS")
+ get_runtimes_target_libdir_common("${COMPILER_RT_DEFAULT_TARGET_TRIPLE}" "${arch}" target)
+ else()
+ # Use exact spelling when building only for the target specified to CMake.
+ set(target "${COMPILER_RT_DEFAULT_TARGET_TRIPLE}")
+ endif()
else()
get_runtimes_target_libdir_common("${COMPILER_RT_DEFAULT_TARGET_TRIPLE}" "${arch}" target)
endif()
diff --git a/compiler-rt/cmake/builtin-config-ix.cmake b/compiler-rt/cmake/builtin-config-ix.cmake
index 528268da729fb..90d9e451ff109 100644
--- a/compiler-rt/cmake/builtin-config-ix.cmake
+++ b/compiler-rt/cmake/builtin-config-ix.cmake
@@ -297,7 +297,7 @@ else()
endforeach()
endif()
-if(OS_NAME MATCHES "Linux|SerenityOS" AND NOT LLVM_USE_SANITIZER AND NOT
+if(OS_NAME MATCHES "Linux|SerenityOS|OHOS" AND NOT LLVM_USE_SANITIZER AND NOT
COMPILER_RT_GPU_BUILD)
set(COMPILER_RT_HAS_CRT TRUE)
else()
diff --git a/compiler-rt/cmake/crt-config-ix.cmake b/compiler-rt/cmake/crt-config-ix.cmake
index ebc7d671e74ee..64112f1636b09 100644
--- a/compiler-rt/cmake/crt-config-ix.cmake
+++ b/compiler-rt/cmake/crt-config-ix.cmake
@@ -47,7 +47,7 @@ if(NOT APPLE)
message(STATUS "Supported architectures for crt: ${CRT_SUPPORTED_ARCH}")
endif()
-if (CRT_SUPPORTED_ARCH AND OS_NAME MATCHES "Linux|SerenityOS" AND NOT LLVM_USE_SANITIZER)
+if (CRT_SUPPORTED_ARCH AND OS_NAME MATCHES "Linux|SerenityOS|OHOS" AND NOT LLVM_USE_SANITIZER)
set(COMPILER_RT_HAS_CRT TRUE)
else()
set(COMPILER_RT_HAS_CRT FALSE)
diff --git a/compiler-rt/lib/builtins/crtbegin.c b/compiler-rt/lib/builtins/crtbegin.c
index 74becdbe5dd0e..381a69fac4664 100644
--- a/compiler-rt/lib/builtins/crtbegin.c
+++ b/compiler-rt/lib/builtins/crtbegin.c
@@ -36,6 +36,10 @@ extern fp __CTOR_LIST_END__[];
extern void __cxa_finalize(void *) __attribute__((weak));
+#if defined(__OHOS__)
+extern void __at_fini() __attribute__((weak));
+#endif
+
static void __attribute__((used)) __do_init(void) {
static _Bool __initialized;
if (__builtin_expect(__initialized, 0))
@@ -114,6 +118,11 @@ static void __attribute__((used)) __do_fini(void) {
return;
__finalized = 1;
+#if defined(__OHOS__)
+ if (__at_fini)
+ __at_fini();
+#endif
+
if (__cxa_finalize)
__cxa_finalize(__dso_handle);
diff --git a/compiler-rt/lib/builtins/emutls.c b/compiler-rt/lib/builtins/emutls.c
index a8a5d7c0749a8..2d15d8e249f43 100644
--- a/compiler-rt/lib/builtins/emutls.c
+++ b/compiler-rt/lib/builtins/emutls.c
@@ -12,7 +12,7 @@
#include "int_lib.h"
-#ifdef __BIONIC__
+#if defined(__BIONIC__) || defined(__OHOS__)
// There are 4 pthread key cleanup rounds on Bionic. Delay emutls deallocation
// to round 2. We need to delay deallocation because:
// - Android versions older than M lack __cxa_thread_atexit_impl, so apps
@@ -51,7 +51,7 @@ static void emutls_shutdown(emutls_address_array *array);
static pthread_mutex_t emutls_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_key_t emutls_pthread_key;
-#ifdef __BIONIC__
+#if defined(__BIONIC__) || defined(__OHOS__)
static bool emutls_key_created = false;
#endif
@@ -401,8 +401,8 @@ void *__emutls_get_address(__emutls_control *control) {
return array->data[index];
}
-#ifdef __BIONIC__
-// Called by Bionic on dlclose to delete the emutls pthread key.
+#if defined(__BIONIC__) || defined(__OHOS__)
+// Called by Bionic/OHOS on dlclose to delete the emutls pthread key.
__attribute__((visibility("hidden"))) void __emutls_unregister_key(void) {
if (emutls_key_created) {
pthread_key_delete(emutls_pthread_key);
diff --git a/libcxx/CMakeLists.txt b/libcxx/CMakeLists.txt
index 845240d1b894c..9a1af0ced8965 100644
--- a/libcxx/CMakeLists.txt
+++ b/libcxx/CMakeLists.txt
@@ -277,7 +277,8 @@ option(LIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY
# or we don't have any ABI library.
if (LIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY
OR NOT LIBCXX_ENABLE_SHARED
- OR LIBCXX_CXX_ABI STREQUAL "none")
+ OR LIBCXX_CXX_ABI STREQUAL "none"
+ OR CMAKE_SYSTEM_NAME STREQUAL "OHOS")
set(ENABLE_LINKER_SCRIPT_DEFAULT_VALUE OFF)
elseif((UNIX OR FUCHSIA) AND NOT APPLE)
set(ENABLE_LINKER_SCRIPT_DEFAULT_VALUE ON)
@@ -450,7 +451,12 @@ set(LIBCXX_STATIC_OUTPUT_NAME "c++" CACHE STRING "Output name for the static lib
# TODO: Use common runtimes infrastructure for output and install paths
if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
- set(LIBCXX_TARGET_SUBDIR ${LLVM_DEFAULT_TARGET_TRIPLE})
+ if(CMAKE_SYSTEM_NAME STREQUAL "OHOS")
+ include(GetToolchainDirs)
+ get_runtimes_target_dirname("${LLVM_DEFAULT_TARGET_TRIPLE}" LIBCXX_TARGET_SUBDIR)
+ else()
+ set(LIBCXX_TARGET_SUBDIR ${LLVM_DEFAULT_TARGET_TRIPLE})
+ endif()
if(LIBCXX_LIBDIR_SUBDIR)
string(APPEND LIBCXX_TARGET_SUBDIR /${LIBCXX_LIBDIR_SUBDIR})
endif()
diff --git a/libcxx/cmake/config-ix.cmake b/libcxx/cmake/config-ix.cmake
index 270d80575adcf..e0e5a3c3094d2 100644
--- a/libcxx/cmake/config-ix.cmake
+++ b/libcxx/cmake/config-ix.cmake
@@ -126,6 +126,8 @@ elseif(PICOLIBC)
set(LIBCXX_HAS_PTHREAD_LIB NO)
set(LIBCXX_HAS_RT_LIB NO)
set(LIBCXX_HAS_ATOMIC_LIB NO)
+elseif(OHOS)
+ set(LIBCXX_HAS_ATOMIC_LIB NO)
else()
check_library_exists(pthread pthread_create "" LIBCXX_HAS_PTHREAD_LIB)
check_library_exists(rt clock_gettime "" LIBCXX_HAS_RT_LIB)
diff --git a/libcxx/include/__config b/libcxx/include/__config
index fdd0558fbec6f..c7da0ec54447c 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -292,7 +292,8 @@ typedef __char32_t char32_t;
defined(__APPLE__) || \
defined(__MVS__) || \
defined(_AIX) || \
- defined(__EMSCRIPTEN__)
+ defined(__EMSCRIPTEN__) || \
+ defined(__OHOS_FAMILY__)
// clang-format on
# undef _LIBCPP_HAS_THREAD_API_PTHREAD
# define _LIBCPP_HAS_THREAD_API_PTHREAD 1
@@ -371,7 +372,7 @@ typedef __char32_t char32_t;
# endif
# if defined(__BIONIC__) || defined(__NuttX__) || defined(__Fuchsia__) || defined(__wasi__) || \
- _LIBCPP_HAS_MUSL_LIBC || defined(__OpenBSD__) || _LIBCPP_LIBC_LLVM_LIBC
+ _LIBCPP_HAS_MUSL_LIBC || defined(__OpenBSD__) || _LIBCPP_LIBC_LLVM_LIBC || defined(__OHOS_FAMILY__)
# define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
# endif
diff --git a/libcxx/include/__cxx03/__config b/libcxx/include/__cxx03/__config
index 27c26084da4b1..d9078a4ddf0d0 100644
--- a/libcxx/include/__cxx03/__config
+++ b/libcxx/include/__cxx03/__config
@@ -680,7 +680,8 @@ typedef __char32_t char32_t;
defined(__APPLE__) || \
defined(__MVS__) || \
defined(_AIX) || \
- defined(__EMSCRIPTEN__)
+ defined(__EMSCRIPTEN__) || \
+ defined(__OHOS_FAMILY__)
// clang-format on
# define _LIBCPP_HAS_THREAD_API_PTHREAD
# elif defined(__Fuchsia__)
@@ -753,7 +754,7 @@ typedef __char32_t char32_t;
# endif
# if defined(__BIONIC__) || defined(__NuttX__) || defined(__Fuchsia__) || defined(__wasi__) || \
- defined(_LIBCPP_HAS_MUSL_LIBC) || defined(__OpenBSD__)
+ defined(_LIBCPP_HAS_MUSL_LIBC) || defined(__OpenBSD__) || defined(__OHOS_FAMILY__)
# define _LIBCPP_PROVIDES_DEFAULT_RUNE_TABLE
# endif
diff --git a/libcxx/include/__cxx03/__locale_dir/locale_base_api.h b/libcxx/include/__cxx03/__locale_dir/locale_base_api.h
index 3dbce825bc76c..a107aeeae5da4 100644
--- a/libcxx/include/__cxx03/__locale_dir/locale_base_api.h
+++ b/libcxx/include/__cxx03/__locale_dir/locale_base_api.h
@@ -23,7 +23,7 @@
# include <__cxx03/__locale_dir/locale_base_api/openbsd.h>
#elif defined(__Fuchsia__)
# include <__cxx03/__locale_dir/locale_base_api/fuchsia.h>
-#elif defined(__wasi__) || defined(_LIBCPP_HAS_MUSL_LIBC)
+#elif defined(__wasi__) || defined(_LIBCPP_HAS_MUSL_LIBC) || defined(__OHOS_FAMILY__)
# include <__cxx03/__locale_dir/locale_base_api/musl.h>
#elif defined(__APPLE__) || defined(__FreeBSD__)
# include <__cxx03/xlocale.h>
diff --git a/libcxx/include/__locale_dir/locale_base_api.h b/libcxx/include/__locale_dir/locale_base_api.h
index e1e60e18fd7c6..7dbbbd0b11654 100644
--- a/libcxx/include/__locale_dir/locale_base_api.h
+++ b/libcxx/include/__locale_dir/locale_base_api.h
@@ -120,7 +120,7 @@
# include <__locale_dir/support/fuchsia.h>
# elif _LIBCPP_LIBC_LLVM_LIBC
# include <__locale_dir/support/llvm_libc.h>
-# elif defined(__linux__)
+# elif defined(__linux__) || defined(__OHOS_FAMILY__)
# include <__locale_dir/support/linux.h>
# elif _LIBCPP_LIBC_NEWLIB
# include <__locale_dir/support/newlib.h>
diff --git a/libcxx/src/include/config_elast.h b/libcxx/src/include/config_elast.h
index daec2429de8eb..328a77d9934a5 100644
--- a/libcxx/src/include/config_elast.h
+++ b/libcxx/src/include/config_elast.h
@@ -43,6 +43,8 @@
# define _LIBCPP_ELAST (_sys_nerr - 1)
#elif defined(_AIX)
# define _LIBCPP_ELAST 127
+#elif defined(__OHOS_FAMILY__)
+// No _LIBCPP_ELAST needed on OHOS
#else
// Warn here so that the person doing the libcxx port has an easier time:
# warning ELAST for this platform not yet implemented
diff --git a/libcxx/test/configs/llvm-libc++-ohos.cfg.in b/libcxx/test/configs/llvm-libc++-ohos.cfg.in
new file mode 100644
index 0000000000000..a20ed9ce9c6a9
--- /dev/null
+++ b/libcxx/test/configs/llvm-libc++-ohos.cfg.in
@@ -0,0 +1,48 @@
+# This testing configuration handles running the test suite against LLVM's
+# libc++ using HDC on OHOS.
+
+lit_config.load_config(config, '@CMAKE_CURRENT_BINARY_DIR@/cmake-bridge.cfg')
+
+config.substitutions.append(('%{flags}',
+ ('--sysroot @CMAKE_SYSROOT@ ' if '@CMAKE_SYSROOT@' else '') + '-pthread'
+))
+config.substitutions.append(('%{compile_flags}',
+ '-nostdinc++ -I %{target-include-dir} -I %{include-dir} -I %{libcxx-dir}/test/support'
+))
+config.substitutions.append(('%{link_flags}',
+ # Link libc++abi/libunwind directly: lld won't resolve libc++'s transitive
+ # DT_NEEDED entries when building the test executable.
+ '-nostdlib++ -L %{lib-dir} -l at LIBCXX_SHARED_OUTPUT_NAME@ -lc++abi -lunwind'
+))
+config.substitutions.append(('%{exec}',
+ '%{executor} --execdir %{temp} -- '
+))
+
+import os, site
+site.addsitedir(os.path.join('@LIBCXX_SOURCE_DIR@', 'utils'))
+import libcxx.test.params, libcxx.test.config
+
+config.available_features.add('LIBCXX-OHOS-FIXME')
+config.available_features.add('ohos-hdc')
+
+libcxx.test.config.configure(
+ libcxx.test.params.DEFAULT_PARAMETERS,
+ libcxx.test.features.DEFAULT_FEATURES,
+ config,
+ lit_config
+)
+
+# The generic libc++ hardening-mode feature probe executes a target binary via
+# %{exec}. On OHOS/HDC that probe can fail for runner reasons even though the
+# configured libc++ headers still expose the selected hardening mode. Preserve
+# the configured mode so UNSUPPORTED/REQUIRES annotations remain stable.
+detected_hardening_features = [
+ feature for feature in config.available_features
+ if feature.startswith('libcpp-hardening-mode=')
+]
+configured_hardening_mode = '@LIBCXX_HARDENING_MODE@'
+if (
+ not detected_hardening_features and
+ configured_hardening_mode in ('none', 'fast', 'extensive', 'debug')
+):
+ config.available_features.add(f'libcpp-hardening-mode={configured_hardening_mode}')
diff --git a/libcxx/utils/ci/buildkite-pipeline.yml b/libcxx/utils/ci/buildkite-pipeline.yml
index d4107cf11ad51..77617f43ae6dc 100644
--- a/libcxx/utils/ci/buildkite-pipeline.yml
+++ b/libcxx/utils/ci/buildkite-pipeline.yml
@@ -172,3 +172,30 @@ steps:
queue: libcxx-builders
os: android
<<: *common
+
+- group: OHOS
+ steps:
+ - label: OHOS AArch64 HDC Smoke
+ command: libcxx/utils/ci/run-buildbot ohos-hdc-aarch64-smoke
+ env:
+ CC: clang
+ CXX: clang++
+ OHOS_TARGET_TRIPLE: aarch64-linux-ohos
+ HDC_TIMEOUT_SECONDS: 240
+ agents:
+ queue: libcxx-builders
+ os: linux
+ device: ohos-hdc
+ <<: *common
+ - label: OHOS AArch64 HDC Full
+ command: libcxx/utils/ci/run-buildbot ohos-hdc-aarch64-full
+ env:
+ CC: clang
+ CXX: clang++
+ OHOS_TARGET_TRIPLE: aarch64-linux-ohos
+ HDC_TIMEOUT_SECONDS: 240
+ agents:
+ queue: libcxx-builders
+ os: linux
+ device: ohos-hdc
+ <<: *common
diff --git a/libcxx/utils/ci/run-buildbot b/libcxx/utils/ci/run-buildbot
index 6376bc1d3dd5a..1867e9c620649 100755
--- a/libcxx/utils/ci/run-buildbot
+++ b/libcxx/utils/ci/run-buildbot
@@ -116,6 +116,41 @@ function clean() {
rm -rf "${BUILD_DIR}"
}
+function require-env-var() {
+ local name="${1}"
+ if [[ -z ${!name+x} ]] || [[ -z "${!name}" ]]; then
+ error "Environment variable ${name} must be defined"
+ exit 1
+ fi
+}
+
+function detect-lit() {
+ if [[ -x "${BUILD_DIR}/bin/llvm-lit" ]]; then
+ LIT_RUNNER=("${BUILD_DIR}/bin/llvm-lit")
+ elif command -v llvm-lit >/dev/null 2>&1; then
+ LIT_RUNNER=("$(command -v llvm-lit)")
+ else
+ LIT_RUNNER=(python3 "${MONOREPO_ROOT}/llvm/utils/lit/lit.py")
+ fi
+}
+
+function run-smoke-test() {
+ local test_dir="${1}"
+ local filter="${2}"
+ step "Running smoke test ${filter}"
+ "${LIT_RUNNER[@]}" -j1 -sv --show-xfail --show-unsupported --filter="${filter}" "${test_dir}"
+}
+
+function ohos-lit-args() {
+ local args="-j1 -sv --xunit-xml-output test-results.xml --time-tests"
+ if python3 -c 'import psutil' >/dev/null 2>&1; then
+ args="${args} --timeout=1500"
+ else
+ echo "warning: python3 psutil not available; running OHOS lit without per-test timeout" >&2
+ fi
+ printf '%s' "${args}"
+}
+
function generate-cmake-base() {
step "Generating CMake"
@@ -153,6 +188,37 @@ function generate-cmake-android() {
"${@}"
}
+function setup-ohos-hdc-env() {
+ require-env-var OHOS_SYSROOT
+
+ OHOS_TARGET_TRIPLE="${OHOS_TARGET_TRIPLE:=aarch64-linux-ohos}"
+ OHOS_EXECUTOR="${MONOREPO_ROOT}/libcxx/utils/ci/vendor/ohos/hdc_run.py"
+ OHOS_LIT_PARAMS="executor=${OHOS_EXECUTOR};target_triple=${OHOS_TARGET_TRIPLE}"
+}
+
+function generate-cmake-ohos-hdc() {
+ setup-ohos-hdc-env
+
+ local lit_args
+ lit_args="$(ohos-lit-args)"
+
+ generate-cmake \
+ -DLLVM_LIT_ARGS="${lit_args}" \
+ -DCMAKE_SYSTEM_NAME=OHOS \
+ -DCMAKE_SYSROOT="${OHOS_SYSROOT}" \
+ -DCMAKE_C_COMPILER_TARGET="${OHOS_TARGET_TRIPLE}" \
+ -DCMAKE_CXX_COMPILER_TARGET="${OHOS_TARGET_TRIPLE}" \
+ -DCMAKE_ASM_COMPILER_TARGET="${OHOS_TARGET_TRIPLE}" \
+ -DLIBCXX_INCLUDE_BENCHMARKS=OFF \
+ -DLIBCXX_TEST_CONFIG="llvm-libc++-ohos.cfg.in" \
+ -DLIBCXXABI_TEST_CONFIG="llvm-libc++abi-ohos.cfg.in" \
+ -DLIBUNWIND_TEST_CONFIG="llvm-libunwind-ohos.cfg.in" \
+ -DLIBCXX_TEST_PARAMS="${OHOS_LIT_PARAMS}" \
+ -DLIBCXXABI_TEST_PARAMS="${OHOS_LIT_PARAMS}" \
+ -DLIBUNWIND_TEST_PARAMS="${OHOS_LIT_PARAMS}" \
+ "${@}"
+}
+
function check-runtimes() {
step "Building libc++ test dependencies"
ninja -vC "${BUILD_DIR}" cxx-test-depends
@@ -795,6 +861,27 @@ android-ndk-*)
step "Running the libc++abi tests"
ninja -vC "${BUILD_DIR}" check-cxxabi
;;
+ohos-hdc-aarch64-full)
+ clean
+
+ generate-cmake-ohos-hdc
+
+ check-runtimes
+;;
+ohos-hdc-aarch64-smoke)
+ clean
+
+ generate-cmake-ohos-hdc
+
+ step "Building the OHOS smoke test dependencies"
+ ninja -vC "${BUILD_DIR}" cxx-test-depends cxxabi-test-depends unwind-test-depends
+
+ detect-lit
+ run-smoke-test "${BUILD_DIR}/libcxxabi/test" 'thread_local_destruction_order.pass.cpp'
+ run-smoke-test "${BUILD_DIR}/libunwind/test" 'bad_unwind_info.pass.cpp'
+ run-smoke-test "${BUILD_DIR}/libunwind/test" 'signal_unwind.pass.cpp'
+ run-smoke-test "${BUILD_DIR}/libcxx/test" 'clocale.pass.cpp'
+;;
#################################################################
# Insert vendor-specific internal configurations below.
#
diff --git a/libcxx/utils/ci/vendor/ohos/hdc_run.py b/libcxx/utils/ci/vendor/ohos/hdc_run.py
new file mode 100755
index 0000000000000..61a3899b88b11
--- /dev/null
+++ b/libcxx/utils/ci/vendor/ohos/hdc_run.py
@@ -0,0 +1,472 @@
+#!/usr/bin/env python3
+# ===----------------------------------------------------------------------===##
+#
+# 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
+#
+# ===----------------------------------------------------------------------===##
+
+import argparse
+import os
+from pathlib import Path
+import re
+import shlex
+import shutil
+import subprocess
+import sys
+import uuid
+
+
+EXIT_MARKER = "__llvm_hdc_exit__="
+
+
+def _parse_kv(items):
+ result = {}
+ for item in items:
+ key, value = item.split("=", 1)
+ result[key] = value
+ return result
+
+
+def _split_path_list(value):
+ return [entry for entry in value.split(os.pathsep) if entry]
+
+
+def _resolve_hdc_binary(hdc):
+ if os.path.isabs(hdc):
+ return hdc
+ resolved = shutil.which(hdc)
+ if resolved is None:
+ sys.exit(f"failed to find hdc binary: {hdc}")
+ return resolved
+
+
+def _is_windows_hdc(path):
+ return path.lower().endswith(".exe")
+
+
+def _find_windows_local_root(hdc_path):
+ parts = Path(hdc_path).parts
+ for index in range(len(parts) - 1):
+ if parts[index] == "AppData" and index + 1 < len(parts) and parts[index + 1] == "Local":
+ return Path(*parts[: index + 2])
+ return None
+
+
+def _default_host_staging_root(hdc_path):
+ if _is_windows_hdc(hdc_path):
+ local_root = _find_windows_local_root(hdc_path)
+ if local_root is None:
+ sys.exit(
+ "failed to derive a Windows staging directory from the hdc.exe path; "
+ "set HDC_HOST_STAGING_ROOT to a path under /mnt/<drive>/..."
+ )
+ return local_root / "Temp" / "llvm-lit-hdc"
+ return Path("/tmp/llvm-lit-hdc")
+
+
+def _to_windows_path(path):
+ resolved = Path(path).resolve()
+ parts = resolved.parts
+ if len(parts) < 4 or parts[1] != "mnt":
+ sys.exit(
+ f"Windows hdc requires a staging path under /mnt/<drive>/..., got: {resolved}"
+ )
+ drive = parts[2].upper()
+ tail = "\\".join(parts[3:])
+ return f"{drive}:\\{tail}" if tail else f"{drive}:\\"
+
+
+def _run_readelf(path):
+ completed = subprocess.run(
+ ["readelf", "-d", path],
+ check=False,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ text=True,
+ )
+ if completed.returncode != 0:
+ return ""
+ return completed.stdout
+
+
+def _read_elf_metadata(path):
+ needed = []
+ runpath_dirs = []
+ seen_dirs = set()
+ for line in _run_readelf(path).splitlines():
+ needed_match = re.search(r"\(NEEDED\).*Shared library: \[(.*)\]", line)
+ if needed_match:
+ needed.append(needed_match.group(1))
+ continue
+
+ runpath_match = re.search(
+ r"\((?:RUNPATH|RPATH)\).*Library runpath: \[(.*)\]", line
+ )
+ if not runpath_match:
+ continue
+ for entry in _split_path_list(runpath_match.group(1)):
+ candidate = Path(entry)
+ if not candidate.is_dir():
+ continue
+ key = str(candidate.resolve())
+ if key in seen_dirs:
+ continue
+ seen_dirs.add(key)
+ runpath_dirs.append(candidate)
+ return needed, runpath_dirs
+
+
+def _find_build_root(execdir):
+ current = Path(execdir).resolve()
+ for candidate in [current, *current.parents]:
+ if (candidate / "CMakeCache.txt").exists():
+ return candidate
+ return None
+
+
+def _collect_build_library_dirs(execdir):
+ build_root = _find_build_root(execdir)
+ if build_root is None:
+ return []
+
+ lib_root = build_root / "lib"
+ if not lib_root.is_dir():
+ return []
+
+ library_dirs = []
+ seen = set()
+ for lib in sorted(lib_root.rglob("*.so*")):
+ if not lib.is_file():
+ continue
+ parent = lib.parent.resolve()
+ key = str(parent)
+ if key in seen:
+ continue
+ seen.add(key)
+ library_dirs.append(parent)
+ return library_dirs
+
+
+def _find_dependency(name, search_dirs):
+ for directory in search_dirs:
+ candidate = Path(directory) / name
+ if candidate.is_file():
+ return candidate.resolve()
+ return None
+
+
+def _copy_needed_libraries(executables, execdir, staging_execdir):
+ search_dirs = _collect_build_library_dirs(execdir)
+ queue = [Path(exe).resolve() for exe in executables]
+ visited = set()
+ copied_names = {path.name for path in staging_execdir.glob("*") if path.is_file()}
+
+ while queue:
+ current = queue.pop(0)
+ current_key = str(current)
+ if current_key in visited:
+ continue
+ visited.add(current_key)
+
+ needed, runpath_dirs = _read_elf_metadata(current)
+ current_search_dirs = []
+ current_seen = set()
+ for directory in [*runpath_dirs, current.parent, *search_dirs]:
+ resolved = Path(directory).resolve()
+ key = str(resolved)
+ if key in current_seen:
+ continue
+ current_seen.add(key)
+ current_search_dirs.append(resolved)
+
+ for directory in runpath_dirs:
+ resolved = directory.resolve()
+ if all(str(resolved) != str(existing) for existing in search_dirs):
+ search_dirs.append(resolved)
+
+ for lib_name in needed:
+ dependency = _find_dependency(lib_name, current_search_dirs)
+ if dependency is None:
+ continue
+ if lib_name not in copied_names:
+ shutil.copy2(dependency, staging_execdir / lib_name)
+ copied_names.add(lib_name)
+ queue.append(dependency)
+
+
+def _copy_execdir(execdir, staging_execdir):
+ if staging_execdir.exists():
+ shutil.rmtree(staging_execdir)
+ shutil.copytree(execdir, staging_execdir)
+
+
+def _iter_files(root):
+ for directory, dirnames, filenames in os.walk(root):
+ dirnames.sort()
+ filenames.sort()
+ yield Path(directory), filenames
+
+
+def _is_test_executable(path):
+ return path.endswith(".tmp.exe") and os.path.exists(path)
+
+
+def _map_local_path(path, local_execdir, remote_execdir):
+ normalized = os.path.normpath(path)
+ execdir = os.path.normpath(local_execdir)
+ if normalized == execdir:
+ return remote_execdir
+ prefix = execdir + os.sep
+ if normalized.startswith(prefix):
+ suffix = normalized[len(prefix) :].replace(os.sep, "/")
+ return f"{remote_execdir}/{suffix}" if suffix else remote_execdir
+ return path
+
+
+def _map_value(value, local_execdir, remote_execdir):
+ return _map_local_path(value, local_execdir, remote_execdir)
+
+
+def _build_env_exports(env, prepend_env, local_execdir, remote_execdir, add_remote_libdir):
+ commands = []
+ mapped_env = {
+ key: _map_value(value, local_execdir, remote_execdir) for key, value in env.items()
+ }
+ mapped_prepend = {
+ key: _map_value(value, local_execdir, remote_execdir)
+ for key, value in prepend_env.items()
+ }
+
+ if add_remote_libdir:
+ existing = mapped_prepend.get("LD_LIBRARY_PATH")
+ mapped_prepend["LD_LIBRARY_PATH"] = (
+ f"{remote_execdir}:{existing}" if existing else remote_execdir
+ )
+
+ for key, value in mapped_env.items():
+ commands.append(f"export {key}={shlex.quote(value)}")
+ for key, value in mapped_prepend.items():
+ commands.append(f"export {key}={shlex.quote(value)}${{{key}:+:{key}}}")
+ return commands
+
+
+def _hdc_prefix(hdc_path, server, target):
+ prefix = [hdc_path]
+ if server:
+ prefix.extend(["-s", server])
+ if target:
+ prefix.extend(["-t", target])
+ return prefix
+
+
+def _run_hdc(
+ prefix,
+ args,
+ *,
+ timeout=None,
+ capture_output=False,
+ stdin=subprocess.DEVNULL,
+ check=True,
+ expect_stdout=None,
+):
+ kwargs = {
+ "check": False,
+ "timeout": timeout,
+ "stdin": stdin,
+ "text": True,
+ }
+ if capture_output:
+ kwargs["stdout"] = subprocess.PIPE
+ kwargs["stderr"] = subprocess.PIPE
+ completed = subprocess.run(prefix + args, **kwargs)
+ output = completed.stdout if capture_output and completed.stdout else ""
+ error_output = completed.stderr if capture_output and completed.stderr else ""
+ if check and completed.returncode != 0:
+ raise RuntimeError(
+ f"hdc command failed with exit code {completed.returncode}: "
+ f"{shlex.join(prefix + args)}\n{output}{error_output}"
+ )
+ if check and expect_stdout is not None and expect_stdout not in output:
+ raise RuntimeError(
+ f"hdc command did not report success: {shlex.join(prefix + args)}\n{output}"
+ )
+ return completed
+
+
+def _run_checked_shell(prefix, command, *, timeout=None):
+ completed = _run_hdc(
+ prefix,
+ [
+ "shell",
+ f"{command}; rc=$?; printf '\\n{EXIT_MARKER}%d\\n' \"$rc\"",
+ ],
+ timeout=timeout,
+ capture_output=True,
+ )
+ exit_code, output = _extract_exit_code(completed.stdout)
+ if exit_code is None:
+ raise RuntimeError(
+ f"failed to parse shell exit code for: {command}\n{completed.stdout}"
+ )
+ if exit_code != 0:
+ raise RuntimeError(
+ f"remote shell command failed with exit code {exit_code}: {command}\n{output}"
+ )
+ return output
+
+
+def _sync_tree_to_device(prefix, local_root, remote_root, use_windows_paths):
+ _run_checked_shell(prefix, f"rm -rf {shlex.quote(remote_root)}")
+ _run_checked_shell(prefix, f"mkdir -p {shlex.quote(remote_root)}")
+
+ for directory, filenames in _iter_files(local_root):
+ relative_dir = os.path.relpath(directory, local_root)
+ device_dir = (
+ remote_root
+ if relative_dir == "."
+ else f"{remote_root}/{relative_dir.replace(os.sep, '/')}"
+ )
+ _run_checked_shell(prefix, f"mkdir -p {shlex.quote(device_dir)}")
+ for name in filenames:
+ local_path = directory / name
+ device_path = f"{device_dir}/{name}"
+ source = _to_windows_path(local_path) if use_windows_paths else str(local_path)
+ _run_hdc(
+ prefix,
+ ["file", "send", source, device_path],
+ capture_output=True,
+ expect_stdout="FileTransfer finish",
+ )
+ if name.endswith(".tmp.exe") or os.access(local_path, os.X_OK):
+ _run_checked_shell(prefix, f"chmod +x {shlex.quote(device_path)}")
+
+
+def _build_remote_command(command, local_execdir, remote_execdir, exports):
+ mapped_command = [
+ _map_local_path(arg, local_execdir, remote_execdir) for arg in command
+ ]
+ pieces = [f"cd {shlex.quote(remote_execdir)}"]
+ pieces.extend(exports)
+ pieces.append(shlex.join(mapped_command))
+ pieces.append(f"rc=$?; printf '\\n{EXIT_MARKER}%d\\n' \"$rc\"")
+ return " && ".join(pieces[:-2]) + f"; {pieces[-2]}; {pieces[-1]}"
+
+
+def _extract_exit_code(output):
+ match = re.search(rf"^(.*)\n{EXIT_MARKER}(\d+)\s*$", output, re.DOTALL)
+ if not match:
+ return None, output
+ return int(match.group(2)), match.group(1)
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--hdc", default=os.environ.get("HDC", "hdc"))
+ parser.add_argument("--hdc-server", default=os.environ.get("HDC_SERVER_IP_PORT"))
+ parser.add_argument("--hdc-target", default=os.environ.get("HDC_UTID"))
+ parser.add_argument("--execdir", required=True)
+ parser.add_argument(
+ "--remote-base-dir",
+ default="/data/local/tmp/llvm-lit-hdc",
+ )
+ parser.add_argument(
+ "--host-staging-root",
+ default=os.environ.get("HDC_HOST_STAGING_ROOT"),
+ )
+ parser.add_argument(
+ "--timeout-seconds",
+ type=int,
+ default=int(os.environ.get("HDC_TIMEOUT_SECONDS", "120")),
+ )
+ parser.add_argument("--env", nargs="*", default=[])
+ parser.add_argument("--prepend_env", nargs="*", default=[])
+ parser.add_argument("--keep-remote-dir", action="store_true")
+ parser.add_argument("--keep-host-staging", action="store_true")
+ parser.add_argument("command", nargs=argparse.ONE_OR_MORE)
+ args = parser.parse_args()
+
+ hdc_path = _resolve_hdc_binary(args.hdc)
+ use_windows_paths = _is_windows_hdc(hdc_path)
+ host_staging_root = (
+ Path(args.host_staging_root)
+ if args.host_staging_root
+ else _default_host_staging_root(hdc_path)
+ )
+ prefix = _hdc_prefix(hdc_path, args.hdc_server, args.hdc_target)
+
+ execdir = Path(args.execdir).resolve()
+ run_id = uuid.uuid4().hex[:12]
+ staging_execdir = host_staging_root / f"run-{run_id}" / execdir.name
+ remote_execdir = f"{args.remote_base_dir}/run-{run_id}/{execdir.name}"
+
+ env = _parse_kv(args.env)
+ prepend_env = _parse_kv(args.prepend_env)
+
+ executables = [arg for arg in args.command if _is_test_executable(arg)]
+ host_staging_root.mkdir(parents=True, exist_ok=True)
+ _copy_execdir(execdir, staging_execdir)
+ _copy_needed_libraries(executables, execdir, staging_execdir)
+
+ add_remote_libdir = any(staging_execdir.glob("*.so*"))
+ exports = _build_env_exports(
+ env,
+ prepend_env,
+ str(execdir),
+ remote_execdir,
+ add_remote_libdir,
+ )
+
+ try:
+ _sync_tree_to_device(prefix, staging_execdir, remote_execdir, use_windows_paths)
+ remote_command = _build_remote_command(
+ args.command,
+ str(execdir),
+ remote_execdir,
+ exports,
+ )
+ try:
+ completed = _run_hdc(
+ prefix,
+ ["shell", remote_command],
+ timeout=args.timeout_seconds,
+ capture_output=True,
+ stdin=None,
+ )
+ except subprocess.TimeoutExpired:
+ print(
+ f"hdc executor timed out after {args.timeout_seconds}s: {' '.join(args.command)}",
+ file=sys.stderr,
+ )
+ return 124
+
+ exit_code, output = _extract_exit_code(completed.stdout)
+ if exit_code is None:
+ print(
+ "failed to parse exit code from hdc shell output",
+ file=sys.stderr,
+ )
+ if completed.stdout:
+ print(completed.stdout, end="", file=sys.stderr)
+ if completed.stderr:
+ print(completed.stderr, end="", file=sys.stderr)
+ return 1
+
+ if output:
+ sys.stdout.write(output)
+ if completed.stderr:
+ sys.stderr.write(completed.stderr)
+ return exit_code
+ finally:
+ if not args.keep_remote_dir:
+ try:
+ _run_checked_shell(prefix, f"rm -rf {shlex.quote(remote_execdir)}")
+ except Exception:
+ pass
+ if not args.keep_host_staging:
+ shutil.rmtree(staging_execdir.parent, ignore_errors=True)
+
+
+if __name__ == "__main__":
+ raise SystemExit(main())
diff --git a/libcxx/utils/ci/vendor/ohos/hdc_run_test.py b/libcxx/utils/ci/vendor/ohos/hdc_run_test.py
new file mode 100644
index 0000000000000..17e2f65bd1fb6
--- /dev/null
+++ b/libcxx/utils/ci/vendor/ohos/hdc_run_test.py
@@ -0,0 +1,115 @@
+#!/usr/bin/env python3
+# ===----------------------------------------------------------------------===##
+#
+# 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
+#
+# ===----------------------------------------------------------------------===##
+
+import os
+from pathlib import Path
+import stat
+import subprocess
+import sys
+import tempfile
+import textwrap
+import unittest
+
+
+SCRIPT_DIR = Path(__file__).resolve().parent
+HDC_RUN = SCRIPT_DIR / "hdc_run.py"
+
+
+class HdcRunTest(unittest.TestCase):
+ def make_fake_hdc(self, directory):
+ fake_hdc = directory / "hdc"
+ fake_hdc.write_text(
+ textwrap.dedent(
+ """\
+ #!/usr/bin/env python3
+ import sys
+
+ EXIT_MARKER = "__llvm_hdc_exit__="
+
+ def main():
+ args = sys.argv[1:]
+ if args[:2] == ["file", "send"]:
+ print("FileTransfer finish")
+ return 0
+
+ if args and args[0] == "shell":
+ command = args[1]
+ if "stderr.tmp.exe" in command:
+ sys.stdout.write("STDOUT-OUTPUT")
+ sys.stderr.write("STDERR-OUTPUT")
+ sys.stdout.write(f"\\n{EXIT_MARKER}0\\n")
+ return 0
+ if "stdin.tmp.exe" in command:
+ sys.stdout.write("IN:" + sys.stdin.read())
+ sys.stdout.write(f"\\n{EXIT_MARKER}0\\n")
+ return 0
+ sys.stdout.write(f"\\n{EXIT_MARKER}0\\n")
+ return 0
+
+ print("unexpected fake hdc invocation: " + repr(args), file=sys.stderr)
+ return 2
+
+ if __name__ == "__main__":
+ raise SystemExit(main())
+ """
+ )
+ )
+ fake_hdc.chmod(fake_hdc.stat().st_mode | stat.S_IXUSR)
+ return fake_hdc
+
+ def run_hdc_run(self, temp_dir, executable_name, *, stdin_text=None):
+ execdir = temp_dir / "execdir"
+ execdir.mkdir()
+ executable = execdir / executable_name
+ executable.write_text("# fake executable marker\n")
+ executable.chmod(executable.stat().st_mode | stat.S_IXUSR)
+
+ fake_hdc = self.make_fake_hdc(temp_dir)
+ return subprocess.run(
+ [
+ sys.executable,
+ str(HDC_RUN),
+ "--hdc",
+ str(fake_hdc),
+ "--execdir",
+ str(execdir),
+ "--host-staging-root",
+ str(temp_dir / "staging"),
+ str(executable),
+ ],
+ input=stdin_text,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ text=True,
+ check=False,
+ )
+
+ def test_preserves_remote_stdout_and_stderr_separately(self):
+ with tempfile.TemporaryDirectory() as temp:
+ completed = self.run_hdc_run(Path(temp), "stderr.tmp.exe")
+
+ self.assertEqual(completed.returncode, 0)
+ self.assertEqual(completed.stdout, "STDOUT-OUTPUT")
+ self.assertEqual(completed.stderr, "STDERR-OUTPUT")
+
+ def test_forwards_stdin_to_remote_command(self):
+ with tempfile.TemporaryDirectory() as temp:
+ completed = self.run_hdc_run(
+ Path(temp),
+ "stdin.tmp.exe",
+ stdin_text="hello from stdin",
+ )
+
+ self.assertEqual(completed.returncode, 0)
+ self.assertEqual(completed.stdout, "IN:hello from stdin")
+ self.assertEqual(completed.stderr, "")
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/libcxxabi/CMakeLists.txt b/libcxxabi/CMakeLists.txt
index e1a1587fb6283..cb22e6fe65108 100644
--- a/libcxxabi/CMakeLists.txt
+++ b/libcxxabi/CMakeLists.txt
@@ -187,7 +187,12 @@ set(LIBCXXABI_INSTALL_RUNTIME_DIR "${CMAKE_INSTALL_BINDIR}" CACHE STRING
# TODO: Use common runtimes infrastructure for output and install paths
if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
- set(LIBCXXABI_TARGET_SUBDIR ${LLVM_DEFAULT_TARGET_TRIPLE})
+ if(CMAKE_SYSTEM_NAME STREQUAL "OHOS")
+ include(GetToolchainDirs)
+ get_runtimes_target_dirname("${LLVM_DEFAULT_TARGET_TRIPLE}" LIBCXXABI_TARGET_SUBDIR)
+ else()
+ set(LIBCXXABI_TARGET_SUBDIR ${LLVM_DEFAULT_TARGET_TRIPLE})
+ endif()
if(LIBCXXABI_LIBDIR_SUBDIR)
string(APPEND LIBCXXABI_TARGET_SUBDIR /${LIBCXXABI_LIBDIR_SUBDIR})
endif()
diff --git a/libcxxabi/test/configs/llvm-libc++abi-ohos.cfg.in b/libcxxabi/test/configs/llvm-libc++abi-ohos.cfg.in
new file mode 100644
index 0000000000000..d18748fe3a3cc
--- /dev/null
+++ b/libcxxabi/test/configs/llvm-libc++abi-ohos.cfg.in
@@ -0,0 +1,30 @@
+# This testing configuration handles running the test suite against LLVM's
+# libc++abi using HDC on OHOS.
+
+lit_config.load_config(config, '@CMAKE_CURRENT_BINARY_DIR@/cmake-bridge.cfg')
+
+config.substitutions.append(('%{flags}',
+ '--sysroot @CMAKE_SYSROOT@' if '@CMAKE_SYSROOT@' else ''
+))
+config.substitutions.append(('%{compile_flags}',
+ '-nostdinc++ -I %{include} -I %{cxx-include} -I %{cxx-target-include} %{maybe-include-libunwind} -I %{libcxx}/test/support -I %{libcxx}/src -D_LIBCPP_ENABLE_CXX17_REMOVED_UNEXPECTED_FUNCTIONS'
+))
+config.substitutions.append(('%{link_flags}',
+ '-nostdlib++ -L %{lib} -lc++ -lc++abi -pthread'
+))
+config.substitutions.append(('%{exec}',
+ '%{executor} --execdir %{temp} -- '
+))
+
+import os, site
+site.addsitedir(os.path.join('@LIBCXXABI_LIBCXX_PATH@', 'utils'))
+import libcxx.test.params, libcxx.test.config
+
+config.available_features.add('ohos-hdc')
+
+libcxx.test.config.configure(
+ libcxx.test.params.DEFAULT_PARAMETERS,
+ libcxx.test.features.DEFAULT_FEATURES,
+ config,
+ lit_config
+)
diff --git a/libunwind/CMakeLists.txt b/libunwind/CMakeLists.txt
index 02132f6c07fcd..4fd11bf5aca2f 100644
--- a/libunwind/CMakeLists.txt
+++ b/libunwind/CMakeLists.txt
@@ -142,7 +142,12 @@ set(LIBUNWIND_STATIC_OUTPUT_NAME "unwind" CACHE STRING "Output name for the stat
# TODO: Use common runtimes infrastructure for output and install paths
if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
- set(LIBUNWIND_TARGET_SUBDIR ${LLVM_DEFAULT_TARGET_TRIPLE})
+ if(CMAKE_SYSTEM_NAME STREQUAL "OHOS")
+ include(GetToolchainDirs)
+ get_runtimes_target_dirname("${LLVM_DEFAULT_TARGET_TRIPLE}" LIBUNWIND_TARGET_SUBDIR)
+ else()
+ set(LIBUNWIND_TARGET_SUBDIR ${LLVM_DEFAULT_TARGET_TRIPLE})
+ endif()
if(LIBUNWIND_LIBDIR_SUBDIR)
string(APPEND LIBUNWIND_TARGET_SUBDIR /${LIBUNWIND_LIBDIR_SUBDIR})
endif()
diff --git a/libunwind/test/configs/llvm-libunwind-ohos.cfg.in b/libunwind/test/configs/llvm-libunwind-ohos.cfg.in
new file mode 100644
index 0000000000000..bce241a7898cf
--- /dev/null
+++ b/libunwind/test/configs/llvm-libunwind-ohos.cfg.in
@@ -0,0 +1,55 @@
+#
+# Configuration file for running the libunwind tests against the shared library
+# using HDC on OHOS.
+#
+
+lit_config.load_config(config, '@CMAKE_CURRENT_BINARY_DIR@/cmake-bridge.cfg')
+
+compile_flags = []
+link_flags = []
+
+if @HAVE_GETAUXVAL@:
+ compile_flags.append('-D_LIBUNWIND_HAVE_GETAUXVAL')
+
+if @HAVE_ELF_AUX_INFO@:
+ compile_flags.append('-D_LIBUNWIND_HAVE_ELF_AUX_INFO')
+
+if @LIBUNWIND_ENABLE_CET@:
+ compile_flags.append('-fcf-protection=full')
+
+if @LIBUNWIND_ENABLE_GCS@:
+ compile_flags.append('-mbranch-protection=standard')
+
+if len('@CMAKE_EXE_EXPORTS_CXX_FLAG@'):
+ link_flags.append('@CMAKE_EXE_EXPORTS_CXX_FLAG@')
+
+if '@CMAKE_DL_LIBS@':
+ link_flags.append('-l at CMAKE_DL_LIBS@')
+
+compile_flags.append('-funwind-tables')
+
+config.substitutions.append(('%{flags}',
+ '--sysroot @CMAKE_SYSROOT@' if '@CMAKE_SYSROOT@' else ''
+))
+config.substitutions.append(('%{compile_flags}',
+ '-nostdinc++ -I %{{include}} {}'.format(' '.join(compile_flags))
+))
+config.substitutions.append(('%{link_flags}',
+ '-L %{{lib}} -lunwind {}'.format(' '.join(link_flags))
+))
+config.substitutions.append(('%{exec}',
+ '%{executor} --execdir %{temp} -- '
+))
+
+import os, site
+site.addsitedir(os.path.join('@LIBUNWIND_LIBCXX_PATH@', 'utils'))
+import libcxx.test.params, libcxx.test.config
+
+config.available_features.add('ohos-hdc')
+
+libcxx.test.config.configure(
+ libcxx.test.params.DEFAULT_PARAMETERS,
+ libcxx.test.features.DEFAULT_FEATURES,
+ config,
+ lit_config
+)
>From e9e5d2e517fb072f3554798e49b7119ec739105f Mon Sep 17 00:00:00 2001
From: hu1hu1 <fanyaohui at huawei.com>
Date: Thu, 25 Jun 2026 11:30:38 +0800
Subject: [PATCH 2/6] Fix OHOS libc++ CI ABI and SME detection
---
libcxx/utils/ci/run-buildbot | 2 ++
libunwind/src/Registers.hpp | 15 +++++++++------
2 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/libcxx/utils/ci/run-buildbot b/libcxx/utils/ci/run-buildbot
index 1867e9c620649..ecf0ca17ae148 100755
--- a/libcxx/utils/ci/run-buildbot
+++ b/libcxx/utils/ci/run-buildbot
@@ -192,6 +192,7 @@ function setup-ohos-hdc-env() {
require-env-var OHOS_SYSROOT
OHOS_TARGET_TRIPLE="${OHOS_TARGET_TRIPLE:=aarch64-linux-ohos}"
+ OHOS_LIBCXX_ABI_NAMESPACE="${OHOS_LIBCXX_ABI_NAMESPACE:=__h}"
OHOS_EXECUTOR="${MONOREPO_ROOT}/libcxx/utils/ci/vendor/ohos/hdc_run.py"
OHOS_LIT_PARAMS="executor=${OHOS_EXECUTOR};target_triple=${OHOS_TARGET_TRIPLE}"
}
@@ -209,6 +210,7 @@ function generate-cmake-ohos-hdc() {
-DCMAKE_C_COMPILER_TARGET="${OHOS_TARGET_TRIPLE}" \
-DCMAKE_CXX_COMPILER_TARGET="${OHOS_TARGET_TRIPLE}" \
-DCMAKE_ASM_COMPILER_TARGET="${OHOS_TARGET_TRIPLE}" \
+ -DLIBCXX_ABI_NAMESPACE="${OHOS_LIBCXX_ABI_NAMESPACE}" \
-DLIBCXX_INCLUDE_BENCHMARKS=OFF \
-DLIBCXX_TEST_CONFIG="llvm-libc++-ohos.cfg.in" \
-DLIBCXXABI_TEST_CONFIG="llvm-libc++abi-ohos.cfg.in" \
diff --git a/libunwind/src/Registers.hpp b/libunwind/src/Registers.hpp
index c88422a6d5f4f..18cb2a523bd0e 100644
--- a/libunwind/src/Registers.hpp
+++ b/libunwind/src/Registers.hpp
@@ -25,6 +25,11 @@
#endif
#if defined(_LIBUNWIND_HAVE_GETAUXVAL) || defined(_LIBUNWIND_HAVE_ELF_AUX_INFO)
#include <sys/auxv.h>
+#if defined(__has_include)
+#if __has_include(<asm/hwcap.h>)
+#include <asm/hwcap.h>
+#endif
+#endif
#endif
namespace libunwind {
@@ -1951,18 +1956,16 @@ class _LIBUNWIND_HIDDEN Registers_arm64 {
return false;
return has_sme != 0;
}
-#elif defined(_LIBUNWIND_HAVE_GETAUXVAL)
+#elif defined(_LIBUNWIND_HAVE_GETAUXVAL) && defined(HWCAP2_SME)
static bool checkHasSME() {
- constexpr int hwcap2_sme = (1 << 23);
unsigned long hwcap2 = getauxval(AT_HWCAP2);
- return (hwcap2 & hwcap2_sme) != 0;
+ return (hwcap2 & HWCAP2_SME) != 0;
}
-#elif defined(_LIBUNWIND_HAVE_ELF_AUX_INFO)
+#elif defined(_LIBUNWIND_HAVE_ELF_AUX_INFO) && defined(HWCAP2_SME)
static bool checkHasSME() {
- constexpr int hwcap2_sme = (1 << 23);
unsigned long hwcap2 = 0;
elf_aux_info(AT_HWCAP2, &hwcap2, sizeof(hwcap2));
- return (hwcap2 & hwcap2_sme) != 0;
+ return (hwcap2 & HWCAP2_SME) != 0;
}
#else
static bool checkHasSME() {
>From 498fa8d127ff49c27d4230996338c6eb5d747fe6 Mon Sep 17 00:00:00 2001
From: hu1hu1 <fanyaohui at huawei.com>
Date: Wed, 1 Jul 2026 15:49:11 +0800
Subject: [PATCH 3/6] Stabilize OHOS HDC runtimes tests
Add OHOS lit features for HDC executor and platform limitations, mark affected libc++ tests as unsupported or expected failures, and adjust test support for OHOS filesystem cleanup and allocation counting behavior.
Also guard the aarch64 ZA unwind test on HWCAP2_SME so devices without a reliable SME feature definition do not execute SME instructions.
---
libcxx/test/configs/llvm-libc++-ohos.cfg.in | 9 +++++-
.../clang/clang_modules_include.gen.py | 3 ++
.../locale.facet/no_allocation.pass.cpp | 1 +
libcxx/test/selftest/dsl/dsl.sh.py | 5 ++++
libcxx/test/selftest/stdin-is-piped.sh.cpp | 1 +
.../directory_entry.cons/path.pass.cpp | 1 +
.../directory_entry.mods/assign.pass.cpp | 1 +
.../directory_entry.mods/refresh.pass.cpp | 1 +
.../replace_filename.pass.cpp | 1 +
.../directory_entry.obs/file_size.pass.cpp | 1 +
.../file_type_obs.pass.cpp | 1 +
.../hard_link_count.pass.cpp | 1 +
.../last_write_time.pass.cpp | 1 +
.../directory_iterator.members/ctor.pass.cpp | 1 +
.../path.member/path.assign/move.pass.cpp | 2 +-
.../path.member/path.construct/move.pass.cpp | 2 +-
.../rec.dir.itr.members/ctor.pass.cpp | 1 +
.../rec.dir.itr.members/increment.pass.cpp | 1 +
.../fs.op.funcs/fs.op.exists/exists.pass.cpp | 1 +
.../is_block_file.pass.cpp | 1 +
.../is_character_file.pass.cpp | 1 +
.../fs.op.is_directory/is_directory.pass.cpp | 1 +
.../fs.op.is_empty/is_empty.pass.cpp | 1 +
.../fs.op.is_fifo/is_fifo.pass.cpp | 1 +
.../fs.op.is_other/is_other.pass.cpp | 1 +
.../is_regular_file.pass.cpp | 1 +
.../fs.op.is_socket/is_socket.pass.cpp | 1 +
.../fs.op.is_symlink/is_symlink.pass.cpp | 1 +
.../last_write_time.pass.cpp | 1 +
.../fs.op.funcs/fs.op.remove/remove.pass.cpp | 1 +
.../fs.op.remove_all/remove_all.pass.cpp | 1 +
.../fs.op.funcs/fs.op.status/status.pass.cpp | 1 +
.../symlink_status.pass.cpp | 1 +
.../temp_directory_path.pass.cpp | 1 +
.../ext.manip/get_money.pass.cpp | 1 +
.../ext.manip/put_money.pass.cpp | 1 +
.../locale-specific_form.pass.cpp | 1 +
.../print.fun/no_file_description.pass.cpp | 3 ++
.../std.manip/setfill_wchar_max.pass.cpp | 1 +
.../narrow.stream.objects/cerr.sh.cpp | 1 +
.../narrow.stream.objects/cin.sh.cpp | 1 +
.../narrow.stream.objects/clog.sh.cpp | 1 +
.../wide.stream.objects/wcerr-imbue.sh.cpp | 1 +
.../wide.stream.objects/wcerr.sh.cpp | 1 +
.../wide.stream.objects/wcin-imbue.sh.cpp | 1 +
.../wide.stream.objects/wcin.sh.cpp | 1 +
.../wide.stream.objects/wclog.sh.cpp | 1 +
.../sized_delete_array.pass.cpp | 1 +
..._array_calls_unsized_delete_array.pass.cpp | 1 +
.../new.delete.single/sized_delete.pass.cpp | 1 +
...sized_delete_calls_unsized_delete.pass.cpp | 1 +
.../locale.collate.byname/compare.pass.cpp | 1 +
.../locale.collate.byname/transform.pass.cpp | 1 +
.../facet.ctype.char.dtor/dtor.pass.cpp | 1 +
.../locale.ctype.byname/is_1.pass.cpp | 1 +
.../locale.ctype.byname/is_many.pass.cpp | 1 +
.../locale.ctype.byname/scan_is.pass.cpp | 1 +
.../locale.ctype.byname/scan_not.pass.cpp | 1 +
.../locale.ctype.byname/tolower_1.pass.cpp | 1 +
.../locale.ctype.byname/tolower_many.pass.cpp | 1 +
.../locale.ctype.byname/toupper_1.pass.cpp | 1 +
.../locale.ctype.byname/toupper_many.pass.cpp | 1 +
.../locale.ctype.byname/widen_1.pass.cpp | 1 +
.../locale.ctype.byname/widen_many.pass.cpp | 1 +
.../get_long_double_en_US.pass.cpp | 1 +
.../get_long_double_zh_CN.pass.cpp | 1 +
.../get_string_en_US.pass.cpp | 1 +
.../put_long_double_en_US.pass.cpp | 1 +
.../put_long_double_zh_CN.pass.cpp | 1 +
.../put_string_en_US.pass.cpp | 1 +
.../locale/locale.cons/default.pass.cpp | 1 +
.../test/std/re/re.traits/transform.pass.cpp | 1 +
.../re/re.traits/transform_primary.pass.cpp | 1 +
.../thread_create_failure.pass.cpp | 1 +
.../thread.jthread/join.deadlock.pass.cpp | 1 +
.../locale-specific_form.pass.cpp | 1 +
libcxx/test/support/count_new.h | 28 +++++++++++++++++++
libcxx/test/support/filesystem_test_helper.h | 4 ++-
libcxx/test/support/test_macros.h | 4 ++-
libunwind/test/aarch64_za_unwind.pass.cpp | 13 +++++----
80 files changed, 132 insertions(+), 11 deletions(-)
diff --git a/libcxx/test/configs/llvm-libc++-ohos.cfg.in b/libcxx/test/configs/llvm-libc++-ohos.cfg.in
index a20ed9ce9c6a9..542bc0cc83a1f 100644
--- a/libcxx/test/configs/llvm-libc++-ohos.cfg.in
+++ b/libcxx/test/configs/llvm-libc++-ohos.cfg.in
@@ -7,7 +7,8 @@ config.substitutions.append(('%{flags}',
('--sysroot @CMAKE_SYSROOT@ ' if '@CMAKE_SYSROOT@' else '') + '-pthread'
))
config.substitutions.append(('%{compile_flags}',
- '-nostdinc++ -I %{target-include-dir} -I %{include-dir} -I %{libcxx-dir}/test/support'
+ '-nostdinc++ -I %{target-include-dir} -I %{include-dir} -I %{libcxx-dir}/test/support '
+ '-DTEST_HAS_NO_RELIABLE_LIBRARY_INTERNAL_ALLOCATIONS'
))
config.substitutions.append(('%{link_flags}',
# Link libc++abi/libunwind directly: lld won't resolve libc++'s transitive
@@ -24,6 +25,12 @@ import libcxx.test.params, libcxx.test.config
config.available_features.add('LIBCXX-OHOS-FIXME')
config.available_features.add('ohos-hdc')
+config.available_features.add('executor-has-no-stdin')
+config.available_features.add('executor-merges-stderr-into-stdout')
+config.available_features.add('executor-runs-as-root')
+config.available_features.add('platform-has-nonportable-locales')
+config.available_features.add('platform-has-unreliable-new-delete-interposition')
+config.available_features.add('pthread-join-self-deadlocks')
libcxx.test.config.configure(
libcxx.test.params.DEFAULT_PARAMETERS,
diff --git a/libcxx/test/extensions/clang/clang_modules_include.gen.py b/libcxx/test/extensions/clang/clang_modules_include.gen.py
index ed058cd908511..88aa51c4dd080 100644
--- a/libcxx/test/extensions/clang/clang_modules_include.gen.py
+++ b/libcxx/test/extensions/clang/clang_modules_include.gen.py
@@ -24,6 +24,9 @@
# The Android headers don't appear to be compatible with modules yet
# UNSUPPORTED: LIBCXX-ANDROID-FIXME
+# The OHOS headers don't appear to be compatible with modules yet
+# UNSUPPORTED: LIBCXX-OHOS-FIXME
+
# TODO: Investigate this failure
# UNSUPPORTED: LIBCXX-FREEBSD-FIXME
diff --git a/libcxx/test/libcxx/localization/locales/locale/locale.types/locale.facet/no_allocation.pass.cpp b/libcxx/test/libcxx/localization/locales/locale/locale.types/locale.facet/no_allocation.pass.cpp
index 6e59b8256ffe7..a98402b5917b6 100644
--- a/libcxx/test/libcxx/localization/locales/locale/locale.types/locale.facet/no_allocation.pass.cpp
+++ b/libcxx/test/libcxx/localization/locales/locale/locale.types/locale.facet/no_allocation.pass.cpp
@@ -12,6 +12,7 @@
// for facets, as it uses __sso_allocator<facet*, N>. It would fail if new
// facets have been added (using install()) but N hasn't been adjusted to
// account for them.
+// UNSUPPORTED: platform-has-unreliable-new-delete-interposition
#include <cassert>
diff --git a/libcxx/test/selftest/dsl/dsl.sh.py b/libcxx/test/selftest/dsl/dsl.sh.py
index f93ccc747d661..fbbacb0c8d979 100644
--- a/libcxx/test/selftest/dsl/dsl.sh.py
+++ b/libcxx/test/selftest/dsl/dsl.sh.py
@@ -9,6 +9,11 @@
# With picolibc, test_program_stderr_is_not_conflated_with_stdout fails
# because stdout & stderr are treated as the same.
# XFAIL: LIBCXX-PICOLIBC-FIXME
+#
+# The OHOS HDC executor currently merges remote stderr into host stdout, and
+# OHOS locale probing accepts some intentionally bogus locale names.
+# UNSUPPORTED: executor-merges-stderr-into-stdout
+# UNSUPPORTED: platform-has-nonportable-locales
# Investigate why this is failing with LLVM libc.
# XFAIL: LLVM-LIBC-FIXME
diff --git a/libcxx/test/selftest/stdin-is-piped.sh.cpp b/libcxx/test/selftest/stdin-is-piped.sh.cpp
index ffd10631c6a67..1e1b8d1bd0317 100644
--- a/libcxx/test/selftest/stdin-is-piped.sh.cpp
+++ b/libcxx/test/selftest/stdin-is-piped.sh.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
// Make sure that the executor pipes standard input to the test-executable being run.
+// UNSUPPORTED: executor-has-no-stdin
// RUN: %{build}
// RUN: echo "abc" | %{exec} %t.exe
diff --git a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/path.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/path.pass.cpp
index a1a37012369d4..d1c2316dec112 100644
--- a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/path.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.cons/path.pass.cpp
@@ -8,6 +8,7 @@
// REQUIRES: can-create-symlinks
// UNSUPPORTED: c++03, c++11, c++14
+// UNSUPPORTED: executor-runs-as-root
// <filesystem>
diff --git a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.mods/assign.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.mods/assign.pass.cpp
index ba14af1240d4b..d4e23a9a3c6b6 100644
--- a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.mods/assign.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.mods/assign.pass.cpp
@@ -8,6 +8,7 @@
// REQUIRES: can-create-symlinks
// UNSUPPORTED: c++03, c++11, c++14
+// UNSUPPORTED: executor-runs-as-root
// <filesystem>
diff --git a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.mods/refresh.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.mods/refresh.pass.cpp
index 20a545b719ed6..f04a6bce76691 100644
--- a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.mods/refresh.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.mods/refresh.pass.cpp
@@ -8,6 +8,7 @@
// REQUIRES: can-create-symlinks
// UNSUPPORTED: c++03, c++11, c++14
+// UNSUPPORTED: executor-runs-as-root
// The string reported on errors changed, which makes those tests fail when run
// against a built library that doesn't contain 0aa637b2037d.
diff --git a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.mods/replace_filename.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.mods/replace_filename.pass.cpp
index 03e9de882ab0a..428d30804a4c3 100644
--- a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.mods/replace_filename.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.mods/replace_filename.pass.cpp
@@ -8,6 +8,7 @@
// REQUIRES: can-create-symlinks
// UNSUPPORTED: c++03, c++11, c++14
+// UNSUPPORTED: executor-runs-as-root
// <filesystem>
diff --git a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/file_size.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/file_size.pass.cpp
index 10829f8a73db1..c8a1c34aa3028 100644
--- a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/file_size.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/file_size.pass.cpp
@@ -8,6 +8,7 @@
// REQUIRES: can-create-symlinks
// UNSUPPORTED: c++03, c++11, c++14
+// UNSUPPORTED: executor-runs-as-root
// The string reported on errors changed, which makes those tests fail when run
// against a built library that doesn't contain 0aa637b2037d.
diff --git a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/file_type_obs.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/file_type_obs.pass.cpp
index 071ee7f6c891f..44b94528f5e32 100644
--- a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/file_type_obs.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/file_type_obs.pass.cpp
@@ -8,6 +8,7 @@
// REQUIRES: can-create-symlinks
// UNSUPPORTED: c++03, c++11, c++14
+// UNSUPPORTED: executor-runs-as-root
// Starting in Android N (API 24), SELinux policy prevents the shell user from
// creating a hard link.
diff --git a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/hard_link_count.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/hard_link_count.pass.cpp
index 5d931891dd0eb..d291ca2cb5641 100644
--- a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/hard_link_count.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/hard_link_count.pass.cpp
@@ -8,6 +8,7 @@
// REQUIRES: can-create-symlinks
// UNSUPPORTED: c++03, c++11, c++14
+// UNSUPPORTED: executor-runs-as-root
// The string reported on errors changed, which makes those tests fail when run
// against a built library that doesn't contain 0aa637b2037d.
diff --git a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/last_write_time.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/last_write_time.pass.cpp
index 82b94a3d6bf5f..e4bc9c41728da 100644
--- a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/last_write_time.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/last_write_time.pass.cpp
@@ -8,6 +8,7 @@
// REQUIRES: can-create-symlinks
// UNSUPPORTED: c++03, c++11, c++14
+// UNSUPPORTED: executor-runs-as-root
// The string reported on errors changed, which makes those tests fail when run
// against a built library that doesn't contain 0aa637b2037d.
diff --git a/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/ctor.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/ctor.pass.cpp
index 8401dbd38cd71..e0fa44ffbc4a5 100644
--- a/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/ctor.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/class.directory_iterator/directory_iterator.members/ctor.pass.cpp
@@ -9,6 +9,7 @@
// REQUIRES: can-create-symlinks
// UNSUPPORTED: c++03, c++11, c++14
// UNSUPPORTED: no-filesystem
+// UNSUPPORTED: executor-runs-as-root
// <filesystem>
diff --git a/libcxx/test/std/input.output/filesystems/class.path/path.member/path.assign/move.pass.cpp b/libcxx/test/std/input.output/filesystems/class.path/path.member/path.assign/move.pass.cpp
index ac5499cdd6f20..2bcc64a3c2651 100644
--- a/libcxx/test/std/input.output/filesystems/class.path/path.member/path.assign/move.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/class.path/path.member/path.assign/move.pass.cpp
@@ -26,7 +26,7 @@ namespace fs = std::filesystem;
int main(int, char**) {
using namespace fs;
static_assert(std::is_nothrow_move_assignable<path>::value, "");
- assert(globalMemCounter.checkOutstandingNewEq(0));
+ ASSERT_WITH_LIBRARY_INTERNAL_ALLOCATIONS(globalMemCounter.checkOutstandingNewEq(0));
const std::string s("we really really really really really really really "
"really really long string so that we allocate");
ASSERT_WITH_LIBRARY_INTERNAL_ALLOCATIONS(
diff --git a/libcxx/test/std/input.output/filesystems/class.path/path.member/path.construct/move.pass.cpp b/libcxx/test/std/input.output/filesystems/class.path/path.member/path.construct/move.pass.cpp
index 1f1843f7d401d..5efdf983f8a10 100644
--- a/libcxx/test/std/input.output/filesystems/class.path/path.member/path.construct/move.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/class.path/path.member/path.construct/move.pass.cpp
@@ -26,7 +26,7 @@ namespace fs = std::filesystem;
int main(int, char**) {
using namespace fs;
static_assert(std::is_nothrow_move_constructible<path>::value, "");
- assert(globalMemCounter.checkOutstandingNewEq(0));
+ ASSERT_WITH_LIBRARY_INTERNAL_ALLOCATIONS(globalMemCounter.checkOutstandingNewEq(0));
const std::string s("we really really really really really really really "
"really really long string so that we allocate");
ASSERT_WITH_LIBRARY_INTERNAL_ALLOCATIONS(
diff --git a/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/ctor.pass.cpp b/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/ctor.pass.cpp
index 08d7ff84378d5..a3768b8cbd83f 100644
--- a/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/ctor.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/ctor.pass.cpp
@@ -9,6 +9,7 @@
// REQUIRES: can-create-symlinks
// UNSUPPORTED: c++03, c++11, c++14
// UNSUPPORTED: no-filesystem
+// UNSUPPORTED: executor-runs-as-root
// <filesystem>
diff --git a/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/increment.pass.cpp b/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/increment.pass.cpp
index 1f2293989b7ef..9e8a70b4339d4 100644
--- a/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/increment.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/class.rec.dir.itr/rec.dir.itr.members/increment.pass.cpp
@@ -9,6 +9,7 @@
// REQUIRES: can-create-symlinks
// UNSUPPORTED: c++03, c++11, c++14
// UNSUPPORTED: no-filesystem
+// UNSUPPORTED: executor-runs-as-root
// On Android L, ~scoped_test_env() is unable to delete the temp dir using
// chmod+rm because chmod is too broken.
diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.exists/exists.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.exists/exists.pass.cpp
index 56465d01021ad..62dc696d6797d 100644
--- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.exists/exists.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.exists/exists.pass.cpp
@@ -9,6 +9,7 @@
// REQUIRES: can-create-symlinks
// UNSUPPORTED: c++03, c++11, c++14
// UNSUPPORTED: no-filesystem
+// UNSUPPORTED: executor-runs-as-root
// <filesystem>
diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_block_file/is_block_file.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_block_file/is_block_file.pass.cpp
index fad880ecf30f7..708fb511dce73 100644
--- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_block_file/is_block_file.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_block_file/is_block_file.pass.cpp
@@ -9,6 +9,7 @@
// REQUIRES: can-create-symlinks
// UNSUPPORTED: c++03, c++11, c++14
// UNSUPPORTED: no-filesystem
+// UNSUPPORTED: executor-runs-as-root
// <filesystem>
diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_char_file/is_character_file.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_char_file/is_character_file.pass.cpp
index 12bc0c198c062..69e357adeafb5 100644
--- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_char_file/is_character_file.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_char_file/is_character_file.pass.cpp
@@ -9,6 +9,7 @@
// REQUIRES: can-create-symlinks
// UNSUPPORTED: c++03, c++11, c++14
// UNSUPPORTED: no-filesystem
+// UNSUPPORTED: executor-runs-as-root
// <filesystem>
diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_directory/is_directory.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_directory/is_directory.pass.cpp
index f1b559cf2d55b..0ed4aa0dc8d58 100644
--- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_directory/is_directory.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_directory/is_directory.pass.cpp
@@ -9,6 +9,7 @@
// REQUIRES: can-create-symlinks
// UNSUPPORTED: c++03, c++11, c++14
// UNSUPPORTED: no-filesystem
+// UNSUPPORTED: executor-runs-as-root
// <filesystem>
diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_empty/is_empty.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_empty/is_empty.pass.cpp
index f3161f2e020d2..579c03f2b8c0b 100644
--- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_empty/is_empty.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_empty/is_empty.pass.cpp
@@ -9,6 +9,7 @@
// REQUIRES: can-create-symlinks
// UNSUPPORTED: c++03, c++11, c++14
// UNSUPPORTED: no-filesystem
+// UNSUPPORTED: executor-runs-as-root
// Starting in Android N (API 24), SELinux policy prevents the shell user from
// creating a FIFO file.
diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_fifo/is_fifo.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_fifo/is_fifo.pass.cpp
index fbf5e7129f7af..1d5312d65be46 100644
--- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_fifo/is_fifo.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_fifo/is_fifo.pass.cpp
@@ -9,6 +9,7 @@
// REQUIRES: can-create-symlinks
// UNSUPPORTED: c++03, c++11, c++14
// UNSUPPORTED: no-filesystem
+// UNSUPPORTED: executor-runs-as-root
// <filesystem>
diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_other/is_other.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_other/is_other.pass.cpp
index d0974640429df..7a3a56a0b161c 100644
--- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_other/is_other.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_other/is_other.pass.cpp
@@ -9,6 +9,7 @@
// REQUIRES: can-create-symlinks
// UNSUPPORTED: c++03, c++11, c++14
// UNSUPPORTED: no-filesystem
+// UNSUPPORTED: executor-runs-as-root
// <filesystem>
diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_regular_file/is_regular_file.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_regular_file/is_regular_file.pass.cpp
index 4a5882e36cde2..8b877ff63b112 100644
--- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_regular_file/is_regular_file.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_regular_file/is_regular_file.pass.cpp
@@ -9,6 +9,7 @@
// REQUIRES: can-create-symlinks
// UNSUPPORTED: c++03, c++11, c++14
// UNSUPPORTED: no-filesystem
+// UNSUPPORTED: executor-runs-as-root
// <filesystem>
diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_socket/is_socket.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_socket/is_socket.pass.cpp
index 382685c21dd99..995125d702de3 100644
--- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_socket/is_socket.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_socket/is_socket.pass.cpp
@@ -9,6 +9,7 @@
// REQUIRES: can-create-symlinks
// UNSUPPORTED: c++03, c++11, c++14
// UNSUPPORTED: no-filesystem
+// UNSUPPORTED: executor-runs-as-root
// <filesystem>
diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_symlink/is_symlink.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_symlink/is_symlink.pass.cpp
index 07b446d80c402..692fe773a0f9e 100644
--- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_symlink/is_symlink.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.is_symlink/is_symlink.pass.cpp
@@ -9,6 +9,7 @@
// REQUIRES: can-create-symlinks
// UNSUPPORTED: c++03, c++11, c++14
// UNSUPPORTED: no-filesystem
+// UNSUPPORTED: executor-runs-as-root
// <filesystem>
diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp
index c420fea21aa66..22c2c114ba687 100644
--- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.last_write_time/last_write_time.pass.cpp
@@ -9,6 +9,7 @@
// REQUIRES: can-create-symlinks
// UNSUPPORTED: c++03, c++11, c++14
// UNSUPPORTED: no-filesystem
+// UNSUPPORTED: executor-runs-as-root
// The string reported on errors changed, which makes those tests fail when run
// against a built library that doesn't contain 0aa637b2037d.
diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.remove/remove.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.remove/remove.pass.cpp
index 56b4a27de6b42..8064feaaf2065 100644
--- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.remove/remove.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.remove/remove.pass.cpp
@@ -9,6 +9,7 @@
// REQUIRES: can-create-symlinks
// UNSUPPORTED: c++03, c++11, c++14
// UNSUPPORTED: no-filesystem
+// UNSUPPORTED: executor-runs-as-root
// <filesystem>
diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp
index b30d56685e2cb..540849ccefc05 100644
--- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.remove_all/remove_all.pass.cpp
@@ -9,6 +9,7 @@
// REQUIRES: can-create-symlinks
// UNSUPPORTED: c++03, c++11, c++14
// UNSUPPORTED: no-filesystem
+// UNSUPPORTED: executor-runs-as-root
// <filesystem>
diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.status/status.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.status/status.pass.cpp
index 425c224606038..02ff1e249d3bc 100644
--- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.status/status.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.status/status.pass.cpp
@@ -9,6 +9,7 @@
// REQUIRES: can-create-symlinks
// UNSUPPORTED: c++03, c++11, c++14
// UNSUPPORTED: no-filesystem
+// UNSUPPORTED: executor-runs-as-root
// Starting in Android N (API 24), SELinux policy prevents the shell user from
// creating a FIFO file.
diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.symlink_status/symlink_status.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.symlink_status/symlink_status.pass.cpp
index 1d405a816e110..41474f9ca1e48 100644
--- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.symlink_status/symlink_status.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.symlink_status/symlink_status.pass.cpp
@@ -9,6 +9,7 @@
// REQUIRES: can-create-symlinks
// UNSUPPORTED: c++03, c++11, c++14
// UNSUPPORTED: no-filesystem
+// UNSUPPORTED: executor-runs-as-root
// Starting in Android N (API 24), SELinux policy prevents the shell user from
// creating a FIFO file.
diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.temp_dir_path/temp_directory_path.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.temp_dir_path/temp_directory_path.pass.cpp
index 38e14438f3fd3..9a891eab6b343 100644
--- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.temp_dir_path/temp_directory_path.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.temp_dir_path/temp_directory_path.pass.cpp
@@ -8,6 +8,7 @@
// UNSUPPORTED: c++03, c++11, c++14
// UNSUPPORTED: no-filesystem
+// UNSUPPORTED: executor-runs-as-root
// <filesystem>
diff --git a/libcxx/test/std/input.output/iostream.format/ext.manip/get_money.pass.cpp b/libcxx/test/std/input.output/iostream.format/ext.manip/get_money.pass.cpp
index 88672851f7b6b..3e1d34ab5257a 100644
--- a/libcxx/test/std/input.output/iostream.format/ext.manip/get_money.pass.cpp
+++ b/libcxx/test/std/input.output/iostream.format/ext.manip/get_money.pass.cpp
@@ -12,6 +12,7 @@
// Bionic has minimal locale support, investigate this later.
// XFAIL: LIBCXX-ANDROID-FIXME
+// UNSUPPORTED: platform-has-nonportable-locales
// REQUIRES: locale.en_US.UTF-8
diff --git a/libcxx/test/std/input.output/iostream.format/ext.manip/put_money.pass.cpp b/libcxx/test/std/input.output/iostream.format/ext.manip/put_money.pass.cpp
index d0ff2c87689d1..4c299b876639e 100644
--- a/libcxx/test/std/input.output/iostream.format/ext.manip/put_money.pass.cpp
+++ b/libcxx/test/std/input.output/iostream.format/ext.manip/put_money.pass.cpp
@@ -12,6 +12,7 @@
// Bionic has minimal locale support, investigate this later.
// XFAIL: LIBCXX-ANDROID-FIXME
+// UNSUPPORTED: platform-has-nonportable-locales
// REQUIRES: locale.en_US.UTF-8
diff --git a/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.formatted.print/locale-specific_form.pass.cpp b/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.formatted.print/locale-specific_form.pass.cpp
index 98fa56b7f4b6d..7970887bac199 100644
--- a/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.formatted.print/locale-specific_form.pass.cpp
+++ b/libcxx/test/std/input.output/iostream.format/output.streams/ostream.formatted/ostream.formatted.print/locale-specific_form.pass.cpp
@@ -17,6 +17,7 @@
// Bionic has minimal locale support, investigate this later.
// XFAIL: LIBCXX-ANDROID-FIXME
+// UNSUPPORTED: platform-has-nonportable-locales
// REQUIRES: locale.en_US.UTF-8
diff --git a/libcxx/test/std/input.output/iostream.format/print.fun/no_file_description.pass.cpp b/libcxx/test/std/input.output/iostream.format/print.fun/no_file_description.pass.cpp
index 283a8fddb8e8f..13e6f74c5a143 100644
--- a/libcxx/test/std/input.output/iostream.format/print.fun/no_file_description.pass.cpp
+++ b/libcxx/test/std/input.output/iostream.format/print.fun/no_file_description.pass.cpp
@@ -17,6 +17,9 @@
// fmemopen is available starting in Android M (API 23)
// XFAIL: target={{.+}}-android{{(eabi)?(21|22)}}
+// OHOS fmemopen/FILE behavior does not currently match the expectation tested here.
+// XFAIL: LIBCXX-OHOS-FIXME
+
// <print>
// The FILE returned by fmemopen does not have file descriptor.
diff --git a/libcxx/test/std/input.output/iostream.format/std.manip/setfill_wchar_max.pass.cpp b/libcxx/test/std/input.output/iostream.format/std.manip/setfill_wchar_max.pass.cpp
index b24c0b90d86f1..2ddddbef70dbb 100644
--- a/libcxx/test/std/input.output/iostream.format/std.manip/setfill_wchar_max.pass.cpp
+++ b/libcxx/test/std/input.output/iostream.format/std.manip/setfill_wchar_max.pass.cpp
@@ -18,6 +18,7 @@
// XFAIL: target=armv{{7|8}}{{l?}}{{.*}}-linux-gnueabihf && libcpp-abi-version=1
// XFAIL: target=aarch64{{.*}}-linux-gnu && libcpp-abi-version=1
// XFAIL: target=aarch64{{.*}}-amazon-linux && libcpp-abi-version=1
+// XFAIL: target={{.*}}-linux-ohos && libcpp-abi-version=1
#include <iomanip>
#include <ostream>
diff --git a/libcxx/test/std/input.output/iostream.objects/narrow.stream.objects/cerr.sh.cpp b/libcxx/test/std/input.output/iostream.objects/narrow.stream.objects/cerr.sh.cpp
index da5563f87df45..ea5af90a90822 100644
--- a/libcxx/test/std/input.output/iostream.objects/narrow.stream.objects/cerr.sh.cpp
+++ b/libcxx/test/std/input.output/iostream.objects/narrow.stream.objects/cerr.sh.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
// XFAIL: LIBCXX-PICOLIBC-FIXME
+// UNSUPPORTED: executor-merges-stderr-into-stdout
// <iostream>
diff --git a/libcxx/test/std/input.output/iostream.objects/narrow.stream.objects/cin.sh.cpp b/libcxx/test/std/input.output/iostream.objects/narrow.stream.objects/cin.sh.cpp
index 4f23b6b9a5d87..6dc0ff36ff4bf 100644
--- a/libcxx/test/std/input.output/iostream.objects/narrow.stream.objects/cin.sh.cpp
+++ b/libcxx/test/std/input.output/iostream.objects/narrow.stream.objects/cin.sh.cpp
@@ -14,6 +14,7 @@
// This test hangs on Android devices that lack shell_v2, which was added in
// Android N (API 24).
// UNSUPPORTED: LIBCXX-ANDROID-FIXME && android-device-api={{2[1-3]}}
+// UNSUPPORTED: executor-has-no-stdin
// <iostream>
diff --git a/libcxx/test/std/input.output/iostream.objects/narrow.stream.objects/clog.sh.cpp b/libcxx/test/std/input.output/iostream.objects/narrow.stream.objects/clog.sh.cpp
index 9bedd67e816ef..cbb9639766207 100644
--- a/libcxx/test/std/input.output/iostream.objects/narrow.stream.objects/clog.sh.cpp
+++ b/libcxx/test/std/input.output/iostream.objects/narrow.stream.objects/clog.sh.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
// XFAIL: LIBCXX-PICOLIBC-FIXME
+// UNSUPPORTED: executor-merges-stderr-into-stdout
// <iostream>
diff --git a/libcxx/test/std/input.output/iostream.objects/wide.stream.objects/wcerr-imbue.sh.cpp b/libcxx/test/std/input.output/iostream.objects/wide.stream.objects/wcerr-imbue.sh.cpp
index ec4c8a009ba0c..59d93e74db3b7 100644
--- a/libcxx/test/std/input.output/iostream.objects/wide.stream.objects/wcerr-imbue.sh.cpp
+++ b/libcxx/test/std/input.output/iostream.objects/wide.stream.objects/wcerr-imbue.sh.cpp
@@ -11,6 +11,7 @@
// wostream wcerr;
// UNSUPPORTED: no-wide-characters
+// UNSUPPORTED: executor-merges-stderr-into-stdout
// RUN: %{build}
// RUN: %{exec} %t.exe 2> %t.actual
diff --git a/libcxx/test/std/input.output/iostream.objects/wide.stream.objects/wcerr.sh.cpp b/libcxx/test/std/input.output/iostream.objects/wide.stream.objects/wcerr.sh.cpp
index ae82035ccfc62..49a6ce0892ea4 100644
--- a/libcxx/test/std/input.output/iostream.objects/wide.stream.objects/wcerr.sh.cpp
+++ b/libcxx/test/std/input.output/iostream.objects/wide.stream.objects/wcerr.sh.cpp
@@ -11,6 +11,7 @@
// wostream wcerr;
// UNSUPPORTED: no-wide-characters
+// UNSUPPORTED: executor-merges-stderr-into-stdout
// RUN: %{build}
// RUN: %{exec} %t.exe 2> %t.actual
diff --git a/libcxx/test/std/input.output/iostream.objects/wide.stream.objects/wcin-imbue.sh.cpp b/libcxx/test/std/input.output/iostream.objects/wide.stream.objects/wcin-imbue.sh.cpp
index 6ae1972234b2b..58a6e18340ddf 100644
--- a/libcxx/test/std/input.output/iostream.objects/wide.stream.objects/wcin-imbue.sh.cpp
+++ b/libcxx/test/std/input.output/iostream.objects/wide.stream.objects/wcin-imbue.sh.cpp
@@ -9,6 +9,7 @@
// This test hangs on Android devices that lack shell_v2, which was added in
// Android N (API 24).
// UNSUPPORTED: LIBCXX-ANDROID-FIXME && android-device-api={{2[1-3]}}
+// UNSUPPORTED: executor-has-no-stdin
// <iostream>
diff --git a/libcxx/test/std/input.output/iostream.objects/wide.stream.objects/wcin.sh.cpp b/libcxx/test/std/input.output/iostream.objects/wide.stream.objects/wcin.sh.cpp
index 08b74b999bbf4..88dcfe0485429 100644
--- a/libcxx/test/std/input.output/iostream.objects/wide.stream.objects/wcin.sh.cpp
+++ b/libcxx/test/std/input.output/iostream.objects/wide.stream.objects/wcin.sh.cpp
@@ -9,6 +9,7 @@
// This test hangs on Android devices that lack shell_v2, which was added in
// Android N (API 24).
// UNSUPPORTED: LIBCXX-ANDROID-FIXME && android-device-api={{2[1-3]}}
+// UNSUPPORTED: executor-has-no-stdin
// <iostream>
diff --git a/libcxx/test/std/input.output/iostream.objects/wide.stream.objects/wclog.sh.cpp b/libcxx/test/std/input.output/iostream.objects/wide.stream.objects/wclog.sh.cpp
index 89e178248ae50..9c9745dcc9777 100644
--- a/libcxx/test/std/input.output/iostream.objects/wide.stream.objects/wclog.sh.cpp
+++ b/libcxx/test/std/input.output/iostream.objects/wide.stream.objects/wclog.sh.cpp
@@ -11,6 +11,7 @@
// wostream wclog;
// XFAIL: no-wide-characters
+// UNSUPPORTED: executor-merges-stderr-into-stdout
// RUN: %{build}
// RUN: %{exec} %t.exe 2> %t.actual
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/sized_delete_array.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/sized_delete_array.pass.cpp
index 0e411f8adc0f2..e563152f2c8cd 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/sized_delete_array.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/sized_delete_array.pass.cpp
@@ -20,6 +20,7 @@
// ADDITIONAL_COMPILE_FLAGS(target=powerpc-ibm-aix): -fsized-deallocation
// ADDITIONAL_COMPILE_FLAGS(target=powerpc64-ibm-aix): -fsized-deallocation
// UNSUPPORTED: sanitizer-new-delete
+// UNSUPPORTED: platform-has-unreliable-new-delete-interposition
// AIX, and z/OS default to -fno-sized-deallocation.
// XFAIL: target={{.+}}-zos{{.*}}
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/sized_delete_array_calls_unsized_delete_array.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/sized_delete_array_calls_unsized_delete_array.pass.cpp
index 026250daeee89..34119303a29ba 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/sized_delete_array_calls_unsized_delete_array.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/sized_delete_array_calls_unsized_delete_array.pass.cpp
@@ -11,6 +11,7 @@
// operator delete [] is called directly.
// UNSUPPORTED: sanitizer-new-delete
+// UNSUPPORTED: platform-has-unreliable-new-delete-interposition
#include <new>
#include <cstddef>
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/sized_delete.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/sized_delete.pass.cpp
index ca0f612bf7578..a4e32aaa11e13 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/sized_delete.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/sized_delete.pass.cpp
@@ -20,6 +20,7 @@
// ADDITIONAL_COMPILE_FLAGS(target=powerpc-ibm-aix): -fsized-deallocation
// ADDITIONAL_COMPILE_FLAGS(target=powerpc64-ibm-aix): -fsized-deallocation
// UNSUPPORTED: sanitizer-new-delete
+// UNSUPPORTED: platform-has-unreliable-new-delete-interposition
// AIX, and z/OS default to -fno-sized-deallocation.
// XFAIL: target={{.+}}-zos{{.*}}
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/sized_delete_calls_unsized_delete.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/sized_delete_calls_unsized_delete.pass.cpp
index fbc9cf070bcba..3ec2b47b53eb0 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/sized_delete_calls_unsized_delete.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/sized_delete_calls_unsized_delete.pass.cpp
@@ -11,6 +11,7 @@
// operator delete is called directly.
// UNSUPPORTED: sanitizer-new-delete
+// UNSUPPORTED: platform-has-unreliable-new-delete-interposition
#include <new>
#include <cstddef>
diff --git a/libcxx/test/std/localization/locale.categories/category.collate/locale.collate.byname/compare.pass.cpp b/libcxx/test/std/localization/locale.categories/category.collate/locale.collate.byname/compare.pass.cpp
index 8ae6bc2d3ba66..7cfd9f955fce7 100644
--- a/libcxx/test/std/localization/locale.categories/category.collate/locale.collate.byname/compare.pass.cpp
+++ b/libcxx/test/std/localization/locale.categories/category.collate/locale.collate.byname/compare.pass.cpp
@@ -8,6 +8,7 @@
// Bionic has minimal locale support, investigate this later.
// XFAIL: LIBCXX-ANDROID-FIXME
+// UNSUPPORTED: platform-has-nonportable-locales
// REQUIRES: locale.en_US.UTF-8
diff --git a/libcxx/test/std/localization/locale.categories/category.collate/locale.collate.byname/transform.pass.cpp b/libcxx/test/std/localization/locale.categories/category.collate/locale.collate.byname/transform.pass.cpp
index 4978db116ef39..743075ede8ece 100644
--- a/libcxx/test/std/localization/locale.categories/category.collate/locale.collate.byname/transform.pass.cpp
+++ b/libcxx/test/std/localization/locale.categories/category.collate/locale.collate.byname/transform.pass.cpp
@@ -11,6 +11,7 @@
// Bionic has minimal locale support, investigate this later.
// XFAIL: LIBCXX-ANDROID-FIXME
+// UNSUPPORTED: platform-has-nonportable-locales
// <locale>
diff --git a/libcxx/test/std/localization/locale.categories/category.ctype/facet.ctype.special/facet.ctype.char.dtor/dtor.pass.cpp b/libcxx/test/std/localization/locale.categories/category.ctype/facet.ctype.special/facet.ctype.char.dtor/dtor.pass.cpp
index 7be7e8d574e6c..b77a4409522f0 100644
--- a/libcxx/test/std/localization/locale.categories/category.ctype/facet.ctype.special/facet.ctype.char.dtor/dtor.pass.cpp
+++ b/libcxx/test/std/localization/locale.categories/category.ctype/facet.ctype.special/facet.ctype.char.dtor/dtor.pass.cpp
@@ -11,6 +11,7 @@
// template <> class ctype<char>
// ~ctype();
+// UNSUPPORTED: platform-has-unreliable-new-delete-interposition
#include <locale>
#include <cassert>
diff --git a/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/is_1.pass.cpp b/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/is_1.pass.cpp
index 5cebc079c4703..c4803c04d173b 100644
--- a/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/is_1.pass.cpp
+++ b/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/is_1.pass.cpp
@@ -17,6 +17,7 @@
// Bionic has minimal locale support, investigate this later.
// XFAIL: LIBCXX-ANDROID-FIXME
+// UNSUPPORTED: platform-has-nonportable-locales
#include <locale>
#include <type_traits>
diff --git a/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/is_many.pass.cpp b/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/is_many.pass.cpp
index 2869378b42b92..5174ffebf281f 100644
--- a/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/is_many.pass.cpp
+++ b/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/is_many.pass.cpp
@@ -17,6 +17,7 @@
// Bionic has minimal locale support, investigate this later.
// XFAIL: LIBCXX-ANDROID-FIXME
+// UNSUPPORTED: platform-has-nonportable-locales
#include <locale>
#include <string>
diff --git a/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/scan_is.pass.cpp b/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/scan_is.pass.cpp
index ea03f042f2d45..665da7323e38a 100644
--- a/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/scan_is.pass.cpp
+++ b/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/scan_is.pass.cpp
@@ -17,6 +17,7 @@
// Bionic has minimal locale support, investigate this later.
// XFAIL: LIBCXX-ANDROID-FIXME
+// UNSUPPORTED: platform-has-nonportable-locales
#include <locale>
#include <string>
diff --git a/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/scan_not.pass.cpp b/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/scan_not.pass.cpp
index 2f7acb843e591..5d87c081b6e1c 100644
--- a/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/scan_not.pass.cpp
+++ b/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/scan_not.pass.cpp
@@ -17,6 +17,7 @@
// Bionic has minimal locale support, investigate this later.
// XFAIL: LIBCXX-ANDROID-FIXME
+// UNSUPPORTED: platform-has-nonportable-locales
#include <locale>
#include <string>
diff --git a/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/tolower_1.pass.cpp b/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/tolower_1.pass.cpp
index 447353de8af72..93d93aa9228f7 100644
--- a/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/tolower_1.pass.cpp
+++ b/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/tolower_1.pass.cpp
@@ -11,6 +11,7 @@
// Bionic has minimal locale support, investigate this later.
// XFAIL: LIBCXX-ANDROID-FIXME
+// UNSUPPORTED: platform-has-nonportable-locales
// <locale>
diff --git a/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/tolower_many.pass.cpp b/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/tolower_many.pass.cpp
index 94ecc6c8fa85b..ab448a01632d6 100644
--- a/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/tolower_many.pass.cpp
+++ b/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/tolower_many.pass.cpp
@@ -11,6 +11,7 @@
// Bionic has minimal locale support, investigate this later.
// XFAIL: LIBCXX-ANDROID-FIXME
+// UNSUPPORTED: platform-has-nonportable-locales
// <locale>
diff --git a/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/toupper_1.pass.cpp b/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/toupper_1.pass.cpp
index 2b37737a26bc3..4be990e5b88c6 100644
--- a/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/toupper_1.pass.cpp
+++ b/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/toupper_1.pass.cpp
@@ -11,6 +11,7 @@
// Bionic has minimal locale support, investigate this later.
// XFAIL: LIBCXX-ANDROID-FIXME
+// UNSUPPORTED: platform-has-nonportable-locales
// <locale>
diff --git a/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/toupper_many.pass.cpp b/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/toupper_many.pass.cpp
index 016d8d736ad22..e0a3912a9315e 100644
--- a/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/toupper_many.pass.cpp
+++ b/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/toupper_many.pass.cpp
@@ -11,6 +11,7 @@
// Bionic has minimal locale support, investigate this later.
// XFAIL: LIBCXX-ANDROID-FIXME
+// UNSUPPORTED: platform-has-nonportable-locales
// <locale>
diff --git a/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/widen_1.pass.cpp b/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/widen_1.pass.cpp
index 959a4be9e1de9..b22629c82444e 100644
--- a/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/widen_1.pass.cpp
+++ b/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/widen_1.pass.cpp
@@ -8,6 +8,7 @@
// REQUIRES: locale.en_US.UTF-8
// XFAIL: no-wide-characters
+// UNSUPPORTED: platform-has-nonportable-locales
// <locale>
diff --git a/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/widen_many.pass.cpp b/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/widen_many.pass.cpp
index 078b4a6fefb7e..c2cd904808794 100644
--- a/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/widen_many.pass.cpp
+++ b/libcxx/test/std/localization/locale.categories/category.ctype/locale.ctype.byname/widen_many.pass.cpp
@@ -8,6 +8,7 @@
// REQUIRES: locale.en_US.UTF-8
// XFAIL: no-wide-characters
+// UNSUPPORTED: platform-has-nonportable-locales
// <locale>
diff --git a/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.get/locale.money.get.members/get_long_double_en_US.pass.cpp b/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.get/locale.money.get.members/get_long_double_en_US.pass.cpp
index 9997b07134563..73b7a6decda36 100644
--- a/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.get/locale.money.get.members/get_long_double_en_US.pass.cpp
+++ b/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.get/locale.money.get.members/get_long_double_en_US.pass.cpp
@@ -15,6 +15,7 @@
// Bionic has minimal locale support, investigate this later.
// XFAIL: LIBCXX-ANDROID-FIXME
+// UNSUPPORTED: platform-has-nonportable-locales
// REQUIRES: locale.en_US.UTF-8
diff --git a/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.get/locale.money.get.members/get_long_double_zh_CN.pass.cpp b/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.get/locale.money.get.members/get_long_double_zh_CN.pass.cpp
index c86df7e6b53bf..deb30d747653f 100644
--- a/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.get/locale.money.get.members/get_long_double_zh_CN.pass.cpp
+++ b/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.get/locale.money.get.members/get_long_double_zh_CN.pass.cpp
@@ -10,6 +10,7 @@
// XFAIL: netbsd
// XFAIL: LIBCXX-FREEBSD-FIXME
+// UNSUPPORTED: platform-has-nonportable-locales
// REQUIRES: locale.zh_CN.UTF-8
diff --git a/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.get/locale.money.get.members/get_string_en_US.pass.cpp b/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.get/locale.money.get.members/get_string_en_US.pass.cpp
index 478df7964f6d2..ee6fbd48b09b6 100644
--- a/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.get/locale.money.get.members/get_string_en_US.pass.cpp
+++ b/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.get/locale.money.get.members/get_string_en_US.pass.cpp
@@ -15,6 +15,7 @@
// Bionic has minimal locale support, investigate this later.
// XFAIL: LIBCXX-ANDROID-FIXME
+// UNSUPPORTED: platform-has-nonportable-locales
// REQUIRES: locale.en_US.UTF-8
diff --git a/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.put/locale.money.put.members/put_long_double_en_US.pass.cpp b/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.put/locale.money.put.members/put_long_double_en_US.pass.cpp
index 4b767fae871fa..c476537c3c7e3 100644
--- a/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.put/locale.money.put.members/put_long_double_en_US.pass.cpp
+++ b/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.put/locale.money.put.members/put_long_double_en_US.pass.cpp
@@ -15,6 +15,7 @@
// Bionic has minimal locale support, investigate this later.
// XFAIL: LIBCXX-ANDROID-FIXME
+// UNSUPPORTED: platform-has-nonportable-locales
// REQUIRES: locale.en_US.UTF-8
diff --git a/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.put/locale.money.put.members/put_long_double_zh_CN.pass.cpp b/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.put/locale.money.put.members/put_long_double_zh_CN.pass.cpp
index 25046a8417083..8174a724d4165 100644
--- a/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.put/locale.money.put.members/put_long_double_zh_CN.pass.cpp
+++ b/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.put/locale.money.put.members/put_long_double_zh_CN.pass.cpp
@@ -10,6 +10,7 @@
// XFAIL: netbsd
// XFAIL: LIBCXX-FREEBSD-FIXME
+// UNSUPPORTED: platform-has-nonportable-locales
// REQUIRES: locale.zh_CN.UTF-8
diff --git a/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.put/locale.money.put.members/put_string_en_US.pass.cpp b/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.put/locale.money.put.members/put_string_en_US.pass.cpp
index 1c8710a008f27..e23cb4bf5f04a 100644
--- a/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.put/locale.money.put.members/put_string_en_US.pass.cpp
+++ b/libcxx/test/std/localization/locale.categories/category.monetary/locale.money.put/locale.money.put.members/put_string_en_US.pass.cpp
@@ -15,6 +15,7 @@
// Bionic has minimal locale support, investigate this later.
// XFAIL: LIBCXX-ANDROID-FIXME
+// UNSUPPORTED: platform-has-nonportable-locales
// REQUIRES: locale.en_US.UTF-8
diff --git a/libcxx/test/std/localization/locales/locale/locale.cons/default.pass.cpp b/libcxx/test/std/localization/locales/locale/locale.cons/default.pass.cpp
index f0086ada30303..a36e3af8d12eb 100644
--- a/libcxx/test/std/localization/locales/locale/locale.cons/default.pass.cpp
+++ b/libcxx/test/std/localization/locales/locale/locale.cons/default.pass.cpp
@@ -12,6 +12,7 @@
// This test runs in C++20, but we have deprecated codecvt<char(16|32), char, mbstate_t> in C++20.
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS
+// UNSUPPORTED: platform-has-unreliable-new-delete-interposition
// <locale>
diff --git a/libcxx/test/std/re/re.traits/transform.pass.cpp b/libcxx/test/std/re/re.traits/transform.pass.cpp
index 80cd3f01faff2..112ecd47ff4e2 100644
--- a/libcxx/test/std/re/re.traits/transform.pass.cpp
+++ b/libcxx/test/std/re/re.traits/transform.pass.cpp
@@ -8,6 +8,7 @@
//
// NetBSD does not support LC_COLLATE at the moment
// XFAIL: netbsd
+// UNSUPPORTED: platform-has-nonportable-locales
// REQUIRES: locale.cs_CZ.ISO8859-2
diff --git a/libcxx/test/std/re/re.traits/transform_primary.pass.cpp b/libcxx/test/std/re/re.traits/transform_primary.pass.cpp
index 422e3a591e643..cbc9387facb30 100644
--- a/libcxx/test/std/re/re.traits/transform_primary.pass.cpp
+++ b/libcxx/test/std/re/re.traits/transform_primary.pass.cpp
@@ -11,6 +11,7 @@
// XFAIL: LIBCXX-AIX-FIXME
// XFAIL: LIBCXX-FREEBSD-FIXME
+// UNSUPPORTED: platform-has-nonportable-locales
// REQUIRES: locale.cs_CZ.ISO8859-2
diff --git a/libcxx/test/std/thread/futures/futures.async/thread_create_failure.pass.cpp b/libcxx/test/std/thread/futures/futures.async/thread_create_failure.pass.cpp
index 40daa49393bd4..110d0ea9fd694 100644
--- a/libcxx/test/std/thread/futures/futures.async/thread_create_failure.pass.cpp
+++ b/libcxx/test/std/thread/futures/futures.async/thread_create_failure.pass.cpp
@@ -15,6 +15,7 @@
// There is no way to limit the number of threads on windows
// UNSUPPORTED: windows
+// UNSUPPORTED: executor-runs-as-root
// macOS and FreeBSD seem to limit the number of processes, not threads via RLIMIT_NPROC.
// XFAIL: target={{.+}}-apple-{{.*}}
diff --git a/libcxx/test/std/thread/thread.jthread/join.deadlock.pass.cpp b/libcxx/test/std/thread/thread.jthread/join.deadlock.pass.cpp
index c6eb0694ab2e1..19573ae52fd71 100644
--- a/libcxx/test/std/thread/thread.jthread/join.deadlock.pass.cpp
+++ b/libcxx/test/std/thread/thread.jthread/join.deadlock.pass.cpp
@@ -9,6 +9,7 @@
// Windows cannot detect the deadlock. Instead of throwing system_error,
// it would dead lock the test
// UNSUPPORTED: windows
+// UNSUPPORTED: pthread-join-self-deadlocks
// TSAN bug: https://llvm.org/PR66537
// UNSUPPORTED: tsan
diff --git a/libcxx/test/std/utilities/format/format.functions/locale-specific_form.pass.cpp b/libcxx/test/std/utilities/format/format.functions/locale-specific_form.pass.cpp
index 51be78e1a02f8..804036e425572 100644
--- a/libcxx/test/std/utilities/format/format.functions/locale-specific_form.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.functions/locale-specific_form.pass.cpp
@@ -14,6 +14,7 @@
// Bionic has minimal locale support, investigate this later.
// XFAIL: LIBCXX-ANDROID-FIXME
+// UNSUPPORTED: platform-has-nonportable-locales
// REQUIRES: locale.en_US.UTF-8
diff --git a/libcxx/test/support/count_new.h b/libcxx/test/support/count_new.h
index f175bc2ffcd44..6901aff00bc4e 100644
--- a/libcxx/test/support/count_new.h
+++ b/libcxx/test/support/count_new.h
@@ -415,6 +415,13 @@ void operator delete(void* p, std::nothrow_t const&) TEST_NOEXCEPT {
std::free(p);
}
+# if defined(__cpp_sized_deallocation) && __cpp_sized_deallocation >= 201309L
+void operator delete(void* p, std::size_t) TEST_NOEXCEPT {
+ getGlobalMemCounter()->deleteCalled(p);
+ std::free(p);
+}
+# endif
+
// operator new[](size_t[, nothrow_t]) and operator delete[](size_t[, nothrow_t])
void* operator new[](std::size_t s) TEST_THROW_SPEC(std::bad_alloc) {
getGlobalMemCounter()->newArrayCalled(s);
@@ -449,6 +456,13 @@ void operator delete[](void* p, std::nothrow_t const&) TEST_NOEXCEPT {
std::free(p);
}
+# if defined(__cpp_sized_deallocation) && __cpp_sized_deallocation >= 201309L
+void operator delete[](void* p, std::size_t) TEST_NOEXCEPT {
+ getGlobalMemCounter()->deleteArrayCalled(p);
+ std::free(p);
+}
+# endif
+
# ifndef TEST_HAS_NO_ALIGNED_ALLOCATION
# if defined(_LIBCPP_MSVCRT_LIKE) || (!defined(_LIBCPP_VERSION) && defined(_WIN32))
# define USE_ALIGNED_ALLOC
@@ -519,6 +533,13 @@ void operator delete(void* p, std::align_val_t av, std::nothrow_t const&) TEST_N
free_aligned_impl(p, av);
}
+# if defined(__cpp_sized_deallocation) && __cpp_sized_deallocation >= 201309L
+void operator delete(void* p, std::size_t, std::align_val_t av) TEST_NOEXCEPT {
+ getGlobalMemCounter()->alignedDeleteCalled(p, static_cast<std::size_t>(av));
+ free_aligned_impl(p, av);
+}
+# endif
+
// operator new[](size_t, align_val_t[, nothrow_t]) and operator delete[](size_t, align_val_t[, nothrow_t])
void* operator new[](std::size_t s, std::align_val_t av) TEST_THROW_SPEC(std::bad_alloc) {
getGlobalMemCounter()->alignedNewArrayCalled(s, static_cast<std::size_t>(av));
@@ -551,6 +572,13 @@ void operator delete[](void* p, std::align_val_t av, std::nothrow_t const&) TEST
free_aligned_impl(p, av);
}
+# if defined(__cpp_sized_deallocation) && __cpp_sized_deallocation >= 201309L
+void operator delete[](void* p, std::size_t, std::align_val_t av) TEST_NOEXCEPT {
+ getGlobalMemCounter()->alignedDeleteArrayCalled(p, static_cast<std::size_t>(av));
+ free_aligned_impl(p, av);
+}
+# endif
+
# endif // TEST_HAS_NO_ALIGNED_ALLOCATION
#endif // DISABLE_NEW_COUNT
diff --git a/libcxx/test/support/filesystem_test_helper.h b/libcxx/test/support/filesystem_test_helper.h
index 2ad9efb32c60f..f820a4a0fa915 100644
--- a/libcxx/test/support/filesystem_test_helper.h
+++ b/libcxx/test/support/filesystem_test_helper.h
@@ -182,7 +182,7 @@ struct scoped_test_env
std::string cmd = "chmod -R 777 " + test_root.string();
#endif // defined(__MVS__)
int ret = std::system(cmd.c_str());
-# if !defined(_AIX) && !defined(__ANDROID__)
+# if !defined(_AIX) && !defined(__ANDROID__) && !defined(__OHOS__)
// On AIX the chmod command will return non-zero when trying to set
// the permissions on a directory that contains a bad symlink. This triggers
// the assert, despite being able to delete everything with the following
@@ -196,6 +196,8 @@ struct scoped_test_env
// LIBCXX-ANDROID-FIXME: Other fixes to consider: place a toybox chmod
// onto old devices, re-enable this assert for devices running Android N
// and up, rewrite this chmod+rm in C or C++.
+ //
+ // OHOS has the same chmod -R behavior for bad symlinks.
assert(ret == 0);
# endif
diff --git a/libcxx/test/support/test_macros.h b/libcxx/test/support/test_macros.h
index 78b1f6eda6576..fdf6bc5b18d72 100644
--- a/libcxx/test/support/test_macros.h
+++ b/libcxx/test/support/test_macros.h
@@ -375,7 +375,7 @@ inline Tp const& DoNotOptimize(Tp const& value) {
#define TEST_NOT_WIN32(...) __VA_ARGS__
#endif
-#if defined(TEST_WINDOWS_DLL) ||defined(__MVS__) || defined(_AIX)
+#if defined(TEST_WINDOWS_DLL) || defined(__MVS__) || defined(_AIX) || defined(TEST_HAS_NO_RELIABLE_LIBRARY_INTERNAL_ALLOCATIONS)
// Macros for waiving cases when we can't count allocations done within
// the library implementation.
//
@@ -386,6 +386,8 @@ inline Tp const& DoNotOptimize(Tp const& value) {
//
// The same goes on IBM zOS.
// The same goes on AIX.
+// Some target test configurations can define
+// TEST_HAS_NO_RELIABLE_LIBRARY_INTERNAL_ALLOCATIONS for the same reason.
#define ASSERT_WITH_LIBRARY_INTERNAL_ALLOCATIONS(...) ((void)(__VA_ARGS__))
#define TEST_SUPPORTS_LIBRARY_INTERNAL_ALLOCATIONS 0
#else
diff --git a/libunwind/test/aarch64_za_unwind.pass.cpp b/libunwind/test/aarch64_za_unwind.pass.cpp
index 36536860c1a96..b28f70a6e8e7a 100644
--- a/libunwind/test/aarch64_za_unwind.pass.cpp
+++ b/libunwind/test/aarch64_za_unwind.pass.cpp
@@ -20,6 +20,9 @@
#if defined(_LIBUNWIND_HAVE_GETAUXVAL) || defined(_LIBUNWIND_HAVE_ELF_AUX_INFO)
#include <sys/auxv.h>
#endif
+#if __has_include(<asm/hwcap.h>)
+#include <asm/hwcap.h>
+#endif
// Basic test of unwinding with SME lazy saves. This tests libunwind disables ZA
// (and commits a lazy save of ZA) before resuming from unwinding.
@@ -33,18 +36,16 @@ static bool checkHasSME() {
return false;
return has_sme != 0;
}
-#elif defined(_LIBUNWIND_HAVE_GETAUXVAL)
+#elif defined(_LIBUNWIND_HAVE_GETAUXVAL) && defined(HWCAP2_SME)
static bool checkHasSME() {
- constexpr int hwcap2_sme = (1 << 23);
unsigned long hwcap2 = getauxval(AT_HWCAP2);
- return (hwcap2 & hwcap2_sme) != 0;
+ return (hwcap2 & HWCAP2_SME) != 0;
}
-#elif defined(_LIBUNWIND_HAVE_ELF_AUX_INFO)
+#elif defined(_LIBUNWIND_HAVE_ELF_AUX_INFO) && defined(HWCAP2_SME)
static bool checkHasSME() {
- constexpr int hwcap2_sme = (1 << 23);
unsigned long hwcap2 = 0;
elf_aux_info(AT_HWCAP2, &hwcap2, sizeof(hwcap2));
- return (hwcap2 & hwcap2_sme) != 0;
+ return (hwcap2 & HWCAP2_SME) != 0;
}
#else
static bool checkHasSME() {
>From bbaa18370c45aaf79c2446be0a6e94dc2aa0ef00 Mon Sep 17 00:00:00 2001
From: hu1hu1 <fanyaohui at huawei.com>
Date: Fri, 3 Jul 2026 10:33:38 +0800
Subject: [PATCH 4/6] Add qemu
---
libcxx/test/configs/llvm-libc++-ohos.cfg.in | 16 +-
libcxx/utils/ci/run-buildbot | 41 ++++-
libcxx/utils/ci/vendor/ohos/qemu_run.py | 144 ++++++++++++++++++
.../test/configs/llvm-libc++abi-ohos.cfg.in | 8 +-
.../test/configs/llvm-libunwind-ohos.cfg.in | 8 +-
5 files changed, 204 insertions(+), 13 deletions(-)
create mode 100755 libcxx/utils/ci/vendor/ohos/qemu_run.py
diff --git a/libcxx/test/configs/llvm-libc++-ohos.cfg.in b/libcxx/test/configs/llvm-libc++-ohos.cfg.in
index 542bc0cc83a1f..20aa7a49d5802 100644
--- a/libcxx/test/configs/llvm-libc++-ohos.cfg.in
+++ b/libcxx/test/configs/llvm-libc++-ohos.cfg.in
@@ -1,5 +1,5 @@
# This testing configuration handles running the test suite against LLVM's
-# libc++ using HDC on OHOS.
+# libc++ using HDC or QEMU on OHOS.
lit_config.load_config(config, '@CMAKE_CURRENT_BINARY_DIR@/cmake-bridge.cfg')
@@ -23,15 +23,21 @@ import os, site
site.addsitedir(os.path.join('@LIBCXX_SOURCE_DIR@', 'utils'))
import libcxx.test.params, libcxx.test.config
+executor_kind = lit_config.params.get('executor_kind', 'ohos-hdc')
+if executor_kind not in ('ohos-hdc', 'ohos-qemu'):
+ lit_config.fatal(f'unsupported OHOS executor_kind: {executor_kind}')
+
config.available_features.add('LIBCXX-OHOS-FIXME')
-config.available_features.add('ohos-hdc')
-config.available_features.add('executor-has-no-stdin')
-config.available_features.add('executor-merges-stderr-into-stdout')
-config.available_features.add('executor-runs-as-root')
+config.available_features.add(executor_kind)
config.available_features.add('platform-has-nonportable-locales')
config.available_features.add('platform-has-unreliable-new-delete-interposition')
config.available_features.add('pthread-join-self-deadlocks')
+if executor_kind == 'ohos-hdc':
+ config.available_features.add('executor-has-no-stdin')
+ config.available_features.add('executor-merges-stderr-into-stdout')
+ config.available_features.add('executor-runs-as-root')
+
libcxx.test.config.configure(
libcxx.test.params.DEFAULT_PARAMETERS,
libcxx.test.features.DEFAULT_FEATURES,
diff --git a/libcxx/utils/ci/run-buildbot b/libcxx/utils/ci/run-buildbot
index ecf0ca17ae148..40739b0fba4d8 100755
--- a/libcxx/utils/ci/run-buildbot
+++ b/libcxx/utils/ci/run-buildbot
@@ -28,6 +28,16 @@ ${PROGNAME} [options] <BUILDER>
--build-dir <DIR> The directory to use for building the library. By default,
this is '<llvm-root>/build/<builder>'.
+--ohos-qemu <PATH> Run OHOS tests under qemu-aarch64 instead of HDC. This also
+ accepts OHOS_QEMU or QEMU from the environment.
+
+--ohos-qemu-sysroot <DIR>
+ Sysroot passed to qemu-aarch64 with -L. Defaults to
+ OHOS_QEMU_SYSROOT, QEMU_SYSROOT, then OHOS_SYSROOT.
+
+--ohos-hdc <PATH> HDC binary to use when OHOS tests run on a device. This sets
+ HDC for the OHOS HDC executor.
+
Environment variables
CC The C compiler to use, this value is used by CMake. This
variable is mandatory.
@@ -84,6 +94,19 @@ while [[ $# -gt 0 ]]; do
BUILD_DIR="${2}"
shift; shift
;;
+ --ohos-qemu)
+ OHOS_QEMU="${2}"
+ shift; shift
+ ;;
+ --ohos-qemu-sysroot)
+ OHOS_QEMU_SYSROOT="${2}"
+ shift; shift
+ ;;
+ --ohos-hdc)
+ HDC="${2}"
+ export HDC
+ shift; shift
+ ;;
*)
BUILDER="${1}"
shift
@@ -193,8 +216,18 @@ function setup-ohos-hdc-env() {
OHOS_TARGET_TRIPLE="${OHOS_TARGET_TRIPLE:=aarch64-linux-ohos}"
OHOS_LIBCXX_ABI_NAMESPACE="${OHOS_LIBCXX_ABI_NAMESPACE:=__h}"
- OHOS_EXECUTOR="${MONOREPO_ROOT}/libcxx/utils/ci/vendor/ohos/hdc_run.py"
- OHOS_LIT_PARAMS="executor=${OHOS_EXECUTOR};target_triple=${OHOS_TARGET_TRIPLE}"
+ OHOS_QEMU="${OHOS_QEMU:-${QEMU:-}}"
+
+ if [[ -n "${OHOS_QEMU}" ]]; then
+ OHOS_QEMU_SYSROOT="${OHOS_QEMU_SYSROOT:-${QEMU_SYSROOT:-${OHOS_SYSROOT}}}"
+ OHOS_EXECUTOR="${MONOREPO_ROOT}/libcxx/utils/ci/vendor/ohos/qemu_run.py --qemu ${OHOS_QEMU} --sysroot ${OHOS_QEMU_SYSROOT}"
+ OHOS_EXECUTOR_KIND="ohos-qemu"
+ else
+ OHOS_EXECUTOR="${MONOREPO_ROOT}/libcxx/utils/ci/vendor/ohos/hdc_run.py"
+ OHOS_EXECUTOR_KIND="ohos-hdc"
+ fi
+
+ OHOS_LIT_PARAMS="executor=${OHOS_EXECUTOR};target_triple=${OHOS_TARGET_TRIPLE};executor_kind=${OHOS_EXECUTOR_KIND}"
}
function generate-cmake-ohos-hdc() {
@@ -863,14 +896,14 @@ android-ndk-*)
step "Running the libc++abi tests"
ninja -vC "${BUILD_DIR}" check-cxxabi
;;
-ohos-hdc-aarch64-full)
+ohos-aarch64-full|ohos-hdc-aarch64-full)
clean
generate-cmake-ohos-hdc
check-runtimes
;;
-ohos-hdc-aarch64-smoke)
+ohos-aarch64-smoke|ohos-hdc-aarch64-smoke)
clean
generate-cmake-ohos-hdc
diff --git a/libcxx/utils/ci/vendor/ohos/qemu_run.py b/libcxx/utils/ci/vendor/ohos/qemu_run.py
new file mode 100755
index 0000000000000..ef7eef7872864
--- /dev/null
+++ b/libcxx/utils/ci/vendor/ohos/qemu_run.py
@@ -0,0 +1,144 @@
+#!/usr/bin/env python3
+# ===----------------------------------------------------------------------===##
+#
+# 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
+#
+# ===----------------------------------------------------------------------===##
+
+import argparse
+import os
+from pathlib import Path
+import shutil
+import subprocess
+import sys
+
+
+def _parse_kv(items):
+ result = {}
+ for item in items:
+ key, value = item.split("=", 1)
+ result[key] = value
+ return result
+
+
+def _resolve_binary(binary):
+ if os.path.isabs(binary):
+ if os.path.isfile(binary) and os.access(binary, os.X_OK):
+ return binary
+ sys.exit(f"failed to find executable: {binary}")
+
+ resolved = shutil.which(binary)
+ if resolved is None:
+ sys.exit(f"failed to find executable: {binary}")
+ return resolved
+
+
+def _find_build_root(execdir):
+ current = Path(execdir).resolve()
+ for candidate in [current, *current.parents]:
+ if (candidate / "CMakeCache.txt").exists():
+ return candidate
+ return None
+
+
+def _collect_build_library_dirs(execdir):
+ build_root = _find_build_root(execdir)
+ if build_root is None:
+ return []
+
+ lib_root = build_root / "lib"
+ if not lib_root.is_dir():
+ return []
+
+ library_dirs = []
+ seen = set()
+ for lib in sorted(lib_root.rglob("*.so*")):
+ if not lib.is_file():
+ continue
+ parent = lib.parent.resolve()
+ key = str(parent)
+ if key in seen:
+ continue
+ seen.add(key)
+ library_dirs.append(str(parent))
+ return library_dirs
+
+
+def _build_target_env_args(env, prepend_env):
+ target_env = dict(env)
+
+ for key, value in prepend_env.items():
+ existing = target_env.get(key, os.environ.get(key, ""))
+ target_env[key] = f"{value}{os.pathsep}{existing}" if existing else value
+
+ args = []
+ for key, value in target_env.items():
+ args.extend(["-E", f"{key}={value}"])
+ return args
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ "--qemu",
+ default=os.environ.get("OHOS_QEMU", os.environ.get("QEMU", "qemu-aarch64")),
+ )
+ parser.add_argument("--sysroot", required=True)
+ parser.add_argument("--execdir", required=True)
+ parser.add_argument(
+ "--timeout-seconds",
+ type=int,
+ default=int(
+ os.environ.get(
+ "OHOS_QEMU_TIMEOUT_SECONDS",
+ os.environ.get("QEMU_TIMEOUT_SECONDS", "600"),
+ )
+ ),
+ )
+ parser.add_argument("--env", nargs="*", default=[])
+ parser.add_argument("--prepend_env", nargs="*", default=[])
+ parser.add_argument("command", nargs=argparse.ONE_OR_MORE)
+ args = parser.parse_args()
+
+ qemu = _resolve_binary(args.qemu)
+ execdir = Path(args.execdir).resolve()
+ env = _parse_kv(args.env)
+ prepend_env = _parse_kv(args.prepend_env)
+
+ build_library_dirs = _collect_build_library_dirs(execdir)
+ if build_library_dirs:
+ existing = prepend_env.get("LD_LIBRARY_PATH")
+ build_library_path = os.pathsep.join(build_library_dirs)
+ prepend_env["LD_LIBRARY_PATH"] = (
+ f"{build_library_path}{os.pathsep}{existing}"
+ if existing
+ else build_library_path
+ )
+
+ cmd = [
+ qemu,
+ "-L",
+ args.sysroot,
+ *_build_target_env_args(env, prepend_env),
+ *args.command,
+ ]
+ try:
+ completed = subprocess.run(
+ cmd,
+ cwd=execdir,
+ timeout=args.timeout_seconds,
+ check=False,
+ )
+ except subprocess.TimeoutExpired:
+ print(
+ f"qemu executor timed out after {args.timeout_seconds}s: {' '.join(args.command)}",
+ file=sys.stderr,
+ )
+ return 124
+ return completed.returncode
+
+
+if __name__ == "__main__":
+ raise SystemExit(main())
diff --git a/libcxxabi/test/configs/llvm-libc++abi-ohos.cfg.in b/libcxxabi/test/configs/llvm-libc++abi-ohos.cfg.in
index d18748fe3a3cc..8f5a17b3dec64 100644
--- a/libcxxabi/test/configs/llvm-libc++abi-ohos.cfg.in
+++ b/libcxxabi/test/configs/llvm-libc++abi-ohos.cfg.in
@@ -1,5 +1,5 @@
# This testing configuration handles running the test suite against LLVM's
-# libc++abi using HDC on OHOS.
+# libc++abi using HDC or QEMU on OHOS.
lit_config.load_config(config, '@CMAKE_CURRENT_BINARY_DIR@/cmake-bridge.cfg')
@@ -20,7 +20,11 @@ import os, site
site.addsitedir(os.path.join('@LIBCXXABI_LIBCXX_PATH@', 'utils'))
import libcxx.test.params, libcxx.test.config
-config.available_features.add('ohos-hdc')
+executor_kind = lit_config.params.get('executor_kind', 'ohos-hdc')
+if executor_kind not in ('ohos-hdc', 'ohos-qemu'):
+ lit_config.fatal(f'unsupported OHOS executor_kind: {executor_kind}')
+
+config.available_features.add(executor_kind)
libcxx.test.config.configure(
libcxx.test.params.DEFAULT_PARAMETERS,
diff --git a/libunwind/test/configs/llvm-libunwind-ohos.cfg.in b/libunwind/test/configs/llvm-libunwind-ohos.cfg.in
index bce241a7898cf..f2a032c41a123 100644
--- a/libunwind/test/configs/llvm-libunwind-ohos.cfg.in
+++ b/libunwind/test/configs/llvm-libunwind-ohos.cfg.in
@@ -1,6 +1,6 @@
#
# Configuration file for running the libunwind tests against the shared library
-# using HDC on OHOS.
+# using HDC or QEMU on OHOS.
#
lit_config.load_config(config, '@CMAKE_CURRENT_BINARY_DIR@/cmake-bridge.cfg')
@@ -45,7 +45,11 @@ import os, site
site.addsitedir(os.path.join('@LIBUNWIND_LIBCXX_PATH@', 'utils'))
import libcxx.test.params, libcxx.test.config
-config.available_features.add('ohos-hdc')
+executor_kind = lit_config.params.get('executor_kind', 'ohos-hdc')
+if executor_kind not in ('ohos-hdc', 'ohos-qemu'):
+ lit_config.fatal(f'unsupported OHOS executor_kind: {executor_kind}')
+
+config.available_features.add(executor_kind)
libcxx.test.config.configure(
libcxx.test.params.DEFAULT_PARAMETERS,
>From dde4d430033711fb7ffa87621ba86b37492f480b Mon Sep 17 00:00:00 2001
From: hu1hu1 <fanyaohui at huawei.com>
Date: Thu, 9 Jul 2026 14:52:40 +0800
Subject: [PATCH 5/6] Fix something for qemu
---
libcxx/test/configs/llvm-libc++-ohos.cfg.in | 4 +++-
.../file.streams/fstreams/filebuf.members/close.pass.cpp | 3 +++
.../fs.op.funcs/fs.op.copy_file/copy_file_procfs.pass.cpp | 2 ++
.../syncstream/osyncstream/thread/several_threads.pass.cpp | 2 ++
libcxxabi/test/configs/llvm-libc++abi-ohos.cfg.in | 4 +++-
libcxxabi/test/guard_threaded_test.pass.cpp | 2 ++
libunwind/test/bad_unwind_info.pass.cpp | 2 ++
libunwind/test/configs/llvm-libunwind-ohos.cfg.in | 4 +++-
libunwind/test/signal_unwind.pass.cpp | 2 ++
9 files changed, 22 insertions(+), 3 deletions(-)
diff --git a/libcxx/test/configs/llvm-libc++-ohos.cfg.in b/libcxx/test/configs/llvm-libc++-ohos.cfg.in
index 20aa7a49d5802..3be1c267ede2a 100644
--- a/libcxx/test/configs/llvm-libc++-ohos.cfg.in
+++ b/libcxx/test/configs/llvm-libc++-ohos.cfg.in
@@ -23,7 +23,9 @@ import os, site
site.addsitedir(os.path.join('@LIBCXX_SOURCE_DIR@', 'utils'))
import libcxx.test.params, libcxx.test.config
-executor_kind = lit_config.params.get('executor_kind', 'ohos-hdc')
+executor_kind = lit_config.params.get(
+ 'executor_kind', getattr(config, 'executor_kind', 'ohos-hdc')
+)
if executor_kind not in ('ohos-hdc', 'ohos-qemu'):
lit_config.fatal(f'unsupported OHOS executor_kind: {executor_kind}')
diff --git a/libcxx/test/std/input.output/file.streams/fstreams/filebuf.members/close.pass.cpp b/libcxx/test/std/input.output/file.streams/fstreams/filebuf.members/close.pass.cpp
index 43233decf1b34..fd6abca7c4fe1 100644
--- a/libcxx/test/std/input.output/file.streams/fstreams/filebuf.members/close.pass.cpp
+++ b/libcxx/test/std/input.output/file.streams/fstreams/filebuf.members/close.pass.cpp
@@ -6,6 +6,9 @@
//
//===----------------------------------------------------------------------===//
+// OHOS qemu-user does not match device fd ownership/signal behavior here.
+// UNSUPPORTED: ohos-qemu
+
// <fstream>
// basic_filebuf<charT,traits>* close();
diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.copy_file/copy_file_procfs.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.copy_file/copy_file_procfs.pass.cpp
index 2c4cfb0ac7661..ce802d6ceba78 100644
--- a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.copy_file/copy_file_procfs.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.copy_file/copy_file_procfs.pass.cpp
@@ -9,6 +9,8 @@
// UNSUPPORTED: c++03, c++11, c++14
// REQUIRES: linux
// UNSUPPORTED: no-filesystem
+// OHOS qemu-user observes the host /proc, not a real OHOS process /proc.
+// UNSUPPORTED: ohos-qemu
// XFAIL: no-localization
// <filesystem>
diff --git a/libcxx/test/std/input.output/syncstream/osyncstream/thread/several_threads.pass.cpp b/libcxx/test/std/input.output/syncstream/osyncstream/thread/several_threads.pass.cpp
index dbf2ded1b532e..77db6396755bf 100644
--- a/libcxx/test/std/input.output/syncstream/osyncstream/thread/several_threads.pass.cpp
+++ b/libcxx/test/std/input.output/syncstream/osyncstream/thread/several_threads.pass.cpp
@@ -10,6 +10,8 @@
// UNSUPPORTED: no-localization
// UNSUPPORTED: no-threads
// UNSUPPORTED: libcpp-has-no-experimental-syncstream
+// This thread-heavy stress test is prohibitively slow under OHOS qemu-user.
+// UNSUPPORTED: ohos-qemu
// <syncstream>
diff --git a/libcxxabi/test/configs/llvm-libc++abi-ohos.cfg.in b/libcxxabi/test/configs/llvm-libc++abi-ohos.cfg.in
index 8f5a17b3dec64..d0a8d1248f88a 100644
--- a/libcxxabi/test/configs/llvm-libc++abi-ohos.cfg.in
+++ b/libcxxabi/test/configs/llvm-libc++abi-ohos.cfg.in
@@ -20,7 +20,9 @@ import os, site
site.addsitedir(os.path.join('@LIBCXXABI_LIBCXX_PATH@', 'utils'))
import libcxx.test.params, libcxx.test.config
-executor_kind = lit_config.params.get('executor_kind', 'ohos-hdc')
+executor_kind = lit_config.params.get(
+ 'executor_kind', getattr(config, 'executor_kind', 'ohos-hdc')
+)
if executor_kind not in ('ohos-hdc', 'ohos-qemu'):
lit_config.fatal(f'unsupported OHOS executor_kind: {executor_kind}')
diff --git a/libcxxabi/test/guard_threaded_test.pass.cpp b/libcxxabi/test/guard_threaded_test.pass.cpp
index d898e60288aca..a4e14f0aca9e4 100644
--- a/libcxxabi/test/guard_threaded_test.pass.cpp
+++ b/libcxxabi/test/guard_threaded_test.pass.cpp
@@ -9,6 +9,8 @@
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
// UNSUPPORTED: no-threads
// UNSUPPORTED: no-exceptions
+// This thread-heavy guard stress test is prohibitively slow under OHOS qemu-user.
+// UNSUPPORTED: ohos-qemu
#define TESTING_CXA_GUARD
#include "../src/cxa_guard_impl.h"
diff --git a/libunwind/test/bad_unwind_info.pass.cpp b/libunwind/test/bad_unwind_info.pass.cpp
index 332b661d2e98f..76102505f2d67 100644
--- a/libunwind/test/bad_unwind_info.pass.cpp
+++ b/libunwind/test/bad_unwind_info.pass.cpp
@@ -13,6 +13,8 @@
// REQUIRES: target={{(aarch64|s390x|x86_64)-.+}}
// UNSUPPORTED: target={{.*-windows.*}}
// UNSUPPORTED: target={{.*-apple.*}}
+// OHOS qemu-user does not reliably model this invalid unwind-info path.
+// UNSUPPORTED: ohos-qemu
// GCC doesn't support __attribute__((naked)) on AArch64.
// UNSUPPORTED: gcc
diff --git a/libunwind/test/configs/llvm-libunwind-ohos.cfg.in b/libunwind/test/configs/llvm-libunwind-ohos.cfg.in
index f2a032c41a123..71d1e711e36d5 100644
--- a/libunwind/test/configs/llvm-libunwind-ohos.cfg.in
+++ b/libunwind/test/configs/llvm-libunwind-ohos.cfg.in
@@ -45,7 +45,9 @@ import os, site
site.addsitedir(os.path.join('@LIBUNWIND_LIBCXX_PATH@', 'utils'))
import libcxx.test.params, libcxx.test.config
-executor_kind = lit_config.params.get('executor_kind', 'ohos-hdc')
+executor_kind = lit_config.params.get(
+ 'executor_kind', getattr(config, 'executor_kind', 'ohos-hdc')
+)
if executor_kind not in ('ohos-hdc', 'ohos-qemu'):
lit_config.fatal(f'unsupported OHOS executor_kind: {executor_kind}')
diff --git a/libunwind/test/signal_unwind.pass.cpp b/libunwind/test/signal_unwind.pass.cpp
index f8798bc3eabeb..ef73a3ea8c59a 100644
--- a/libunwind/test/signal_unwind.pass.cpp
+++ b/libunwind/test/signal_unwind.pass.cpp
@@ -10,6 +10,8 @@
// Ensure that the unwinder can cope with the signal handler.
// REQUIRES: target={{(aarch64|loongarch64|riscv64|s390x|x86_64)-.+}}
// UNSUPPORTED: target={{.*-windows.*}}
+// OHOS qemu-user does not provide device-equivalent signal unwinding behavior.
+// UNSUPPORTED: ohos-qemu
// TODO: Figure out why this fails with Memory Sanitizer.
// XFAIL: msan
>From c81df7252fb00b5b9b41f0a29393e775abc9c810 Mon Sep 17 00:00:00 2001
From: hu1hu1 <fanyaohui at huawei.com>
Date: Thu, 9 Jul 2026 15:19:29 +0800
Subject: [PATCH 6/6] delete run-smoke-test
---
libcxx/utils/ci/buildkite-pipeline.yml | 12 ----------
libcxx/utils/ci/run-buildbot | 31 --------------------------
2 files changed, 43 deletions(-)
diff --git a/libcxx/utils/ci/buildkite-pipeline.yml b/libcxx/utils/ci/buildkite-pipeline.yml
index 77617f43ae6dc..70bc69637a7f2 100644
--- a/libcxx/utils/ci/buildkite-pipeline.yml
+++ b/libcxx/utils/ci/buildkite-pipeline.yml
@@ -175,18 +175,6 @@ steps:
- group: OHOS
steps:
- - label: OHOS AArch64 HDC Smoke
- command: libcxx/utils/ci/run-buildbot ohos-hdc-aarch64-smoke
- env:
- CC: clang
- CXX: clang++
- OHOS_TARGET_TRIPLE: aarch64-linux-ohos
- HDC_TIMEOUT_SECONDS: 240
- agents:
- queue: libcxx-builders
- os: linux
- device: ohos-hdc
- <<: *common
- label: OHOS AArch64 HDC Full
command: libcxx/utils/ci/run-buildbot ohos-hdc-aarch64-full
env:
diff --git a/libcxx/utils/ci/run-buildbot b/libcxx/utils/ci/run-buildbot
index 40739b0fba4d8..e7d751df484e4 100755
--- a/libcxx/utils/ci/run-buildbot
+++ b/libcxx/utils/ci/run-buildbot
@@ -147,23 +147,6 @@ function require-env-var() {
fi
}
-function detect-lit() {
- if [[ -x "${BUILD_DIR}/bin/llvm-lit" ]]; then
- LIT_RUNNER=("${BUILD_DIR}/bin/llvm-lit")
- elif command -v llvm-lit >/dev/null 2>&1; then
- LIT_RUNNER=("$(command -v llvm-lit)")
- else
- LIT_RUNNER=(python3 "${MONOREPO_ROOT}/llvm/utils/lit/lit.py")
- fi
-}
-
-function run-smoke-test() {
- local test_dir="${1}"
- local filter="${2}"
- step "Running smoke test ${filter}"
- "${LIT_RUNNER[@]}" -j1 -sv --show-xfail --show-unsupported --filter="${filter}" "${test_dir}"
-}
-
function ohos-lit-args() {
local args="-j1 -sv --xunit-xml-output test-results.xml --time-tests"
if python3 -c 'import psutil' >/dev/null 2>&1; then
@@ -903,20 +886,6 @@ ohos-aarch64-full|ohos-hdc-aarch64-full)
check-runtimes
;;
-ohos-aarch64-smoke|ohos-hdc-aarch64-smoke)
- clean
-
- generate-cmake-ohos-hdc
-
- step "Building the OHOS smoke test dependencies"
- ninja -vC "${BUILD_DIR}" cxx-test-depends cxxabi-test-depends unwind-test-depends
-
- detect-lit
- run-smoke-test "${BUILD_DIR}/libcxxabi/test" 'thread_local_destruction_order.pass.cpp'
- run-smoke-test "${BUILD_DIR}/libunwind/test" 'bad_unwind_info.pass.cpp'
- run-smoke-test "${BUILD_DIR}/libunwind/test" 'signal_unwind.pass.cpp'
- run-smoke-test "${BUILD_DIR}/libcxx/test" 'clocale.pass.cpp'
-;;
#################################################################
# Insert vendor-specific internal configurations below.
#
More information about the cfe-commits
mailing list