Only minimal tests are added at this point. The error conditions (like index out
of bounds) will be handled by the models. Once we have models that use
CProverString.setLength(), more comprehensive tests will be added.
This is required because otherwise a cfgt<..., goto_programt::targett> wouldn't be able to
accept const_targett as an argument to get_node_index(...) etc, which is undesirable. In
particular its own entry_mapt::keys() would not be usable. In general this ought to be some
constified version of 'I', but since base `cfgt` is currently restricted to either targett
or const_targett then statically specifying const_targett suffices.
Symex-driven loading may notice that the clinit method is not really reachable, because
we're calling a virtual method with no truly viable callees, which amounts to an assume(false).
Previously the state guard being false was taken to indicate unreachable code,
and different causes of unreachability were handled inconsistently:
* ASSUME false implied unreachability but had no effect on the guard
* --unwind or --depth being exceeded usually meant setting the guard false
This meant that expensive code downstream of an ASSUME false *was* executed, but the state
guard was maintained as usual including shrinking the guard when branches converge, while
--unwind or --depth limit breaks led to code *not* being executed (vital for these options
to function properly) but the state guard grew ever larger because the part that had gone
missing (been set to false) never got merged back in.
This commit distinguishes the two concepts: the "reachable" flag is set false whenever a
limit break OR and ASSUME false happens, but state guard maintenance continues as normal.
A new symex_unreachable_goto tries to find some way through the CFG back to reachable code;
when it can't due to loops *then* it sets the state guard to false, signifying our not
being able to figure out where the guard ought to be merged back in.
This means that ASSUME false instructions now correctly truncate execution and are
recognised as unreachable code for the purposes of state merging (leading to better
constant propagation downstream), but in some cases we may see more guard growth
because code downstream of an ASSUME false is executed less rigorously that before,
which could result in the guard not being merged or being merged later than it otherwise
would have been.
Depth and unwind limit breaks behave roughly as before, except that there is some chance
the state guard will be merged rather than discarded, reducing costs downstream.
This is to specify that we want to replace all throw instructions by
assert false.
This is useful mainly for performance reasons as it simplifies
conditions for symex, while retaining the non-exceptional behaviour of
the program.
Extract java_bytecode_language_optionst class from
java_bytecode_language class, to make it more structured by separating
the fields that are expected to remain constant during the execution
once they are initialized.
This implements constant propagation of CProverString.deleteCharAt() which in
turn enables constant propagation of StringBuilder.deleteCharAt() and
StringBuffer.deleteCharAt().
Change existing test such that it cannot be solved by constant propagation, add
a test for which verification fails, and add variants that use StringBuffer
instead of StringBuilder.
This will allow references to be replaced after the all value pairs
have been replaced.
For instance in the regression test
regression/jbmc/deterministic_assignments_json/test_char_array_pass.desc
the reference 2 wouldn't have been assigned before the end of the
assign_from_json call in which it is referenced for the first time so
its allocation size would be non-deterministic but this is fixed by this
commit.
This should be an output of the functions rather than an "info".
We make it so that assign_*_from_json functions have a return
type which reflects what the function does. That way we separate
the json to assignment conversion from the writting of code blocks,
which will ultimately allow us to rewrite references in the assignments.
This will be use in assign_from_json for json files in which the "@ref"
and "@id" entries are used, so that we can easily substitute code marked
by "@ref" by the code corresponding to the object marked by "@id".
This also move object_creation_referencet to the new header file since
it will be used there, and the allocate_array is now declared in the new
header and defined in the corresponding cpp file.
This means that generated error messages show what the particular
invariant failure actually generated was, instead of the catch framework
default of `{?}`.
`REQUIRE_THROWS_MATCHES` is the functionality built into the catch
framework for this purpose. Using it allows more concise specification
of the requirement.