Commands and flags¶
Standalone verifier¶
cpp-verify file.cpp
cpp-verify --backend=z3 file.cpp
cpp-verify --backend=bmc --unroll=3 file.cpp
cpp-verify --backend=lean --lean-out=goal.lean file.cpp
cpp-verify --check-ub file.cpp
cpp-verify --timeout=20000 file.cpp
cpp-verify --dump-ir=1,2,3,4 file.cpp
cpp-verify is a Clang tooling driver: it always adds -std=c++17 and -fverify-contracts.
Backends¶
Flag |
Meaning |
|---|---|
|
Default. Weakest precondition + Z3 (loops via contracts on the WP path). |
|
Unroll loops up to |
|
Write Lean 4 scratch-pad to |
|
BMC loop bound only. |
|
Also prove freedom from undefined behavior (signed integer overflow,
division/modulo by zero) for |
|
Per-query Z3 timeout in milliseconds (default 10000; |
Supported compiler¶
Contract syntax and -fverify-contracts exist only in this repository’s
Clang. Use the shipped ./build/bin/cpp-verify and
./build/bin/clang++ for any code that uses contracts — stock GCC or upstream
Clang reject the flag and the contract keywords. (Building cpp-verify itself from
source is independent and works with any standard host compiler.)
Compile with contracts (clang++)¶
clang++ -std=c++17 -fverify-contracts -c file.cpp -o file.o # compile + verify
clang++ -std=c++17 -fno-verify -fsyntax-only file.cpp # light syntax/semantics check
Two independent axes¶
Contract behaviour is governed by two switches, not one. Understanding the split is the whole game:
Switch (flag) |
Default |
What it controls |
|---|---|---|
Contract language
|
off |
Whether the parser recognises |
Run the prover
|
on (when contracts are on) |
Whether the SMT verifier runs (in a thread, parallel to code generation).
The verifier runs by default once contracts are enabled; |
-fno-verify is meaningless without the contract language, so it implies
-fverify-contracts (unless you explicitly pass -fno-verify-contracts). That
makes a lone -fno-verify a fast light check: it validates C++ syntax,
contract syntax, and contract semantics (the old/result placement and
bool-convertibility rules), but does not check your logic. Ideal for
editors, CI pre-flight, and LLM/agent loops.
Quick lookup¶
Flags (with |
Contracts |
Verify |
Result |
|---|---|---|---|
(none) |
off |
— |
Plain C++; |
|
on |
yes |
Full: compile and verify in parallel. A failed contract is a compile error. |
|
on (implied) |
no |
Light: parse + Sema + compile, skip the solver. Catches syntax/semantic errors, ignores logic. |
|
on (implied) |
no |
Fastest light check — no code generation either. |
|
off |
— |
Off entirely. Combined with |
The standalone cpp-verify tool always runs the full path (it adds
-fverify-contracts for you and does no code generation).
IR dump layers¶
--dump-ir accepts a comma-separated mask (or all):
Layer |
Content |
|---|---|
|
VCR IR — typed control flow, contracts preserved |
|
Passive IR — SSA, |
|
Verification condition (logical formula) |
|
Z3 translation of the VC |
Examples:
cpp-verify --dump-ir=1 file.cpp
cpp-verify --dump-ir=layer-3,layer-4 file.cpp
cpp-verify --dump-ir file.cpp # all layers
Layers are separated by a line of ====== in the output.
Testing and coverage¶
Regression tests live under clang/test/Verify/. From the repository root:
Script |
Purpose |
|---|---|
|
Run executable examples (pass / expected-fail). |
|
Fast profile merge after a normal build (from repo root). |
|
Full instrumented rebuild + sweep (slow; use when changing coverage setup). |
Set CPPVERIFY_ENABLE_COVERAGE=ON on clangVerify only — not the whole LLVM tree.
Engine headers: C++ API reference.