Fixing LLVM LIT Test Failures When Using Macro‑Gated Code

Summary

When writing LLVM LIT tests for code gated behind macros, the test framework may still attempt to execute checks even if the macro is undefined. This leads to spurious failures or unexpected behavior in the testing pipeline.

Root Cause

LIT does not automatically respect preprocessor conditionals (e.g., #ifdef, #if) when determining whether to run tests. The test executor analyzes all directives regardless of macro definitions, causing mismatches between expected and actual code paths.

Why This Happens in Real Systems

  • Preprocessor conditionals are not evaluated during LIT parsing
  • Tests often assume all code paths exist without considering build configurations
  • Macro-gated functions are omitted during compilation but not during test execution

Real-World Impact

  • False-negative test failures due to missing symbols or invalid syntax
  • Increased noise in CI/CD pipelines from irrelevant test errors
  • Developer confusion when tests fail in environments where the macro is disabled
  • Difficulty maintaining portable test suites across build configurations

Example or Code

To conditionally enable checks in LIT, use REQUIRES or UNSUPPORTED directives paired with feature detection:

; RUN: llvm-as  /dev/null
; REQUIRES: macro_defined

define void @gated_function() {
entry:
  ret void
}

Or use --force-conditional flag to respect preprocessor logic:

llvm-lit --force-conditional test_file.ll

How Senior Engineers Fix It

  • Explicitly annotate test files with REQUIRES/UNSUPPORTED based on macro presence
  • Use llvm-config --features to query available macros and gate tests dynamically
  • Implement custom LIT substitutions to inject preprocessor definitions
  • Separate macro-dependent tests into conditional test suites

Why Juniors Miss It

  • Assume LIT mirrors compiler behavior and automatically skips inactive code paths
  • Lack awareness of --force-conditional or feature-based test gating mechanisms
  • Do not account for differences between compile-time preprocessing and runtime test execution
  • Overlook the need for explicit environment synchronization in cross-platform builds

Leave a Comment