Repository navigation
verify: Treat the contract constructs by their meaning in Clang's own analyses - #37
Merged
Merged
Conversation
…ssions and statements.
SwayamInSync
force-pushed
the
fix/contract-node-sites
branch
from
October 18, 2026 14:19
19dda28 to
9c72d10
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.
Six
switches over statement classes in Clang's own code did not list the contract classes (ForallExpr,ExistsExpr,ContractChooseExpr,OldExpr,ResultExpr, and the ghost statements), as the build warns (enumeration value 'ForallExprClass' not handled in switch). Three of them fell through tollvm_unreachable, which a release build compiles to undefined behavior, one let the analyzer drop the path, and one hid the constructs from libclang:Each site now handles the classes by their meaning: a contract expression is never evaluated, and ghost code emits no code.
Sema::canThrow: a contract expression or ghost statement cannot throw.CheckICE(C++98 integral constant expressions): a contract expression is not one.Expr::HasSideEffects: a contract expression has its operands' side effects, as if it were evaluated, which is what the fallthrough already computed; it is now listed with the other expressions that recurse.cannot yet mangle ExistsExpr expression), as other expressions without a mangling are. Since verify: Compile contracts in templates, ignoring a template's contracts with a warning #28 one reaches it in a template's signature, and main mangles it to nothing:template <class T> void test(int (&)[sizeof(cppverify::exists(k, 0, 3, k == T()), T())])instantiated forintis_Z4testIiEvRAszcmcvT__E_i, a comma (cm) with one operand, which neitherllvm-cxxfiltnorc++filtaccepts.CXCursor_NotImplemented, an invalid cursor that clients skip, and in a clause its operands went with it.CI fails when the build log shows a
switchover statement classes that misses one of them, so a new upstreamswitchcannot miss them silently.Testing:
Verify/contracts_in_clang_analyses.cppchecksnoexcepton a contract expression (C++17), a contract expression in an integral constant expression (C++98), and the analyzer's null-dereference warnings after a ghost block and aftercppverify::check, and the mangler's error for the template above. Each of its four runs fails on main (two by a crash and a hang, one by the missing warnings, one by the missing error). Removing the cases fromcanThrow, fromCheckICE, or from the mangler, or the CFG's omission, fails it; removing them from the analyzer'sswitchdoes not, since the CFG never gives it those nodes.Index/cppverify-cursors.cppchecks the cursor of each construct and of its operands; it fails on main and without the libclang cases. The CI check matches the ten warnings ofSemaExceptionSpec.cppin each of two rebuilds of main's Sema, and none in a build of all of Clang on this branch (clang-test-depends, the target CI builds), which found the libclang site.Checked on main together with the change of #38, for quantifiers in executable code, whose files are disjoint from these: in a build with assertions every Clang test passes (48,612), as do the Verify suite and the libclang and libIndex tests of the constructs; in a release build the Verify suite gives 417 passed, 1 unsupported. A verdict differential against main over the Verify sources, the new test left out since main hangs on it, changes only the new test of #38 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; these changes do not reach the verifier's queries. No time changed.Rebased onto main after #28, #32, and #34, with the mangler's test added: Verify suite 421 passed, 1 unsupported; in a build with assertions this test,
CodeGenCXX/mangle-fail.cpp,Verify/template_contracts.cpp, and the libclang test pass.