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_gcc_builtin_has_attribute)
278 else if(expr.
id()==ID_clang_builtin_convertvector)
287 else if(expr.
id()==ID_builtin_offsetof)
289 else if(expr.
id()==ID_string_constant)
292 expr.
set(ID_C_lvalue,
true);
294 else if(expr.
id()==ID_arguments)
298 else if(expr.
id()==ID_designated_initializer)
300 exprt &designator=
static_cast<exprt &
>(expr.
add(ID_designator));
304 if(it->id()==ID_index)
308 else if(expr.
id()==ID_initializer_list)
314 expr.
id() == ID_forall || expr.
id() == ID_exists || expr.
id() == ID_lambda)
320 auto &bindings = binary_expr.op0().operands();
321 auto &where = binary_expr.op1();
323 for(
const auto &binding : bindings)
325 if(binding.get(ID_statement) != ID_decl)
328 error() <<
"expected declaration as operand of quantifier" <<
eom;
335 [&](
const exprt &subexpr)
342 error() <<
"quantifier must not contain function calls" <<
eom;
347 for(
auto &binding : bindings)
350 if(expr.
id() == ID_lambda)
354 for(
auto &binding : bindings)
355 domain.push_back(binding.type());
365 else if(expr.
id()==ID_label)
369 else if(expr.
id()==ID_array)
373 else if(expr.
id()==ID_complex)
378 else if(expr.
id() == ID_complex_real)
382 if(op.
type().
id() != ID_complex)
387 error() <<
"real part retrieval expects numerical operand, "
395 expr.
swap(complex_real_expr);
403 complex_real_expr.
set(ID_C_lvalue,
true);
406 complex_real_expr.
type().
set(ID_C_constant,
true);
408 expr.
swap(complex_real_expr);
411 else if(expr.
id() == ID_complex_imag)
415 if(op.
type().
id() != ID_complex)
420 error() <<
"real part retrieval expects numerical operand, "
428 expr.
swap(complex_imag_expr);
436 complex_imag_expr.
set(ID_C_lvalue,
true);
439 complex_imag_expr.
type().
set(ID_C_constant,
true);
441 expr.
swap(complex_imag_expr);
444 else if(expr.
id()==ID_generic_selection)
461 for(
auto &irep : generic_associations)
463 if(irep.get(ID_type_arg) != ID_default)
465 typet &type =
static_cast<typet &
>(irep.add(ID_type_arg));
474 const typet &op_type = op.type();
476 for(
const auto &irep : generic_associations)
478 if(irep.get(ID_type_arg) == ID_default)
479 default_match =
static_cast<const exprt &
>(irep.find(ID_value));
480 else if(op_type ==
static_cast<const typet &
>(irep.find(ID_type_arg)))
482 assoc_match =
static_cast<const exprt &
>(irep.find(ID_value));
489 expr.
swap(default_match);
493 error() <<
"unmatched generic selection: " <<
to_string(op.type())
499 expr.
swap(assoc_match);
504 else if(expr.
id()==ID_gcc_asm_input ||
505 expr.
id()==ID_gcc_asm_output ||
506 expr.
id()==ID_gcc_asm_clobbered_register)
509 else if(expr.
id()==ID_lshr || expr.
id()==ID_ashr ||
510 expr.
id()==ID_assign_lshr || expr.
id()==ID_assign_ashr)
515 expr.
id() == ID_C_spec_assigns || expr.
id() == ID_C_spec_frees ||
516 expr.
id() == ID_target_list)
527 exprt tmp = bit_cast_expr->lower();
533 error() <<
"bit cast from '" <<
to_string(bit_cast_expr->op().type())
552 expr.
set(ID_C_lvalue,
true);
560 auto type_not_permitted = [
this](
const exprt &expr)
565 <<
"' not permitted for va_arg" <<
eom;
575 if(components.size() != 5)
576 type_not_permitted(expr);
578 else if(arg.
type().
id() != ID_pointer && arg.
type().
id() != ID_array)
579 type_not_permitted(expr);
603 symbolt symbol{ID_gcc_builtin_va_arg, symbol_type, ID_C};
633 error() <<
"builtin_offsetof expects no operands" <<
eom;
640 const exprt &member =
static_cast<const exprt &
>(expr.
add(ID_designator));
644 for(
const auto &op : member.
operands())
646 if(op.id() == ID_member)
648 if(type.
id() != ID_union_tag && type.
id() != ID_struct_tag)
651 error() <<
"offsetof of member expects struct/union type, "
657 irep_idt component_name = op.get(ID_component_name);
671 if(type.
id() == ID_struct_tag)
676 if(!o_opt.has_value())
679 error() <<
"offsetof failed to determine offset of '"
680 << component_name <<
"'" <<
eom;
696 for(
const auto &c : struct_union_type.
components())
700 (c.type().id() == ID_struct_tag || c.type().id() == ID_union_tag))
704 if(type.
id() == ID_struct_tag)
709 if(!o_opt.has_value())
712 error() <<
"offsetof failed to determine offset of '"
713 << component_name <<
"'" <<
eom;
723 typet tmp = c.type();
726 type.
id() == ID_union_tag || type.
id() == ID_struct_tag);
736 error() <<
"offset-of of member failed to find component '"
737 << component_name <<
"' in '" <<
to_string(type) <<
"'"
744 else if(op.id() == ID_index)
746 if(type.
id()!=ID_array)
749 error() <<
"offsetof of index expects array type" <<
eom;
758 auto element_size_opt =
761 if(!element_size_opt.has_value())
764 error() <<
"offsetof failed to determine array element size" <<
eom;
787 if(expr.
id()==ID_side_effect &&
788 expr.
get(ID_statement)==ID_function_call)
793 else if(expr.
id()==ID_side_effect &&
794 expr.
get(ID_statement)==ID_statement_expression)
799 expr.
id() == ID_forall || expr.
id() == ID_exists || expr.
id() == ID_lambda)
805 auto &bindings = binary_expr.op0().operands();
807 for(
auto &binding : bindings)
816 error() <<
"forall/exists expects one declarator exactly" <<
eom;
823 symbol_table_baset::symbolst::const_iterator s_it =
834 const symbolt &symbol = s_it->second;
841 error() <<
"unexpected quantified symbol" <<
eom;
865 id_type_mapt::const_iterator p_it=
parameter_map.find(identifier);
869 expr.
type()=p_it->second;
870 expr.
set(ID_C_lvalue,
true);
875 asm_label_mapt::const_iterator entry=
879 identifier=entry->second;
885 if(
lookup(identifier, symbol_ptr))
888 error() <<
"failed to find symbol '" << identifier <<
"'" <<
eom;
892 const symbolt &symbol=*symbol_ptr;
897 error() <<
"did not expect a type symbol here, but got '"
916 expr.
set(ID_C_cformat, base_name);
931 else if(identifier==
"__func__" ||
932 identifier==
"__FUNCTION__" ||
933 identifier==
"__PRETTY_FUNCTION__")
939 s.
set(ID_C_lvalue,
true);
950 expr.
set(ID_C_lvalue,
true);
952 if(expr.
type().
id()==ID_code)
955 tmp.
set(ID_C_implicit,
true);
974 if(last_statement==ID_expression)
980 if(op.
type().
id()==ID_array)
1005 type.
swap(
static_cast<typet &
>(expr.
add(ID_type_arg)));
1022 if(type.
id()==ID_c_bit_field)
1026 if(op.
id() == ID_comma || op.
id() == ID_side_effect)
1033 config.ansi_c.char_width,
1040 if(!size_of_opt.has_value())
1043 error() <<
"type has no size: "
1048 new_expr = size_of_opt.value();
1054 error() <<
"sizeof cannot be applied to bit fields" <<
eom;
1058 else if(type.
id() == ID_bool)
1061 error() <<
"sizeof cannot be applied to single bits" <<
eom;
1064 else if(type.
id() == ID_empty)
1073 (type.
id() == ID_struct_tag &&
1075 (type.
id() == ID_union_tag &&
1077 (type.
id() == ID_c_enum_tag &&
1082 error() <<
"invalid application of \'sizeof\' to an incomplete type\n\t\'"
1089 if(!size_of_opt.has_value())
1096 new_expr = size_of_opt.value();
1100 new_expr.
swap(expr);
1102 expr.
add(ID_C_c_sizeof_type)=type;
1108 ID_statement_expression,
void_type(), location);
1110 decl_block.set_statement(ID_decl_block);
1123 expr.
swap(comma_expr);
1129 typet argument_type;
1137 argument_type=op_type;
1161 decl_block.set_statement(ID_decl_block);
1172 std::move(side_effect_expr), ID_comma, op, op.
type()};
1173 op.
swap(comma_expr);
1179 expr_type.
id() == ID_union_tag && expr_type != op.
type() &&
1180 op.
id() != ID_initializer_list)
1193 for(
const auto &c : union_type.components())
1195 if(c.type() == op.
type())
1201 expr.
set(ID_C_lvalue,
true);
1209 <<
"' not found in union" <<
eom;
1216 if(op.
id()==ID_initializer_list)
1225 exprt tmp(ID_compound_literal, expr.
type());
1229 if(op.
id()==ID_array &&
1230 expr.
type().
id()==ID_array &&
1235 expr.
set(ID_C_lvalue,
true);
1240 if(expr_type.
id()==ID_empty)
1246 if(expr_type == op_type)
1251 if(expr_type.
id()==ID_vector)
1254 if(op_type.
id()==ID_vector)
1256 else if(op_type.
id()==ID_signedbv ||
1257 op_type.
id()==ID_unsignedbv)
1264 error() <<
"type cast to '" <<
to_string(expr_type) <<
"' is not permitted"
1272 else if(op_type.
id()==ID_array)
1277 if(error_opt.has_value())
1283 else if(op_type.
id()==ID_empty)
1285 if(expr_type.
id()!=ID_empty)
1288 error() <<
"type cast from void only permitted to void, but got '"
1293 else if(op_type.
id()==ID_vector)
1300 if((expr_type.
id()==ID_signedbv ||
1301 expr_type.
id()==ID_unsignedbv) &&
1310 <<
"' not permitted" <<
eom;
1317 error() <<
"type cast from '" <<
to_string(op_type) <<
"' not permitted"
1333 if(expr_type.
id()==ID_pointer)
1334 expr.
set(ID_C_lvalue,
true);
1351 const typet &array_type = array_expr.
type();
1352 const typet &index_type = index_expr.
type();
1355 array_type.
id() != ID_array && array_type.
id() != ID_pointer &&
1356 array_type.
id() != ID_vector &&
1357 (index_type.
id() == ID_array || index_type.
id() == ID_pointer ||
1358 index_type.
id() == ID_vector))
1359 std::swap(array_expr, index_expr);
1367 const typet final_array_type = array_expr.
type();
1369 if(final_array_type.
id()==ID_array ||
1370 final_array_type.
id()==ID_vector)
1374 if(array_expr.
get_bool(ID_C_lvalue))
1375 expr.
set(ID_C_lvalue,
true);
1377 if(final_array_type.
get_bool(ID_C_constant))
1378 expr.
type().
set(ID_C_constant,
true);
1380 else if(final_array_type.
id()==ID_pointer)
1386 std::swap(summands, expr.
operands());
1388 expr.
id(ID_dereference);
1389 expr.
set(ID_C_lvalue,
true);
1395 error() <<
"operator [] must take array/vector or pointer but got '"
1404 if(expr.
op0().
type().
id() == ID_floatbv)
1406 if(expr.
id()==ID_equal)
1407 expr.
id(ID_ieee_float_equal);
1408 else if(expr.
id()==ID_notequal)
1409 expr.
id(ID_ieee_float_notequal);
1422 if(o_type0.
id() == ID_vector || o_type1.
id() == ID_vector)
1430 if(expr.
id()==ID_equal || expr.
id()==ID_notequal)
1432 if(o_type0 == o_type1)
1434 if(o_type0.
id() != ID_array)
1455 if(type0.
id()==ID_pointer)
1457 if(expr.
id()==ID_equal || expr.
id()==ID_notequal)
1460 if(expr.
id()==ID_le || expr.
id()==ID_lt ||
1461 expr.
id()==ID_ge || expr.
id()==ID_gt)
1465 if(type0.
id()==ID_string_constant)
1467 if(expr.
id()==ID_equal || expr.
id()==ID_notequal)
1499 if(type0.
id()==ID_pointer && type1.
id()==ID_pointer)
1507 error() <<
"operator '" << expr.
id() <<
"' not defined for types '"
1518 if(o_type0.
id() != ID_vector || o_type0 != o_type1)
1521 error() <<
"vector operator '" << expr.
id() <<
"' not defined for types '"
1529 auto subtype_width =
1538 if(expr.
id() == ID_notequal)
1539 expr.
id(ID_vector_notequal);
1547 const typet &op0_type = op.type();
1549 if(op0_type.
id() == ID_array)
1554 index_expr.
set(ID_C_lvalue,
true);
1555 op.swap(index_expr);
1557 else if(op0_type.
id() == ID_pointer)
1568 error() <<
"ptrmember operator requires pointer or array type "
1569 "on left hand side, but got '"
1583 if(type.
id() != ID_struct_tag && type.
id() != ID_union_tag)
1586 error() <<
"member operator requires structure type "
1587 "on left hand side but got '"
1598 error() <<
"member operator got incomplete " << type.
id()
1599 <<
" type on left hand side" <<
eom;
1604 expr.
get(ID_component_name);
1620 error() <<
"member '" << component_name <<
"' not found in '"
1633 expr.
set(ID_C_lvalue,
true);
1637 struct_union_type.
get_bool(ID_C_constant))
1639 expr.
type().
set(ID_C_constant,
true);
1645 if(!identifier.
empty())
1646 expr.
set(ID_C_identifier, identifier);
1650 if(access==ID_private)
1653 error() <<
"member '" << component_name <<
"' is " << access <<
eom;
1665 const typet o_type0=operands[0].type();
1666 const typet o_type1=operands[1].type();
1667 const typet o_type2=operands[2].type();
1671 if(o_type1.
id() == ID_empty || o_type2.
id() == ID_empty)
1691 if(operands[1].type().
id()==ID_pointer &&
1692 operands[2].type().
id()!=ID_pointer)
1694 else if(operands[2].type().
id()==ID_pointer &&
1695 operands[1].type().
id()!=ID_pointer)
1698 if(operands[1].type().
id()==ID_pointer &&
1699 operands[2].type().
id()==ID_pointer &&
1700 operands[1].type()!=operands[2].type())
1747 if(operands[1].type().
id()==ID_empty ||
1748 operands[2].type().
id()==ID_empty)
1755 operands[1].type() != operands[2].type() ||
1756 operands[1].type().
id() == ID_array)
1761 if(operands[1].type() == operands[2].type())
1763 expr.
type()=operands[1].type();
1769 if(operands[1].get_bool(ID_C_lvalue) &&
1770 operands[2].get_bool(ID_C_lvalue))
1771 expr.
set(ID_C_lvalue,
true);
1777 error() <<
"operator ?: not defined for types '" <<
to_string(o_type1)
1790 if(operands.size()!=2)
1793 error() <<
"gcc conditional_expr expects two operands" <<
eom;
1799 if_exprt if_expr(operands[0], operands[0], operands[1]);
1816 if(error_opt.has_value())
1820 if(op.
id()==ID_label)
1833 op.
id() == ID_address_of && op.
get_bool(ID_C_implicit) &&
1839 tmp.
set(ID_C_implicit,
false);
1844 if(op.
id()==ID_struct ||
1845 op.
id()==ID_union ||
1846 op.
id()==ID_array ||
1847 op.
id()==ID_string_constant)
1855 else if(op.
type().
id()==ID_code)
1862 error() <<
"address_of error: '" <<
to_string(op) <<
"' not an lvalue"
1876 if(op_type.
id()==ID_array)
1884 else if(op_type.
id()==ID_pointer)
1889 expr.
type().
id() == ID_empty &&
1893 error() <<
"dereferencing void pointer" <<
eom;
1901 <<
"' is not a pointer, but got '" <<
to_string(op_type) <<
"'"
1906 expr.
set(ID_C_lvalue,
true);
1917 if(expr.
type().
id()==ID_code)
1920 tmp.
set(ID_C_implicit,
true);
1930 if(statement==ID_preincrement ||
1931 statement==ID_predecrement ||
1932 statement==ID_postincrement ||
1933 statement==ID_postdecrement)
1942 <<
"' not an lvalue" <<
eom;
1953 if(type0.
id() == ID_c_enum_tag)
1959 error() <<
"operator '" << statement <<
"' given incomplete type '"
1969 else if(type0.
id() == ID_c_bit_field)
1973 typet type_before{type0};
1975 expr.
type()=underlying_type;
1979 else if(type0.
id() == ID_bool || type0.
id() == ID_c_bool)
1988 else if(type0.
id() == ID_pointer)
1996 error() <<
"operator '" << statement <<
"' not defined for type '"
2003 else if(statement==ID_function_call)
2006 else if(statement==ID_statement_expression)
2008 else if(statement==ID_gcc_conditional_expression)
2013 error() <<
"unknown side effect: " << statement <<
eom;
2025 "expression must be a " CPROVER_PREFIX "typed_target function call");
2032 "expected 1 argument for " CPROVER_PREFIX "typed_target, found " +
2033 std::to_string(expr.
arguments().size()),
2043 arg0.source_location()};
2047 if(!size.has_value())
2051 "typed_target of type " +
2053 arg0.source_location()};
2062 arguments.push_back(size.value());
2064 if(arg0.type().id() == ID_pointer)
2080 "expression must be a " CPROVER_PREFIX "obeys_contract function call");
2085 "expected 2 arguments for " CPROVER_PREFIX "obeys_contract, found " +
2086 std::to_string(expr.
arguments().size()),
2092 auto &function_pointer = expr.
arguments()[0];
2095 function_pointer.type().id() != ID_pointer ||
2096 to_pointer_type(function_pointer.type()).base_type().id() != ID_code ||
2097 !function_pointer.get_bool(ID_C_lvalue))
2101 "obeys_contract must be a function pointer lvalue expression",
2102 function_pointer.source_location());
2109 "obeys_contract must have no ternary operator",
2110 function_pointer.source_location());
2114 auto &address_of_contract = expr.
arguments()[1];
2117 address_of_contract.id() != ID_address_of ||
2119 address_of_contract.type().id() != ID_pointer ||
2120 to_pointer_type(address_of_contract.type()).base_type().id() != ID_code)
2124 "obeys_contract must must be a function symbol",
2125 address_of_contract.source_location());
2128 if(function_pointer.type() != address_of_contract.type())
2132 "obeys_contract must have the same function pointer type",
2141 return ::builtin_factory(
2143 config.ansi_c.float16_type,
2154 error() <<
"function_call side effect expects two operands" <<
eom;
2163 if(f_op.
id()==ID_symbol)
2167 asm_label_mapt::const_iterator entry=
2170 identifier=entry->second;
2187 identifier ==
"__noop" &&
2201 identifier ==
"__builtin_nondeterministic_value" &&
2212 error() <<
"__builtin_nondeterministic_value expects one operand"
2225 identifier ==
"__builtin_shuffle" &&
2233 else if(identifier ==
"__builtin_shufflevector")
2243 identifier ==
"__builtin_elementwise_add_sat" ||
2244 identifier ==
"__builtin_elementwise_sub_sat")
2256 error() <<
"equal expects two operands" <<
eom;
2267 error() <<
"equal expects two operands of same type" <<
eom;
2271 expr.
swap(equality_expr);
2285 overflow.
id(ID_minus);
2290 overflow.
id(ID_mult);
2295 overflow.
id(ID_plus);
2300 overflow.
id(ID_shl);
2319 expr.
swap(overflow);
2327 std::ostringstream error_message;
2328 error_message << identifier <<
" takes exactly 1 argument, but "
2329 << expr.
arguments().size() <<
" were provided";
2337 std::ostringstream error_message;
2338 error_message << identifier <<
" expects enum, but ("
2339 <<
expr2c(arg1, *
this) <<
") has type `"
2340 <<
type2c(arg1.type(), *
this) <<
'`';
2359 id2string(identifier) +
" expects one or two operands",
2364 auto &pointer_expr = expr.
arguments()[0];
2365 if(pointer_expr.type().id() == ID_array)
2368 dest_type.base_type().set(ID_C_constant,
true);
2371 else if(pointer_expr.type().id() != ID_pointer)
2374 id2string(identifier) +
" expects a pointer as first argument",
2390 const auto &subtype =
2392 if(subtype.id() == ID_empty)
2396 " expects a size when given a void pointer",
2402 size_expr = std::move(size_expr_opt.value());
2418 irep_idt shadow_memory_builtin_id = shadow_memory_builtin->identifier();
2420 const auto builtin_code_type =
2424 builtin_code_type.has_ellipsis() &&
2425 builtin_code_type.parameters().empty(),
2426 "Shadow memory builtins should be an ellipsis with 0 parameter");
2432 shadow_memory_builtin_id, shadow_memory_builtin->type(), ID_C};
2433 new_symbol.
base_name = shadow_memory_builtin_id;
2444 f_op = std::move(*shadow_memory_builtin);
2450 irep_idt identifier_with_type = gcc_polymorphic->identifier();
2453 !parameters.empty(),
2454 "GCC polymorphic built-ins should have at least one parameter");
2459 if(parameters.front().type().id() == ID_pointer)
2461 identifier_with_type =
2468 identifier_with_type =
2472 gcc_polymorphic->identifier(identifier_with_type);
2476 for(std::size_t i = 0; i < parameters.size(); ++i)
2478 const std::string base_name =
"p_" + std::to_string(i);
2483 id2string(identifier_with_type) +
"::" + base_name;
2486 new_symbol.
type = parameters[i].type();
2489 new_symbol.
mode = ID_C;
2491 parameters[i].set_identifier(new_symbol.
name);
2492 parameters[i].set_base_name(new_symbol.
base_name);
2498 identifier_with_type, gcc_polymorphic->type(), ID_C};
2499 new_symbol.
base_name = identifier_with_type;
2507 new_symbol.
value = implementation;
2512 f_op = std::move(*gcc_polymorphic);
2524 if(identifier==
"malloc" ||
2525 identifier==
"realloc" ||
2526 identifier==
"reallocf" ||
2527 identifier==
"valloc")
2536 new_symbol.
type.
set(ID_C_incomplete,
true);
2548 debug() <<
"builtin '" << identifier <<
"' is unknown" <<
eom;
2553 warning() <<
"function '" << identifier <<
"' is not declared" <<
eom;
2564 if(f_op_type.
id() == ID_mathematical_function)
2566 const auto &mathematical_function_type =
2570 if(expr.
arguments().size() != mathematical_function_type.domain().size())
2573 error() <<
"expected " << mathematical_function_type.domain().size()
2574 <<
" arguments but got " << expr.
arguments().size() <<
eom;
2582 if(p.first.type() != p.second)
2595 expr.
swap(function_application);
2599 if(f_op_type.
id()!=ID_pointer)
2602 error() <<
"expected function/function pointer as argument but got '"
2608 if(f_op.
id() == ID_address_of && f_op.
get_bool(ID_C_implicit))
2615 tmp.
set(ID_C_implicit,
true);
2620 if(f_op.
type().
id()!=ID_code)
2623 error() <<
"expected code as argument" <<
eom;
2646 if(f_op.
id()!=ID_symbol)
2694 if(arg.type().id() != ID_pointer)
2698 "pointer_in_range_dfcc expects pointer-typed arguments",
2699 arg.source_location()};
2709 error() <<
"same_object expects two operands" <<
eom;
2715 exprt same_object_expr=
2719 return same_object_expr;
2726 error() <<
"get_must expects two operands" <<
eom;
2736 return std::move(get_must_expr);
2743 error() <<
"get_may expects two operands" <<
eom;
2753 return std::move(get_may_expr);
2760 error() <<
"is_invalid_pointer expects one operand" <<
eom;
2769 return same_object_expr;
2776 error() <<
"buffer_size expects one operand" <<
eom;
2786 return buffer_size_expr;
2794 error() <<
"is_list expects one operand" <<
eom;
2801 expr.
arguments()[0].type().id() != ID_pointer ||
2806 error() <<
"is_list expects a struct-pointer operand" <<
eom;
2814 return std::move(is_list_expr);
2822 error() <<
"is_dll expects one operand" <<
eom;
2829 expr.
arguments()[0].type().id() != ID_pointer ||
2834 error() <<
"is_dll expects a struct-pointer operand" <<
eom;
2842 return std::move(is_dll_expr);
2850 error() <<
"is_cyclic_dll expects one operand" <<
eom;
2857 expr.
arguments()[0].type().id() != ID_pointer ||
2862 error() <<
"is_cyclic_dll expects a struct-pointer operand" <<
eom;
2870 return std::move(is_cyclic_dll_expr);
2878 error() <<
"is_sentinel_dll expects two or three operands" <<
eom;
2885 args_no_cast.reserve(expr.
arguments().size());
2886 for(
const auto &argument : expr.
arguments())
2890 args_no_cast.back().type().id() != ID_pointer ||
2895 error() <<
"is_sentinel_dll_node expects struct-pointer operands"
2902 is_sentinel_dll_expr.
operands() = args_no_cast;
2905 return std::move(is_sentinel_dll_expr);
2913 error() <<
"is_cstring expects one operand" <<
eom;
2919 if(expr.
arguments()[0].type().id() != ID_pointer)
2922 error() <<
"is_cstring expects a pointer operand" <<
eom;
2929 return std::move(is_cstring_expr);
2937 error() <<
"cstrlen expects one operand" <<
eom;
2943 if(expr.
arguments()[0].type().id() != ID_pointer)
2946 error() <<
"cstrlen expects a pointer operand" <<
eom;
2953 return std::move(cstrlen_expr);
2960 error() <<
"is_zero_string expects one operand" <<
eom;
2968 is_zero_string_expr.
set(ID_C_lvalue,
true);
2971 return std::move(is_zero_string_expr);
2978 error() <<
"zero_string_length expects one operand" <<
eom;
2984 exprt zero_string_length_expr(
"zero_string_length",
size_type());
2986 zero_string_length_expr.
set(ID_C_lvalue,
true);
2989 return zero_string_length_expr;
2996 error() <<
"dynamic_object expects one argument" <<
eom;
3005 return is_dynamic_object_expr;
3012 error() <<
"live_object expects one argument" <<
eom;
3021 return live_object_expr;
3028 error() <<
"pointer_in_range expects three arguments" <<
eom;
3038 return pointer_in_range_expr;
3045 error() <<
"writeable_object expects one argument" <<
eom;
3054 return writeable_object_expr;
3062 error() <<
"separate expects two or more arguments" <<
eom;
3071 return separate_expr;
3078 error() <<
"pointer_offset expects one argument" <<
eom;
3094 error() <<
"object_size expects one operand" <<
eom;
3103 return std::move(object_size_expr);
3110 error() <<
"pointer_object expects one argument" <<
eom;
3121 else if(identifier==
"__builtin_bswap16" ||
3122 identifier==
"__builtin_bswap32" ||
3123 identifier==
"__builtin_bswap64")
3128 error() << identifier <<
" expects one operand" <<
eom;
3138 return std::move(bswap_expr);
3141 identifier ==
"__builtin_rotateleft8" ||
3142 identifier ==
"__builtin_rotateleft16" ||
3143 identifier ==
"__builtin_rotateleft32" ||
3144 identifier ==
"__builtin_rotateleft64" ||
3145 identifier ==
"__builtin_rotateright8" ||
3146 identifier ==
"__builtin_rotateright16" ||
3147 identifier ==
"__builtin_rotateright32" ||
3148 identifier ==
"__builtin_rotateright64")
3154 error() << identifier <<
" expects two operands" <<
eom;
3160 irep_idt id = (identifier ==
"__builtin_rotateleft8" ||
3161 identifier ==
"__builtin_rotateleft16" ||
3162 identifier ==
"__builtin_rotateleft32" ||
3163 identifier ==
"__builtin_rotateleft64")
3170 return std::move(rotate_expr);
3172 else if(identifier==
"__builtin_nontemporal_load")
3177 error() << identifier <<
" expects one operand" <<
eom;
3186 if(ptr_arg.
type().
id()!=ID_pointer)
3189 error() <<
"__builtin_nontemporal_load takes pointer as argument" <<
eom;
3198 identifier ==
"__builtin_fpclassify" ||
3204 error() << identifier <<
" expects six arguments" <<
eom;
3217 if(fp_value.
type().
id() != ID_floatbv)
3220 error() <<
"non-floating-point argument for " << identifier <<
eom;
3228 const auto &arguments = expr.
arguments();
3247 identifier==
"__builtin_isnan")
3252 error() <<
"isnan expects one operand" <<
eom;
3270 error() <<
"isfinite expects one operand" <<
eom;
3282 identifier ==
CPROVER_PREFIX "inf" || identifier ==
"__builtin_inf" ||
3283 identifier ==
"__builtin_huge_val")
3290 return std::move(inf_expr);
3293 identifier ==
CPROVER_PREFIX "inff" || identifier ==
"__builtin_inff" ||
3294 identifier ==
"__builtin_huge_valf")
3301 return std::move(inff_expr);
3304 identifier ==
CPROVER_PREFIX "infl" || identifier ==
"__builtin_infl" ||
3305 identifier ==
"__builtin_huge_vall")
3312 return std::move(infl_expr);
3322 error() << identifier <<
" expects two arguments" <<
eom;
3326 auto round_to_integral_expr =
3330 return std::move(round_to_integral_expr);
3343 error() <<
"abs-functions expect one operand" <<
eom;
3352 return std::move(abs_expr);
3362 error() <<
"fmod-functions expect two operands" <<
eom;
3376 return std::move(fmod_expr);
3386 error() <<
"remainder-functions expect two operands" <<
eom;
3400 return std::move(floatbv_rem_expr);
3409 error() <<
"fma-functions expect three operands" <<
eom;
3418 ID_floatbv_fma, expr.
arguments(), std::move(result_type));
3422 return std::move(fma_expr);
3429 error() <<
"allocate expects two operands" <<
eom;
3438 return std::move(malloc_expr);
3447 error() << identifier <<
" expects one operand" <<
eom;
3451 const auto ¶m_id = expr.
arguments().front().id();
3452 if(!(param_id == ID_dereference || param_id == ID_member ||
3453 param_id == ID_symbol || param_id == ID_ptrmember ||
3454 param_id == ID_constant || param_id == ID_typecast ||
3455 param_id == ID_index))
3458 error() <<
"Tracking history of " << param_id
3459 <<
" expressions is not supported yet." <<
eom;
3468 return std::move(old_expr);
3473 identifier==
"__builtin_isinf")
3478 error() << identifier <<
" expects one operand" <<
eom;
3486 if(fp_value.
type().
id() != ID_floatbv)
3489 error() <<
"non-floating-point argument for " << identifier <<
eom;
3498 else if(identifier ==
"__builtin_isinf_sign")
3503 error() << identifier <<
" expects one operand" <<
eom;
3513 if(fp_value.
type().
id() != ID_floatbv)
3516 error() <<
"non-floating-point argument for " << identifier <<
eom;
3534 identifier ==
"__builtin_isnormal")
3539 error() << identifier <<
" expects one operand" <<
eom;
3547 if(fp_value.
type().
id() != ID_floatbv)
3550 error() <<
"non-floating-point argument for " << identifier <<
eom;
3562 identifier==
"__builtin_signbit" ||
3563 identifier==
"__builtin_signbitf" ||
3564 identifier==
"__builtin_signbitl")
3569 error() << identifier <<
" expects one operand" <<
eom;
3580 else if(identifier==
"__builtin_popcount" ||
3581 identifier==
"__builtin_popcountl" ||
3582 identifier==
"__builtin_popcountll" ||
3583 identifier==
"__popcnt16" ||
3584 identifier==
"__popcnt" ||
3585 identifier==
"__popcnt64")
3590 error() << identifier <<
" expects one operand" <<
eom;
3599 return std::move(popcount_expr);
3602 identifier ==
"__builtin_clz" || identifier ==
"__builtin_clzl" ||
3603 identifier ==
"__builtin_clzll" || identifier ==
"__lzcnt16" ||
3604 identifier ==
"__lzcnt" || identifier ==
"__lzcnt64")
3609 error() << identifier <<
" expects one operand" <<
eom;
3619 return std::move(clz);
3622 identifier ==
"__builtin_ctz" || identifier ==
"__builtin_ctzl" ||
3623 identifier ==
"__builtin_ctzll")
3628 error() << identifier <<
" expects one operand" <<
eom;
3638 return std::move(ctz);
3641 identifier ==
"__builtin_ffs" || identifier ==
"__builtin_ffsl" ||
3642 identifier ==
"__builtin_ffsll")
3647 error() << identifier <<
" expects one operand" <<
eom;
3656 return std::move(ffs);
3658 else if(identifier==
"__builtin_expect")
3669 error() <<
"__builtin_expect expects two arguments" <<
eom;
3678 identifier ==
"__builtin_object_size" ||
3679 identifier ==
"__builtin_dynamic_object_size")
3690 error() <<
"__builtin_object_size expects two arguments" <<
eom;
3707 error() <<
"__builtin_object_size expects constant as second argument, "
3715 if(arg1==0 || arg1==1)
3728 else if(identifier==
"__builtin_choose_expr")
3734 error() <<
"__builtin_choose_expr expects three arguments" <<
eom;
3749 else if(identifier==
"__builtin_constant_p")
3756 error() <<
"__builtin_constant_p expects one argument" <<
eom;
3772 tmp1.
id() == ID_typecast &&
3778 .
id() == ID_string_constant)
3790 else if(identifier==
"__builtin_classify_type")
3797 error() <<
"__builtin_classify_type expects one argument" <<
eom;
3808 const typet &type =
object.type().
id() == ID_c_bit_field
3812 unsigned type_number;
3814 if(type.
id() == ID_bool || type.
id() == ID_c_bool)
3822 type_number = type.
id() == ID_empty ? 0u
3823 : (type.
id() == ID_bool || type.
id() == ID_c_bool) ? 4u
3824 : (type.
id() == ID_pointer || type.
id() == ID_array) ? 5u
3825 : type.
id() == ID_floatbv ? 8u
3826 : (type.
id() == ID_complex &&
3829 : type.
id() == ID_struct_tag ? 12u
3830 : type.
id() == ID_union_tag
3841 identifier ==
"__builtin_add_overflow" ||
3842 identifier ==
"__builtin_sadd_overflow" ||
3843 identifier ==
"__builtin_saddl_overflow" ||
3844 identifier ==
"__builtin_saddll_overflow" ||
3845 identifier ==
"__builtin_uadd_overflow" ||
3846 identifier ==
"__builtin_uaddl_overflow" ||
3847 identifier ==
"__builtin_uaddll_overflow" ||
3848 identifier ==
"__builtin_add_overflow_p")
3853 identifier ==
"__builtin_sub_overflow" ||
3854 identifier ==
"__builtin_ssub_overflow" ||
3855 identifier ==
"__builtin_ssubl_overflow" ||
3856 identifier ==
"__builtin_ssubll_overflow" ||
3857 identifier ==
"__builtin_usub_overflow" ||
3858 identifier ==
"__builtin_usubl_overflow" ||
3859 identifier ==
"__builtin_usubll_overflow" ||
3860 identifier ==
"__builtin_sub_overflow_p")
3865 identifier ==
"__builtin_mul_overflow" ||
3866 identifier ==
"__builtin_smul_overflow" ||
3867 identifier ==
"__builtin_smull_overflow" ||
3868 identifier ==
"__builtin_smulll_overflow" ||
3869 identifier ==
"__builtin_umul_overflow" ||
3870 identifier ==
"__builtin_umull_overflow" ||
3871 identifier ==
"__builtin_umulll_overflow" ||
3872 identifier ==
"__builtin_mul_overflow_p")
3877 identifier ==
"__builtin_bitreverse8" ||
3878 identifier ==
"__builtin_bitreverse16" ||
3879 identifier ==
"__builtin_bitreverse32" ||
3880 identifier ==
"__builtin_bitreverse64")
3885 std::ostringstream error_message;
3886 error_message <<
"error: " << identifier <<
" expects one operand";
3896 return std::move(bitreverse);
3912 std::ostringstream error_message;
3913 error_message << identifier <<
" takes exactly 3 arguments, but "
3914 << expr.
arguments().size() <<
" were provided";
3928 auto const raise_wrong_argument_error =
3930 const exprt &wrong_argument, std::size_t argument_number,
bool _p) {
3931 std::ostringstream error_message;
3932 error_message <<
"error: " << identifier <<
" has signature "
3933 << identifier <<
"(integral, integral, integral"
3934 << (_p ?
"" :
"*") <<
"), "
3935 <<
"but argument " << argument_number <<
" ("
3936 <<
expr2c(wrong_argument, *
this) <<
") has type `"
3937 <<
type2c(wrong_argument.
type(), *
this) <<
'`';
3941 for(
int arg_index = 0; arg_index <= (!is__p_variant ? 1 : 2); ++arg_index)
3943 auto const &argument = expr.
arguments()[arg_index];
3947 raise_wrong_argument_error(argument, arg_index + 1, is__p_variant);
3951 !is__p_variant && (
result.type().id() != ID_pointer ||
3955 raise_wrong_argument_error(
result, 3, is__p_variant);
3974 std::ostringstream error_message;
3975 error_message <<
"error: " << identifier
3976 <<
" takes exactly two arguments, but "
3977 << expr.
arguments().size() <<
" were provided";
3985 identifier ==
"__builtin_elementwise_sub_sat")
3991 identifier ==
"__builtin_elementwise_add_sat")
4016 if(code_type.
get_bool(ID_C_incomplete))
4020 else if(code_type.
is_KnR())
4024 for(std::size_t i = arguments.size(); i < parameters.size(); ++i)
4026 arguments.push_back(
4032 if(parameters.size() > arguments.size())
4035 error() <<
"not enough function arguments" <<
eom;
4039 else if(parameters.size() != arguments.size())
4042 error() <<
"wrong number of function arguments: "
4043 <<
"expected " << parameters.size() <<
", but got "
4044 << arguments.size() <<
eom;
4048 for(std::size_t i=0; i<arguments.size(); i++)
4050 exprt &op=arguments[i];
4056 else if(i < parameters.size())
4062 op.
get(ID_statement) == ID_assign && op.
type().
id() != ID_bool)
4065 warning() <<
"assignment where Boolean argument is expected" <<
eom;
4074 if(op.
type().
id() == ID_array)
4077 dest_type.base_type().set(ID_C_constant,
true);
4095 if(o_type.
id()==ID_vector)
4114 error() <<
"operator '" << expr.
id() <<
"' not defined for type '"
4169 if(o_type0.
id()==ID_vector &&
4170 o_type1.
id()==ID_vector)
4184 o_type0.
id() == ID_vector && o_type1.
id() != ID_vector &&
4189 expr.
type() = o_type0;
4193 o_type0.
id() != ID_vector && o_type1.
id() == ID_vector &&
4198 expr.
type() = o_type1;
4202 if(expr.
id() == ID_saturating_minus || expr.
id() == ID_saturating_plus)
4215 if(expr.
id()==ID_plus || expr.
id()==ID_minus ||
4216 expr.
id()==ID_mult || expr.
id()==ID_div)
4218 if(type0.
id()==ID_pointer || type1.
id()==ID_pointer)
4223 else if(type0==type1)
4232 else if(expr.
id()==ID_mod)
4236 if(type0.
id()==ID_signedbv || type0.
id()==ID_unsignedbv)
4244 expr.
id() == ID_bitand || expr.
id() == ID_bitnand ||
4245 expr.
id() == ID_bitxor || expr.
id() == ID_bitor)
4254 else if(type0.
id()==ID_bool)
4256 if(expr.
id()==ID_bitand)
4258 else if(expr.
id() == ID_bitnand)
4260 else if(expr.
id()==ID_bitor)
4262 else if(expr.
id()==ID_bitxor)
4271 else if(expr.
id() == ID_saturating_minus || expr.
id() == ID_saturating_plus)
4275 (type0.
id() == ID_signedbv || type0.
id() == ID_unsignedbv))
4277 expr.
type() = type0;
4283 error() <<
"operator '" << expr.
id() <<
"' not defined for types '"
4299 if(o_type0.
id()==ID_vector &&
4300 o_type1.
id()==ID_vector)
4316 o_type0.
id() == ID_vector &&
4334 if(expr.
id()==ID_shr)
4338 if(op0_type.
id()==ID_unsignedbv)
4343 else if(op0_type.
id()==ID_signedbv)
4354 error() <<
"operator '" << expr.
id() <<
"' not defined for types '"
4368 base_type.
id() == ID_struct_tag &&
4372 error() <<
"pointer arithmetic with unknown object size" <<
eom;
4376 base_type.
id() == ID_union_tag &&
4380 error() <<
"pointer arithmetic with unknown object size" <<
eom;
4384 base_type.
id() == ID_empty &&
4388 error() <<
"pointer arithmetic with unknown object size" <<
eom;
4391 else if(base_type.
id() == ID_empty)
4409 if(expr.
id()==ID_minus ||
4410 (expr.
id()==ID_side_effect && expr.
get(ID_statement)==ID_assign_minus))
4412 if(type0.
id()==ID_pointer &&
4413 type1.
id()==ID_pointer)
4426 if(type0.
id()==ID_pointer &&
4427 (type1.
id()==ID_bool ||
4428 type1.
id()==ID_c_bool ||
4429 type1.
id()==ID_unsignedbv ||
4430 type1.
id()==ID_signedbv ||
4431 type1.
id()==ID_c_bit_field ||
4432 type1.
id()==ID_c_enum_tag))
4440 else if(expr.
id()==ID_plus ||
4441 (expr.
id()==ID_side_effect && expr.
get(ID_statement)==ID_assign_plus))
4443 exprt *p_op, *int_op;
4445 if(type0.
id()==ID_pointer)
4450 else if(type1.
id()==ID_pointer)
4457 p_op=int_op=
nullptr;
4461 const typet &int_op_type = int_op->
type();
4463 if(int_op_type.
id()==ID_bool ||
4464 int_op_type.
id()==ID_c_bool ||
4465 int_op_type.
id()==ID_unsignedbv ||
4466 int_op_type.
id()==ID_signedbv ||
4467 int_op_type.
id()==ID_c_bit_field ||
4468 int_op_type.
id()==ID_c_enum_tag)
4479 if(expr.
id()==ID_side_effect)
4485 error() <<
"operator '" << op_name <<
"' not defined for types '"
4516 if(type0.
id()==ID_empty)
4519 error() <<
"cannot assign void" <<
eom;
4526 error() <<
"assignment error: '" <<
to_string(op0) <<
"' not an lvalue"
4539 if(type0.
id() == ID_array)
4542 error() <<
"direct assignments to arrays not permitted" <<
eom;
4548 if(op0.
type() != op1.
type() && op0.
type().
id() == ID_c_bit_field)
4557 expr.
type()=o_type0;
4559 if(statement==ID_assign)
4564 else if(statement==ID_assign_shl ||
4565 statement==ID_assign_shr)
4567 if(o_type0.
id() == ID_vector)
4572 o_type1.
id() == ID_vector &&
4573 vector_o_type0.element_type() ==
4575 is_number(vector_o_type0.element_type()))
4591 if(statement==ID_assign_shl)
4601 if(underlying_type.
id()==ID_unsignedbv ||
4602 underlying_type.
id()==ID_c_bool)
4604 expr.
set(ID_statement, ID_assign_lshr);
4607 else if(underlying_type.
id()==ID_signedbv)
4609 expr.
set(ID_statement, ID_assign_ashr);
4615 else if(statement==ID_assign_bitxor ||
4616 statement==ID_assign_bitand ||
4617 statement==ID_assign_bitor)
4620 if(o_type0.
id()==ID_bool ||
4621 o_type0.
id()==ID_c_bool)
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_c_enum_tag ||
4633 o_type0.
id()==ID_unsignedbv ||
4634 o_type0.
id()==ID_signedbv ||
4635 o_type0.
id()==ID_c_bit_field)
4639 op1.
type().
id() == ID_c_enum_tag || op1.
type().
id() == ID_unsignedbv ||
4640 op1.
type().
id() == ID_signedbv || op1.
type().
id() == ID_c_bit_field)
4645 else if(o_type0.
id()==ID_vector &&
4646 o_type1.
id()==ID_vector)
4657 o_type0.
id() == ID_vector &&
4658 (o_type1.
id() == ID_bool || o_type1.
id() == ID_c_bool ||
4659 o_type1.
id() == ID_c_enum_tag || o_type1.
id() == ID_unsignedbv ||
4660 o_type1.
id() == ID_signedbv))
4669 if(o_type0.
id()==ID_pointer &&
4670 (statement==ID_assign_minus || statement==ID_assign_plus))
4675 else if(o_type0.
id()==ID_vector &&
4676 o_type1.
id()==ID_vector)
4686 else if(o_type0.
id() == ID_vector)
4692 op1.
type().
id() == ID_c_bool || op1.
type().
id() == ID_c_enum_tag)
4698 else if(o_type0.
id()==ID_bool ||
4699 o_type0.
id()==ID_c_bool)
4704 op1.
type().
id() == ID_c_enum_tag || op1.
type().
id() == ID_unsignedbv ||
4705 op1.
type().
id() == ID_signedbv)
4716 op1.
type().
id() == ID_c_bool || op1.
type().
id() == ID_c_enum_tag)
4724 error() <<
"assignment '" << statement <<
"' not defined for types '"
4754 if(e.
id() == ID_infinity)
4760 if(e.
id() == ID_address_of)
4765 e.
id() == ID_typecast || e.
id() == ID_array_of || e.
id() == ID_plus ||
4766 e.
id() == ID_mult || e.
id() == ID_array || e.
id() == ID_with ||
4767 e.
id() == ID_struct || e.
id() == ID_union || e.
id() == ID_empty_union ||
4768 e.
id() == ID_equal || e.
id() == ID_notequal || e.
id() == ID_lt ||
4769 e.
id() == ID_le || e.
id() == ID_gt || e.
id() == ID_ge ||
4770 e.
id() == ID_if || e.
id() == ID_not || e.
id() == ID_and ||
4771 e.
id() == ID_or || e.
id() == ID_bitnot || e.
id() == ID_bitand ||
4772 e.
id() == ID_bitor || e.
id() == ID_bitxor || e.
id() == ID_vector)
4776 return is_constant(op);
4786 if(e.
id() == ID_symbol)
4788 return e.
type().
id() == ID_code ||
4791 else if(e.
id() == ID_array && e.
get_bool(ID_C_string_constant))
4793 else if(e.
id() == ID_label)
4795 else if(e.
id() == ID_index)
4802 else if(e.
id() == ID_member)
4806 else if(e.
id() == ID_dereference)
4812 else if(e.
id() == ID_string_constant)
4826 const auto rounding_mode =
4836 error() <<
"expected constant expression, but got '" <<
to_string(expr)
4853 error() <<
"conversion to integer constant failed" <<
eom;
4861 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
static const commandt quote_begin
Start quoted text.
message_handlert & get_message_handler()
mstreamt & warning() const
static const commandt quote_end
End quoted text.
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 identifier(const irep_idt &identifier)
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)