CBMC
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
goto_inline_class.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: Function Inlining
4
5Author: Daniel Kroening, kroening@kroening.com
6
7\*******************************************************************/
8
11
12#include "goto_inline_class.h"
13
14#ifdef DEBUG
15#include <iostream>
16#endif
17
18#include <util/cprover_prefix.h>
19#include <util/invariant.h>
20#include <util/namespace.h>
21#include <util/std_code.h>
22#include <util/symbol.h>
23
25 const goto_programt::targett target,
26 const irep_idt &function_name, // name of called function
27 const goto_functiont::parameter_identifierst &parameter_identifiers,
28 const exprt::operandst &arguments, // arguments of call
29 goto_programt &dest)
30{
31 PRECONDITION(target->is_function_call());
32 PRECONDITION(dest.empty());
33
34 const source_locationt &source_location = target->source_location();
35
36 // iterates over the operands
37 exprt::operandst::const_iterator it1=arguments.begin();
38
39 // iterates over the parameters
40 for(const auto &identifier : parameter_identifiers)
41 {
43 !identifier.empty(),
44 source_location.as_string() + ": no identifier for function parameter");
45
46 const symbolt &symbol = ns.lookup(identifier);
47
48 // this is the type the n-th argument should have
49 const typet &parameter_type = symbol.type;
50
51 code_declt decl{symbol.symbol_expr()};
52 decl.add_source_location() = source_location;
53 dest.add(goto_programt::make_decl(std::move(decl), source_location));
54
55 // this is the actual parameter
57
58 // if you run out of actual arguments there was a mismatch
59 if(it1==arguments.end())
60 {
61 log.warning().source_location = source_location;
62 log.warning() << "call to '" << function_name << "': "
63 << "not enough arguments, "
64 << "inserting non-deterministic value" << messaget::eom;
65
67 }
68 else
69 actual=*it1;
70
71 // nil means "don't assign"
72 if(actual.is_nil())
73 {
74 }
75 else
76 {
77 // it should be the same exact type as the parameter,
78 // subject to some exceptions
79 if(parameter_type != actual.type())
80 {
82 const typet &f_acttype = actual.type();
83
84 // we are willing to do some conversion
85 if(
86 (f_partype.id() == ID_pointer && f_acttype.id() == ID_pointer) ||
87 (f_partype.id() == ID_pointer && f_acttype.id() == ID_array &&
90 {
92 }
93 else if((f_partype.id()==ID_signedbv ||
95 f_partype.id()==ID_bool) &&
96 (f_acttype.id()==ID_signedbv ||
98 f_acttype.id()==ID_bool))
99 {
101 }
102 else
103 {
105 }
106 }
107
108 // adds an assignment of the actual parameter to the formal parameter
109 code_assignt assignment(symbol_exprt(identifier, parameter_type), actual);
110 assignment.add_source_location()=source_location;
111
112 dest.add(goto_programt::make_assignment(assignment, source_location));
113 }
114
115 if(it1!=arguments.end())
116 ++it1;
117 }
118
119 if(it1!=arguments.end())
120 {
121 // too many arguments -- we just ignore that, no harm done
122 }
123}
124
126 const goto_programt::targett target,
127 const goto_functiont::parameter_identifierst &parameter_identifiers,
128 goto_programt &dest)
129{
130 PRECONDITION(target->is_function_call());
131 PRECONDITION(dest.empty());
132
133 const source_locationt &source_location = target->source_location();
134
135 for(const auto &identifier : parameter_identifiers)
136 {
137 INVARIANT(
138 !identifier.empty(),
139 source_location.as_string() + ": no identifier for function parameter");
140
141 {
142 const symbolt &symbol=ns.lookup(identifier);
143
144 goto_programt::targett dead = dest.add(
145 goto_programt::make_dead(symbol.symbol_expr(), source_location));
146 dead->code_nonconst().add_source_location() = source_location;
147 }
148 }
149}
150
152 goto_programt &dest, // inlining this
153 const exprt &lhs) // lhs in caller
154{
155 for(goto_programt::instructionst::iterator
156 it=dest.instructions.begin();
157 it!=dest.instructions.end();
158 it++)
159 {
160 if(it->is_set_return_value())
161 {
162 if(lhs.is_not_nil())
163 {
164 // a typecast may be necessary if the declared return type at the call
165 // site differs from the defined return type
167 lhs,
168 typecast_exprt::conditional_cast(it->return_value(), lhs.type()),
169 it->source_location());
170 }
171 else
172 {
174 code_expressiont(it->return_value()), it->source_location());
175 }
176 }
177 }
178}
179
181 source_locationt &dest,
183{
184 // we copy, and then adjust for property_id, property_class
185 // and comment, if necessary
186
188 irep_idt property_class=dest.get_property_class();
189 irep_idt property_id=dest.get_property_id();
190
191 dest=new_location;
192
193 if(!comment.empty())
194 dest.set_comment(comment);
195
196 if(!property_class.empty())
197 dest.set_property_class(property_class);
198
199 if(!property_id.empty())
200 dest.set_property_id(property_id);
201}
202
204 exprt &dest,
206{
207 Forall_operands(it, dest)
209
210 if(dest.find(ID_C_source_location).is_not_nil())
212}
213
215 const goto_functiont &goto_function,
216 goto_programt &dest,
218 const exprt &lhs,
219 const symbol_exprt &function,
220 const exprt::operandst &arguments)
221{
222 PRECONDITION(target->is_function_call());
223 PRECONDITION(!dest.empty());
224 PRECONDITION(goto_function.body_available());
225
226 const irep_idt identifier=function.get_identifier();
227
228 goto_programt body;
229 body.copy_from(goto_function.body);
230 inline_log.copy_from(goto_function.body, body);
231
234 end.is_end_function(),
235 "final instruction of a function must be an END_FUNCTION");
237
238 // make sure the inlined function does not introduce hiding
239 if(goto_function.is_hidden())
240 {
241 for(auto &instruction : body.instructions)
242 instruction.labels.remove(CPROVER_PREFIX "HIDE");
243 }
244
245 replace_return(body, lhs);
246
249 target, identifier, goto_function.parameter_identifiers, arguments, tmp1);
250
252 parameter_destruction(target, goto_function.parameter_identifiers, tmp2);
253
255 tmp.destructive_append(tmp1); // par assignment
256 tmp.destructive_append(body); // body
257 tmp.destructive_append(tmp2); // par destruction
258
260 t_it=goto_function.body.instructions.begin();
261 unsigned begin_location_number=t_it->location_number;
262 t_it=--goto_function.body.instructions.end();
264 t_it->is_end_function(),
265 "final instruction of a function must be an END_FUNCTION");
266 unsigned end_location_number=t_it->location_number;
267
268 unsigned call_location_number=target->location_number;
269
271 tmp,
272 begin_location_number,
273 end_location_number,
274 call_location_number,
275 identifier);
276
278 {
279 for(auto &instruction : tmp.instructions)
280 {
282 instruction.source_location_nonconst(), target->source_location());
283 replace_location(instruction.code_nonconst(), target->source_location());
284
285 if(instruction.has_condition())
286 {
288 instruction.condition_nonconst(), target->source_location());
289 }
290 }
291 }
292
293 // kill call
294 *target = goto_programt::make_location(target->source_location());
295 target++;
296
297 dest.destructive_insert(target, tmp);
298}
299
303 goto_programt &dest,
304 const inline_mapt &inline_map,
305 const bool transitive,
306 const bool force_full,
308{
309 PRECONDITION(target->is_function_call());
310 PRECONDITION(!dest.empty());
312
313#ifdef DEBUG
314 std::cout << "Expanding call:\n";
315 target->output(std::cout);
316#endif
317
318 exprt lhs;
320 exprt::operandst arguments;
321
322 get_call(target, lhs, function_expr, arguments);
323
324 if(function_expr.id()!=ID_symbol)
325 return;
326
328
329 const irep_idt identifier=function.get_identifier();
330
331 if(is_ignored(identifier))
332 return;
333
334 // see if we are already expanding it
335 if(recursion_set.find(identifier)!=recursion_set.end())
336 {
337 // it's recursive.
338 // Uh. Buh. Give up.
340 log.warning() << "recursion is ignored on call to '" << identifier << "'"
341 << messaget::eom;
342
343 if(force_full)
344 target->turn_into_skip();
345
346 return;
347 }
348
349 goto_functionst::function_mapt::iterator f_it=
350 goto_functions.function_map.find(identifier);
351
353 {
355 log.warning() << "missing function '" << identifier << "' is ignored"
356 << messaget::eom;
357
358 if(force_full)
359 target->turn_into_skip();
360
361 return;
362 }
363
364 // function to inline
365 goto_functiont &goto_function=f_it->second;
366
367 if(goto_function.body_available())
368 {
369 if(transitive)
370 {
371 const goto_functiont &cached=
373 identifier,
374 goto_function,
375 force_full);
376
377 // insert 'cached' into 'dest' at 'target'
379 cached,
380 dest,
381 target,
382 lhs,
383 function,
384 arguments);
385
386 log.progress() << "Inserting " << identifier << " into caller"
387 << messaget::eom;
388 log.progress() << "Number of instructions: "
389 << cached.body.instructions.size() << messaget::eom;
390
391 if(!caching)
392 {
393 log.progress() << "Removing " << identifier << " from cache"
394 << messaget::eom;
395 log.progress() << "Number of instructions: "
396 << cached.body.instructions.size() << messaget::eom;
397
399 cache.erase(identifier);
400 }
401 }
402 else
403 {
404 // inline non-transitively
406 identifier,
407 goto_function,
409 force_full);
410
411 // insert 'goto_function' into 'dest' at 'target'
413 goto_function,
414 dest,
415 target,
416 lhs,
417 function,
418 arguments);
419 }
420 }
421 else // no body available
422 {
423 if(no_body_set.insert(identifier).second) // newly inserted
424 {
426 log.warning() << "no body for function '" << identifier << "'"
427 << messaget::eom;
428 }
429 }
430}
431
434 exprt &lhs,
435 exprt &function,
436 exprt::operandst &arguments)
437{
438 PRECONDITION(it->is_function_call());
439
440 lhs = it->call_lhs();
441 function = it->call_function();
442 arguments = it->call_arguments();
443}
444
451 const inline_mapt &inline_map,
452 const bool force_full)
453{
455
457 {
458 const irep_idt identifier = gf_entry.first;
459 DATA_INVARIANT(!identifier.empty(), "function name must not be empty");
460 goto_functiont &goto_function = gf_entry.second;
461
462 if(!goto_function.body_available())
463 continue;
464
465 goto_inline(identifier, goto_function, inline_map, force_full);
466 }
467}
468
477 const irep_idt identifier,
478 goto_functiont &goto_function,
479 const inline_mapt &inline_map,
480 const bool force_full)
481{
483
485 identifier,
486 goto_function,
488 force_full);
489}
490
493 goto_programt &goto_program,
494 const bool force_full)
495{
497 for(const auto &call : call_list)
498 {
499 // each top level call in the program gets its own fresh inline map
502 goto_program, inline_map, call.second, force_full, call.first);
503 }
504}
505
507 const irep_idt identifier,
508 goto_functiont &goto_function,
509 const inline_mapt &inline_map,
510 const bool force_full)
511{
512 PRECONDITION(goto_function.body_available());
513
514 finished_sett::const_iterator f_it=finished_set.find(identifier);
515
516 if(f_it!=finished_set.end())
517 return;
518
520
521 goto_programt &goto_program=goto_function.body;
522
523 const inline_mapt::const_iterator im_it=inline_map.find(identifier);
524
525 if(im_it==inline_map.end())
526 return;
527
528 const call_listt &call_list=im_it->second;
529
530 if(call_list.empty())
531 return;
532
533 recursion_set.insert(identifier);
534
535 for(const auto &call : call_list)
536 {
537 const bool transitive=call.second;
538
541
543 goto_program,
547 call.first);
548 }
549
550 recursion_set.erase(identifier);
551
552 // remove_skip(goto_program);
553 // goto_program.update(); // does not change loop ids
554
555 finished_set.insert(identifier);
556}
557
559 const irep_idt identifier,
560 const goto_functiont &goto_function,
561 const bool force_full)
562{
563 PRECONDITION(goto_function.body_available());
564
565 cachet::const_iterator c_it=cache.find(identifier);
566
567 if(c_it!=cache.end())
568 {
569 const goto_functiont &cached=c_it->second;
571 cached.body_available(),
572 "body of cached functions must be available");
573 return cached;
574 }
575
576 goto_functiont &cached=cache[identifier];
578 cached.body.empty(), "body of new function in cache must be empty");
579
580 log.progress() << "Creating copy of " << identifier << messaget::eom;
581 log.progress() << "Number of instructions: "
582 << goto_function.body.instructions.size() << messaget::eom;
583
584 cached.copy_from(goto_function); // location numbers not changed
585 inline_log.copy_from(goto_function.body, cached.body);
586
587 goto_programt &goto_program=cached.body;
588
590
592 {
593 if(i_it->is_function_call())
594 call_list.push_back(i_it);
595 }
596
597 if(call_list.empty())
598 return cached;
599
600 recursion_set.insert(identifier);
601
602 for(const auto &call : call_list)
603 {
605 goto_program,
606 inline_mapt(),
607 true,
609 call);
610 }
611
612 recursion_set.erase(identifier);
613
614 // remove_skip(goto_program);
615 // goto_program.update(); // does not change loop ids
616
617 return cached;
618}
619
621{
622 return id == CPROVER_PREFIX "cleanup" || id == CPROVER_PREFIX "set_must" ||
623 id == CPROVER_PREFIX "set_may" || id == CPROVER_PREFIX "clear_must" ||
624 id == CPROVER_PREFIX "clear_may" || id == CPROVER_PREFIX "cover";
625}
626
628 const irep_idt identifier,
629 const inline_mapt &inline_map) const
630{
631 goto_functionst::function_mapt::const_iterator f_it=
632 goto_functions.function_map.find(identifier);
633
635
636 inline_mapt::const_iterator im_it=inline_map.find(identifier);
637
638 if(im_it==inline_map.end())
639 return true;
640
641 const call_listt &call_list=im_it->second;
642
643 if(call_list.empty())
644 return true;
645
647
648 for(const auto &call : call_list)
649 {
650 const goto_programt::const_targett target=call.first;
651
652 #if 0
653 // might not hold if call was previously inlined
654 if(target->function!=identifier)
655 return false;
656 #endif
657
658 // location numbers increasing
659 if(
661 target->location_number <= ln)
662 {
663 return false;
664 }
665
666 if(!target->is_function_call())
667 return false;
668
669 ln=target->location_number;
670 }
671
672 return true;
673}
674
676{
677 for(const auto &gf_entry : goto_functions.function_map)
678 {
680 return false;
681 }
682
683 return true;
684}
685
687 std::ostream &out,
688 const inline_mapt &inline_map)
689{
691
692 for(const auto &it : inline_map)
693 {
694 const irep_idt &id=it.first;
695 const call_listt &call_list=it.second;
696
697 out << "Function: " << id << "\n";
698
699 goto_functionst::function_mapt::const_iterator f_it=
701
702 if(f_it!=goto_functions.function_map.end() &&
703 !call_list.empty())
704 {
705 const goto_functiont &goto_function=f_it->second;
707 goto_function.body_available(),
708 "cannot inline function with empty body");
709
710 for(const auto &call : call_list)
711 {
712 const goto_programt::const_targett target=call.first;
713 bool transitive=call.second;
714
715 out << " Call:\n";
716 target->output(out);
717 out << " Transitive: " << transitive << "\n";
718 }
719 }
720 else
721 {
722 out << " -\n";
723 }
724 }
725}
726
727void goto_inlinet::output_cache(std::ostream &out) const
728{
729 for(auto it=cache.begin(); it!=cache.end(); it++)
730 {
731 if(it!=cache.begin())
732 out << ", ";
733
734 out << it->first << "\n";
735 }
736}
737
738// remove segment that refer to the given goto program
740 const goto_programt &goto_program)
741{
742 forall_goto_program_instructions(it, goto_program)
743 log_map.erase(it);
744}
745
747 const goto_functionst::function_mapt &function_map)
748{
749 for(const auto &it : function_map)
750 {
751 const goto_functiont &goto_function=it.second;
752
753 if(!goto_function.body_available())
754 continue;
755
756 cleanup(goto_function.body);
757 }
758}
759
761 const goto_programt &goto_program,
762 const unsigned begin_location_number,
763 const unsigned end_location_number,
764 const unsigned call_location_number,
765 const irep_idt function)
766{
767 PRECONDITION(!goto_program.empty());
768 PRECONDITION(!function.empty());
769 PRECONDITION(end_location_number >= begin_location_number);
770
771 goto_programt::const_targett start=goto_program.instructions.begin();
772 INVARIANT(
773 log_map.find(start) == log_map.end(),
774 "inline function should be registered once in map of inline functions");
775
776 goto_programt::const_targett end=goto_program.instructions.end();
777 end--;
778
780 info.begin_location_number=begin_location_number;
781 info.end_location_number=end_location_number;
782 info.call_location_number=call_location_number;
783 info.function=function;
784 info.end=end;
785
786 log_map[start]=info;
787}
788
790 const goto_programt &from,
791 const goto_programt &to)
792{
793 PRECONDITION(from.instructions.size() == to.instructions.size());
794
795 goto_programt::const_targett it1=from.instructions.begin();
796 goto_programt::const_targett it2=to.instructions.begin();
797
798 for(; it1!=from.instructions.end(); it1++, it2++)
799 {
801 it2 != to.instructions.end(),
802 "'to' target function is not allowed to be empty");
804 it1->location_number == it2->location_number,
805 "both functions' instruction should point to the same source");
806
807 log_mapt::const_iterator l_it=log_map.find(it1);
808 if(l_it!=log_map.end()) // a segment starts here
809 {
810 // as 'to' is a fresh copy
812 log_map.find(it2) == log_map.end(),
813 "'to' target is not expected to be in the log_map");
814
817
818 // find end of new
821 while(tmp_it!=end)
822 {
823 new_end++;
824 tmp_it++;
825 }
826
827 info.end=new_end;
828
829 log_map[it2]=info;
830 }
831 }
832}
833
834// call after goto_functions.update()!
836{
838 json_arrayt &json_inlined=json_result["inlined"].make_array();
839
840 for(const auto &it : log_map)
841 {
842 goto_programt::const_targett start=it.first;
843 const goto_inline_log_infot &info=it.second;
845
846 PRECONDITION(start->location_number <= end->location_number);
847
849 json_numbert(std::to_string(info.begin_location_number)),
850 json_numbert(std::to_string(info.end_location_number))};
851 json_arrayt json_new{json_numbert(std::to_string(start->location_number)),
852 json_numbert(std::to_string(end->location_number))};
853
854 json_objectt object{
855 {"call", json_numbert(std::to_string(info.call_location_number))},
856 {"function", json_stringt(info.function.c_str())},
857 {"originalSegment", std::move(json_orig)},
858 {"inlinedSegment", std::move(json_new)}};
859
860 json_inlined.push_back(std::move(object));
861 }
862
863 return std::move(json_result);
864}
virtual void output(const namespacet &ns, const irep_idt &function_id, const goto_programt &goto_program, std::ostream &out) const
Output the abstract states for a single function.
Definition ai.cpp:39
virtual void clear()
Reset the abstract state.
Definition ai.h:265
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
A goto_instruction_codet representing an assignment in the program.
A goto_instruction_codet representing the declaration of a local variable.
codet representation of an expression statement.
Definition std_code.h:1394
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition dstring.h:38
bool empty() const
Definition dstring.h:89
Base class for all expressions.
Definition expr.h:56
const source_locationt & find_source_location() const
Get a source_locationt from the expression or from its operands (non-recursively).
Definition expr.cpp:147
std::vector< exprt > operandst
Definition expr.h:58
typet & type()
Return the type of the expression.
Definition expr.h:84
const source_locationt & source_location() const
Definition expr.h:231
source_locationt & add_source_location()
Definition expr.h:236
std::map< irep_idt, goto_functiont > function_mapt
function_mapt function_map
A goto function, consisting of function body (see body) and parameter identifiers (see parameter_iden...
goto_programt body
bool is_hidden() const
std::vector< irep_idt > parameter_identifierst
parameter_identifierst parameter_identifiers
The identifiers of the parameters of this function.
bool body_available() const
void copy_from(const goto_programt &from, const goto_programt &to)
void cleanup(const goto_programt &goto_program)
void add_segment(const goto_programt &goto_program, const unsigned begin_location_number, const unsigned end_location_number, const unsigned call_location_number, const irep_idt function)
bool is_ignored(const irep_idt id) const
void goto_inline_nontransitive(const irep_idt identifier, goto_functiont &goto_function, const inline_mapt &inline_map, const bool force_full)
std::list< callt > call_listt
goto_functionst & goto_functions
static void get_call(goto_programt::const_targett target, exprt &lhs, exprt &function, exprt::operandst &arguments)
no_body_sett no_body_set
const goto_functiont & goto_inline_transitive(const irep_idt identifier, const goto_functiont &goto_function, const bool force_full)
void goto_inline(const irep_idt identifier, goto_functiont &goto_function, const inline_mapt &inline_map, const bool force_full=false)
Inline all of the chosen calls in a given function.
recursion_sett recursion_set
void insert_function_body(const goto_functiont &f, goto_programt &dest, goto_programt::targett target, const exprt &lhs, const symbol_exprt &function, const exprt::operandst &arguments)
bool check_inline_map(const inline_mapt &inline_map) const
void parameter_destruction(const goto_programt::targett target, const goto_functiont::parameter_identifierst &parameter_identifiers, goto_programt &dest)
const bool adjust_function
goto_inline_logt inline_log
void output_inline_map(std::ostream &out, const inline_mapt &inline_map)
goto_functionst::goto_functiont goto_functiont
void parameter_assignments(const goto_programt::targett target, const irep_idt &function_name, const goto_functiont::parameter_identifierst &parameter_identifiers, const exprt::operandst &arguments, goto_programt &dest)
std::map< irep_idt, call_listt > inline_mapt
void replace_return(goto_programt &body, const exprt &lhs)
finished_sett finished_set
const namespacet & ns
void expand_function_call(goto_programt &dest, const inline_mapt &inline_map, const bool transitive, const bool force_full, goto_programt::targett target)
Inlines a single function call Calls out to goto_inline_transitive or goto_inline_nontransitive.
void output_cache(std::ostream &out) const
This class represents an instruction in the GOTO intermediate representation.
static const unsigned nil_target
Uniquely identify an invalid target or location.
const source_locationt & source_location() const
A generic container class for the GOTO intermediate representation of one function.
instructionst instructions
The list of instructions in the goto program.
void copy_from(const goto_programt &src)
Copy a full goto program, preserving targets.
static instructiont make_dead(const symbol_exprt &symbol, const source_locationt &l=source_locationt::nil())
void destructive_insert(const_targett target, goto_programt &p)
Inserts the given program p before target.
instructionst::iterator targett
instructionst::const_iterator const_targett
static instructiont make_assignment(const code_assignt &_code, const source_locationt &l=source_locationt::nil())
Create an assignment instruction.
static instructiont make_other(const goto_instruction_codet &_code, const source_locationt &l=source_locationt::nil())
static instructiont make_location(const source_locationt &l)
targett add(instructiont &&instruction)
Adds a given instruction at the end.
bool empty() const
Is the program empty?
static instructiont make_decl(const symbol_exprt &symbol, const source_locationt &l=source_locationt::nil())
std::list< targett > targetst
const irept & find(const irep_idt &name) const
Definition irep.cpp:93
bool is_not_nil() const
Definition irep.h:372
Definition json.h:27
source_locationt source_location
Definition message.h:239
mstreamt & warning() const
Definition message.h:396
mstreamt & progress() const
Definition message.h:416
static eomt eom
Definition message.h:289
A side_effect_exprt that returns a non-deterministically chosen value.
Definition std_code.h:1520
void set_comment(const irep_idt &comment)
void set_property_id(const irep_idt &property_id)
const irep_idt & get_property_id() const
void set_property_class(const irep_idt &property_class)
const irep_idt & get_property_class() const
std::string as_string() const
const irep_idt & get_comment() const
Expression to hold a symbol (variable)
Definition std_expr.h:131
const irep_idt & get_identifier() const
Definition std_expr.h:160
Symbol table entry.
Definition symbol.h:28
class symbol_exprt symbol_expr() const
Produces a symbol_exprt for a symbol.
Definition symbol.cpp:121
typet type
Type of symbol.
Definition symbol.h:31
Semantic type conversion.
Definition std_expr.h:2073
static exprt conditional_cast(const exprt &expr, const typet &type)
Definition std_expr.h:2081
The type of an expression, extends irept.
Definition type.h:29
#define CPROVER_PREFIX
#define Forall_operands(it, expr)
Definition expr.h:27
void replace_location(source_locationt &dest, const source_locationt &new_location)
Function Inlining This is a class that encapsulates the state and functionality needed to do inline m...
#define forall_goto_program_instructions(it, program)
#define Forall_goto_program_instructions(it, program)
static std::string comment(const rw_set_baset::entryt &entry, bool write)
#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
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition std_expr.h:272
Symbol table entry.
const type_with_subtypet & to_type_with_subtype(const typet &type)
Definition type.h:208