void java_bytecode_convert_classt::convert( symbolt &class_symbol, const fieldt &f) { typet field_type=java_type_from_string(f.signature); // is this a static field? if(f.is_static) { // Create the symbol; we won't add to the struct type. symbolt new_symbol; new_symbol.is_static_lifetime=true; new_symbol.is_lvalue=true; new_symbol.is_state_var=true; new_symbol.name=id2string(class_symbol.name)+"."+id2string(f.name); new_symbol.base_name=f.name; new_symbol.type=field_type; new_symbol.pretty_name=id2string(class_symbol.pretty_name)+ "."+id2string(f.name); new_symbol.mode=ID_java; new_symbol.is_type=false; const namespacet ns(symbol_table); new_symbol.value= zero_initializer( field_type, class_symbol.location, ns, get_message_handler()); // Do we have the static field symbol already? const auto s_it=symbol_table.symbols.find(new_symbol.name); if(s_it!=symbol_table.symbols.end()) symbol_table.symbols.erase(s_it); // erase, we stubbed it if(symbol_table.add(new_symbol)) assert(false && "failed to add static field symbol"); } else { class_typet &class_type=to_class_type(class_symbol.type); class_type.components().push_back(class_typet::componentt()); class_typet::componentt &component=class_type.components().back(); component.set_name(f.name); component.set_base_name(f.name); component.set_pretty_name(f.name); component.type()=field_type; if(f.is_private) component.set_access(ID_private); else if(f.is_protected) component.set_access(ID_protected); else if(f.is_public) component.set_access(ID_public); } }
void c_typecheck_baset::do_initializer(symbolt &symbol) { // this one doesn't need initialization if(has_prefix(id2string(symbol.name), CPROVER_PREFIX "constant_infinity")) return; if(symbol.static_lifetime) { if(symbol.value.is_nil()) { const typet &final_type=follow(symbol.type); if(final_type.id()!=ID_incomplete_struct && final_type.id()!=ID_incomplete_array && final_type.id()!=ID_empty) { // zero initializer symbol.value=zero_initializer(symbol.type, symbol.location); symbol.value.set("#zero_initializer", true); } } else { typecheck_expr(symbol.value); do_initializer(symbol.value, symbol.type, true); if(follow(symbol.type).id()==ID_incomplete_array) symbol.type=symbol.value.type(); } } else if(!symbol.is_type) { const typet &final_type=follow(symbol.type); if(final_type.id()==ID_incomplete_c_enum || final_type.id()==ID_c_enum) { if(symbol.is_macro) { // these must have a constant value assert(symbol.value.is_not_nil()); typecheck_expr(symbol.value); locationt location=symbol.value.location(); do_initializer(symbol.value, symbol.type, true); make_constant(symbol.value); } } else if(symbol.value.is_not_nil()) { typecheck_expr(symbol.value); do_initializer(symbol.value, symbol.type, true); if(follow(symbol.type).id()==ID_incomplete_array) symbol.type=symbol.value.type(); } } }
exprt c_typecheck_baset::do_initializer_list( const exprt &value, const typet &type, bool force_constant) { assert(value.id()==ID_initializer_list); if(type.id()==ID_symbol) return do_initializer_list( value, follow(type), force_constant); exprt result; if(type.id()==ID_struct || type.id()==ID_array || type.id()==ID_union) { // start with zero everywhere result=zero_initializer(type, value.location()); } else if(type.id()==ID_incomplete_array) { // start with empty array result=exprt(ID_array, type); result.location()=value.location(); } else { // The initializer for a scalar shall be a single expression, // * optionally enclosed in braces. * if(value.operands().size()==1) return do_initializer_rec(value.op0(), type, force_constant); err_location(value); str << "cannot initialize `" << to_string(type) << "' with " "an initializer list"; throw 0; } designatort current_designator; designator_enter(type, current_designator); forall_operands(it, value) { do_designated_initializer( result, current_designator, *it, force_constant); // increase designator -- might go up increment_designator(current_designator); }
void c_typecheck_baset::typecheck_return(codet &code) { if(code.operands().empty()) { if(follow(return_type).id()!=ID_empty) { // gcc doesn't actually complain, it just warns! // We'll put a zero here, which is dubious. exprt zero=zero_initializer(return_type, code.source_location(), *this, get_message_handler()); code.copy_to_operands(zero); } } else if(code.operands().size()==1) { typecheck_expr(code.op0()); if(follow(return_type).id()==ID_empty) { // gcc doesn't actually complain, it just warns! if(follow(code.op0().type()).id()!=ID_empty) { warning().source_location=code.source_location(); warning() << "function has return void "; warning() << "but a return statement returning "; warning() << to_string(follow(code.op0().type())); warning() << eom; code.op0().make_typecast(return_type); } } else implicit_typecast(code.op0(), return_type); } else { err_location(code); error() << "return expected to have 0 or 1 operands" << eom; throw 0; } }
void goto_convertt::do_java_new( const exprt &lhs, const side_effect_exprt &rhs, goto_programt &dest) { if(lhs.is_nil()) throw "do_java_new without lhs is yet to be implemented"; source_locationt location=rhs.source_location(); assert(rhs.operands().empty()); if(rhs.type().id()!=ID_pointer) throw "do_java_new returns pointer"; typet object_type=rhs.type().subtype(); // build size expression exprt object_size=size_of_expr(object_type, ns); if(object_size.is_nil()) throw "do_java_new got nil object_size"; // we produce a malloc side-effect, which stays side_effect_exprt malloc_expr(ID_malloc); malloc_expr.copy_to_operands(object_size); malloc_expr.type()=pointer_typet(object_type); goto_programt::targett t_n=dest.add_instruction(ASSIGN); t_n->code=code_assignt(lhs, malloc_expr); t_n->source_location=location; // zero-initialize the object dereference_exprt deref(lhs, object_type); exprt zero_object=zero_initializer(object_type, location, ns, get_message_handler()); set_class_identifier(to_struct_expr(zero_object), ns, to_symbol_type(object_type)); goto_programt::targett t_i=dest.add_instruction(ASSIGN); t_i->code=code_assignt(deref, zero_object); t_i->source_location=location; }
void cpp_typecheckt::static_initialization() { code_blockt block_sini; // Static Initialization Block code_blockt block_dini; // Dynamic Initialization Block disable_access_control = true; // first do zero initialization context.foreach_operand([this, &block_sini](const symbolt &s) { if(!s.static_lifetime || s.mode != current_mode) return; // it has a non-code initializer already? if(s.value.is_not_nil() && s.value.id() != "code") return; // it's a declaration only if(s.is_extern) return; if(!s.lvalue) return; zero_initializer( cpp_symbol_expr(s), s.type, s.location, block_sini.operands()); }); while(!dinis.empty()) { symbolt &symbol = *context.find_symbol(dinis.front()); dinis.pop_front(); if(symbol.is_extern) continue; if(symbol.mode != current_mode) continue; assert(symbol.static_lifetime); assert(!symbol.is_type); assert(symbol.type.id() != "code"); exprt symexpr = cpp_symbol_expr(symbol); if(symbol.value.is_not_nil()) { if(!cpp_is_pod(symbol.type)) { block_dini.move_to_operands(symbol.value); } else { exprt symbexpr("symbol", symbol.type); symbexpr.identifier(symbol.name); codet code; code.set_statement("assign"); code.copy_to_operands(symbexpr, symbol.value); code.location() = symbol.location; if(symbol.value.id() == "constant") block_sini.move_to_operands(code); else block_dini.move_to_operands(code); } // Make it nil because we do not want // global_init to try to initialize the // object symbol.value.make_nil(); } else { exprt::operandst ops; codet call = cpp_constructor(locationt(), symexpr, ops); if(call.is_not_nil()) block_dini.move_to_operands(call); } } block_sini.move_to_operands(block_dini); // Create the initialization procedure symbolt init_symbol; init_symbol.name = "#ini#" + id2string(module); init_symbol.base_name = "#ini#" + id2string(module); init_symbol.value.swap(block_sini); init_symbol.mode = current_mode; init_symbol.module = module; init_symbol.type = code_typet(); init_symbol.type.add("return_type") = typet("empty"); init_symbol.type.set("initialization", true); init_symbol.is_type = false; init_symbol.is_macro = false; context.move(init_symbol); disable_access_control = false; }
bool static_lifetime_init( symbol_tablet &symbol_table, const source_locationt &source_location, message_handlert &message_handler) { namespacet ns(symbol_table); symbol_tablet::symbolst::iterator s_it= symbol_table.symbols.find(INITIALIZE_FUNCTION); if(s_it==symbol_table.symbols.end()) return false; symbolt &init_symbol=s_it->second; init_symbol.value=code_blockt(); init_symbol.value.add_source_location()=source_location; code_blockt &dest=to_code_block(to_code(init_symbol.value)); // add the magic label to hide dest.add(code_labelt("__CPROVER_HIDE", code_skipt())); // do assignments based on "value" // sort alphabetically for reproducible results std::set<std::string> symbols; forall_symbols(it, symbol_table.symbols) symbols.insert(id2string(it->first)); for(const std::string &id : symbols) { const symbolt &symbol=ns.lookup(id); const irep_idt &identifier=symbol.name; if(!symbol.is_static_lifetime) continue; if(symbol.is_type || symbol.is_macro) continue; // special values if(identifier==CPROVER_PREFIX "constant_infinity_uint" || identifier==CPROVER_PREFIX "memory" || identifier=="__func__" || identifier=="__FUNCTION__" || identifier=="__PRETTY_FUNCTION__" || identifier=="argc'" || identifier=="argv'" || identifier=="envp'" || identifier=="envp_size'") continue; // just for linking if(has_prefix(id, CPROVER_PREFIX "architecture_")) continue; const typet &type=ns.follow(symbol.type); // check type if(type.id()==ID_code || type.id()==ID_empty) continue; // We won't try to initialize any symbols that have // remained incomplete. if(symbol.value.is_nil() && symbol.is_extern) // Compilers would usually complain about these // symbols being undefined. continue; if(type.id()==ID_array && to_array_type(type).size().is_nil()) { // C standard 6.9.2, paragraph 5 // adjust the type to an array of size 1 symbol_tablet::symbolst::iterator it= symbol_table.symbols.find(identifier); assert(it!=symbol_table.symbols.end()); it->second.type=type; it->second.type.set(ID_size, from_integer(1, size_type())); } if(type.id()==ID_incomplete_struct || type.id()==ID_incomplete_union) continue; // do not initialize if(symbol.value.id()==ID_nondet) continue; // do not initialize exprt rhs; if(symbol.value.is_nil()) { try { namespacet ns(symbol_table); rhs=zero_initializer(symbol.type, symbol.location, ns, message_handler); assert(rhs.is_not_nil()); } catch(...) { return true; } } else rhs=symbol.value; code_assignt code(symbol.symbol_expr(), rhs); code.add_source_location()=symbol.location; dest.move_to_operands(code); } // call designated "initialization" functions for(const std::string &id : symbols) { const symbolt &symbol=ns.lookup(id); if(symbol.type.id()==ID_code && to_code_type(symbol.type).return_type().id()==ID_constructor) { code_function_callt function_call; function_call.function()=symbol.symbol_expr(); function_call.add_source_location()=source_location; dest.move_to_operands(function_call); } } return false; }
exprt c_typecheck_baset::do_initializer_list( const exprt &value, const typet &type, bool force_constant) { assert(value.id()==ID_initializer_list); const typet &full_type=follow(type); exprt result; if(full_type.id()==ID_struct || full_type.id()==ID_union || full_type.id()==ID_vector) { // start with zero everywhere result= zero_initializer( type, value.source_location(), *this, get_message_handler()); } else if(full_type.id()==ID_array) { if(to_array_type(full_type).size().is_nil()) { // start with empty array result=exprt(ID_array, full_type); result.add_source_location()=value.source_location(); } else { // start with zero everywhere result= zero_initializer( type, value.source_location(), *this, get_message_handler()); } // 6.7.9, 14: An array of character type may be initialized by a character // string literal or UTF-8 string literal, optionally enclosed in braces. if(value.operands().size()>=1 && value.op0().id()==ID_string_constant && (full_type.subtype().id()==ID_signedbv || full_type.subtype().id()==ID_unsignedbv) && full_type.subtype().get(ID_width)==char_type().get(ID_width)) { if(value.operands().size()>1) { warning().source_location=value.find_source_location(); warning() << "ignoring excess initializers" << eom; } return do_initializer_rec(value.op0(), type, force_constant); } } else { // The initializer for a scalar shall be a single expression, // * optionally enclosed in braces. * if(value.operands().size()==1) return do_initializer_rec(value.op0(), type, force_constant); err_location(value); error() << "cannot initialize `" << to_string(full_type) << "' with an initializer list" << eom; throw 0; } designatort current_designator; designator_enter(type, current_designator); forall_operands(it, value) { do_designated_initializer( result, current_designator, *it, force_constant); // increase designator -- might go up increment_designator(current_designator); }
exprt c_typecheck_baset::do_initializer_rec( const exprt &value, const typet &type, bool force_constant) { const typet &full_type=follow(type); if(full_type.id()==ID_incomplete_struct) { err_location(value); error() << "type `" << to_string(full_type) << "' is still incomplete -- cannot initialize" << eom; throw 0; } if(value.id()==ID_initializer_list) return do_initializer_list(value, type, force_constant); if(value.id()==ID_array && value.get_bool(ID_C_string_constant) && full_type.id()==ID_array && (full_type.subtype().id()==ID_signedbv || full_type.subtype().id()==ID_unsignedbv) && full_type.subtype().get(ID_width)==value.type().subtype().get(ID_width)) { exprt tmp=value; // adjust char type tmp.type().subtype()=full_type.subtype(); Forall_operands(it, tmp) it->type()=full_type.subtype(); if(full_type.id()==ID_array && to_array_type(full_type).is_complete()) { // check size mp_integer array_size; if(to_integer(to_array_type(full_type).size(), array_size)) { err_location(value); error() << "array size needs to be constant, got " << to_string(to_array_type(full_type).size()) << eom; throw 0; } if(array_size<0) { err_location(value); error() << "array size must not be negative" << eom; throw 0; } if(mp_integer(tmp.operands().size())>array_size) { // cut off long strings. gcc does a warning for this tmp.operands().resize(integer2size_t(array_size)); tmp.type()=type; } else if(mp_integer(tmp.operands().size())<array_size) { // fill up tmp.type()=type; exprt zero= zero_initializer( full_type.subtype(), value.source_location(), *this, get_message_handler()); tmp.operands().resize(integer2size_t(array_size), zero); } } return tmp; } if(value.id()==ID_string_constant && full_type.id()==ID_array && (full_type.subtype().id()==ID_signedbv || full_type.subtype().id()==ID_unsignedbv) && full_type.subtype().get(ID_width)==char_type().get(ID_width)) { // will go away, to be replaced by the above block string_constantt tmp1=to_string_constant(value); // adjust char type tmp1.type().subtype()=full_type.subtype(); exprt tmp2=tmp1.to_array_expr(); if(full_type.id()==ID_array && to_array_type(full_type).is_complete()) { // check size mp_integer array_size; if(to_integer(to_array_type(full_type).size(), array_size)) { err_location(value); error() << "array size needs to be constant, got " << to_string(to_array_type(full_type).size()) << eom; throw 0; } if(array_size<0) { err_location(value); error() << "array size must not be negative" << eom; throw 0; } if(mp_integer(tmp2.operands().size())>array_size) { // cut off long strings. gcc does a warning for this tmp2.operands().resize(integer2size_t(array_size)); tmp2.type()=type; } else if(mp_integer(tmp2.operands().size())<array_size) { // fill up tmp2.type()=type; exprt zero= zero_initializer( full_type.subtype(), value.source_location(), *this, get_message_handler()); tmp2.operands().resize(integer2size_t(array_size), zero); } } return tmp2; } if(full_type.id()==ID_array && to_array_type(full_type).size().is_nil()) { err_location(value); error() << "type `" << to_string(full_type) << "' cannot be initialized with `" << to_string(value) << "'" << eom; throw 0; } if(value.id()==ID_designated_initializer) { err_location(value); error() << "type `" << to_string(full_type) << "' cannot be initialized with designated initializer" << eom; throw 0; } exprt result=value; implicit_typecast(result, type); return result; }
void c_typecheck_baset::do_designated_initializer( exprt &result, designatort &designator, const exprt &value, bool force_constant) { assert(!designator.empty()); if(value.id()==ID_designated_initializer) { assert(value.operands().size()==1); designator= make_designator( designator.front().type, static_cast<const exprt &>(value.find(ID_designator))); assert(!designator.empty()); return do_designated_initializer( result, designator, value.op0(), force_constant); } exprt *dest=&result; // first phase: follow given designator for(size_t i=0; i<designator.size(); i++) { size_t index=designator[i].index; const typet &type=designator[i].type; const typet &full_type=follow(type); if(full_type.id()==ID_array || full_type.id()==ID_vector) { if(index>=dest->operands().size()) { if(full_type.id()==ID_array && (to_array_type(full_type).size().is_zero() || to_array_type(full_type).size().is_nil())) { // we are willing to grow an incomplete or zero-sized array exprt zero= zero_initializer( full_type.subtype(), value.source_location(), *this, get_message_handler()); dest->operands().resize(integer2size_t(index)+1, zero); // todo: adjust type! } else { err_location(value); error() << "array index designator " << index << " out of bounds (" << dest->operands().size() << ")" << eom; throw 0; } } dest=&(dest->operands()[integer2size_t(index)]); } else if(full_type.id()==ID_struct) { const struct_typet::componentst &components= to_struct_type(full_type).components(); if(index>=dest->operands().size()) { err_location(value); error() << "structure member designator " << index << " out of bounds (" << dest->operands().size() << ")" << eom; throw 0; } assert(index<components.size()); assert(components[index].type().id()!=ID_code && !components[index].get_is_padding()); dest=&(dest->operands()[index]); } else if(full_type.id()==ID_union) { const union_typet &union_type=to_union_type(full_type); const union_typet::componentst &components= union_type.components(); assert(index<components.size()); const union_typet::componentt &component=union_type.components()[index]; if(dest->id()==ID_union && dest->get(ID_component_name)==component.get_name()) { // Already right union component. We can initialize multiple submembers, // so do not overwrite this. } else { // Note that gcc issues a warning if the union component is switched. // Build a union expression from given component. union_exprt union_expr(type); union_expr.op()= zero_initializer( component.type(), value.source_location(), *this, get_message_handler()); union_expr.add_source_location()=value.source_location(); union_expr.set_component_name(component.get_name()); *dest=union_expr; } dest=&(dest->op0()); } else assert(false); } // second phase: assign value // for this, we may need to go down, adding to the designator while(true) { // see what type we have to initialize const typet &type=designator.back().subtype; const typet &full_type=follow(type); assert(full_type.id()!=ID_symbol); // do we initialize a scalar? if(full_type.id()!=ID_struct && full_type.id()!=ID_union && full_type.id()!=ID_array && full_type.id()!=ID_vector) { // The initializer for a scalar shall be a single expression, // * optionally enclosed in braces. * if(value.id()==ID_initializer_list && value.operands().size()==1) *dest=do_initializer_rec(value.op0(), type, force_constant); else *dest=do_initializer_rec(value, type, force_constant); assert(full_type==follow(dest->type())); return; // done } // union? The component in the zero initializer might // not be the first one. if(full_type.id()==ID_union) { const union_typet &union_type=to_union_type(full_type); const union_typet::componentst &components= union_type.components(); if(!components.empty()) { const union_typet::componentt &component= union_type.components().front(); union_exprt union_expr(type); union_expr.op()= zero_initializer( component.type(), value.source_location(), *this, get_message_handler()); union_expr.add_source_location()=value.source_location(); union_expr.set_component_name(component.get_name()); *dest=union_expr; } } // see what initializer we are given if(value.id()==ID_initializer_list) { *dest=do_initializer_rec(value, type, force_constant); return; // done } else if(value.id()==ID_string_constant) { // We stop for initializers that are string-constants, // which are like arrays. We only do so if we are to // initialize an array of scalars. if(full_type.id()==ID_array && (follow(full_type.subtype()).id()==ID_signedbv || follow(full_type.subtype()).id()==ID_unsignedbv)) { *dest=do_initializer_rec(value, type, force_constant); return; // done } } else if(follow(value.type())==full_type) { // a struct/union/vector can be initialized directly with // an expression of the right type. This doesn't // work with arrays, unfortunately. if(full_type.id()==ID_struct || full_type.id()==ID_union || full_type.id()==ID_vector) { *dest=value; return; // done } } assert(full_type.id()==ID_struct || full_type.id()==ID_union || full_type.id()==ID_array || full_type.id()==ID_vector); // we are initializing a compound type, and enter it! // this may change the type, full_type might not be valid anymore const typet dest_type=full_type; designator_enter(type, designator); if(dest->operands().empty()) { err_location(value); error() << "cannot initialize type `" << to_string(dest_type) << "' using value `" << to_string(value) << "'" << eom; throw 0; } dest=&(dest->op0()); // we run into another loop iteration } }
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 c_typecheck_baset::do_designated_initializer( exprt &result, designatort &designator, const exprt &value, bool force_constant) { assert(!designator.empty()); if(value.id()==ID_designated_initializer) { assert(value.operands().size()==1); designator= make_designator( designator.front().type, static_cast<const exprt &>(value.find(ID_designator))); assert(!designator.empty()); return do_designated_initializer( result, designator, value.op0(), force_constant); } exprt *dest=&result; // first phase: follow given designator for(unsigned i=0; i<designator.size(); i++) { unsigned index=designator[i].index; const typet &type=designator[i].type; assert(type.id()!=ID_symbol); if(type.id()==ID_array || type.id()==ID_struct || type.id()==ID_incomplete_array) { if(index>=dest->operands().size()) { if(type.id()==ID_incomplete_array) { exprt zero=zero_initializer(type.subtype(), value.location()); dest->operands().resize(integer2long(index)+1, zero); } else { err_location(value); str << "index designator " << index << " out of bounds (" << dest->operands().size() << ")"; throw 0; } } dest=&(dest->operands()[integer2long(index)]); } else if(type.id()==ID_union) { // union initialization is quite special const union_typet &union_type=to_union_type(type); const union_typet::componentt &component=union_type.components()[index]; // build a union expression from the argument exprt union_expr(ID_union, type); union_expr.operands().resize(1); union_expr.op0()=zero_initializer(component.type(), value.location()); union_expr.location()=value.location(); union_expr.set(ID_component_name, component.get_name()); *dest=union_expr; dest=&(dest->op0()); } else assert(false); } // second phase: assign value // for this, we may need to go down, adding to the designator while(true) { // see what type we have to initialize typet type=follow(designator.back().subtype); assert(type.id()!=ID_symbol); // do we initialize a scalar? if(type.id()!=ID_struct && type.id()!=ID_union && type.id()!=ID_array && type.id()!=ID_incomplete_array) { // The initializer for a scalar shall be a single expression, // * optionally enclosed in braces. * if(value.id()==ID_initializer_list && value.operands().size()==1) *dest=do_initializer_rec(value.op0(), type, force_constant); else *dest=do_initializer_rec(value, type, force_constant); assert(type==follow(dest->type())); return; // done } // see what initializer we are given if(value.id()==ID_initializer_list) { *dest=do_initializer_rec(value, type, force_constant); return; // done } else if(value.id()==ID_string_constant) { // We stop for initializers that are string-constants, // which are like arrays. We only do so if we are to // initialize an array of scalars. if((type.id()==ID_array || type.id()==ID_incomplete_array) && (follow(type.subtype()).id()==ID_signedbv || follow(type.subtype()).id()==ID_unsignedbv)) { *dest=do_initializer_rec(value, type, force_constant); return; // done } } else if(follow(value.type())==type) { // a struct/union can be initialized directly with // an expression of the right type. This doesn't // work with arrays, unfortunately. if(type.id()==ID_struct || type.id()==ID_union) { *dest=value; return; // done } } // we are initializing a compound type, and enter it! designator_enter(type, designator); assert(!dest->operands().empty()); dest=&(dest->op0()); // we run into another loop iteration } }
exprt c_typecheck_baset::zero_initializer( const typet &type, const locationt &location) { const irep_idt &type_id=type.id(); if(type_id==ID_bool) { exprt result=false_exprt(); result.location()=location; return result; } else if(type_id==ID_unsignedbv || type_id==ID_signedbv || type_id==ID_floatbv || type_id==ID_fixedbv || type_id==ID_pointer) { exprt result=gen_zero(type); result.location()=location; return result; } else if(type_id==ID_code) { err_location(location); throw "cannot zero-initialize code-type"; } else if(type_id==ID_c_enum || type_id==ID_incomplete_c_enum) { constant_exprt value(type); value.set_value(ID_0); value.location()=location; return value; } else if(type_id==ID_array) { const array_typet &array_type=to_array_type(type); exprt tmpval=zero_initializer(array_type.subtype(), location); mp_integer array_size; if(array_type.size().id()==ID_infinity) { exprt value(ID_array_of, type); value.copy_to_operands(tmpval); value.location()=location; return value; } else if(to_integer(array_type.size(), array_size)) { err_location(location); str << "failed to zero-initialize array of non-fixed size `" << to_string(array_type.size()) << "'"; throw 0; } if(array_size<0) { err_location(location); throw "failed to zero-initialize array of with negative size"; } exprt value(ID_array, type); value.operands().resize(integer2long(array_size), tmpval); value.location()=location; return value; } else if(type_id==ID_incomplete_array) { // we initialize this with an empty array exprt value(ID_array, type); value.type().id(ID_array); value.type().set(ID_size, gen_zero(size_type())); value.location()=location; return value; } else if(type_id==ID_struct) { const struct_typet::componentst &components= to_struct_type(type).components(); exprt value(ID_struct, type); value.operands().reserve(components.size()); for(struct_typet::componentst::const_iterator it=components.begin(); it!=components.end(); it++) value.copy_to_operands(zero_initializer(it->type(), location)); value.location()=location; return value; } else if(type_id==ID_union) { const union_typet::componentst &components= to_union_type(type).components(); exprt value(ID_union, type); if(components.empty()) return value; // stupid empty union value.set(ID_component_name, components.front().get(ID_name)); value.copy_to_operands( zero_initializer(components.front().type(), location)); value.location()=location; return value; } else if(type_id==ID_symbol) return zero_initializer(follow(type), location); else { err_location(location); str << "Failed to zero-initialize `" << to_string(type) << "'"; throw 0; } }