Go to the documentation of this file.
38 const irep_idt &identifier =
function.get_identifier();
41 if(arguments.size()!=2)
44 error() <<
"'" << identifier <<
"' expected to have two arguments" <<
eom;
51 error() <<
"'" << identifier <<
"' expected to have LHS" <<
eom;
58 if(lhs.
type().
id()!=ID_unsignedbv &&
59 lhs.
type().
id()!=ID_signedbv)
62 error() <<
"'" << identifier <<
"' expected other type" <<
eom;
66 if(arguments[0].type().
id()!=lhs.
type().
id() ||
67 arguments[1].type().id()!=lhs.
type().
id())
70 error() <<
"'" << identifier
71 <<
"' expected operands to be of same type as LHS" <<
eom;
79 error() <<
"'" << identifier
80 <<
"' expected operands to be constant literals" <<
eom;
91 error() <<
"error converting operands" <<
eom;
98 error() <<
"expected lower bound to be smaller or equal to the "
99 <<
"upper bound" <<
eom;
103 rhs.add_to_operands(
exprt{arguments[0]},
exprt{arguments[1]});
116 const irep_idt &identifier =
function.get_identifier();
119 if(arguments.size()!=2)
122 error() <<
"'" << identifier <<
"' expected to have two arguments" <<
eom;
129 error() <<
"'" << identifier <<
"' expected to have LHS" <<
eom;
138 error() <<
"'" << identifier <<
"' expected bool" <<
eom;
142 if(arguments[0].type().
id()!=ID_unsignedbv ||
143 arguments[0].
id()!=ID_constant)
146 error() <<
"'" << identifier <<
"' expected first operand to be "
147 <<
"a constant literal of type unsigned long" <<
eom;
152 arguments[1].type().
id() != ID_unsignedbv ||
153 arguments[1].
id() != ID_constant)
156 error() <<
"'" << identifier <<
"' expected second operand to be "
157 <<
"a constant literal of type unsigned long" <<
eom;
168 error() <<
"error converting operands" <<
eom;
175 error() <<
"probability has to be smaller than 1" <<
eom;
182 error() <<
"denominator may not be zero" <<
eom;
186 rationalt numerator(num), denominator(den);
187 rationalt prob = numerator / denominator;
202 const irep_idt &f_id =
function.get_identifier();
206 codet printf_code(ID_printf, arguments,
function.source_location());
216 const irep_idt &f_id =
function.get_identifier();
220 if(arguments.empty())
223 error() <<
"scanf takes at least one argument" <<
eom;
235 std::size_t argument_number=1;
237 for(
const auto &t : token_list)
243 if(argument_number<arguments.size())
249 if(type->id() == ID_array)
258 *type,
"scanf_string", dest,
function.source_location());
266 codet array_copy_statement;
268 array_copy_statement.
operands().resize(2);
269 array_copy_statement.
op0()=ptr;
270 \ array_copy_statement.
op1()=rhs;
272 function.source_location();
291 *type,
function.source_location());
314 const exprt &
function,
318 if(arguments.size()<2)
321 error() <<
"input takes at least two arguments" <<
eom;
329 const exprt &
function,
333 if(arguments.size()<2)
336 error() <<
"output takes at least two arguments" <<
eom;
352 error() <<
"atomic_begin does not expect an LHS" <<
eom;
356 if(!arguments.empty())
359 error() <<
"atomic_begin takes no arguments" <<
eom;
375 error() <<
"atomic_end does not expect an LHS" <<
eom;
379 if(!arguments.empty())
382 error() <<
"atomic_end takes no arguments" <<
eom;
397 error() <<
"do_cpp_new without lhs is yet to be implemented" <<
eom;
403 static_cast<const exprt &
>(rhs.
find(ID_sizeof));
405 bool new_array=rhs.
get(ID_statement)==ID_cpp_new_array;
418 exprt tmp_symbol_expr;
425 ns.
lookup(new_array?
"__new_array":
"__new").symbol_expr();
430 const typet &return_type=
447 new_call.
lhs()=tmp_symbol_expr;
450 convert(new_call, dest, ID_cpp);
457 new_array?
"__placement_new_array":
"__placement_new").symbol_expr();
479 new_call.
lhs()=tmp_symbol_expr;
482 for(std::size_t i=0; i<code_type.
parameters().size(); i++)
488 convert(new_call, dest, ID_cpp);
493 error() <<
"cpp_new expected to have 0 or 1 operands" <<
eom;
516 static_cast<const exprt &
>(rhs.
find(ID_initializer));
540 if(src.
id()==ID_typecast)
543 if(src.
id()!=ID_address_of)
546 error() <<
"expected array-pointer as argument" <<
eom;
552 if(address_of_expr.object().id() != ID_index)
555 error() <<
"expected array-element as argument" <<
eom;
559 const auto &index_expr =
to_index_expr(address_of_expr.object());
561 if(index_expr.array().type().id() != ID_array)
564 error() <<
"expected array as argument" <<
eom;
568 return index_expr.array();
578 if(arguments.size()!=2)
581 error() <<
id <<
" expects two arguments" <<
eom;
585 codet array_op_statement(
id);
586 array_op_statement.
operands()=arguments;
591 if(
id == ID_array_equal)
602 if(result.
id() == ID_address_of)
606 result = address_of_expr.object();
609 while(result.
type().
id() == ID_array &&
625 const auto enum_expr = arguments.front();
626 const auto enum_type =
627 type_try_dynamic_cast<c_enum_tag_typet>(enum_expr.type());
633 for(
const auto &enum_value : enum_values)
636 disjuncts.push_back(
equal_exprt(enum_expr, std::move(val)));
656 auto source_location =
function.find_source_location();
657 source_location.add_pragma(
"disable:pointer-check");
658 source_location.add_pragma(
"disable:pointer-overflow-check");
659 source_location.add_pragma(
"disable:pointer-primitive-check");
662 if(arguments.size() != 2)
665 error() <<
"'" << identifier <<
"' expected to have two arguments" <<
eom;
670 if(arguments[0].type().
id() != ID_pointer)
673 error() <<
"'" << identifier
674 <<
"' first argument expected to have `void *` type" <<
eom;
678 if(arguments[1].type().
id() != ID_unsignedbv)
681 error() <<
"'" << identifier
682 <<
"' second argument expected to have `size_t` type" <<
eom;
690 error() <<
"'" << identifier <<
"' not expected to have a LHS" <<
eom;
703 t->source_location_nonconst().set(
"user-provided",
false);
704 t->source_location_nonconst().set_property_class(ID_assertion);
705 t->source_location_nonconst().set_comment(
706 "assertion havoc_slice " +
from_expr(
ns, identifier, ok_expr));
710 const symbolt &nondet_contents =
711 new_tmp_symbol(array_type,
"nondet_contents", dest, source_location, mode);
720 codet array_replace(ID_array_replace, {arg0, arg1}, source_location);
732 if(
function.get_bool(ID_C_invalid_object))
736 const irep_idt &identifier=
function.get_identifier();
742 error() <<
"error: function '" << identifier <<
"' not found" <<
eom;
746 if(symbol->
type.
id()!=ID_code)
749 error() <<
"error: function '" << identifier
750 <<
"' type mismatch: expected code" <<
eom;
775 identifier ==
CPROVER_PREFIX "assume" || identifier ==
"__VERIFIER_assume")
777 if(arguments.size()!=1)
780 error() <<
"'" << identifier <<
"' expected to have one argument" <<
eom;
787 function.source_location()));
789 t->source_location_nonconst().set(
"user-provided",
true);
794 error() << identifier <<
" expected not to have LHS" <<
eom;
798 else if(identifier==
"__VERIFIER_error")
800 if(!arguments.empty())
803 error() <<
"'" << identifier <<
"' expected to have no arguments" <<
eom;
810 t->source_location_nonconst().set(
"user-provided",
true);
811 t->source_location_nonconst().set_property_class(ID_assertion);
816 error() << identifier <<
" expected not to have LHS" <<
eom;
824 a->source_location_nonconst().set(
"user-provided",
true);
827 identifier ==
"assert" &&
830 if(arguments.size()!=1)
833 error() <<
"'" << identifier <<
"' expected to have one argument" <<
eom;
840 function.source_location()));
841 t->source_location_nonconst().set(
"user-provided",
true);
842 t->source_location_nonconst().set_property_class(ID_assertion);
843 t->source_location_nonconst().set_comment(
844 "assertion " +
from_expr(
ns, identifier, arguments.front()));
849 error() << identifier <<
" expected not to have LHS" <<
eom;
862 if(arguments.size()!=2)
865 error() <<
"'" << identifier <<
"' expected to have two arguments" <<
eom;
869 bool is_precondition=
871 bool is_postcondition = identifier ==
CPROVER_PREFIX "postcondition";
879 function.source_location()));
883 t->source_location_nonconst().set_property_class(ID_precondition);
885 else if(is_postcondition)
887 t->source_location_nonconst().set_property_class(ID_postcondition);
891 t->source_location_nonconst().set(
892 "user-provided", !
function.source_location().is_built_in());
893 t->source_location_nonconst().set_property_class(ID_assertion);
896 t->source_location_nonconst().set_comment(description);
901 error() << identifier <<
" expected not to have LHS" <<
eom;
907 if(arguments.size()!=1)
910 error() <<
"'" << identifier <<
"' expected to have one argument" <<
eom;
917 error() << identifier <<
" expected not to have LHS" <<
eom;
921 codet havoc(ID_havoc_object);
929 do_printf(lhs,
function, arguments, dest);
933 do_scanf(lhs,
function, arguments, dest);
936 identifier==
"__CPROVER::input")
941 error() << identifier <<
" expected not to have LHS" <<
eom;
945 do_input(
function, arguments, dest);
948 identifier==
"__CPROVER::output")
953 error() << identifier <<
" expected not to have LHS" <<
eom;
960 identifier==
"__CPROVER::atomic_begin" ||
961 identifier==
"java::org.cprover.CProver.atomicBegin:()V" ||
962 identifier==
"__VERIFIER_atomic_begin")
967 identifier==
"__CPROVER::atomic_end" ||
968 identifier==
"java::org.cprover.CProver.atomicEnd:()V" ||
969 identifier==
"__VERIFIER_atomic_end")
992 if(lhs.
type().
id()==ID_c_bool)
995 rhs.
set(ID_C_identifier, identifier);
1001 rhs.
set(ID_C_identifier, identifier);
1014 if(
function.type().get_bool(ID_C_incomplete))
1017 error() <<
"'" << identifier <<
"' is not declared, "
1018 <<
"missing type information required to construct call to "
1019 <<
"uninterpreted function" <<
eom;
1025 for(
const auto ¶meter : function_call_type.
parameters())
1026 domain.push_back(parameter.type());
1033 assignment.add_source_location()=
function.source_location();
1038 do_array_op(ID_array_equal, lhs,
function, arguments, dest);
1042 do_array_op(ID_array_set, lhs,
function, arguments, dest);
1046 do_array_op(ID_array_copy, lhs,
function, arguments, dest);
1050 do_array_op(ID_array_replace, lhs,
function, arguments, dest);
1052 else if(identifier==
"__assert_fail" ||
1053 identifier==
"_assert" ||
1054 identifier==
"__assert_c99" ||
1055 identifier==
"_wassert")
1076 if(arguments.size()!=4 &&
1077 arguments.size()!=3)
1080 error() <<
"'" << identifier <<
"' expected to have four arguments"
1091 t->source_location_nonconst().set(
"user-provided",
true);
1092 t->source_location_nonconst().set_property_class(ID_assertion);
1093 t->source_location_nonconst().set_comment(description);
1096 else if(identifier==
"__assert_rtn" ||
1097 identifier==
"__assert")
1108 if(arguments.size()==4)
1113 else if(arguments.size()==3)
1121 error() <<
"'" << identifier <<
"' expected to have four arguments"
1129 t->source_location_nonconst().set(
"user-provided",
true);
1130 t->source_location_nonconst().set_property_class(ID_assertion);
1131 t->source_location_nonconst().set_comment(description);
1134 else if(identifier==
"__assert_func")
1139 if(arguments.size()!=4)
1142 error() <<
"'" << identifier <<
"' expected to have four arguments"
1157 description=
"assertion";
1163 t->source_location_nonconst().set(
"user-provided",
true);
1164 t->source_location_nonconst().set_property_class(ID_assertion);
1165 t->source_location_nonconst().set_comment(description);
1170 if(arguments.empty())
1173 error() <<
"'" << identifier <<
"' expected to have at least one argument"
1178 codet fence(ID_fence);
1180 for(
const auto &argument : arguments)
1185 else if(identifier==
"__builtin_prefetch")
1189 else if(identifier==
"__builtin_unreachable")
1193 else if(identifier==ID_gcc_builtin_va_arg)
1201 if(arguments.size()!=1)
1204 error() <<
"'" << identifier <<
"' expected to have one argument" <<
eom;
1212 exprt list_arg_cast = list_arg;
1214 list_arg.
type().
id() == ID_pointer &&
1232 ID_C_va_arg_type,
to_code_type(
function.type()).return_type());
1234 std::move(assign),
function.source_location()));
1236 else if(identifier==
"__builtin_va_copy")
1238 if(arguments.size()!=2)
1241 error() <<
"'" << identifier <<
"' expected to have two arguments" <<
eom;
1251 error() <<
"va_copy argument expected to be lvalue" <<
eom;
1256 dest_expr, src_expr,
function.source_location()));
1258 else if(identifier ==
"__builtin_va_start" || identifier ==
"__va_start")
1262 if(arguments.size()!=2)
1265 error() <<
"'" << identifier <<
"' expected to have two arguments" <<
eom;
1274 error() <<
"va_start argument expected to be lvalue" <<
eom;
1279 dest_expr.
type().
id() == ID_pointer &&
1288 rhs.add_to_operands(
1292 std::move(dest_expr), std::move(rhs),
function.source_location()));
1294 else if(identifier==
"__builtin_va_end")
1297 if(arguments.size()!=1)
1300 error() <<
"'" << identifier <<
"' expected to have one argument" <<
eom;
1309 error() <<
"va_end argument expected to be lvalue" <<
eom;
1314 if(dest_expr.
type().
id() == ID_pointer)
1320 dest_expr, *zero,
function.source_location()));
1324 identifier ==
"__builtin_isgreater" ||
1325 identifier ==
"__builtin_isgreaterequal" ||
1326 identifier ==
"__builtin_isless" || identifier ==
"__builtin_islessequal" ||
1327 identifier ==
"__builtin_islessgreater" ||
1328 identifier ==
"__builtin_isunordered")
1332 if(arguments.size()!=2 ||
1339 error() <<
"'" << identifier
1340 <<
"' expected to have two float/double arguments" <<
eom;
1346 bool use_double=arguments[0].type()==
double_type();
1347 if(arguments[0].type()!=arguments[1].type())
1364 const typet &a_t=new_arguments[0].type();
1371 name+=use_double?
'd':
'f';
1375 new_function.
type()=f_type;
1384 new_symbol.
name=name;
1385 new_symbol.
type=f_type;
1386 new_symbol.
location=
function.source_location();
1393 (identifier ==
"alloca" || identifier ==
"__builtin_alloca") &&
1394 function.source_location().get_function() !=
"alloca")
1397 exprt new_lhs = lhs;
1422 exprt alloca_result =
1426 std::move(alloca_result),
1429 std::move(dead_object_sym), std::move(rhs), source_location};
void copy_to_operands(const exprt &expr)
Copy the given argument to the end of exprt's operands.
static instructiont make_other(const goto_instruction_codet &_code, const source_locationt &l=source_locationt::nil())
#define UNREACHABLE
This should be used to mark dead code.
void do_havoc_slice(const exprt &lhs, const symbol_exprt &function, const exprt::operandst &arguments, goto_programt &dest, const irep_idt &mode)
bool has_symbol(const irep_idt &name) const
Check whether a symbol exists in the symbol table.
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
static exprt conditional_cast(const exprt &expr, const typet &type)
bool is_assignable(const exprt &expr)
Returns true iff the argument is one of the following:
const unary_exprt & to_unary_expr(const exprt &expr)
Cast an exprt to a unary_exprt.
virtual void do_cpp_new(const exprt &lhs, const side_effect_exprt &rhs, goto_programt &dest)
const exprt & skip_typecast(const exprt &expr)
find the expression nested inside typecasts, if any
void do_output(const exprt &rhs, const exprt::operandst &arguments, goto_programt &dest)
static void replace_new_object(const exprt &object, exprt &dest)
void convert(const codet &code, goto_programt &dest, const irep_idt &mode)
converts 'code' and appends the result to 'dest'
void copy(const codet &code, goto_program_instruction_typet type, goto_programt &dest)
#define CHECK_RETURN(CONDITION)
The type of an expression, extends irept.
std::vector< parametert > parameterst
void clean_expr(exprt &expr, goto_programt &dest, const irep_idt &mode, bool result_is_used=true)
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
const irept & find(const irep_idt &name) const
exprt get_array_argument(const exprt &src)
void cpp_new_initializer(const exprt &lhs, const side_effect_exprt &rhs, goto_programt &dest)
builds a goto program for object initialization after new
typet type
Type of symbol.
Operator to dereference a pointer.
The trinary if-then-else operator.
void do_atomic_end(const exprt &lhs, const symbol_exprt &function, const exprt::operandst &arguments, goto_programt &dest)
std::vector< c_enum_membert > memberst
void add_pragma(const irep_idt &pragma)
targett add(instructiont &&instruction)
Adds a given instruction at the end.
const type_with_subtypet & to_type_with_subtype(const typet &type)
The plus expression Associativity is not specified.
Base class for all expressions.
const exprt & op1() const =delete
irep_idt base_name
Base (non-scoped) name.
const union_typet & follow_tag(const union_tag_typet &) const
Follow type tag of union type.
Expression to hold a symbol (variable)
static instructiont make_assignment(const code_assignt &_code, const source_locationt &l=source_locationt::nil())
Create an assignment instruction.
optionalt< exprt > zero_initializer(const typet &type, const source_locationt &source_location, const namespacet &ns)
Create the equivalent of zero for type type.
symbolt & new_tmp_symbol(const typet &type, const std::string &suffix, goto_programt &dest, const source_locationt &, const irep_idt &mode)
const irep_idt & get(const irep_idt &name) const
virtual void do_function_call_symbol(const exprt &lhs, const symbol_exprt &function, const exprt::operandst &arguments, goto_programt &dest, const irep_idt &mode)
add function calls to function queue for later processing
const exprt & size() const
A goto_instruction_codet representing the declaration that an output of a particular description has ...
void do_enum_is_in_range(const exprt &lhs, const symbol_exprt &function, const exprt::operandst &arguments, goto_programt &dest)
Converts calls to the built in enum_is_in_range function to a test that the given enum value is in th...
const codet & to_code(const exprt &expr)
typet & type()
Return the type of the expression.
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
goto_instruction_codet representation of a function call statement.
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
exprt disjunction(const exprt::operandst &op)
1) generates a disjunction for two or more operands 2) for one operand, returns the operand 3) return...
struct goto_convertt::targetst targets
static instructiont make_assertion(const exprt &g, const source_locationt &l=source_locationt::nil())
void add(const codet &destructor)
Adds a destructor to the current stack, attaching itself to the current node.
signedbv_typet signed_int_type()
bool has_prefix(const std::string &s, const std::string &prefix)
void do_scanf(const exprt &lhs, const symbol_exprt &function, const exprt::operandst &arguments, goto_programt &dest)
const std::string & id2string(const irep_idt &d)
source_locationt source_location
irep_idt get_string_constant(const exprt &expr)
void set(const irep_idt &name, const irep_idt &value)
#define PRECONDITION(CONDITION)
const source_locationt & source_location() const
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
class symbol_exprt symbol_expr() const
Produces a symbol_exprt for a symbol.
floatbv_typet float_type()
Application of (mathematical) function.
std::vector< typet > domaint
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
exprt simplify_expr(exprt src, const namespacet &ns)
pointer_typet pointer_type(const typet &subtype)
static instructiont make_atomic_begin(const source_locationt &l=source_locationt::nil())
exprt object_size(const exprt &pointer)
const irep_idt & id() const
std::vector< exprt > operandst
The Boolean constant false.
const parameterst & parameters() const
source_locationt & add_source_location()
floatbv_typet double_type()
const irep_idt & get_statement() const
void destructive_append(goto_programt &p)
Appends the given program p to *this. p is destroyed.
bitvector_typet char_type()
A side_effect_exprt that returns a non-deterministically chosen value.
bool add(const symbolt &symbol)
Add a new symbol to the symbol table.
Deprecated expression utility functions.
exprt value
Initial value of symbol.
void do_input(const exprt &rhs, const exprt::operandst &arguments, goto_programt &dest)
void do_printf(const exprt &lhs, const symbol_exprt &function, const exprt::operandst &arguments, goto_programt &dest)
void do_atomic_begin(const exprt &lhs, const symbol_exprt &function, const exprt::operandst &arguments, goto_programt &dest)
destructor_treet destructor_stack
source_locationt location
Source code location of definition of symbol.
const typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
const typet & base_type() const
The type of the data what we point to.
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
A generic container class for the GOTO intermediate representation of one function.
void do_array_op(const irep_idt &id, const exprt &lhs, const symbol_exprt &function, const exprt::operandst &arguments, goto_programt &dest)
A base class for a predicate that indicates that an address range is ok to read or write or both.
const typet & subtype() const
symbol_table_baset & symbol_table
bool is_one() const
Return whether the expression is a constant representing 1.
const typet & return_type() const
void set_statement(const irep_idt &statement)
static instructiont make_assumption(const exprt &g, const source_locationt &l=source_locationt::nil())
const address_of_exprt & to_address_of_expr(const exprt &expr)
Cast an exprt to an address_of_exprt.
Operator to return the address of an object.
source_locationt & add_source_location()
Semantic type conversion.
signedbv_typet pointer_diff_type()
unsignedbv_typet size_type()
A goto_instruction_codet representing an assignment in the program.
A constant literal expression.
bitvector_typet c_index_type()
bool is_constant(const typet &type)
This method tests, if the given typet is a constant.
const irep_idt & get_value() const
const source_locationt & source_location() const
exprt make_va_list(const exprt &expr)
A type for mathematical functions (do not confuse with functions/methods in code)
std::string from_expr(const namespacet &ns, const irep_idt &identifier, const exprt &expr)
void set_identifier(const irep_idt &identifier)
irep_idt name
The unique identifier.
bool get_bool(const irep_idt &name) const
instructionst::iterator targett
An expression containing a side effect.
void do_prob_uniform(const exprt &lhs, const symbol_exprt &function, const exprt::operandst &arguments, goto_programt &dest)
const memberst & members() const
void do_prob_coin(const exprt &lhs, const symbol_exprt &function, const exprt::operandst &arguments, goto_programt &dest)
const typet & element_type() const
The type of the elements of the array.
static instructiont make_atomic_end(const source_locationt &l=source_locationt::nil())
Data structure for representing an arbitrary statement in a program.
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
void make_temp_symbol(exprt &expr, const std::string &suffix, goto_programt &, const irep_idt &mode)