[llvm] [libc][bazel] Add bazel targets for libc/include/... tests. (PR #141150)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 23 11:44:46 PDT 2025


https://github.com/jtstogel updated https://github.com/llvm/llvm-project/pull/141150

>From 2498281fdb83436363a61acef32adef80e974ae4 Mon Sep 17 00:00:00 2001
From: Jackson Stogel <jtstogel at gmail.com>
Date: Mon, 23 Jun 2025 18:10:15 +0000
Subject: [PATCH] Add bazel targets for libc/include/... tests.

These tests are compiled with `-DLIBC_FULL_BUILD`, since otherwise
inclusion of system headers can redefined macros defined by LLVM
libc.

Also, set `alwayslink=True` for `//libc/test:LibcUnitTest`. This ensures that the `main` function provided always gets linked into a test target. While not strictly necessary, it makes it so tests like https://github.com/llvm/llvm-project/blob/45d8759cbed0f216786729718608a8be72a505c6/libc/test/include/signbit_test.c will give a duplicate symbol error if they incorrectly depend on `LibcUnitTest`.
---
 bolt/lib/Rewrite/RewriteInstance.cpp          |  37 +-
 .../libc/test/UnitTest/BUILD.bazel            |   3 +
 .../libc/test/include/BUILD.bazel             | 420 +++++++++++++++++-
 .../libc/test/libc_test_rules.bzl             |  32 +-
 4 files changed, 451 insertions(+), 41 deletions(-)

diff --git a/bolt/lib/Rewrite/RewriteInstance.cpp b/bolt/lib/Rewrite/RewriteInstance.cpp
index d650e5db54bf9..93bd93b6cb984 100644
--- a/bolt/lib/Rewrite/RewriteInstance.cpp
+++ b/bolt/lib/Rewrite/RewriteInstance.cpp
@@ -780,14 +780,6 @@ void RewriteInstance::discoverFileObjects() {
 
   // For local symbols we want to keep track of associated FILE symbol name for
   // disambiguation by combined name.
-  StringRef FileSymbolName;
-  bool SeenFileName = false;
-  struct SymbolRefHash {
-    size_t operator()(SymbolRef const &S) const {
-      return std::hash<decltype(DataRefImpl::p)>{}(S.getRawDataRefImpl().p);
-    }
-  };
-  std::unordered_map<SymbolRef, StringRef, SymbolRefHash> SymbolToFileName;
   for (const ELFSymbolRef &Symbol : InputFile->symbols()) {
     Expected<StringRef> NameOrError = Symbol.getName();
     if (NameOrError && NameOrError->starts_with("__asan_init")) {
@@ -806,21 +798,8 @@ void RewriteInstance::discoverFileObjects() {
     if (cantFail(Symbol.getFlags()) & SymbolRef::SF_Undefined)
       continue;
 
-    if (cantFail(Symbol.getType()) == SymbolRef::ST_File) {
+    if (cantFail(Symbol.getType()) == SymbolRef::ST_File)
       FileSymbols.emplace_back(Symbol);
-      StringRef Name =
-          cantFail(std::move(NameOrError), "cannot get symbol name for file");
-      // Ignore Clang LTO artificial FILE symbol as it is not always generated,
-      // and this uncertainty is causing havoc in function name matching.
-      if (Name == "ld-temp.o")
-        continue;
-      FileSymbolName = Name;
-      SeenFileName = true;
-      continue;
-    }
-    if (!FileSymbolName.empty() &&
-        !(cantFail(Symbol.getFlags()) & SymbolRef::SF_Global))
-      SymbolToFileName[Symbol] = FileSymbolName;
   }
 
   // Sort symbols in the file by value. Ignore symbols from non-allocatable
@@ -1028,14 +1007,14 @@ void RewriteInstance::discoverFileObjects() {
       // The <id> field is used for disambiguation of local symbols since there
       // could be identical function names coming from identical file names
       // (e.g. from different directories).
-      std::string AltPrefix;
-      auto SFI = SymbolToFileName.find(Symbol);
-      if (SymbolType == SymbolRef::ST_Function && SFI != SymbolToFileName.end())
-        AltPrefix = Name + "/" + std::string(SFI->second);
+      auto SFI = llvm::upper_bound(FileSymbols, ELFSymbolRef(Symbol));
+      if (SymbolType == SymbolRef::ST_Function && SFI != FileSymbols.begin()) {
+        StringRef FileSymbolName = cantFail(SFI[-1].getName());
+        if (!FileSymbolName.empty())
+          AlternativeName = NR.uniquify(Name + "/" + FileSymbolName.str());
+      }
 
       UniqueName = NR.uniquify(Name);
-      if (!AltPrefix.empty())
-        AlternativeName = NR.uniquify(AltPrefix);
     }
 
     uint64_t SymbolSize = ELFSymbolRef(Symbol).getSize();
@@ -1294,7 +1273,7 @@ void RewriteInstance::discoverFileObjects() {
                              FDE->getAddressRange());
   }
 
-  BC->setHasSymbolsWithFileName(SeenFileName);
+  BC->setHasSymbolsWithFileName(FileSymbols.size());
 
   // Now that all the functions were created - adjust their boundaries.
   adjustFunctionBoundaries();
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 2c5ad7d27ce84..090bd1b1ba7aa 100644
--- a/utils/bazel/llvm-project-overlay/libc/test/UnitTest/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/test/UnitTest/BUILD.bazel
@@ -72,6 +72,9 @@ libc_test_library(
         "//libc:llvm_libc_macros_stdfix_macros",
         "//llvm:Support",
     ],
+    # Force linking in this library's `main()` to surface
+    # a duplicate symbol error if a test defines its own main.
+    alwayslink = True,
 )
 
 libc_test_library(
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 51e8424282af0..1cc4c25f72291 100644
--- a/utils/bazel/llvm-project-overlay/libc/test/include/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/test/include/BUILD.bazel
@@ -4,19 +4,437 @@
 
 # Tests for LLVM libc public headers.
 
-load("//libc/test:libc_test_rules.bzl", "libc_test")
+load("//libc/test:libc_test_rules.bzl", "libc_test", "libc_test_library")
 
 package(default_visibility = ["//visibility:public"])
 
 licenses(["notice"])
 
+# Header unit tests that include system headers (via unit test utils)
+# are compiled under LIBC_FULL_BUILD,
+# since otherwise system headers and libc headers conflict.
+_HEADER_TEST_DEFINES = [
+    "LIBC_FULL_BUILD",
+    "LIBC_COPT_USE_C_ASSERT",
+]
+
+# Disable system stdlib headers,
+# since these tests package their own libc definitions.
+_HEADER_TEST_COPTS = [
+    "-nostdlib",
+    "-nostdlib++",
+    "-nostdinc++",
+]
+
+libc_test(
+    name = "assert_test",
+    srcs = ["assert_test.cpp"],
+    deps = ["//libc:public_headers_deps"],
+)
+
+libc_test(
+    name = "complex_test",
+    srcs = ["complex_test.cpp"],
+    copts = _HEADER_TEST_COPTS,
+    local_defines = _HEADER_TEST_DEFINES,
+    deps = [
+        "//libc:public_headers_deps",
+        "//libc/test/UnitTest:fp_test_helpers",
+    ],
+)
+
+libc_test_library(
+    name = "fpclassify_test_fixture",
+    hdrs = ["FpClassifyTest.h"],
+    copts = _HEADER_TEST_COPTS,
+    local_defines = _HEADER_TEST_DEFINES,
+    deps = [
+        "//libc:public_headers_deps",
+        "//libc/test/UnitTest:LibcUnitTest",
+        "//libc/test/UnitTest:fp_test_helpers",
+    ],
+)
+
+libc_test(
+    name = "fpclassify_test",
+    srcs = ["fpclassify_test.cpp"],
+    copts = _HEADER_TEST_COPTS,
+    local_defines = _HEADER_TEST_DEFINES,
+    deps = [
+        ":fpclassify_test_fixture",
+        "//libc:public_headers_deps",
+    ],
+)
+
+libc_test(
+    name = "fpclassifyf_test",
+    srcs = ["fpclassifyf_test.cpp"],
+    copts = _HEADER_TEST_COPTS,
+    local_defines = _HEADER_TEST_DEFINES,
+    deps = [
+        ":fpclassify_test_fixture",
+        "//libc:public_headers_deps",
+    ],
+)
+
+libc_test(
+    name = "fpclassifyl_test",
+    srcs = ["fpclassifyl_test.cpp"],
+    copts = _HEADER_TEST_COPTS,
+    local_defines = _HEADER_TEST_DEFINES,
+    deps = [
+        ":fpclassify_test_fixture",
+        "//libc:public_headers_deps",
+    ],
+)
+
+libc_test(
+    name = "fpclassify_c_test",
+    srcs = ["fpclassify_test.c"],
+    use_test_framework = False,
+    deps = ["//libc:public_headers_deps"],
+)
+
+libc_test_library(
+    name = "isfinite_test_fixture",
+    hdrs = ["IsFiniteTest.h"],
+    copts = _HEADER_TEST_COPTS,
+    local_defines = _HEADER_TEST_DEFINES,
+    deps = [
+        "//libc:public_headers_deps",
+        "//libc/test/UnitTest:LibcUnitTest",
+        "//libc/test/UnitTest:fp_test_helpers",
+    ],
+)
+
+libc_test(
+    name = "isfinite_test",
+    srcs = ["isfinite_test.cpp"],
+    copts = _HEADER_TEST_COPTS,
+    local_defines = _HEADER_TEST_DEFINES,
+    deps = [
+        ":isfinite_test_fixture",
+        "//libc:public_headers_deps",
+    ],
+)
+
+libc_test(
+    name = "isfinitef_test",
+    srcs = ["isfinitef_test.cpp"],
+    copts = _HEADER_TEST_COPTS,
+    local_defines = _HEADER_TEST_DEFINES,
+    deps = [
+        ":isfinite_test_fixture",
+        "//libc:public_headers_deps",
+    ],
+)
+
+libc_test(
+    name = "isfinitel_test",
+    srcs = ["isfinitel_test.cpp"],
+    copts = _HEADER_TEST_COPTS,
+    local_defines = _HEADER_TEST_DEFINES,
+    deps = [
+        ":isfinite_test_fixture",
+        "//libc:public_headers_deps",
+    ],
+)
+
+libc_test(
+    name = "isfinite_c_test",
+    srcs = ["isfinite_test.c"],
+    use_test_framework = False,
+    deps = ["//libc:public_headers_deps"],
+)
+
+libc_test_library(
+    name = "isinf_test_fixture",
+    hdrs = ["IsInfTest.h"],
+    copts = _HEADER_TEST_COPTS,
+    local_defines = _HEADER_TEST_DEFINES,
+    deps = [
+        "//libc:public_headers_deps",
+        "//libc/test/UnitTest:LibcUnitTest",
+        "//libc/test/UnitTest:fp_test_helpers",
+    ],
+)
+
+libc_test(
+    name = "isinf_test",
+    srcs = ["isinf_test.cpp"],
+    copts = _HEADER_TEST_COPTS,
+    local_defines = _HEADER_TEST_DEFINES,
+    deps = [
+        ":isinf_test_fixture",
+        "//libc:public_headers_deps",
+    ],
+)
+
+libc_test(
+    name = "isinff_test",
+    srcs = ["isinff_test.cpp"],
+    copts = _HEADER_TEST_COPTS,
+    local_defines = _HEADER_TEST_DEFINES,
+    deps = [
+        ":isinf_test_fixture",
+        "//libc:public_headers_deps",
+    ],
+)
+
+libc_test(
+    name = "isinfl_test",
+    srcs = ["isinfl_test.cpp"],
+    copts = _HEADER_TEST_COPTS,
+    local_defines = _HEADER_TEST_DEFINES,
+    deps = [
+        ":isinf_test_fixture",
+        "//libc:public_headers_deps",
+    ],
+)
+
+libc_test(
+    name = "isinf_c_test",
+    srcs = ["isinf_test.c"],
+    use_test_framework = False,
+    deps = ["//libc:public_headers_deps"],
+)
+
+libc_test_library(
+    name = "isnan_test_fixture",
+    hdrs = ["IsNanTest.h"],
+    copts = _HEADER_TEST_COPTS,
+    local_defines = _HEADER_TEST_DEFINES,
+    deps = [
+        "//libc:public_headers_deps",
+        "//libc/test/UnitTest:LibcUnitTest",
+        "//libc/test/UnitTest:fp_test_helpers",
+    ],
+)
+
+libc_test(
+    name = "isnan_test",
+    srcs = ["isnan_test.cpp"],
+    copts = _HEADER_TEST_COPTS,
+    local_defines = _HEADER_TEST_DEFINES,
+    deps = [
+        ":isnan_test_fixture",
+        "//libc:public_headers_deps",
+    ],
+)
+
+libc_test(
+    name = "isnanf_test",
+    srcs = ["isnanf_test.cpp"],
+    copts = _HEADER_TEST_COPTS,
+    local_defines = _HEADER_TEST_DEFINES,
+    deps = [
+        ":isnan_test_fixture",
+        "//libc:public_headers_deps",
+    ],
+)
+
+libc_test(
+    name = "isnanl_test",
+    srcs = ["isnanl_test.cpp"],
+    copts = _HEADER_TEST_COPTS,
+    local_defines = _HEADER_TEST_DEFINES,
+    deps = [
+        ":isnan_test_fixture",
+        "//libc:public_headers_deps",
+    ],
+)
+
+libc_test(
+    name = "isnan_c_test",
+    srcs = ["isnan_test.c"],
+    use_test_framework = False,
+    deps = ["//libc:public_headers_deps"],
+)
+
+libc_test_library(
+    name = "isnormal_test_fixture",
+    hdrs = ["IsNormalTest.h"],
+    copts = _HEADER_TEST_COPTS,
+    local_defines = _HEADER_TEST_DEFINES,
+    deps = [
+        "//libc:public_headers_deps",
+        "//libc/test/UnitTest:LibcUnitTest",
+        "//libc/test/UnitTest:fp_test_helpers",
+    ],
+)
+
+libc_test(
+    name = "isnormal_test",
+    srcs = ["isnormal_test.cpp"],
+    copts = _HEADER_TEST_COPTS,
+    local_defines = _HEADER_TEST_DEFINES,
+    deps = [
+        ":isnormal_test_fixture",
+        "//libc:public_headers_deps",
+    ],
+)
+
+libc_test(
+    name = "isnormalf_test",
+    srcs = ["isnormalf_test.cpp"],
+    copts = _HEADER_TEST_COPTS,
+    local_defines = _HEADER_TEST_DEFINES,
+    deps = [
+        ":isnormal_test_fixture",
+        "//libc:public_headers_deps",
+    ],
+)
+
+libc_test(
+    name = "isnormall_test",
+    srcs = ["isnormall_test.cpp"],
+    copts = _HEADER_TEST_COPTS,
+    local_defines = _HEADER_TEST_DEFINES,
+    deps = [
+        ":isnormal_test_fixture",
+        "//libc:public_headers_deps",
+    ],
+)
+
+libc_test(
+    name = "isnormal_c_test",
+    srcs = ["isnormal_test.c"],
+    use_test_framework = False,
+    deps = ["//libc:public_headers_deps"],
+)
+
+libc_test(
+    name = "issubnormal_c_test",
+    srcs = ["issubnormal_test.c"],
+    use_test_framework = False,
+    deps = ["//libc:public_headers_deps"],
+)
+
+libc_test_library(
+    name = "iszero_test_fixture",
+    hdrs = ["IsZeroTest.h"],
+    copts = _HEADER_TEST_COPTS,
+    local_defines = _HEADER_TEST_DEFINES,
+    deps = [
+        "//libc:public_headers_deps",
+        "//libc/test/UnitTest:LibcUnitTest",
+        "//libc/test/UnitTest:fp_test_helpers",
+    ],
+)
+
+libc_test(
+    name = "iszero_test",
+    srcs = ["iszero_test.cpp"],
+    copts = _HEADER_TEST_COPTS,
+    local_defines = _HEADER_TEST_DEFINES,
+    deps = [
+        ":iszero_test_fixture",
+        "//libc:public_headers_deps",
+    ],
+)
+
+libc_test(
+    name = "iszerof_test",
+    srcs = ["iszerof_test.cpp"],
+    copts = _HEADER_TEST_COPTS,
+    local_defines = _HEADER_TEST_DEFINES,
+    deps = [
+        ":iszero_test_fixture",
+        "//libc:public_headers_deps",
+    ],
+)
+
+libc_test(
+    name = "iszerol_test",
+    srcs = ["iszerol_test.cpp"],
+    copts = _HEADER_TEST_COPTS,
+    local_defines = _HEADER_TEST_DEFINES,
+    deps = [
+        ":iszero_test_fixture",
+        "//libc:public_headers_deps",
+    ],
+)
+
+libc_test(
+    name = "iszero_c_test",
+    srcs = ["iszero_test.c"],
+    use_test_framework = False,
+    deps = ["//libc:public_headers_deps"],
+)
+
+libc_test_library(
+    name = "signbit_test_fixture",
+    hdrs = ["SignbitTest.h"],
+    copts = _HEADER_TEST_COPTS,
+    local_defines = _HEADER_TEST_DEFINES,
+    deps = [
+        "//libc:public_headers_deps",
+        "//libc/test/UnitTest:LibcUnitTest",
+        "//libc/test/UnitTest:fp_test_helpers",
+    ],
+)
+
+libc_test(
+    name = "signbit_test",
+    srcs = ["signbit_test.cpp"],
+    copts = _HEADER_TEST_COPTS,
+    local_defines = _HEADER_TEST_DEFINES,
+    deps = [
+        ":signbit_test_fixture",
+        "//libc:public_headers_deps",
+    ],
+)
+
+libc_test(
+    name = "signbitf_test",
+    srcs = ["signbitf_test.cpp"],
+    copts = _HEADER_TEST_COPTS,
+    local_defines = _HEADER_TEST_DEFINES,
+    deps = [
+        ":signbit_test_fixture",
+        "//libc:public_headers_deps",
+    ],
+)
+
+libc_test(
+    name = "signbitl_test",
+    srcs = ["signbitl_test.cpp"],
+    copts = _HEADER_TEST_COPTS,
+    local_defines = _HEADER_TEST_DEFINES,
+    deps = [
+        ":signbit_test_fixture",
+        "//libc:public_headers_deps",
+    ],
+)
+
 libc_test(
     name = "stdbit_test",
     srcs = [
         "stdbit_stub.h",
         "stdbit_test.cpp",
     ],
+    deps = ["//libc:public_headers_deps"],
+)
+
+libc_test(
+    name = "signbit_c_test",
+    srcs = ["signbit_test.c"],
+    use_test_framework = False,
+    deps = ["//libc:public_headers_deps"],
+)
+
+libc_test(
+    name = "stdckdint_test",
+    srcs = ["stdckdint_test.cpp"],
+    deps = ["//libc:public_headers_deps"],
+)
+
+libc_test(
+    name = "sys_queue_test",
+    srcs = ["sys/queue_test.cpp"],
     deps = [
+        "//libc:__support_char_vector",
+        "//libc:__support_cpp_string",
         "//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 ba8753a17a855..0c7a9dfdd0594 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
@@ -15,7 +15,13 @@ When performing tests we make sure to always use the internal version.
 load("//libc:libc_build_rules.bzl", "libc_common_copts")
 load("//libc:libc_configure_options.bzl", "LIBC_CONFIGURE_OPTIONS")
 
-def libc_test(name, copts = [], deps = [], local_defines = [], **kwargs):
+def libc_test(
+        name,
+        copts = [],
+        deps = [],
+        local_defines = [],
+        use_test_framework = True,
+        **kwargs):
     """Add target for a libc test.
 
     Args:
@@ -23,21 +29,25 @@ def libc_test(name, copts = [], deps = [], local_defines = [], **kwargs):
       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.
       **kwargs: Attributes relevant for a cc_test.
     """
+    deps = deps + [
+        "//libc:__support_macros_config",
+        "//libc:__support_libc_errno",
+        "//libc:errno",
+        "//libc:func_aligned_alloc",
+        "//libc:func_free",
+        "//libc:func_malloc",
+        "//libc:func_realloc",
+    ]
+    if use_test_framework:
+        deps = deps + ["//libc/test/UnitTest:LibcUnitTest"]
+
     native.cc_test(
         name = name,
         local_defines = local_defines + LIBC_CONFIGURE_OPTIONS,
-        deps = [
-            "//libc/test/UnitTest:LibcUnitTest",
-            "//libc:__support_macros_config",
-            "//libc:__support_libc_errno",
-            "//libc:errno",
-            "//libc:func_aligned_alloc",
-            "//libc:func_free",
-            "//libc:func_malloc",
-            "//libc:func_realloc",
-        ] + deps,
+        deps = deps,
         copts = copts + libc_common_copts(),
         linkstatic = 1,
         **kwargs



More information about the llvm-commits mailing list