[libc-commits] [libc] 72f5694 - [libc] Enable full-build code coverage (#221802)
via libc-commits
libc-commits at lists.llvm.org
Thu Sep 10 09:50:36 PDT 2026
Author: Tapiwa Gonga
Date: 2026-09-10T17:50:31+01:00
New Revision: 72f5694df7b6c9fa94f22468f5cd468d305b9917
URL: https://github.com/llvm/llvm-project/commit/72f5694df7b6c9fa94f22468f5cd468d305b9917
DIFF: https://github.com/llvm/llvm-project/commit/72f5694df7b6c9fa94f22468f5cd468d305b9917.diff
LOG: [libc] Enable full-build code coverage (#221802)
Extended LIBC_ENABLE_COVERAGE to support LLVM_LIBC_FULL_BUILD=ON and
added the LIBC_ENABLE_COVERAGE_MCDC CMake option for MC/DC coverage.
This enables developers and CI pipelines to measure source-level and
MC/DC coverage directly on hermetic tests in full-build configurations
without relying on the host C library.
Updated add_libc_hermetic in LLVMLibCTestRules.cmake to link hermetic
tests with -noprofilelib, -u__llvm_profile_runtime, and compiler-rt's
profiling library. Replaced internal entrypoint objects in
link_object_files with public entrypoint objects for the C functions
referenced by libclang_rt.profile.a.
Added calloc and __errno_location to HermeticTestUtils.cpp to satisfy
remaining freestanding profiling runtime dependencies. Updated
libc/docs/dev/code_coverage.md with full-build instructions.
Assisted-by: Automated tooling, human reviewed.
Added:
Modified:
libc/CMakeLists.txt
libc/cmake/modules/LLVMLibCTestRules.cmake
libc/docs/dev/code_coverage.md
libc/test/UnitTest/CMakeLists.txt
libc/test/UnitTest/HermeticTestUtils.cpp
Removed:
################################################################################
diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt
index b21741c161e44..d7769bb7d0667 100644
--- a/libc/CMakeLists.txt
+++ b/libc/CMakeLists.txt
@@ -93,15 +93,20 @@ set(LIBC_TEST_LINK_OPTIONS_DEFAULT "" CACHE STRING "Common link options for all
# Enable source-based code coverage using Clang's continuous profiling mode.
option(LIBC_ENABLE_COVERAGE "Build libc with coverage instrumentation" OFF)
+option(LIBC_ENABLE_COVERAGE_MCDC
+ "Enable Modified Condition / Decision Coverage (MC/DC)" OFF)
if(LIBC_ENABLE_COVERAGE)
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
list(APPEND LIBC_COMPILE_OPTIONS_DEFAULT
- "-fprofile-instr-generate=libc_cov_%c%p.profraw"
+ "-fprofile-instr-generate=libc_cov_%p.profraw"
"-fcoverage-mapping"
"-fprofile-continuous")
list(APPEND LIBC_TEST_LINK_OPTIONS_DEFAULT
- "-fprofile-instr-generate=libc_cov_%c%p.profraw"
+ "-fprofile-instr-generate=libc_cov_%p.profraw"
"-fprofile-continuous")
+ if(LIBC_ENABLE_COVERAGE_MCDC)
+ list(APPEND LIBC_COMPILE_OPTIONS_DEFAULT "-fcoverage-mcdc")
+ endif()
else()
message(FATAL_ERROR
"Coverage instrumentation is currently only supported with Clang")
@@ -181,10 +186,31 @@ if(LIBC_ENABLE_COVERAGE)
"LIBC_ENABLE_COVERAGE is not supported on GPU or baremetal targets.")
endif()
if(LLVM_LIBC_FULL_BUILD)
- message(FATAL_ERROR
- "LIBC_ENABLE_COVERAGE is only supported in overlay mode "
- "(LLVM_LIBC_FULL_BUILD=OFF). Full build mode uses hermetic tests "
- "which cannot link the compiler-rt profiling runtime.")
+ set(target_arg "")
+ if(LIBC_TARGET_TRIPLE)
+ set(target_arg "--target=${LIBC_TARGET_TRIPLE}")
+ endif()
+ execute_process(
+ COMMAND ${CMAKE_CXX_COMPILER} ${target_arg}
+ --print-file-name=libclang_rt.profile.a
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ OUTPUT_VARIABLE libc_profile_lib
+ )
+ if(NOT EXISTS "${libc_profile_lib}")
+ set(profile_arch_lib
+ "libclang_rt.profile-${LIBC_TARGET_ARCHITECTURE}.a")
+ execute_process(
+ COMMAND ${CMAKE_CXX_COMPILER} ${target_arg}
+ --print-file-name=${profile_arch_lib}
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ OUTPUT_VARIABLE libc_profile_lib
+ )
+ endif()
+ if(NOT EXISTS "${libc_profile_lib}")
+ message(FATAL_ERROR "Coverage enabled but profile runtime not found.")
+ endif()
+ set(LIBC_CLANG_PROFILE_LIB "${libc_profile_lib}"
+ CACHE INTERNAL "Clang profile runtime")
endif()
endif()
option(LLVM_LIBC_IMPLEMENTATION_DEFINED_TEST_BEHAVIOR "Build LLVM libc tests assuming our implementation-defined behavior" ON)
diff --git a/libc/cmake/modules/LLVMLibCTestRules.cmake b/libc/cmake/modules/LLVMLibCTestRules.cmake
index 7c9d79a741945..b9bda4fd08b4d 100644
--- a/libc/cmake/modules/LLVMLibCTestRules.cmake
+++ b/libc/cmake/modules/LLVMLibCTestRules.cmake
@@ -824,6 +824,49 @@ function(add_libc_hermetic test_name)
list(APPEND fq_deps_list libc.src.time.clock)
endif()
+ if(LIBC_ENABLE_COVERAGE)
+ set(coverage_deps
+ libc.src.stdio.fclose
+ libc.src.stdio.fdopen
+ libc.src.stdio.feof
+ libc.src.stdio.fflush
+ libc.src.stdio.fileno
+ libc.src.stdio.fopen
+ libc.src.stdio.fprintf
+ libc.src.stdio.fread
+ libc.src.stdio.fseek
+ libc.src.stdio.ftell
+ libc.src.stdio.fwrite
+ libc.src.stdio.snprintf
+ libc.src.stdio.stderr
+ libc.src.stdio.vfprintf
+ libc.src.stdio.vsnprintf
+ libc.src.fcntl.fcntl
+ libc.src.fcntl.open
+ libc.src.stdlib.getenv
+ libc.src.stdlib.setenv
+ libc.src.stdlib.strtol
+ libc.src.string.strchr
+ libc.src.string.strcmp
+ libc.src.string.strdup
+ libc.src.string.strerror
+ libc.src.string.strlen
+ libc.src.string.strncpy
+ libc.src.string.strrchr
+ libc.src.sys.mman.madvise
+ libc.src.sys.mman.mmap
+ libc.src.sys.mman.munmap
+ libc.src.sys.prctl.prctl
+ libc.src.sys.stat.mkdir
+ libc.src.sys.utsname.uname
+ libc.src.unistd.fork
+ libc.src.unistd.ftruncate
+ libc.src.unistd.getpagesize
+ libc.src.unistd.getpid
+ )
+ list(APPEND fq_deps_list ${coverage_deps})
+ endif()
+
list(REMOVE_DUPLICATES fq_deps_list)
# TODO: Instead of gathering internal object files from entrypoints,
@@ -840,6 +883,18 @@ function(add_libc_hermetic test_name)
endif()
list(REMOVE_DUPLICATES link_object_files)
+ if(LIBC_ENABLE_COVERAGE)
+ foreach(cov_dep IN LISTS coverage_deps)
+ get_target_property(is_alias ${cov_dep} "IS_ALIAS")
+ if(is_alias)
+ get_target_property(real_target ${cov_dep} "DEPS")
+ else()
+ set(real_target ${cov_dep})
+ endif()
+ string(REPLACE "${real_target}.__internal__" "${real_target}" link_object_files "${link_object_files}")
+ endforeach()
+ endif()
+
# Make a library of all deps
add_library(
${fq_target_name}.__libc__
@@ -905,6 +960,12 @@ function(add_libc_hermetic test_name)
${LIBC_LINK_OPTIONS_DEFAULT}
${LIBC_TEST_LINK_OPTIONS_DEFAULT}
)
+ if(LIBC_ENABLE_COVERAGE)
+ list(APPEND link_options
+ -noprofilelib
+ -u__llvm_profile_runtime
+ )
+ endif()
target_link_options(${fq_build_target_name} PRIVATE ${link_options})
else()
# Older version of gcc does not support `nostdlib++` flag. We use
@@ -916,15 +977,31 @@ function(add_libc_hermetic test_name)
${LIBC_LINK_OPTIONS_DEFAULT}
${LIBC_TEST_LINK_OPTIONS_DEFAULT}
)
+ if(LIBC_ENABLE_COVERAGE)
+ list(APPEND link_options
+ -noprofilelib
+ -u__llvm_profile_runtime
+ )
+ endif()
target_link_options(${fq_build_target_name} PRIVATE ${link_options})
list(APPEND compiler_runtime ${LIBGCC_S_LOCATION})
endif()
+
+ set(coverage_link_libs "")
+ if(LIBC_ENABLE_COVERAGE)
+ set(coverage_link_libs
+ "${LIBC_CLANG_PROFILE_LIB}"
+ ${fq_target_name}.__libc__
+ )
+ endif()
+
target_link_libraries(
${fq_build_target_name}
PRIVATE
libc.startup.${LIBC_TARGET_OS}.crt1
${HERMETIC_TEST_LINK_LIBRARIES}
${fq_target_name}.__libc__
+ ${coverage_link_libs}
${compiler_runtime}
)
add_dependencies(${fq_build_target_name} ${fq_deps_list})
diff --git a/libc/docs/dev/code_coverage.md b/libc/docs/dev/code_coverage.md
index ab6a8288f1fdc..8e58ca5d14ffd 100644
--- a/libc/docs/dev/code_coverage.md
+++ b/libc/docs/dev/code_coverage.md
@@ -51,27 +51,32 @@ executed across parent and child processes directly to the profile file.
### Build System Integration
Setting `-DLIBC_ENABLE_COVERAGE=ON` in the CMake configuration passes
-`-fprofile-instr-generate=libc_cov_%c%p.profraw`, `-fcoverage-mapping`, and
+`-fprofile-instr-generate=libc_cov_%p.profraw`, `-fcoverage-mapping`, and
`-fprofile-continuous` across all LLVM-libc compilation units and test link
-steps. This ensures uniform instrumentation across entrypoints and unit test
-harnesses.
+steps. When `-fprofile-continuous` is enabled, Clang automatically prepends
+`%c` to the profile file template, avoiding duplicate specifier warnings at
+runtime. Setting `-DLIBC_ENABLE_COVERAGE_MCDC=ON` additionally enables
+`-fcoverage-mcdc`.
## Running Code Coverage Locally
### Prerequisites & Toolchain Setup
-Generating coverage reports requires Clang, LLVM profile tools, CMake, and
+Generating coverage reports requires Clang 24, LLVM profile tools, CMake, and
Ninja:
-* **Compiler:** Clang 18 or later (Clang 21 or later is required for MC/DC
- instrumentation).
-* **LLVM Utilities:** Matching major versions of `llvm-profdata` and `llvm-cov`.
+* **Compiler:** Clang 24 (or Clang built from HEAD). Full-build hermetic tests
+ link `libclang_rt.profile.a`, which must match the compiler version and cannot
+ rely on distro-built libraries with glibc source fortification.
+* **LLVM Utilities:** Matching Clang 24 versions of `llvm-profdata` and
+ `llvm-cov`.
+* **Linker:** `lld` is recommended when configuring full-build mode.
* **Build System:** CMake 3.28+ and Ninja.
#### Toolchain Discovery
-If your Linux distribution packages version-suffixed binaries (e.g. `clang-21`,
-`llvm-profdata-21`), discover and export them:
+If your Linux distribution packages version-suffixed binaries (e.g. `clang-24`,
+`llvm-profdata-24`), discover and export them:
```bash
CLANG_MAJOR=$(clang --version | sed -n 's/.*version \([0-9]*\).*/\1/p')
@@ -90,6 +95,25 @@ export LLVM_COV=llvm-cov
Subsequent merge and report commands reference `$LLVM_PROFDATA` and `$LLVM_COV`.
+#### Building Clang 24 with Profiling Support
+
+Full-build hermetic tests link `libclang_rt.profile.a`. Distro-built compiler-rt
+packages on distributions like Debian or Ubuntu are built with glibc source
+fortification enabled, which LLVM-libc does not support because it introduces
+unresolved symbols such as `__vfprintf_chk`. Furthermore, compiler-rt must
+match the exact version of the compiler used to build. The recommended approach
+is building Clang 24, lld, and compiler-rt from HEAD:
+
+```bash
+cmake -G Ninja -S llvm -B build-clang \
+ -DCMAKE_BUILD_TYPE=Release \
+ -DCMAKE_INSTALL_PREFIX="$HOME/clang" \
+ -DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra;lld" \
+ -DLLVM_ENABLE_RUNTIMES="compiler-rt" \
+ -DLLVM_USE_LINKER=lld
+ninja -C build-clang install
+```
+
---
## Cleaning Profile Counters
@@ -111,51 +135,67 @@ rm -f libc_full.profdata libc_mcdc.profdata libc_single.profdata \
Standard coverage measures physical line execution and conditional branch
outcomes across all LLVM-libc entrypoints and internal support utilities.
-### 1. CMake Configuration
+### 1. Clean Prior Profile Artifacts
-Configures CMake to build LLVM-libc in overlay mode, setting
-`-DLIBC_ENABLE_COVERAGE=ON` to pass Clang's continuous profiling and coverage
-mapping flags to the compiler:
+Removes previously generated raw profile counters and profile data to maintain
+a clean baseline:
+
+```bash
+rm -f build-cov/libc_cov_*.profraw libc_cov_*.profraw profraw_list.txt libc_full.profdata
+```
+
+### 2. Configure Full-Build Coverage with Clang 24
+
+Configures CMake to build LLVM-libc with code coverage enabled using Clang 24
+and LLD:
```bash
cmake -G Ninja -S runtimes -B build-cov \
- -DCMAKE_C_COMPILER=clang \
- -DCMAKE_CXX_COMPILER=clang++ \
+ -DCMAKE_C_COMPILER="$PWD/build-clang/bin/clang" \
+ -DCMAKE_CXX_COMPILER="$PWD/build-clang/bin/clang++" \
+ -DLLVM_USE_LINKER=lld \
-DCMAKE_BUILD_TYPE=Debug \
-DLLVM_ENABLE_RUNTIMES="libc" \
- -DLLVM_LIBC_FULL_BUILD=OFF \
+ -DLLVM_LIBC_FULL_BUILD=ON \
-DLIBC_ENABLE_COVERAGE=ON
```
-### 2. Build and Execute All Unit Tests
+### 3. Export Environment Variables
+
+Exports the profile output pattern and Clang 24 tool paths:
+
+```bash
+export LLVM_PROFILE_FILE="libc_cov_%p.profraw"
+export LLVM_PROFDATA="$PWD/build-clang/bin/llvm-profdata"
+export LLVM_COV="$PWD/build-clang/bin/llvm-cov"
+```
+
+### 4. Build and Execute Hermetic Tests
-Compiles all libc unit test executables and executes them in parallel. As each
-test executes, its counters are mapped directly to disk via the OS page cache:
+Compiles and executes the full hermetic test suite:
```bash
-export LLVM_PROFILE_FILE="libc_cov_%c%p.profraw"
-ninja -k 0 -C build-cov libc-unit-tests
+ninja -k 0 -C build-cov libc-hermetic-tests
```
:::{note}
-In LLVM-libc, `libc-unit-tests` builds and executes tests in a single
-invocation. The `-k 0` flag ensures Ninja continues executing all remaining
-test targets even if an individual edge-case test encounters an error. To only
-compile test binaries without immediately executing them, use
-`ninja -C build-cov libc-unit-tests-build`.
+The `-k 0` flag ensures Ninja continues executing all remaining test targets
+even if an individual edge-case test encounters an error. To only compile test
+binaries without executing them, use
+`ninja -C build-cov libc-hermetic-tests-build`.
:::
-### 3. Merge Profile Counters
+### 5. Merge Profile Counters
Scans the build tree for all generated `.profraw` files and indexes them into a
unified, sparse `.profdata` archive using `$LLVM_PROFDATA`:
```bash
-find build-cov/ -name "libc_cov_*.profraw" > profraw_list.txt
+find build-cov -name "libc_cov_*.profraw" > profraw_list.txt
"$LLVM_PROFDATA" merge -sparse -f profraw_list.txt -o libc_full.profdata
```
-### 4. Generate Coverage Reports
+### 6. Generate Coverage Reports
Collects all compiled test binary paths and invokes `$LLVM_COV` to correlate
recorded profile counters against the libc source tree:
@@ -171,6 +211,7 @@ done
Reports can be generated in
diff erent formats:
#### Option 1: Terminal Summary Report
+
Prints an aggregated terminal summary showing line, region, and branch coverage
percentages for each file:
@@ -182,7 +223,17 @@ percentages for each file:
-ignore-filename-regex=".*(test|utils).*"
```
+To restrict the terminal report to a specific source file:
+
+```bash
+"$LLVM_COV" report \
+ -instr-profile=libc_full.profdata \
+ "${TEST_BINS[0]}" "${OBJECT_FLAGS[@]}" \
+ libc/src/string/strlen.cpp
+```
+
#### Option 2: Interactive HTML Dashboard
+
Generates an interactive HTML dashboard containing sortable directory metrics
and syntax-highlighted source views:
@@ -209,44 +260,61 @@ as `if (A && B)`). It verifies that each individual sub-condition evaluates to
both true and false and independently affects the outcome of the enclosing
decision.
-### 1. CMake Configuration
+### 1. Clean Prior Profile Artifacts
-Configures CMake with `-fcoverage-mcdc` alongside profiling flags, enabling the
-compiler frontend to generate boolean condition bitmaps for compound decisions:
+Removes previous MC/DC profile counters and profile data:
+
+```bash
+rm -f build-cov-mcdc/libc_cov_*.profraw libc_cov_*.profraw profraw_list.txt libc_mcdc.profdata
+```
+
+### 2. Configure Full-Build Coverage with MC/DC using Clang 24
+
+Configures CMake with `-DLIBC_ENABLE_COVERAGE_MCDC=ON` alongside profiling
+flags using Clang 24 and LLD:
```bash
cmake -G Ninja -S runtimes -B build-cov-mcdc \
- -DCMAKE_C_COMPILER=clang \
- -DCMAKE_CXX_COMPILER=clang++ \
+ -DCMAKE_C_COMPILER="$PWD/build-clang/bin/clang" \
+ -DCMAKE_CXX_COMPILER="$PWD/build-clang/bin/clang++" \
+ -DLLVM_USE_LINKER=lld \
-DCMAKE_BUILD_TYPE=Debug \
-DLLVM_ENABLE_RUNTIMES="libc" \
- -DLLVM_LIBC_FULL_BUILD=OFF \
+ -DLLVM_LIBC_FULL_BUILD=ON \
-DLIBC_ENABLE_COVERAGE=ON \
- -DCMAKE_C_FLAGS="-fcoverage-mcdc" \
- -DCMAKE_CXX_FLAGS="-fcoverage-mcdc"
+ -DLIBC_ENABLE_COVERAGE_MCDC=ON
+```
+
+### 3. Export Environment Variables
+
+Exports the profile output pattern and Clang 24 tool paths:
+
+```bash
+export LLVM_PROFILE_FILE="libc_cov_%p.profraw"
+export LLVM_PROFDATA="$PWD/build-clang/bin/llvm-profdata"
+export LLVM_COV="$PWD/build-clang/bin/llvm-cov"
```
-### 2. Build and Execute Tests
+### 4. Build and Execute Hermetic Tests
-Compiles and executes all unit tests with MC/DC instrumentation enabled, saving
-condition evaluation bitmasks into raw profile files upon completion:
+Compiles and executes test executables in parallel with MC/DC instrumentation
+enabled:
```bash
-export LLVM_PROFILE_FILE="libc_cov_%c%p.profraw"
-ninja -k 0 -C build-cov-mcdc libc-unit-tests
+ninja -k 0 -C build-cov-mcdc libc-hermetic-tests
```
-### 3. Merge Profiles
+### 5. Merge Profile Counters
Indexes and merges all MC/DC `.profraw` files into a unified
`libc_mcdc.profdata` archive for report generation:
```bash
-find build-cov-mcdc/ -name "libc_cov_*.profraw" > profraw_list.txt
+find build-cov-mcdc -name "libc_cov_*.profraw" > profraw_list.txt
"$LLVM_PROFDATA" merge -sparse -f profraw_list.txt -o libc_mcdc.profdata
```
-### 4. Generate Reports
+### 6. Generate MC/DC Coverage Reports
Maps MC/DC bitmap records to source AST decisions and evaluates condition
independence pairs:
@@ -262,6 +330,7 @@ done
Reports can be generated in two formats depending on your needs:
#### Option 1: Terminal Summary Report
+
Displays the terminal coverage summary including MC/DC Condition and Missed
Condition percentages:
@@ -275,6 +344,7 @@ Condition percentages:
```
#### Option 2: Interactive HTML Dashboard
+
Produces an HTML report with expandable MC/DC decision truth tables and test
vector coverage breakdowns:
@@ -299,7 +369,7 @@ xdg-open coverage_mcdc_html/index.html
## Running Coverage for a Single Test
When developing or modifying a specific function, coverage can be collected for
-a single test without building and executing the entire test suite.
+a single hermetic test without building and executing the entire test suite.
The commands below use `libc.test.src.ctype.isalpha_test` (which tests
`libc/src/ctype/isalpha.cpp`) as an example. You can test any other entrypoint
@@ -309,25 +379,32 @@ by substituting the target name and source file path:
* **Source path pattern:** `libc/<path_to_source>/<source_file>.cpp`
(e.g. `libc/src/string/strlen.cpp`)
-### 1. Build and Execute the Targeted Test
+### 1. Clean Prior Profile Artifacts
+
+Removes previously generated raw profile counters:
+
+```bash
+rm -f libc_cov_*.profraw profraw_list.txt libc_single.profdata
+```
+
+### 2. Build and Execute the Targeted Test
Compiles and runs only the specified test binary, immediately writing execution
profile counters to disk upon completion:
```bash
-export LLVM_PROFILE_FILE="libc_cov_%c%p.profraw"
+export LLVM_PROFILE_FILE="libc_cov_%p.profraw"
-# For a standard coverage build
+# Standard coverage build
ninja -C build-cov libc.test.src.ctype.isalpha_test
-# For an MC/DC build
+# MC/DC coverage build
ninja -C build-cov-mcdc libc.test.src.ctype.isalpha_test
```
-### 2. Merge the Profile
+### 3. Merge the Profile
-Merges the single test's raw profile into an indexed database for targeted
-inspection (searching whichever build directory was compiled):
+Merges the single test's raw profile into an indexed database:
```bash
find build-cov/ build-cov-mcdc/ \
@@ -335,12 +412,10 @@ find build-cov/ build-cov-mcdc/ \
"$LLVM_PROFDATA" merge -sparse -f profraw_list.txt -o libc_single.profdata
```
-### 3. View the Terminal Report
-
-Reports can be viewed as an overall file summary or an annotated line-by-line
-breakdown:
+### 4. View Coverage Reports
#### Option 1: Summary Table Report
+
```bash
BIN_DIR="build-cov/libc/test/src/ctype"
"$LLVM_COV" report \
@@ -350,6 +425,7 @@ BIN_DIR="build-cov/libc/test/src/ctype"
```
#### Option 2: Line-by-Line & Truth Table View
+
```bash
BIN_DIR="build-cov-mcdc/libc/test/src/ctype"
"$LLVM_COV" show \
@@ -405,9 +481,10 @@ When inspecting with `--show-mcdc`, `llvm-cov` displays an MC/DC analysis table
beneath each compound decision. For instance, consider the following decision:
```text
- 19| if (c < 0 || c > 255)
- -----------------------------------------------
- | Conditions: C1 = (c < 0), C2 = (c > 255)
+ 19| if (c < 0 || c > cpp::numeric_limits<unsigned char>::max())
+ ------------------------------------------------------------------
+ | Conditions: C1 = (c < 0)
+ | C2 = (c > cpp::numeric_limits<unsigned char>::max())
|
| Executed Test Vectors:
| C1, C2 Result
@@ -417,10 +494,11 @@ beneath each compound decision. For instance, consider the following decision:
| C1-Pair: covered (1, 2)
| C2-Pair: not covered
| MC/DC Coverage: 50.00%
- -----------------------------------------------
+ ------------------------------------------------------------------
```
-* **Conditions:** **C1** represents `c < 0` and **C2** represents `c > 255`.
+* **Conditions:** **C1** represents `c < 0` and **C2** represents
+ `c > cpp::numeric_limits<unsigned char>::max()`.
* **Executed Vectors:**
* **Vector 1 (`F, F = F`):** Tested with a valid character (`c = 'a'`). Both
C1 and C2 evaluated False, producing an overall False result.
diff --git a/libc/test/UnitTest/CMakeLists.txt b/libc/test/UnitTest/CMakeLists.txt
index e6d978e16b46f..f409b644ef852 100644
--- a/libc/test/UnitTest/CMakeLists.txt
+++ b/libc/test/UnitTest/CMakeLists.txt
@@ -169,7 +169,9 @@ add_unittest_framework_library(
SRCS
${libc_hermetic_test_support_srcs}
DEPENDS
+ libc.hdr.errno_macros
libc.hdr.stdint_proxy
+ libc.src.__support.libc_errno
)
add_header_library(
diff --git a/libc/test/UnitTest/HermeticTestUtils.cpp b/libc/test/UnitTest/HermeticTestUtils.cpp
index a9bbf13a1f190..4a5cbd8040b52 100644
--- a/libc/test/UnitTest/HermeticTestUtils.cpp
+++ b/libc/test/UnitTest/HermeticTestUtils.cpp
@@ -6,8 +6,10 @@
//
//===----------------------------------------------------------------------===//
+#include "hdr/errno_macros.h"
#include "hdr/stdint_proxy.h"
#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
#include <stddef.h>
@@ -123,6 +125,26 @@ unsigned long __getauxval(unsigned long id) {
}
#endif
+void *calloc(size_t num, size_t size) {
+ if (num == 0 || size == 0)
+ return nullptr;
+ size_t total = 0;
+ if (__builtin_mul_overflow(num, size, &total)) {
+ LIBC_NAMESPACE::libc_errno = ENOMEM;
+ return nullptr;
+ }
+ void *mem = malloc(total);
+ if (mem == nullptr) {
+ LIBC_NAMESPACE::libc_errno = ENOMEM;
+ return nullptr;
+ }
+ LIBC_NAMESPACE::memset(mem, 0, total);
+ return mem;
+}
+#if defined(__linux__)
+int *__errno_location() noexcept { return LIBC_NAMESPACE::__llvm_libc_errno(); }
+#endif
+
} // extern "C"
void *operator new([[maybe_unused]] size_t size, void *ptr) { return ptr; }
More information about the libc-commits
mailing list