[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