CBMC
Loading...
Searching...
No Matches
c_typecheck_code.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: C Language Type Checking
4
5Author: Daniel Kroening, kroening@kroening.com
6
7\*******************************************************************/
8
11
12#include <util/c_types.h>
13#include <util/config.h>
14#include <util/cprover_prefix.h>
15#include <util/expr_util.h>
16#include <util/range.h>
19
20#include "ansi_c_declaration.h"
21#include "c_expr.h"
22#include "c_typecheck_base.h"
23
28
30{
31 if(code.id()!=ID_code)
32 {
34 error() << "expected code, got " << code.pretty() << eom;
35 throw 0;
36 }
37
38 code.type() = empty_typet();
39
40 const irep_idt &statement=code.get_statement();
41
42 if(statement==ID_expression)
44 else if(statement==ID_label)
46 else if(statement==ID_switch_case)
48 else if(statement==ID_gcc_switch_case_range)
50 else if(statement==ID_block)
52 else if(statement==ID_decl_block)
53 {
54 }
55 else if(statement==ID_ifthenelse)
57 else if(statement==ID_while)
59 else if(statement==ID_dowhile)
61 else if(statement==ID_for)
62 typecheck_for(code);
63 else if(statement==ID_switch)
64 typecheck_switch(code);
65 else if(statement==ID_break)
66 typecheck_break(code);
67 else if(statement==ID_goto)
69 else if(statement==ID_gcc_computed_goto)
71 else if(statement==ID_continue)
73 else if(statement==ID_return)
75 else if(statement==ID_decl)
76 typecheck_decl(code);
77 else if(statement==ID_assign)
78 typecheck_assign(code);
79 else if(statement==ID_skip)
80 {
81 }
82 else if(statement==ID_asm)
84 else if(statement==ID_start_thread)
86 else if(statement==ID_gcc_local_label)
88 else if(statement==ID_msc_try_finally)
89 {
90 PRECONDITION(code.operands().size() == 2);
91 typecheck_code(to_code(code.op0()));
92 typecheck_code(to_code(code.op1()));
93 }
94 else if(statement==ID_msc_try_except)
95 {
96 PRECONDITION(code.operands().size() == 3);
97 typecheck_code(to_code(code.op0()));
98 typecheck_expr(code.op1());
99 typecheck_code(to_code(code.op2()));
100 }
101 else if(statement==ID_msc_leave)
102 {
103 // fine as is, but should check that we
104 // are in a 'try' block
105 }
106 else if(statement==ID_static_assert)
107 {
108 // C23 allows static_assert without message
109 PRECONDITION(code.operands().size() == 1 || code.operands().size() == 2);
110
111 typecheck_expr(code.op0());
112
113 if(code.operands().size() == 2)
114 typecheck_expr(code.op1());
115
117 make_constant(code.op0());
118
119 if(code.op0() == false)
120 {
121 // failed
123 error() << "static assertion failed";
124 if(code.operands().size() == 2 && code.op1().id() == ID_string_constant)
125 error() << ": " << to_string_constant(code.op1()).value();
126 error() << eom;
127 throw 0;
128 }
129 }
130 else if(statement==ID_CPROVER_try_catch ||
131 statement==ID_CPROVER_try_finally)
132 {
133 PRECONDITION(code.operands().size() == 2);
134 typecheck_code(to_code(code.op0()));
135 typecheck_code(to_code(code.op1()));
136 }
137 else if(statement==ID_CPROVER_throw)
138 {
139 PRECONDITION(code.operands().empty());
140 }
141 else if(statement==ID_assume ||
142 statement==ID_assert)
143 {
144 // These are not generated by the C/C++ parsers,
145 // but we allow them for the benefit of other users
146 // of the typechecker.
147 PRECONDITION(code.operands().size() == 1);
148 typecheck_expr(code.op0());
149 }
150 else
151 {
153 error() << "unexpected statement: " << statement << eom;
154 throw 0;
155 }
156}
157
159{
160 const irep_idt flavor = code.get_flavor();
161
162 if(flavor==ID_gcc)
163 {
164 // These have 5 operands.
165 // The first operand is a string.
166 // Operands 1, 2, 3, 4 are lists of expressions.
167
168 // Operand 1: OutputOperands
169 // Operand 2: InputOperands
170 // Operand 3: Clobbers
171 // Operand 4: GotoLabels
172
173 auto &code_asm_gcc = to_code_asm_gcc(code);
174
175 typecheck_expr(code_asm_gcc.asm_text());
176
177 // the operands are lists of expressions
179 code_asm_gcc.operands().begin() + 1, code_asm_gcc.operands().end()))
180 {
181 for(auto &expr : op.operands())
182 typecheck_expr(expr);
183 }
184 }
185 else if(flavor==ID_msc)
186 {
187 PRECONDITION(code.operands().size() == 1);
188 typecheck_expr(code.op0());
189 }
190}
191
193{
194 if(code.operands().size()!=2)
195 {
197 error() << "assignment statement expected to have two operands"
198 << eom;
199 throw 0;
200 }
201
202 typecheck_expr(code.op0());
203 typecheck_expr(code.op1());
204
205 implicit_typecast(code.op1(), code.op0().type());
206}
207
209{
210 for(auto &c : code.statements())
212
213 // do decl-blocks
214
216 new_ops.statements().reserve(code.statements().size());
217
218 for(auto &code_op : code.statements())
219 {
220 if(code_op.is_not_nil())
221 new_ops.add(std::move(code_op));
222 }
223
224 code.statements().swap(new_ops.statements());
225}
226
228{
230 {
232 error() << "break not allowed here" << eom;
233 throw 0;
234 }
235}
236
238{
240 {
242 error() << "continue not allowed here" << eom;
243 throw 0;
244 }
245}
246
248{
249 // this comes with 1 operand, which is a declaration
250 if(code.operands().size()!=1)
251 {
253 error() << "decl expected to have 1 operand" << eom;
254 throw 0;
255 }
256
257 // op0 must be declaration
258 if(code.op0().id()!=ID_declaration)
259 {
261 error() << "decl statement expected to have declaration as operand"
262 << eom;
263 throw 0;
264 }
265
266 ansi_c_declarationt declaration;
267 declaration.swap(code.op0());
268
269 if(declaration.get_is_static_assert())
270 {
271 codet new_code(ID_static_assert);
272 new_code.add_source_location()=code.source_location();
273 new_code.operands().swap(declaration.operands());
274 code.swap(new_code);
275 typecheck_code(code);
276 return; // done
277 }
278
279 typecheck_declaration(declaration);
280
281 std::list<codet> new_code;
282
283 // iterate over declarators
284
285 for(const auto &d : declaration.declarators())
286 {
287 irep_idt identifier = d.get_name();
288
289 // look it up
290 symbol_table_baset::symbolst::const_iterator s_it =
291 symbol_table.symbols.find(identifier);
292
293 if(s_it==symbol_table.symbols.end())
294 {
296 error() << "failed to find decl symbol '" << identifier
297 << "' in symbol table" << eom;
298 throw 0;
299 }
300
301 const symbolt &symbol=s_it->second;
302
303 // This must not be an incomplete type, unless it's 'extern'
304 // or a typedef.
305 if(!symbol.is_type &&
306 !symbol.is_extern &&
307 !is_complete_type(symbol.type))
308 {
310 error() << "incomplete type not permitted here" << eom;
311 throw 0;
312 }
313
314 // see if it's a typedef
315 // or a function
316 // or static
317 if(symbol.is_type || symbol.type.id() == ID_code)
318 {
319 // we ignore
320 }
321 else if(symbol.is_static_lifetime)
322 {
323 // make sure the initialization value is a compile-time constant
324 if(symbol.value.is_not_nil())
325 {
326 exprt init_value = symbol.value;
328 }
329 }
330 else
331 {
332 code_frontend_declt decl(symbol.symbol_expr());
333 decl.add_source_location() = symbol.location;
334 decl.symbol().add_source_location() = symbol.location;
335
336 // add initializer, if any
337 if(symbol.value.is_not_nil())
338 {
339 decl.operands().resize(2);
340 decl.op1() = symbol.value;
341 }
342
343 new_code.push_back(decl);
344 }
345 }
346
347 // stash away any side-effects in the declaration
348 new_code.splice(new_code.begin(), clean_code);
349
350 if(new_code.empty())
351 {
352 source_locationt source_location=code.source_location();
353 code=code_skipt();
354 code.add_source_location()=source_location;
355 }
356 else if(new_code.size()==1)
357 {
358 code.swap(new_code.front());
359 }
360 else
361 {
362 // build a decl-block
363 auto code_block=code_blockt::from_list(new_code);
364 code_block.set_statement(ID_decl_block);
365 code.swap(code_block);
366 }
367}
368
370{
371 if(type.id() == ID_array)
372 {
373 const auto &array_type = to_array_type(type);
374
375 if(array_type.size().is_nil())
376 return false;
377
378 return is_complete_type(array_type.element_type());
379 }
380 else if(type.id()==ID_struct || type.id()==ID_union)
381 {
382 const auto &struct_union_type = to_struct_union_type(type);
383
384 if(struct_union_type.is_incomplete())
385 return false;
386
387 for(const auto &c : struct_union_type.components())
388 if(!is_complete_type(c.type()))
389 return false;
390 }
391 else if(type.id()==ID_vector)
392 return is_complete_type(to_vector_type(type).element_type());
394 {
396 }
398 {
400 }
401
402 return true;
403}
404
406{
407 if(code.operands().size()!=1)
408 {
410 error() << "expression statement expected to have one operand"
411 << eom;
412 throw 0;
413 }
414
415 exprt &op=code.op0();
416 typecheck_expr(op);
417}
418
420{
421 if(code.operands().size()!=4)
422 {
424 error() << "for expected to have four operands" << eom;
425 throw 0;
426 }
427
428 // the "for" statement has an implicit block around it,
429 // since code.op0() may contain declarations
430 //
431 // we therefore transform
432 //
433 // for(a;b;c) d;
434 //
435 // to
436 //
437 // { a; for(;b;c) d; }
438 //
439 // if config.ansi_c.for_has_scope
440
441 if(!config.ansi_c.for_has_scope ||
442 code.op0().is_nil())
443 {
444 if(code.op0().is_not_nil())
445 typecheck_code(to_code(code.op0()));
446
447 if(code.op1().is_nil())
448 code.op1()=true_exprt();
449 else
450 {
451 typecheck_expr(code.op1());
453 }
454
455 if(code.op2().is_not_nil())
456 typecheck_expr(code.op2());
457
458 if(code.op3().is_not_nil())
459 {
460 // save & set flags
463
465
466 // recursive call
467 if(to_code(code.op3()).get_statement()==ID_decl_block)
468 {
470 code_block.add_source_location()=code.op3().source_location();
471
472 code_block.add(std::move(to_code(code.op3())));
473 code.op3().swap(code_block);
474 }
475 typecheck_code(to_code(code.op3()));
476
477 // restore flags
480 }
481 }
482 else
483 {
485 code_block.add_source_location()=code.source_location();
486 if(to_code(code.op3()).get_statement()==ID_block)
487 {
488 code_block.set(
490 to_code_block(to_code(code.op3())).end_location());
491 }
492 else
493 {
494 code_block.set(
496 code.op3().source_location());
497 }
498
499 code_block.reserve_operands(2);
500 code_block.add(std::move(to_code(code.op0())));
501 code.op0().make_nil();
502 code_block.add(std::move(code));
503 code.swap(code_block);
504 typecheck_code(code); // recursive call
505 }
506
509
510 if(code.find(ID_C_spec_assigns).is_not_nil())
511 {
513 static_cast<unary_exprt &>(code.add(ID_C_spec_assigns)).op().operands());
514 }
515
516 if(code.find(ID_C_spec_frees).is_not_nil())
517 {
519 static_cast<unary_exprt &>(code.add(ID_C_spec_frees)).op().operands());
520 }
521}
522
524{
525 // record the label
526 if(!labels_defined.emplace(code.get_label(), code.source_location()).second)
527 {
529 error() << "duplicate label '" << code.get_label() << "'" << eom;
530 throw 0;
531 }
532
533 typecheck_code(code.code());
534}
535
537{
538 if(code.operands().size()!=2)
539 {
541 error() << "switch_case expected to have two operands" << eom;
542 throw 0;
543 }
544
545 typecheck_code(code.code());
546
547 if(code.is_default())
548 {
549 if(!case_is_allowed)
550 {
552 error() << "did not expect default label here" << eom;
553 throw 0;
554 }
555 }
556 else
557 {
558 if(!case_is_allowed)
559 {
561 error() << "did not expect " << quote_begin << "case" << quote_end
562 << " here" << eom;
563 throw 0;
564 }
565
566 exprt &case_expr=code.case_op();
570 }
571}
572
575{
576 if(!case_is_allowed)
577 {
579 error() << "did not expect " << quote_begin << "case" << quote_end
580 << " here" << eom;
581 throw 0;
582 }
583
584 typecheck_expr(code.lower());
585 typecheck_expr(code.upper());
588 make_constant(code.lower());
589 make_constant(code.upper());
590 typecheck_code(code.code());
591}
592
594{
595 // these are just declarations, e.g.,
596 // __label__ here, there;
597}
598
600{
601 // we record the label used
603}
604
606{
607 if(code.operands().size()!=1)
608 {
610 error() << "computed-goto expected to have one operand" << eom;
611 throw 0;
612 }
613
614 exprt &dest=code.op0();
615
616 if(dest.id()!=ID_dereference)
617 {
619 error() << "computed-goto expected to have dereferencing operand"
620 << eom;
621 throw 0;
622 }
623
624 typecheck_expr(to_unary_expr(dest).op());
625 dest.type() = void_type();
626}
627
629{
630 if(code.operands().size()!=3)
631 {
633 error() << "ifthenelse expected to have three operands" << eom;
634 throw 0;
635 }
636
637 exprt &cond=code.cond();
638
639 typecheck_expr(cond);
640
642
643 if(code.then_case().get_statement() == ID_decl_block)
644 {
646 code_block.add_source_location()=code.then_case().source_location();
647 code.then_case() = code_block;
648 }
649
651
652 if(!code.else_case().is_nil())
653 {
654 if(code.else_case().get_statement() == ID_decl_block)
655 {
657 code_block.add_source_location()=code.else_case().source_location();
658 code.else_case() = code_block;
659 }
660
662 }
663}
664
666{
667 if(code.operands().size()!=1)
668 {
670 error() << "start_thread expected to have one operand" << eom;
671 throw 0;
672 }
673
674 typecheck_code(to_code(code.op0()));
675}
676
678{
679 if(code.has_return_value())
680 {
682
683 if(return_type.id() == ID_empty)
684 {
685 // gcc doesn't actually complain, it just warns!
686 if(code.return_value().type().id() != ID_empty)
687 {
689
690 warning() << "function has return void ";
691 warning() << "but a return statement returning ";
692 warning() << to_string(code.return_value().type());
693 warning() << eom;
694
696 }
697 }
698 else
700 }
701 else if(
704 {
705 // gcc doesn't actually complain, it just warns!
707 warning() << "non-void function should return a value" << eom;
708
709 code.return_value() =
711 }
712}
713
715{
716 // we expect a code_switcht, but might return either a code_switcht or a
717 // code_blockt, hence don't use code_switcht in the interface
719
721
722 // this needs to be promoted
724
725 // save & set flags
726
730
731 switch_op_type = code_switch.value().type();
733
735
736 if(code_switch.body().get_statement() == ID_block)
737 {
738 // Collect all declarations before the first case, if there is any case
739 // (including a default one).
741
743 for(auto &statement : body_block.statements())
744 {
745 if(statement.get_statement() == ID_switch_case)
746 break;
747 else if(statement.get_statement() == ID_decl)
748 {
749 if(statement.operands().size() == 1)
750 {
752 wrapping_block.statements().back().swap(statement);
753 }
754 else
755 {
756 PRECONDITION(statement.operands().size() == 2);
757 wrapping_block.add(statement);
758 wrapping_block.statements().back().operands().pop_back();
759 statement.set_statement(ID_assign);
760 }
761 }
762 }
763
764 if(!wrapping_block.statements().empty())
765 {
766 wrapping_block.add(std::move(code));
767 code.swap(wrapping_block);
768 }
769 }
770
771 // restore flags
775}
776
778{
779 if(code.operands().size()!=2)
780 {
782 error() << "while expected to have two operands" << eom;
783 throw 0;
784 }
785
786 typecheck_expr(code.cond());
788
789 // save & set flags
792
794
795 if(code.body().get_statement()==ID_decl_block)
796 {
797 code_blockt code_block({code.body()});
798 code_block.add_source_location()=code.body().source_location();
799 code.body() = code_block;
800 }
801 typecheck_code(code.body());
802
803 // restore flags
806
809
810 if(code.find(ID_C_spec_assigns).is_not_nil())
811 {
813 static_cast<unary_exprt &>(code.add(ID_C_spec_assigns)).op().operands());
814 }
815
816 if(code.find(ID_C_spec_frees).is_not_nil())
817 {
819 static_cast<unary_exprt &>(code.add(ID_C_spec_frees)).op().operands());
820 }
821}
822
824{
825 if(code.operands().size()!=2)
826 {
828 error() << "do while expected to have two operands" << eom;
829 throw 0;
830 }
831
832 typecheck_expr(code.cond());
834
835 // save & set flags
838
840
841 if(code.body().get_statement()==ID_decl_block)
842 {
843 code_blockt code_block({code.body()});
844 code_block.add_source_location()=code.body().source_location();
845 code.body() = code_block;
846 }
847 typecheck_code(code.body());
848
849 // restore flags
852
855
856 if(code.find(ID_C_spec_assigns).is_not_nil())
857 {
859 static_cast<unary_exprt &>(code.add(ID_C_spec_assigns)).op().operands());
860 }
861
862 if(code.find(ID_C_spec_frees).is_not_nil())
863 {
865 static_cast<unary_exprt &>(code.add(ID_C_spec_frees)).op().operands());
866 }
867}
868
870{
871 if(has_subexpr(expr, ID_side_effect))
872 {
874 "side-effects not allowed in assigns clause targets",
875 expr.source_location()};
876 }
877 if(has_subexpr(expr, ID_if))
878 {
880 "ternary expressions not allowed in assigns clause targets",
881 expr.source_location()};
882 }
883}
884
886{
887 // compute type
888 typecheck_expr(condition);
889
890 // make it boolean if needed
891 implicit_typecast_bool(condition);
892
893 // non-fatal warnings
895 {
896 // Remark: we allow function calls without further checks for now because
897 // they are mandatory for some applications.
898 // The next step must be to check that the called functions have a contract
899 // with an empty assigns clause and that they indeed satisfy their contract
900 // using a CI check.
902 warning()
903 << "function with possible side-effect called in target's condition"
904 << eom;
905 }
906
907 if(condition.type().id() == ID_empty)
908 {
910 "void-typed expressions not allowed as assigns clause conditions",
911 condition.source_location()};
912 }
913
914 if(has_subexpr(condition, [&](const exprt &subexpr) {
917 }))
918 {
920 "side-effects not allowed in assigns clause conditions",
921 condition.source_location()};
922 }
923
924 if(has_subexpr(condition, ID_if))
925 {
927 "ternary expressions not allowed in assigns clause conditions",
928 condition.source_location()};
929 }
930}
931
933 exprt::operandst &targets,
934 const std::function<void(exprt &)> typecheck_target,
935 const std::string &clause_type)
936{
938
939 for(auto &target : targets)
940 {
942 {
944 "expected a conditional target group expression in " + clause_type +
945 "clause, found " + id2string(target.id()),
946 target.source_location()};
947 }
948
951
952 // typecheck condition
953 auto &condition = conditional_target_group.condition();
954 typecheck_spec_condition(condition);
955
956 if(condition == true)
957 {
958 // if the condition is trivially true,
959 // simplify expr and expose the bare expressions
960 for(auto &actual_target : conditional_target_group.targets())
961 {
963 new_targets.push_back(actual_target);
964 }
965 }
966 else
967 {
968 // if the condition is not trivially true, typecheck in place
969 for(auto &actual_target : conditional_target_group.targets())
970 {
972 }
973 new_targets.push_back(std::move(target));
974 }
975 }
976
977 // now each target is either:
978 // - a simple side-effect-free unconditional lvalue expression or
979 // - a conditional target group expression with a non-trivial condition
980
981 // update original vector in-place
982 std::swap(targets, new_targets);
983}
984
986{
987 const std::function<void(exprt &)> typecheck_target = [&](exprt &target) {
989 };
991}
992
994{
995 const std::function<void(exprt &)> typecheck_target = [&](exprt &target) {
997 };
999}
1000
1002{
1003 // compute type
1004 typecheck_expr(target);
1005
1006 if(target.get_bool(ID_C_lvalue))
1007 {
1008 if(target.type().id() == ID_empty)
1009 {
1011 "lvalue expressions with void type not allowed in assigns clauses",
1012 target.source_location()};
1013 }
1014 throw_on_side_effects(target);
1015 return;
1016 }
1018 {
1019 const auto &funcall = to_side_effect_expr_function_call(target);
1020 if(!can_cast_expr<symbol_exprt>(funcall.function()))
1021 {
1023 "function pointer calls not allowed in assigns clauses",
1024 target.source_location());
1025 }
1026
1027 if(target.type().id() != ID_empty)
1028 {
1030 "expecting void return type for function '" +
1031 id2string(to_symbol_expr(funcall.function()).identifier()) +
1032 "' called in assigns clause",
1033 target.source_location());
1034 }
1035
1036 for(const auto &argument : funcall.arguments())
1038 }
1039 else
1040 {
1041 // if we reach this point the target did not pass the checks
1043 "assigns clause target must be a non-void lvalue or a call to a function "
1044 "returning void",
1045 target.source_location());
1046 }
1047}
1048
1050{
1051 // compute type
1052 typecheck_expr(target);
1053 const auto &type = target.type();
1054
1056 {
1057 // an expression with pointer-type without side effects
1058 throw_on_side_effects(target);
1059 }
1061 {
1062 // A call to a void function symbol without other side effects
1063 const auto &funcall = to_side_effect_expr_function_call(target);
1064
1065 if(!can_cast_expr<symbol_exprt>(funcall.function()))
1066 {
1068 "function pointer calls not allowed in frees clauses",
1069 target.source_location());
1070 }
1071
1072 if(type.id() != ID_empty)
1073 {
1075 "expecting void return type for function '" +
1076 id2string(to_symbol_expr(funcall.function()).identifier()) +
1077 "' called in frees clause",
1078 target.source_location());
1079 }
1080
1081 for(const auto &argument : funcall.arguments())
1083 }
1084 else
1085 {
1086 // anything else is rejected
1088 "frees clause target must be a pointer-typed expression or a call to a "
1089 "function returning void",
1090 target.source_location());
1091 }
1092}
1093
1095{
1096 if(code.find(ID_C_spec_loop_invariant).is_not_nil())
1097 {
1098 for(auto &invariant :
1099 (static_cast<exprt &>(code.add(ID_C_spec_loop_invariant)).operands()))
1100 {
1101 typecheck_expr(invariant);
1102 implicit_typecast_bool(invariant);
1104 invariant,
1105 ID_old,
1106 CPROVER_PREFIX "old is not allowed in loop invariants.");
1107 }
1108 }
1109}
1110
1112{
1113 if(code.find(ID_C_spec_decreases).is_not_nil())
1114 {
1115 for(auto &decreases_clause_component :
1116 (static_cast<exprt &>(code.add(ID_C_spec_decreases)).operands()))
1117 {
1120 }
1121 }
1122}
ANSI-CC Language Type Checking.
configt config
Definition config.cpp:25
API to expression classes that are internal to the C frontend.
const conditional_target_group_exprt & to_conditional_target_group_expr(const exprt &expr)
Cast an exprt to a conditional_target_group_exprt.
Definition c_expr.h:306
void validate_expr(const shuffle_vector_exprt &value)
Definition c_expr.h:82
ANSI-C Language Type Checking.
empty_typet void_type()
Definition c_types.cpp:245
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:566
const declaratorst & declarators() const
bool get_is_static_assert() const
symbol_table_baset & symbol_table
virtual void implicit_typecast(exprt &expr, const typet &type)
virtual void typecheck_break(codet &code)
std::map< irep_idt, source_locationt > labels_used
virtual void typecheck_expr(exprt &expr)
virtual void typecheck_block(code_blockt &code)
virtual void typecheck_code(codet &code)
virtual void typecheck_while(code_whilet &code)
void disallow_subexpr_by_id(const exprt &, const irep_idt &, const std::string &) const
virtual void throw_on_side_effects(const exprt &expr)
virtual void typecheck_decl(codet &code)
virtual void typecheck_spec_decreases(codet &code)
virtual void make_constant(exprt &expr)
virtual void typecheck_assign(codet &expr)
virtual void typecheck_continue(codet &code)
virtual void implicit_typecast_arithmetic(exprt &expr)
virtual void typecheck_spec_frees_target(exprt &target)
std::list< codet > clean_code
virtual std::string to_string(const exprt &expr)
void typecheck_declaration(ansi_c_declarationt &)
virtual void typecheck_spec_assigns_target(exprt &target)
virtual void typecheck_gcc_local_label(codet &code)
virtual void typecheck_spec_condition(exprt &condition)
virtual void start_typecheck_code()
virtual void typecheck_asm(code_asmt &code)
virtual void typecheck_gcc_computed_goto(codet &code)
virtual void typecheck_conditional_targets(exprt::operandst &targets, const std::function< void(exprt &)> typecheck_target, const std::string &clause_type)
virtual void typecheck_for(codet &code)
virtual void typecheck_switch(codet &code)
virtual void typecheck_spec_frees(exprt::operandst &targets)
virtual void typecheck_expression(codet &code)
virtual void typecheck_return(code_frontend_returnt &)
virtual void typecheck_spec_assigns(exprt::operandst &targets)
virtual bool is_complete_type(const typet &type) const
virtual void typecheck_start_thread(codet &code)
virtual void typecheck_switch_case(code_switch_caset &code)
virtual void typecheck_spec_loop_invariant(codet &code)
virtual void typecheck_gcc_switch_case_range(code_gcc_switch_case_ranget &)
virtual void implicit_typecast_bool(exprt &expr)
virtual void typecheck_dowhile(code_dowhilet &code)
virtual void typecheck_ifthenelse(code_ifthenelset &code)
virtual void typecheck_goto(code_gotot &code)
virtual void typecheck_label(code_labelt &code)
std::map< irep_idt, source_locationt > labels_defined
codet representation of an inline assembler statement.
Definition std_code.h:1253
const irep_idt & get_flavor() const
Definition std_code.h:1263
A codet representing sequential composition of program statements.
Definition std_code.h:130
static code_blockt from_list(const std::list< codet > &_list)
Definition std_code.h:148
code_operandst & statements()
Definition std_code.h:138
codet representation of a do while statement.
Definition std_code.h:672
const codet & body() const
Definition std_code.h:689
const exprt & cond() const
Definition std_code.h:679
A codet representing the declaration of a local variable.
Definition std_code.h:347
symbol_exprt & symbol()
Definition std_code.h:354
codet representation of a "return from a function" statement.
Definition std_code.h:893
const exprt & return_value() const
Definition std_code.h:903
bool has_return_value() const
Definition std_code.h:913
codet representation of a switch-case, i.e. a case statement within a switch.
Definition std_code.h:1097
const exprt & upper() const
upper bound of range
Definition std_code.h:1119
const exprt & lower() const
lower bound of range
Definition std_code.h:1107
codet & code()
the statement to be executed when the case applies
Definition std_code.h:1131
codet representation of a goto statement.
Definition std_code.h:841
const irep_idt & get_destination() const
Definition std_code.h:853
codet representation of an if-then-else statement.
Definition std_code.h:460
const exprt & cond() const
Definition std_code.h:478
const codet & else_case() const
Definition std_code.h:498
const codet & then_case() const
Definition std_code.h:488
codet representation of a label for branch targets.
Definition std_code.h:959
const irep_idt & get_label() const
Definition std_code.h:967
codet & code()
Definition std_code.h:977
A codet representing a skip statement.
Definition std_code.h:322
codet representation of a switch-case, i.e. a case statement within a switch.
Definition std_code.h:1023
const exprt & case_op() const
Definition std_code.h:1040
bool is_default() const
Definition std_code.h:1030
codet representing a switch statement.
Definition std_code.h:548
codet representing a while statement.
Definition std_code.h:610
const exprt & cond() const
Definition std_code.h:617
const codet & body() const
Definition std_code.h:627
Data structure for representing an arbitrary statement in a program.
exprt & op3()
Definition expr.h:143
exprt & op0()
Definition expr.h:134
exprt & op1()
Definition expr.h:137
exprt & op2()
Definition expr.h:140
const irep_idt & get_statement() const
struct configt::ansi_ct ansi_c
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition dstring.h:38
The empty type.
Definition std_types.h:50
Base class for all expressions.
Definition expr.h:57
const source_locationt & find_source_location() const
Get a source_locationt from the expression or from its operands (non-recursively).
Definition expr.cpp:68
std::vector< exprt > operandst
Definition expr.h:59
typet & type()
Return the type of the expression.
Definition expr.h:85
operandst & operands()
Definition expr.h:95
const source_locationt & source_location() const
Definition expr.h:236
source_locationt & add_source_location()
Definition expr.h:241
Thrown when we can't handle something in an input source file.
bool get_bool(const irep_idt &name) const
Definition irep.cpp:57
std::string pretty(unsigned indent=0, unsigned max_indent=0) const
Definition irep.cpp:482
const irept & find(const irep_idt &name) const
Definition irep.cpp:93
bool is_not_nil() const
Definition irep.h:372
void make_nil()
Definition irep.h:446
void swap(irept &irep)
Definition irep.h:434
const irep_idt & id() const
Definition irep.h:388
irept & add(const irep_idt &name)
Definition irep.cpp:103
bool is_nil() const
Definition irep.h:368
source_locationt source_location
Definition message.h:239
static const commandt quote_begin
Start quoted text.
Definition message.h:389
mstreamt & error() const
Definition message.h:401
mstreamt & warning() const
Definition message.h:406
static const commandt quote_end
End quoted text.
Definition message.h:393
static eomt eom
Definition message.h:289
const union_typet & follow_tag(const union_tag_typet &) const
Follow type tag of union type.
Definition namespace.cpp:49
A side_effect_exprt that returns a non-deterministically chosen value.
Definition std_code.h:1520
const symbolst & symbols
Read-only field, used to look up symbols given their names.
Symbol table entry.
Definition symbol.h:28
bool is_extern
Definition symbol.h:74
bool is_static_lifetime
Definition symbol.h:70
bool is_type
Definition symbol.h:61
source_locationt location
Source code location of definition of symbol.
Definition symbol.h:37
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
exprt value
Initial value of symbol.
Definition symbol.h:34
The Boolean constant true.
Definition std_expr.h:3126
Semantic type conversion.
Definition std_expr.h:1995
The type of an expression, extends irept.
Definition type.h:29
Generic base class for unary expressions.
Definition std_expr.h:364
const exprt & op() const
Definition std_expr.h:394
#define CPROVER_PREFIX
bool has_subexpr(const exprt &expr, const std::function< bool(const exprt &)> &pred)
returns true if the expression has a subexpression that satisfies pred
Deprecated expression utility functions.
const std::string & id2string(const irep_idt &d)
Definition irep.h:44
Ranges: pair of begin and end iterators, which can be initialized from containers,...
#define PRECONDITION(CONDITION)
Definition invariant.h:463
const code_switch_caset & to_code_switch_case(const codet &code)
Definition std_code.h:1077
const code_gotot & to_code_goto(const codet &code)
Definition std_code.h:875
code_asm_gcct & to_code_asm_gcc(codet &code)
Definition std_code.h:1373
const code_frontend_returnt & to_code_frontend_return(const codet &code)
Definition std_code.h:943
side_effect_expr_function_callt & to_side_effect_expr_function_call(exprt &expr)
Definition std_code.h:1739
const code_dowhilet & to_code_dowhile(const codet &code)
Definition std_code.h:716
const code_whilet & to_code_while(const codet &code)
Definition std_code.h:654
const code_labelt & to_code_label(const codet &code)
Definition std_code.h:1004
bool can_cast_expr< side_effect_expr_function_callt >(const exprt &base)
Definition std_code.h:1730
const code_blockt & to_code_block(const codet &code)
Definition std_code.h:203
const code_ifthenelset & to_code_ifthenelse(const codet &code)
Definition std_code.h:530
const code_gcc_switch_case_ranget & to_code_gcc_switch_case_range(const codet &code)
Definition std_code.h:1161
bool can_cast_expr< side_effect_exprt >(const exprt &base)
Definition std_code.h:1498
code_asmt & to_code_asm(codet &code)
Definition std_code.h:1282
const code_switcht & to_code_switch(const codet &code)
Definition std_code.h:592
const codet & to_code(const exprt &expr)
const unary_exprt & to_unary_expr(const exprt &expr)
Cast an exprt to a unary_exprt.
Definition std_expr.h:424
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition std_expr.h:221
const vector_typet & to_vector_type(const typet &type)
Cast a typet to a vector_typet.
Definition std_types.h:1006
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition std_types.h:887
const struct_union_typet & to_struct_union_type(const typet &type)
Cast a typet to a struct_union_typet.
Definition std_types.h:213
const string_constantt & to_string_constant(const exprt &expr)
Author: Diffblue Ltd.