byte_update lowering now proceeds as follows:
1) Determine the size of the update, with the size of the object to be
updated as an upper bound. We fail if neither can be determined.
2) Turn the update value into a byte array of the size determined above.
3) If the offset is not constant, turn the object into a byte array, and
use a "with" expression to encode the update; else update the values in
place.
4) Construct a new object.
source_location.h is transitivly included in almost every translation unit.
Avoid the prefix.h include by moving the a method definition to the cpp file.
It may have worked before via the fallback to flattening of the entire
expression to a bitvector, but let's be on the safe side and construct
appropriate expressions.
This is follow-up from a discussion on PR #3998, and a comment by
@tautschnig.
This function always fails, with an exception, when given anything but a
constant_exprt.
This change means that the caller must do the type conversion. The benefit
is to make the caller more aware of the requirement that this must be a
constant, and to make the caller handle the error appropriately (with an
user-friendly error message) in case this is not possible.
The disadvantage is additional code at the call site.
These are intended as helpers for when you want to convert a string to
and integer, but don't want to assert the result (e.g. when dealing with
user input there's usually something better you can do than outright
crashing if the conversion fails), but also don't want to deal with
exceptions (which involve more code to write and read and it's easy to
handle the wrong set of exceptions, whether it is too many or too few).
sourcet contains an interator, and the current interface explicitly allows
it to be uninitialised. However, most parts of the code base access
source.pc without checking. This commit removes the option to leave the
source uninitialized.
Block coverage obtained with "cbmc --cover locations" now reports the file name
and line number of every line of source code contributing to a basic block in
the "description" field of the xml output. (The lines contributing to a block
can come from multiple files via function inlining and definitions in include
files, so reporting line numbers alone is not sufficient.)
Let's only test byte extracts within bounds for now (there is ample work to be
done to get those right), but make sure there is possible combination for each
pair of types. Endianness needs to be taken into account when constructing the
expected value. Disable any non-POD tests as they all need more work.
This commit adds templates for `expr_try_dynamic_cast` and
`type_try_dynamic_cast` where the parameter is an rvalue and the return
type is an `optionalt`. This is implemented by moving the parameter into
the `optionalt`.
Included are unit tests of the new templates, which show that they
return the types and values expected. As well as tests and a static
assert for the existing overloads which show that they still return a
pointer.
These new templates are useful in the case where we are using the
result of a function, which returns by value but only in the case where
the value can be cast to a given type. For example with the new
overloads the following code can be written -
```
exprt enig();
void handle_struct_case(const struct_exprt &struct_expr);
void myFunction()
{
if(const auto my_struct = expr_try_dynamic_cast<struct_exprt>(enig()))
handle_struct_case(*my_struct);
}
```
However without the new templates and because the old ones do not bind
to rvalues, an additional temporary variable otherwise would have to be
declared -
```
void myFunction2()
{
const exprt enigma = enig();
if(const auto my_struct = expr_try_dynamic_cast<struct_exprt>(enigma))
handle_struct_case(*my_struct);
}
```
Previously we stored a reference to the name_prefix parameter in
allocate objects that led to segfaults if it was constructed with
a temporary. Now we store a copy instead, which prevents that from
happening.
The end result of this commit is that code like the following example
can be used to construct `json_arrayt` / `json_objectt` -
```
const std::vector<std::string> input{"foo", "bar"};
const auto json_array =
make_range(input)
.map(constructor_of<json_stringt>())
.collect<json_arrayt>();
```
This commit includes -
* Constructors from iterators for json_arrayt and json_objectt, so
that the iterators from a range can be used to construct these classes.
* A `collect` member function for `ranget`, so that a chain of range
operations can finish with the construction of a resulting container
containing a collection of the results.
* A `constructor_of` template function, which provides syntactic sugar
when using `map` to call a constructor, compared to writing a new lambda
function each time such an operation is carried out.
* Unit tests covering all of the above functionality.
This new constructor facilitates the construction of instances of
`json_arrayt` which are const, because it gives a tidy way to construct
an entire `json_arrayt`.
This new constructor facilitates the construction of instances of
`json_objectt` which are const, because it gives a tidy way to construct
an entire `json_objectt`.
We strictly require Visual Studio 2015 or later in other areas of the code base,
and thus do not need to maintain bits of code that is necessarily dead.
Following the pattern in util/mathematical_types.h, expression classes that
don't exist immediately in usual programming languages are now in
util/mathematical_expr.h.
This is to avoid direct inclusion of catch.hpp when use_catch.h should be used
instead. The first guard here is module_dependencies.txt, where only
testing-utils must have "catch" listed. The second line of defense is a macro
that must be set.
Deferencing a `const` iterator which refers to a non-const value should
enable mutation of that value. This is consistent with how iterators in
the STL work. It means that we only need to provide a single const
overload of these operators, not both the const and non-const
variations. So the benefit of this commit is better consistency with the
STL and fewer operator overloads to maintain.
Given that `filter` and `concat` didn't work with const input
collections, it seems prudent to test that `map` works with const input
collections as well. There is no corresponding fix to make this test
pass in this PR.
Algorithms which are written expecting a STL container may reference a
`value_type` member, as this is the name of the member in STL
containers. Therefore this needs to be named the same way in `ranget` in
order to be compatible with such algorithms.
This commit includes a unit test of `ranget` having correct the
`value_type` defined.
It was previously impossible to iterate over a `const` range, because
you couldn't call `.begin()` on it. This fixes that issue. Changing this
to `const` does not allow the internals of the range to be mutated, as
it returns a copy of the begin iterator, not a reference to it.
This commit adds `const` to ranges in range unit test to show that
ranges can be made const correct, using this fix.
Dereferencing a `concat_iteratort` from concating const collections
with `ranget` would previously introduce a compile error, due to a
`const` to non-const conversion. This commit fixes this, by using the
same return type as the iterator which it wraps around.
This commit includes a test for using range to concat `const`
collections.
Dereferencing a `filter_iteratort` from filtering a const collection
with `ranget` would previously introduce a compile error, due to a
`const` to non-const conversion. This commit fixes this, by using the
same return type as the iterator which it wraps around.
This commit includes a test for using range to filter a `const`
collection.
This unit test, tests that the functionality added to `json_objectt` in
the previous commit enables `json_object` to be used as the output
container of `std::transform`. It also tests that `std::inserter` can be
used to construct an `std::insert_iterator<json_objectt>` from a
`json_objectt`. This test is included, because it is good to test new
functionality.
The existing array_list_exprt constructor relies on other deprecated
constructors; instead introduce a non-deprecated one and use it across the
codebase.
The unit test first outputs a symbol table to JSON via show_symbol_table() and
then reads it back in again via symbol_table_from_json(). Then, it checks that
the initial symbol table and the symbol table read back in again are equal.
C/C++ front-ends generate arithmetic shifts for signed bitvectors, and Java
type-casts signed bitvectors to unsigned for the ">>>" operator. Yet
goto-programs still support logical right shift for both signed and unsigned
bitvectors. Thus the simplifier also needs to handle them correctly.
chdir is POSIX and will eventually be implemented via
std::filesystem::current_path. Moving this functionality to util helps removing
OS-specific parts from other areas of the code base.
Furthermore make get_temporary_directory return an absolute, resolved path.
This avoids warnings about unused local variables and also is more concise. Also
change one use of REQUIRE_THROWS to the more precise REQUIRE_THROWS_AS to make
sure we are seeing the expected kind of exception.
Uniformly format all Author and Module lines, and remove stray whitespace before
the end-of-header line. Also add in a missing "in" in some files to make the
grammar work out.
This reduces the memory footprint by up to 5 (GCC's STL) pointers for both
named_sub. The cost is that computing the size of lists and add/remove require
additional iterator increments.
With hexadecimal coding of constants we need to use expr2bits/bits2expr to
evaluate extractbits, and just the underlying get_bvrep_bit for extractbit. Also
document these expressions to clarify their semantics with regard to endianness.
Add a method that checks a symbol for structural validity
according to some predetermined rule, and add it as an
extra rule for symbol-table validity that each symbol is
well-formed.
This commit updates `ranget.map` so that the type is inferred from the
return type of the function passed. This makes the usage of `map` less
verbose and makes it more inline with other `ranget` operations like
`filter`.
Look up the symbol id in symbol table and call base_type_eq on every symbol
expression in guard and code whenever relevant. Includes a unit test.
Also fixes unit tests that these new checks brake.