-
Notifications
You must be signed in to change notification settings - Fork 285
Cleanup error handling of cbmc/ folder #2703
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
Cleanup error handling of cbmc/ folder #2703
Conversation
martin-cs
left a comment
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.
Approve subject to addressing the comments.
src/cbmc/symex_coverage.cpp
Outdated
| goto_programt::const_targett end_function= | ||
| --gf_it->second.body.instructions.end(); | ||
| assert(end_function->is_end_function()); | ||
| INVARIANT(end_function->is_end_function(), |
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.
DATA_INVARIANT I think.
src/cbmc/symex_coverage.cpp
Outdated
| "Last instruction in a function body is end function"); | ||
| file_name=end_function->source_location.get_file(); | ||
| assert(!file_name.empty()); | ||
| INVARIANT(!file_name.empty(), |
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.
DATA_INVARIANT
src/util/parse_options.cpp
Outdated
| catch(invalid_user_input_exceptiont &e) | ||
| { | ||
| std::cerr << e.what() << "\n"; | ||
| return CPROVER_EXIT_EXCEPTION; |
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.
CPROVER_EXIT_USAGE_ERROR ?
src/cbmc/bmc_cover.cpp
Outdated
| } | ||
|
|
||
| assert(cover_goals.size()==goal_map.size()); | ||
| INVARIANT(cover_goals.size()==goal_map.size(), |
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.
apply clang-format
| int res = parse_options.main(); | ||
|
|
||
| #ifdef IREP_HASH_STATS | ||
| std::cout << "IREP_HASH_CNT=" << irep_hash_cnt << '\n'; |
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.
indentation
src/util/exception_utils.h
Outdated
| std::string what() const noexcept | ||
| { | ||
| std::string res; | ||
| res += "\nInvalid User Input Exception\n"; |
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'd remove the word Exception.
src/cbmc/cbmc_solvers.cpp
Outdated
| error() << "sorry, this solver does not support beautification" << eom; | ||
| throw 0; | ||
| throw invalid_user_input_exceptiont( | ||
| "Sorry, this solver does not support beautification", |
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 this solver -> the chosen solver ? (same below)
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 drop "sorry" - we don't apologise elsewhere either.
src/util/parse_options.cpp
Outdated
| } | ||
| catch(invalid_user_input_exceptiont &e) | ||
| { | ||
| std::cerr << e.what() << "\n"; |
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.
No. This must go into a message stream.
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 was like this in the original design, but then I saw during rebasing on develop, that recently a similar change was eliminated, so I thought that it must have been that this is more appropriate. If I am also to do that now, I will need to add a messaget into parse_options_baset, which will require changes in various places
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 found exactly what I was referring to. So parse_options_baset doesn't seem to inherit from messaget and doesn't contain a reference to a messaget. If I do this, then I get loads of compilation errors regarding ambiguous calls to things like status(), get_message_handler(), etc.
It's also consistent with the rest of the file. parse_options_baset::usage_error(), parse_options_baset::unknown_options_msg() seem to be following the same pattern of using std::cerr
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.
At the risk of contradicting @peterschrammel: I don't think a message stream can be used here, because setting up the desired one requires successful parsing of command-line options (picking, e.g., JSON output with a verbosity of 5). Hence I'm with @NlightNFotis that using std::cerr is correct here.
src/cbmc/cbmc_main.cpp
Outdated
| int main(int argc, const char **argv) | ||
| { | ||
| #endif | ||
| try |
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 squash this with the first commit that introduce the change that you undo here.
tautschnig
left a comment
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 looks like a good direction of work to me, but I'd suggest to make this as clean as possible unless there is a need to rush it in? If so, please break it apart into separate pull requests as the need for further discussion varies widely among the commits.
src/cbmc/bmc_cover.cpp
Outdated
|
|
||
| assert(cover_goals.size()==goal_map.size()); | ||
| INVARIANT(cover_goals.size()==goal_map.size(), | ||
| "We add coverage for each goal"); |
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 coding standard says that error messages start with a lower-case letter.
src/cbmc/symex_coverage.cpp
Outdated
| assert(cov.second.num_executions>0); | ||
| INVARIANT(cov.second.num_executions>0, | ||
| // FIXME I don't know what this means | ||
| "Number of executions most be positive"); |
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 a PRECONDITION. A coverage entry can only exist when a location has actually been covered in at least one execution.
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's a problem with that, in that the PRECONDITION according to documentation should only contain unmodified arguments to a function, but I can change it, since it makes it easier to drop the message which appears incorrect as well.
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.
You might use a DATA_INVARIANT, paraphrasing in the message what I said above (coverage entries can only exist with at least one execution).
src/cbmc/cbmc_main.cpp
Outdated
| catch(invalid_user_input_exceptiont &e) | ||
| { | ||
| std::cerr << e.what() << std::endl; | ||
| } |
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.
Design note: I don't think such an exception should propagate out of parse_options for the key task of parse_options is to parse options? If anything goes wrong it should and does return an error code. Having both error codes and exceptions seems wrong 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.
This is a comment on outdated code. The error handling is now being contained in parse_optionst::main(), and doesn't escape that context. parse_optionst::main() will indeed return an error code, that is is being handled in cbmc_main
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.
Btw, it also appears that parse_optionst was mainly useful during the evolution of the code, but now that has been rebased, its usefulness has diminished, so I am trying to eliminate it.
src/util/exception_utils.h
Outdated
| { | ||
| } | ||
|
|
||
| std::string what() const noexcept |
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 don't think this should be a header-only class. Add a cpp file and move the implementation of at least this function over there. No need to inline it everywhere, will just unnecessarily increase the size of the binary.
src/cbmc/cbmc_solvers.cpp
Outdated
| void cbmc_solverst::no_beautification() | ||
| { | ||
| if(options.get_bool_option("beautify")) | ||
| bool beautify = options.get_bool_option("beautify"); |
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 is this temporary introduced?
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 remember I had a reason in the beginning but I may have refactored it enough that it's now unneeded.
src/cbmc/cbmc_solvers.cpp
Outdated
| error() << "sorry, this solver does not support beautification" << eom; | ||
| throw 0; | ||
| throw invalid_user_input_exceptiont( | ||
| "Sorry, this solver does not support beautification", |
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 drop "sorry" - we don't apologise elsewhere either.
src/cbmc/cbmc_solvers.cpp
Outdated
| if(options.get_bool_option("all-properties") || | ||
| options.get_option("cover")!="" || | ||
| options.get_option("incremental-check")!="") | ||
| bool all_properties = options.get_bool_option("all-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.
const (here and below)
src/cbmc/cbmc_solvers.cpp
Outdated
| options.get_option("cover")!="" || | ||
| options.get_option("incremental-check")!="") | ||
| bool all_properties = options.get_bool_option("all-properties"); | ||
| bool cover = options.get_option("cover") != ""; |
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.
While you're cleaning this up: use .is_set instead of get_option(...) != ""
src/util/parse_options.h
Outdated
| bool parse_result; | ||
| }; | ||
|
|
||
| class parse_optionst : public parse_options_baset |
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'm not sure we need this derived class: can't it just be changed in parse_options_baset and make everyone benefit without changes?
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 not needed anymore. I have eliminated it.
src/util/exception_utils.h
Outdated
| res += "Option: " + option + "\n"; | ||
| res += "Reason: " + reason; | ||
| // Print an optional correct usage message assuming correct input parameters have been passed | ||
| res += correct_input.empty() ? "\n" : " Try: " + correct_input + "\n"; |
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 "Try: ..." portion should better be on a new line.
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.
@tautschnig Suggested to drop the Try altogether, and just add in the various constructor callsites so that it reads more like a sentence.
3c9225c to
f06cbea
Compare
|
@peterschrammel You have a red (blocker) cross applied to this. All your points have now been addressed. Can you take a look now and tell me if there's anything more you would want explained or changed? |
|
@tautschnig Hi, can you also take a look to see if it's closer to what you expect? It's the same as before, but cleaned up and the changes suggested applied. The only extra is the last commit, which I thought makes sense to not be squashed, as it is a good atomic change (it replaces |
src/cbmc/cbmc_main.cpp
Outdated
| #endif | ||
| cbmc_parse_optionst parse_options(argc, argv); | ||
| try | ||
| { |
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 change is undone two commits later. Why is this change made at all?
|
|
||
| #include "exception_utils.h" | ||
|
|
||
| std::string invalid_user_input_exceptiont::what() const noexcept |
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.
Ideally, there should also be a version hat can serialise into json and XML in a more structure way (in a future PR).
src/cbmc/bv_cbmc.cpp
Outdated
| } | ||
| DATA_INVARIANT( | ||
| expr.operands().size() != 4, | ||
| "waitfor expression is expected to have four operands"); |
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.
@chrisr-diffblue, @martin-cs, the source location is lost here. Would it be possible to have variants of the INVARIANT macros that take a source location explicitly so that it can be output in a structured way?
|
@NlightNFotis, the changes in f257667 that are later undone in 017c1b0 need to be removed. |
|
Could this one please be rebased and cleaned up with regard to the comments raised by @peterschrammel - then it might be good to go. |
|
@tautschnig Yes, this is waiting for us to decide on a clean way to create a more structured, "variadic" invariant, that can take a |
Apart from the fact that the specific bit of code that @peterschrammel commented on is now gone from the repository: can't we just solve this by doing |
f06cbea to
3bd4322
Compare
|
@tautschnig I have now rebased the PR and I'm waiting for CI to pass. Then it should be good to go. We decided to go ahead with this now and we can implement the structured invariants later. |
tautschnig
left a comment
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 are still changes in the individual commits that just modify what was added in one of the other commits in this series. Some soft reset and the use of git add -p seems to be due.
src/cbmc/cbmc_solvers.h
Outdated
| prop_convt &prop_conv() const | ||
| { | ||
| assert(prop_conv_ptr!=nullptr); | ||
| PRECONDITION(prop_conv_ptr!=nullptr); |
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: clang-format.
allredj
left a comment
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: 3bd4322).
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).
3bd4322 to
2e6d6a0
Compare
|
@tautschnig I have implemented all of the changes suggested in your comments, and Peter's comments (bar the structured invariant). I have also pinged Peter for a re-review. Can you take a look at it and green-light it if you think it's good to go? |
| propt &prop() const | ||
| { | ||
| PRECONDITION(prop_ptr!=nullptr); | ||
| PRECONDITION(prop_ptr != nullptr); |
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 still in the wrong commit, fixing up a change from an earlier commit.
| cbmc_parse_optionst parse_options(argc, argv); | ||
|
|
||
| int res=parse_options.main(); | ||
| int res = parse_options.main(); |
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.
Unnecessary change?
| std::string res; | ||
| res += "\nInvalid User Input\n"; | ||
| res += "Option: " + option + "\n"; | ||
| res += "Reason: " + reason; |
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.
Wishlist: please add a test for this, i.e., intentionally use CBMC with incorrect options.
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 you need this as part of this PR, or can it go in as part of a follow up PR for example?
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.
Up to you, as long as it happens at some 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.
We plan to make some further improvements to user error handling, so we'll definitely be adding suitable test cases as part of that work, so I'd be happy for this PR to go in, with tests following as part of the later improvements.
allredj
left a comment
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: 2e6d6a0).
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).
Perform various cleanups of the error handling mechanisms in the
src/cbmc/folder. These include turningasserts intoINVARIANTs andPRECONDITIONs as well as a new custom exception class.