-
Notifications
You must be signed in to change notification settings - Fork 274
New goto checker interfaces [blocks: 3579] #3564
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New goto checker interfaces [blocks: 3579] #3564
Conversation
91f3b5b
to
c54e65f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚫
This PR failed Diffblue compatibility checks (cbmc commit: c54e65f).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/94498702
Status will be re-evaluated on next push.
Please contact @peterschrammel, @thk123, or @allredj for support.
Common spurious failures:
- the cbmc commit has disappeared in the mean time (e.g. in a force-push)
- the author is not in the list of contributors (e.g. first-time contributors).
The incompatibility may have been introduced by an earlier PR. In that case merging this
PR should be avoided unless it fixes the current incompatibility.
c54e65f
to
d21bdf2
Compare
d21bdf2
to
1968915
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚫
This PR failed Diffblue compatibility checks (cbmc commit: 1968915).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/94899319
Status will be re-evaluated on next push.
Please contact @peterschrammel, @thk123, or @allredj for support.
Common spurious failures:
- the cbmc commit has disappeared in the mean time (e.g. in a force-push)
- the author is not in the list of contributors (e.g. first-time contributors).
The incompatibility may have been introduced by an earlier PR. In that case merging this
PR should be avoided unless it fixes the current incompatibility.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some naming suggestions, otherwise looks fine
src/goto-checker/goto_checker.h
Outdated
/// subsequent call to operator(). | ||
/// `goto_checkert` derivatives shall be implemented in a way such | ||
/// that repeated calls to operator() shall return the next FAILed | ||
/// property until eventually not returning any FAILing properties. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This last sentence is not clear, since the operator does not return a property.
And this sounds like something we would want to be enforced by the interface.
/// a goto model. It typically uses, but doesn't have to use, a | ||
/// `goto_checkert` to iteratively determine the verification result | ||
/// of each property. | ||
class goto_verifiert |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think checker and verifier can easily be confused and the difference in meaning is not clear. I also can't find a very good naming for this two classes. Maybe this class is the one that should be goto_checker
and the other one could be named something like incremental_goto_checker
? since it's only checking until the next counter-example is found.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 - I also believe, but am not really sure, that the incremental nature is the difference? If this is correct, then the naming proposed by @romainbrenguier seems good; if it isn't, then the documentation needs to be revisited.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Going with incremental_goto_checkert
due to lack of more intuitive names.
src/goto-checker/properties.cpp
Outdated
propertiest initialize_properties(const abstract_goto_modelt &goto_model) | ||
{ | ||
propertiest properties; | ||
forall_goto_functions(it, goto_model.get_goto_functions()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⛏️ an ranged-for would be preferred here, to make explicit that it
is used just to access the data and not for other iterator operations. 🐇
src/goto-checker/properties.cpp
Outdated
|
||
const source_locationt &source_location = i_it->source_location; | ||
|
||
irep_idt property_id = source_location.get_property_id(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⛏️ intermediary variable source_location
is superfluous
src/goto-checker/properties.cpp
Outdated
|
||
const source_locationt &source_location = i_it->source_location; | ||
|
||
irep_idt property_id = source_location.get_property_id(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be const
src/goto-checker/properties.h
Outdated
struct property_infot | ||
{ | ||
/// A pointer to the corresponding goto instruction | ||
goto_programt::const_targett location; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The naming is a bit confusing as I would expect location
to be a source_locationt
. Could it be renamed to something like instruction_pointer
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Going with pc
which is used in other classes such as goto_tracet
.
src/goto-checker/goto_checker.h
Outdated
/// the state of the analysis that it performs (e.g. goto-symex, solver, etc). | ||
/// It is not responsible for maintaining outcomes (e.g. property results, | ||
/// counterexamples, etc). However, an implementation may restrict the | ||
/// sets of properties it is asked to check (e.g. only sequences of subsets). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"subsets" of what?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please check whether it's clearer now.
src/goto-checker/goto_checker.h
Outdated
/// one by one to the caller. | ||
/// An implementation of `goto_checkert` is responsible for maintaining | ||
/// the state of the analysis that it performs (e.g. goto-symex, solver, etc). | ||
/// It is not responsible for maintaining outcomes (e.g. property results, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does "It" refer to the implementation? I'd use "An implementation of goto_checkert
is not responsible for maintaining outcomes ..."
/// a goto model. It typically uses, but doesn't have to use, a | ||
/// `goto_checkert` to iteratively determine the verification result | ||
/// of each property. | ||
class goto_verifiert |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 - I also believe, but am not really sure, that the incremental nature is the difference? If this is correct, then the naming proposed by @romainbrenguier seems good; if it isn't, then the documentation needs to be revisited.
src/goto-checker/goto_checker.h
Outdated
{ | ||
/// The goto checker may be able to determine the results for more | ||
/// properties if operator() is called again. | ||
HAVE_MORE, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PARTIAL_RESULT
?
src/goto-checker/goto_checker.h
Outdated
}; | ||
|
||
/// Check whether the given properties with status UNKNOWN or newly | ||
/// discovered properties hold |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Newly discovered by the checker or by the caller?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both, unfortunately.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggest adding that to the comment then
src/goto-checker/goto_checker.h
Outdated
/// After returning DONE, another call to operator() with the same | ||
/// properties will return DONE and leave the properties' results unchanged. | ||
/// If there is a property with status FAIL then its counterexample | ||
/// can be retrieved by calling `build_error_trace` before any |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This sounds like it binds an implementation into an odd stateful implementation, how about just passing a boolean to operator()
to indicate whether you want traces built or not?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- That will not make it less stateful if you still have to call a function to retrieve the trace.
- A bool
should_build_trace
together withoptional<goto_tracet>
has the problem of what to return when not buildlng a trace and the status is HAVE_MORE... an empty trace? - One could have two operators: one that returns
optional<goto_tracet>
and another one that returns a status. The caller can pick which one to use depending on whether they want traces or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was envisaging something like std::pair<statust, optionalt<tracet>>
, but option 3 sounds pretty good to me
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm... having to decide whether I want a trace or not before actually knowing which property failed is a limitation for certain algorithms (e.g. synthesising invariants while checking properties: I don't need a counterexample when I fail due to a non-inductive invariant candidate, but I'd like to have the counterexample when a property fails).
So, I think the two operations should be separate. I'm not worried about the statefulness because it is quite natural.
src/goto-checker/properties.h
Outdated
/// The result status of a property | ||
enum class property_resultt | ||
{ | ||
/// The property was not reached (also used for initialization) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not reached yet, I guess -- what's the difference between this and UNKNOWN?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would rather be for unreachable assertions (for instance in methods that are loaded but not called from the entry point)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That seems the same as NOT_REACHABLE
. Perhaps they should be NOT_REACHABLE
and NOT_SATISFIABLE
(can get there, but can't concurrently satisfy the condition)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll add examples to clarify these notions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Assume we run a path-symex that does at most 5 unwindings and stops
before exploring the else branch (*).
int main(int argc, char **argv)
{
if(argc < 0)
assert(0); // NOT_REACHABLE
assert(argc >= 0); // PASS
if(argc < 5)
{
for(int i=0; i<10; i++)
{
assert(i == 2) // FAIL
assert(i != 15); // UNKNOWN
}
}
else // (*)
{
assert(0); // NOT_REACHED
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about NOT_REACHED
-> NOT_CHECKED
? NOT_REACHED
and NOT_REACHABLE
are so close to synonyms it will surely confuse.
Re: naming both the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be good to apply Romain's comments, especially about the ranged for.
src/goto-checker/goto_checker.h
Outdated
/// Check whether the given properties with status UNKNOWN or newly | ||
/// discovered properties hold | ||
/// \param [out] properties: Updates those properties whose | ||
/// results have been determined. Newly discovered properties are added. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⛏️ Argument descriptions should talk about the arguments themselves, not the function. Maybe rephrase to:
Properties updated to whether their results have been determined
.
src/goto-checker/goto_checker.h
Outdated
/// property until eventually not returning any FAILing properties. | ||
virtual statust operator()(propertiest &properties) = 0; | ||
|
||
/// This builds and returns the counterexample |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⛏️ Redundant This
src/goto-checker/properties.cpp
Outdated
UNREACHABLE; | ||
} | ||
|
||
/// Returns the properties in the goto model |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⛏️ Returns
-> Return
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⛏️ And perhaps document that this function also initialises the properties (it's clear from the name, but it's confusing that the documentation doesn't match the function name).
src/goto-checker/properties.cpp
Outdated
propertiest properties; | ||
forall_goto_functions(it, goto_model.get_goto_functions()) | ||
{ | ||
if(!it->second.is_inlined() || it->first == goto_functionst::entry_point()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⛏️ Maybe document why we exclude all inlined functions except the entry point?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a good question. It seems legacy to me and we should be able to remove this filter.
The first condition used to be necessary in times where goto_partial_inline
was used.
The second condition is unclear to me (is the entry point marked inlined?). @kroening, @tautschnig, any insights?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the entry point were marked as inlined that would just seem wrong (and useless) to me. I'd suggest to remove this second part of the condition.
@peterschrammel Please send a ping when this one is ready for (re-)review. |
1968915
to
e209fce
Compare
ping |
src/goto-checker/goto_verifier.h
Outdated
|
||
/// An implementation of `goto_verifiert` checks all properties in | ||
/// a goto model. It typically uses, but doesn't have to use, a | ||
/// `goto_checkert` to iteratively determine the verification result |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be incremental_goto_checkert
?
{ | ||
return properties; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs a virtual ~goto_verifiert() = default;
@@ -0,0 +1,21 @@ | |||
/*******************************************************************\ | |||
|
|||
Module: Goto Checker Interface |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit-pick: add "Incremental"
FOUND_FAIL, | ||
/// The goto checker has returned all results for the given set | ||
/// of properties. | ||
DONE |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So what's the initial status to use then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why would you need an initial status?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There always has to be some "status" - otherwise it's a "result" I'd say?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made naming of result vs status more consistent
virtual statust operator()(propertiest &properties) = 0; | ||
|
||
/// Builds and returns the counterexample | ||
virtual goto_tracet build_error_trace() const = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we have move operators so that we can reasonably pass a goto_tracet
by value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be implicit
src/goto-checker/properties.cpp
Outdated
for(const auto &function_pair : goto_functions.function_map) | ||
{ | ||
if(!function_pair.second.is_inlined() || | ||
function_pair.first == goto_functionst::entry_point()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comment on the earlier version: the second condition should be removed.
src/goto-checker/properties.cpp
Outdated
property_infot &property = | ||
properties[i_it->source_location.get_property_id()]; | ||
property.result = property_resultt::NOT_CHECKED; | ||
property.pc = i_it; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A property_infot
should have a constructor so that we can do
properties.emplace(i_it->source_location.get_property_id(), {property_resultt::NOT_CHECKED, i_it});
here.
e209fce
to
f1f62b2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️
Passed Diffblue compatibility checks (cbmc commit: f1f62b2).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/97146777
f1f62b2
to
badcae8
Compare
incremental_goto_checkert: returns a trace or 'done' goto_verifiert: uses incremental_goto_checkert to check a set of properties property utilities
badcae8
to
a1100e1
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✔️
Passed Diffblue compatibility checks (cbmc commit: a1100e1).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/97160722
This will replace
safety_checkert
andproperty_checkert
, and become the basis for breaking up thebmct
monolith.Based on #3557. Review only last commit.
I'm not happy with the naming of
goto_checkert
, which doesn't intuitively describe what it is doing - hoping for better suggestions from the reviewers.