[libc-commits] [libc] [llvm] [libc] Add a C unit test framework wrapper and convert existing tests (PR #213657)

Pavel Labath via libc-commits libc-commits at lists.llvm.org
Mon Aug 3 05:54:39 PDT 2026


https://github.com/labath updated https://github.com/llvm/llvm-project/pull/213657

>From cddc2b450a9ce82636f236db506acf071e90e4fc Mon Sep 17 00:00:00 2001
From: Pavel Labath <pavel at labath.sk>
Date: Mon, 3 Aug 2026 12:20:04 +0000
Subject: [PATCH 1/3] [libc] Add a C unit test framework wrapper and convert
 existing tests

This removes the dependency on the host C library (hermetic tests), makes sure
the tests actually do something in release builds (where assert() is a noop),
and makes better and more consistent failure messages.

This is just a thin wrapper over the existing framework which repackages the C++
interface into something consumable by C code. I tried to keep the interface
consistent, but of course, many of the framework features are C++ only.

The main trick here was getting the static library linker to extract
LibcCTest.cpp.o from libLibcTest.unit.a. Since C test cases don't instantiate
static CTest objects in their own translation unit like C++ tests do (which they
cannot do portably), nothing in the object file referenced LibcCTest.cpp.  I
made this work by introducing libc_c_test_anchor() and calling it explicitly
inside the generated libc_c_test_run() function.
---
 libc/cmake/modules/LLVMLibCTestRules.cmake |  3 +-
 libc/test/UnitTest/CMakeLists.txt          |  2 +
 libc/test/UnitTest/LibcCTest.cpp           | 36 ++++++++++++++
 libc/test/UnitTest/LibcCTest.h             | 56 ++++++++++++++++++++++
 libc/test/include/fpclassify_test.c        | 18 ++++---
 libc/test/include/isfinite_test.c          | 12 ++---
 libc/test/include/isinf_test.c             | 12 ++---
 libc/test/include/isnan_test.c             | 12 ++---
 libc/test/include/isnormal_test.c          | 18 ++++---
 libc/test/include/issubnormal_test.c       | 16 +++----
 libc/test/include/iszero_test.c            | 18 ++++---
 libc/test/include/math_constants_test.c    |  4 +-
 libc/test/include/signbit_test.c           | 18 ++++---
 libc/test/include/stdbit_test.c            | 27 +++++------
 14 files changed, 164 insertions(+), 88 deletions(-)
 create mode 100644 libc/test/UnitTest/LibcCTest.cpp
 create mode 100644 libc/test/UnitTest/LibcCTest.h

diff --git a/libc/cmake/modules/LLVMLibCTestRules.cmake b/libc/cmake/modules/LLVMLibCTestRules.cmake
index 418551f137e44..1abf21dda1249 100644
--- a/libc/cmake/modules/LLVMLibCTestRules.cmake
+++ b/libc/cmake/modules/LLVMLibCTestRules.cmake
@@ -374,8 +374,9 @@ function(create_libc_unittest fq_target_name)
   )
 
   # LibcUnitTest should not depend on anything in LINK_LIBRARIES.
+  list(APPEND link_libraries LibcTest.unit)
   if(NOT LIBC_UNITTEST_C_TEST)
-    list(APPEND link_libraries LibcDeathTestExecutors.unit LibcTest.unit)
+    list(APPEND link_libraries LibcDeathTestExecutors.unit)
   endif()
 
   target_link_libraries(${fq_build_target_name} PRIVATE ${link_libraries})
diff --git a/libc/test/UnitTest/CMakeLists.txt b/libc/test/UnitTest/CMakeLists.txt
index 1732473e355dc..9b244a9003d82 100644
--- a/libc/test/UnitTest/CMakeLists.txt
+++ b/libc/test/UnitTest/CMakeLists.txt
@@ -73,10 +73,12 @@ add_unittest_framework_library(
   LibcTest
   SRCS
     CmakeFilePath.cpp
+    LibcCTest.cpp
     LibcTest.cpp
     LibcTestMain.cpp
     TestLogger.cpp
   HDRS
+    LibcCTest.h
     LibcTest.h
     Test.h
     TestLogger.h
diff --git a/libc/test/UnitTest/LibcCTest.cpp b/libc/test/UnitTest/LibcCTest.cpp
new file mode 100644
index 0000000000000..4436fa937e7f6
--- /dev/null
+++ b/libc/test/UnitTest/LibcCTest.cpp
@@ -0,0 +1,36 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Helpers for libc C unittests.
+///
+//===----------------------------------------------------------------------===//
+
+#include "test/UnitTest/LibcCTest.h"
+#include "test/UnitTest/LibcTest.h"
+
+namespace {
+class CTest : public LIBC_NAMESPACE::testing::Test {
+public:
+  CTest() { addTest(this); }
+  void Run() override { libc_c_test_run(); }
+  const char *getName() const override { return LIBC_C_TEST_NAME; }
+};
+} // namespace
+
+static CTest c_test_instance;
+
+extern "C" void libc_c_test_anchor() {}
+
+extern "C" void libc_c_test_fail(const char *cond, int expected,
+                                   const char *file, int line) {
+  LIBC_NAMESPACE::testing::internal::test(
+      LIBC_NAMESPACE::testing::TestCond::EQ, !expected,
+      static_cast<bool>(expected), cond, expected ? "true" : "false",
+      LIBC_NAMESPACE::testing::internal::Location(file, line));
+}
diff --git a/libc/test/UnitTest/LibcCTest.h b/libc/test/UnitTest/LibcCTest.h
new file mode 100644
index 0000000000000..c0cd1b91e4088
--- /dev/null
+++ b/libc/test/UnitTest/LibcCTest.h
@@ -0,0 +1,56 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// C wrappers for libc unittests
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_TEST_UNITTEST_LIBCCTEST_H
+#define LLVM_LIBC_TEST_UNITTEST_LIBCCTEST_H
+
+#include "include/__llvm-libc-common.h"
+
+__BEGIN_C_DECLS
+
+// These symbols are implementation details of the test macros. Do not reference
+// them directly.
+void libc_c_test_fail(const char *cond, int expected, const char *file,
+                      int line);
+extern const char LIBC_C_TEST_NAME[];
+void libc_c_test_run(void);
+void libc_c_test_anchor(void);
+
+__END_C_DECLS
+
+// Use LibcTest.h in C++ code.
+#ifndef __cplusplus
+#define TEST(name)                                                             \
+  const char LIBC_C_TEST_NAME[] = "LlvmLibcCTest." #name;                      \
+  void libc_c_test_run_impl(void);                                             \
+  void libc_c_test_run(void) {                                                 \
+    libc_c_test_anchor(); /* Force a reference to the C test framework. */     \
+    libc_c_test_run_impl();                                                    \
+  }                                                                            \
+  void libc_c_test_run_impl(void)
+#define LIBC_C_TEST_SCAFFOLDING_(cond, expected, ret_or_empty)                 \
+  do {                                                                         \
+    if (!(cond) != !(expected)) {                                              \
+      libc_c_test_fail(#cond, (expected), __FILE__, __LINE__);                 \
+      ret_or_empty;                                                            \
+    }                                                                          \
+  } while (0)
+
+#define EXPECT_TRUE(cond)  LIBC_C_TEST_SCAFFOLDING_(cond, 1, )
+#define ASSERT_TRUE(cond)  LIBC_C_TEST_SCAFFOLDING_(cond, 1, return)
+
+#define EXPECT_FALSE(cond) LIBC_C_TEST_SCAFFOLDING_(cond, 0, )
+#define ASSERT_FALSE(cond) LIBC_C_TEST_SCAFFOLDING_(cond, 0, return)
+#endif
+
+#endif // LLVM_LIBC_TEST_UNITTEST_LIBCCTEST_H
diff --git a/libc/test/include/fpclassify_test.c b/libc/test/include/fpclassify_test.c
index d52d999301115..4717e1e583353 100644
--- a/libc/test/include/fpclassify_test.c
+++ b/libc/test/include/fpclassify_test.c
@@ -6,20 +6,18 @@
 //
 //===----------------------------------------------------------------------===//
 #include "include/llvm-libc-macros/math-function-macros.h"
-
-#include <assert.h>
+#include "test/UnitTest/LibcCTest.h"
 
 // check if macro is defined
 #ifndef fpclassify
 #error "fpclassify macro is not defined"
 #else
-int main(void) {
-  assert(fpclassify(1.819f) == FP_NORMAL);
-  assert(fpclassify(-1.726) == FP_NORMAL);
-  assert(fpclassify(1.426L) == FP_NORMAL);
-  assert(fpclassify(-0.0f) == FP_ZERO);
-  assert(fpclassify(0.0) == FP_ZERO);
-  assert(fpclassify(-0.0L) == FP_ZERO);
-  return 0;
+TEST(fpclassify) {
+  EXPECT_TRUE(fpclassify(1.819f) == FP_NORMAL);
+  EXPECT_TRUE(fpclassify(-1.726) == FP_NORMAL);
+  EXPECT_TRUE(fpclassify(1.426L) == FP_NORMAL);
+  EXPECT_TRUE(fpclassify(-0.0f) == FP_ZERO);
+  EXPECT_TRUE(fpclassify(0.0) == FP_ZERO); 
+  EXPECT_TRUE(fpclassify(-0.0L) == FP_ZERO);
 }
 #endif
diff --git a/libc/test/include/isfinite_test.c b/libc/test/include/isfinite_test.c
index 9cc897db7c040..1cece5c9fe605 100644
--- a/libc/test/include/isfinite_test.c
+++ b/libc/test/include/isfinite_test.c
@@ -6,17 +6,15 @@
 //
 //===----------------------------------------------------------------------===//
 #include "include/llvm-libc-macros/math-function-macros.h"
-
-#include <assert.h>
+#include "test/UnitTest/LibcCTest.h"
 
 // check if macro is defined
 #ifndef isfinite
 #error "isfinite macro is not defined"
 #else
-int main(void) {
-  assert(isfinite(1.0f));
-  assert(isfinite(1.0));
-  assert(isfinite(1.0L));
-  return 0;
+TEST(isfinite) {
+  EXPECT_TRUE(isfinite(1.0f));
+  EXPECT_TRUE(isfinite(1.0));
+  EXPECT_TRUE(isfinite(1.0L));
 }
 #endif
diff --git a/libc/test/include/isinf_test.c b/libc/test/include/isinf_test.c
index 7dc6ce5579263..d818c7df66bdc 100644
--- a/libc/test/include/isinf_test.c
+++ b/libc/test/include/isinf_test.c
@@ -6,17 +6,15 @@
 //
 //===----------------------------------------------------------------------===//
 #include "include/llvm-libc-macros/math-function-macros.h"
-
-#include <assert.h>
+#include "test/UnitTest/LibcCTest.h"
 
 // check if macro is defined
 #ifndef isinf
 #error "isinf macro is not defined"
 #else
-int main(void) {
-  assert(!isinf(1.0f));
-  assert(!isinf(1.0));
-  assert(!isinf(1.0L));
-  return 0;
+TEST(isinf) {
+  EXPECT_FALSE(isinf(1.0f));
+  EXPECT_FALSE(isinf(1.0));
+  EXPECT_FALSE(isinf(1.0L));
 }
 #endif
diff --git a/libc/test/include/isnan_test.c b/libc/test/include/isnan_test.c
index 2234c2b2b37ad..137be638c91f2 100644
--- a/libc/test/include/isnan_test.c
+++ b/libc/test/include/isnan_test.c
@@ -6,17 +6,15 @@
 //
 //===----------------------------------------------------------------------===//
 #include "include/llvm-libc-macros/math-function-macros.h"
-
-#include <assert.h>
+#include "test/UnitTest/LibcCTest.h"
 
 // check if macro is defined
 #ifndef isnan
 #error "isnan macro is not defined"
 #else
-int main(void) {
-  assert(!isnan(1.0f));
-  assert(!isnan(1.0));
-  assert(!isnan(1.0L));
-  return 0;
+TEST(isnan) {
+  EXPECT_FALSE(isnan(1.0f));
+  EXPECT_FALSE(isnan(1.0));
+  EXPECT_FALSE(isnan(1.0L));
 }
 #endif
diff --git a/libc/test/include/isnormal_test.c b/libc/test/include/isnormal_test.c
index 9f576d5cb0713..7d3df67fe3593 100644
--- a/libc/test/include/isnormal_test.c
+++ b/libc/test/include/isnormal_test.c
@@ -6,20 +6,18 @@
 //
 //===----------------------------------------------------------------------===//
 #include "include/llvm-libc-macros/math-function-macros.h"
-
-#include <assert.h>
+#include "test/UnitTest/LibcCTest.h"
 
 // check if macro is defined
 #ifndef isnormal
 #error "isnormal macro is not defined"
 #else
-int main(void) {
-  assert(isnormal(1.819f) == 1);
-  assert(isnormal(-1.726) == 1);
-  assert(isnormal(1.426L) == 1);
-  assert(isnormal(-0.0f) == 0);
-  assert(isnormal(0.0) == 0);
-  assert(isnormal(-0.0L) == 0);
-  return 0;
+TEST(isnormal) {
+  EXPECT_TRUE(isnormal(1.819f) == 1);
+  EXPECT_TRUE(isnormal(-1.726) == 1);
+  EXPECT_TRUE(isnormal(1.426L) == 1);
+  EXPECT_TRUE(isnormal(-0.0f) == 0);
+  EXPECT_TRUE(isnormal(0.0) == 0);
+  EXPECT_TRUE(isnormal(-0.0L) == 0);
 }
 #endif
diff --git a/libc/test/include/issubnormal_test.c b/libc/test/include/issubnormal_test.c
index b5dea843bce89..ccaee8081ea0f 100644
--- a/libc/test/include/issubnormal_test.c
+++ b/libc/test/include/issubnormal_test.c
@@ -6,19 +6,17 @@
 //
 //===----------------------------------------------------------------------===//
 #include "include/llvm-libc-macros/math-function-macros.h"
-
-#include <assert.h>
+#include "test/UnitTest/LibcCTest.h"
 
 // check if macro is defined
 #ifndef issubnormal
 #error "issubnormal macro is not defined"
 #else
-int main(void) {
-  assert(issubnormal(1.819f) == 0);
-  assert(issubnormal(-1.726) == 0);
-  assert(issubnormal(1.426L) == 0);
-  assert(issubnormal(1e-308) == 1);
-  assert(issubnormal(-1e-308) == 1);
-  return 0;
+TEST(issubnormal) {
+  EXPECT_TRUE(issubnormal(1.819f) == 0);
+  EXPECT_TRUE(issubnormal(-1.726) == 0);
+  EXPECT_TRUE(issubnormal(1.426L) == 0);
+  EXPECT_TRUE(issubnormal(1e-308) == 1);
+  EXPECT_TRUE(issubnormal(-1e-308) == 1);
 }
 #endif
diff --git a/libc/test/include/iszero_test.c b/libc/test/include/iszero_test.c
index daffde50cdff5..0baee520f345a 100644
--- a/libc/test/include/iszero_test.c
+++ b/libc/test/include/iszero_test.c
@@ -6,20 +6,18 @@
 //
 //===----------------------------------------------------------------------===//
 #include "include/llvm-libc-macros/math-function-macros.h"
-
-#include <assert.h>
+#include "test/UnitTest/LibcCTest.h"
 
 // check if macro is defined
 #ifndef iszero
 #error "iszero macro is not defined"
 #else
-int main(void) {
-  assert(iszero(1.0f) == 0);
-  assert(iszero(1.0) == 0);
-  assert(iszero(1.0L) == 0);
-  assert(iszero(0.0f) == 1);
-  assert(iszero(0.0) == 1);
-  assert(iszero(0.0L) == 1);
-  return 0;
+TEST(iszero) {
+  EXPECT_TRUE(iszero(1.0f) == 0);
+  EXPECT_TRUE(iszero(1.0) == 0);
+  EXPECT_TRUE(iszero(1.0L) == 0);
+  EXPECT_TRUE(iszero(0.0f) == 1);
+  EXPECT_TRUE(iszero(0.0) == 1);
+  EXPECT_TRUE(iszero(0.0L) == 1);
 }
 #endif
diff --git a/libc/test/include/math_constants_test.c b/libc/test/include/math_constants_test.c
index eb497a9d8a50a..ae043aa9e3648 100644
--- a/libc/test/include/math_constants_test.c
+++ b/libc/test/include/math_constants_test.c
@@ -6,6 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 #include "include/llvm-libc-macros/math-macros.h"
+#include "test/UnitTest/LibcCTest.h"
 
 #define IS_DOUBLE(X) _Generic((X), double: 1, default: 0)
 
@@ -15,9 +16,8 @@
 #ifndef M_PI
 #error "M_PI macro is not defined"
 #else
-int main(void) {
+TEST(math_constants) {
   _Static_assert(IS_DOUBLE(M_PI), "M_PI is not of double type.");
   _Static_assert(IS_FLOAT(M_PIf), "M_PIf is not of float type.");
-  return 0;
 }
 #endif
diff --git a/libc/test/include/signbit_test.c b/libc/test/include/signbit_test.c
index 2f25624ea8026..81702260ab476 100644
--- a/libc/test/include/signbit_test.c
+++ b/libc/test/include/signbit_test.c
@@ -6,20 +6,18 @@
 //
 //===----------------------------------------------------------------------===//
 #include "include/llvm-libc-macros/math-function-macros.h"
-
-#include <assert.h>
+#include "test/UnitTest/LibcCTest.h"
 
 // check if macro is defined
 #ifndef signbit
 #error "signbit macro is not defined"
 #else
-int main(void) {
-  assert(!signbit(1.0f));
-  assert(!signbit(1.0));
-  assert(!signbit(1.0L));
-  assert(signbit(-1.0f));
-  assert(signbit(-1.0));
-  assert(signbit(-1.0L));
-  return 0;
+TEST(signbit) {
+  EXPECT_FALSE(signbit(1.0f));
+  EXPECT_FALSE(signbit(1.0));
+  EXPECT_FALSE(signbit(1.0L));
+  EXPECT_TRUE(signbit(-1.0f));
+  EXPECT_TRUE(signbit(-1.0));
+  EXPECT_TRUE(signbit(-1.0L));
 }
 #endif
diff --git a/libc/test/include/stdbit_test.c b/libc/test/include/stdbit_test.c
index 207609ee1dd00..3f444ec70b229 100644
--- a/libc/test/include/stdbit_test.c
+++ b/libc/test/include/stdbit_test.c
@@ -23,19 +23,18 @@
 #include "stdbit_stub.h"
 
 #include "include/llvm-libc-macros/stdbit-macros.h"
-
-#include <assert.h>
+#include "test/UnitTest/LibcCTest.h"
 
 #define CHECK_FUNCTION(FUNC_NAME, VAL)                                         \
   do {                                                                         \
-    assert(FUNC_NAME((unsigned char)0U) == VAL##AU);                           \
-    assert(FUNC_NAME((unsigned short)0U) == VAL##BU);                          \
-    assert(FUNC_NAME(0U) == VAL##CU);                                          \
-    assert(FUNC_NAME(0UL) == VAL##DU);                                         \
-    assert(FUNC_NAME(0ULL) == VAL##EU);                                        \
+    EXPECT_TRUE(FUNC_NAME((unsigned char)0U) == VAL##AU);                      \
+    EXPECT_TRUE(FUNC_NAME((unsigned short)0U) == VAL##BU);                     \
+    EXPECT_TRUE(FUNC_NAME(0U) == VAL##CU);                                     \
+    EXPECT_TRUE(FUNC_NAME(0UL) == VAL##DU);                                    \
+    EXPECT_TRUE(FUNC_NAME(0ULL) == VAL##EU);                                   \
   } while (0)
 
-int main(void) {
+TEST(stdbit) {
   CHECK_FUNCTION(stdc_leading_zeros, 0xA);
   CHECK_FUNCTION(stdc_leading_ones, 0xB);
   CHECK_FUNCTION(stdc_trailing_zeros, 0xC);
@@ -47,15 +46,13 @@ int main(void) {
   CHECK_FUNCTION(stdc_count_zeros, 0x2);
   CHECK_FUNCTION(stdc_count_ones, 0x3);
 
-  assert(!stdc_has_single_bit((unsigned char)1U));
-  assert(!stdc_has_single_bit((unsigned short)1U));
-  assert(!stdc_has_single_bit(1U));
-  assert(!stdc_has_single_bit(1UL));
-  assert(!stdc_has_single_bit(1ULL));
+  EXPECT_FALSE(stdc_has_single_bit((unsigned char)1U));
+  EXPECT_FALSE(stdc_has_single_bit((unsigned short)1U));
+  EXPECT_FALSE(stdc_has_single_bit(1U));
+  EXPECT_FALSE(stdc_has_single_bit(1UL));
+  EXPECT_FALSE(stdc_has_single_bit(1ULL));
 
   CHECK_FUNCTION(stdc_bit_width, 0x4);
   CHECK_FUNCTION(stdc_bit_floor, 0x5);
   CHECK_FUNCTION(stdc_bit_ceil, 0x6);
-
-  return 0;
 }

>From 8c407b40f5ca5d80d2a0d756fc303926ac9c02c8 Mon Sep 17 00:00:00 2001
From: Pavel Labath <pavel at labath.sk>
Date: Mon, 3 Aug 2026 12:44:41 +0000
Subject: [PATCH 2/3] format

---
 libc/test/UnitTest/LibcCTest.cpp    | 2 +-
 libc/test/UnitTest/LibcCTest.h      | 4 ++--
 libc/test/include/fpclassify_test.c | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/libc/test/UnitTest/LibcCTest.cpp b/libc/test/UnitTest/LibcCTest.cpp
index 4436fa937e7f6..8e19f7dd30227 100644
--- a/libc/test/UnitTest/LibcCTest.cpp
+++ b/libc/test/UnitTest/LibcCTest.cpp
@@ -28,7 +28,7 @@ static CTest c_test_instance;
 extern "C" void libc_c_test_anchor() {}
 
 extern "C" void libc_c_test_fail(const char *cond, int expected,
-                                   const char *file, int line) {
+                                 const char *file, int line) {
   LIBC_NAMESPACE::testing::internal::test(
       LIBC_NAMESPACE::testing::TestCond::EQ, !expected,
       static_cast<bool>(expected), cond, expected ? "true" : "false",
diff --git a/libc/test/UnitTest/LibcCTest.h b/libc/test/UnitTest/LibcCTest.h
index c0cd1b91e4088..cac8a271e7d88 100644
--- a/libc/test/UnitTest/LibcCTest.h
+++ b/libc/test/UnitTest/LibcCTest.h
@@ -46,8 +46,8 @@ __END_C_DECLS
     }                                                                          \
   } while (0)
 
-#define EXPECT_TRUE(cond)  LIBC_C_TEST_SCAFFOLDING_(cond, 1, )
-#define ASSERT_TRUE(cond)  LIBC_C_TEST_SCAFFOLDING_(cond, 1, return)
+#define EXPECT_TRUE(cond) LIBC_C_TEST_SCAFFOLDING_(cond, 1, )
+#define ASSERT_TRUE(cond) LIBC_C_TEST_SCAFFOLDING_(cond, 1, return)
 
 #define EXPECT_FALSE(cond) LIBC_C_TEST_SCAFFOLDING_(cond, 0, )
 #define ASSERT_FALSE(cond) LIBC_C_TEST_SCAFFOLDING_(cond, 0, return)
diff --git a/libc/test/include/fpclassify_test.c b/libc/test/include/fpclassify_test.c
index 4717e1e583353..0d265552b29ed 100644
--- a/libc/test/include/fpclassify_test.c
+++ b/libc/test/include/fpclassify_test.c
@@ -17,7 +17,7 @@ TEST(fpclassify) {
   EXPECT_TRUE(fpclassify(-1.726) == FP_NORMAL);
   EXPECT_TRUE(fpclassify(1.426L) == FP_NORMAL);
   EXPECT_TRUE(fpclassify(-0.0f) == FP_ZERO);
-  EXPECT_TRUE(fpclassify(0.0) == FP_ZERO); 
+  EXPECT_TRUE(fpclassify(0.0) == FP_ZERO);
   EXPECT_TRUE(fpclassify(-0.0L) == FP_ZERO);
 }
 #endif

>From 9ced0f380a8c84a20903656fef5f61d65925e78f Mon Sep 17 00:00:00 2001
From: Pavel Labath <pavel at labath.sk>
Date: Mon, 3 Aug 2026 12:54:14 +0000
Subject: [PATCH 3/3] fix bazel build

---
 .../libc/test/UnitTest/BUILD.bazel               | 10 ++++++++++
 .../libc/test/include/BUILD.bazel                | 16 ++++++++--------
 .../libc/test/libc_test_rules.bzl                |  8 +++++---
 3 files changed, 23 insertions(+), 11 deletions(-)

diff --git a/utils/bazel/llvm-project-overlay/libc/test/UnitTest/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/test/UnitTest/BUILD.bazel
index 7d25fe869e193..742261cfbe6cc 100644
--- a/utils/bazel/llvm-project-overlay/libc/test/UnitTest/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/test/UnitTest/BUILD.bazel
@@ -82,6 +82,16 @@ libc_test_library(
     alwayslink = True,
 )
 
+libc_test_library(
+    name = "LibcCTest",
+    srcs = ["LibcCTest.cpp"],
+    hdrs = ["LibcCTest.h"],
+    deps = [
+        ":LibcUnitTest",
+        "//libc:public_headers_deps",
+    ],
+)
+
 libc_test_library(
     name = "fp_test_helpers",
     srcs = [
diff --git a/utils/bazel/llvm-project-overlay/libc/test/include/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/test/include/BUILD.bazel
index 9be937e37a2ad..dcaf655c5b5c9 100644
--- a/utils/bazel/llvm-project-overlay/libc/test/include/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/test/include/BUILD.bazel
@@ -68,7 +68,7 @@ libc_test(
 libc_test(
     name = "fpclassify_c_test",
     srcs = ["fpclassify_test.c"],
-    use_test_framework = False,
+    c_test = True,
     deps = ["//libc:public_headers_deps"],
 )
 
@@ -114,7 +114,7 @@ libc_test(
 libc_test(
     name = "isfinite_c_test",
     srcs = ["isfinite_test.c"],
-    use_test_framework = False,
+    c_test = True,
     deps = ["//libc:public_headers_deps"],
 )
 
@@ -160,7 +160,7 @@ libc_test(
 libc_test(
     name = "isinf_c_test",
     srcs = ["isinf_test.c"],
-    use_test_framework = False,
+    c_test = True,
     deps = ["//libc:public_headers_deps"],
 )
 
@@ -206,7 +206,7 @@ libc_test(
 libc_test(
     name = "isnan_c_test",
     srcs = ["isnan_test.c"],
-    use_test_framework = False,
+    c_test = True,
     deps = ["//libc:public_headers_deps"],
 )
 
@@ -252,14 +252,14 @@ libc_test(
 libc_test(
     name = "isnormal_c_test",
     srcs = ["isnormal_test.c"],
-    use_test_framework = False,
+    c_test = True,
     deps = ["//libc:public_headers_deps"],
 )
 
 libc_test(
     name = "issubnormal_c_test",
     srcs = ["issubnormal_test.c"],
-    use_test_framework = False,
+    c_test = True,
     deps = ["//libc:public_headers_deps"],
 )
 
@@ -305,7 +305,7 @@ libc_test(
 libc_test(
     name = "iszero_c_test",
     srcs = ["iszero_test.c"],
-    use_test_framework = False,
+    c_test = True,
     deps = ["//libc:public_headers_deps"],
 )
 
@@ -361,7 +361,7 @@ libc_test(
 libc_test(
     name = "signbit_c_test",
     srcs = ["signbit_test.c"],
-    use_test_framework = False,
+    c_test = True,
     deps = ["//libc:public_headers_deps"],
 )
 
diff --git a/utils/bazel/llvm-project-overlay/libc/test/libc_test_rules.bzl b/utils/bazel/llvm-project-overlay/libc/test/libc_test_rules.bzl
index dfe6ff5850704..9aa3073517ac2 100644
--- a/utils/bazel/llvm-project-overlay/libc/test/libc_test_rules.bzl
+++ b/utils/bazel/llvm-project-overlay/libc/test/libc_test_rules.bzl
@@ -30,7 +30,7 @@ def libc_test(
         copts = [],
         deps = [],
         local_defines = [],
-        use_test_framework = True,
+        c_test = False,
         full_build = False,
         **kwargs):
     """Add target for a libc test.
@@ -40,7 +40,7 @@ def libc_test(
       copts: The list of options to add to the C++ compilation command.
       deps: The list of libc functions and libraries to be linked in.
       local_defines: The list of target local_defines if any.
-      use_test_framework: Whether to use the libc unit test `main` function.
+      c_test: Whether this test is a C unit test (uses LibcCTest).
       full_build: Whether to compile with LIBC_FULL_BUILD and disallow
           use of system headers. This is useful for tests that include both
           LLVM libc headers and proxy headers to avoid conflicting definitions.
@@ -56,7 +56,9 @@ def libc_test(
         "//libc:func_malloc",
         "//libc:func_realloc",
     ]
-    if use_test_framework:
+    if c_test:
+        deps = deps + ["//libc/test/UnitTest:LibcCTest"]
+    else:
         deps = deps + ["//libc/test/UnitTest:LibcUnitTest"]
 
     if full_build:



More information about the libc-commits mailing list