CoreTrace concurrency analyzer for C and C++ source files compiled to in-memory LLVM IR.
The project follows the coretrace-stack-analyzer conventions:
- CMake-based build with LLVM/Clang integration.
coretrace-compiler/compilerlibused as the compilation backend.- Public C++ API for compilation and analysis.
- CLI wrapper for local analysis runs.
- Consumer example in
extern-project/.
The repository no longer stops at IR compilation. It currently provides a single-translation-unit
concurrency analysis pipeline on top of the generated llvm::Module.
Supported analysis rules:
DataRaceGlobal: unsynchronized concurrent access detection for shared globals.MissingJoin: joinable thread handles not joined or detached before scope exit.DeadlockLockOrder: simple lock-order inversion and direct-call self-deadlock detection.
Current implementation boundaries:
- Single TU only.
- Direct-call interprocedural propagation is supported for thread context, thread lifecycle, and lock state.
MissingJoinsupports bothpthreadandstd::thread.DeadlockLockOrderis intentionally conservative and does not yet model arbitrary3+lock cycles across the whole program.- Multi-TU analysis, compile database ingestion, incremental cache, and full LLVM alias-analysis coverage are not finished yet.
The analyzer is intentionally layered so compilation concerns stay isolated from analysis concerns:
- CLI / consumer layer: parse options, invoke compilation, render reports.
InMemoryIRCompiler: validate request, build compile commands, invoke the backend, load LLVM IR.- Analysis facts layer: build translation-unit facts from the
llvm::Module. - Propagation layer: derive reusable interprocedural facts such as thread reachability, lifecycle, and effective held locks at call sites.
- Checker layer: run rule-specific analyzers on top of the shared facts.
- Reporting layer: emit human, JSON, or SARIF diagnostics.
This separation is preferable to a monolithic checker because new rules can reuse the same facts and propagation passes without duplicating LLVM traversal logic.
The project intentionally depends on compilerlib (coretrace-compiler) as the compilation
backend, but the dependency is isolated behind internal interfaces:
InMemoryIRCompiler: orchestration and error mapping.CompileCommandBuilder: normalize and construct compile arguments.ICompilationBackend/CompilerLibBackend: invokecompilerlib.IIRLoader/LLVMIRLoader: parsellorbcpayloads intollvm::Module.
InMemoryIRCompiler keeps a stable public compile(...) API and also supports dependency
injection for architecture-level tests.
cmake -S . -B build-llvm20 \
-DLLVM_DIR=/opt/homebrew/opt/llvm@20/lib/cmake/llvm \
-DClang_DIR=/opt/homebrew/opt/llvm@20/lib/cmake/clang \
-DCLANG_EXECUTABLE=/opt/homebrew/opt/llvm@20/bin/clang \
-DCLANG_RESOURCE_DIR=/opt/homebrew/opt/llvm@20/lib/clang/20
cmake --build build-llvm20 -j4Compile only:
./build-llvm20/coretrace_concurrency_analyzer /tmp/sample.c --ir-format=ll
./build-llvm20/coretrace_concurrency_analyzer /tmp/sample.c --ir-format=bcAnalyze with all available rules enabled by default:
./build-llvm20/coretrace_concurrency_analyzer /tmp/sample.c --analyze --format=human
./build-llvm20/coretrace_concurrency_analyzer /tmp/sample.c --analyze --format=json
./build-llvm20/coretrace_concurrency_analyzer /tmp/sample.c --analyze --format=sarifSelect one or more rules explicitly:
./build-llvm20/coretrace_concurrency_analyzer /tmp/sample.c --analyze --rules=data-race
./build-llvm20/coretrace_concurrency_analyzer /tmp/sample.c --analyze --rules=missing-join
./build-llvm20/coretrace_concurrency_analyzer /tmp/sample.c --analyze --rules=data-race,missing-join
./build-llvm20/coretrace_concurrency_analyzer /tmp/sample.c --analyze --rules=allSupported CLI options:
--ir-format=ll|bc--compile-arg=<arg>repeatable--instrument--analyze--rules=data-race|missing-join|deadlock-lock-order|all--format=human|json|sarif--verbose--to forward all trailing compiler args
Notes:
--analyzeenables all currently available rules by default.--rules=...acts as an explicit rule filter.--rulesand--formatrequire--analyze.
Compilation API:
CompileRequestCompileResultInMemoryIRCompiler
Analysis API:
AnalysisOptionsSingleTUConcurrencyAnalyzerDiagnosticReport
Minimal example:
#include "coretrace_concurrency_analyzer.hpp"
#include "coretrace_concurrency_analysis.hpp"
#include <llvm/IR/LLVMContext.h>
llvm::LLVMContext context;
ctrace::concurrency::CompileRequest request{
.inputFile = "sample.cpp",
};
ctrace::concurrency::InMemoryIRCompiler compiler;
const auto result = compiler.compile(request, context);
if (!result.success)
return 1;
ctrace::concurrency::SingleTUConcurrencyAnalyzer analyzer;
const auto report = analyzer.analyze(*result.module);Use AnalysisOptions when you want a subset of rules instead of the default all-rules behavior.
Structured diagnostics expose:
- severity
- rule identifier
- message
- source location
- related locations
- notes
- rule-specific properties
Rendered formats:
humanjsonsarif
extraCompileArgs are forwarded as raw compiler arguments to compilerlib::compile(...)
without sanitization. They are not shell-expanded by this tool, but they still influence
compilation behavior and file access done by the compiler toolchain.
Use this API or CLI only with trusted inputs, or place an explicit allowlist in front of it for untrusted callers.
cmake -S extern-project -B extern-project/build-llvm20 \
-DLLVM_DIR=/opt/homebrew/opt/llvm@20/lib/cmake/llvm \
-DClang_DIR=/opt/homebrew/opt/llvm@20/lib/cmake/clang \
-DCLANG_EXECUTABLE=/opt/homebrew/opt/llvm@20/bin/clang \
-DCLANG_RESOURCE_DIR=/opt/homebrew/opt/llvm@20/lib/clang/20
cmake --build extern-project/build-llvm20 -j4
./extern-project/build-llvm20/concurrency_consumer /tmp/sample.c --ir-format=ll
./extern-project/build-llvm20/concurrency_consumer /tmp/sample.c --analyze --rules=allconcurrency_consumer keeps backward compatibility with the legacy positional format (ll|bc) as
second argument.
CompileResult exposes a structured CompileError:
error.code: typedstd::error_codebacked byCompileErrcerror.phase: coarse pipeline stageerror.message: contextual details such as input path, parser diagnostics, or backend details
Use formatCompileError(result.error) to render a stable CLI or log-friendly message.
Run the C++ test suite with CTest:
ctest --test-dir build --output-on-failureReplace build with your configured build directory, for example build-llvm20.
Optional Python integration tests:
python3 tests/integration/cli/test_analyzer.py
CORETRACE_ANALYZER_BIN=./build/coretrace_concurrency_analyzer \
python3 -m pytest tests/integration/cli/test_human_output_golden.py- Format:
./scripts/format.sh - Check:
./scripts/format-check.sh - Naming and style conventions: see
CONTRIBUTING.md - Fixture corpora under
tests/fixtures/are excluded from clang-format checks
This project is licensed under the Apache License 2.0. See LICENSE and NOTICE.