Go to the documentation of this file.
31 if(code.
id()!=ID_code)
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)
55 else if(statement==ID_ifthenelse)
57 else if(statement==ID_while)
59 else if(statement==ID_dowhile)
61 else if(statement==ID_for)
63 else if(statement==ID_switch)
65 else if(statement==ID_break)
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)
77 else if(statement==ID_assign)
79 else if(statement==ID_skip)
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)
94 else if(statement==ID_msc_try_except)
101 else if(statement==ID_msc_leave)
106 else if(statement==ID_static_assert)
120 error() <<
"static assertion failed";
121 if(code.
op1().
id() == ID_string_constant)
127 else if(statement==ID_CPROVER_try_catch ||
128 statement==ID_CPROVER_try_finally)
134 else if(statement==ID_CPROVER_throw)
138 else if(statement==ID_assume ||
139 statement==ID_assert)
150 error() <<
"unexpected statement: " << statement <<
eom;
176 code_asm_gcc.operands().begin() + 1, code_asm_gcc.operands().end()))
178 for(
auto &expr : op.operands())
182 else if(flavor==ID_msc)
194 error() <<
"assignment statement expected to have two operands"
217 if(code_op.is_not_nil())
218 new_ops.
add(std::move(code_op));
229 error() <<
"break not allowed here" <<
eom;
239 error() <<
"continue not allowed here" <<
eom;
250 error() <<
"decl expected to have 1 operand" <<
eom;
255 if(code.
op0().
id()!=ID_declaration)
258 error() <<
"decl statement expected to have declaration as operand"
268 codet new_code(ID_static_assert);
278 std::list<codet> new_code;
287 symbol_tablet::symbolst::const_iterator s_it=
293 error() <<
"failed to find decl symbol '" << identifier
294 <<
"' in symbol table" <<
eom;
298 const symbolt &symbol=s_it->second;
307 error() <<
"incomplete type not permitted here" <<
eom;
340 new_code.push_back(decl);
345 new_code.splice(new_code.begin(),
clean_code);
353 else if(new_code.size()==1)
355 code.
swap(new_code.front());
361 code_block.set_statement(ID_decl_block);
362 code.
swap(code_block);
368 if(type.
id() == ID_array)
372 if(array_type.size().is_nil())
377 else if(type.
id()==ID_struct || type.
id()==ID_union)
381 if(struct_union_type.is_incomplete())
384 for(
const auto &c : struct_union_type.components())
388 else if(type.
id()==ID_vector)
390 else if(type.
id() == ID_struct_tag || type.
id() == ID_union_tag)
403 error() <<
"expression statement expected to have one operand"
417 error() <<
"for expected to have four operands" <<
eom;
495 code_block.
add(std::move(code));
496 code.
swap(code_block);
528 error() <<
"switch_case expected to have two operands" <<
eom;
539 error() <<
"did not expect default label here" <<
eom;
548 error() <<
"did not expect `case' here" <<
eom;
565 error() <<
"did not expect `case' here" <<
eom;
595 error() <<
"computed-goto expected to have one operand" <<
eom;
601 if(dest.
id()!=ID_dereference)
604 error() <<
"computed-goto expected to have dereferencing operand"
618 error() <<
"ifthenelse expected to have three operands" <<
eom;
627 if(cond.
id()==ID_sideeffect &&
628 cond.
get(ID_statement)==ID_assign)
630 warning(
"warning: assignment in if condition");
663 error() <<
"start_thread expected to have one operand" <<
eom;
683 warning() <<
"function has return void ";
684 warning() <<
"but a return statement returning ";
700 warning() <<
"non-void function should return a value" <<
eom;
736 for(
auto &statement : body_block.
statements())
738 if(statement.get_statement() == ID_switch_case)
740 else if(statement.get_statement() == ID_decl)
742 if(statement.operands().size() == 1)
745 wrapping_block.
statements().back().swap(statement);
750 wrapping_block.
add(statement);
751 wrapping_block.
statements().back().operands().pop_back();
752 statement.set_statement(ID_assign);
759 wrapping_block.
add(std::move(code));
760 code.
swap(wrapping_block);
775 error() <<
"while expected to have two operands" <<
eom;
792 code.
body() = code_block;
815 error() <<
"do while expected to have two operands" <<
eom;
832 code.
body() = code_block;
855 "side-effects not allowed in assigns clause targets",
861 "ternary expressions not allowed in assigns clause targets",
884 <<
"function with possible side-effect called in target's condition"
888 if(condition.
type().
id() == ID_empty)
891 "void-typed expressions not allowed as assigns clause conditions",
901 "side-effects not allowed in assigns clause conditions",
908 "ternary expressions not allowed in assigns clause conditions",
915 const std::function<
void(
exprt &)> typecheck_target,
916 const std::string &clause_type)
920 for(
auto &target : targets)
925 "expected a conditional target group expression in " + clause_type +
926 "clause, found " +
id2string(target.id()),
927 target.source_location()};
934 auto &condition = conditional_target_group.condition();
937 if(condition.is_true())
941 for(
auto &actual_target : conditional_target_group.targets())
943 typecheck_target(actual_target);
944 new_targets.push_back(actual_target);
950 for(
auto &actual_target : conditional_target_group.targets())
952 typecheck_target(actual_target);
954 new_targets.push_back(std::move(target));
963 std::swap(targets, new_targets);
968 const std::function<void(
exprt &)> typecheck_target = [&](
exprt &target) {
981 if(target.
type().
id() == ID_empty)
984 "lvalue expressions with void type not allowed in assigns clauses",
990 else if(target.
id() == ID_pointer_object)
1007 for(
const auto &argument : funcall.arguments())
1015 "function pointer calls not allowed in assigns clauses",
1021 "assigns clause target must be a non-void lvalue or a call to one "
1034 error() <<
"expected ID_function_pointer_obeys_contract expression in "
1035 "requires_contract/ensures_contract clause, found "
1036 << expr.
id() <<
eom;
1046 auto &function_pointer = obeys_expr.function_pointer();
1050 function_pointer.type().id() != ID_pointer ||
1054 error() <<
"the first parameter of the clause must be a function pointer "
1060 if(!function_pointer.get_bool(ID_C_lvalue))
1063 error() <<
"first parameter of the clause must be an lvalue" <<
eom;
1070 error() <<
"first parameter of the clause must have no side-effects" <<
eom;
1077 error() <<
"first parameter of the clause must have no ternary operator"
1083 auto &address_of_contract = obeys_expr.address_of_contract();
1087 address_of_contract.id() != ID_address_of ||
1089 address_of_contract.
type().
id() != ID_pointer ||
1093 error() <<
"the second parameter of the requires_contract/ensures_contract "
1094 "clause must be a function symbol"
1099 if(function_pointer.type() != address_of_contract.type())
1102 error() <<
"the first and second parameter of the "
1103 "requires_contract/ensures_contract clause must have the same "
1104 "function pointer type "
1114 for(
auto &invariant :
1131 for(
auto &decreases_clause_component :
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
const exprt & case_op() const
bool can_cast_expr< symbol_exprt >(const exprt &base)
A codet representing sequential composition of program statements.
virtual void implicit_typecast_arithmetic(exprt &expr)
const unary_exprt & to_unary_expr(const exprt &expr)
Cast an exprt to a unary_exprt.
codet representation of a switch-case, i.e. a case statement within a switch.
static code_blockt from_list(const std::list< codet > &_list)
side_effect_expr_function_callt & to_side_effect_expr_function_call(exprt &expr)
bool has_subexpr(const exprt &expr, const std::function< bool(const exprt &)> &pred)
returns true if the expression has a subexpression that satisfies pred
virtual void typecheck_spec_loop_invariant(codet &code)
const declaratorst & declarators() const
bool can_cast_expr< side_effect_expr_function_callt >(const exprt &base)
bool can_cast_expr< function_pointer_obeys_contract_exprt >(const exprt &base)
codet representing a while statement.
virtual void typecheck_spec_condition(exprt &condition)
virtual void typecheck_while(code_whilet &code)
codet representation of an inline assembler statement.
const struct_union_typet & to_struct_union_type(const typet &type)
Cast a typet to a struct_union_typet.
The type of an expression, extends irept.
const codet & then_case() const
std::string pretty(unsigned indent=0, unsigned max_indent=0) const
const exprt & upper() const
upper bound of range
void typecheck_declaration(ansi_c_declarationt &)
virtual void typecheck_break(codet &code)
virtual std::string to_string(const exprt &expr)
const irept & find(const irep_idt &name) const
typet type
Type of symbol.
bool can_cast_expr< side_effect_exprt >(const exprt &base)
virtual void typecheck_spec_assigns_target(exprt &target)
const string_constantt & to_string_constant(const exprt &expr)
void disallow_subexpr_by_id(const exprt &, const irep_idt &, const std::string &) const
A codet representing the declaration of a local variable.
Base class for all expressions.
Generic base class for unary expressions.
Thrown when we can't handle something in an input source file.
const code_whilet & to_code_while(const codet &code)
codet representation of a switch-case, i.e. a case statement within a switch.
const exprt & cond() const
struct configt::ansi_ct ansi_c
bool get_is_static_assert() const
void validate_expr(const shuffle_vector_exprt &value)
codet representation of an if-then-else statement.
bool is_false() const
Return whether the expression is a constant representing false.
const exprt & lower() const
lower bound of range
std::list< codet > clean_code
const irep_idt & get(const irep_idt &name) const
virtual void make_constant(exprt &expr)
const exprt & return_value() const
const code_switch_caset & to_code_switch_case(const codet &code)
code_operandst & statements()
const codet & to_code(const exprt &expr)
typet & type()
Return the type of the expression.
virtual void typecheck_continue(codet &code)
codet representation of a do while statement.
virtual void typecheck_asm(code_asmt &code)
virtual void implicit_typecast_bool(exprt &expr)
const std::string & id2string(const irep_idt &d)
codet & code()
the statement to be executed when the case applies
source_locationt source_location
const code_gotot & to_code_goto(const codet &code)
void set(const irep_idt &name, const irep_idt &value)
virtual void typecheck_label(code_labelt &code)
codet representation of a goto statement.
const code_ifthenelset & to_code_ifthenelse(const codet &code)
codet representation of a label for branch targets.
#define PRECONDITION(CONDITION)
const source_locationt & find_source_location() const
Get a source_locationt from the expression or from its operands (non-recursively).
const irep_idt & get_identifier() const
virtual void typecheck_spec_decreases(codet &code)
virtual bool is_complete_type(const typet &type) const
A range is a pair of a begin and an end iterators.
const code_labelt & to_code_label(const codet &code)
class symbol_exprt symbol_expr() const
Produces a symbol_exprt for a symbol.
virtual void throw_on_side_effects(const exprt &expr)
virtual void typecheck_expression(codet &code)
virtual void typecheck_conditional_targets(exprt::operandst &targets, const std::function< void(exprt &)> typecheck_target, const std::string &clause_type)
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
symbol_tablet & symbol_table
const code_dowhilet & to_code_dowhile(const codet &code)
virtual void typecheck_goto(code_gotot &code)
virtual void typecheck_code(codet &code)
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
const exprt & cond() const
const codet & body() const
const irep_idt & id() const
std::vector< exprt > operandst
void add(const codet &code)
code_asm_gcct & to_code_asm_gcc(codet &code)
const conditional_target_group_exprt & to_conditional_target_group_expr(const exprt &expr)
Cast an exprt to a conditional_target_group_exprt.
virtual void typecheck_switch(codet &code)
virtual void typecheck_dowhile(code_dowhilet &code)
std::map< irep_idt, source_locationt > labels_used
virtual void typecheck_expr(exprt &expr)
codet representation of a "return from a function" statement.
const code_gcc_switch_case_ranget & to_code_gcc_switch_case_range(const codet &code)
A side_effect_exprt that returns a non-deterministically chosen value.
const irep_idt & get_label() const
code_asmt & to_code_asm(codet &code)
Deprecated expression utility functions.
virtual void typecheck_for(codet &code)
const exprt & value() const
exprt value
Initial value of symbol.
virtual void typecheck_spec_function_pointer_obeys_contract(exprt &expr)
const code_frontend_returnt & to_code_frontend_return(const codet &code)
irept & add(const irep_idt &name)
virtual void typecheck_decl(codet &code)
virtual void typecheck_gcc_switch_case_range(code_gcc_switch_case_ranget &)
A codet representing a skip statement.
const typet & follow(const typet &) const
Resolve type symbol to the type it points to.
source_locationt location
Source code location of definition of symbol.
std::map< irep_idt, source_locationt > labels_defined
codet representing a switch statement.
const codet & body() const
const symbolst & symbols
Read-only field, used to look up symbols given their names.
const codet & else_case() const
virtual void typecheck_assign(codet &expr)
const code_switcht & to_code_switch(const codet &code)
const typet & base_type() const
The type of the data what we point to.
const irep_idt & get_destination() const
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
bool has_return_value() const
virtual void typecheck_start_thread(codet &code)
virtual void typecheck_return(code_frontend_returnt &)
const exprt & cond() const
virtual void typecheck_ifthenelse(code_ifthenelset &code)
const vector_typet & to_vector_type(const typet &type)
Cast a typet to a vector_typet.
const code_blockt & to_code_block(const codet &code)
virtual void typecheck_spec_assigns(exprt::operandst &targets)
const address_of_exprt & to_address_of_expr(const exprt &expr)
Cast an exprt to an address_of_exprt.
virtual void start_typecheck_code()
bool can_cast_expr< conditional_target_group_exprt >(const exprt &base)
virtual void typecheck_switch_case(code_switch_caset &code)
virtual void typecheck_gcc_computed_goto(codet &code)
source_locationt & add_source_location()
const irep_idt & get_flavor() const
const codet & body() const
Semantic type conversion.
The Boolean constant true.
const irep_idt & get_statement() const
mstreamt & warning() const
void reserve_operands(operandst::size_type n)
const source_locationt & source_location() const
virtual void typecheck_gcc_local_label(codet &code)
const irep_idt & get_value() const
bool get_bool(const irep_idt &name) const
source_locationt end_location() const
virtual void typecheck_block(code_blockt &code)
virtual void implicit_typecast(exprt &expr, const typet &type)
Data structure for representing an arbitrary statement in a program.
const function_pointer_obeys_contract_exprt & to_function_pointer_obeys_contract_expr(const exprt &expr)
Cast an exprt to a function_pointer_obeys_contract_exprt.