Repository navigation
E14: contracts of files verified apart, checked together - #99
Merged
Merged
Conversation
…ps, and name an unmeasured loop beside a failure.
… proved by unrolling, and beside an unmeasured loop.
…their verdicts rely on so that each is a whole run's verdict.
…se that is executable.
…h its counterexample and backend.
…solving each after the first past the earlier failures.
…firm a failure after a loop past the checks that fail before it.
…sing the earlier failures reaches.
… once in confirmation_invariants.cpp.
…ver finds at once.
This was referenced Oct 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
#98 settles contracts across files when one run verifies them all. A build verifies each object on its own, though:
clang++ -fverify-contracts -c src/a.cppseesclamp100declared without a definition. Before this PR such a run could only warn about the contract and leave every caller that relies on itUnresolved [callee.contract]. Nothing ever checked those callers against the definition's verification insrc/mathx.cpp.Now each file verified apart can record its contracts, and one check settles the records, as the link settles symbols. This is the third step of plan item E14. On R26 (#98's example), with the wrong definition
return 101;:The check exits non-zero. With
return 100;it printsContracts: 1 proof rests on contracts of other files, 0 on one not establishedand exits 0.cpp-verify --contracts-out=FILErecords one file the same way.On the base (#98), compiling
a.cppwarns thatclamp100has no definition and reportsscaledasUnresolved [callee.contract], whether or notclamp100is right.Stacked on #98.
Design
--contracts-out=FILE, or-fverify-contracts-out=FILEon the compiler, makes a file's contracts declared without a definition hold provisionally, exactly as in a run over several files (Verifier::deferredContracts).[assumes=clamp100], so the file's own output never presents it as settled.recordContractsthen writes acppverify.contracts/1JSON record:defined: each contract the file verifies, with its key (identity and contract text, as in E14: contracts across the files of one run, and trust that stays on the definition #98), its name, whether the file establishes it, and the other files' contracts that rests on;proofs: each proof that rests on contracts of other files, with its function, the location of its declaration, and those contracts.cpp-verify --check-contracts RECORD...reads the records and settles them with the least fixpoint of E14: contracts across the files of one run, and trust that stays on the definition #98, now the classContractSettlement, whichCrossFileRun::finishuses too. So files verified apart are settled exactly as one run over them would be.--contracts-outwith several sources is an error, since a run over several files settles their contracts itself.-fverify-contracts-outis a driver option that is forwarded to-cc1(FrontendOptions::VerifyContractsOut).CodeGenActionpasses it tostartCppVerifyAsync, which writes the record once the compile-time verification ends.Tests
suite/contracts_link_check.test(new) reuses #98's inputs and covers:[assumes=clamp100]on the proofs that rest on it, with no warning.clang -fverify-contracts-out, then the check against the right and the wrong definition, the failure located at the proof's function.--contracts-outwith several sources.Each mutant below, applied alone, makes the test fail:
[assumes=...]L7 survived its first run, which tested the mutated build's
cpp-verifywith the unmutatedclang; with the mutatedclangit fails the test.Docs
Checked
clang/test/Verifyon this branch: 488 passed, 1 unsupported (darwin only), no failure. Its compiler-path lines ran aclanglinked before the last change to the record's locations, which the check of the wrong definition through the compiler now catches. Withclangrebuilt,contracts_link_check.test,contracts_across_files.test,trusted_declarations.cpp,docs_examples.test, andDriver/verify_contracts.cpppass.--contracts-out, and every run over several files, gives the output it gave on the base: every existing test passes unchanged.