CBMC
Loading...
Searching...
No Matches
std_expr.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module:
4
5Author: Daniel Kroening, kroening@kroening.com
6
7\*******************************************************************/
8
9#include "std_expr.h"
10
11#include "arith_tools.h"
12#include "config.h"
13#include "expr_util.h"
14#include "fixedbv.h"
15#include "ieee_float.h"
16#include "mathematical_types.h"
17#include "namespace.h"
18#include "pointer_expr.h"
19#include "range.h"
20#include "rational.h"
21#include "rational_tools.h"
22#include "substitute_symbols.h"
23
24#include <map>
25
27{
28 const std::string val=id2string(get_value());
29 return val.find_first_not_of('0')==std::string::npos;
30}
31
32bool operator==(const exprt &lhs, bool rhs)
33{
34 return lhs.is_constant() && to_constant_expr(lhs) == rhs;
35}
36
37bool operator!=(const exprt &lhs, bool rhs)
38{
39 return !lhs.is_constant() || to_constant_expr(lhs) != rhs;
40}
41
42bool constant_exprt::operator==(bool rhs) const
43{
44 return is_boolean() && (get_value() != ID_false) == rhs;
45}
46
47bool constant_exprt::operator!=(bool rhs) const
48{
49 return !is_boolean() || (get_value() != ID_false) != rhs;
50}
51
52bool operator==(const exprt &lhs, int rhs)
53{
54 if(lhs.is_constant())
55 return to_constant_expr(lhs) == rhs;
56 else
57 return false;
58}
59
60bool operator!=(const exprt &lhs, int rhs)
61{
62 if(lhs.is_constant())
63 return to_constant_expr(lhs) != rhs;
64 else
65 return true;
66}
67
68bool constant_exprt::operator==(int rhs) const
69{
70 if(rhs == 0)
71 {
72 const irep_idt &type_id = type().id();
73
74 if(type_id == ID_integer)
75 {
76 return integer_typet{}.zero_expr() == *this;
77 }
78 else if(type_id == ID_natural)
79 {
80 return natural_typet{}.zero_expr() == *this;
81 }
82 else if(type_id == ID_real)
83 {
84 return real_typet{}.zero_expr() == *this;
85 }
86 else if(type_id == ID_rational)
87 {
89 if(to_rational(*this, rat_value))
90 CHECK_RETURN(false);
91 return rat_value.is_zero();
92 }
93 else if(
96 {
97 return value_is_zero_string();
98 }
99 else if(type_id == ID_fixedbv)
100 {
101 return fixedbvt(*this).is_zero();
102 }
103 else if(type_id == ID_floatbv)
104 {
105 return ieee_float_valuet(*this).is_zero();
106 }
107 else if(type_id == ID_pointer)
108 {
109 return *this == nullptr;
110 }
111 else
112 return false;
113 }
114 else if(rhs == 1)
115 {
116 const irep_idt &type_id = type().id();
117
118 if(type_id == ID_integer)
119 {
120 return integer_typet{}.one_expr() == *this;
121 }
122 else if(type_id == ID_natural)
123 {
124 return natural_typet{}.one_expr() == *this;
125 }
126 else if(type_id == ID_real)
127 {
128 return real_typet{}.one_expr() == *this;
129 }
130 else if(type_id == ID_rational)
131 {
133 if(to_rational(*this, rat_value))
134 CHECK_RETURN(false);
135 return rat_value.is_one();
136 }
137 else if(
140 {
141 const auto width = to_bitvector_type(type()).get_width();
143 bvrep2integer(id2string(get_value()), width, false);
144 return int_value == 1;
145 }
146 else if(type_id == ID_fixedbv)
147 {
149 fixedbvt one{spec};
150 one.from_integer(1);
151 return one == fixedbvt{*this};
152 }
153 else if(type_id == ID_floatbv)
154 {
155 return ieee_float_valuet(*this) == 1;
156 }
157 else
158 return false;
159 }
160 else
161 PRECONDITION(false);
162}
163
164bool constant_exprt::operator!=(int rhs) const
165{
166 PRECONDITION(rhs == 0 || rhs == 1);
167 return !(*this == rhs);
168}
169
171{
172 if(type().id() != ID_pointer)
173 return false;
174
175 if(get_value() == ID_NULL)
176 return true;
177
178 // We used to support "0" (when NULL_is_zero), but really front-ends should
179 // resolve this and generate ID_NULL instead.
180 INVARIANT(
181 !value_is_zero_string() || !config.ansi_c.NULL_is_zero,
182 "front-end should use ID_NULL");
183 return false;
184}
185
186bool operator==(const exprt &lhs, std::nullptr_t rhs)
187{
188 (void)rhs; // unused parameter
189 return lhs.is_constant() && to_constant_expr(lhs).is_null_pointer();
190}
191
192bool operator!=(const exprt &lhs, std::nullptr_t rhs)
193{
194 (void)rhs; // unused parameter
195 return !lhs.is_constant() || !to_constant_expr(lhs).is_null_pointer();
196}
197
198bool constant_exprt::operator==(std::nullptr_t rhs) const
199{
200 (void)rhs; // unused parameter
201 return is_null_pointer();
202}
203
204bool constant_exprt::operator!=(std::nullptr_t rhs) const
205{
206 (void)rhs; // unused parameter
207 return !is_null_pointer();
208}
209
211{
212 nullary_exprt::check(expr, vm);
213
214 const auto value = expr.get(ID_value);
215
217 vm,
218 !can_cast_type<bitvector_typet>(expr.type()) || !value.empty(),
219 "bitvector constant must have a non-empty value");
220
222 vm,
225 expr.type().id() == ID_verilog_unsignedbv ||
226 expr.type().id() == ID_verilog_signedbv ||
227 id2string(value).find_first_not_of("0123456789ABCDEF") ==
228 std::string::npos,
229 "negative bitvector constant must use two's complement");
230
232 vm,
234 expr.type().id() == ID_verilog_unsignedbv ||
235 expr.type().id() == ID_verilog_signedbv || value == ID_0 ||
236 id2string(value)[0] != '0',
237 "bitvector constant must not have leading zeros");
238}
239
241{
242 if(op.empty())
243 return false_exprt();
244 else if(op.size()==1)
245 return op.front();
246 else
247 {
248 return or_exprt(exprt::operandst(op));
249 }
250}
251
253{
254 PRECONDITION(a.is_boolean() && b.is_boolean());
255 if(b.is_constant())
256 {
257 if(to_constant_expr(b) == false)
258 return false_exprt{};
259 return a;
260 }
261 if(a.is_constant())
262 {
263 if(to_constant_expr(a) == false)
264 return false_exprt{};
265 return b;
266 }
267 if(b.id() == ID_and)
268 {
269 b.add_to_operands(std::move(a));
270 return b;
271 }
272 return and_exprt{std::move(a), std::move(b)};
273}
274
276{
277 if(op.empty())
278 return true_exprt();
279 else if(op.size()==1)
280 return op.front();
281 else if(op.size() == 2)
282 return conjunction(op[0], op[1]);
283 else
284 {
285 return and_exprt(exprt::operandst(op));
286 }
287}
288
289// Implementation of struct_exprt::component for const / non const overloads.
290template <typename T>
291auto component(T &struct_expr, const irep_idt &name, const namespacet &ns)
292 -> decltype(struct_expr.op0())
293{
294 static_assert(
295 std::is_base_of<struct_exprt, T>::value, "T must be a struct_exprt.");
297 struct_expr.type().id() == ID_struct_tag
298 ? ns.follow_tag(to_struct_tag_type(struct_expr.type()))
299 : to_struct_type(struct_expr.type());
300 const auto index = struct_type.component_number(name);
302 index < struct_expr.operands().size(),
303 "component matching index should exist");
304 return struct_expr.operands()[index];
305}
306
309{
310 return ::component(*this, name, ns);
311}
312
314const exprt &
315struct_exprt::component(const irep_idt &name, const namespacet &ns) const
316{
317 return ::component(*this, name, ns);
318}
319
328 const exprt &expr,
329 const namespacet &ns,
330 const validation_modet vm)
331{
332 check(expr, vm);
333
334 const auto &member_expr = to_member_expr(expr);
335
336 const typet &compound_type = member_expr.compound().type();
337 const auto *struct_union_type =
338 (compound_type.id() == ID_struct_tag || compound_type.id() == ID_union_tag)
339 ? &ns.follow_tag(to_struct_or_union_tag_type(compound_type))
342 vm,
343 struct_union_type != nullptr,
344 "member must address a struct, union or compatible type");
345
346 const auto &component =
347 struct_union_type->get_component(member_expr.get_component_name());
348
350 vm,
351 component.is_not_nil(),
352 "member component '" + id2string(member_expr.get_component_name()) +
353 "' must exist on addressed type");
354
356 vm,
357 component.type() == member_expr.type(),
358 "member expression's type must match the addressed struct or union "
359 "component");
360}
361
362void let_exprt::validate(const exprt &expr, const validation_modet vm)
363{
364 check(expr, vm);
365
366 const auto &let_expr = to_let_expr(expr);
367
369 vm,
370 let_expr.values().size() == let_expr.variables().size(),
371 "number of variables must match number of values");
372
373 for(const auto &binding :
374 make_range(let_expr.variables()).zip(let_expr.values()))
375 {
377 vm,
378 binding.first.id() == ID_symbol,
379 "let binding symbols must be symbols");
380
382 vm,
383 binding.first.type() == binding.second.type(),
384 "let bindings must be type consistent");
385 }
386}
387
389{
391 PRECONDITION(!designators.empty());
392
393 with_exprt result{exprt{}, exprt{}, exprt{}};
394 exprt *dest = &result;
395
396 for(const auto &expr : designators)
397 {
398 with_exprt tmp{exprt{}, exprt{}, exprt{}};
399
400 if(expr.id() == ID_index_designator)
401 {
402 tmp.where() = to_index_designator(expr).index();
403 }
404 else if(expr.id() == ID_member_designator)
405 {
406 // irep_idt component_name=
407 // to_member_designator(*it).get_component_name();
408 }
409 else
411
412 *dest = tmp;
413 dest = &to_with_expr(*dest).new_value();
414 }
415
416 return result;
417}
418
420{
421 // number of values must match the number of bound variables
422 auto &variables = this->variables();
423 PRECONDITION(variables.size() == values.size());
424
425 std::map<symbol_exprt, exprt> value_map;
426
427 for(std::size_t i = 0; i < variables.size(); i++)
428 {
429 // types must match
430 PRECONDITION(variables[i].type() == values[i].type());
431 value_map[variables[i]] = values[i];
432 }
433
434 // build a substitution map
435 std::map<irep_idt, exprt> substitutions;
436
437 for(std::size_t i = 0; i < variables.size(); i++)
438 substitutions[variables[i].get_identifier()] = values[i];
439
440 // now recurse downwards and substitute in 'where'
442
443 if(substitute_result.has_value())
444 return substitute_result.value();
445 else
446 return where(); // trivial case, variables not used
447}
448
449exprt binding_exprt::instantiate(const variablest &new_variables) const
450{
451 std::vector<exprt> values;
452 values.reserve(new_variables.size());
453 for(const auto &new_variable : new_variables)
454 values.push_back(new_variable);
455 return instantiate(values);
456}
457
459{
460 INVARIANT(
461 operands().size() % 2 == 0, "cond must have even number of operands");
462
463 exprt result = nil_exprt();
464
465 auto &operands = this->operands();
466
467 // functional version -- go backwards
468 for(std::size_t i = operands.size(); i != 0; i -= 2)
469 {
470 INVARIANT(
471 i >= 2,
472 "since the number of operands is even if i is nonzero it must be "
473 "greater than two");
474
475 const exprt &cond = operands[i - 2];
476 const exprt &value = operands[i - 1];
477
478 if(result.is_nil())
479 result = value;
480 else
481 result = if_exprt{cond, value, std::move(result)};
482 }
483
484 return result;
485}
configt config
Definition config.cpp:25
mp_integer bvrep2integer(const irep_idt &src, std::size_t width, bool is_signed)
convert a bit-vector representation (possibly signed) to integer
const fixedbv_typet & to_fixedbv_type(const typet &type)
Cast a typet to a fixedbv_typet.
const bitvector_typet & to_bitvector_type(const typet &type)
Cast a typet to a bitvector_typet.
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
Boolean AND.
Definition std_expr.h:2125
static void check(const exprt &expr, const validation_modet vm=validation_modet::INVARIANT)
Definition std_expr.h:650
exprt & where()
Definition std_expr.h:3312
variablest & variables()
Definition std_expr.h:3302
exprt instantiate(const exprt::operandst &) const
substitute free occurrences of the variables in where() by the given values
Definition std_expr.cpp:419
std::vector< symbol_exprt > variablest
Definition std_expr.h:3283
exprt lower() const
Definition std_expr.cpp:458
struct configt::ansi_ct ansi_c
const irep_idt & get_value() const
Definition std_expr.h:3126
bool operator!=(bool rhs) const
Return whether the expression lhs is not a constant of Boolean type or is not representing the Boolea...
Definition std_expr.cpp:47
bool value_is_zero_string() const
Definition std_expr.cpp:26
bool operator==(bool rhs) const
Return whether the expression lhs is a constant of Boolean type that is representing the Boolean valu...
Definition std_expr.cpp:42
bool is_null_pointer() const
Returns true if expr has a pointer type and a value NULL; it also returns true when expr has value ze...
Definition std_expr.cpp:170
static void check(const exprt &expr, const validation_modet vm=validation_modet::INVARIANT)
Definition std_expr.cpp:210
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition dstring.h:38
Base class for all expressions.
Definition expr.h:57
std::vector< exprt > operandst
Definition expr.h:59
bool is_boolean() const
Return whether the expression represents a Boolean.
Definition expr.h:229
bool is_constant() const
Return whether the expression is a constant.
Definition expr.h:213
typet & type()
Return the type of the expression.
Definition expr.h:85
operandst & operands()
Definition expr.h:95
The Boolean constant false.
Definition std_expr.h:3246
void from_integer(const mp_integer &i)
Definition fixedbv.cpp:32
bool is_zero() const
Definition fixedbv.h:71
An IEEE 754 floating-point value, including specificiation.
Definition ieee_float.h:117
bool is_zero() const
Definition ieee_float.h:250
The trinary if-then-else operator.
Definition std_expr.h:2502
Unbounded, signed integers (mathematical integers, not bitvectors)
constant_exprt one_expr() const
constant_exprt zero_expr() const
const irep_idt & get(const irep_idt &name) const
Definition irep.cpp:44
const irep_idt & id() const
Definition irep.h:388
bool is_nil() const
Definition irep.h:368
static void validate(const exprt &, validation_modet)
Definition std_expr.cpp:362
binding_exprt & binding()
Definition std_expr.h:3406
static void validate(const exprt &expr, const namespacet &ns, const validation_modet vm=validation_modet::INVARIANT)
Check that the member expression has the right number of operands, refers to a component that exists ...
Definition std_expr.cpp:327
static void check(const exprt &expr, const validation_modet vm=validation_modet::INVARIANT)
Definition std_expr.h:3031
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
Natural numbers including zero (mathematical integers, not bitvectors)
constant_exprt zero_expr() const
constant_exprt one_expr() const
The NIL expression.
Definition std_expr.h:3255
static void check(const exprt &expr, const validation_modet vm=validation_modet::INVARIANT)
Definition std_expr.h:29
Boolean OR.
Definition std_expr.h:2275
Unbounded, signed real numbers.
constant_exprt zero_expr() const
constant_exprt one_expr() const
exprt & component(const irep_idt &name, const namespacet &ns)
Definition std_expr.cpp:308
Structure type, corresponds to C style structs.
Definition std_types.h:231
The Boolean constant true.
Definition std_expr.h:3237
The type of an expression, extends irept.
Definition type.h:29
with_exprt make_with_expr() const
converts an update expr into a (possibly nested) with expression
Definition std_expr.cpp:388
exprt::operandst & designator()
Definition std_expr.h:2809
Operator to update elements in structs and arrays.
Definition std_expr.h:2603
Deprecated expression utility functions.
const std::string & id2string(const irep_idt &d)
Definition irep.h:44
Mathematical types.
API to expression classes for Pointers.
Ranges: pair of begin and end iterators, which can be initialized from containers,...
ranget< iteratort > make_range(iteratort begin, iteratort end)
Definition range.h:522
bool to_rational(const exprt &expr, rationalt &rational_value)
#define CHECK_RETURN(CONDITION)
Definition invariant.h:495
#define UNREACHABLE
This should be used to mark dead code.
Definition invariant.h:525
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
Definition invariant.h:534
#define PRECONDITION(CONDITION)
Definition invariant.h:463
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition invariant.h:423
bool operator==(const exprt &lhs, bool rhs)
Return whether the expression lhs is a constant of Boolean type that is representing the Boolean valu...
Definition std_expr.cpp:32
exprt disjunction(const exprt::operandst &op)
1) generates a disjunction for two or more operands 2) for one operand, returns the operand 3) return...
Definition std_expr.cpp:240
auto component(T &struct_expr, const irep_idt &name, const namespacet &ns) -> decltype(struct_expr.op0())
Definition std_expr.cpp:291
bool operator!=(const exprt &lhs, bool rhs)
Return whether the expression lhs is not a constant of Boolean type or is not representing the Boolea...
Definition std_expr.cpp:37
exprt conjunction(exprt a, exprt b)
Conjunction of two expressions.
Definition std_expr.cpp:252
API to expression classes.
const let_exprt & to_let_expr(const exprt &expr)
Cast an exprt to a let_exprt.
Definition std_expr.h:3502
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
Definition std_expr.h:3064
const index_designatort & to_index_designator(const exprt &expr)
Cast an exprt to an index_designatort.
Definition std_expr.h:2714
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
Definition std_expr.h:3189
const with_exprt & to_with_expr(const exprt &expr)
Cast an exprt to a with_exprt.
Definition std_expr.h:2661
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
Definition std_types.h:308
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 struct_or_union_tag_typet & to_struct_or_union_tag_type(const typet &type)
Cast a typet to a struct_or_union_tag_typet.
Definition std_types.h:478
std::optional< exprt > substitute_symbols(const std::map< irep_idt, exprt > &substitutions, exprt src)
Substitute free occurrences of the variables given by their identifiers in the keys of the map in the...
Symbol Substitution.
#define DATA_CHECK(vm, condition, message)
This macro takes a condition which denotes a well-formedness criterion on goto programs,...
Definition validate.h:22
validation_modet