Repository navigation
Static locals as their function's private state - #128
Merged
Merged
Conversation
… places at their addresses.
…ctions' private objects.
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.
Plan item B6 (globals beyond scalars), second part: static locals. Every static local that was not a constant table stopped its function (
static local variables are unsupported). Stacked on #127 (B6a), whose commits it shows until that merges.On the base
The example below (with this PR's output further down):
With this PR
first_callreturns 1 only the first time.Design
A static local with a constant initializer is a global object (B6a) that only its function names. No contract can name it: ACSL scopes contracts the same way, and Frama-C, which renames a static local to a global, leaves a function that writes one unable to state its
assigns. So it is the function's private state:inPrivateObject).VFunction::PrivateObjects) are its own statics and, after conversion, those of every function its call graph reaches (recursion, a callback through another function); an inlined helper's (B5) join the function it runs in. After a call, each of the callee's objects is changed (havocPrivateObjects), and a loop that makes the call has them in its write set. A call of any other function keeps them, and callers state nothing about them.solver.timeout; leaf by leaf they take milliseconds.a pointer to the static local value is unsupported: its function's state would escape), which is what makes the call graph a sound bound on who changes it. A static local whose initializer runs code at the first call (static int first = x;) is rejected too.cppverify::oldof a static local in its function's loop invariants is its value at entry.Tests
suite/static_locals.cpp(new): a counter that saturates, and its callers; the initializer is not the value at entry (first_call); a record and an array; a value kept across a call of an unrelated function (keeps); a value changed by a callee that calls back (owner, throughpass_on), by a direct recursive call (recursive), by a recursive call to a function with a static record (recursive_record), and by a call in a loop (looped), each a certified failure; a helper's static in the function it is inlined into (ticked); a loop invariant over a static andcppverify::oldof one; and the three rejections.lookup_tables.cpp:seen, a static array, now verifies.On a release build of this branch, the whole Verify suite passes (512 of 513, one unsupported). A first run failed
shared_logic_terms.test, which pins the size ofset_value's module: the store frame check of every function had gained|| falsewhere it has no static locals (8 more nodes before simplification, one more rewrite). The disjunct is now added only with private state, so a function without static locals lowers to the same module as before.Mutants
Each mutant below, applied alone and rebuilt, is caught by
static_locals.cpp(andlookup_tables.cppfor S11), 11 of 11:recursive_recordendssolver.timeoutinstead of failingcppverify::oldof a static local is rejectedDocs
Not done