Repository navigation
verify: Reject a quantifier in executable code - #38
Merged
Merged
Conversation
…in executable code.
…where a quantifier belongs.
…instantiated or not.
SwayamInSync
force-pushed
the
fix/executable-quantifiers
branch
from
October 18, 2026 14:42
a52c770 to
3932193
Compare
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.
A quantifier in executable code compiled without a diagnostic, to
poison:CodeGen returns
poisonfor every contract expression as a safety net, since contract expressions should never reach it, and Sema rejectscppverify::choosein executable code (err_choose_in_executable_code) but notcppverify::forallorcppverify::exists. The verifier reads the quantifier as a quantifier, so a function could verify and compile to undefined behavior.ExecutableSpecUseFinder, which already rejects spec functions, ghost variables, collections, andchoosein executable code, now rejects the quantifiers too, with the error that namedchooseand now names the construct (cppverify::forall exists only for verification and cannot be used in executable code; use it in a contract, ghost block, or spec or proof function). A construct is reported once, with what it contains, rather than once for each nested quantifier, choice, or spec call inside it. Contracts, ghost code,cppverify::check, and unevaluated operands (sizeof,decltype,noexcept) are unaffected.Testing:
Verify/errors_quantifier_in_executable.cppchecks a quantifier returned, used as an initializer, nested in another, in a global initializer, and in two templates (one never instantiated, one instantiated twice, each reported once), and that quantifiers in a contract, acheck, a ghost block, andsizeofcompile with nopoisonin the IR. It fails on main. Each of six mutations fails it orerrors_choose.cpp: not checkingforall,exists, orchoose; reporting a nested quantifier again; reporting one in ghost code; and reporting one again for each instantiation of its template.errors_namespaced.cppwrote a bareforall(underusing namespace cppverify) in areturnstatement. The parser recovers it ascppverify::forall, which now also draws the new error, so the test writes it in acppverify::check, where a quantifier belongs, and still checks its one error.Checked on main together with the change of #37, for Clang's analyses, whose files are disjoint from these: in a build with assertions every Clang test passes (48,612), as does the Verify suite; in a release build the Verify suite gives 417 passed, 1 unsupported. A verdict differential against main over the Verify sources changes only the new test and
decode_uleb128_canonical(llvm_uleb128.cpp, withroundtrip_uleb128after it), which timed out in main's run and verified here, as in another differential against main the same day; that file has no quantifier in executable code. No time changed.Rebased onto main after #28, after which a quantifier whose body depends on a template parameter compiles, as in the template cases: Verify suite 421 passed, 1 unsupported.