CBMC
statement_list_typecheck.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Statement List Language Type Checking
4 
5 Author: Matthias Weiss, matthias.weiss@diffblue.com
6 
7 \*******************************************************************/
8 
11 
13 
14 #include <util/cprover_prefix.h>
15 #include <util/message.h>
16 #include <util/namespace.h>
17 #include <util/pointer_expr.h>
18 #include <util/simplify_expr.h>
19 #include <util/std_code.h>
20 #include <util/symbol_table_base.h>
21 
23 
25 
27 #define STATEMENT_LIST_PTR_WIDTH 64
28 // TODO: Replace with more specific exception throws.
29 #define TYPECHECK_ERROR 0
31 #define DATA_BLOCK_PARAMETER_NAME "data_block"
33 #define DATA_BLOCK_TYPE_POSTFIX "_db"
35 #define CPROVER_ASSERT CPROVER_PREFIX "assert"
37 #define CPROVER_ASSUME CPROVER_PREFIX "assume"
39 #define CPROVER_TEMP_RLO CPROVER_PREFIX "temp_rlo"
40 
41 static const std::vector<irep_idt> logic_sequence_initializers = {
42  ID_statement_list_and,
43  ID_statement_list_and_not,
44  ID_statement_list_or,
45  ID_statement_list_or_not,
46  ID_statement_list_xor,
47  ID_statement_list_xor_not,
48  ID_statement_list_and_nested,
49  ID_statement_list_and_not_nested,
50  ID_statement_list_or_nested,
51  ID_statement_list_or_not_nested,
52  ID_statement_list_xor_nested,
53  ID_statement_list_xor_not_nested,
54 };
55 
56 static const std::vector<irep_idt> logic_sequence_terminators = {
57  ID_statement_list_set_rlo,
58  ID_statement_list_clr_rlo,
59  ID_statement_list_set,
60  ID_statement_list_reset,
61  ID_statement_list_assign,
62 };
63 
71  const struct_typet &data_block_type,
72  const irep_idt &function_block_name)
73 {
74  const pointer_typet db_ptr{data_block_type, STATEMENT_LIST_PTR_WIDTH};
75  code_typet::parametert param{db_ptr};
76  param.set_identifier(
77  id2string(function_block_name) + "::" + DATA_BLOCK_PARAMETER_NAME);
78  param.set_base_name(DATA_BLOCK_PARAMETER_NAME);
79  return param;
80 }
81 
83  const statement_list_parse_treet &parse_tree,
84  symbol_table_baset &symbol_table,
85  const std::string &module,
86  message_handlert &message_handler)
87 {
88  statement_list_typecheckt stl_typecheck(
89  parse_tree, symbol_table, module, message_handler);
90 
91  return stl_typecheck.typecheck_main();
92 }
93 
95  exprt rlo_bit,
96  bool or_bit,
97  codet function_code)
98  : rlo_bit(rlo_bit), or_bit(or_bit), function_code(function_code)
99 {
100 }
101 
103  size_t nesting_depth,
104  bool jumps_permitted,
105  bool fc_false_required)
106  : nesting_depth(nesting_depth),
107  jumps_permitted(jumps_permitted),
108  fc_false_required(fc_false_required)
109 {
110 }
112  size_t nesting_depth,
113  bool sets_fc_false)
114  : nesting_depth(nesting_depth), sets_fc_false(sets_fc_false)
115 {
116 }
117 
121  const std::string &module,
126  module(module)
127 {
128 }
129 
131 {
132  // First fill the symbol table with function, tag and parameter declarations
133  // to be able to properly resolve block calls later.
140  // Temporary RLO symbol for certain operations.
141  add_temp_rlo();
142 
143  // Iterate through all networks to generate the function bodies.
146  {
149  }
151  {
152  symbolt &function_sym{symbol_table.get_writeable_ref(fc.name)};
153  typecheck_statement_list_networks(fc, function_sym);
154  }
155 }
156 
158  const statement_list_parse_treet::function_blockt &function_block)
159 {
160  // Create FB symbol.
161  symbolt function_block_sym{function_block.name, typet{}, ID_statement_list};
162  function_block_sym.module = module;
163  function_block_sym.base_name = function_block_sym.name;
164  function_block_sym.pretty_name = function_block_sym.name;
165 
166  // When calling function blocks, the passed parameters are value-copied to a
167  // corresponding instance data block. This block contains all input, inout,
168  // output and static variables. The function block reads and writes only
169  // those fields and does not modify the actual parameters. To simulate this
170  // behaviour, all function blocks are modeled as functions with a single
171  // parameter: An instance of their data block, whose members they modify.
172 
173  // Create and add DB type symbol.
174  const struct_typet data_block_type{
175  create_instance_data_block_type(function_block)};
176  type_symbolt data_block{
177  id2string(function_block_sym.name) + DATA_BLOCK_TYPE_POSTFIX,
178  data_block_type,
179  ID_statement_list};
180  data_block.base_name = data_block.name;
181  symbol_table.add(data_block);
182 
183  // Create and add parameter symbol.
185  create_data_block_parameter(data_block_type, function_block_sym.name)};
186  parameter_symbolt param_sym;
187  param_sym.module = module;
188  param_sym.type = param.type();
189  param_sym.name = param.get_identifier();
191  param_sym.pretty_name = param_sym.base_name;
192  param_sym.mode = ID_statement_list;
193  symbol_table.add(param_sym);
194 
195  // Setup FB symbol type and value.
197  params.push_back(param);
198  code_typet fb_type{params, empty_typet()};
199  fb_type.set(ID_statement_list_type, ID_statement_list_function_block);
200  function_block_sym.type = fb_type;
201  symbol_table.add(function_block_sym);
202 }
203 
206 {
207  symbolt function_sym{function.name, typet{}, ID_statement_list};
208  function_sym.module = module;
209  function_sym.base_name = function_sym.name;
210  function_sym.pretty_name = function_sym.name;
213  function.var_input, params, function.name, ID_statement_list_var_input);
215  function.var_inout, params, function.name, ID_statement_list_var_inout);
217  function.var_output, params, function.name, ID_statement_list_var_output);
218 
219  code_typet fc_type{params, function.return_type};
220  fc_type.set(ID_statement_list_type, ID_statement_list_function);
221  function_sym.type = fc_type;
222  symbol_table.add(function_sym);
223 }
224 
226 {
227  for(const symbol_exprt &tag : parse_tree.tags)
228  {
229  symbolt tag_sym{tag.get_identifier(), tag.type(), ID_statement_list};
230  tag_sym.is_static_lifetime = true;
231  tag_sym.module = module;
232  tag_sym.base_name = tag_sym.name;
233  tag_sym.pretty_name = tag_sym.name;
234  symbol_table.add(tag_sym);
235  }
236 }
237 
239 {
240  symbolt temp_rlo{CPROVER_TEMP_RLO, get_bool_type(), ID_statement_list};
241  temp_rlo.is_static_lifetime = true;
242  temp_rlo.module = module;
243  temp_rlo.base_name = temp_rlo.name;
244  temp_rlo.pretty_name = temp_rlo.name;
245  symbol_table.add(temp_rlo);
246 }
247 
249  const statement_list_parse_treet::function_blockt &function_block)
250 {
253  function_block.var_input, components, ID_statement_list_var_input);
255  function_block.var_inout, components, ID_statement_list_var_inout);
257  function_block.var_output, components, ID_statement_list_var_output);
259  function_block.var_static, components, ID_statement_list_var_static);
260 
261  return struct_typet{components};
262 }
263 
267  const irep_idt &var_property)
268 {
269  for(const statement_list_parse_treet::var_declarationt &declaration :
270  var_decls)
271  {
272  const irep_idt &var_name{declaration.variable.get_identifier()};
273  const typet &var_type{declaration.variable.type()};
274  struct_union_typet::componentt component{var_name, var_type};
275  component.set(ID_statement_list_type, var_property);
276  components.push_back(component);
277  }
278 }
279 
282  code_typet::parameterst &params,
283  const irep_idt &function_name,
284  const irep_idt &var_property)
285 {
286  for(const statement_list_parse_treet::var_declarationt &declaration :
287  var_decls)
288  {
289  parameter_symbolt param_sym;
290  param_sym.module = module;
291  param_sym.type = declaration.variable.type();
292  param_sym.name = id2string(function_name) +
293  "::" + id2string(declaration.variable.get_identifier());
294  param_sym.base_name = declaration.variable.get_identifier();
295  param_sym.pretty_name = param_sym.base_name;
296  param_sym.mode = ID_statement_list;
297  symbol_table.add(param_sym);
298 
299  code_typet::parametert param{declaration.variable.type()};
300  param.set_identifier(param_sym.name);
301  param.set_base_name(declaration.variable.get_identifier());
302  param.set(ID_statement_list_type, var_property);
303  params.push_back(param);
304  }
305 }
306 
308  const statement_list_parse_treet::tia_modulet &tia_module,
309  symbolt &tia_symbol)
310 {
311  for(const statement_list_parse_treet::var_declarationt &declaration :
312  tia_module.var_temp)
313  {
314  symbolt temp_sym{
315  id2string(tia_symbol.name) +
316  "::" + id2string(declaration.variable.get_identifier()),
317  declaration.variable.type(),
318  ID_statement_list};
319  temp_sym.base_name = declaration.variable.get_identifier();
320  temp_sym.pretty_name = temp_sym.base_name;
321  temp_sym.module = module;
322  symbol_table.add(temp_sym);
323 
324  const code_declt code_decl{temp_sym.symbol_expr()};
325  tia_symbol.value.add_to_operands(code_decl);
326  }
327 }
328 
330  const statement_list_parse_treet::tia_modulet &tia_module,
331  symbolt &tia_symbol)
332 {
333  // Leave value empty if there are no networks to iterate through.
334  if(tia_module.networks.empty())
335  return;
336  if(tia_symbol.value.is_nil())
337  tia_symbol.value = code_blockt{};
338 
340  typecheck_temp_var_decls(tia_module, tia_symbol);
341 
342  for(const auto &network : tia_module.networks)
343  {
345  for(const auto &instruction : network.instructions)
346  typecheck_statement_list_instruction(instruction, tia_symbol);
347  }
349 }
350 
352 {
353  if(!label_references.empty())
354  {
355  error() << "Unable to find the labels:";
356  for(auto pair : label_references)
357  {
358  error() << "\n";
359  error() << id2string(pair.first);
360  }
361  error() << eom;
362  throw TYPECHECK_ERROR;
363  }
364 }
365 
367  const statement_list_parse_treet::instructiont &instruction,
368  symbolt &tia_element)
369 {
370  const codet &op_code{instruction.tokens.back()};
371  typecheck_code(op_code, tia_element);
372 }
373 
375  const codet &instruction,
376  symbolt &tia_element)
377 {
378  const irep_idt statement{instruction.get_statement()};
379 
380  if(ID_label == statement)
381  typecheck_label(instruction, tia_element);
382  else if(ID_statement_list_load == statement)
383  typecheck_statement_list_load(instruction, tia_element);
384  else if(ID_statement_list_transfer == statement)
385  typecheck_statement_list_transfer(instruction, tia_element);
386  else if(ID_statement_list_accu_int_add == statement)
388  else if(ID_statement_list_accu_int_sub == statement)
390  else if(ID_statement_list_accu_int_mul == statement)
392  else if(ID_statement_list_accu_int_div == statement)
394  else if(ID_statement_list_accu_int_eq == statement)
396  else if(ID_statement_list_accu_int_neq == statement)
398  else if(ID_statement_list_accu_int_lt == statement)
400  else if(ID_statement_list_accu_int_gt == statement)
402  else if(ID_statement_list_accu_int_lte == statement)
404  else if(ID_statement_list_accu_int_gte == statement)
406  else if(ID_statement_list_accu_dint_add == statement)
408  else if(ID_statement_list_accu_dint_sub == statement)
410  else if(ID_statement_list_accu_dint_mul == statement)
412  else if(ID_statement_list_accu_dint_div == statement)
414  else if(ID_statement_list_accu_dint_eq == statement)
416  else if(ID_statement_list_accu_dint_neq == statement)
418  else if(ID_statement_list_accu_dint_lt == statement)
420  else if(ID_statement_list_accu_dint_gt == statement)
422  else if(ID_statement_list_accu_dint_lte == statement)
424  else if(ID_statement_list_accu_dint_gte == statement)
426  else if(ID_statement_list_accu_real_add == statement)
428  else if(ID_statement_list_accu_real_sub == statement)
430  else if(ID_statement_list_accu_real_mul == statement)
432  else if(ID_statement_list_accu_real_div == statement)
434  else if(ID_statement_list_accu_real_eq == statement)
436  else if(ID_statement_list_accu_real_neq == statement)
438  else if(ID_statement_list_accu_real_lt == statement)
440  else if(ID_statement_list_accu_real_gt == statement)
442  else if(ID_statement_list_accu_real_lte == statement)
444  else if(ID_statement_list_accu_real_gte == statement)
446  else if(ID_statement_list_not == statement)
447  typecheck_statement_list_not(instruction);
448  else if(ID_statement_list_and == statement)
449  typecheck_statement_list_and(instruction, tia_element);
450  else if(ID_statement_list_and_not == statement)
451  typecheck_statement_list_and_not(instruction, tia_element);
452  else if(ID_statement_list_or == statement)
453  typecheck_statement_list_or(instruction, tia_element);
454  else if(ID_statement_list_or_not == statement)
455  typecheck_statement_list_or_not(instruction, tia_element);
456  else if(ID_statement_list_xor == statement)
457  typecheck_statement_list_xor(instruction, tia_element);
458  else if(ID_statement_list_xor_not == statement)
459  typecheck_statement_list_xor_not(instruction, tia_element);
460  else if(ID_statement_list_and_nested == statement)
462  else if(ID_statement_list_and_not_nested == statement)
464  else if(ID_statement_list_or_nested == statement)
466  else if(ID_statement_list_or_not_nested == statement)
468  else if(ID_statement_list_xor_nested == statement)
470  else if(ID_statement_list_xor_not_nested == statement)
472  else if(ID_statement_list_nesting_closed == statement)
474  else if(ID_statement_list_assign == statement)
475  typecheck_statement_list_assign(instruction, tia_element);
476  else if(ID_statement_list_set_rlo == statement)
478  else if(ID_statement_list_clr_rlo == statement)
480  else if(ID_statement_list_set == statement)
481  typecheck_statement_list_set(instruction, tia_element);
482  else if(ID_statement_list_reset == statement)
483  typecheck_statement_list_reset(instruction, tia_element);
484  else if(ID_statement_list_jump_unconditional == statement)
485  typecheck_statement_list_jump_unconditional(instruction, tia_element);
486  else if(ID_statement_list_jump_conditional == statement)
487  typecheck_statement_list_jump_conditional(instruction, tia_element);
488  else if(ID_statement_list_jump_conditional_not == statement)
489  typecheck_statement_list_jump_conditional_not(instruction, tia_element);
490  else if(ID_statement_list_nop == statement)
491  return;
492  else if(ID_statement_list_call == statement)
493  typecheck_statement_list_call(instruction, tia_element);
494  else
495  {
496  error() << "OP code of instruction not found: "
497  << instruction.get_statement() << eom;
498  throw TYPECHECK_ERROR;
499  }
500 }
501 
503  const codet &instruction,
504  symbolt &tia_element)
505 {
506  const code_labelt &label = to_code_label(instruction);
507 
508  // Check if label is duplicate (not allowed in STL).
509  if(stl_labels.find(label.get_label()) != end(stl_labels))
510  {
511  error() << "Multiple definitions of label " << id2string(label.get_label())
512  << eom;
513  throw TYPECHECK_ERROR;
514  }
515 
516  // Determine the properties of this location in the code.
518 
519  // Store the implicit RLO in order to correctly separate the different
520  // blocks of logic.
521  if(location.jumps_permitted)
522  save_rlo_state(tia_element);
523 
524  // Now check if there are any jumps that referenced that label before and
525  // validate these.
526  typecheck_jump_locations(label, location);
527 
528  // Only add the label to the code if jumps are permitted. Proceed as normal
529  // if they are not. An added label will always point at an empty code
530  // location due to the way how the typecheck works.
531  if(location.jumps_permitted)
532  tia_element.value.add_to_operands(
533  code_labelt{label.get_label(), code_skipt{}});
534 
535  // Recursive call to check the label target.
536  typecheck_code(label.code(), tia_element);
537 }
538 
541 {
542  // Jumps to a label are only allowed if one of the following conditions
543  // applies:
544  //
545  // a) The /FC bit is false when encountering the instruction (pointing at the
546  // beginning of a logic sequence or no sequence at all).
547  // b) The /FC bit is set to false after processing the instruction (pointing
548  // at the termination of a logic sequence). This excludes nesting-open
549  // operations since although they terminate the current sequence, it will
550  // be resumed later.
551  //
552  // Labels at locations where this does not hold true compile, but actual
553  // jumps to them do not.
554  //
555  // Additionally, jumps to instructions that mark the beginning of a logic
556  // sequence are only allowed if the jump instruction itself sets the /FC bit
557  // to false.
558 
559  bool jumps_permitted = false;
560  bool fc_false_required = false;
561  if(!fc_bit)
562  {
563  jumps_permitted = true;
564  // Check if label points to new logic sequence.
565  for(const irep_idt &op_code : logic_sequence_initializers)
566  if(op_code == label.code().get_statement())
567  {
568  fc_false_required = true;
569  break;
570  }
571  }
572  else // Check if the label's instruction terminates the logic sequence.
573  {
574  for(const irep_idt &op_code : logic_sequence_terminators)
575  if(op_code == label.code().get_statement())
576  {
577  jumps_permitted = true;
578  break;
579  }
580  }
581 
582  // Add the label to map.
583  stl_label_locationt location{
584  nesting_stack.size(), jumps_permitted, fc_false_required};
585  stl_labels.emplace(label.get_label(), location);
586  return location;
587 }
588 
590  const code_labelt &label,
592 {
593  // Now check if there are any jumps that referenced that label before and
594  // validate these.
595  auto reference_it = label_references.find(label.get_label());
596  if(reference_it != end(label_references))
597  {
598  if(!location.jumps_permitted)
599  {
600  error() << "Not allowed to jump to label " << id2string(label.get_label())
601  << eom;
602  throw TYPECHECK_ERROR;
603  }
604  for(auto jump_location_it = begin(reference_it->second);
605  jump_location_it != end(reference_it->second);
606  ++jump_location_it)
607  {
608  if(location.fc_false_required && !jump_location_it->sets_fc_false)
609  {
610  error() << "Jump to label " << id2string(label.get_label())
611  << " can not be unconditional" << eom;
612  throw TYPECHECK_ERROR;
613  }
614  if(nesting_stack.size() != jump_location_it->nesting_depth)
615  {
616  error() << "Jump to label " << id2string(label.get_label())
617  << " violates brace scope" << eom;
618  throw TYPECHECK_ERROR;
619  }
620  }
621  // Remove entry after validation.
622  label_references.erase(label.get_label());
623  }
624 }
625 
627  const codet &op_code,
628  const symbolt &tia_element)
629 {
630  const symbol_exprt *const symbol =
631  expr_try_dynamic_cast<symbol_exprt>(op_code.op0());
632  if(symbol)
633  {
634  const irep_idt &identifier{symbol->get_identifier()};
635  const exprt val{typecheck_identifier(tia_element, identifier)};
636  accumulator.push_back(val);
637  }
638  else if(can_cast_expr<constant_exprt>(op_code.op0()))
639  accumulator.push_back(op_code.op0());
640  else
641  {
642  error() << "Instruction is not followed by symbol or constant" << eom;
643  throw TYPECHECK_ERROR;
644  }
645 }
646 
648  const codet &op_code,
649  symbolt &tia_element)
650 {
652  const exprt lhs{typecheck_identifier(tia_element, op.get_identifier())};
653  if(lhs.type() != accumulator.back().type())
654  {
655  error() << "Types of transfer assignment do not match" << eom;
656  throw TYPECHECK_ERROR;
657  }
658  const code_assignt assignment{lhs, accumulator.back()};
659  tia_element.value.add_to_operands(assignment);
660 }
661 
663  const codet &op_code)
664 {
666 
667  // Pop first operand, peek second.
668  const exprt accu1{accumulator.back()};
669  accumulator.pop_back();
670  const exprt &accu2{accumulator.back()};
671  const plus_exprt operation{accu2, accu1};
672  accumulator.push_back(operation);
673 }
674 
676  const codet &op_code)
677 {
679 
680  // Pop first operand, peek second.
681  const exprt accu1{accumulator.back()};
682  accumulator.pop_back();
683  const exprt &accu2{accumulator.back()};
684  const minus_exprt operation{accu2, accu1};
685  accumulator.push_back(operation);
686 }
687 
689  const codet &op_code)
690 {
692 
693  // Pop first operand, peek second.
694  const exprt accu1{accumulator.back()};
695  accumulator.pop_back();
696  const exprt &accu2{accumulator.back()};
697  const mult_exprt operation{accu2, accu1};
698  accumulator.push_back(operation);
699 }
700 
702  const codet &op_code)
703 {
705 
706  // Pop first operand, peek second.
707  const exprt accu1{accumulator.back()};
708  accumulator.pop_back();
709  const exprt &accu2{accumulator.back()};
710  const div_exprt operation{accu2, accu1};
711  accumulator.push_back(operation);
712 }
713 
715  const codet &op_code)
716 {
719 }
720 
722  const codet &op_code)
723 {
726 }
727 
729  const codet &op_code)
730 {
733 }
734 
736  const codet &op_code)
737 {
740 }
741 
743  const codet &op_code)
744 {
747 }
748 
750  const codet &op_code)
751 {
754 }
755 
757  const codet &op_code)
758 {
760 
761  // Pop first operand, peek second.
762  const exprt accu1{accumulator.back()};
763  accumulator.pop_back();
764  const exprt &accu2{accumulator.back()};
765  const plus_exprt operation{accu2, accu1};
766  accumulator.push_back(operation);
767 }
768 
770  const codet &op_code)
771 {
773 
774  // Pop first operand, peek second.
775  const exprt accu1{accumulator.back()};
776  accumulator.pop_back();
777  const exprt &accu2{accumulator.back()};
778  const minus_exprt operation{accu2, accu1};
779  accumulator.push_back(operation);
780 }
781 
783  const codet &op_code)
784 {
786 
787  // Pop first operand, peek second.
788  const exprt accu1{accumulator.back()};
789  accumulator.pop_back();
790  const exprt &accu2{accumulator.back()};
791  const mult_exprt operation{accu2, accu1};
792  accumulator.push_back(operation);
793 }
794 
796  const codet &op_code)
797 {
799 
800  // Pop first operand, peek second.
801  const exprt accu1{accumulator.back()};
802  accumulator.pop_back();
803  const exprt &accu2{accumulator.back()};
804  const div_exprt operation{accu2, accu1};
805  accumulator.push_back(operation);
806 }
807 
809  const codet &op_code)
810 {
813 }
814 
816  const codet &op_code)
817 {
820 }
821 
823  const codet &op_code)
824 {
827 }
828 
830  const codet &op_code)
831 {
834 }
835 
837  const codet &op_code)
838 {
841 }
842 
844  const codet &op_code)
845 {
848 }
849 
851  const codet &op_code)
852 {
854 
855  // Pop first operand, peek second.
856  const exprt accu1{accumulator.back()};
857  accumulator.pop_back();
858  const exprt &accu2{accumulator.back()};
859  const plus_exprt operation{accu2, accu1};
860  accumulator.push_back(operation);
861 }
862 
864  const codet &op_code)
865 {
867 
868  // Pop first operand, peek second.
869  const exprt accu1{accumulator.back()};
870  accumulator.pop_back();
871  const exprt &accu2{accumulator.back()};
872  const minus_exprt operation{accu2, accu1};
873  accumulator.push_back(operation);
874 }
875 
877  const codet &op_code)
878 {
880 
881  // Pop first operand, peek second.
882  const exprt accu1{accumulator.back()};
883  accumulator.pop_back();
884  const exprt &accu2{accumulator.back()};
885  const mult_exprt operation{accu2, accu1};
886  accumulator.push_back(operation);
887 }
888 
890  const codet &op_code)
891 {
893 
894  // Pop first operand, peek second.
895  const exprt accu1{accumulator.back()};
896  accumulator.pop_back();
897  const exprt &accu2{accumulator.back()};
898  const div_exprt operation{accu2, accu1};
899  accumulator.push_back(operation);
900 }
901 
903  const codet &op_code)
904 {
907 }
908 
910  const codet &op_code)
911 {
914 }
915 
917  const codet &op_code)
918 {
921 }
922 
924  const codet &op_code)
925 {
928 }
929 
931  const codet &op_code)
932 {
935 }
936 
938  const codet &op_code)
939 {
942 }
943 
945  const codet &op_code)
946 {
948  const not_exprt unsimplified{rlo_bit};
949  rlo_bit = simplify_expr(unsimplified, namespacet(symbol_table));
950 }
951 
953  const codet &op_code,
954  const symbolt &tia_element)
955 {
956  exprt op{
957  typecheck_simple_boolean_instruction_operand(op_code, tia_element, false)};
958 
959  // If inside of a bit string and if the OR bit is not set, create an 'and'
960  // expression with the operand and the current contents of the rlo bit. If
961  // the OR bit is set then this instruction is part of an 'and-before-or'
962  // block and needs to be added to the rlo in a special way.
963  if(fc_bit && or_bit)
965  else if(fc_bit)
966  {
967  const and_exprt unsimplified{rlo_bit, op};
968  rlo_bit = simplify_expr(unsimplified, namespacet(symbol_table));
969  }
970  else
972 }
973 
975  const codet &op_code,
976  const symbolt &tia_element)
977 {
978  exprt op{
979  typecheck_simple_boolean_instruction_operand(op_code, tia_element, true)};
980 
981  // If inside of a bit string and if the OR bit is not set, create an 'and'
982  // expression with the operand and the current contents of the rlo bit. If
983  // the OR bit is set then this instruction is part of an 'and-before-or'
984  // block and needs to be added to the rlo in a special way.
985  if(or_bit && fc_bit)
987  else if(fc_bit)
988  {
989  const and_exprt unsimplified{rlo_bit, op};
990  rlo_bit = simplify_expr(unsimplified, namespacet(symbol_table));
991  }
992  else
994 }
995 
997  const codet &op_code,
998  const symbolt &tia_element)
999 {
1000  if(op_code.operands().empty())
1001  {
1003  return;
1004  }
1005  const symbol_exprt &sym{
1007  const exprt op{typecheck_identifier(tia_element, sym.get_identifier())};
1008 
1009  // If inside of a bit string, create an 'or' expression with the operand and
1010  // the current contents of the rlo bit.
1011  if(fc_bit)
1012  {
1013  const or_exprt unsimplified{rlo_bit, op};
1014  rlo_bit = simplify_expr(unsimplified, namespacet(symbol_table));
1015  or_bit = false;
1016  }
1017  else
1019 }
1020 
1022  const codet &op_code,
1023  const symbolt &tia_element)
1024 {
1025  const symbol_exprt &sym{
1027  const exprt op{typecheck_identifier(tia_element, sym.get_identifier())};
1028  const not_exprt not_op{op};
1029 
1030  // If inside of a bit string, create an 'or' expression with the operand and
1031  // the current contents of the rlo bit.
1032  if(fc_bit)
1033  {
1034  const or_exprt unsimplified{rlo_bit, not_op};
1035  rlo_bit = simplify_expr(unsimplified, namespacet(symbol_table));
1036  or_bit = false;
1037  }
1038  else
1039  initialize_bit_expression(not_op);
1040 }
1041 
1043  const codet &op_code,
1044  const symbolt &tia_element)
1045 {
1046  const symbol_exprt &sym{
1048  const exprt op{typecheck_identifier(tia_element, sym.get_identifier())};
1049 
1050  // If inside of a bit string, create an 'xor' expression with the operand and
1051  // the current contents of the rlo bit.
1052  if(fc_bit)
1053  {
1054  const xor_exprt unsimplified{rlo_bit, op};
1055  rlo_bit = simplify_expr(unsimplified, namespacet(symbol_table));
1056  or_bit = false;
1057  }
1058  else
1060 }
1061 
1063  const codet &op_code,
1064  const symbolt &tia_element)
1065 {
1066  const symbol_exprt &sym{
1068  const exprt op{typecheck_identifier(tia_element, sym.get_identifier())};
1069  const not_exprt not_op{op};
1070 
1071  // If inside of a bit string, create an 'xor not' expression with the
1072  // operand and the current contents of the rlo bit.
1073  if(fc_bit)
1074  {
1075  const xor_exprt unsimplified{rlo_bit, not_op};
1076  rlo_bit = simplify_expr(unsimplified, namespacet(symbol_table));
1077  or_bit = false;
1078  }
1079  else
1080  initialize_bit_expression(not_op);
1081 }
1082 
1084 {
1085  if(fc_bit)
1086  {
1088  or_bit = true;
1089  }
1090  else
1091  return; // Instruction has no semantic influence.
1092 }
1093 
1095  const codet &op_code)
1096 {
1097  // Set the rlo to true implicitly so that the value of the AND instruction
1098  // is being loaded in case of a new bit string.
1100 }
1101 
1103  const codet &op_code)
1104 {
1105  // Set the rlo to true implicitly so that the value of the AND instruction
1106  // is being loaded in case of a new bit string.
1108 }
1109 
1111  const codet &op_code)
1112 {
1113  // Set the rlo to false implicitly so that the value of the OR instruction
1114  // is being loaded in case of a new bit string.
1116 }
1117 
1119  const codet &op_code)
1120 {
1121  // Set the rlo to false implicitly so that the value of the OR instruction
1122  // is being loaded in case of a new bit string.
1124 }
1125 
1127  const codet &op_code)
1128 {
1129  // Set the rlo to false implicitly so that the value of the XOR instruction
1130  // is being loaded in case of a new bit string.
1132 }
1133 
1135  const codet &op_code)
1136 {
1137  // Set the rlo to false implicitly so that the value of the XOR instruction
1138  // is being loaded in case of a new bit string.
1140 }
1141 
1143  const codet &op_code)
1144 {
1146  if(nesting_stack.empty())
1147  {
1148  error() << "Wrong order of brackets (Right parenthesis is not preceded by "
1149  "nesting)"
1150  << eom;
1151  throw TYPECHECK_ERROR;
1152  }
1153  or_bit = nesting_stack.back().or_bit;
1154  fc_bit = true;
1155  const irep_idt &statement{nesting_stack.back().function_code.get_statement()};
1156  if(ID_statement_list_and_nested == statement)
1157  {
1158  if(or_bit)
1159  {
1160  const exprt op{rlo_bit};
1161  rlo_bit = nesting_stack.back().rlo_bit;
1163  }
1164  else
1165  rlo_bit = and_exprt{nesting_stack.back().rlo_bit, rlo_bit};
1166  }
1167  else if(ID_statement_list_and_not_nested == statement)
1168  {
1169  if(or_bit)
1170  {
1171  const not_exprt op{rlo_bit};
1172  rlo_bit = nesting_stack.back().rlo_bit;
1174  }
1175  else
1176  rlo_bit = and_exprt{nesting_stack.back().rlo_bit, not_exprt{rlo_bit}};
1177  }
1178  else if(ID_statement_list_or_nested == statement)
1179  {
1180  or_bit = false;
1181  rlo_bit = or_exprt{nesting_stack.back().rlo_bit, rlo_bit};
1182  }
1183  else if(ID_statement_list_or_not_nested == statement)
1184  {
1185  or_bit = false;
1186  rlo_bit = or_exprt{nesting_stack.back().rlo_bit, not_exprt{rlo_bit}};
1187  }
1188  else if(ID_statement_list_xor_nested == statement)
1189  {
1190  or_bit = false;
1191  rlo_bit = xor_exprt{nesting_stack.back().rlo_bit, rlo_bit};
1192  }
1193  else if(ID_statement_list_xor_not_nested == statement)
1194  {
1195  or_bit = false;
1196  rlo_bit = xor_exprt{nesting_stack.back().rlo_bit, not_exprt{rlo_bit}};
1197  }
1198  nesting_stack.pop_back();
1199 }
1200 
1202  const codet &op_code,
1203  symbolt &tia_element)
1204 {
1206  const exprt lhs{typecheck_identifier(tia_element, op.get_identifier())};
1207 
1208  if(lhs.type() != rlo_bit.type())
1209  {
1210  error() << "Types of assign do not match" << eom;
1211  throw TYPECHECK_ERROR;
1212  }
1213  const code_assignt assignment{lhs, rlo_bit};
1214  tia_element.value.add_to_operands(assignment);
1215  fc_bit = false;
1216  or_bit = false;
1217  // Set RLO to assigned operand in order to prevent false results if a symbol
1218  // that's implicitly part of the RLO was changed by the assignment.
1219  rlo_bit = lhs;
1220 }
1221 
1223  const codet &op_code)
1224 {
1226  fc_bit = false;
1227  or_bit = false;
1228  rlo_bit = true_exprt();
1229 }
1230 
1232  const codet &op_code)
1233 {
1235  fc_bit = false;
1236  or_bit = false;
1237  rlo_bit = false_exprt();
1238 }
1239 
1241  const codet &op_code,
1242  symbolt &tia_element)
1243 {
1245  const irep_idt &identifier{op.get_identifier()};
1246 
1247  save_rlo_state(tia_element);
1248 
1249  const exprt lhs{typecheck_identifier(tia_element, identifier)};
1250  const code_assignt assignment{lhs, true_exprt()};
1251  const code_ifthenelset ifthen{rlo_bit, assignment};
1252  tia_element.value.add_to_operands(ifthen);
1253  fc_bit = false;
1254  or_bit = false;
1255 }
1256 
1258  const codet &op_code,
1259  symbolt &tia_element)
1260 {
1262  const irep_idt &identifier{op.get_identifier()};
1263 
1264  save_rlo_state(tia_element);
1265 
1266  const exprt lhs{typecheck_identifier(tia_element, identifier)};
1267  const code_assignt assignment{lhs, false_exprt()};
1268  const code_ifthenelset ifthen{rlo_bit, assignment};
1269  tia_element.value.add_to_operands(ifthen);
1270  fc_bit = false;
1271  or_bit = false;
1272 }
1273 
1275  const codet &op_code,
1276  symbolt &tia_element)
1277 {
1279  const irep_idt &identifier{op.get_identifier()};
1280  if(symbol_table.has_symbol(identifier))
1281  typecheck_called_tia_element(op_code, tia_element);
1282  else if(identifier == CPROVER_ASSUME)
1283  typecheck_CPROVER_assume(op_code, tia_element);
1284  else if(identifier == CPROVER_ASSERT)
1285  typecheck_CPROVER_assert(op_code, tia_element);
1286  else
1287  {
1288  error() << "Called function could not be found" << eom;
1289  throw TYPECHECK_ERROR;
1290  }
1291  fc_bit = false;
1292  or_bit = false;
1293 }
1294 
1296  const codet &op_code,
1297  symbolt &tia_element)
1298 {
1299  const symbol_exprt &label{
1301  typecheck_label_reference(label.get_identifier(), false);
1302 
1303  save_rlo_state(tia_element);
1304  code_gotot unconditional{label.get_identifier()};
1305  tia_element.value.add_to_operands(unconditional);
1306 }
1307 
1309  const codet &op_code,
1310  symbolt &tia_element)
1311 {
1312  const symbol_exprt &label{
1314  typecheck_label_reference(label.get_identifier(), true);
1315 
1316  save_rlo_state(tia_element);
1317  code_gotot jump{label.get_identifier()};
1318  code_ifthenelset conditional{rlo_bit, jump};
1319  tia_element.value.add_to_operands(conditional);
1320 
1321  fc_bit = false;
1322  or_bit = false;
1323  rlo_bit = true_exprt{};
1324 }
1325 
1327  const codet &op_code,
1328  symbolt &tia_element)
1329 {
1330  const symbol_exprt &label{
1332  typecheck_label_reference(label.get_identifier(), true);
1333 
1334  save_rlo_state(tia_element);
1335  code_gotot jump{label.get_identifier()};
1336  code_ifthenelset not_conditional{not_exprt{rlo_bit}, jump};
1337  tia_element.value.add_to_operands(not_conditional);
1338 
1339  fc_bit = false;
1340  or_bit = false;
1341  rlo_bit = true_exprt{};
1342 }
1343 
1345  const codet &op_code)
1346 {
1348  const exprt &accu1{accumulator.back()};
1349  const exprt &accu2{accumulator.at(accumulator.size() - 2)};
1350 
1351  // Are both operands integers?
1352  const signedbv_typet *const accu_type1 =
1353  type_try_dynamic_cast<signedbv_typet>(accu1.type());
1354  const signedbv_typet *const accu_type2 =
1355  type_try_dynamic_cast<signedbv_typet>(accu2.type());
1356  if(
1357  !accu_type1 || !accu_type2 || accu_type1->get_width() != STL_INT_WIDTH ||
1358  accu_type2->get_width() != STL_INT_WIDTH)
1359  {
1360  error() << "Operands of integer addition are no integers" << eom;
1361  throw TYPECHECK_ERROR;
1362  }
1363 }
1364 
1366  const codet &op_code)
1367 {
1369  const exprt &accu1{accumulator.back()};
1370  const exprt &accu2{accumulator.at(accumulator.size() - 2)};
1371 
1372  // Are both operands double integers?
1373  const signedbv_typet *const accu_type1 =
1374  type_try_dynamic_cast<signedbv_typet>(accu1.type());
1375  const signedbv_typet *const accu_type2 =
1376  type_try_dynamic_cast<signedbv_typet>(accu2.type());
1377  if(
1378  !accu_type1 || !accu_type2 || accu_type1->get_width() != STL_DINT_WIDTH ||
1379  accu_type2->get_width() != STL_DINT_WIDTH)
1380  {
1381  error() << "Operands of double integer addition are no double integers"
1382  << eom;
1383  throw TYPECHECK_ERROR;
1384  }
1385 }
1386 
1388  const codet &op_code)
1389 {
1391  const exprt &accu1{accumulator.back()};
1392  const exprt &accu2{accumulator.at(accumulator.size() - 2)};
1393 
1394  // Are both operands real types?
1395  if(!(can_cast_type<floatbv_typet>(accu1.type()) &&
1396  can_cast_type<floatbv_typet>(accu2.type())))
1397  {
1398  error() << "Operands of Real addition do not have the type Real" << eom;
1399  throw TYPECHECK_ERROR;
1400  }
1401 }
1402 
1404  const irep_idt &comparison)
1405 {
1406  const exprt &accu1{accumulator.back()};
1407  const exprt &accu2{accumulator.at(accumulator.size() - 2)};
1408  // STL behaviour: ACCU2 is lhs, ACCU1 is rhs.
1409  const binary_relation_exprt operation{accu2, comparison, accu1};
1410  rlo_bit = operation;
1411 }
1412 
1414  const irep_idt &label,
1415  bool sets_fc_false)
1416 {
1417  // If the label is already present in the list, check if it matches the
1418  // criteria.
1419  auto label_it = stl_labels.find(label);
1420  if(label_it != end(stl_labels))
1421  {
1422  if(!label_it->second.jumps_permitted)
1423  {
1424  error() << "Not allowed to jump to label " << id2string(label_it->first)
1425  << eom;
1426  throw TYPECHECK_ERROR;
1427  }
1428 
1429  if(label_it->second.fc_false_required && !sets_fc_false)
1430  {
1431  error() << "Jump to label " << id2string(label_it->first)
1432  << " can not be unconditional" << eom;
1433  throw TYPECHECK_ERROR;
1434  }
1435 
1436  if(label_it->second.nesting_depth != nesting_stack.size())
1437  {
1438  error() << "Jump to label " << id2string(label_it->first)
1439  << " violates brace scope" << eom;
1440  throw TYPECHECK_ERROR;
1441  }
1442  }
1443  else // If it was not encountered yet, create a new reference entry.
1444  {
1445  stl_jump_locationt location{nesting_stack.size(), sets_fc_false};
1446  auto reference_it = label_references.find(label);
1447  if(reference_it == end(label_references))
1448  {
1449  std::vector<stl_jump_locationt> locations;
1450  locations.push_back(location);
1451  label_references.emplace(label, locations);
1452  }
1453  else
1454  reference_it->second.push_back(location);
1455  }
1456 }
1457 
1458 const symbol_exprt &
1460  const codet &op_code)
1461 {
1462  const symbol_exprt *const symbol =
1463  expr_try_dynamic_cast<symbol_exprt>(op_code.op0());
1464 
1465  if(symbol)
1466  return *symbol;
1467 
1468  error() << "Instruction is not followed by symbol" << eom;
1469  throw TYPECHECK_ERROR;
1470 }
1471 
1473  const codet &op_code)
1474 {
1475  if(op_code.operands().size() > 0)
1476  {
1477  error() << "Instruction is followed by operand" << eom;
1478  throw TYPECHECK_ERROR;
1479  }
1480 }
1481 
1483  const codet &op_code)
1484 {
1486  if(accumulator.size() < 2)
1487  {
1488  error() << "Not enough operands in the accumulator" << eom;
1489  throw TYPECHECK_ERROR;
1490  }
1491 }
1492 
1494  const codet &op_code,
1495  const exprt &rlo_value)
1496 {
1498  // If inside of a bit string use the value of the rlo. If this is the first
1499  // expression of a bit string, load the value of the nested operation by
1500  // implicitly setting the rlo to the specified value.
1501  if(!fc_bit)
1502  rlo_bit = rlo_value;
1503  const nesting_stack_entryt stack_entry{rlo_bit, or_bit, op_code};
1504  nesting_stack.push_back(stack_entry);
1505  fc_bit = false;
1506  or_bit = false;
1507 }
1508 
1510  const codet &op_code,
1511  const symbolt &tia_element,
1512  bool negate)
1513 {
1514  const symbol_exprt &sym{
1516  const exprt op{typecheck_identifier(tia_element, sym.get_identifier())};
1517  const not_exprt not_op{op};
1518  return negate ? not_op : op;
1519 }
1520 
1522  const symbolt &tia_element,
1523  const irep_idt &identifier)
1524 {
1525  const code_typet &element_type{to_code_type(tia_element.type)};
1526 
1527  // Check for temporary variables.
1529  id2string(tia_element.name) + "::" + id2string(identifier)))
1530  {
1531  const symbolt &sym{symbol_table.lookup_ref(
1532  id2string(tia_element.name) + "::" + id2string(identifier))};
1533  return sym.symbol_expr();
1534  }
1535 
1536  // Check for global tags.
1537  if(symbol_table.has_symbol(identifier))
1538  return symbol_table.lookup_ref(identifier).symbol_expr();
1539 
1540  if(
1541  element_type.get(ID_statement_list_type) ==
1542  ID_statement_list_function_block)
1543  {
1544  // Check for variables inside of the function block interface.
1545  const symbolt &data_block{symbol_table.get_writeable_ref(
1546  id2string(tia_element.name) + "::" + DATA_BLOCK_PARAMETER_NAME)};
1547  const symbol_exprt db_expr = data_block.symbol_expr();
1548  const struct_typet *const db_type = type_try_dynamic_cast<struct_typet>(
1549  to_type_with_subtype(db_expr.type()).subtype());
1550  if(!db_type)
1551  UNREACHABLE;
1552  for(const struct_union_typet::componentt &member : db_type->components())
1553  {
1554  if(member.get_name() == identifier)
1555  {
1556  const dereference_exprt deref_db{db_expr};
1557  const member_exprt val{deref_db, member.get_name(), member.type()};
1558  return val;
1559  }
1560  }
1561  }
1562  else if(
1563  element_type.get(ID_statement_list_type) == ID_statement_list_function)
1564  {
1565  // Check for variables inside of the function interface.
1566  for(const auto &member : element_type.parameters())
1567  {
1568  if(member.get_base_name() == identifier)
1569  {
1570  const symbolt &par{
1571  symbol_table.get_writeable_ref(member.get_identifier())};
1572  return par.symbol_expr();
1573  }
1574  }
1575  }
1576  else
1577  UNREACHABLE; // Variable declarations should only be checked for FCs or FBs
1578 
1579  error() << "Identifier could not be found in project" << eom;
1580  throw TYPECHECK_ERROR;
1581 }
1582 
1584  const codet &op_code,
1585  symbolt &tia_element)
1586 {
1587  if(
1588  const auto assignment =
1589  expr_try_dynamic_cast<code_frontend_assignt>(op_code.op1()))
1590  {
1591  const code_assertt assertion{
1592  typecheck_function_call_argument_rhs(tia_element, assignment->rhs())};
1593  tia_element.value.add_to_operands(assertion);
1594  }
1595  else
1596  {
1597  error() << "No assignment found for assertion" << eom;
1598  throw TYPECHECK_ERROR;
1599  }
1600 }
1601 
1603  const codet &op_code,
1604  symbolt &tia_element)
1605 {
1606  if(
1607  const auto assignment =
1608  expr_try_dynamic_cast<code_frontend_assignt>(op_code.op1()))
1609  {
1610  const code_assumet assumption{
1611  typecheck_function_call_argument_rhs(tia_element, assignment->rhs())};
1612  tia_element.value.add_to_operands(assumption);
1613  }
1614  else
1615  {
1616  error() << "No assignment found for assumption" << eom;
1617  throw TYPECHECK_ERROR;
1618  }
1619 }
1620 
1622  const codet &op_code,
1623  symbolt &tia_element)
1624 {
1625  const symbol_exprt &call_operand{to_symbol_expr(op_code.op0())};
1626  const symbolt &called_function{
1627  symbol_table.lookup_ref(call_operand.get_identifier())};
1628  const code_typet &called_type{to_code_type(called_function.type)};
1629  // Is it a STL function or STL function block?
1630  if(
1631  called_type.get(ID_statement_list_type) == ID_statement_list_function_block)
1632  typecheck_called_function_block(op_code, tia_element);
1633  else if(called_type.get(ID_statement_list_type) == ID_statement_list_function)
1634  typecheck_called_function(op_code, tia_element);
1635  else
1636  {
1637  error() << "Tried to call element that is no function or function block"
1638  << eom;
1639  throw TYPECHECK_ERROR;
1640  }
1641 }
1642 
1644  const codet &op_code,
1645  symbolt &tia_element)
1646 {
1647  const symbol_exprt call_operand{to_symbol_expr(op_code.op0())};
1648  const symbolt &called_function_sym{
1649  symbol_table.lookup_ref(call_operand.get_identifier())};
1650  const symbol_exprt called_function_expr{called_function_sym.symbol_expr()};
1651  const code_typet &called_type{to_code_type(called_function_sym.type)};
1652 
1653  // Check if function name is followed by data block.
1655  {
1656  error() << "Function calls should not address instance data blocks" << eom;
1657  throw TYPECHECK_ERROR;
1658  }
1659 
1660  // Check if function interface matches the call and fill argument list.
1661  const code_typet::parameterst &params{called_type.parameters()};
1663  std::vector<code_frontend_assignt> assignments;
1664  for(const auto &expr : op_code.operands())
1665  {
1666  if(auto assign = expr_try_dynamic_cast<code_frontend_assignt>(expr))
1667  assignments.push_back(*assign);
1668  }
1669 
1670  for(const code_typet::parametert &param : params)
1671  args.emplace_back(
1672  typecheck_function_call_arguments(assignments, param, tia_element));
1673 
1674  // Check the return value if present.
1675  if(called_type.return_type().is_nil())
1676  tia_element.value.add_to_operands(
1677  code_function_callt{called_function_expr, args});
1678  else
1679  {
1681  assignments, called_type.return_type(), tia_element)};
1682  tia_element.value.add_to_operands(
1683  code_function_callt{lhs, called_function_expr, args});
1684  }
1685 }
1686 
1688  const codet &op_code,
1689  symbolt &tia_element)
1690 {
1691  // TODO: Implement support for function block calls.
1692  // Needs code statements which assign the parameters to the instance data
1693  // block, call the function and write the result back to the parameters
1694  // afterwards.
1695  error() << "Calls to function blocks are not supported yet" << eom;
1696  throw TYPECHECK_ERROR;
1697 }
1698 
1700  const std::vector<code_frontend_assignt> &assignments,
1701  const code_typet::parametert &param,
1702  const symbolt &tia_element)
1703 {
1704  const irep_idt &param_name = param.get_base_name();
1705  const typet &param_type = param.type();
1706  for(const auto &assignment : assignments)
1707  {
1708  const symbol_exprt &lhs{to_symbol_expr(assignment.lhs())};
1709  if(param_name == lhs.get_identifier())
1710  {
1711  exprt assigned_variable{
1712  typecheck_function_call_argument_rhs(tia_element, assignment.rhs())};
1713 
1714  if(param_type == assigned_variable.type())
1715  return assigned_variable;
1716  else
1717  {
1718  error() << "Types of parameter assignment do not match: "
1719  << param.type().id() << " != " << assigned_variable.type().id()
1720  << eom;
1721  throw TYPECHECK_ERROR;
1722  }
1723  }
1724  }
1725  error() << "No assignment found for function parameter "
1726  << param.get_identifier() << eom;
1727  throw TYPECHECK_ERROR;
1728 }
1729 
1731  const symbolt &tia_element,
1732  const exprt &rhs)
1733 {
1734  exprt assigned_operand;
1735  const symbol_exprt *const symbol_rhs =
1736  expr_try_dynamic_cast<symbol_exprt>(rhs);
1737  if(symbol_rhs)
1738  assigned_operand =
1739  typecheck_identifier(tia_element, symbol_rhs->get_identifier());
1740  else // constant_exprt.
1741  assigned_operand = rhs;
1742  return assigned_operand;
1743 }
1744 
1746  const std::vector<code_frontend_assignt> &assignments,
1747  const typet &return_type,
1748  const symbolt &tia_element)
1749 {
1750  for(const auto &assignment : assignments)
1751  {
1752  const symbol_exprt &lhs{to_symbol_expr(assignment.lhs())};
1753  if(ID_statement_list_return_value_id == lhs.get_identifier())
1754  {
1755  const symbol_exprt &rhs{to_symbol_expr(assignment.rhs())};
1756  const exprt assigned_variable{
1757  typecheck_identifier(tia_element, rhs.get_identifier())};
1758  if(return_type == assigned_variable.type())
1759  return assigned_variable;
1760  else
1761  {
1762  error() << "Types of return value assignment do not match: "
1763  << return_type.id() << " != " << assigned_variable.type().id()
1764  << eom;
1765  throw TYPECHECK_ERROR;
1766  }
1767  }
1768  }
1769  error() << "No assignment found for function return value" << eom;
1770  throw TYPECHECK_ERROR;
1771 }
1772 
1774 {
1775  or_exprt or_wrapper{to_or_expr(rlo_bit)};
1776 
1777  if(can_cast_expr<constant_exprt>(or_wrapper.op1()))
1778  or_wrapper.op1();
1779  else if(can_cast_expr<and_exprt>(or_wrapper.op1()))
1780  {
1781  and_exprt &and_op{to_and_expr(or_wrapper.op1())};
1782  and_op.add_to_operands(op);
1783  or_wrapper.op1() = and_op;
1784  }
1785  else
1786  {
1787  and_exprt and_op{or_wrapper.op1(), op};
1788  or_wrapper.op1() = and_op;
1789  }
1790  rlo_bit = or_wrapper;
1791 }
1792 
1794 {
1795  fc_bit = true;
1796  or_bit = false;
1797  rlo_bit = op;
1798 }
1799 
1801 {
1802  rlo_bit = true_exprt{};
1803  fc_bit = false;
1804  or_bit = false;
1805  nesting_stack.clear();
1806 }
1807 
1809 {
1811  label_references.clear();
1812  stl_labels.clear();
1813 }
1814 
1816 {
1817  symbol_exprt temp_rlo{
1819  const code_assignt rlo_assignment{temp_rlo, rlo_bit};
1820  tia_element.value.add_to_operands(rlo_assignment);
1821  rlo_bit = std::move(temp_rlo);
1822 }
bool can_cast_type< floatbv_typet >(const typet &type)
Check whether a reference to a typet is a floatbv_typet.
Boolean AND.
Definition: std_expr.h:2125
A base class for relations, i.e., binary predicates whose two operands have the same type.
Definition: std_expr.h:762
std::size_t get_width() const
Definition: std_types.h:925
A non-fatal assertion, which checks a condition then permits execution to continue.
Definition: std_code.h:270
A goto_instruction_codet representing an assignment in the program.
An assumption, which must hold in subsequent code.
Definition: std_code.h:217
A codet representing sequential composition of program statements.
Definition: std_code.h:130
A goto_instruction_codet representing the declaration of a local variable.
goto_instruction_codet representation of a function call statement.
exprt::operandst argumentst
codet representation of a goto statement.
Definition: std_code.h:841
codet representation of an if-then-else statement.
Definition: std_code.h:460
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
const irep_idt & get_base_name() const
Definition: std_types.h:639
const irep_idt & get_identifier() const
Definition: std_types.h:634
void set_identifier(const irep_idt &identifier)
Definition: std_types.h:624
Base type of functions.
Definition: std_types.h:583
std::vector< parametert > parameterst
Definition: std_types.h:585
const typet & return_type() const
Definition: std_types.h:689
Data structure for representing an arbitrary statement in a program.
Definition: std_code_base.h:29
exprt & op1()
Definition: expr.h:136
exprt & op0()
Definition: expr.h:133
const irep_idt & get_statement() const
Definition: std_code_base.h:65
Operator to dereference a pointer.
Definition: pointer_expr.h:834
Division.
Definition: std_expr.h:1157
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:51
Base class for all expressions.
Definition: expr.h:56
exprt & op1()
Definition: expr.h:136
typet & type()
Return the type of the expression.
Definition: expr.h:84
operandst & operands()
Definition: expr.h:94
void add_to_operands(const exprt &expr)
Add the given argument to the end of exprt's operands.
Definition: expr.h:170
The Boolean constant false.
Definition: std_expr.h:3077
void set(const irep_idt &name, const irep_idt &value)
Definition: irep.h:412
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:2849
mstreamt & error() const
Definition: message.h:391
message_handlert * message_handler
Definition: message.h:431
static eomt eom
Definition: message.h:289
Binary minus.
Definition: std_expr.h:1061
Binary multiplication Associativity is not specified.
Definition: std_expr.h:1107
exprt & op1()
Definition: std_expr.h:938
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:94
Boolean negation.
Definition: std_expr.h:2332
Boolean OR.
Definition: std_expr.h:2233
Symbol table entry of function parameterThis is a symbol generated as part of type checking.
Definition: symbol.h:179
The plus expression Associativity is not specified.
Definition: std_expr.h:1002
The pointer type These are both 'bitvector_typet' (they have a width) and 'type_with_subtypet' (they ...
Definition: pointer_expr.h:24
Fixed-width bit-vector with two's complement interpretation.
Intermediate representation of a parsed Statement List file before converting it into a goto program.
std::list< var_declarationt > var_declarationst
functionst functions
List of functions this parse tree includes.
function_blockst function_blocks
List of function blocks this parse tree includes.
std::vector< symbol_exprt > tags
List of tags that were included in the source.
Class for encapsulating the current state of the type check.
void typecheck_accumulator_compare_instruction(const irep_idt &comparison)
Performs a typecheck on an STL comparison instruction.
void typecheck_statement_list_accu_real_div(const codet &op_code)
Performs a typecheck on a STL accumulator divide instruction for reals.
struct_typet create_instance_data_block_type(const statement_list_parse_treet::function_blockt &function_block)
Creates a data block type for the given function block.
const symbol_exprt & typecheck_instruction_with_non_const_operand(const codet &op_code)
Performs a typecheck on a STL instruction with an additional operand that should be no constant.
void typecheck_statement_list_accu_real_lte(const codet &op_code)
Performs a typecheck on a STL accumulator less than or equal comparison instruction for integers.
const statement_list_parse_treet & parse_tree
Parse tree which is used to fill the symbol table.
void typecheck_statement_list_nesting_closed(const codet &op_code)
Performs a typecheck on a Nesting Closed instruction.
void typecheck_statement_list_accu_real_sub(const codet &op_code)
Performs a typecheck on a STL accumulator subtract instruction for reals.
void typecheck_statement_list_networks(const statement_list_parse_treet::tia_modulet &tia_module, symbolt &tia_symbol)
Performs a typecheck on the networks of a TIA module and saves the result to the given symbol.
void clear_module_state()
Modifies the state of the typecheck to resemble the beginning of a new module.
void typecheck_statement_list_accu_int_add(const codet &op_code)
Performs a typecheck on a STL accumulator add instruction for integers.
void typecheck_jump_locations(const code_labelt &label, const stl_label_locationt &location)
Performs a typecheck on all references for the given label.
void typecheck_label_reference(const irep_idt &label, bool sets_fc_false)
Checks if the given label is already present and compares the current state with it.
void typecheck_statement_list_clr_rlo(const codet &op_code)
Performs a typecheck on a STL 'CLR' instruction and modifies the RLO, OR and FC bit.
statement_list_typecheckt(const statement_list_parse_treet &parse_tree, symbol_table_baset &symbol_table, const std::string &module, message_handlert &message_handler)
Creates a new instance of statement_list_typecheckt.
symbol_table_baset & symbol_table
Reference to the symbol table that should be filled during the typecheck.
void typecheck_statement_list_transfer(const codet &op_code, symbolt &tia_element)
Performs a typecheck on a STL transfer instruction and saves the result to the given symbol.
void typecheck_function_declaration(const statement_list_parse_treet::functiont &function)
Performs a typecheck on a function declaration inside of the parse tree and adds symbols for it and i...
void typecheck_statement_list_accu_dint_gte(const codet &op_code)
Performs a typecheck on a STL accumulator greater than or equal comparison instruction for double int...
void typecheck_statement_list_and_not(const codet &op_code, const symbolt &tia_element)
Performs a typecheck on a STL boolean And Not instruction.
void add_to_or_rlo_wrapper(const exprt &op)
Adds the given expression to the operands of the Or expression that is saved in the RLO.
void typecheck_function_block_var_decls(const statement_list_parse_treet::var_declarationst &var_decls, struct_union_typet::componentst &components, const irep_idt &var_property)
Performs a typecheck on a variable declaration list and saves the result to the given component eleme...
exprt typecheck_return_value_assignment(const std::vector< code_frontend_assignt > &assignments, const typet &return_type, const symbolt &tia_element)
Checks if there is a return value assignment inside of the assignment list of a function call and ret...
exprt typecheck_function_call_argument_rhs(const symbolt &tia_element, const exprt &rhs)
Checks if the given assigned expression is a variable or a constant and returns the typechecked versi...
void typecheck() override
Performs the actual typecheck by using the parse tree with which the object was initialized and modif...
void typecheck_statement_list_accu_dint_mul(const codet &op_code)
Performs a typecheck on a STL accumulator divide instruction for double integers.
void typecheck_statement_list_accu_int_gte(const codet &op_code)
Performs a typecheck on a STL accumulator greater than or equal comparison instruction for integers.
void typecheck_statement_list_nested_xor(const codet &op_code)
Performs a typecheck on a nested XOR instruction.
void typecheck_statement_list_accu_int_mul(const codet &op_code)
Performs a typecheck on a STL accumulator multiply instruction for integers.
const irep_idt module
Name of the module this typecheck belongs to.
void typecheck_statement_list_accu_int_lt(const codet &op_code)
Performs a typecheck on a STL accumulator less than comparison instruction for integers.
void typecheck_statement_list_nested_or_not(const codet &op_code)
Performs a typecheck on a nested Or Not instruction.
void typecheck_statement_list_set_rlo(const codet &op_code)
Performs a typecheck on a STL 'SET' instruction and modifies the RLO, OR and FC bit.
void typecheck_statement_list_accu_dint_add(const codet &op_code)
Performs a typecheck on a STL accumulator add instruction for double integers.
void typecheck_statement_list_accu_real_gt(const codet &op_code)
Performs a typecheck on a STL accumulator greater than comparison instruction for double integers.
std::vector< exprt > accumulator
Representation of the accumulator of a TIA element.
void typecheck_statement_list_nested_xor_not(const codet &op_code)
Performs a typecheck on a nested XOR Not instruction.
void clear_network_state()
Modifies the state of the typecheck to resemble the beginning of a new network.
void typecheck_statement_list_accu_real_eq(const codet &op_code)
Performs a typecheck on a STL accumulator equality comparison instruction for double integers.
void typecheck_statement_list_xor(const codet &op_code, const symbolt &tia_element)
Performs a typecheck on a STL boolean XOR instruction.
exprt typecheck_identifier(const symbolt &tia_element, const irep_idt &identifier)
Performs a typecheck on the given identifier and returns its symbol.
void typecheck_tag_list()
Performs a typecheck on the tag list of the referenced parse tree and adds symbols for its contents t...
void typecheck_statement_list_xor_not(const codet &op_code, const symbolt &tia_element)
Performs a typecheck on a STL boolean XOR Not instruction.
void typecheck_called_tia_element(const codet &op_code, symbolt &tia_element)
Performs a typecheck on a call of a TIA element and saves the result to the given symbol.
void typecheck_statement_list_jump_unconditional(const codet &op_code, symbolt &tia_element)
Performs a typecheck on an unconditional jump instruction (JU) and adds the jump to the given symbol.
void typecheck_code(const codet &instruction, symbolt &tia_element)
Performs a typecheck for the specified instruction in code form.
void typecheck_CPROVER_assume(const codet &op_code, symbolt &tia_element)
Performs a typecheck on a call of __CPOVER_ASSUME and saves the result to the given symbol.
void typecheck_statement_list_accu_real_add(const codet &op_code)
Performs a typecheck on a STL accumulator add instruction for reals.
label_referencest label_references
Holds associations between labels and jumps that are referencing it.
exprt rlo_bit
Result of Logic Operation (Part of the TIA status word).
exprt typecheck_simple_boolean_instruction_operand(const codet &op_code, const symbolt &tia_element, bool negate)
Performs a typecheck on the operand of a not nested boolean instruction and returns the result.
bool or_bit
Or (Part of the TIA status word).
void typecheck_statement_list_accu_dint_lt(const codet &op_code)
Performs a typecheck on a STL accumulator less than comparison instruction for double integers.
stl_labelst stl_labels
Data structure that contains data about the labels of the current module.
void typecheck_function_block_declaration(const statement_list_parse_treet::function_blockt &function_block)
Performs a typecheck on a function block declaration inside of the parse tree and adds symbols for it...
void typecheck_statement_list_load(const codet &op_code, const symbolt &tia_element)
Performs a typecheck on a STL load instruction.
void typecheck_statement_list_accu_int_div(const codet &op_code)
Performs a typecheck on a STL accumulator divide instruction for integers.
stl_label_locationt typecheck_label_location(const code_labelt &label)
Converts the properties of the current typecheck state to a label location.
void typecheck_statement_list_accu_int_neq(const codet &op_code)
Performs a typecheck on a STL accumulator inequality comparison instruction for integers.
void typecheck_statement_list_or(const codet &op_code, const symbolt &tia_element)
Performs a typecheck on a STL boolean Or instruction.
void typecheck_statement_list_accu_int_arith(const codet &op_code)
Performs a typecheck on a STL Accumulator instruction for integers.
void typecheck_statement_list_and(const codet &op_code, const symbolt &tia_element)
Performs a typecheck on a STL boolean And instruction.
void typecheck_statement_list_accu_real_lt(const codet &op_code)
Performs a typecheck on a STL accumulator less than comparison instruction for double integers.
void typecheck_instruction_without_operand(const codet &op_code)
Performs a typecheck on an operand-less STL instruction.
void typecheck_label(const codet &instruction, symbolt &tia_element)
Performs a typecheck for the given label in code form.
bool fc_bit
First Check (Part of the TIA status word).
void typecheck_statement_list_jump_conditional(const codet &op_code, symbolt &tia_element)
Performs a typecheck on a conditional jump instruction (JC) and adds it to the given symbol.
void typecheck_statement_list_jump_conditional_not(const codet &op_code, symbolt &tia_element)
Performs a typecheck on a inverted conditional jump instruction (JCN) and adds it to the given symbol...
void typecheck_statement_list_or_not(const codet &op_code, const symbolt &tia_element)
Performs a typecheck on a STL boolean Or Not instruction.
void typecheck_label_references()
Checks if all jumps reference labels that exist.
void typecheck_binary_accumulator_instruction(const codet &op_code)
Performs a typecheck on a STL instruction that uses two accumulator entries.
void initialize_bit_expression(const exprt &op)
Initializes the FC, RLO an OR bits for the scenario when a new boolean instruction was encontered.
void typecheck_statement_list_call(const codet &op_code, symbolt &tia_element)
Performs a typecheck on a STL Call instruction and saves the result to the given symbol.
void typecheck_statement_list_nested_or(const codet &op_code)
Performs a typecheck on a nested Or instruction.
void typecheck_statement_list_accu_dint_neq(const codet &op_code)
Performs a typecheck on a STL accumulator inequality comparison instruction for double integers.
void typecheck_statement_list_accu_real_mul(const codet &op_code)
Performs a typecheck on a STL accumulator multiply instruction for reals.
exprt typecheck_function_call_arguments(const std::vector< code_frontend_assignt > &assignments, const code_typet::parametert &param, const symbolt &tia_element)
Checks if the given parameter is inside of the assignment list of a function call and returns the exp...
void typecheck_temp_var_decls(const statement_list_parse_treet::tia_modulet &tia_module, symbolt &tia_symbol)
Performs a typecheck on the temp variables of a TIA module and saves the result to the given symbol v...
void typecheck_statement_list_accu_dint_arith(const codet &op_code)
Performs a typecheck on a STL Accumulator instruction for double integers.
void typecheck_CPROVER_assert(const codet &op_code, symbolt &tia_element)
Performs a typecheck on a call of __CPOVER_ASSERT and saves the result to the given symbol.
void typecheck_statement_list_nested_and_not(const codet &op_code)
Performs a typecheck on a nested And Not instruction.
void typecheck_statement_list_accu_int_gt(const codet &op_code)
Performs a typecheck on a STL accumulator greater than comparison instruction for integers.
void typecheck_statement_list_accu_int_sub(const codet &op_code)
Performs a typecheck on a STL accumulator subtract instruction for integers.
void typecheck_function_var_decls(const statement_list_parse_treet::var_declarationst &var_decls, code_typet::parameterst &params, const irep_idt &function_name, const irep_idt &var_property)
Performs a typecheck on a variable declaration list and saves the result to the given component eleme...
void typecheck_statement_list_instruction(const statement_list_parse_treet::instructiont &instruction, symbolt &tia_element)
Performs a typecheck on a single instruction and saves the result to the given symbol body if necessa...
void typecheck_statement_list_accu_dint_eq(const codet &op_code)
Performs a typecheck on a STL accumulator equality comparison instruction for double integers.
void typecheck_statement_list_accu_real_arith(const codet &op_code)
Performs a typecheck on a STL Accumulator instruction for reals.
void typecheck_statement_list_accu_real_gte(const codet &op_code)
Performs a typecheck on a STL accumulator greater than or equal comparison instruction for double int...
void typecheck_statement_list_reset(const codet &op_code, symbolt &tia_element)
Performs a typecheck on a STL 'R' instruction and saves the result to the given symbol.
void typecheck_statement_list_accu_real_neq(const codet &op_code)
Performs a typecheck on a STL accumulator inequality comparison instruction for double integers.
nesting_stackt nesting_stack
Representation of the nesting stack.
void typecheck_statement_list_not(const codet &op_code)
Performs a typecheck on a STL boolean NOT instruction.
void typecheck_statement_list_accu_dint_lte(const codet &op_code)
Performs a typecheck on a STL accumulator less than or equal comparison instruction for double intege...
void typecheck_called_function(const codet &op_code, symbolt &tia_element)
Performs a typecheck on a call of a TIA function and saves the result to the given symbol.
void typecheck_statement_list_accu_int_lte(const codet &op_code)
Performs a typecheck on a STL accumulator less than or equal comparison instruction for integers.
void typecheck_statement_list_accu_dint_gt(const codet &op_code)
Performs a typecheck on a STL accumulator greater than comparison instruction for double integers.
void typecheck_statement_list_assign(const codet &op_code, symbolt &tia_element)
Performs a typecheck on a STL assign instruction and saves the result to the given symbol.
void typecheck_statement_list_accu_int_eq(const codet &op_code)
Performs a typecheck on a STL accumulator equality comparison instruction for integers.
void typecheck_statement_list_accu_dint_sub(const codet &op_code)
Performs a typecheck on a STL accumulator subtract instruction for double integers.
void typecheck_called_function_block(const codet &op_code, symbolt &tia_element)
Performs a typecheck on a call of a TIA function block and saves the result to the given symbol.
void typecheck_statement_list_accu_dint_div(const codet &op_code)
Performs a typecheck on a STL accumulator divide instruction for double integers.
void add_temp_rlo()
Adds a symbol for the RLO to the symbol table.
void typecheck_statement_list_nested_and(const codet &op_code)
Performs a typecheck on a nested And instruction.
void save_rlo_state(symbolt &tia_element)
Saves the current RLO bit to a temporary variable to prevent false overrides when modifying boolean v...
void typecheck_nested_boolean_instruction(const codet &op_code, const exprt &rlo_value)
Performs a typecheck on a STL instruction that initializes a new boolean nesting.
void typecheck_statement_list_set(const codet &op_code, symbolt &tia_element)
Performs a typecheck on a STL 'S' instruction and saves the result to the given symbol.
void typecheck_statement_list_and_before_or()
Performs a typecheck on a STL operand-less Or instruction.
Structure type, corresponds to C style structs.
Definition: std_types.h:231
const componentst & components() const
Definition: std_types.h:147
std::vector< componentt > componentst
Definition: std_types.h:140
Expression to hold a symbol (variable)
Definition: std_expr.h:131
const irep_idt & get_identifier() const
Definition: std_expr.h:160
The symbol table base class interface.
symbolt & get_writeable_ref(const irep_idt &name)
Find a symbol in the symbol table for read-write access.
const symbolt & lookup_ref(const irep_idt &name) const
Find a symbol in the symbol table for read-only access.
bool has_symbol(const irep_idt &name) const
Check whether a symbol exists in the symbol table.
bool add(const symbolt &symbol)
Add a new symbol to the symbol table.
Symbol table entry.
Definition: symbol.h:28
irep_idt base_name
Base (non-scoped) name.
Definition: symbol.h:46
irep_idt module
Name of module the symbol belongs to.
Definition: symbol.h:43
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
irep_idt name
The unique identifier.
Definition: symbol.h:40
irep_idt pretty_name
Language-specific display name.
Definition: symbol.h:52
exprt value
Initial value of symbol.
Definition: symbol.h:34
irep_idt mode
Language mode.
Definition: symbol.h:49
The Boolean constant true.
Definition: std_expr.h:3068
Symbol table entry describing a data typeThis is a symbol generated as part of type checking.
Definition: symbol.h:139
const typet & subtype() const
Definition: type.h:187
virtual bool typecheck_main()
Definition: typecheck.cpp:14
The type of an expression, extends irept.
Definition: type.h:29
Boolean XOR.
Definition: std_expr.h:2296
const std::string & id2string(const irep_idt &d)
Definition: irep.h:44
API to expression classes for Pointers.
exprt simplify_expr(exprt src, const namespacet &ns)
#define UNREACHABLE
This should be used to mark dead code.
Definition: invariant.h:525
bool statement_list_typecheck(const statement_list_parse_treet &parse_tree, symbol_table_baset &symbol_table, const std::string &module, message_handlert &message_handler)
Create a new statement_list_typecheckt object and perform a type check to fill the symbol table.
#define CPROVER_ASSERT
Name of the CBMC assert function.
#define CPROVER_TEMP_RLO
Name of the RLO symbol used in some operations.
static code_typet::parametert create_data_block_parameter(const struct_typet &data_block_type, const irep_idt &function_block_name)
Creates the artificial data block parameter with a generic name and the specified type.
#define DATA_BLOCK_PARAMETER_NAME
Artificial name for the data block interface of a function block.
#define DATA_BLOCK_TYPE_POSTFIX
Postfix for the type of a data block.
#define STATEMENT_LIST_PTR_WIDTH
Size of pointers in Siemens TIA.
static const std::vector< irep_idt > logic_sequence_terminators
#define TYPECHECK_ERROR
#define CPROVER_ASSUME
Name of the CBMC assume function.
static const std::vector< irep_idt > logic_sequence_initializers
Statement List Language Type Checking.
bool_typet get_bool_type()
Creates a new type that resembles the 'Bool' type of the Siemens PLC languages.
Statement List Type Helper.
#define STL_INT_WIDTH
#define STL_DINT_WIDTH
bool can_cast_expr< code_frontend_assignt >(const exprt &base)
Definition: std_code.h:103
const code_labelt & to_code_label(const codet &code)
Definition: std_code.h:1004
auto component(T &struct_expr, const irep_idt &name, const namespacet &ns) -> decltype(struct_expr.op0())
Definition: std_expr.cpp:97
const or_exprt & to_or_expr(const exprt &expr)
Cast an exprt to a or_exprt.
Definition: std_expr.h:2280
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition: std_expr.h:272
const and_exprt & to_and_expr(const exprt &expr)
Cast an exprt to a and_exprt.
Definition: std_expr.h:2172
bool can_cast_expr< constant_exprt >(const exprt &base)
Definition: std_expr.h:3034
bool can_cast_expr< and_exprt >(const exprt &base)
Definition: std_expr.h:2161
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition: std_types.h:788
Structure for a simple function block in Statement List.
var_declarationst var_static
FB-exclusive static variable declarations.
Structure for a simple function in Statement List.
Represents a regular Statement List instruction which consists out of one or more codet tokens.
std::vector< codet > tokens
Data structure for all tokens of the instruction.
Base element of all modules in the Totally Integrated Automation (TIA) portal by Siemens.
var_declarationst var_input
Input variable declarations.
const irep_idt name
Name of the module.
var_declarationst var_inout
Inout variable declarations.
networkst networks
List of all networks of this module.
var_declarationst var_temp
Temp variable declarations.
var_declarationst var_output
Output variable declarations.
Struct for a single variable declaration in Statement List.
symbol_exprt variable
Representation of the variable, including identifier and type.
Every time branching occurs inside of a boolean expression string in STL, the current value of the RL...
nesting_stack_entryt(exprt rlo_bit, bool or_bit, codet function_code)
Holds information about the properties of a jump instruction.
stl_jump_locationt(size_t nesting_depth, bool sets_fc_false)
Constructs a new location with the specified properties.
Holds information about the instruction and the nesting depth to which a label points.
const bool jumps_permitted
States if jumps to this location are permitted or if the location is invalid.
stl_label_locationt(size_t nesting_depth, bool jumps_permitted, bool fc_false_required)
Constructs a new location with the specified properties.
const bool fc_false_required
States if jump instructions to this location need to set the /FC bit to false.
Author: Diffblue Ltd.
const type_with_subtypet & to_type_with_subtype(const typet &type)
Definition: type.h:208