CBMC
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
string_refinement_util.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: String solver
4
5Author: Diffblue Ltd.
6
7\*******************************************************************/
8
10
11#include <numeric>
12
13#include <util/arith_tools.h>
14#include <util/expr_util.h>
15#include <util/magic.h>
16#include <util/namespace.h>
17#include <util/std_expr.h>
18#include <util/unicode.h>
19
20bool is_char_type(const typet &type)
21{
22 return type.id() == ID_unsignedbv && to_unsignedbv_type(type).get_width() <=
24}
25
26bool is_char_array_type(const typet &type, const namespacet &ns)
27{
28 if(type.id() == ID_struct_tag)
30 return type.id() == ID_array &&
31 is_char_type(to_array_type(type).element_type());
32}
33
34bool is_char_pointer_type(const typet &type)
35{
36 return type.id() == ID_pointer &&
37 is_char_type(to_pointer_type(type).base_type());
38}
39
40bool has_char_pointer_subtype(const typet &type, const namespacet &ns)
41{
42 return has_subtype(type, is_char_pointer_type, ns);
43}
44
45bool has_char_array_subexpr(const exprt &expr, const namespacet &ns)
46{
47 return has_subexpr(
48 expr, [&](const exprt &e) { return is_char_array_type(e.type(), ns); });
49}
50
51std::string
52utf16_constant_array_to_java(const array_exprt &arr, std::size_t length)
53{
54 PRECONDITION(std::all_of(
55 arr.operands().begin(),
56 arr.operands().end(),
58
59 std::wstring out(length, '?');
60
61 for(std::size_t i = 0; i < arr.operands().size() && i < length; i++)
62 out[i] = numeric_cast_v<unsigned>(to_constant_expr(arr.operands()[i]));
63
65}
66
68{
69 auto ref = std::ref(static_cast<const exprt &>(expr));
70 while(can_cast_expr<with_exprt>(ref.get()))
71 {
72 const auto &with_expr = expr_dynamic_cast<with_exprt>(ref.get());
73 const auto current_index =
75 entries[current_index] = with_expr.new_value();
76 ref = with_expr.old();
77 }
78
79 // This function only handles 'with' and 'array_of' expressions
80 PRECONDITION(ref.get().id() == ID_array_of);
82}
83
85 const with_exprt &expr,
86 const exprt &index)
87{
89
90 return std::accumulate(
91 sparse_array.entries.begin(),
92 sparse_array.entries.end(),
93 sparse_array.default_value,
94 [&](
95 const exprt if_expr,
96 const std::pair<std::size_t, exprt> &entry) { // NOLINT
97 const exprt entry_index = from_integer(entry.first, index.type());
98 const exprt &then_expr = entry.second;
99 CHECK_RETURN(then_expr.type() == if_expr.type());
100 const equal_exprt index_equal(index, entry_index);
101 return if_exprt(index_equal, then_expr, if_expr, if_expr.type());
102 });
103}
104
106{
107 return std::accumulate(
108 entries.rbegin(),
109 entries.rend(),
111 [&](
112 const exprt if_expr,
113 const std::pair<std::size_t, exprt> &entry) { // NOLINT
114 const exprt entry_index = from_integer(entry.first, index.type());
115 const exprt &then_expr = entry.second;
116 CHECK_RETURN(then_expr.type() == if_expr.type());
117 const binary_relation_exprt index_small_eq(index, ID_le, entry_index);
118 return if_exprt(index_small_eq, then_expr, if_expr, if_expr.type());
119 });
120}
121
123 const array_exprt &expr,
124 const exprt &extra_value)
126{
127 const auto &operands = expr.operands();
129 for(std::size_t i = 0; i < operands.size(); ++i)
130 {
131 const std::size_t index = operands.size() - 1 - i;
132 if(operands[index].id() != ID_unknown && operands[index] != last_added)
133 {
134 entries[index] = operands[index];
135 last_added = operands[index];
136 }
137 }
138}
139
141 const array_list_exprt &expr,
142 const exprt &extra_value)
144{
145 PRECONDITION(expr.operands().size() % 2 == 0);
146 for(std::size_t i = 0; i < expr.operands().size(); i += 2)
147 {
148 const auto index = numeric_cast<std::size_t>(expr.operands()[i]);
149 INVARIANT(
150 expr.operands()[i + 1].type() == extra_value.type(),
151 "all values in array should have the same type");
152 if(index.has_value() && expr.operands()[i + 1].id() != ID_unknown)
153 entries[*index] = expr.operands()[i + 1];
154 }
155}
156
157std::optional<interval_sparse_arrayt>
168
169exprt interval_sparse_arrayt::at(const std::size_t index) const
170{
171 // First element at or after index
172 const auto it = entries.lower_bound(index);
173 return it != entries.end() ? it->second : default_value;
174}
175
177 std::size_t size,
178 const typet &index_type) const
179{
181 default_value.type(), from_integer(size, index_type));
182 array_exprt array({}, array_type);
183 array.operands().reserve(size);
184
185 auto it = entries.begin();
186 for(; it != entries.end() && it->first < size; ++it)
187 array.operands().resize(it->first + 1, it->second);
188
189 array.operands().resize(
190 size, it == entries.end() ? default_value : it->second);
191 return array;
192}
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
const unsignedbv_typet & to_unsignedbv_type(const typet &type)
Cast a typet to an unsignedbv_typet.
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
Array constructor from list of elements.
Definition std_expr.h:1621
Array constructor from a list of index-element pairs Operands are index/value pairs,...
Definition std_expr.h:1681
Arrays with given size.
Definition std_types.h:807
Base class for all expressions.
Definition expr.h:56
typet & type()
Return the type of the expression.
Definition expr.h:84
operandst & operands()
Definition expr.h:94
Represents arrays by the indexes up to which the value remains the same.
exprt to_if_expression(const exprt &index) const
static std::optional< interval_sparse_arrayt > of_expr(const exprt &expr, const exprt &extra_value)
If the expression is an array_exprt or a with_exprt uses the appropriate constructor,...
array_exprt concretize(std::size_t size, const typet &index_type) const
Convert to an array representation, ignores elements at index >= size.
interval_sparse_arrayt(const with_exprt &expr)
An expression of the form array_of(x) with {i:=a} with {j:=b} is converted to an array arr where for ...
exprt at(std::size_t index) const
Get the value at the specified index.
const irep_idt & id() const
Definition irep.h:388
const union_typet & follow_tag(const union_tag_typet &) const
Follow type tag of union type.
Definition namespace.cpp:49
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition namespace.h:91
Represents arrays of the form array_of(x) with {i:=a} with {j:=b} ... by a default value x and a list...
std::map< std::size_t, exprt > entries
static exprt to_if_expression(const with_exprt &expr, const exprt &index)
Creates an if_expr corresponding to the result of accessing the array at the given index.
sparse_arrayt(const with_exprt &expr)
Initialize a sparse array from an expression of the form array_of(x) with {i:=a} with {j:=b} ....
The type of an expression, extends irept.
Definition type.h:29
Operator to update elements in structs and arrays.
Definition std_expr.h:2598
bool has_subexpr(const exprt &expr, const std::function< bool(const exprt &)> &pred)
returns true if the expression has a subexpression that satisfies pred
bool has_subtype(const typet &type, const std::function< bool(const typet &)> &pred, const namespacet &ns)
returns true if any of the contained types satisfies pred
Deprecated expression utility functions.
Magic numbers used throughout the codebase.
const std::size_t STRING_REFINEMENT_MAX_CHAR_WIDTH
Definition magic.h:12
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
#define PRECONDITION(CONDITION)
Definition invariant.h:463
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition invariant.h:423
API to expression classes.
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
Definition std_expr.h:3172
const struct_tag_typet & to_struct_tag_type(const typet &type)
Cast a typet to a struct_tag_typet.
Definition std_types.h:518
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition std_types.h:888
std::string utf16_constant_array_to_java(const array_exprt &arr, std::size_t length)
Construct a string from a constant array.
bool is_char_type(const typet &type)
For now, any unsigned bitvector type of width smaller or equal to 16 is considered a character.
bool has_char_pointer_subtype(const typet &type, const namespacet &ns)
bool is_char_array_type(const typet &type, const namespacet &ns)
Distinguish char array from other types.
bool has_char_array_subexpr(const exprt &expr, const namespacet &ns)
bool is_char_pointer_type(const typet &type)
For now, any unsigned bitvector type is considered a character.
static void utf16_native_endian_to_java_string(const wchar_t ch, std::ostringstream &result, const std::locale &loc)
Escapes non-printable characters, whitespace except for spaces, double quotes and backslashes.
Definition unicode.cpp:272