Goto programs validation#3191
Conversation
| const irep_idt &identifier = | ||
| to_symbol_expr(function_call.function()).get_identifier(); | ||
|
|
||
| DATA_CHECK(function_map.find(identifier) != function_map.end(), ""); |
There was a problem hiding this comment.
Please fill the comment (also below).
| DATA_CHECK( | ||
| fun.second.body.instructions.back().is_end_function(), | ||
| "last instruction should be of end function type"); | ||
| }; |
There was a problem hiding this comment.
Is the semicolon necessary?
There was a problem hiding this comment.
erm..nope! Well spotted.
f3410eb to
81732d2
Compare
81732d2 to
1de2516
Compare
martin-cs
left a comment
There was a problem hiding this comment.
Right direction but not finished yet.
| class test_for_function_addresst : public const_expr_visitort | ||
| { | ||
| private: | ||
| const irep_idt match_id{ID_address_of}; |
There was a problem hiding this comment.
??? Why not just use ID_address_of directly?
| if(!test_for_function_address.identifiers.empty()) | ||
| { | ||
| for(auto &identifier : test_for_function_address.identifiers) | ||
| DATA_CHECK(function_map.find(identifier) != function_map.end(), |
There was a problem hiding this comment.
Does this work for pre-linking goto-programs?
There was a problem hiding this comment.
@martin-cs
That got us thinking... and I rewrote the following check (which now has the comments below)
/// Check that goto-programs that have a body end with an END_FUNCTION
/// instruction.
///
/// NB functions that are only declared, and not used will not appear in the
/// function map. Functions that are declared only and used to e.g.
/// initialise a function pointer will have no body.
void check_last_instruction();
|
@tautschnig suggested that I chime in here: const source_locationt &sloc_of(const goto_programt::const_targett &ins) const
{
return ins->code.source_location().is_not_nil()
? ins->code.source_location()
: ins->source_location;
}
source_locationt &sloc_of(const goto_programt::const_targett &ins)
{
return const_cast<source_locationt &>(
static_cast<const dispatch_loop_detectort &>(*this).sloc_of(ins));
}
const source_locationt &sloc_of(const goto_programt::instructiont &ins) const
{
return ins.code.source_location().is_not_nil() ? ins.code.source_location()
: ins.source_location;
}
source_locationt &sloc_of(const goto_programt::instructiont &ins)
{
return const_cast<source_locationt &>(
static_cast<const dispatch_loop_detectort &>(*this).sloc_of(ins));
} |
9ccd64d to
1cb3da1
Compare
|
@karkhaz Many thanks for bringing this up. A check is now in place - not currently active as the code needs patching to ensure both locations are set. I'll raise an issue for that. |
f56e3c5 to
91ace58
Compare
e7d94af to
1fb1129
Compare
allredj
left a comment
There was a problem hiding this comment.
✔️
Passed Diffblue compatibility checks (cbmc commit: 1fb1129).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/102487466
src/cbmc/cbmc_parse_options.cpp
Outdated
| goto_model.validate( | ||
| validation_modet::INVARIANT, | ||
| goto_model_validation_optionst{ | ||
| goto_model_validation_optionst::set_optionst::all_true}); |
There was a problem hiding this comment.
Given how often that all_true option is used, simply make that the default?
There was a problem hiding this comment.
Done. Also for INVARIANT.
src/goto-programs/goto_program.cpp
Outdated
| vm, | ||
| code.source_location().is_not_nil(), | ||
| "each instruction code field, must have non nil source location"); | ||
|
|
There was a problem hiding this comment.
Note that not every instruction has a code member, so this will fail.
There was a problem hiding this comment.
Action taken (after team chat). In commit message (reproduced here in case it helps):
Removed previously disabled checks :
Not every instruction has a code member - so removed checks that both
instruction sourcelocation and code sourcelocation are set and identical
Remove also remaining check that every instruction have a non-nil
sourcelocation as this would have to be optional (if enabled fails
many regression tests). This also simplifies considerably the overall
validation pass (removes much passing around of the options structure).
| /// - lhs of every \ref code_function_callt instruction is nil | ||
| /// - all return types are void (of both calls and functions themselves) | ||
| void check_returns_removed(); | ||
|
|
There was a problem hiding this comment.
removed in validate_goto_model.cpp
DATA_CHECK(
vm,
goto_function.type.return_type().id() == ID_empty,
"functions must have empty return type");
| { | ||
| const code_function_callt &function_call = | ||
| to_code_function_call(instr.code); | ||
| DATA_CHECK( |
There was a problem hiding this comment.
Use instr.get_function_call().
| if(instr.is_function_call()) | ||
| { | ||
| const auto &function_call = to_code_function_call(instr.code); | ||
| DATA_CHECK( |
| // check functions that are called | ||
| if(instr.is_function_call()) | ||
| { | ||
| const auto &function_call = to_code_function_call(instr.code); |
| auto &instructions = goto_function.body.instructions; | ||
|
|
||
| goto_programt::instructiont instruction; | ||
| instruction.make_end_function(); |
There was a problem hiding this comment.
instructiont::make_end_function is deprecated -- use goto_programt::make_end_function
| goto_programt::instructiont instruction; | ||
| instruction.make_end_function(); | ||
| instructions.push_back(instruction); | ||
| instructions.back().source_location.id("id_any_valid_id"); |
There was a problem hiding this comment.
The source_locationt ireps don't have an ID.
| // required as goto_function.validate checks (if a function has a body) that | ||
| // the last instruction of a function body marks the function's end. | ||
| goto_programt::instructiont end_function_instruction; | ||
| end_function_instruction.make_end_function(); |
Removed previously disabled checks: Not every instruction has a code member - so removed checks that both instruction sourcelocation and code sourcelocation are set and identical Remove also remaining check that every instruction have a non-nil sourcelocation as this would have to be optional (if enabled fails many regression tests). This also simplifies considerably the overall validation pass (removes much passing around of the options structure). Removes check on function return type - this will be preserved (diffblue#4266) goto_model::validate now has default parameters. Minor fixes.
Removed previously disabled checks: Not every instruction has a code member - so removed checks that both instruction sourcelocation and code sourcelocation are set and identical Remove also remaining check that every instruction have a non-nil sourcelocation as this would have to be optional (if enabled fails many regression tests). This also simplifies considerably the overall validation pass (removes much passing around of the options structure). Removes check on function return type - this will be preserved (diffblue#4266) goto_model::validate now has default parameters. Minor fixes.
Although additional checks may hold, they have their own unit tests and it is these tests that should fail when these checks fail.
73e94b4 to
6ba2cf4
Compare
allredj
left a comment
There was a problem hiding this comment.
✔️
Passed Diffblue compatibility checks (cbmc commit: 6ba2cf4).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/102836757
martin-cs
left a comment
There was a problem hiding this comment.
As a start this is reasonable but there are many invariants it doesn't check (whether variables follow the DECL - use - DEAD cycle, scoping of variables, whether exprt's are well formed, etc.). I presume these will be in follow-up patches.
| bool function_pointer_calls_removed = true; | ||
| bool check_returns_removed = true; | ||
| bool check_called_functions = true; | ||
|
|
There was a problem hiding this comment.
If this is intended to be comprehensive right now, it should also check for vector and complex. If this is intended to be a general framework then it's not super urgent.
There was a problem hiding this comment.
Its a general framework right now - everyone is invited to fill in the additional checks :-)
2019-03-01
NB Will squash prior to merge.
Fairly major changes after review by Kroening.
2019-02-27
There will be a follow up PR to this to re-enable the checks for an entry-point ("validate_goto_modelt::entry_point_exists()")
This is temporarily disabled as some (<6) regression tests have no entry point, and in some
cases this is intentional (e.g. testing json-ui warnings)
2018-12-21
The first two commits are not new. Changes to reviews have been put into separate commits - but the last commit is the most consequential as it deals with @daniel.poetzl’s request for a change of location and I break the source location tests out into a new unit test file.
• Relevant to this PR (the bigger picture) are also the remarks on
#751 & more recently on #3188
These are not addressed directly here as such, but I am flagging these as context/reminders for reviewers/ going forward.
In particular:
#3188 (comment)
There are several (hopefully nested but maybe not) ideas of what a "valid" goto-program is that are implicitly assumed by different parts of the code. Part of the point of all of this validity checking was to map out, clarify and correct these. Parts of the code assume that there are no RETURN instructions, parts assume that there are and things like the last instruction (apart from END_INSTRUCTION) should be return. I was asking how your validity checks will cope with this. It seems there are two options:
@peterschrammel added:
There are several kinds of Goto program that (should) form a subset chain.
The transformations in process_Goto_program() go through this chain in several feature reduction passes.
Certain analyses may require a specific kind of Goto program.
So, 'valid' depends on the stage of processing. We should make this explicit.