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 goto_symext::replace_nondet(exprt &expr) { if(expr.id()==ID_sideeffect && expr.get(ID_statement)==ID_nondet) { exprt new_expr(ID_nondet_symbol, expr.type()); new_expr.set(ID_identifier, "symex::nondet"+i2string(nondet_count++)); new_expr.location()=expr.location(); expr.swap(new_expr); } else Forall_operands(it, expr) replace_nondet(*it); }
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 } }
void goto_convertt::clean_expr( exprt &expr, goto_programt &dest, bool result_is_used) { // this cleans: // && || ?: comma (control-dependency) // function calls // object constructors like arrays, string constants, structs // ++ -- // compound assignments if(!needs_cleaning(expr)) return; if(expr.id()==ID_and || expr.id()==ID_or) { // rewrite into ?: rewrite_boolean(expr); // recursive call clean_expr(expr, dest, result_is_used); return; } else if(expr.id()==ID_if) { if(expr.operands().size()!=3) throw "if takes three arguments"; if(!expr.op0().is_boolean()) throw "first argument of `if' must be boolean, but got " +expr.op0().to_string(); // first pull out condition -- we need to prevent // this getting destroyed by the side-effects in the other // operands make_temp_symbol(expr.op0(), "condition", dest); // now clean arguments goto_programt tmp_true, tmp_false; clean_expr(expr.op1(), tmp_true, result_is_used); clean_expr(expr.op2(), tmp_false, result_is_used); // generate guard for argument side-effects generate_ifthenelse( expr.op0(), tmp_true, tmp_false, expr.location(), dest); return; } else if(expr.id()==ID_comma) { exprt result; Forall_operands(it, expr) { bool last=(it==--expr.operands().end()); if(last) { result.swap(*it); clean_expr(result, dest, result_is_used); } else clean_expr(*it, dest, false); }