void c_typecastt::implicit_typecast_arithmetic( exprt &expr, c_typet c_type) { typet new_type; const typet &expr_type=ns.follow(expr.type()); switch(c_type) { case PTR: if(expr_type.id()==ID_array) { new_type.id(ID_pointer); new_type.subtype()=expr_type.subtype(); break; } return; case BOOL: new_type=bool_typet(); break; case CHAR: assert(false); // should always be promoted to int case UCHAR: assert(false); // should always be promoted to int case SHORT: assert(false); // should always be promoted to int case USHORT: assert(false); // should always be promoted to int case INT: new_type=int_type(); break; case UINT: new_type=uint_type(); break; case LONG: new_type=long_int_type(); break; case ULONG: new_type=long_uint_type(); break; case LONGLONG: new_type=long_long_int_type(); break; case ULONGLONG: new_type=long_long_uint_type(); break; case SINGLE: new_type=float_type(); break; case DOUBLE: new_type=double_type(); break; case LONGDOUBLE: new_type=long_double_type(); break; case RATIONAL: new_type=rational_typet(); break; case REAL: new_type=real_typet(); break; case INTEGER: new_type=integer_typet(); break; case COMPLEX: return; // do nothing default: return; } if(new_type!=expr_type) { if(new_type.id()==ID_pointer && expr_type.id()==ID_array) { exprt index_expr(ID_index, expr_type.subtype()); index_expr.reserve_operands(2); index_expr.move_to_operands(expr); index_expr.copy_to_operands(gen_zero(index_type())); expr=exprt(ID_address_of, new_type); expr.move_to_operands(index_expr); } else do_typecast(expr, new_type); } }
bool c_typecheck_baset::zero_initializer(exprt &value, const typet &type) const { const std::string &type_id = type.id_string(); if(type_id == "bool") { value.make_false(); return false; } if( type_id == "unsignedbv" || type_id == "signedbv" || type_id == "floatbv" || type_id == "fixedbv" || type_id == "pointer") { value = gen_zero(type); return false; } else if(type_id == "code") return false; else if(type_id == "c_enum" || type_id == "incomplete_c_enum") { value = exprt("constant", type); value.value(i2string(0)); return false; } else if(type_id == "array") { const array_typet &array_type = to_array_type(type); exprt tmpval; if(zero_initializer(tmpval, array_type.subtype())) return true; const exprt &size_expr = array_type.size(); if(size_expr.id() == "infinity") { } else { mp_integer size; if(to_integer(size_expr, size)) return true; // Permit GCC zero sized arrays; disallow negative sized arrays. // Cringe slightly when doing it though. if(size < 0) return true; } value = exprt("array_of", type); value.move_to_operands(tmpval); return false; } else if(type_id == "struct") { const irept::subt &components = type.components().get_sub(); value = exprt("struct", type); forall_irep(it, components) { exprt tmp; if(zero_initializer(tmp, (const typet &)it->type())) return true; value.move_to_operands(tmp); } return false; }
void goto_inlinet::replace_return( goto_programt &dest, const exprt &lhs, const exprt &constrain) { for(goto_programt::instructionst::iterator it=dest.instructions.begin(); it!=dest.instructions.end(); it++) { if(it->is_return()) { #if 0 if(lhs.is_not_nil()) { if(it->code.operands().size()!=1) { error().source_location=it->code.find_source_location(); str << "return expects one operand!"; warning_msg(); continue; } goto_programt tmp; goto_programt::targett assignment=tmp.add_instruction(ASSIGN); code_assignt code_assign(lhs, it->code.op0()); // this may happen if the declared return type at the call site // differs from the defined return type if(code_assign.lhs().type()!= code_assign.rhs().type()) code_assign.rhs().make_typecast(code_assign.lhs().type()); assignment->code=code_assign; assignment->source_location=it->source_location; assignment->function=it->function; if(constrain.is_not_nil() && !constrain.is_true()) { codet constrain(ID_bp_constrain); constrain.reserve_operands(2); constrain.move_to_operands(assignment->code); constrain.copy_to_operands(constrain); } dest.insert_before_swap(it, *assignment); it++; } else if(!it->code.operands().empty()) { goto_programt tmp; goto_programt::targett expression=tmp.add_instruction(OTHER); expression->code=codet(ID_expression); expression->code.move_to_operands(it->code.op0()); expression->source_location=it->source_location; expression->function=it->function; dest.insert_before_swap(it, *expression); it++; } it->make_goto(--dest.instructions.end()); #else if(lhs.is_not_nil()) { if(it->code.operands().size()!=1) { warning().source_location=it->code.find_source_location(); warning() << "return expects one operand!\n" << it->code.pretty() << eom; continue; } code_assignt code_assign(lhs, it->code.op0()); // this may happen if the declared return type at the call site // differs from the defined return type if(code_assign.lhs().type()!= code_assign.rhs().type()) code_assign.rhs().make_typecast(code_assign.lhs().type()); if(constrain.is_not_nil() && !constrain.is_true()) { codet constrain(ID_bp_constrain); constrain.reserve_operands(2); constrain.move_to_operands(code_assign); constrain.copy_to_operands(constrain); it->code=constrain; it->type=OTHER; } else { it->code=code_assign; it->type=ASSIGN; } it++; } else if(!it->code.operands().empty()) { codet expression(ID_expression); expression.move_to_operands(it->code.op0()); it->code=expression; it->type=OTHER; it++; } #endif } } }