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;
322 error() <<
"quantifier must not contain side effects" <<
eom;
327 for(
auto &binding : bindings)
330 if(expr.
id() == ID_lambda)
334 for(
auto &binding : bindings)
335 domain.push_back(binding.type());
345 else if(expr.
id()==ID_label)
349 else if(expr.
id()==ID_array)
353 else if(expr.
id()==ID_complex)
358 else if(expr.
id() == ID_complex_real)
362 if(op.
type().
id() != ID_complex)
367 error() <<
"real part retrieval expects numerical operand, "
375 expr.
swap(complex_real_expr);
383 complex_real_expr.
set(ID_C_lvalue,
true);
386 complex_real_expr.
type().
set(ID_C_constant,
true);
388 expr.
swap(complex_real_expr);
391 else if(expr.
id() == ID_complex_imag)
395 if(op.
type().
id() != ID_complex)
400 error() <<
"real part retrieval expects numerical operand, "
408 expr.
swap(complex_imag_expr);
416 complex_imag_expr.
set(ID_C_lvalue,
true);
419 complex_imag_expr.
type().
set(ID_C_constant,
true);
421 expr.
swap(complex_imag_expr);
424 else if(expr.
id()==ID_generic_selection)
441 for(
auto &irep : generic_associations)
443 if(irep.get(ID_type_arg) != ID_default)
445 typet &type =
static_cast<typet &
>(irep.add(ID_type_arg));
454 const typet &op_type = op.type();
456 for(
const auto &irep : generic_associations)
458 if(irep.get(ID_type_arg) == ID_default)
459 default_match =
static_cast<const exprt &
>(irep.find(ID_value));
460 else if(op_type ==
static_cast<const typet &
>(irep.find(ID_type_arg)))
462 assoc_match =
static_cast<const exprt &
>(irep.find(ID_value));
469 expr.
swap(default_match);
473 error() <<
"unmatched generic selection: " <<
to_string(op.type())
479 expr.
swap(assoc_match);
484 else if(expr.
id()==ID_gcc_asm_input ||
485 expr.
id()==ID_gcc_asm_output ||
486 expr.
id()==ID_gcc_asm_clobbered_register)
489 else if(expr.
id()==ID_lshr || expr.
id()==ID_ashr ||
490 expr.
id()==ID_assign_lshr || expr.
id()==ID_assign_ashr)
495 expr.
id() == ID_C_spec_assigns || expr.
id() == ID_C_spec_frees ||
496 expr.
id() == ID_target_list)
500 else if(
auto bit_cast_expr = expr_try_dynamic_cast<bit_cast_exprt>(expr))
507 exprt tmp = bit_cast_expr->lower();
513 error() <<
"bit cast from '" <<
to_string(bit_cast_expr->op().type())
532 expr.
set(ID_C_lvalue,
true);
567 symbolt symbol{ID_gcc_builtin_va_arg, symbol_type, ID_C};
568 symbol.base_name=ID_gcc_builtin_va_arg;
597 error() <<
"builtin_offsetof expects no operands" <<
eom;
604 const exprt &member =
static_cast<const exprt &
>(expr.
add(ID_designator));
608 for(
const auto &op : member.
operands())
610 if(op.id() == ID_member)
612 if(type.
id() != ID_union_tag && type.
id() != ID_struct_tag)
615 error() <<
"offsetof of member expects struct/union type, "
621 irep_idt component_name = op.get(ID_component_name);
635 if(type.
id() == ID_struct_tag)
640 if(!o_opt.has_value())
643 error() <<
"offsetof failed to determine offset of '"
644 << component_name <<
"'" <<
eom;
660 for(
const auto &c : struct_union_type.
components())
664 (c.type().id() == ID_struct_tag || c.type().id() == ID_union_tag))
668 if(type.
id() == ID_struct_tag)
673 if(!o_opt.has_value())
676 error() <<
"offsetof failed to determine offset of '"
677 << component_name <<
"'" <<
eom;
687 typet tmp = c.type();
690 type.
id() == ID_union_tag || type.
id() == ID_struct_tag);
700 error() <<
"offset-of of member failed to find component '"
701 << component_name <<
"' in '" <<
to_string(type) <<
"'"
708 else if(op.id() == ID_index)
710 if(type.
id()!=ID_array)
713 error() <<
"offsetof of index expects array type" <<
eom;
722 auto element_size_opt =
725 if(!element_size_opt.has_value())
728 error() <<
"offsetof failed to determine array element size" <<
eom;
751 if(expr.
id()==ID_side_effect &&
752 expr.
get(ID_statement)==ID_function_call)
757 else if(expr.
id()==ID_side_effect &&
758 expr.
get(ID_statement)==ID_statement_expression)
763 expr.
id() == ID_forall || expr.
id() == ID_exists || expr.
id() == ID_lambda)
769 auto &bindings = binary_expr.op0().operands();
771 for(
auto &binding : bindings)
780 error() <<
"forall/exists expects one declarator exactly" <<
eom;
787 symbol_table_baset::symbolst::const_iterator s_it =
793 error() <<
"failed to find bound symbol `" << identifier
794 <<
"' in symbol table" <<
eom;
798 const symbolt &symbol = s_it->second;
805 error() <<
"unexpected quantified symbol" <<
eom;
829 id_type_mapt::const_iterator p_it=
parameter_map.find(identifier);
833 expr.
type()=p_it->second;
834 expr.
set(ID_C_lvalue,
true);
839 asm_label_mapt::const_iterator entry=
843 identifier=entry->second;
849 if(
lookup(identifier, symbol_ptr))
852 error() <<
"failed to find symbol '" << identifier <<
"'" <<
eom;
856 const symbolt &symbol=*symbol_ptr;
861 error() <<
"did not expect a type symbol here, but got '"
880 expr.
set(ID_C_cformat, base_name);
895 else if(identifier==
"__func__" ||
896 identifier==
"__FUNCTION__" ||
897 identifier==
"__PRETTY_FUNCTION__")
903 s.
set(ID_C_lvalue,
true);
914 expr.
set(ID_C_lvalue,
true);
916 if(expr.
type().
id()==ID_code)
919 tmp.
set(ID_C_implicit,
true);
938 if(last_statement==ID_expression)
944 if(op.
type().
id()==ID_array)
986 if(type.
id()==ID_c_bit_field)
990 if(op.
id() == ID_comma || op.
id() == ID_side_effect)
1004 if(!size_of_opt.has_value())
1007 error() <<
"type has no size: "
1012 new_expr = size_of_opt.value();
1018 error() <<
"sizeof cannot be applied to bit fields" <<
eom;
1022 else if(type.
id() == ID_bool)
1025 error() <<
"sizeof cannot be applied to single bits" <<
eom;
1028 else if(type.
id() == ID_empty)
1037 (type.
id() == ID_struct_tag &&
1039 (type.
id() == ID_union_tag &&
1041 (type.
id() == ID_c_enum_tag &&
1046 error() <<
"invalid application of \'sizeof\' to an incomplete type\n\t\'"
1053 if(!size_of_opt.has_value())
1060 new_expr = size_of_opt.value();
1064 new_expr.
swap(expr);
1066 expr.
add(ID_C_c_sizeof_type)=type;
1072 ID_statement_expression,
void_type(), location);
1074 decl_block.set_statement(ID_decl_block);
1087 expr.
swap(comma_expr);
1093 typet argument_type;
1101 argument_type=op_type;
1125 decl_block.set_statement(ID_decl_block);
1136 std::move(side_effect_expr), ID_comma, op, op.
type()};
1137 op.
swap(comma_expr);
1143 expr_type.
id() == ID_union_tag && expr_type != op.
type() &&
1144 op.
id() != ID_initializer_list)
1157 for(
const auto &c : union_type.components())
1159 if(c.type() == op.
type())
1165 expr.
set(ID_C_lvalue,
true);
1173 <<
"' not found in union" <<
eom;
1180 if(op.
id()==ID_initializer_list)
1189 exprt tmp(ID_compound_literal, expr.
type());
1193 if(op.
id()==ID_array &&
1194 expr.
type().
id()==ID_array &&
1199 expr.
set(ID_C_lvalue,
true);
1204 if(expr_type.
id()==ID_empty)
1210 if(expr_type == op_type)
1215 if(expr_type.
id()==ID_vector)
1218 if(op_type.
id()==ID_vector)
1220 else if(op_type.
id()==ID_signedbv ||
1221 op_type.
id()==ID_unsignedbv)
1228 error() <<
"type cast to '" <<
to_string(expr_type) <<
"' is not permitted"
1236 else if(op_type.
id()==ID_array)
1241 if(error_opt.has_value())
1247 else if(op_type.
id()==ID_empty)
1249 if(expr_type.
id()!=ID_empty)
1252 error() <<
"type cast from void only permitted to void, but got '"
1257 else if(op_type.
id()==ID_vector)
1264 if((expr_type.
id()==ID_signedbv ||
1265 expr_type.
id()==ID_unsignedbv) &&
1274 <<
"' not permitted" <<
eom;
1281 error() <<
"type cast from '" <<
to_string(op_type) <<
"' not permitted"
1297 if(expr_type.
id()==ID_pointer)
1298 expr.
set(ID_C_lvalue,
true);
1315 const typet &array_type = array_expr.
type();
1316 const typet &index_type = index_expr.
type();
1319 array_type.
id() != ID_array && array_type.
id() != ID_pointer &&
1320 array_type.
id() != ID_vector &&
1321 (index_type.
id() == ID_array || index_type.
id() == ID_pointer ||
1322 index_type.
id() == ID_vector))
1323 std::swap(array_expr, index_expr);
1331 const typet final_array_type = array_expr.
type();
1333 if(final_array_type.
id()==ID_array ||
1334 final_array_type.
id()==ID_vector)
1338 if(array_expr.
get_bool(ID_C_lvalue))
1339 expr.
set(ID_C_lvalue,
true);
1341 if(final_array_type.
get_bool(ID_C_constant))
1342 expr.
type().
set(ID_C_constant,
true);
1344 else if(final_array_type.
id()==ID_pointer)
1350 std::swap(summands, expr.
operands());
1352 expr.
id(ID_dereference);
1353 expr.
set(ID_C_lvalue,
true);
1359 error() <<
"operator [] must take array/vector or pointer but got '"
1368 if(expr.
op0().
type().
id() == ID_floatbv)
1370 if(expr.
id()==ID_equal)
1371 expr.
id(ID_ieee_float_equal);
1372 else if(expr.
id()==ID_notequal)
1373 expr.
id(ID_ieee_float_notequal);
1386 if(o_type0.
id() == ID_vector || o_type1.
id() == ID_vector)
1394 if(expr.
id()==ID_equal || expr.
id()==ID_notequal)
1396 if(o_type0 == o_type1)
1398 if(o_type0.
id() != ID_array)
1419 if(type0.
id()==ID_pointer)
1421 if(expr.
id()==ID_equal || expr.
id()==ID_notequal)
1424 if(expr.
id()==ID_le || expr.
id()==ID_lt ||
1425 expr.
id()==ID_ge || expr.
id()==ID_gt)
1429 if(type0.
id()==ID_string_constant)
1431 if(expr.
id()==ID_equal || expr.
id()==ID_notequal)
1438 if(type0.
id()==ID_pointer &&
1445 if(type1.
id()==ID_pointer &&
1465 if(type0.
id()==ID_pointer && type1.
id()==ID_pointer)
1473 error() <<
"operator '" << expr.
id() <<
"' not defined for types '"
1484 if(o_type0.
id() != ID_vector || o_type0 != o_type1)
1487 error() <<
"vector operator '" << expr.
id() <<
"' not defined for types '"
1495 auto subtype_width =
1504 if(expr.
id() == ID_notequal)
1505 expr.
id(ID_vector_notequal);
1513 const typet &op0_type = op.type();
1515 if(op0_type.
id() == ID_array)
1520 index_expr.
set(ID_C_lvalue,
true);
1521 op.swap(index_expr);
1523 else if(op0_type.
id() == ID_pointer)
1534 error() <<
"ptrmember operator requires pointer or array type "
1535 "on left hand side, but got '"
1549 if(type.
id() != ID_struct_tag && type.
id() != ID_union_tag)
1552 error() <<
"member operator requires structure type "
1553 "on left hand side but got '"
1564 error() <<
"member operator got incomplete " << type.
id()
1565 <<
" type on left hand side" <<
eom;
1570 expr.
get(ID_component_name);
1586 error() <<
"member '" << component_name <<
"' not found in '"
1599 expr.
set(ID_C_lvalue,
true);
1603 struct_union_type.
get_bool(ID_C_constant))
1605 expr.
type().
set(ID_C_constant,
true);
1611 if(!identifier.
empty())
1612 expr.
set(ID_C_identifier, identifier);
1616 if(access==ID_private)
1619 error() <<
"member '" << component_name <<
"' is " << access <<
eom;
1631 const typet o_type0=operands[0].type();
1632 const typet o_type1=operands[1].type();
1633 const typet o_type2=operands[2].type();
1637 if(o_type1.
id() == ID_empty || o_type2.
id() == ID_empty)
1646 auto string_constant = expr_try_dynamic_cast<string_constantt>(operands[1]))
1652 auto string_constant = expr_try_dynamic_cast<string_constantt>(operands[2]))
1657 if(operands[1].type().
id()==ID_pointer &&
1658 operands[2].type().
id()!=ID_pointer)
1660 else if(operands[2].type().
id()==ID_pointer &&
1661 operands[1].type().
id()!=ID_pointer)
1664 if(operands[1].type().
id()==ID_pointer &&
1665 operands[2].type().
id()==ID_pointer &&
1666 operands[1].type()!=operands[2].type())
1713 if(operands[1].type().
id()==ID_empty ||
1714 operands[2].type().
id()==ID_empty)
1721 operands[1].type() != operands[2].type() ||
1722 operands[1].type().
id() == ID_array)
1727 if(operands[1].type() == operands[2].type())
1729 expr.
type()=operands[1].type();
1735 if(operands[1].get_bool(ID_C_lvalue) &&
1736 operands[2].get_bool(ID_C_lvalue))
1737 expr.
set(ID_C_lvalue,
true);
1743 error() <<
"operator ?: not defined for types '" <<
to_string(o_type1)
1756 if(operands.size()!=2)
1759 error() <<
"gcc conditional_expr expects two operands" <<
eom;
1765 if_exprt if_expr(operands[0], operands[0], operands[1]);
1782 if(error_opt.has_value())
1786 if(op.
id()==ID_label)
1799 op.
id() == ID_address_of && op.
get_bool(ID_C_implicit) &&
1805 tmp.
set(ID_C_implicit,
false);
1810 if(op.
id()==ID_struct ||
1811 op.
id()==ID_union ||
1812 op.
id()==ID_array ||
1813 op.
id()==ID_string_constant)
1821 else if(op.
type().
id()==ID_code)
1828 error() <<
"address_of error: '" <<
to_string(op) <<
"' not an lvalue"
1842 if(op_type.
id()==ID_array)
1850 else if(op_type.
id()==ID_pointer)
1855 expr.
type().
id() == ID_empty &&
1859 error() <<
"dereferencing void pointer" <<
eom;
1867 <<
"' is not a pointer, but got '" <<
to_string(op_type) <<
"'"
1872 expr.
set(ID_C_lvalue,
true);
1883 if(expr.
type().
id()==ID_code)
1886 tmp.
set(ID_C_implicit,
true);
1896 if(statement==ID_preincrement ||
1897 statement==ID_predecrement ||
1898 statement==ID_postincrement ||
1899 statement==ID_postdecrement)
1908 <<
"' not an lvalue" <<
eom;
1919 if(type0.
id() == ID_c_enum_tag)
1925 error() <<
"operator '" << statement <<
"' given incomplete type '"
1935 else if(type0.
id() == ID_c_bit_field)
1939 typet type_before{type0};
1941 expr.
type()=underlying_type;
1945 else if(type0.
id() == ID_bool || type0.
id() == ID_c_bool)
1954 else if(type0.
id() == ID_pointer)
1962 error() <<
"operator '" << statement <<
"' not defined for type '"
1969 else if(statement==ID_function_call)
1972 else if(statement==ID_statement_expression)
1974 else if(statement==ID_gcc_conditional_expression)
1979 error() <<
"unknown side effect: " << statement <<
eom;
1991 "expression must be a " CPROVER_PREFIX "typed_target function call");
1998 "expected 1 argument for " CPROVER_PREFIX "typed_target, found " +
2009 arg0.source_location()};
2013 if(!size.has_value())
2017 "typed_target of type " +
2019 arg0.source_location()};
2028 arguments.push_back(size.value());
2030 if(arg0.type().id() == ID_pointer)
2046 "expression must be a " CPROVER_PREFIX "obeys_contract function call");
2051 "expected 2 arguments for " CPROVER_PREFIX "obeys_contract, found " +
2058 auto &function_pointer = expr.
arguments()[0];
2061 function_pointer.type().id() != ID_pointer ||
2063 !function_pointer.get_bool(ID_C_lvalue))
2067 "obeys_contract must be a function pointer lvalue expression",
2068 function_pointer.source_location());
2075 "obeys_contract must have no ternary operator",
2076 function_pointer.source_location());
2080 auto &address_of_contract = expr.
arguments()[1];
2083 address_of_contract.id() != ID_address_of ||
2085 address_of_contract.
type().
id() != ID_pointer ||
2090 "obeys_contract must must be a function symbol",
2091 address_of_contract.source_location());
2094 if(function_pointer.type() != address_of_contract.type())
2098 "obeys_contract must have the same function pointer type",
2120 error() <<
"function_call side effect expects two operands" <<
eom;
2129 if(f_op.
id()==ID_symbol)
2133 asm_label_mapt::const_iterator entry=
2136 identifier=entry->second;
2153 identifier ==
"__noop" &&
2167 identifier ==
"__builtin_shuffle" &&
2175 else if(identifier ==
"__builtin_shufflevector")
2185 identifier ==
"__builtin_elementwise_add_sat" ||
2186 identifier ==
"__builtin_elementwise_sub_sat")
2198 error() <<
"equal expects two operands" <<
eom;
2209 error() <<
"equal expects two operands of same type" <<
eom;
2213 expr.
swap(equality_expr);
2227 overflow.
id(ID_minus);
2232 overflow.id(ID_mult);
2237 overflow.id(ID_plus);
2242 overflow.id(ID_shl);
2247 overflow.
operands()[0], overflow.id(), overflow.operands()[1]};
2248 of.add_source_location() = overflow.source_location();
2260 overflow.add_source_location() = tmp.source_location();
2261 expr.
swap(overflow);
2269 std::ostringstream error_message;
2270 error_message << identifier <<
" takes exactly 1 argument, but "
2271 << expr.
arguments().size() <<
" were provided";
2279 std::ostringstream error_message;
2280 error_message << identifier <<
" expects enum, but ("
2281 <<
expr2c(arg1, *
this) <<
") has type `"
2282 <<
type2c(arg1.type(), *
this) <<
'`';
2289 exprt lowered = in_range.lower(*
this);
2301 id2string(identifier) +
" expects one or two operands",
2306 auto &pointer_expr = expr.
arguments()[0];
2307 if(pointer_expr.type().id() == ID_array)
2310 dest_type.base_type().set(ID_C_constant,
true);
2313 else if(pointer_expr.type().id() != ID_pointer)
2316 id2string(identifier) +
" expects a pointer as first argument",
2332 const auto &subtype =
2334 if(subtype.id() == ID_empty)
2338 " expects a size when given a void pointer",
2344 size_expr = std::move(size_expr_opt.value());
2360 irep_idt shadow_memory_builtin_id =
2361 shadow_memory_builtin->get_identifier();
2363 const auto builtin_code_type =
2367 builtin_code_type.has_ellipsis() &&
2368 builtin_code_type.parameters().empty(),
2369 "Shadow memory builtins should be an ellipsis with 0 parameter");
2375 shadow_memory_builtin_id, shadow_memory_builtin->type(), ID_C};
2376 new_symbol.base_name = shadow_memory_builtin_id;
2387 f_op = std::move(*shadow_memory_builtin);
2393 irep_idt identifier_with_type = gcc_polymorphic->get_identifier();
2396 !parameters.empty(),
2397 "GCC polymorphic built-ins should have at least one parameter");
2402 if(parameters.front().type().id() == ID_pointer)
2404 identifier_with_type =
2411 identifier_with_type =
2415 gcc_polymorphic->set_identifier(identifier_with_type);
2419 for(std::size_t i = 0; i < parameters.size(); ++i)
2426 id2string(identifier_with_type) +
"::" + base_name;
2429 new_symbol.
type = parameters[i].type();
2432 new_symbol.
mode = ID_C;
2434 parameters[i].set_identifier(new_symbol.
name);
2435 parameters[i].set_base_name(new_symbol.
base_name);
2441 identifier_with_type, gcc_polymorphic->type(), ID_C};
2442 new_symbol.base_name = identifier_with_type;
2450 new_symbol.value = implementation;
2455 f_op = std::move(*gcc_polymorphic);
2467 if(identifier==
"malloc" ||
2468 identifier==
"realloc" ||
2469 identifier==
"reallocf" ||
2470 identifier==
"valloc")
2477 new_symbol.base_name=identifier;
2479 new_symbol.type.
set(ID_C_incomplete,
true);
2491 debug() <<
"builtin '" << identifier <<
"' is unknown" <<
eom;
2496 warning() <<
"function '" << identifier <<
"' is not declared" <<
eom;
2507 if(f_op_type.
id() == ID_mathematical_function)
2509 const auto &mathematical_function_type =
2513 if(expr.
arguments().size() != mathematical_function_type.domain().size())
2516 error() <<
"expected " << mathematical_function_type.domain().size()
2517 <<
" arguments but got " << expr.
arguments().size() <<
eom;
2525 if(p.first.type() != p.second)
2538 expr.
swap(function_application);
2542 if(f_op_type.
id()!=ID_pointer)
2545 error() <<
"expected function/function pointer as argument but got '"
2551 if(f_op.
id() == ID_address_of && f_op.
get_bool(ID_C_implicit))
2558 tmp.
set(ID_C_implicit,
true);
2563 if(f_op.
type().
id()!=ID_code)
2566 error() <<
"expected code as argument" <<
eom;
2589 if(f_op.
id()!=ID_symbol)
2625 if(arg.type().id() != ID_pointer)
2629 "pointer_in_range_dfcc expects pointer-typed arguments",
2630 arg.source_location()};
2640 error() <<
"same_object expects two operands" <<
eom;
2646 exprt same_object_expr=
2650 return same_object_expr;
2657 error() <<
"get_must expects two operands" <<
eom;
2667 return std::move(get_must_expr);
2674 error() <<
"get_may expects two operands" <<
eom;
2684 return std::move(get_may_expr);
2691 error() <<
"is_invalid_pointer expects one operand" <<
eom;
2700 return same_object_expr;
2707 error() <<
"buffer_size expects one operand" <<
eom;
2717 return buffer_size_expr;
2725 error() <<
"is_list expects one operand" <<
eom;
2732 expr.
arguments()[0].type().id() != ID_pointer ||
2737 error() <<
"is_list expects a struct-pointer operand" <<
eom;
2745 return std::move(is_list_expr);
2753 error() <<
"is_dll expects one operand" <<
eom;
2760 expr.
arguments()[0].type().id() != ID_pointer ||
2765 error() <<
"is_dll expects a struct-pointer operand" <<
eom;
2773 return std::move(is_dll_expr);
2781 error() <<
"is_cyclic_dll expects one operand" <<
eom;
2788 expr.
arguments()[0].type().id() != ID_pointer ||
2793 error() <<
"is_cyclic_dll expects a struct-pointer operand" <<
eom;
2801 return std::move(is_cyclic_dll_expr);
2809 error() <<
"is_sentinel_dll expects two or three operands" <<
eom;
2816 args_no_cast.reserve(expr.
arguments().size());
2817 for(
const auto &argument : expr.
arguments())
2821 args_no_cast.back().type().id() != ID_pointer ||
2826 error() <<
"is_sentinel_dll_node expects struct-pointer operands"
2833 is_sentinel_dll_expr.
operands() = args_no_cast;
2836 return std::move(is_sentinel_dll_expr);
2844 error() <<
"is_cstring expects one operand" <<
eom;
2850 if(expr.
arguments()[0].type().id() != ID_pointer)
2853 error() <<
"is_cstring expects a pointer operand" <<
eom;
2860 return std::move(is_cstring_expr);
2868 error() <<
"cstrlen expects one operand" <<
eom;
2874 if(expr.
arguments()[0].type().id() != ID_pointer)
2877 error() <<
"cstrlen expects a pointer operand" <<
eom;
2884 return std::move(cstrlen_expr);
2891 error() <<
"is_zero_string expects one operand" <<
eom;
2899 is_zero_string_expr.
set(ID_C_lvalue,
true);
2902 return std::move(is_zero_string_expr);
2909 error() <<
"zero_string_length expects one operand" <<
eom;
2915 exprt zero_string_length_expr(
"zero_string_length",
size_type());
2917 zero_string_length_expr.
set(ID_C_lvalue,
true);
2920 return zero_string_length_expr;
2927 error() <<
"dynamic_object expects one argument" <<
eom;
2936 return is_dynamic_object_expr;
2943 error() <<
"live_object expects one argument" <<
eom;
2952 return live_object_expr;
2959 error() <<
"pointer_in_range expects three arguments" <<
eom;
2969 return pointer_in_range_expr;
2976 error() <<
"writeable_object expects one argument" <<
eom;
2985 return writeable_object_expr;
2993 error() <<
"separate expects two or more arguments" <<
eom;
3002 return separate_expr;
3009 error() <<
"pointer_offset expects one argument" <<
eom;
3025 error() <<
"object_size expects one operand" <<
eom;
3034 return std::move(object_size_expr);
3041 error() <<
"pointer_object expects one argument" <<
eom;
3052 else if(identifier==
"__builtin_bswap16" ||
3053 identifier==
"__builtin_bswap32" ||
3054 identifier==
"__builtin_bswap64")
3059 error() << identifier <<
" expects one operand" <<
eom;
3069 return std::move(bswap_expr);
3072 identifier ==
"__builtin_rotateleft8" ||
3073 identifier ==
"__builtin_rotateleft16" ||
3074 identifier ==
"__builtin_rotateleft32" ||
3075 identifier ==
"__builtin_rotateleft64" ||
3076 identifier ==
"__builtin_rotateright8" ||
3077 identifier ==
"__builtin_rotateright16" ||
3078 identifier ==
"__builtin_rotateright32" ||
3079 identifier ==
"__builtin_rotateright64")
3085 error() << identifier <<
" expects two operands" <<
eom;
3091 irep_idt id = (identifier ==
"__builtin_rotateleft8" ||
3092 identifier ==
"__builtin_rotateleft16" ||
3093 identifier ==
"__builtin_rotateleft32" ||
3094 identifier ==
"__builtin_rotateleft64")
3101 return std::move(rotate_expr);
3103 else if(identifier==
"__builtin_nontemporal_load")
3108 error() << identifier <<
" expects one operand" <<
eom;
3117 if(ptr_arg.
type().
id()!=ID_pointer)
3120 error() <<
"__builtin_nontemporal_load takes pointer as argument" <<
eom;
3129 identifier ==
"__builtin_fpclassify" ||
3135 error() << identifier <<
" expects six arguments" <<
eom;
3148 if(fp_value.
type().
id() != ID_floatbv)
3151 error() <<
"non-floating-point argument for " << identifier <<
eom;
3159 const auto &arguments = expr.
arguments();
3178 identifier==
"__builtin_isnan")
3183 error() <<
"isnan expects one operand" <<
eom;
3201 error() <<
"isfinite expects one operand" <<
eom;
3213 identifier==
"__builtin_inf")
3220 return std::move(inf_expr);
3229 return std::move(inff_expr);
3238 return std::move(infl_expr);
3251 error() <<
"abs-functions expect one operand" <<
eom;
3260 return std::move(abs_expr);
3270 error() <<
"fmod-functions expect two operands" <<
eom;
3284 return std::move(fmod_expr);
3294 error() <<
"remainder-functions expect two operands" <<
eom;
3308 return std::move(floatbv_rem_expr);
3315 error() <<
"allocate expects two operands" <<
eom;
3324 return std::move(malloc_expr);
3333 error() << identifier <<
" expects one operand" <<
eom;
3337 const auto ¶m_id = expr.
arguments().front().id();
3338 if(!(param_id == ID_dereference || param_id == ID_member ||
3339 param_id == ID_symbol || param_id == ID_ptrmember ||
3340 param_id == ID_constant || param_id == ID_typecast ||
3341 param_id == ID_index))
3344 error() <<
"Tracking history of " << param_id
3345 <<
" expressions is not supported yet." <<
eom;
3354 return std::move(old_expr);
3359 identifier==
"__builtin_isinf")
3364 error() << identifier <<
" expects one operand" <<
eom;
3372 if(fp_value.
type().
id() != ID_floatbv)
3375 error() <<
"non-floating-point argument for " << identifier <<
eom;
3384 else if(identifier ==
"__builtin_isinf_sign")
3389 error() << identifier <<
" expects one operand" <<
eom;
3399 if(fp_value.
type().
id() != ID_floatbv)
3402 error() <<
"non-floating-point argument for " << identifier <<
eom;
3420 identifier ==
"__builtin_isnormal")
3425 error() << identifier <<
" expects one operand" <<
eom;
3433 if(fp_value.
type().
id() != ID_floatbv)
3436 error() <<
"non-floating-point argument for " << identifier <<
eom;
3448 identifier==
"__builtin_signbit" ||
3449 identifier==
"__builtin_signbitf" ||
3450 identifier==
"__builtin_signbitl")
3455 error() << identifier <<
" expects one operand" <<
eom;
3466 else if(identifier==
"__builtin_popcount" ||
3467 identifier==
"__builtin_popcountl" ||
3468 identifier==
"__builtin_popcountll" ||
3469 identifier==
"__popcnt16" ||
3470 identifier==
"__popcnt" ||
3471 identifier==
"__popcnt64")
3476 error() << identifier <<
" expects one operand" <<
eom;
3485 return std::move(popcount_expr);
3488 identifier ==
"__builtin_clz" || identifier ==
"__builtin_clzl" ||
3489 identifier ==
"__builtin_clzll" || identifier ==
"__lzcnt16" ||
3490 identifier ==
"__lzcnt" || identifier ==
"__lzcnt64")
3495 error() << identifier <<
" expects one operand" <<
eom;
3505 return std::move(clz);
3508 identifier ==
"__builtin_ctz" || identifier ==
"__builtin_ctzl" ||
3509 identifier ==
"__builtin_ctzll")
3514 error() << identifier <<
" expects one operand" <<
eom;
3524 return std::move(ctz);
3527 identifier ==
"__builtin_ffs" || identifier ==
"__builtin_ffsl" ||
3528 identifier ==
"__builtin_ffsll")
3533 error() << identifier <<
" expects one operand" <<
eom;
3542 return std::move(ffs);
3544 else if(identifier==
"__builtin_expect")
3555 error() <<
"__builtin_expect expects two arguments" <<
eom;
3564 identifier ==
"__builtin_object_size" ||
3565 identifier ==
"__builtin_dynamic_object_size")
3576 error() <<
"__builtin_object_size expects two arguments" <<
eom;
3593 error() <<
"__builtin_object_size expects constant as second argument, "
3601 if(arg1==0 || arg1==1)
3614 else if(identifier==
"__builtin_choose_expr")
3620 error() <<
"__builtin_choose_expr expects three arguments" <<
eom;
3635 else if(identifier==
"__builtin_constant_p")
3642 error() <<
"__builtin_constant_p expects one argument" <<
eom;
3658 tmp1.
id() == ID_typecast &&
3664 .
id() == ID_string_constant)
3676 else if(identifier==
"__builtin_classify_type")
3683 error() <<
"__builtin_classify_type expects one argument" <<
eom;
3694 const typet &type =
object.type().
id() == ID_c_bit_field
3698 unsigned type_number;
3700 if(type.
id() == ID_bool || type.
id() == ID_c_bool)
3708 type_number = type.
id() == ID_empty ? 0u
3709 : (type.
id() == ID_bool || type.
id() == ID_c_bool) ? 4u
3710 : (type.
id() == ID_pointer || type.
id() == ID_array) ? 5u
3711 : type.
id() == ID_floatbv ? 8u
3712 : (type.
id() == ID_complex &&
3715 : type.
id() == ID_struct_tag ? 12u
3716 : type.
id() == ID_union_tag
3727 identifier ==
"__builtin_add_overflow" ||
3728 identifier ==
"__builtin_sadd_overflow" ||
3729 identifier ==
"__builtin_saddl_overflow" ||
3730 identifier ==
"__builtin_saddll_overflow" ||
3731 identifier ==
"__builtin_uadd_overflow" ||
3732 identifier ==
"__builtin_uaddl_overflow" ||
3733 identifier ==
"__builtin_uaddll_overflow" ||
3734 identifier ==
"__builtin_add_overflow_p")
3739 identifier ==
"__builtin_sub_overflow" ||
3740 identifier ==
"__builtin_ssub_overflow" ||
3741 identifier ==
"__builtin_ssubl_overflow" ||
3742 identifier ==
"__builtin_ssubll_overflow" ||
3743 identifier ==
"__builtin_usub_overflow" ||
3744 identifier ==
"__builtin_usubl_overflow" ||
3745 identifier ==
"__builtin_usubll_overflow" ||
3746 identifier ==
"__builtin_sub_overflow_p")
3751 identifier ==
"__builtin_mul_overflow" ||
3752 identifier ==
"__builtin_smul_overflow" ||
3753 identifier ==
"__builtin_smull_overflow" ||
3754 identifier ==
"__builtin_smulll_overflow" ||
3755 identifier ==
"__builtin_umul_overflow" ||
3756 identifier ==
"__builtin_umull_overflow" ||
3757 identifier ==
"__builtin_umulll_overflow" ||
3758 identifier ==
"__builtin_mul_overflow_p")
3763 identifier ==
"__builtin_bitreverse8" ||
3764 identifier ==
"__builtin_bitreverse16" ||
3765 identifier ==
"__builtin_bitreverse32" ||
3766 identifier ==
"__builtin_bitreverse64")
3771 std::ostringstream error_message;
3772 error_message <<
"error: " << identifier <<
" expects one operand";
3780 bitreverse.add_source_location() = source_location;
3782 return std::move(bitreverse);
3798 std::ostringstream error_message;
3799 error_message << identifier <<
" takes exactly 3 arguments, but "
3800 << expr.
arguments().size() <<
" were provided";
3814 auto const raise_wrong_argument_error =
3816 const exprt &wrong_argument, std::size_t argument_number,
bool _p) {
3817 std::ostringstream error_message;
3818 error_message <<
"error: " << identifier <<
" has signature "
3819 << identifier <<
"(integral, integral, integral"
3820 << (_p ?
"" :
"*") <<
"), "
3821 <<
"but argument " << argument_number <<
" ("
3822 <<
expr2c(wrong_argument, *
this) <<
") has type `"
3823 <<
type2c(wrong_argument.
type(), *
this) <<
'`';
3827 for(
int arg_index = 0; arg_index <= (!is__p_variant ? 1 : 2); ++arg_index)
3829 auto const &argument = expr.
arguments()[arg_index];
3833 raise_wrong_argument_error(argument, arg_index + 1, is__p_variant);
3837 !is__p_variant && (
result.type().id() != ID_pointer ||
3841 raise_wrong_argument_error(
result, 3, is__p_variant);
3860 std::ostringstream error_message;
3861 error_message <<
"error: " << identifier
3862 <<
" takes exactly two arguments, but "
3863 << expr.
arguments().size() <<
" were provided";
3871 identifier ==
"__builtin_elementwise_sub_sat")
3877 identifier ==
"__builtin_elementwise_add_sat")
3902 if(code_type.
get_bool(ID_C_incomplete))
3906 else if(code_type.
is_KnR())
3910 for(std::size_t i = arguments.size(); i < parameters.size(); ++i)
3912 arguments.push_back(
3918 if(parameters.size() > arguments.size())
3921 error() <<
"not enough function arguments" <<
eom;
3925 else if(parameters.size() != arguments.size())
3928 error() <<
"wrong number of function arguments: "
3929 <<
"expected " << parameters.size() <<
", but got "
3930 << arguments.size() <<
eom;
3934 for(std::size_t i=0; i<arguments.size(); i++)
3936 exprt &op=arguments[i];
3942 else if(i < parameters.size())
3948 op.
get(ID_statement) == ID_assign && op.
type().
id() != ID_bool)
3951 warning() <<
"assignment where Boolean argument is expected" <<
eom;
3960 if(op.
type().
id() == ID_array)
3963 dest_type.base_type().set(ID_C_constant,
true);
3981 if(o_type.
id()==ID_vector)
4000 error() <<
"operator '" << expr.
id() <<
"' not defined for type '"
4024 const auto s0 = numeric_cast<mp_integer>(type0.
size());
4025 const auto s1 = numeric_cast<mp_integer>(type1.
size());
4055 if(o_type0.
id()==ID_vector &&
4056 o_type1.
id()==ID_vector)
4070 o_type0.
id() == ID_vector && o_type1.
id() != ID_vector &&
4075 expr.
type() = o_type0;
4079 o_type0.
id() != ID_vector && o_type1.
id() == ID_vector &&
4084 expr.
type() = o_type1;
4088 if(expr.
id() == ID_saturating_minus || expr.
id() == ID_saturating_plus)
4101 if(expr.
id()==ID_plus || expr.
id()==ID_minus ||
4102 expr.
id()==ID_mult || expr.
id()==ID_div)
4104 if(type0.
id()==ID_pointer || type1.
id()==ID_pointer)
4109 else if(type0==type1)
4118 else if(expr.
id()==ID_mod)
4122 if(type0.
id()==ID_signedbv || type0.
id()==ID_unsignedbv)
4130 expr.
id() == ID_bitand || expr.
id() == ID_bitnand ||
4131 expr.
id() == ID_bitxor || expr.
id() == ID_bitor)
4140 else if(type0.
id()==ID_bool)
4142 if(expr.
id()==ID_bitand)
4144 else if(expr.
id() == ID_bitnand)
4146 else if(expr.
id()==ID_bitor)
4148 else if(expr.
id()==ID_bitxor)
4157 else if(expr.
id() == ID_saturating_minus || expr.
id() == ID_saturating_plus)
4161 (type0.
id() == ID_signedbv || type0.
id() == ID_unsignedbv))
4163 expr.
type() = type0;
4169 error() <<
"operator '" << expr.
id() <<
"' not defined for types '"
4185 if(o_type0.
id()==ID_vector &&
4186 o_type1.
id()==ID_vector)
4202 o_type0.
id() == ID_vector &&
4220 if(expr.
id()==ID_shr)
4224 if(op0_type.
id()==ID_unsignedbv)
4229 else if(op0_type.
id()==ID_signedbv)
4240 error() <<
"operator '" << expr.
id() <<
"' not defined for types '"
4254 base_type.
id() == ID_struct_tag &&
4258 error() <<
"pointer arithmetic with unknown object size" <<
eom;
4262 base_type.
id() == ID_union_tag &&
4266 error() <<
"pointer arithmetic with unknown object size" <<
eom;
4270 base_type.
id() == ID_empty &&
4274 error() <<
"pointer arithmetic with unknown object size" <<
eom;
4277 else if(base_type.
id() == ID_empty)
4295 if(expr.
id()==ID_minus ||
4296 (expr.
id()==ID_side_effect && expr.
get(ID_statement)==ID_assign_minus))
4298 if(type0.
id()==ID_pointer &&
4299 type1.
id()==ID_pointer)
4312 if(type0.
id()==ID_pointer &&
4313 (type1.
id()==ID_bool ||
4314 type1.
id()==ID_c_bool ||
4315 type1.
id()==ID_unsignedbv ||
4316 type1.
id()==ID_signedbv ||
4317 type1.
id()==ID_c_bit_field ||
4318 type1.
id()==ID_c_enum_tag))
4326 else if(expr.
id()==ID_plus ||
4327 (expr.
id()==ID_side_effect && expr.
get(ID_statement)==ID_assign_plus))
4329 exprt *p_op, *int_op;
4331 if(type0.
id()==ID_pointer)
4336 else if(type1.
id()==ID_pointer)
4343 p_op=int_op=
nullptr;
4347 const typet &int_op_type = int_op->
type();
4349 if(int_op_type.
id()==ID_bool ||
4350 int_op_type.
id()==ID_c_bool ||
4351 int_op_type.
id()==ID_unsignedbv ||
4352 int_op_type.
id()==ID_signedbv ||
4353 int_op_type.
id()==ID_c_bit_field ||
4354 int_op_type.
id()==ID_c_enum_tag)
4365 if(expr.
id()==ID_side_effect)
4371 error() <<
"operator '" << op_name <<
"' not defined for types '"
4402 if(type0.
id()==ID_empty)
4405 error() <<
"cannot assign void" <<
eom;
4412 error() <<
"assignment error: '" <<
to_string(op0) <<
"' not an lvalue"
4425 if(type0.
id() == ID_array)
4428 error() <<
"direct assignments to arrays not permitted" <<
eom;
4434 if(op0.
type() != op1.
type() && op0.
type().
id() == ID_c_bit_field)
4443 expr.
type()=o_type0;
4445 if(statement==ID_assign)
4450 else if(statement==ID_assign_shl ||
4451 statement==ID_assign_shr)
4453 if(o_type0.
id() == ID_vector)
4458 o_type1.
id() == ID_vector &&
4459 vector_o_type0.element_type() ==
4461 is_number(vector_o_type0.element_type()))
4477 if(statement==ID_assign_shl)
4487 if(underlying_type.
id()==ID_unsignedbv ||
4488 underlying_type.
id()==ID_c_bool)
4490 expr.
set(ID_statement, ID_assign_lshr);
4493 else if(underlying_type.
id()==ID_signedbv)
4495 expr.
set(ID_statement, ID_assign_ashr);
4501 else if(statement==ID_assign_bitxor ||
4502 statement==ID_assign_bitand ||
4503 statement==ID_assign_bitor)
4506 if(o_type0.
id()==ID_bool ||
4507 o_type0.
id()==ID_c_bool)
4512 op1.
type().
id() == ID_c_enum_tag || op1.
type().
id() == ID_unsignedbv ||
4513 op1.
type().
id() == ID_signedbv || op1.
type().
id() == ID_c_bit_field)
4518 else if(o_type0.
id()==ID_c_enum_tag ||
4519 o_type0.
id()==ID_unsignedbv ||
4520 o_type0.
id()==ID_signedbv ||
4521 o_type0.
id()==ID_c_bit_field)
4525 op1.
type().
id() == ID_c_enum_tag || op1.
type().
id() == ID_unsignedbv ||
4526 op1.
type().
id() == ID_signedbv || op1.
type().
id() == ID_c_bit_field)
4531 else if(o_type0.
id()==ID_vector &&
4532 o_type1.
id()==ID_vector)
4543 o_type0.
id() == ID_vector &&
4544 (o_type1.
id() == ID_bool || o_type1.
id() == ID_c_bool ||
4545 o_type1.
id() == ID_c_enum_tag || o_type1.
id() == ID_unsignedbv ||
4546 o_type1.
id() == ID_signedbv))
4555 if(o_type0.
id()==ID_pointer &&
4556 (statement==ID_assign_minus || statement==ID_assign_plus))
4561 else if(o_type0.
id()==ID_vector &&
4562 o_type1.
id()==ID_vector)
4572 else if(o_type0.
id() == ID_vector)
4578 op1.
type().
id() == ID_c_bool || op1.
type().
id() == ID_c_enum_tag)
4584 else if(o_type0.
id()==ID_bool ||
4585 o_type0.
id()==ID_c_bool)
4590 op1.
type().
id() == ID_c_enum_tag || op1.
type().
id() == ID_unsignedbv ||
4591 op1.
type().
id() == ID_signedbv)
4602 op1.
type().
id() == ID_c_bool || op1.
type().
id() == ID_c_enum_tag)
4610 error() <<
"assignment '" << statement <<
"' not defined for types '"
4640 if(e.
id() == ID_infinity)
4646 if(e.
id() == ID_address_of)
4651 e.
id() == ID_typecast || e.
id() == ID_array_of || e.
id() == ID_plus ||
4652 e.
id() == ID_mult || e.
id() == ID_array || e.
id() == ID_with ||
4653 e.
id() == ID_struct || e.
id() == ID_union || e.
id() == ID_empty_union ||
4654 e.
id() == ID_equal || e.
id() == ID_notequal || e.
id() == ID_lt ||
4655 e.
id() == ID_le || e.
id() == ID_gt || e.
id() == ID_ge ||
4656 e.
id() == ID_if || e.
id() == ID_not || e.
id() == ID_and ||
4657 e.
id() == ID_or || e.
id() == ID_bitnot || e.
id() == ID_bitand ||
4658 e.
id() == ID_bitor || e.
id() == ID_bitxor || e.
id() == ID_vector)
4662 return is_constant(op);
4672 if(e.
id() == ID_symbol)
4674 return e.
type().
id() == ID_code ||
4677 else if(e.
id() == ID_array && e.
get_bool(ID_C_string_constant))
4679 else if(e.
id() == ID_label)
4681 else if(e.
id() == ID_index)
4688 else if(e.
id() == ID_member)
4692 else if(e.
id() == ID_dereference)
4698 else if(e.
id() == ID_string_constant)
4712 const auto rounding_mode =
4722 error() <<
"expected constant expression, but got '" <<
to_string(expr)
4739 error() <<
"conversion to integer constant failed" <<
eom;
4747 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 floatbv_typet & to_floatbv_type(const typet &type)
Cast a typet to a floatbv_typet.
const bitvector_typet & to_bitvector_type(const typet &type)
Cast a typet to a bitvector_typet.
bool builtin_factory(const irep_idt &identifier, bool support_float16_type, symbol_table_baset &symbol_table, message_handlert &mh)
Check whether given identifier is a compiler built-in.
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()
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()
bool can_cast_type< c_enum_tag_typet >(const typet &type)
Check whether a reference to a typet is a c_enum_tag_typet.
const c_enum_typet & to_c_enum_type(const typet &type)
Cast a typet to a c_enum_typet.
const union_tag_typet & to_union_tag_type(const typet &type)
Cast a typet to a union_tag_typet.
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_tag_typet & to_c_enum_tag_type(const typet &type)
Cast a typet to a c_enum_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.
const exprt & size() const
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 typet & return_type() const
bool has_ellipsis() const
const parameterst & parameters() 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.
struct configt::ansi_ct ansi_c
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.
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
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...
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
bool is_true() const
Return whether the expression is a constant representing true.
void copy_to_operands(const exprt &expr)
Copy the given argument to the end of exprt's operands.
source_locationt & add_source_location()
bool is_boolean() const
Return whether the expression represents a Boolean.
const source_locationt & source_location() const
typet & type()
Return the type of the expression.
bool is_constant() const
Return whether the expression is a constant.
void add_to_operands(const exprt &expr)
Add the given argument to the end of exprt's operands.
The Boolean constant false.
Returns one plus the index of the least-significant one bit, or zero if the operand is zero.
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_floatt plus_infinity(const ieee_float_spect &_spec)
static ieee_floatt zero(const floatbv_typet &type)
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
mstreamt & warning() const
mstreamt & result() const
message_handlert & get_message_handler()
Binary multiplication 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...
const symbolt & lookup(const irep_idt &name) const
Lookup a symbol in the namespace.
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 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.
const componentst & components() const
Expression to hold a symbol (variable)
void set_identifier(const irep_idt &identifier)
const irep_idt & get_identifier() const
const symbolst & symbols
Read-only field, used to look up symbols given their names.
bool has_symbol(const irep_idt &name) const
Check whether a symbol exists in the symbol table.
bool add(const symbolt &symbol)
Add a new symbol to the symbol table.
virtual std::pair< symbolt &, bool > insert(symbolt symbol)=0
Move or copy a new symbol to the symbol table.
irep_idt base_name
Base (non-scoped) name.
const irep_idt & display_name() const
Return language specific display name if present.
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.
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.
typet && with_source_location(source_locationt location) &&
This is a 'fluent style' method for creating a new type with an added-on source location.
source_locationt & add_source_location()
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
const typet & element_type() const
The type of the elements of the vector.
typet index_type() const
The type of any index expression into an instance of this type.
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)
constant_exprt make_boolean_expr(bool value)
returns true_exprt if given true and false_exprt otherwise
bool is_assignable(const exprt &expr)
Returns true iff the argument is one of the following:
const exprt & skip_typecast(const exprt &expr)
find the expression nested inside typecasts, if any
bool has_subexpr(const exprt &expr, const std::function< bool(const exprt &)> &pred)
returns true if the expression has a subexpression that satisfies pred
bool is_null_pointer(const constant_exprt &expr)
Returns true if expr has a pointer type and a value NULL; it also returns true when expr has value ze...
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 dereference_exprt & to_dereference_expr(const exprt &expr)
Cast an exprt to a dereference_exprt.
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
const address_of_exprt & to_address_of_expr(const exprt &expr)
Cast an exprt to an address_of_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)
side_effect_expr_statement_expressiont & to_side_effect_expr_statement_expression(exprt &expr)
side_effect_exprt & to_side_effect_expr(exprt &expr)
side_effect_expr_function_callt & to_side_effect_expr_function_call(exprt &expr)
const code_frontend_declt & to_code_frontend_decl(const codet &code)
const code_blockt & to_code_block(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 if_exprt & to_if_expr(const exprt &expr)
Cast an exprt to an if_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 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 member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
const unary_exprt & to_unary_expr(const exprt &expr)
Cast an exprt to a unary_exprt.
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 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 array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
const complex_typet & to_complex_type(const typet &type)
Cast a typet to a complex_typet.
const struct_tag_typet & to_struct_tag_type(const typet &type)
Cast a typet to a struct_tag_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.
std::string to_string(const string_not_contains_constraintt &expr)
Used for debug printing.
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)