48 if(expr.
id()==ID_already_typechecked)
66 if(expr.
id()==ID_div ||
71 if(expr.
type().
id()==ID_floatbv &&
80 expr.
id(ID_floatbv_div);
81 else if(expr.
id()==ID_mult)
82 expr.
id(ID_floatbv_mult);
83 else if(expr.
id()==ID_plus)
84 expr.
id(ID_floatbv_plus);
85 else if(expr.
id()==ID_minus)
86 expr.
id(ID_floatbv_minus);
107 if(type1.
id()==ID_c_enum_tag)
109 else if(type2.
id()==ID_c_enum_tag)
112 if(type1.
id()==ID_c_enum)
114 if(type2.
id()==ID_c_enum)
119 else if(type2.
id()==ID_c_enum)
124 else if(type1.
id()==ID_pointer &&
125 type2.
id()==ID_pointer)
130 else if(type1.
id()==ID_array &&
131 type2.
id()==ID_array)
137 else if(type1.
id()==ID_code &&
151 for(std::size_t i=0; i<c_type1.
parameters().size(); i++)
167 if(type1.
get(ID_C_c_type)==type2.
get(ID_C_c_type))
177 if(expr.
id()==ID_side_effect)
181 else if(expr.
id()==ID_infinity)
185 else if(expr.
id()==ID_symbol)
187 else if(expr.
id()==ID_unary_plus ||
188 expr.
id()==ID_unary_minus ||
189 expr.
id()==ID_bitnot)
191 else if(expr.
id()==ID_not)
194 expr.
id() == ID_and || expr.
id() == ID_or || expr.
id() == ID_implies ||
197 else if(expr.
id()==ID_address_of)
199 else if(expr.
id()==ID_dereference)
201 else if(expr.
id()==ID_member)
203 else if(expr.
id()==ID_ptrmember)
205 else if(expr.
id()==ID_equal ||
206 expr.
id()==ID_notequal ||
212 else if(expr.
id()==ID_index)
214 else if(expr.
id()==ID_typecast)
216 else if(expr.
id()==ID_sizeof)
218 else if(expr.
id()==ID_alignof)
221 expr.
id() == ID_plus || expr.
id() == ID_minus || expr.
id() == ID_mult ||
222 expr.
id() == ID_div || expr.
id() == ID_mod || expr.
id() == ID_bitand ||
223 expr.
id() == ID_bitxor || expr.
id() == ID_bitor || expr.
id() == ID_bitnand)
227 else if(expr.
id()==ID_shl || expr.
id()==ID_shr)
229 else if(expr.
id()==ID_comma)
231 else if(expr.
id()==ID_if)
233 else if(expr.
id()==ID_code)
236 error() <<
"typecheck_expr_main got code: " << expr.
pretty() <<
eom;
239 else if(expr.
id()==ID_gcc_builtin_va_arg)
241 else if(expr.
id()==ID_cw_va_arg_typeof)
243 else if(expr.
id()==ID_gcc_builtin_types_compatible_p)
254 subtypes[0].
remove(ID_C_constant);
255 subtypes[0].remove(ID_C_volatile);
256 subtypes[0].remove(ID_C_restricted);
257 subtypes[1].remove(ID_C_constant);
258 subtypes[1].remove(ID_C_volatile);
259 subtypes[1].remove(ID_C_restricted);
264 else if(expr.
id()==ID_clang_builtin_convertvector)
273 else if(expr.
id()==ID_builtin_offsetof)
275 else if(expr.
id()==ID_string_constant)
278 expr.
set(ID_C_lvalue,
true);
280 else if(expr.
id()==ID_arguments)
284 else if(expr.
id()==ID_designated_initializer)
286 exprt &designator=
static_cast<exprt &
>(expr.
add(ID_designator));
290 if(it->id()==ID_index)
294 else if(expr.
id()==ID_initializer_list)
300 expr.
id() == ID_forall || expr.
id() == ID_exists || expr.
id() == ID_lambda)
306 auto &bindings = binary_expr.op0().operands();
307 auto &where = binary_expr.op1();
309 for(
const auto &binding : bindings)
311 if(binding.get(ID_statement) != ID_decl)
314 error() <<
"expected declaration as operand of quantifier" <<
eom;
321 [&](
const exprt &subexpr)
328 error() <<
"quantifier must not contain function calls" <<
eom;
333 for(
auto &binding : bindings)
336 if(expr.
id() == ID_lambda)
340 for(
auto &binding : bindings)
341 domain.push_back(binding.type());
351 else if(expr.
id()==ID_label)
355 else if(expr.
id()==ID_array)
359 else if(expr.
id()==ID_complex)
364 else if(expr.
id() == ID_complex_real)
368 if(op.
type().
id() != ID_complex)
373 error() <<
"real part retrieval expects numerical operand, "
381 expr.
swap(complex_real_expr);
389 complex_real_expr.
set(ID_C_lvalue,
true);
392 complex_real_expr.
type().
set(ID_C_constant,
true);
394 expr.
swap(complex_real_expr);
397 else if(expr.
id() == ID_complex_imag)
401 if(op.
type().
id() != ID_complex)
406 error() <<
"real part retrieval expects numerical operand, "
414 expr.
swap(complex_imag_expr);
422 complex_imag_expr.
set(ID_C_lvalue,
true);
425 complex_imag_expr.
type().
set(ID_C_constant,
true);
427 expr.
swap(complex_imag_expr);
430 else if(expr.
id()==ID_generic_selection)
447 for(
auto &irep : generic_associations)
449 if(irep.get(ID_type_arg) != ID_default)
451 typet &type =
static_cast<typet &
>(irep.add(ID_type_arg));
460 const typet &op_type = op.type();
462 for(
const auto &irep : generic_associations)
464 if(irep.get(ID_type_arg) == ID_default)
465 default_match =
static_cast<const exprt &
>(irep.find(ID_value));
466 else if(op_type ==
static_cast<const typet &
>(irep.find(ID_type_arg)))
468 assoc_match =
static_cast<const exprt &
>(irep.find(ID_value));
475 expr.
swap(default_match);
479 error() <<
"unmatched generic selection: " <<
to_string(op.type())
485 expr.
swap(assoc_match);
490 else if(expr.
id()==ID_gcc_asm_input ||
491 expr.
id()==ID_gcc_asm_output ||
492 expr.
id()==ID_gcc_asm_clobbered_register)
495 else if(expr.
id()==ID_lshr || expr.
id()==ID_ashr ||
496 expr.
id()==ID_assign_lshr || expr.
id()==ID_assign_ashr)
501 expr.
id() == ID_C_spec_assigns || expr.
id() == ID_C_spec_frees ||
502 expr.
id() == ID_target_list)
513 exprt tmp = bit_cast_expr->lower();
519 error() <<
"bit cast from '" <<
to_string(bit_cast_expr->op().type())
538 expr.
set(ID_C_lvalue,
true);
546 auto type_not_permitted = [
this](
const exprt &expr)
551 <<
"' not permitted for va_arg" <<
eom;
561 if(components.size() != 5)
562 type_not_permitted(expr);
564 else if(arg.
type().
id() != ID_pointer && arg.
type().
id() != ID_array)
565 type_not_permitted(expr);
589 symbolt symbol{ID_gcc_builtin_va_arg, symbol_type, ID_C};
619 error() <<
"builtin_offsetof expects no operands" <<
eom;
626 const exprt &member =
static_cast<const exprt &
>(expr.
add(ID_designator));
630 for(
const auto &op : member.
operands())
632 if(op.id() == ID_member)
634 if(type.
id() != ID_union_tag && type.
id() != ID_struct_tag)
637 error() <<
"offsetof of member expects struct/union type, "
643 irep_idt component_name = op.get(ID_component_name);
657 if(type.
id() == ID_struct_tag)
662 if(!o_opt.has_value())
665 error() <<
"offsetof failed to determine offset of '"
666 << component_name <<
"'" <<
eom;
682 for(
const auto &c : struct_union_type.
components())
686 (c.type().id() == ID_struct_tag || c.type().id() == ID_union_tag))
690 if(type.
id() == ID_struct_tag)
695 if(!o_opt.has_value())
698 error() <<
"offsetof failed to determine offset of '"
699 << component_name <<
"'" <<
eom;
709 typet tmp = c.type();
712 type.
id() == ID_union_tag || type.
id() == ID_struct_tag);
722 error() <<
"offset-of of member failed to find component '"
723 << component_name <<
"' in '" <<
to_string(type) <<
"'"
730 else if(op.id() == ID_index)
732 if(type.
id()!=ID_array)
735 error() <<
"offsetof of index expects array type" <<
eom;
744 auto element_size_opt =
747 if(!element_size_opt.has_value())
750 error() <<
"offsetof failed to determine array element size" <<
eom;
773 if(expr.
id()==ID_side_effect &&
774 expr.
get(ID_statement)==ID_function_call)
779 else if(expr.
id()==ID_side_effect &&
780 expr.
get(ID_statement)==ID_statement_expression)
785 expr.
id() == ID_forall || expr.
id() == ID_exists || expr.
id() == ID_lambda)
791 auto &bindings = binary_expr.op0().operands();
793 for(
auto &binding : bindings)
802 error() <<
"forall/exists expects one declarator exactly" <<
eom;
809 symbol_table_baset::symbolst::const_iterator s_it =
815 error() <<
"failed to find bound symbol `" << identifier
816 <<
"' in symbol table" <<
eom;
820 const symbolt &symbol = s_it->second;
827 error() <<
"unexpected quantified symbol" <<
eom;
851 id_type_mapt::const_iterator p_it=
parameter_map.find(identifier);
855 expr.
type()=p_it->second;
856 expr.
set(ID_C_lvalue,
true);
861 asm_label_mapt::const_iterator entry=
865 identifier=entry->second;
871 if(
lookup(identifier, symbol_ptr))
874 error() <<
"failed to find symbol '" << identifier <<
"'" <<
eom;
878 const symbolt &symbol=*symbol_ptr;
883 error() <<
"did not expect a type symbol here, but got '"
902 expr.
set(ID_C_cformat, base_name);
917 else if(identifier==
"__func__" ||
918 identifier==
"__FUNCTION__" ||
919 identifier==
"__PRETTY_FUNCTION__")
925 s.
set(ID_C_lvalue,
true);
936 expr.
set(ID_C_lvalue,
true);
938 if(expr.
type().
id()==ID_code)
941 tmp.
set(ID_C_implicit,
true);
960 if(last_statement==ID_expression)
966 if(op.
type().
id()==ID_array)
1008 if(type.
id()==ID_c_bit_field)
1012 if(op.
id() == ID_comma || op.
id() == ID_side_effect)
1019 config.ansi_c.char_width,
1026 if(!size_of_opt.has_value())
1029 error() <<
"type has no size: "
1034 new_expr = size_of_opt.value();
1040 error() <<
"sizeof cannot be applied to bit fields" <<
eom;
1044 else if(type.
id() == ID_bool)
1047 error() <<
"sizeof cannot be applied to single bits" <<
eom;
1050 else if(type.
id() == ID_empty)
1059 (type.
id() == ID_struct_tag &&
1061 (type.
id() == ID_union_tag &&
1063 (type.
id() == ID_c_enum_tag &&
1068 error() <<
"invalid application of \'sizeof\' to an incomplete type\n\t\'"
1075 if(!size_of_opt.has_value())
1082 new_expr = size_of_opt.value();
1086 new_expr.
swap(expr);
1088 expr.
add(ID_C_c_sizeof_type)=type;
1094 ID_statement_expression,
void_type(), location);
1096 decl_block.set_statement(ID_decl_block);
1109 expr.
swap(comma_expr);
1115 typet argument_type;
1123 argument_type=op_type;
1147 decl_block.set_statement(ID_decl_block);
1158 std::move(side_effect_expr), ID_comma, op, op.
type()};
1159 op.
swap(comma_expr);
1165 expr_type.
id() == ID_union_tag && expr_type != op.
type() &&
1166 op.
id() != ID_initializer_list)
1179 for(
const auto &c : union_type.components())
1181 if(c.type() == op.
type())
1187 expr.
set(ID_C_lvalue,
true);
1195 <<
"' not found in union" <<
eom;
1202 if(op.
id()==ID_initializer_list)
1211 exprt tmp(ID_compound_literal, expr.
type());
1215 if(op.
id()==ID_array &&
1216 expr.
type().
id()==ID_array &&
1221 expr.
set(ID_C_lvalue,
true);
1226 if(expr_type.
id()==ID_empty)
1232 if(expr_type == op_type)
1237 if(expr_type.
id()==ID_vector)
1240 if(op_type.
id()==ID_vector)
1242 else if(op_type.
id()==ID_signedbv ||
1243 op_type.
id()==ID_unsignedbv)
1250 error() <<
"type cast to '" <<
to_string(expr_type) <<
"' is not permitted"
1258 else if(op_type.
id()==ID_array)
1263 if(error_opt.has_value())
1269 else if(op_type.
id()==ID_empty)
1271 if(expr_type.
id()!=ID_empty)
1274 error() <<
"type cast from void only permitted to void, but got '"
1279 else if(op_type.
id()==ID_vector)
1286 if((expr_type.
id()==ID_signedbv ||
1287 expr_type.
id()==ID_unsignedbv) &&
1296 <<
"' not permitted" <<
eom;
1303 error() <<
"type cast from '" <<
to_string(op_type) <<
"' not permitted"
1319 if(expr_type.
id()==ID_pointer)
1320 expr.
set(ID_C_lvalue,
true);
1337 const typet &array_type = array_expr.
type();
1338 const typet &index_type = index_expr.
type();
1341 array_type.
id() != ID_array && array_type.
id() != ID_pointer &&
1342 array_type.
id() != ID_vector &&
1343 (index_type.
id() == ID_array || index_type.
id() == ID_pointer ||
1344 index_type.
id() == ID_vector))
1345 std::swap(array_expr, index_expr);
1353 const typet final_array_type = array_expr.
type();
1355 if(final_array_type.
id()==ID_array ||
1356 final_array_type.
id()==ID_vector)
1360 if(array_expr.
get_bool(ID_C_lvalue))
1361 expr.
set(ID_C_lvalue,
true);
1363 if(final_array_type.
get_bool(ID_C_constant))
1364 expr.
type().
set(ID_C_constant,
true);
1366 else if(final_array_type.
id()==ID_pointer)
1372 std::swap(summands, expr.
operands());
1374 expr.
id(ID_dereference);
1375 expr.
set(ID_C_lvalue,
true);
1381 error() <<
"operator [] must take array/vector or pointer but got '"
1390 if(expr.
op0().
type().
id() == ID_floatbv)
1392 if(expr.
id()==ID_equal)
1393 expr.
id(ID_ieee_float_equal);
1394 else if(expr.
id()==ID_notequal)
1395 expr.
id(ID_ieee_float_notequal);
1408 if(o_type0.
id() == ID_vector || o_type1.
id() == ID_vector)
1416 if(expr.
id()==ID_equal || expr.
id()==ID_notequal)
1418 if(o_type0 == o_type1)
1420 if(o_type0.
id() != ID_array)
1441 if(type0.
id()==ID_pointer)
1443 if(expr.
id()==ID_equal || expr.
id()==ID_notequal)
1446 if(expr.
id()==ID_le || expr.
id()==ID_lt ||
1447 expr.
id()==ID_ge || expr.
id()==ID_gt)
1451 if(type0.
id()==ID_string_constant)
1453 if(expr.
id()==ID_equal || expr.
id()==ID_notequal)
1485 if(type0.
id()==ID_pointer && type1.
id()==ID_pointer)
1493 error() <<
"operator '" << expr.
id() <<
"' not defined for types '"
1504 if(o_type0.
id() != ID_vector || o_type0 != o_type1)
1507 error() <<
"vector operator '" << expr.
id() <<
"' not defined for types '"
1515 auto subtype_width =
1524 if(expr.
id() == ID_notequal)
1525 expr.
id(ID_vector_notequal);
1533 const typet &op0_type = op.type();
1535 if(op0_type.
id() == ID_array)
1540 index_expr.
set(ID_C_lvalue,
true);
1541 op.swap(index_expr);
1543 else if(op0_type.
id() == ID_pointer)
1554 error() <<
"ptrmember operator requires pointer or array type "
1555 "on left hand side, but got '"
1569 if(type.
id() != ID_struct_tag && type.
id() != ID_union_tag)
1572 error() <<
"member operator requires structure type "
1573 "on left hand side but got '"
1584 error() <<
"member operator got incomplete " << type.
id()
1585 <<
" type on left hand side" <<
eom;
1590 expr.
get(ID_component_name);
1606 error() <<
"member '" << component_name <<
"' not found in '"
1619 expr.
set(ID_C_lvalue,
true);
1623 struct_union_type.
get_bool(ID_C_constant))
1625 expr.
type().
set(ID_C_constant,
true);
1631 if(!identifier.
empty())
1632 expr.
set(ID_C_identifier, identifier);
1636 if(access==ID_private)
1639 error() <<
"member '" << component_name <<
"' is " << access <<
eom;
1651 const typet o_type0=operands[0].type();
1652 const typet o_type1=operands[1].type();
1653 const typet o_type2=operands[2].type();
1657 if(o_type1.
id() == ID_empty || o_type2.
id() == ID_empty)
1677 if(operands[1].type().
id()==ID_pointer &&
1678 operands[2].type().
id()!=ID_pointer)
1680 else if(operands[2].type().
id()==ID_pointer &&
1681 operands[1].type().
id()!=ID_pointer)
1684 if(operands[1].type().
id()==ID_pointer &&
1685 operands[2].type().
id()==ID_pointer &&
1686 operands[1].type()!=operands[2].type())
1733 if(operands[1].type().
id()==ID_empty ||
1734 operands[2].type().
id()==ID_empty)
1741 operands[1].type() != operands[2].type() ||
1742 operands[1].type().
id() == ID_array)
1747 if(operands[1].type() == operands[2].type())
1749 expr.
type()=operands[1].type();
1755 if(operands[1].get_bool(ID_C_lvalue) &&
1756 operands[2].get_bool(ID_C_lvalue))
1757 expr.
set(ID_C_lvalue,
true);
1763 error() <<
"operator ?: not defined for types '" <<
to_string(o_type1)
1776 if(operands.size()!=2)
1779 error() <<
"gcc conditional_expr expects two operands" <<
eom;
1785 if_exprt if_expr(operands[0], operands[0], operands[1]);
1802 if(error_opt.has_value())
1806 if(op.
id()==ID_label)
1819 op.
id() == ID_address_of && op.
get_bool(ID_C_implicit) &&
1825 tmp.
set(ID_C_implicit,
false);
1830 if(op.
id()==ID_struct ||
1831 op.
id()==ID_union ||
1832 op.
id()==ID_array ||
1833 op.
id()==ID_string_constant)
1841 else if(op.
type().
id()==ID_code)
1848 error() <<
"address_of error: '" <<
to_string(op) <<
"' not an lvalue"
1862 if(op_type.
id()==ID_array)
1870 else if(op_type.
id()==ID_pointer)
1875 expr.
type().
id() == ID_empty &&
1879 error() <<
"dereferencing void pointer" <<
eom;
1887 <<
"' is not a pointer, but got '" <<
to_string(op_type) <<
"'"
1892 expr.
set(ID_C_lvalue,
true);
1903 if(expr.
type().
id()==ID_code)
1906 tmp.
set(ID_C_implicit,
true);
1916 if(statement==ID_preincrement ||
1917 statement==ID_predecrement ||
1918 statement==ID_postincrement ||
1919 statement==ID_postdecrement)
1928 <<
"' not an lvalue" <<
eom;
1939 if(type0.
id() == ID_c_enum_tag)
1945 error() <<
"operator '" << statement <<
"' given incomplete type '"
1955 else if(type0.
id() == ID_c_bit_field)
1959 typet type_before{type0};
1961 expr.
type()=underlying_type;
1965 else if(type0.
id() == ID_bool || type0.
id() == ID_c_bool)
1974 else if(type0.
id() == ID_pointer)
1982 error() <<
"operator '" << statement <<
"' not defined for type '"
1989 else if(statement==ID_function_call)
1992 else if(statement==ID_statement_expression)
1994 else if(statement==ID_gcc_conditional_expression)
1999 error() <<
"unknown side effect: " << statement <<
eom;
2011 "expression must be a " CPROVER_PREFIX "typed_target function call");
2018 "expected 1 argument for " CPROVER_PREFIX "typed_target, found " +
2019 std::to_string(expr.
arguments().size()),
2029 arg0.source_location()};
2033 if(!size.has_value())
2037 "typed_target of type " +
2039 arg0.source_location()};
2048 arguments.push_back(size.value());
2050 if(arg0.type().id() == ID_pointer)
2066 "expression must be a " CPROVER_PREFIX "obeys_contract function call");
2071 "expected 2 arguments for " CPROVER_PREFIX "obeys_contract, found " +
2072 std::to_string(expr.
arguments().size()),
2078 auto &function_pointer = expr.
arguments()[0];
2081 function_pointer.type().id() != ID_pointer ||
2082 to_pointer_type(function_pointer.type()).base_type().id() != ID_code ||
2083 !function_pointer.get_bool(ID_C_lvalue))
2087 "obeys_contract must be a function pointer lvalue expression",
2088 function_pointer.source_location());
2095 "obeys_contract must have no ternary operator",
2096 function_pointer.source_location());
2100 auto &address_of_contract = expr.
arguments()[1];
2103 address_of_contract.id() != ID_address_of ||
2105 address_of_contract.type().id() != ID_pointer ||
2106 to_pointer_type(address_of_contract.type()).base_type().id() != ID_code)
2110 "obeys_contract must must be a function symbol",
2111 address_of_contract.source_location());
2114 if(function_pointer.type() != address_of_contract.type())
2118 "obeys_contract must have the same function pointer type",
2127 return ::builtin_factory(
2129 config.ansi_c.float16_type,
2140 error() <<
"function_call side effect expects two operands" <<
eom;
2149 if(f_op.
id()==ID_symbol)
2153 asm_label_mapt::const_iterator entry=
2156 identifier=entry->second;
2173 identifier ==
"__noop" &&
2187 identifier ==
"__builtin_nondeterministic_value" &&
2198 error() <<
"__builtin_nondeterministic_value expects one operand"
2211 identifier ==
"__builtin_shuffle" &&
2219 else if(identifier ==
"__builtin_shufflevector")
2229 identifier ==
"__builtin_elementwise_add_sat" ||
2230 identifier ==
"__builtin_elementwise_sub_sat")
2242 error() <<
"equal expects two operands" <<
eom;
2253 error() <<
"equal expects two operands of same type" <<
eom;
2257 expr.
swap(equality_expr);
2271 overflow.
id(ID_minus);
2276 overflow.
id(ID_mult);
2281 overflow.
id(ID_plus);
2286 overflow.
id(ID_shl);
2305 expr.
swap(overflow);
2313 std::ostringstream error_message;
2314 error_message << identifier <<
" takes exactly 1 argument, but "
2315 << expr.
arguments().size() <<
" were provided";
2323 std::ostringstream error_message;
2324 error_message << identifier <<
" expects enum, but ("
2325 <<
expr2c(arg1, *
this) <<
") has type `"
2326 <<
type2c(arg1.type(), *
this) <<
'`';
2345 id2string(identifier) +
" expects one or two operands",
2350 auto &pointer_expr = expr.
arguments()[0];
2351 if(pointer_expr.type().id() == ID_array)
2354 dest_type.base_type().set(ID_C_constant,
true);
2357 else if(pointer_expr.type().id() != ID_pointer)
2360 id2string(identifier) +
" expects a pointer as first argument",
2376 const auto &subtype =
2378 if(subtype.id() == ID_empty)
2382 " expects a size when given a void pointer",
2388 size_expr = std::move(size_expr_opt.value());
2404 irep_idt shadow_memory_builtin_id =
2405 shadow_memory_builtin->get_identifier();
2407 const auto builtin_code_type =
2411 builtin_code_type.has_ellipsis() &&
2412 builtin_code_type.parameters().empty(),
2413 "Shadow memory builtins should be an ellipsis with 0 parameter");
2419 shadow_memory_builtin_id, shadow_memory_builtin->type(), ID_C};
2420 new_symbol.
base_name = shadow_memory_builtin_id;
2431 f_op = std::move(*shadow_memory_builtin);
2437 irep_idt identifier_with_type = gcc_polymorphic->get_identifier();
2440 !parameters.empty(),
2441 "GCC polymorphic built-ins should have at least one parameter");
2446 if(parameters.front().type().id() == ID_pointer)
2448 identifier_with_type =
2455 identifier_with_type =
2459 gcc_polymorphic->set_identifier(identifier_with_type);
2463 for(std::size_t i = 0; i < parameters.size(); ++i)
2465 const std::string base_name =
"p_" + std::to_string(i);
2470 id2string(identifier_with_type) +
"::" + base_name;
2473 new_symbol.
type = parameters[i].type();
2476 new_symbol.
mode = ID_C;
2478 parameters[i].set_identifier(new_symbol.
name);
2479 parameters[i].set_base_name(new_symbol.
base_name);
2485 identifier_with_type, gcc_polymorphic->type(), ID_C};
2486 new_symbol.
base_name = identifier_with_type;
2494 new_symbol.
value = implementation;
2499 f_op = std::move(*gcc_polymorphic);
2511 if(identifier==
"malloc" ||
2512 identifier==
"realloc" ||
2513 identifier==
"reallocf" ||
2514 identifier==
"valloc")
2523 new_symbol.
type.
set(ID_C_incomplete,
true);
2535 debug() <<
"builtin '" << identifier <<
"' is unknown" <<
eom;
2540 warning() <<
"function '" << identifier <<
"' is not declared" <<
eom;
2551 if(f_op_type.
id() == ID_mathematical_function)
2553 const auto &mathematical_function_type =
2557 if(expr.
arguments().size() != mathematical_function_type.domain().size())
2560 error() <<
"expected " << mathematical_function_type.domain().size()
2561 <<
" arguments but got " << expr.
arguments().size() <<
eom;
2569 if(p.first.type() != p.second)
2582 expr.
swap(function_application);
2586 if(f_op_type.
id()!=ID_pointer)
2589 error() <<
"expected function/function pointer as argument but got '"
2595 if(f_op.
id() == ID_address_of && f_op.
get_bool(ID_C_implicit))
2602 tmp.
set(ID_C_implicit,
true);
2607 if(f_op.
type().
id()!=ID_code)
2610 error() <<
"expected code as argument" <<
eom;
2633 if(f_op.
id()!=ID_symbol)
2681 if(arg.type().id() != ID_pointer)
2685 "pointer_in_range_dfcc expects pointer-typed arguments",
2686 arg.source_location()};
2696 error() <<
"same_object expects two operands" <<
eom;
2702 exprt same_object_expr=
2706 return same_object_expr;
2713 error() <<
"get_must expects two operands" <<
eom;
2723 return std::move(get_must_expr);
2730 error() <<
"get_may expects two operands" <<
eom;
2740 return std::move(get_may_expr);
2747 error() <<
"is_invalid_pointer expects one operand" <<
eom;
2756 return same_object_expr;
2763 error() <<
"buffer_size expects one operand" <<
eom;
2773 return buffer_size_expr;
2781 error() <<
"is_list expects one operand" <<
eom;
2788 expr.
arguments()[0].type().id() != ID_pointer ||
2793 error() <<
"is_list expects a struct-pointer operand" <<
eom;
2801 return std::move(is_list_expr);
2809 error() <<
"is_dll expects one operand" <<
eom;
2816 expr.
arguments()[0].type().id() != ID_pointer ||
2821 error() <<
"is_dll expects a struct-pointer operand" <<
eom;
2829 return std::move(is_dll_expr);
2837 error() <<
"is_cyclic_dll expects one operand" <<
eom;
2844 expr.
arguments()[0].type().id() != ID_pointer ||
2849 error() <<
"is_cyclic_dll expects a struct-pointer operand" <<
eom;
2857 return std::move(is_cyclic_dll_expr);
2865 error() <<
"is_sentinel_dll expects two or three operands" <<
eom;
2872 args_no_cast.reserve(expr.
arguments().size());
2873 for(
const auto &argument : expr.
arguments())
2877 args_no_cast.back().type().id() != ID_pointer ||
2882 error() <<
"is_sentinel_dll_node expects struct-pointer operands"
2889 is_sentinel_dll_expr.
operands() = args_no_cast;
2892 return std::move(is_sentinel_dll_expr);
2900 error() <<
"is_cstring expects one operand" <<
eom;
2906 if(expr.
arguments()[0].type().id() != ID_pointer)
2909 error() <<
"is_cstring expects a pointer operand" <<
eom;
2916 return std::move(is_cstring_expr);
2924 error() <<
"cstrlen expects one operand" <<
eom;
2930 if(expr.
arguments()[0].type().id() != ID_pointer)
2933 error() <<
"cstrlen expects a pointer operand" <<
eom;
2940 return std::move(cstrlen_expr);
2947 error() <<
"is_zero_string expects one operand" <<
eom;
2955 is_zero_string_expr.
set(ID_C_lvalue,
true);
2958 return std::move(is_zero_string_expr);
2965 error() <<
"zero_string_length expects one operand" <<
eom;
2971 exprt zero_string_length_expr(
"zero_string_length",
size_type());
2973 zero_string_length_expr.
set(ID_C_lvalue,
true);
2976 return zero_string_length_expr;
2983 error() <<
"dynamic_object expects one argument" <<
eom;
2992 return is_dynamic_object_expr;
2999 error() <<
"live_object expects one argument" <<
eom;
3008 return live_object_expr;
3015 error() <<
"pointer_in_range expects three arguments" <<
eom;
3025 return pointer_in_range_expr;
3032 error() <<
"writeable_object expects one argument" <<
eom;
3041 return writeable_object_expr;
3049 error() <<
"separate expects two or more arguments" <<
eom;
3058 return separate_expr;
3065 error() <<
"pointer_offset expects one argument" <<
eom;
3081 error() <<
"object_size expects one operand" <<
eom;
3090 return std::move(object_size_expr);
3097 error() <<
"pointer_object expects one argument" <<
eom;
3108 else if(identifier==
"__builtin_bswap16" ||
3109 identifier==
"__builtin_bswap32" ||
3110 identifier==
"__builtin_bswap64")
3115 error() << identifier <<
" expects one operand" <<
eom;
3125 return std::move(bswap_expr);
3128 identifier ==
"__builtin_rotateleft8" ||
3129 identifier ==
"__builtin_rotateleft16" ||
3130 identifier ==
"__builtin_rotateleft32" ||
3131 identifier ==
"__builtin_rotateleft64" ||
3132 identifier ==
"__builtin_rotateright8" ||
3133 identifier ==
"__builtin_rotateright16" ||
3134 identifier ==
"__builtin_rotateright32" ||
3135 identifier ==
"__builtin_rotateright64")
3141 error() << identifier <<
" expects two operands" <<
eom;
3147 irep_idt id = (identifier ==
"__builtin_rotateleft8" ||
3148 identifier ==
"__builtin_rotateleft16" ||
3149 identifier ==
"__builtin_rotateleft32" ||
3150 identifier ==
"__builtin_rotateleft64")
3157 return std::move(rotate_expr);
3159 else if(identifier==
"__builtin_nontemporal_load")
3164 error() << identifier <<
" expects one operand" <<
eom;
3173 if(ptr_arg.
type().
id()!=ID_pointer)
3176 error() <<
"__builtin_nontemporal_load takes pointer as argument" <<
eom;
3185 identifier ==
"__builtin_fpclassify" ||
3191 error() << identifier <<
" expects six arguments" <<
eom;
3204 if(fp_value.
type().
id() != ID_floatbv)
3207 error() <<
"non-floating-point argument for " << identifier <<
eom;
3215 const auto &arguments = expr.
arguments();
3234 identifier==
"__builtin_isnan")
3239 error() <<
"isnan expects one operand" <<
eom;
3257 error() <<
"isfinite expects one operand" <<
eom;
3269 identifier ==
CPROVER_PREFIX "inf" || identifier ==
"__builtin_inf" ||
3270 identifier ==
"__builtin_huge_val")
3277 return std::move(inf_expr);
3280 identifier ==
CPROVER_PREFIX "inff" || identifier ==
"__builtin_inff" ||
3281 identifier ==
"__builtin_huge_valf")
3288 return std::move(inff_expr);
3291 identifier ==
CPROVER_PREFIX "infl" || identifier ==
"__builtin_infl" ||
3292 identifier ==
"__builtin_huge_vall")
3299 return std::move(infl_expr);
3309 error() << identifier <<
" expects two arguments" <<
eom;
3313 auto round_to_integral_expr =
3317 return std::move(round_to_integral_expr);
3330 error() <<
"abs-functions expect one operand" <<
eom;
3339 return std::move(abs_expr);
3349 error() <<
"fmod-functions expect two operands" <<
eom;
3363 return std::move(fmod_expr);
3373 error() <<
"remainder-functions expect two operands" <<
eom;
3387 return std::move(floatbv_rem_expr);
3396 error() <<
"fma-functions expect three operands" <<
eom;
3405 ID_floatbv_fma, expr.
arguments(), std::move(result_type));
3409 return std::move(fma_expr);
3416 error() <<
"allocate expects two operands" <<
eom;
3425 return std::move(malloc_expr);
3434 error() << identifier <<
" expects one operand" <<
eom;
3438 const auto ¶m_id = expr.
arguments().front().id();
3439 if(!(param_id == ID_dereference || param_id == ID_member ||
3440 param_id == ID_symbol || param_id == ID_ptrmember ||
3441 param_id == ID_constant || param_id == ID_typecast ||
3442 param_id == ID_index))
3445 error() <<
"Tracking history of " << param_id
3446 <<
" expressions is not supported yet." <<
eom;
3455 return std::move(old_expr);
3460 identifier==
"__builtin_isinf")
3465 error() << identifier <<
" expects one operand" <<
eom;
3473 if(fp_value.
type().
id() != ID_floatbv)
3476 error() <<
"non-floating-point argument for " << identifier <<
eom;
3485 else if(identifier ==
"__builtin_isinf_sign")
3490 error() << identifier <<
" expects one operand" <<
eom;
3500 if(fp_value.
type().
id() != ID_floatbv)
3503 error() <<
"non-floating-point argument for " << identifier <<
eom;
3521 identifier ==
"__builtin_isnormal")
3526 error() << identifier <<
" expects one operand" <<
eom;
3534 if(fp_value.
type().
id() != ID_floatbv)
3537 error() <<
"non-floating-point argument for " << identifier <<
eom;
3549 identifier==
"__builtin_signbit" ||
3550 identifier==
"__builtin_signbitf" ||
3551 identifier==
"__builtin_signbitl")
3556 error() << identifier <<
" expects one operand" <<
eom;
3567 else if(identifier==
"__builtin_popcount" ||
3568 identifier==
"__builtin_popcountl" ||
3569 identifier==
"__builtin_popcountll" ||
3570 identifier==
"__popcnt16" ||
3571 identifier==
"__popcnt" ||
3572 identifier==
"__popcnt64")
3577 error() << identifier <<
" expects one operand" <<
eom;
3586 return std::move(popcount_expr);
3589 identifier ==
"__builtin_clz" || identifier ==
"__builtin_clzl" ||
3590 identifier ==
"__builtin_clzll" || identifier ==
"__lzcnt16" ||
3591 identifier ==
"__lzcnt" || identifier ==
"__lzcnt64")
3596 error() << identifier <<
" expects one operand" <<
eom;
3606 return std::move(clz);
3609 identifier ==
"__builtin_ctz" || identifier ==
"__builtin_ctzl" ||
3610 identifier ==
"__builtin_ctzll")
3615 error() << identifier <<
" expects one operand" <<
eom;
3625 return std::move(ctz);
3628 identifier ==
"__builtin_ffs" || identifier ==
"__builtin_ffsl" ||
3629 identifier ==
"__builtin_ffsll")
3634 error() << identifier <<
" expects one operand" <<
eom;
3643 return std::move(ffs);
3645 else if(identifier==
"__builtin_expect")
3656 error() <<
"__builtin_expect expects two arguments" <<
eom;
3665 identifier ==
"__builtin_object_size" ||
3666 identifier ==
"__builtin_dynamic_object_size")
3677 error() <<
"__builtin_object_size expects two arguments" <<
eom;
3694 error() <<
"__builtin_object_size expects constant as second argument, "
3702 if(arg1==0 || arg1==1)
3715 else if(identifier==
"__builtin_choose_expr")
3721 error() <<
"__builtin_choose_expr expects three arguments" <<
eom;
3736 else if(identifier==
"__builtin_constant_p")
3743 error() <<
"__builtin_constant_p expects one argument" <<
eom;
3759 tmp1.
id() == ID_typecast &&
3765 .
id() == ID_string_constant)
3777 else if(identifier==
"__builtin_classify_type")
3784 error() <<
"__builtin_classify_type expects one argument" <<
eom;
3795 const typet &type =
object.type().
id() == ID_c_bit_field
3799 unsigned type_number;
3801 if(type.
id() == ID_bool || type.
id() == ID_c_bool)
3809 type_number = type.
id() == ID_empty ? 0u
3810 : (type.
id() == ID_bool || type.
id() == ID_c_bool) ? 4u
3811 : (type.
id() == ID_pointer || type.
id() == ID_array) ? 5u
3812 : type.
id() == ID_floatbv ? 8u
3813 : (type.
id() == ID_complex &&
3816 : type.
id() == ID_struct_tag ? 12u
3817 : type.
id() == ID_union_tag
3828 identifier ==
"__builtin_add_overflow" ||
3829 identifier ==
"__builtin_sadd_overflow" ||
3830 identifier ==
"__builtin_saddl_overflow" ||
3831 identifier ==
"__builtin_saddll_overflow" ||
3832 identifier ==
"__builtin_uadd_overflow" ||
3833 identifier ==
"__builtin_uaddl_overflow" ||
3834 identifier ==
"__builtin_uaddll_overflow" ||
3835 identifier ==
"__builtin_add_overflow_p")
3840 identifier ==
"__builtin_sub_overflow" ||
3841 identifier ==
"__builtin_ssub_overflow" ||
3842 identifier ==
"__builtin_ssubl_overflow" ||
3843 identifier ==
"__builtin_ssubll_overflow" ||
3844 identifier ==
"__builtin_usub_overflow" ||
3845 identifier ==
"__builtin_usubl_overflow" ||
3846 identifier ==
"__builtin_usubll_overflow" ||
3847 identifier ==
"__builtin_sub_overflow_p")
3852 identifier ==
"__builtin_mul_overflow" ||
3853 identifier ==
"__builtin_smul_overflow" ||
3854 identifier ==
"__builtin_smull_overflow" ||
3855 identifier ==
"__builtin_smulll_overflow" ||
3856 identifier ==
"__builtin_umul_overflow" ||
3857 identifier ==
"__builtin_umull_overflow" ||
3858 identifier ==
"__builtin_umulll_overflow" ||
3859 identifier ==
"__builtin_mul_overflow_p")
3864 identifier ==
"__builtin_bitreverse8" ||
3865 identifier ==
"__builtin_bitreverse16" ||
3866 identifier ==
"__builtin_bitreverse32" ||
3867 identifier ==
"__builtin_bitreverse64")
3872 std::ostringstream error_message;
3873 error_message <<
"error: " << identifier <<
" expects one operand";
3883 return std::move(bitreverse);
3899 std::ostringstream error_message;
3900 error_message << identifier <<
" takes exactly 3 arguments, but "
3901 << expr.
arguments().size() <<
" were provided";
3915 auto const raise_wrong_argument_error =
3917 const exprt &wrong_argument, std::size_t argument_number,
bool _p) {
3918 std::ostringstream error_message;
3919 error_message <<
"error: " << identifier <<
" has signature "
3920 << identifier <<
"(integral, integral, integral"
3921 << (_p ?
"" :
"*") <<
"), "
3922 <<
"but argument " << argument_number <<
" ("
3923 <<
expr2c(wrong_argument, *
this) <<
") has type `"
3924 <<
type2c(wrong_argument.
type(), *
this) <<
'`';
3928 for(
int arg_index = 0; arg_index <= (!is__p_variant ? 1 : 2); ++arg_index)
3930 auto const &argument = expr.
arguments()[arg_index];
3934 raise_wrong_argument_error(argument, arg_index + 1, is__p_variant);
3938 !is__p_variant && (
result.type().id() != ID_pointer ||
3942 raise_wrong_argument_error(
result, 3, is__p_variant);
3961 std::ostringstream error_message;
3962 error_message <<
"error: " << identifier
3963 <<
" takes exactly two arguments, but "
3964 << expr.
arguments().size() <<
" were provided";
3972 identifier ==
"__builtin_elementwise_sub_sat")
3978 identifier ==
"__builtin_elementwise_add_sat")
4003 if(code_type.
get_bool(ID_C_incomplete))
4007 else if(code_type.
is_KnR())
4011 for(std::size_t i = arguments.size(); i < parameters.size(); ++i)
4013 arguments.push_back(
4019 if(parameters.size() > arguments.size())
4022 error() <<
"not enough function arguments" <<
eom;
4026 else if(parameters.size() != arguments.size())
4029 error() <<
"wrong number of function arguments: "
4030 <<
"expected " << parameters.size() <<
", but got "
4031 << arguments.size() <<
eom;
4035 for(std::size_t i=0; i<arguments.size(); i++)
4037 exprt &op=arguments[i];
4043 else if(i < parameters.size())
4049 op.
get(ID_statement) == ID_assign && op.
type().
id() != ID_bool)
4052 warning() <<
"assignment where Boolean argument is expected" <<
eom;
4061 if(op.
type().
id() == ID_array)
4064 dest_type.base_type().set(ID_C_constant,
true);
4082 if(o_type.
id()==ID_vector)
4101 error() <<
"operator '" << expr.
id() <<
"' not defined for type '"
4156 if(o_type0.
id()==ID_vector &&
4157 o_type1.
id()==ID_vector)
4171 o_type0.
id() == ID_vector && o_type1.
id() != ID_vector &&
4176 expr.
type() = o_type0;
4180 o_type0.
id() != ID_vector && o_type1.
id() == ID_vector &&
4185 expr.
type() = o_type1;
4189 if(expr.
id() == ID_saturating_minus || expr.
id() == ID_saturating_plus)
4202 if(expr.
id()==ID_plus || expr.
id()==ID_minus ||
4203 expr.
id()==ID_mult || expr.
id()==ID_div)
4205 if(type0.
id()==ID_pointer || type1.
id()==ID_pointer)
4210 else if(type0==type1)
4219 else if(expr.
id()==ID_mod)
4223 if(type0.
id()==ID_signedbv || type0.
id()==ID_unsignedbv)
4231 expr.
id() == ID_bitand || expr.
id() == ID_bitnand ||
4232 expr.
id() == ID_bitxor || expr.
id() == ID_bitor)
4241 else if(type0.
id()==ID_bool)
4243 if(expr.
id()==ID_bitand)
4245 else if(expr.
id() == ID_bitnand)
4247 else if(expr.
id()==ID_bitor)
4249 else if(expr.
id()==ID_bitxor)
4258 else if(expr.
id() == ID_saturating_minus || expr.
id() == ID_saturating_plus)
4262 (type0.
id() == ID_signedbv || type0.
id() == ID_unsignedbv))
4264 expr.
type() = type0;
4270 error() <<
"operator '" << expr.
id() <<
"' not defined for types '"
4286 if(o_type0.
id()==ID_vector &&
4287 o_type1.
id()==ID_vector)
4303 o_type0.
id() == ID_vector &&
4321 if(expr.
id()==ID_shr)
4325 if(op0_type.
id()==ID_unsignedbv)
4330 else if(op0_type.
id()==ID_signedbv)
4341 error() <<
"operator '" << expr.
id() <<
"' not defined for types '"
4355 base_type.
id() == ID_struct_tag &&
4359 error() <<
"pointer arithmetic with unknown object size" <<
eom;
4363 base_type.
id() == ID_union_tag &&
4367 error() <<
"pointer arithmetic with unknown object size" <<
eom;
4371 base_type.
id() == ID_empty &&
4375 error() <<
"pointer arithmetic with unknown object size" <<
eom;
4378 else if(base_type.
id() == ID_empty)
4396 if(expr.
id()==ID_minus ||
4397 (expr.
id()==ID_side_effect && expr.
get(ID_statement)==ID_assign_minus))
4399 if(type0.
id()==ID_pointer &&
4400 type1.
id()==ID_pointer)
4413 if(type0.
id()==ID_pointer &&
4414 (type1.
id()==ID_bool ||
4415 type1.
id()==ID_c_bool ||
4416 type1.
id()==ID_unsignedbv ||
4417 type1.
id()==ID_signedbv ||
4418 type1.
id()==ID_c_bit_field ||
4419 type1.
id()==ID_c_enum_tag))
4427 else if(expr.
id()==ID_plus ||
4428 (expr.
id()==ID_side_effect && expr.
get(ID_statement)==ID_assign_plus))
4430 exprt *p_op, *int_op;
4432 if(type0.
id()==ID_pointer)
4437 else if(type1.
id()==ID_pointer)
4444 p_op=int_op=
nullptr;
4448 const typet &int_op_type = int_op->
type();
4450 if(int_op_type.
id()==ID_bool ||
4451 int_op_type.
id()==ID_c_bool ||
4452 int_op_type.
id()==ID_unsignedbv ||
4453 int_op_type.
id()==ID_signedbv ||
4454 int_op_type.
id()==ID_c_bit_field ||
4455 int_op_type.
id()==ID_c_enum_tag)
4466 if(expr.
id()==ID_side_effect)
4472 error() <<
"operator '" << op_name <<
"' not defined for types '"
4503 if(type0.
id()==ID_empty)
4506 error() <<
"cannot assign void" <<
eom;
4513 error() <<
"assignment error: '" <<
to_string(op0) <<
"' not an lvalue"
4526 if(type0.
id() == ID_array)
4529 error() <<
"direct assignments to arrays not permitted" <<
eom;
4535 if(op0.
type() != op1.
type() && op0.
type().
id() == ID_c_bit_field)
4544 expr.
type()=o_type0;
4546 if(statement==ID_assign)
4551 else if(statement==ID_assign_shl ||
4552 statement==ID_assign_shr)
4554 if(o_type0.
id() == ID_vector)
4559 o_type1.
id() == ID_vector &&
4560 vector_o_type0.element_type() ==
4562 is_number(vector_o_type0.element_type()))
4578 if(statement==ID_assign_shl)
4588 if(underlying_type.
id()==ID_unsignedbv ||
4589 underlying_type.
id()==ID_c_bool)
4591 expr.
set(ID_statement, ID_assign_lshr);
4594 else if(underlying_type.
id()==ID_signedbv)
4596 expr.
set(ID_statement, ID_assign_ashr);
4602 else if(statement==ID_assign_bitxor ||
4603 statement==ID_assign_bitand ||
4604 statement==ID_assign_bitor)
4607 if(o_type0.
id()==ID_bool ||
4608 o_type0.
id()==ID_c_bool)
4613 op1.
type().
id() == ID_c_enum_tag || op1.
type().
id() == ID_unsignedbv ||
4614 op1.
type().
id() == ID_signedbv || op1.
type().
id() == ID_c_bit_field)
4619 else if(o_type0.
id()==ID_c_enum_tag ||
4620 o_type0.
id()==ID_unsignedbv ||
4621 o_type0.
id()==ID_signedbv ||
4622 o_type0.
id()==ID_c_bit_field)
4626 op1.
type().
id() == ID_c_enum_tag || op1.
type().
id() == ID_unsignedbv ||
4627 op1.
type().
id() == ID_signedbv || op1.
type().
id() == ID_c_bit_field)
4632 else if(o_type0.
id()==ID_vector &&
4633 o_type1.
id()==ID_vector)
4644 o_type0.
id() == ID_vector &&
4645 (o_type1.
id() == ID_bool || o_type1.
id() == ID_c_bool ||
4646 o_type1.
id() == ID_c_enum_tag || o_type1.
id() == ID_unsignedbv ||
4647 o_type1.
id() == ID_signedbv))
4656 if(o_type0.
id()==ID_pointer &&
4657 (statement==ID_assign_minus || statement==ID_assign_plus))
4662 else if(o_type0.
id()==ID_vector &&
4663 o_type1.
id()==ID_vector)
4673 else if(o_type0.
id() == ID_vector)
4679 op1.
type().
id() == ID_c_bool || op1.
type().
id() == ID_c_enum_tag)
4685 else if(o_type0.
id()==ID_bool ||
4686 o_type0.
id()==ID_c_bool)
4691 op1.
type().
id() == ID_c_enum_tag || op1.
type().
id() == ID_unsignedbv ||
4692 op1.
type().
id() == ID_signedbv)
4703 op1.
type().
id() == ID_c_bool || op1.
type().
id() == ID_c_enum_tag)
4711 error() <<
"assignment '" << statement <<
"' not defined for types '"
4741 if(e.
id() == ID_infinity)
4747 if(e.
id() == ID_address_of)
4752 e.
id() == ID_typecast || e.
id() == ID_array_of || e.
id() == ID_plus ||
4753 e.
id() == ID_mult || e.
id() == ID_array || e.
id() == ID_with ||
4754 e.
id() == ID_struct || e.
id() == ID_union || e.
id() == ID_empty_union ||
4755 e.
id() == ID_equal || e.
id() == ID_notequal || e.
id() == ID_lt ||
4756 e.
id() == ID_le || e.
id() == ID_gt || e.
id() == ID_ge ||
4757 e.
id() == ID_if || e.
id() == ID_not || e.
id() == ID_and ||
4758 e.
id() == ID_or || e.
id() == ID_bitnot || e.
id() == ID_bitand ||
4759 e.
id() == ID_bitor || e.
id() == ID_bitxor || e.
id() == ID_vector)
4763 return is_constant(op);
4773 if(e.
id() == ID_symbol)
4775 return e.
type().
id() == ID_code ||
4778 else if(e.
id() == ID_array && e.
get_bool(ID_C_string_constant))
4780 else if(e.
id() == ID_label)
4782 else if(e.
id() == ID_index)
4789 else if(e.
id() == ID_member)
4793 else if(e.
id() == ID_dereference)
4799 else if(e.
id() == ID_string_constant)
4813 const auto rounding_mode =
4823 error() <<
"expected constant expression, but got '" <<
to_string(expr)
4840 error() <<
"conversion to integer constant failed" <<
eom;
4848 const std::string &message)
const
void adjust_float_expressions(exprt &expr, const exprt &rounding_mode)
Replaces arithmetic operations and typecasts involving floating point numbers with their equivalent f...
bool has_component_rec(const typet &type, const irep_idt &component_name, const namespacet &ns)
exprt get_component_rec(const exprt &struct_union, const irep_idt &component_name, const namespacet &ns)
C Language Type Checking.
ANSI-CC Language Type Checking.
ansi_c_declarationt & to_ansi_c_declaration(exprt &expr)
const T & as_const(T &value)
Return a reference to the same object but ensures the type is const.
API to expression classes for bitvectors.
const shift_exprt & to_shift_expr(const exprt &expr)
Cast an exprt to a shift_exprt.
bool is_signed_or_unsigned_bitvector(const typet &type)
This method tests, if the given typet is a signed or unsigned bitvector.
const bitvector_typet & to_bitvector_type(const typet &type)
Cast a typet to a bitvector_typet.
const floatbv_typet & to_floatbv_type(const typet &type)
Cast a typet to a floatbv_typet.
API to expression classes that are internal to the C frontend.
ANSI-C Language Type Checking.
already_typechecked_exprt & to_already_typechecked_expr(exprt &expr)
unsignedbv_typet unsigned_int_type()
unsignedbv_typet size_type()
signedbv_typet signed_int_type()
pointer_typet pointer_type(const typet &subtype)
signedbv_typet pointer_diff_type()
bitvector_typet char_type()
floatbv_typet long_double_type()
bitvector_typet c_index_type()
const c_bit_field_typet & to_c_bit_field_type(const typet &type)
Cast a typet to a c_bit_field_typet.
const c_enum_typet & to_c_enum_type(const typet &type)
Cast a typet to a c_enum_typet.
const c_enum_tag_typet & to_c_enum_tag_type(const typet &type)
Cast a typet to a c_enum_tag_typet.
const union_tag_typet & to_union_tag_type(const typet &type)
Cast a typet to a union_tag_typet.
Operator to return the address of an object.
const declaratorst & declarators() const
const typet & element_type() const
The type of the elements of the array.
A base class for binary expressions.
A Boolean expression returning true, iff operation kind would result in an overflow when applied to o...
A base class for expressions that are predicates, i.e., Boolean-typed, and that take exactly two argu...
A base class for relations, i.e., binary predicates whose two operands have the same type.
Reverse the order of bits in a bit-vector.
std::size_t get_width() const
The byte swap expression.
Type for C bit fields These are both 'bitvector_typet' (they have a width) and 'type_with_subtypet' (...
const typet & underlying_type() const
const typet & underlying_type() const
bool is_incomplete() const
enum types may be incomplete
static std::optional< std::string > check_address_can_be_taken(const typet &)
virtual void typecheck_obeys_contract_call(side_effect_expr_function_callt &expr)
Checks an obeys_contract predicate occurrence.
virtual void typecheck_expr_main(exprt &expr)
symbol_table_baset & symbol_table
virtual void implicit_typecast(exprt &expr, const typet &type)
virtual void typecheck_expr_alignof(exprt &expr)
static bool is_numeric_type(const typet &src)
virtual void typecheck_expr_pointer_arithmetic(exprt &expr)
virtual void typecheck_expr_rel_vector(binary_exprt &expr)
virtual void typecheck_expr_address_of(exprt &expr)
virtual void make_index_type(exprt &expr)
std::map< irep_idt, source_locationt > labels_used
virtual void typecheck_expr_constant(exprt &expr)
virtual void typecheck_expr(exprt &expr)
virtual void do_initializer(exprt &initializer, const typet &type, bool force_constant)
virtual void typecheck_code(codet &code)
virtual void typecheck_expr_binary_arithmetic(exprt &expr)
virtual void adjust_float_rel(binary_relation_exprt &)
virtual void typecheck_expr_unary_arithmetic(exprt &expr)
virtual void typecheck_expr_sizeof(exprt &expr)
void move_symbol(symbolt &symbol, symbolt *&new_symbol)
virtual void typecheck_expr_side_effect(side_effect_exprt &expr)
void disallow_subexpr_by_id(const exprt &, const irep_idt &, const std::string &) const
bool gcc_vector_types_compatible(const vector_typet &, const vector_typet &)
virtual bool gcc_types_compatible_p(const typet &, const typet &)
virtual void typecheck_expr_index(exprt &expr)
virtual void typecheck_expr_function_identifier(exprt &expr)
virtual void typecheck_expr_shifts(shift_exprt &expr)
virtual void make_constant(exprt &expr)
virtual void typecheck_expr_comma(exprt &expr)
exprt typecheck_saturating_arithmetic(const side_effect_expr_function_callt &expr)
virtual void typecheck_expr_builtin_va_arg(exprt &expr)
virtual void implicit_typecast_arithmetic(exprt &expr)
virtual void typecheck_side_effect_function_call(side_effect_expr_function_callt &expr)
static void add_rounding_mode(exprt &)
std::list< codet > clean_code
virtual std::string to_string(const exprt &expr)
virtual void typecheck_expr_binary_boolean(exprt &expr)
void typecheck_declaration(ansi_c_declarationt &)
virtual void typecheck_side_effect_statement_expression(side_effect_exprt &expr)
virtual exprt do_special_functions(side_effect_expr_function_callt &expr)
asm_label_mapt asm_label_map
virtual std::optional< symbol_exprt > typecheck_shadow_memory_builtin(const side_effect_expr_function_callt &expr)
Typecheck the function if it is a shadow_memory builtin and return a symbol for it.
virtual void typecheck_expr_cw_va_arg_typeof(exprt &expr)
exprt typecheck_builtin_overflow(side_effect_expr_function_callt &expr, const irep_idt &arith_op)
virtual void typecheck_side_effect_gcc_conditional_expression(side_effect_exprt &expr)
virtual void typecheck_side_effect_assignment(side_effect_exprt &expr)
virtual code_blockt instantiate_gcc_polymorphic_builtin(const irep_idt &identifier, const symbol_exprt &function_symbol)
virtual void typecheck_expr_operands(exprt &expr)
virtual std::optional< symbol_exprt > typecheck_gcc_polymorphic_builtin(const irep_idt &identifier, const exprt::operandst &arguments, const source_locationt &source_location)
virtual void typecheck_typed_target_call(side_effect_expr_function_callt &expr)
virtual void make_constant_index(exprt &expr)
virtual void typecheck_function_call_arguments(side_effect_expr_function_callt &expr)
Typecheck the parameters in a function call expression, and where necessary, make implicit casts arou...
virtual bool is_complete_type(const typet &type) const
id_type_mapt parameter_map
virtual void typecheck_expr_symbol(exprt &expr)
virtual void typecheck_expr_trinary(if_exprt &expr)
virtual void typecheck_expr_ptrmember(exprt &expr)
virtual void typecheck_arithmetic_pointer(exprt &expr)
virtual void typecheck_expr_unary_boolean(exprt &expr)
virtual void implicit_typecast_bool(exprt &expr)
virtual exprt typecheck_shuffle_vector(const side_effect_expr_function_callt &expr)
virtual void typecheck_expr_member(exprt &expr)
virtual void typecheck_expr_dereference(exprt &expr)
virtual void typecheck_type(typet &type)
virtual void typecheck_expr_typecast(exprt &expr)
virtual void typecheck_expr_rel(binary_relation_exprt &expr)
virtual void typecheck_expr_builtin_offsetof(exprt &expr)
virtual bool builtin_factory(const irep_idt &)
A codet representing sequential composition of program statements.
static code_blockt from_list(const std::list< codet > &_list)
codet & find_last_statement()
A codet representing the declaration of a local variable.
std::vector< parametert > parameterst
const parameterst & parameters() const
const typet & return_type() const
bool has_ellipsis() const
Data structure for representing an arbitrary statement in a program.
const irep_idt & get_statement() const
Imaginary part of the expression describing a complex number.
Real part of the expression describing a complex number.
Complex numbers made of pair of given subtype.
A constant literal expression.
The count leading zeros (counting the number of zero bits starting from the most-significant bit) exp...
The count trailing zeros (counting the number of zero bits starting from the least-significant bit) e...
An expression, akin to ISO C's strlen, that denotes the length of a zero-terminated string that start...
Operator to dereference a pointer.
bool starts_with(const char *s) const
equivalent of as_string().starts_with(s)
A Boolean expression returning true, iff the value of an enum-typed symbol equals one of the enum's d...
exprt lower(const namespacet &ns) const
Base class for all expressions.
const source_locationt & find_source_location() const
Get a source_locationt from the expression or from its operands (non-recursively).
std::vector< exprt > operandst
void copy_to_operands(const exprt &expr)
Copy the given argument to the end of exprt's operands.
bool is_boolean() const
Return whether the expression represents a Boolean.
bool is_constant() const
Return whether the expression is a constant.
typet & type()
Return the type of the expression.
const source_locationt & source_location() const
source_locationt & add_source_location()
void add_to_operands(const exprt &expr)
Add the given argument to the end of exprt's operands.
exprt & with_source_location(source_locationt location) &
Add the source location from location, if it is non-nil.
The Boolean constant false.
Returns one plus the index of the least-significant one bit, or zero if the operand is zero.
Round a floating-point number to an integral value considering the given rounding mode.
Fixed-width bit-vector with IEEE floating-point interpretation.
Application of (mathematical) function.
A class for an expression that indicates a history variable.
IEEE-floating-point equality.
static ieee_float_spect single_precision()
static ieee_float_spect double_precision()
constant_exprt to_expr() const
static ieee_float_valuet zero(const floatbv_typet &type)
static ieee_float_valuet plus_infinity(const ieee_float_spect &_spec)
The trinary if-then-else operator.
An expression denoting infinity.
Thrown when we can't handle something in an input source file.
bool get_bool(const irep_idt &name) const
std::string pretty(unsigned indent=0, unsigned max_indent=0) const
const irep_idt & get(const irep_idt &name) const
void remove(const irep_idt &name)
void set(const irep_idt &name, const irep_idt &value)
const irep_idt & id() const
irept & add(const irep_idt &name)
Architecturally similar to can_forward_propagatet, but specialized for what is a constexpr,...
is_compile_time_constantt(const namespacet &ns)
bool is_constant(const exprt &e) const
This function determines what expressions are to be propagated as "constants".
bool is_constant_address_of(const exprt &e) const
this function determines which reference-typed expressions are constant
bool operator()(const exprt &e) const
returns true iff the expression can be considered constant
A predicate that indicates that a zero-terminated string starts at the given address.
Evaluates to true if the operand is a pointer to a dynamic object.
Evaluates to true if the operand is finite.
Evaluates to true if the operand is infinite.
Evaluates to true if the operand is NaN.
Evaluates to true if the operand is a normal number.
A predicate that indicates that the object pointed to is live.
A type for mathematical functions (do not confuse with functions/methods in code).
std::vector< typet > domaint
source_locationt source_location
message_handlert & get_message_handler()
mstreamt & warning() const
mstreamt & result() const
Binary multiplication Associativity is not specified.
A base class for multi-ary expressions Associativity is not specified.
void follow_macros(exprt &) const
Follow macros to their values in a given expression.
const union_typet & follow_tag(const union_tag_typet &) const
Follow type tag of union type.
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
The null pointer constant.
Expression for finding the size (in bytes) of the object a pointer points to.
Symbol table entry of function parameterThis is a symbol generated as part of type checking.
The plus expression Associativity is not specified.
pointer_in_range(a, b, c) evaluates to true iff same_object(a, b, c) ∧ r_ok(a, offset(c)-offset(a)) ∧...
const typet & base_type() const
The type of the data what we point to.
The popcount (counting the number of bits set to 1) expression.
A base class for expressions that are predicates, i.e., Boolean-typed.
A base class for a predicate that indicates that an address range is ok to read or write or both.
Saturating subtraction expression.
The saturating plus expression.
A predicate that indicates that the objects pointed to are distinct.
A base class for shift and rotate operators.
A side_effect_exprt representation of a function call side effect.
exprt::operandst & arguments()
A side_effect_exprt that returns a non-deterministically chosen value.
A Boolean expression returning true, iff the result of performing operation kind on operands a and b ...
An expression containing a side effect.
const irep_idt & get_statement() const
Sign of an expression Predicate is true if _op is negative, false otherwise.
Fixed-width bit-vector with two's complement interpretation.
const irep_idt & get_function() const
Base type for structs and unions.
const componentst & components() const
const componentt & get_component(const irep_idt &component_name) const
Get the reference to a component with given name.
bool has_component(const irep_idt &component_name) const
bool is_incomplete() const
A struct/union may be incomplete.
Expression to hold a symbol (variable).
void set_identifier(const irep_idt &identifier)
const irep_idt & get_identifier() const
irep_idt base_name
Base (non-scoped) name.
source_locationt location
Source code location of definition of symbol.
class symbol_exprt symbol_expr() const
Produces a symbol_exprt for a symbol.
typet type
Type of symbol.
irep_idt name
The unique identifier.
const irep_idt & display_name() const
Return language specific display name if present.
exprt value
Initial value of symbol.
irep_idt mode
Language mode.
The Boolean constant true.
Type with multiple subtypes.
const typet & subtype() const
Semantic type conversion.
static exprt conditional_cast(const exprt &expr, const typet &type)
The type of an expression, extends irept.
Generic base class for unary expressions.
A Boolean expression returning true, iff negation would result in an overflow when applied to the (si...
Union constructor from single element.
const constant_exprt & size() const
typet index_type() const
The type of any index expression into an instance of this type.
const typet & element_type() const
The type of the elements of the vector.
A predicate that indicates that the object pointed to is writeable.
std::string expr2c(const exprt &expr, const namespacet &ns, const expr2c_configurationt &configuration)
std::string type2c(const typet &type, const namespacet &ns, const expr2c_configurationt &configuration)
#define Forall_operands(it, expr)
auto type_try_dynamic_cast(TType &base) -> typename detail::expr_try_dynamic_cast_return_typet< T, TType >::type
Try to cast a reference to a generic typet to a specific derived class.
bool can_cast_type(const typet &base)
Check whether a reference to a generic typet is of a specific derived class.
auto expr_try_dynamic_cast(TExpr &base) -> typename detail::expr_try_dynamic_cast_return_typet< T, TExpr >::type
Try to cast a reference to a generic exprt to a specific derived class.
constant_exprt make_boolean_expr(bool value)
returns true_exprt if given true and false_exprt otherwise
const exprt & skip_typecast(const exprt &expr)
find the expression nested inside typecasts, if any
bool is_assignable(const exprt &expr)
Returns true iff the argument is one of the following:
bool has_subexpr(const exprt &expr, const std::function< bool(const exprt &)> &pred)
returns true if the expression has a subexpression that satisfies pred
Deprecated expression utility functions.
API to expression classes for floating-point arithmetic.
const ieee_float_op_exprt & to_ieee_float_op_expr(const exprt &expr)
Cast an exprt to an ieee_float_op_exprt.
const std::string & id2string(const irep_idt &d)
API to expression classes for 'mathematical' expressions.
bool is_number(const typet &type)
Returns true if the type is a rational, real, integer, natural, complex, unsignedbv,...
const mathematical_function_typet & to_mathematical_function_type(const typet &type)
Cast a typet to a mathematical_function_typet.
mp_integer alignment(const typet &type, const namespacet &ns)
ANSI-C Language Type Checking.
API to expression classes for Pointers.
const address_of_exprt & to_address_of_expr(const exprt &expr)
Cast an exprt to an address_of_exprt.
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
const dereference_exprt & to_dereference_expr(const exprt &expr)
Cast an exprt to a dereference_exprt.
std::optional< mp_integer > pointer_offset_bits(const typet &type, const namespacet &ns)
std::optional< exprt > size_of_expr(const typet &type, const namespacet &ns)
std::optional< exprt > member_offset_expr(const member_exprt &member_expr, const namespacet &ns)
exprt pointer_offset(const exprt &pointer)
exprt same_object(const exprt &p1, const exprt &p2)
exprt pointer_object(const exprt &p)
Various predicates over pointers in programs.
Ranges: pair of begin and end iterators, which can be initialized from containers,...
ranget< iteratort > make_range(iteratort begin, iteratort end)
exprt deref_expr(const exprt &expr)
Wraps a given expression into a dereference_exprt unless it is an address_of_exprt in which case it j...
bool simplify(exprt &expr, const namespacet &ns)
exprt simplify_expr(exprt src, const namespacet &ns)
#define CHECK_RETURN(CONDITION)
#define UNREACHABLE
This should be used to mark dead code.
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
#define PRECONDITION(CONDITION)
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
side_effect_exprt & to_side_effect_expr(exprt &expr)
side_effect_expr_statement_expressiont & to_side_effect_expr_statement_expression(exprt &expr)
side_effect_expr_function_callt & to_side_effect_expr_function_call(exprt &expr)
bool can_cast_expr< side_effect_expr_function_callt >(const exprt &base)
const code_blockt & to_code_block(const codet &code)
bool can_cast_expr< side_effect_exprt >(const exprt &base)
const code_frontend_declt & to_code_frontend_decl(const codet &code)
const codet & to_code(const exprt &expr)
auto component(T &struct_expr, const irep_idt &name, const namespacet &ns) -> decltype(struct_expr.op0())
const binary_relation_exprt & to_binary_relation_expr(const exprt &expr)
Cast an exprt to a binary_relation_exprt.
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
const typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
const binary_exprt & to_binary_expr(const exprt &expr)
Cast an exprt to a binary_exprt.
const unary_exprt & to_unary_expr(const exprt &expr)
Cast an exprt to a unary_exprt.
const if_exprt & to_if_expr(const exprt &expr)
Cast an exprt to an if_exprt.
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
const vector_typet & to_vector_type(const typet &type)
Cast a typet to a vector_typet.
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
bool is_constant(const typet &type)
This method tests, if the given typet is a constant.
const struct_tag_typet & to_struct_tag_type(const typet &type)
Cast a typet to a struct_tag_typet.
const complex_typet & to_complex_type(const typet &type)
Cast a typet to a complex_typet.
const struct_or_union_tag_typet & to_struct_or_union_tag_type(const typet &type)
Cast a typet to a struct_or_union_tag_typet.
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
bool has_suffix(const std::string &s, const std::string &suffix)
std::string type_to_partial_identifier(const typet &type, const namespacet &ns)
Constructs a string describing the given type, which can be used as part of a C identifier.
const type_with_subtypet & to_type_with_subtype(const typet &type)