[libc-commits] [libc] e8802ef - [libc][test] Condition out tests that can't work on bare metal (#215830)
via libc-commits
libc-commits at lists.llvm.org
Mon Aug 17 05:06:56 PDT 2026
Author: Simon Tatham
Date: 2026-08-17T13:06:50+01:00
New Revision: e8802ef063617cd473cb0b47dd25b2fccfd2eea8
URL: https://github.com/llvm/llvm-project/commit/e8802ef063617cd473cb0b47dd25b2fccfd2eea8
DIFF: https://github.com/llvm/llvm-project/commit/e8802ef063617cd473cb0b47dd25b2fccfd2eea8.diff
LOG: [libc][test] Condition out tests that can't work on bare metal (#215830)
In bare-metal builds of libc, the `EXPECT_DEATH` macro may not be
defined. Also, `signal-macros.h` may not define the values needed for
the rest of `<signal.h>` to work. So tests that rely on either of those
things will fail to compile.
I've conditioned out the `EXPECT_DEATH` tests completely if
`EXPECT_DEATH` isn't defined. There's inherently no reliable way to
define it: you can't rely on finding out about segmentation faults by a
signal, because accessing memory outside valid C objects might silently
succeed (valid unused memory), or generate a CPU fault that no kernel
traps for you, or overwrite something important outside your program.
The check for signals in `FPExceptMatcher.cpp` can be more lenient, and
just condition out the signal-handling code, leaving the test of
cumulative FP exception flags in place, so that the checker simply
returns "no signal was caught" unconditionally.
Added:
Modified:
libc/test/UnitTest/CMakeLists.txt
libc/test/UnitTest/FPExceptMatcher.cpp
libc/test/UnitTest/LibcTest.h
Removed:
################################################################################
diff --git a/libc/test/UnitTest/CMakeLists.txt b/libc/test/UnitTest/CMakeLists.txt
index afb943acc5c62..fa7f374726055 100644
--- a/libc/test/UnitTest/CMakeLists.txt
+++ b/libc/test/UnitTest/CMakeLists.txt
@@ -23,6 +23,22 @@ function(add_unittest_framework_library name)
if(TARGET libc.src.time.clock)
target_compile_definitions(${lib} PRIVATE TARGET_SUPPORTS_CLOCK)
endif()
+
+ # Find out if the target supports catching signals.
+ if(NOT LLVM_LIBC_FULL_BUILD)
+ # In an overlay build of libc, assume signal.h is available: the host
+ # libc will provide it even if we don't.
+ set(no_signal FALSE)
+ elseif(TARGET libc.src.signal.signal)
+ # In a full build, signal.h only exists if we provide it ourselves, which
+ # we might not on bare metal.
+ get_target_property(no_signal libc.src.signal.signal SKIPPED)
+ else()
+ set(no_signal TRUE)
+ endif()
+ if(NOT no_signal)
+ target_compile_definitions(${lib} PRIVATE TARGET_SUPPORTS_SIGNAL_CATCHING)
+ endif()
endforeach()
if(LLVM_LIBC_FULL_BUILD)
diff --git a/libc/test/UnitTest/FPExceptMatcher.cpp b/libc/test/UnitTest/FPExceptMatcher.cpp
index 10b6ff9f91da1..6da21a279ff3d 100644
--- a/libc/test/UnitTest/FPExceptMatcher.cpp
+++ b/libc/test/UnitTest/FPExceptMatcher.cpp
@@ -20,7 +20,9 @@
#include "hdr/types/fenv_t.h"
#include "src/__support/FPUtil/FEnvImpl.h"
#include <setjmp.h>
+#if TARGET_SUPPORTS_SIGNAL_CATCHING
#include <signal.h>
+#endif
#if LIBC_TEST_HAS_MATCHERS()
@@ -33,31 +35,38 @@ namespace testing {
#define siglongjmp(buf, val) longjmp(buf, val)
#endif
-#ifdef __FreeBSD__
-using sighandler_t = __sighandler_t *;
-#endif
+static thread_local bool caughtExcept;
+
+#if TARGET_SUPPORTS_SIGNAL_CATCHING
static thread_local sigjmp_buf jumpBuffer;
-static thread_local bool caughtExcept;
static void sigfpeHandler([[maybe_unused]] int sig) {
caughtExcept = true;
siglongjmp(jumpBuffer, -1);
}
+#endif // TARGET_SUPPORTS_SIGNAL_CATCHING
+
FPExceptMatcher::FPExceptMatcher(FunctionCaller *func) {
+#if TARGET_SUPPORTS_SIGNAL_CATCHING
auto *oldSIGFPEHandler = signal(SIGFPE, &sigfpeHandler);
+#endif
caughtExcept = false;
fenv_t oldEnv;
fputil::get_env(&oldEnv);
+#if TARGET_SUPPORTS_SIGNAL_CATCHING
if (sigsetjmp(jumpBuffer, 1) == 0)
+#endif
func->call();
delete func;
// We restore the previous floating point environment after
// the call to the function which can potentially raise SIGFPE.
fputil::set_env(&oldEnv);
+#if TARGET_SUPPORTS_SIGNAL_CATCHING
signal(SIGFPE, oldSIGFPEHandler);
+#endif
exceptionRaised = caughtExcept;
}
diff --git a/libc/test/UnitTest/LibcTest.h b/libc/test/UnitTest/LibcTest.h
index 740d08335ab24..2758d3ef83bab 100644
--- a/libc/test/UnitTest/LibcTest.h
+++ b/libc/test/UnitTest/LibcTest.h
@@ -521,6 +521,14 @@ CString libc_make_test_file_path_func(const char *file_name);
#endif // LIBC_TEST_SKIP_DEATH_TESTS
+#else // LIBC_TEST_SUBPROCESS_TESTS
+
+// EXPECT_DEATH can appear in a test of any function, e.g. checking for a crash
+// if passing nullptr to the function. So it must be defined, even if it can't
+// do anything.
+#define EXPECT_DEATH(FUNC, SIG)
+#define ASSERT_DEATH(FUNC, SIG)
+
#endif // LIBC_TEST_SUBPROCESS_TESTS
////////////////////////////////////////////////////////////////////////////////
More information about the libc-commits
mailing list