CBMC
Loading...
Searching...
No Matches
graphml_witness.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: Witnesses for Traces and Proofs
4
5Author: Daniel Kroening
6
7\*******************************************************************/
8
11
12#include "graphml_witness.h"
13
14#include <util/arith_tools.h>
15#include <util/byte_operators.h>
16#include <util/c_types.h>
17#include <util/cprover_prefix.h>
18#include <util/find_symbols.h>
19#include <util/namespace.h>
21#include <util/prefix.h>
22#include <util/ssa_expr.h>
24#include <util/symbol.h>
25
26#include <ansi-c/expr2c.h>
29#include <langapi/mode.h>
30
31#include "goto_program.h"
32#include "goto_trace.h"
33
34static std::string
35expr_to_string(const namespacet &ns, const irep_idt &id, const exprt &expr)
36{
37 if(get_mode_from_identifier(ns, id) == ID_C)
39 else
40 return from_expr(ns, id, expr);
41}
42
44{
45 if(expr.id()==ID_symbol)
46 {
47 if(is_ssa_expr(expr))
48 expr=to_ssa_expr(expr).get_original_expr();
49 else
50 {
51 std::string identifier=
52 id2string(to_symbol_expr(expr).get_identifier());
53
54 std::string::size_type l0_l1=identifier.find_first_of("!@");
55 if(l0_l1!=std::string::npos)
56 {
57 identifier.resize(l0_l1);
58 to_symbol_expr(expr).set_identifier(identifier);
59 }
60 }
61
62 return;
63 }
64 else if(expr.id() == ID_string_constant)
65 {
66 std::string output_string = expr_to_string(ns, "", expr);
68 expr = to_string_constant(expr).to_array_expr();
69 }
70
71 Forall_operands(it, expr)
72 remove_l0_l1(*it);
73}
74
76 const irep_idt &identifier,
77 const code_assignt &assign)
78{
79 const auto cit = cache.find({identifier.get_no(), &assign.read()});
80 if(cit != cache.end())
81 return cit->second;
82
83 std::string result;
84
85 if(assign.rhs().id() == ID_array_list)
86 {
88 const auto &ops = array_list.operands();
89
90 for(std::size_t listidx = 0; listidx != ops.size(); listidx += 2)
91 {
92 const index_exprt index{assign.lhs(), ops[listidx]};
93 if(!result.empty())
94 result += ' ';
95 result +=
96 convert_assign_rec(identifier, code_assignt{index, ops[listidx + 1]});
97 }
98 }
99 else if(assign.rhs().id() == ID_array)
100 {
101 const array_typet &type = to_array_type(assign.rhs().type());
102
103 unsigned i=0;
104 for(const auto &op : assign.rhs().operands())
105 {
106 index_exprt index(
107 assign.lhs(), from_integer(i++, c_index_type()), type.element_type());
108 if(!result.empty())
109 result+=' ';
110 result += convert_assign_rec(identifier, code_assignt(index, op));
111 }
112 }
113 else if(assign.rhs().id()==ID_struct ||
114 assign.rhs().id()==ID_union)
115 {
116 // dereferencing may have resulted in an lhs that is the first
117 // struct member; undo this
118 if(
119 assign.lhs().id() == ID_member &&
120 assign.lhs().type() != assign.rhs().type())
121 {
122 code_assignt tmp=assign;
123 tmp.lhs()=to_member_expr(assign.lhs()).struct_op();
124
125 return convert_assign_rec(identifier, tmp);
126 }
127 else if(assign.lhs().id()==ID_byte_extract_little_endian ||
129 {
130 code_assignt tmp=assign;
131 tmp.lhs()=to_byte_extract_expr(assign.lhs()).op();
132
133 return convert_assign_rec(identifier, tmp);
134 }
135
136 const typet &lhs_type = assign.lhs().type();
137 const struct_union_typet::componentst &components =
138 (lhs_type.id() == ID_struct_tag || lhs_type.id() == ID_union_tag)
139 ? ns.follow_tag(to_struct_or_union_tag_type(lhs_type)).components()
140 : to_struct_union_type(lhs_type).components();
141
142 exprt::operandst::const_iterator it=
143 assign.rhs().operands().begin();
144 for(const auto &comp : components)
145 {
147 comp.type().id() != ID_code, "struct member must not be of code type");
148 if(
149 comp.get_is_padding() ||
150 // for some reason #is_padding gets lost in *some* cases
151 comp.get_name().starts_with("$pad"))
152 continue;
153
154 INVARIANT(
155 it != assign.rhs().operands().end(), "expression must have operands");
156
157 member_exprt member(
158 assign.lhs(),
159 comp.get_name(),
160 it->type());
161 if(!result.empty())
162 result+=' ';
163 result+=convert_assign_rec(identifier, code_assignt(member, *it));
164 ++it;
165
166 // for unions just assign to the first member
167 if(assign.rhs().id()==ID_union)
168 break;
169 }
170 }
171 else if(assign.rhs().id() == ID_with)
172 {
173 const with_exprt &with_expr = to_with_expr(assign.rhs());
174
175 if(!result.empty())
176 result += ' ';
177
178 if(with_expr.where().id() == ID_member_name)
179 {
180 const member_exprt member{
181 assign.lhs(),
182 with_expr.where().get(ID_component_name),
183 with_expr.new_value().type()};
184 result += convert_assign_rec(
185 identifier, code_assignt(member, with_expr.new_value()));
186 }
187 else
188 {
189 const index_exprt index{assign.lhs(), with_expr.where()};
190 result += convert_assign_rec(
191 identifier, code_assignt(index, with_expr.new_value()));
192 }
193 }
194 else
195 {
196 exprt clean_rhs=assign.rhs();
198
199 exprt clean_lhs = assign.lhs();
201 std::string lhs = expr_to_string(ns, identifier, clean_lhs);
202
203 if(
204 lhs.find("#return_value") != std::string::npos ||
205 (lhs.find('$') != std::string::npos &&
206 has_prefix(lhs, "return_value___VERIFIER_nondet_")))
207 {
208 lhs="\\result";
209 }
210
211 result = lhs + " = " + expr_to_string(ns, identifier, clean_rhs) + ";";
212 }
213
214 cache.insert({{identifier.get_no(), &assign.read()}, result});
215 return result;
216}
217
218static bool filter_out(
219 const goto_tracet &goto_trace,
220 const goto_tracet::stepst::const_iterator &prev_it,
221 goto_tracet::stepst::const_iterator &it)
222{
223 if(
224 it->hidden &&
225 (!it->pc->is_assign() || it->pc->assign_rhs().id() != ID_side_effect ||
226 it->pc->assign_rhs().get(ID_statement) != ID_nondet))
227 return true;
228
229 if(!it->is_assignment() && !it->is_goto() && !it->is_assert())
230 return true;
231
232 // we filter out steps with the same source location
233 // TODO: if these are assignments we should accumulate them into
234 // a single edge
235 if(
236 prev_it != goto_trace.steps.end() &&
237 prev_it->pc->source_location() == it->pc->source_location())
238 return true;
239
240 if(it->is_goto() && it->pc->condition() == true)
241 return true;
242
243 const source_locationt &source_location = it->pc->source_location();
244
245 if(source_location.is_nil() ||
246 source_location.get_file().empty() ||
247 source_location.is_built_in() ||
248 source_location.get_line().empty())
249 {
250 const irep_idt id = source_location.get_function();
251 // Do not filter out assertions in functions the name of which starts with
252 // CPROVER_PREFIX, because we need to maintain those as violation nodes:
253 // these are assertions generated, for examples, for memory leaks.
254 if(!id.starts_with(CPROVER_PREFIX) || !it->is_assert())
255 return true;
256 }
257
258 return false;
259}
260
261static bool contains_symbol_prefix(const exprt &expr, const std::string &prefix)
262{
263 if(
264 expr.id() == ID_symbol &&
265 to_symbol_expr(expr).get_identifier().starts_with(prefix))
266 {
267 return true;
268 }
269
270 for(const auto &op : expr.operands())
271 {
272 if(contains_symbol_prefix(op, prefix))
273 return true;
274 }
275 return false;
276}
277
281 const namespacet &ns,
282 const irep_idt &function_id)
283{
284 const symbolt *symbol_ptr = nullptr;
285 if(ns.lookup(function_id, symbol_ptr))
286 return true; // not found -- not a user function
287
288 if(symbol_ptr->type.id() != ID_code)
289 return true; // not a function
290
291 if(symbol_ptr->value.is_nil())
292 return true; // no body (truly extern)
293
294 if(symbol_ptr->location.is_built_in())
295 return true; // body from a built-in library source
296
297 return false;
298}
299
304static bool all_symbols_in_scope(const exprt &expr, const irep_idt &function_id)
305{
306 find_symbols_sett symbols;
307 find_symbols(expr, symbols);
308
309 for(const auto &symbol_id : symbols)
310 {
311 if(id2string(symbol_id).find(CPROVER_PREFIX) != std::string::npos)
312 continue;
313
314 std::string symbol_str = id2string(symbol_id);
315 auto scope_sep = symbol_str.find("::");
316
317 if(scope_sep != std::string::npos)
318 {
319 if(symbol_str.substr(0, scope_sep) != id2string(function_id))
320 return false;
321 }
322 }
323
324 return true;
325}
326
329{
330 unsigned int max_thread_idx = 0;
331 bool trace_has_violation = false;
332 for(goto_tracet::stepst::const_iterator it = goto_trace.steps.begin();
333 it != goto_trace.steps.end();
334 ++it)
335 {
336 if(it->thread_nr > max_thread_idx)
337 max_thread_idx = it->thread_nr;
338 if(it->is_assert() && !it->cond_value)
339 trace_has_violation = true;
340 }
341
342 graphml.key_values["sourcecodelang"]="C";
343
345 graphml[sink].node_name="sink";
346 graphml[sink].is_violation=false;
347 graphml[sink].has_invariant=false;
348
350 {
351 std::vector<graphmlt::node_indext> nodes;
352
353 for(unsigned int i = 0; i <= max_thread_idx + 1; ++i)
354 {
355 nodes.push_back(graphml.add_node());
356 graphml[nodes.back()].node_name = "N" + std::to_string(i);
357 graphml[nodes.back()].is_violation = i == max_thread_idx + 1;
358 graphml[nodes.back()].has_invariant = false;
359 }
360
361 for(auto it = nodes.cbegin(); std::next(it) != nodes.cend(); ++it)
362 {
363 xmlt edge("edge");
364 edge.set_attribute("source", graphml[*it].node_name);
365 edge.set_attribute("target", graphml[*std::next(it)].node_name);
366 const auto thread_id = std::distance(nodes.cbegin(), it);
367 xmlt &data = edge.new_element("data");
368 data.set_attribute("key", "createThread");
369 data.data = std::to_string(thread_id);
370 if(thread_id == 0)
371 {
372 xmlt &data = edge.new_element("data");
373 data.set_attribute("key", "enterFunction");
374 data.data = "main";
375 }
376 graphml[*std::next(it)].in[*it].xml_node = edge;
377 graphml[*it].out[*std::next(it)].xml_node = edge;
378 }
379
380 // we do not provide any further details as CPAchecker does not seem to
381 // handle more detailed concurrency witnesses
382 return;
383 }
384
385 // step numbers start at 1
386 std::vector<std::size_t> step_to_node(goto_trace.steps.size()+1, 0);
387
388 goto_tracet::stepst::const_iterator prev_it=goto_trace.steps.end();
389 for(goto_tracet::stepst::const_iterator
390 it=goto_trace.steps.begin();
391 it!=goto_trace.steps.end();
392 it++) // we cannot replace this by a ranged for
393 {
395 {
396 step_to_node[it->step_nr]=sink;
397
398 continue;
399 }
400
401 // skip declarations followed by an immediate assignment
402 goto_tracet::stepst::const_iterator next=it;
403 ++next;
404 if(
405 next != goto_trace.steps.end() &&
407 it->full_lhs == next->full_lhs &&
408 it->pc->source_location() == next->pc->source_location())
409 {
410 step_to_node[it->step_nr]=sink;
411
412 continue;
413 }
414
415 prev_it=it;
416
417 const source_locationt &source_location = it->pc->source_location();
418
420 graphml[node].node_name=
421 std::to_string(it->pc->location_number)+"."+std::to_string(it->step_nr);
422 graphml[node].file=source_location.get_file();
423 graphml[node].line=source_location.get_line();
424 graphml[node].is_violation=
425 it->type==goto_trace_stept::typet::ASSERT && !it->cond_value;
426 graphml[node].has_invariant=false;
427
428 step_to_node[it->step_nr]=node;
429 }
430
431 unsigned thread_id = 0;
432
433 // build edges
434 for(goto_tracet::stepst::const_iterator
435 it=goto_trace.steps.begin();
436 it!=goto_trace.steps.end();
437 ) // no ++it
438 {
439 const std::size_t from=step_to_node[it->step_nr];
440
441 // no outgoing edges from sinks or violation nodes
442 if(from == sink || graphml[from].is_violation)
443 {
444 ++it;
445 continue;
446 }
447
448 auto next = std::next(it);
449 for(; next != goto_trace.steps.end() &&
450 (step_to_node[next->step_nr] == sink ||
451 pointee_address_equalt{}(it->pc, next->pc)); // NOLINT
452 ++next)
453 {
454 // advance
455 }
456 const std::size_t to=
457 next==goto_trace.steps.end()?
458 sink:step_to_node[next->step_nr];
459
460 switch(it->type)
461 {
466 {
467 xmlt edge(
468 "edge",
469 {{"source", graphml[from].node_name},
470 {"target", graphml[to].node_name}},
471 {});
472
473 {
474 xmlt &data_f = edge.new_element("data");
475 data_f.set_attribute("key", "originfile");
476 data_f.data = id2string(graphml[from].file);
477
478 xmlt &data_l = edge.new_element("data");
479 data_l.set_attribute("key", "startline");
480 data_l.data = id2string(graphml[from].line);
481
482 xmlt &data_t = edge.new_element("data");
483 data_t.set_attribute("key", "threadId");
484 data_t.data = std::to_string(it->thread_nr);
485 }
486
487 const auto lhs_object = it->get_lhs_object();
488 if(
490 lhs_object.has_value())
491 {
492 const std::string &lhs_id = id2string(lhs_object->get_identifier());
493 if(lhs_id.find("pthread_create::thread") != std::string::npos)
494 {
495 xmlt &data_t = edge.new_element("data");
496 data_t.set_attribute("key", "createThread");
497 data_t.data = std::to_string(++thread_id);
498 }
499 else if(
501 it->full_lhs_value, SYMEX_DYNAMIC_PREFIX "::dynamic_object") &&
503 it->full_lhs, SYMEX_DYNAMIC_PREFIX "::dynamic_object") &&
504 lhs_id.find("thread") == std::string::npos &&
505 lhs_id.find("mutex") == std::string::npos &&
506 (!it->full_lhs_value.is_constant() ||
507 !it->full_lhs_value.has_operands() ||
508 !has_prefix(
509 id2string(
510 to_multi_ary_expr(it->full_lhs_value).op0().get(ID_value)),
511 "INVALID-")))
512 {
513 // Determine effective scope from lhs_id: the prefix before the
514 // first "::" matches function_id in CBMC's C naming convention
515 // (e.g., "main::1::x" -> "main").
516 irep_idt scope_function = it->function_id;
517 auto sep = lhs_id.find("::");
518 if(sep != std::string::npos)
519 scope_function = lhs_id.substr(0, sep);
520
521 // Skip assumptions from __CPROVER_initialize,
522 // built-in/extern functions, or with out-of-scope
523 // symbols in the RHS
524 code_assignt assign{it->full_lhs, it->full_lhs_value};
525 if(
526 scope_function != CPROVER_PREFIX "initialize" &&
529 {
530 xmlt &val = edge.new_element("data");
531 val.set_attribute("key", "assumption");
532
533 val.data = convert_assign_rec(lhs_id, assign);
534
535 if(!scope_function.empty())
536 {
537 xmlt &val_s = edge.new_element("data");
538 val_s.set_attribute("key", "assumption.scope");
540 }
541
542 if(has_prefix(val.data, "\\result ="))
543 {
544 xmlt &val_f = edge.new_element("data");
545 val_f.set_attribute("key", "assumption.resultfunction");
546 val_f.data = id2string(it->function_id);
547 }
548 }
549 }
550 }
551 else if(it->type == goto_trace_stept::typet::GOTO && it->pc->is_goto())
552 {
553 }
554
555 graphml[to].in[from].xml_node = edge;
556 graphml[from].out[to].xml_node = edge;
557
558 break;
559 }
560
576 // ignore
577 break;
578 }
579
580 it=next;
581 }
582}
583
586{
587 graphml.key_values["sourcecodelang"]="C";
588
590 graphml[sink].node_name="sink";
591 graphml[sink].is_violation=false;
592 graphml[sink].has_invariant=false;
593
594 // step numbers start at 1
595 std::vector<std::size_t> step_to_node(equation.SSA_steps.size()+1, 0);
596
597 std::size_t step_nr=1;
598 for(symex_target_equationt::SSA_stepst::const_iterator
599 it=equation.SSA_steps.begin();
600 it!=equation.SSA_steps.end();
601 it++, step_nr++) // we cannot replace this by a ranged for
602 {
603 const source_locationt &source_location = it->source.pc->source_location();
604
605 if(
606 it->hidden ||
607 (!it->is_assignment() && !it->is_goto() && !it->is_assert()) ||
608 (it->is_goto() && it->source.pc->condition() == true) ||
609 source_location.is_nil() || source_location.is_built_in() ||
610 source_location.get_line().empty())
611 {
612 step_to_node[step_nr]=sink;
613
614 continue;
615 }
616
617 // skip declarations followed by an immediate assignment
618 symex_target_equationt::SSA_stepst::const_iterator next=it;
619 ++next;
620 if(
621 next != equation.SSA_steps.end() && next->is_assignment() &&
622 it->ssa_full_lhs == next->ssa_full_lhs &&
623 it->source.pc->source_location() == next->source.pc->source_location())
624 {
625 step_to_node[step_nr]=sink;
626
627 continue;
628 }
629
631 graphml[node].node_name=
632 std::to_string(it->source.pc->location_number)+"."+
633 std::to_string(step_nr);
634 graphml[node].file=source_location.get_file();
635 graphml[node].line=source_location.get_line();
636 graphml[node].is_violation=false;
637 graphml[node].has_invariant=false;
638
639 step_to_node[step_nr]=node;
640 }
641
642 // build edges
643 step_nr=1;
644 for(symex_target_equationt::SSA_stepst::const_iterator
645 it=equation.SSA_steps.begin();
646 it!=equation.SSA_steps.end();
647 ) // no ++it
648 {
649 const std::size_t from=step_to_node[step_nr];
650
651 if(from==sink)
652 {
653 ++it;
654 ++step_nr;
655 continue;
656 }
657
658 symex_target_equationt::SSA_stepst::const_iterator next=it;
659 std::size_t next_step_nr=step_nr;
660 for(++next, ++next_step_nr;
661 next!=equation.SSA_steps.end() &&
662 (step_to_node[next_step_nr]==sink || it->source.pc==next->source.pc);
663 ++next, ++next_step_nr)
664 {
665 // advance
666 }
667 const std::size_t to=
668 next==equation.SSA_steps.end()?
670
671 switch(it->type)
672 {
677 {
678 xmlt edge(
679 "edge",
680 {{"source", graphml[from].node_name},
681 {"target", graphml[to].node_name}},
682 {});
683
684 {
685 xmlt &data_f = edge.new_element("data");
686 data_f.set_attribute("key", "originfile");
687 data_f.data = id2string(graphml[from].file);
688
689 xmlt &data_l = edge.new_element("data");
690 data_l.set_attribute("key", "startline");
691 data_l.data = id2string(graphml[from].line);
692 }
693
694 if(
695 (it->is_assignment() || it->is_decl()) && it->ssa_rhs.is_not_nil() &&
696 it->ssa_full_lhs.is_not_nil())
697 {
698 irep_idt identifier = it->ssa_lhs.get_object_name();
699
700 // Determine effective scope from identifier: the prefix before the
701 // first "::" matches function_id in CBMC's C naming convention
702 // (e.g., "main::1::x" -> "main").
703 irep_idt scope_function = it->source.function_id;
704 std::string id_str = id2string(identifier);
705 auto sep = id_str.find("::");
706 if(sep != std::string::npos)
707 scope_function = id_str.substr(0, sep);
708
709 code_assignt assign(it->ssa_lhs, it->ssa_rhs);
710
711 if(
712 scope_function != CPROVER_PREFIX "initialize" &&
715 {
716 graphml[to].has_invariant = true;
717 graphml[to].invariant = convert_assign_rec(identifier, assign);
718
719 if(!scope_function.empty())
720 {
721 graphml[to].invariant_scope = id2string(scope_function);
722 }
723 }
724 }
725
726 graphml[to].in[from].xml_node = edge;
727 graphml[from].out[to].xml_node = edge;
728
729 break;
730 }
731
747 // ignore
748 break;
749 }
750
751 it=next;
752 step_nr=next_step_nr;
753 }
754}
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
Expression classes for byte-level operators.
const byte_extract_exprt & to_byte_extract_expr(const exprt &expr)
bitvector_typet c_index_type()
Definition c_types.cpp:16
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:566
Array constructor from a list of index-element pairs Operands are index/value pairs,...
Definition std_expr.h:1622
Arrays with given size.
Definition std_types.h:807
const typet & element_type() const
The type of the elements of the array.
Definition std_types.h:827
A goto_instruction_codet representing an assignment in the program.
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition dstring.h:38
unsigned get_no() const
Definition dstring.h:182
Base class for all expressions.
Definition expr.h:57
typet & type()
Return the type of the expression.
Definition expr.h:85
operandst & operands()
Definition expr.h:95
Trace of a GOTO program.
Definition goto_trace.h:177
const namespacet & ns
void operator()(const goto_tracet &goto_trace)
counterexample witness
std::unordered_map< std::pair< unsigned int, const irept::dt * >, std::string, pair_hash< unsigned int, const irept::dt * > > cache
void remove_l0_l1(exprt &expr)
std::string convert_assign_rec(const irep_idt &identifier, const code_assignt &assign)
key_valuest key_values
Definition graphml.h:67
nodet::node_indext node_indext
Definition graph.h:173
const edgest & out(node_indext n) const
Definition graph.h:227
node_indext add_node(arguments &&... values)
Definition graph.h:180
const edgest & in(node_indext n) const
Definition graph.h:222
Array index operator.
Definition std_expr.h:1421
const irep_idt & id() const
Definition irep.h:388
bool is_nil() const
Definition irep.h:368
Extract member of struct or union.
Definition std_expr.h:2856
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition namespace.h:91
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
const dt & read() const
Definition irep.h:240
const irep_idt & get_function() const
const irep_idt & get_file() const
const irep_idt & get_line() const
static bool is_built_in(const std::string &s)
std::vector< componentt > componentst
Definition std_types.h:140
Symbol table entry.
Definition symbol.h:28
Inheriting the interface of symex_targett this class represents the SSA form of the input program as ...
The type of an expression, extends irept.
Definition type.h:29
Operator to update elements in structs and arrays.
Definition std_expr.h:2510
Definition xml.h:21
xmlt & new_element(const std::string &key)
Definition xml.h:95
void set_attribute(const std::string &attribute, unsigned value)
Definition xml.cpp:198
std::string data
Definition xml.h:39
static bool is_printable_xml(const std::string &s)
Determine whether s does not contain any characters that cannot be escaped in XML 1....
Definition xml.cpp:160
bool has_prefix(const std::string &s, const std::string &prefix)
Definition converter.cpp:13
#define CPROVER_PREFIX
std::string expr2c(const exprt &expr, const namespacet &ns, const expr2c_configurationt &configuration)
Definition expr2c.cpp:4188
#define Forall_operands(it, expr)
Definition expr.h:28
static bool find_symbols(symbol_kindt, const typet &, std::function< bool(const symbol_exprt &)>, std::unordered_set< irep_idt > &bindings, const std::vector< irep_idt > &subs_to_find)
Find identifiers with id ID_symbol of the sub expressions and the subs with ID in subs_to_find consid...
std::unordered_set< irep_idt > find_symbols_sett
Concrete Goto Program.
Traces of GOTO Programs.
static bool all_symbols_in_scope(const exprt &expr, const irep_idt &function_id)
Check if all symbols in an expression are in scope.
static std::string expr_to_string(const namespacet &ns, const irep_idt &id, const exprt &expr)
static bool is_function_built_in_or_extern(const namespacet &ns, const irep_idt &function_id)
Check if a function is built-in (CPROVER library), has no body, or does not exist in the symbol table...
static bool contains_symbol_prefix(const exprt &expr, const std::string &prefix)
static bool filter_out(const goto_tracet &goto_trace, const goto_tracet::stepst::const_iterator &prev_it, goto_tracet::stepst::const_iterator &it)
Witnesses for Traces and Proofs.
const std::string & id2string(const irep_idt &d)
Definition irep.h:44
const std::string thread_id
std::string from_expr(const namespacet &ns, const irep_idt &identifier, const exprt &expr)
const irep_idt & get_mode_from_identifier(const namespacet &ns, const irep_idt &identifier)
Get the mode of the given identifier's symbol.
Definition mode.cpp:66
Various predicates over pointers in programs.
#define SYMEX_DYNAMIC_PREFIX
#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 INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition invariant.h:423
bool is_ssa_expr(const exprt &expr)
Definition ssa_expr.h:125
const ssa_exprt & to_ssa_expr(const exprt &expr)
Cast a generic exprt to an ssa_exprt.
Definition ssa_expr.h:145
const array_list_exprt & to_array_list_expr(const exprt &expr)
Definition std_expr.h:1660
const multi_ary_exprt & to_multi_ary_expr(const exprt &expr)
Cast an exprt to a multi_ary_exprt.
Definition std_expr.h:981
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
Definition std_expr.h:2943
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition std_expr.h:211
const with_exprt & to_with_expr(const exprt &expr)
Cast an exprt to a with_exprt.
Definition std_expr.h:2563
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
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition std_types.h:888
const struct_union_typet & to_struct_union_type(const typet &type)
Cast a typet to a struct_union_typet.
Definition std_types.h:214
const string_constantt & to_string_constant(const exprt &expr)
static expr2c_configurationt clean_configuration
This prints compilable C that loses some of the internal details of the GOTO program.
Definition expr2c.h:52
Functor to check whether iterators from different collections point at the same object.
Symbol table entry.
Generate Equation using Symbolic Execution.