void component_exprt::gen_loc_var( exprt &loc_var, const exprt &expr, std::string suffix) { std::string base; if (expr.id()==ID_symbol) base="."+id2string(to_symbol_expr(expr).get_identifier()); else if (expr.id()==ID_constant) base=".const"; else if (expr.id()==ID_typecast) { base=".typecast__"+id2string(expr.type().id()); if (expr.type().id()==ID_signedbv) { base=base+i2string(to_signedbv_type(expr.type()).get_width()); } else if (expr.type().id()==ID_unsignedbv) { base=base+i2string(to_unsignedbv_type(expr.type()).get_width()); } } else if(id_maps.find(expr.id())!=id_maps.end()) base=".OPERATOR."+id_maps[expr.id()]; else base=".OPERATOR."+id2string(expr.id()); std::string final_name="L."+id2string(source_location.get_line())+"."+i2string(instruction_number)+"_"+i2string(component_cnt)+"_"+i2string(unique_identifier)+base+suffix; //typet type(ID_integer); //exprt loc_var(ID_symbol, type); to_symbol_expr(loc_var).set_identifier(final_name); }
std::set<symbol_exprt> concurrency_aware_abstractort::targets_of_lvalue(const exprt& lvalue, goto_programt::const_targett program_location) { std::set<symbol_exprt> result; if(lvalue.id() == ID_index) { exprt array_name = lvalue.op0(); if(array_name.id() == ID_symbol) { result.insert(to_symbol_expr(array_name)); } else { return targets_of_lvalue(array_name, program_location); } } else if(lvalue.id() == ID_member) { assert(lvalue.operands().size() == 1); return targets_of_lvalue(lvalue.op0(), program_location); } else if(lvalue.id() == ID_symbol) { result.insert(to_symbol_expr(lvalue)); } else if(lvalue.id() == ID_dereference) { // We would like to add anything the pointer can point to, // but not the pointer itself value_setst::valuest value_set; pointer_info.get_values(program_location, lvalue.op0(), value_set); for(value_setst::valuest::iterator it = value_set.begin(); it != value_set.end(); it++) { if(it->id() != ID_object_descriptor) { // TODO: We may need to deal with this situation more carefully continue; } object_descriptor_exprt& object_descriptor = to_object_descriptor_expr(*it); if(object_descriptor.offset() != from_integer(0, index_type())) { std::cout << "Pointer " << from_expr(lvalue.op0()) << " can point to " << from_expr(*it) << " at line " << program_location->location.get_line() << ", we cannot handle this" << std::endl; exit(1); } if(object_descriptor.object().id() != ID_symbol) { std::cout << "Pointer " << from_expr(lvalue.op0()) << " can point to " << from_expr(*it) << " at line " << program_location->location.get_line() << ", we cannot handle this" << std::endl; exit(1); } result.insert(to_symbol_expr(object_descriptor.object())); } } else { std::cout << "Cannot currently handle lvalue: " << from_expr(lvalue) << std::endl; assert(false); } return result; }
void constant_propagator_domaint::assign_rec( valuest &values, const exprt &lhs, const exprt &rhs, const namespacet &ns) { const typet & lhs_type = ns.follow(lhs.type()); const typet & rhs_type = ns.follow(rhs.type()); #ifdef DEBUG std::cout << "assign: " << from_expr(ns, "", lhs) << " := " << from_type(ns, "", rhs_type) << '\n'; #endif if(lhs.id()==ID_symbol && rhs.id()==ID_if) { exprt cond=rhs.op0(); assert(cond.operands().size()==2); if(values.is_constant(cond.op0()) && values.is_constant(cond.op1())) { if(cond.op0().id()==ID_index) { exprt index=cond.op0(); exprt new_expr=concatenate_array_id(index.op0(), index.op1(), index.type()); values.replace_const(new_expr); cond.op0()=new_expr; cond = simplify_expr(cond,ns); } else assert(0); assign(values, to_symbol_expr(lhs), cond, ns); } } else if(lhs.id()==ID_symbol && rhs_type.id()!=ID_array && rhs_type.id()!=ID_struct && rhs_type.id()!=ID_union) { if(values.is_constant(rhs)) assign(values, to_symbol_expr(lhs), rhs, ns); else values.set_to_top(to_symbol_expr(lhs)); } else if(lhs.id()==ID_symbol && lhs_type.id()==ID_array && rhs_type.id()==ID_array) { exprt new_expr; mp_integer idx=0; forall_operands(it, rhs) { new_expr=concatenate_array_id(lhs, idx, it->type()); assign(values, to_symbol_expr(new_expr), *it, ns); idx = idx +1; }
void goto_convertt::do_function_call( const exprt &lhs, const exprt &function, const exprt::operandst &arguments, goto_programt &dest) { // make it all side effect free exprt new_lhs=lhs, new_function=function; exprt::operandst new_arguments=arguments; if(!new_lhs.is_nil()) clean_expr(new_lhs, dest); clean_expr(new_function, dest); // the arguments of __noop do not get evaluated if(new_function.id()==ID_symbol && to_symbol_expr(new_function).get_identifier()=="__noop") { new_arguments.clear(); } Forall_expr(it, new_arguments) clean_expr(*it, dest); // split on the function if(new_function.id()==ID_if) { do_function_call_if(new_lhs, to_if_expr(new_function), new_arguments, dest); } else if(new_function.id()==ID_symbol) { do_function_call_symbol(new_lhs, to_symbol_expr(new_function), new_arguments, dest); } else if(new_function.id()=="NULL-object") { } else if(new_function.id()==ID_dereference || new_function.id()=="virtual_function") { do_function_call_other(new_lhs, new_function, new_arguments, dest); } else { error().source_location=function.find_source_location(); error() << "unexpected function argument: " << new_function.id() << eom; throw 0; } }
void goto_symext::symex_dead(statet &state) { const goto_programt::instructiont &instruction=*state.source.pc; const codet &code=to_code(instruction.code); if(code.operands().size()!=1) throw "dead expects one operand"; if(code.op0().id()!=ID_symbol) throw "dead expects symbol as first operand"; // We increase the L2 renaming to make these non-deterministic. // We also prevent propagation of old values. ssa_exprt ssa(to_symbol_expr(code.op0())); state.rename(ssa, ns, goto_symex_statet::L1); // in case of pointers, put something into the value set if(ns.follow(code.op0().type()).id()==ID_pointer) { exprt failed= get_failed_symbol(to_symbol_expr(code.op0()), ns); exprt rhs; if(failed.is_not_nil()) { address_of_exprt address_of_expr; address_of_expr.object()=failed; address_of_expr.type()=code.op0().type(); rhs=address_of_expr; } else rhs=exprt(ID_invalid); state.rename(rhs, ns, goto_symex_statet::L1); state.value_set.assign(ssa, rhs, ns, true, false); } ssa_exprt ssa_lhs=to_ssa_expr(ssa); const irep_idt &l1_identifier=ssa_lhs.get_identifier(); // prevent propagation state.propagation.remove(l1_identifier); // L2 renaming if(state.level2.current_names.find(l1_identifier)!= state.level2.current_names.end()) state.level2.increase_counter(l1_identifier); }
void remove_virtual_functionst::get_functions( const exprt &function, functionst &functions) { const irep_idt class_id=function.get(ID_C_class); const irep_idt component_name=function.get(ID_component_name); assert(!class_id.empty()); // iterate over all children, transitively std::vector<irep_idt> children= class_hierarchy.get_children_trans(class_id); for(const auto & child : children) { exprt method=get_method(child, component_name); if(method.is_not_nil()) { functiont function; function.class_id=child; function.symbol_expr=to_symbol_expr(method); function.symbol_expr.set(ID_C_class, child); functions.push_back(function); } } // Start from current class, go to parents until something // is found. irep_idt c=class_id; while(!c.empty()) { exprt method=get_method(c, component_name); if(method.is_not_nil()) { functiont function; function.class_id=c; function.symbol_expr=to_symbol_expr(method); function.symbol_expr.set(ID_C_class, c); functions.push_back(function); break; // abort } const class_hierarchyt::idst &parents= class_hierarchy.class_map[c].parents; if(parents.empty()) break; c=parents.front(); } }
void nondet_static( const namespacet &ns, goto_functionst &goto_functions, const irep_idt &fct_name) { goto_functionst::function_mapt::iterator i_it=goto_functions.function_map.find(fct_name); assert(i_it!=goto_functions.function_map.end()); goto_programt &init=i_it->second.body; Forall_goto_program_instructions(i_it, init) { const goto_programt::instructiont &instruction=*i_it; if(instruction.is_assign()) { const symbol_exprt &sym=to_symbol_expr( to_code_assign(instruction.code).lhs()); // is it a __CPROVER_* variable? if(has_prefix(id2string(sym.get_identifier()), CPROVER_PREFIX)) continue; // static lifetime? if(!ns.lookup(sym.get_identifier()).is_static_lifetime) continue; // constant? if(sym.type().get_bool(ID_C_constant)) continue; i_it=init.insert_before(++i_it); i_it->make_assignment(); i_it->code=code_assignt(sym, side_effect_expr_nondett(sym.type())); i_it->location=instruction.location; i_it->function=instruction.function; } else if(instruction.is_function_call()) { const code_function_callt &fct=to_code_function_call(instruction.code); const symbol_exprt &fsym=to_symbol_expr(fct.function()); if(has_prefix(id2string(fsym.get_identifier()), "c::#ini#")) nondet_static(ns, goto_functions, fsym.get_identifier()); } } }
void summarizer_fwt::inline_summaries(const function_namet &function_name, local_SSAt &SSA, const exprt &precondition, bool context_sensitive) { for(local_SSAt::nodest::const_iterator n_it = SSA.nodes.begin(); n_it != SSA.nodes.end(); n_it++) { for(local_SSAt::nodet::function_callst::const_iterator f_it = n_it->function_calls.begin(); f_it != n_it->function_calls.end(); f_it++) { assert(f_it->function().id()==ID_symbol); //no function pointers if(!check_call_reachable(function_name,SSA,n_it,f_it,precondition,true)) { continue; } if(!check_precondition(function_name,SSA,n_it,f_it, precondition,context_sensitive)) { exprt precondition_call = true_exprt(); if(context_sensitive) precondition_call = compute_calling_context( function_name,SSA,n_it,f_it,precondition,true); irep_idt fname = to_symbol_expr(f_it->function()).get_identifier(); status() << "Recursively summarizing function " << fname << eom; compute_summary_rec(fname,precondition_call,context_sensitive); summaries_used++; } } } }
void thread_exit_instrumentation(goto_functionst &goto_functions) { // we'll look for START THREAD std::set<irep_idt> thread_fkts; forall_goto_functions(f_it, goto_functions) { if(has_start_thread(f_it->second.body)) { // now look for functions called for(const auto &instruction : f_it->second.body.instructions) if(instruction.is_function_call()) { const exprt &function=to_code_function_call(instruction.code).function(); if(function.id()==ID_symbol) thread_fkts.insert(to_symbol_expr(function).get_identifier()); } } } // now instrument for(const auto &fkt : thread_fkts) { thread_exit_instrumentation(goto_functions.function_map[fkt].body); } }
bool symex_dereference_statet::has_failed_symbol( const exprt &expr, const symbolt *&symbol) { renaming_nst renaming_ns(goto_symex.ns, state); if(expr.id()==ID_symbol) { const symbolt &ptr_symbol= renaming_ns.lookup(to_symbol_expr(expr).get_identifier()); const irep_idt &failed_symbol= ptr_symbol.type.get("#failed_symbol"); if(failed_symbol!="" && !renaming_ns.lookup(failed_symbol, symbol)) { symbolt sym=*symbol; symbolt *sym_ptr=0; sym.name=state.rename(sym.name, renaming_ns, goto_symex_statet::L1); goto_symex.new_symbol_table.move(sym, sym_ptr); symbol=sym_ptr; return true; } } return false; }
void rd_range_domaint::assign( const namespacet &ns, locationt from, const exprt &lhs, const mp_integer &range_start, const mp_integer &size) { if(lhs.id()==ID_member) assign(ns, from, to_member_expr(lhs).struct_op(), range_start, size); else if(lhs.id()==ID_index) assign(ns, from, to_index_expr(lhs).array(), range_start, size); else { const symbol_exprt &symbol=to_symbol_expr(lhs); const irep_idt identifier=symbol.get_identifier(); if(range_start>=0) { kill(from, identifier, range_start, size); gen(from, identifier, range_start, size); } else { mp_integer full_size=pointer_offset_size(ns, symbol.type()); gen(from, identifier, 0, full_size); } } }
void goto_checkt::invalidate(const exprt &lhs) { if(lhs.id()==ID_index) invalidate(to_index_expr(lhs).array()); else if(lhs.id()==ID_member) invalidate(to_member_expr(lhs).struct_op()); else if(lhs.id()==ID_symbol) { // clear all assertions about 'symbol' find_symbols_sett find_symbols_set; find_symbols_set.insert(to_symbol_expr(lhs).get_identifier()); for(assertionst::iterator it=assertions.begin(); it!=assertions.end(); ) // no it++ { assertionst::iterator next=it; next++; if(has_symbol(*it, find_symbols_set) || has_dereference(*it)) assertions.erase(it); it=next; } } else { // give up, clear all assertions.clear(); } }
void concurrency_instrumentationt::instrument(exprt &expr) { std::set<exprt> symbols; find_symbols(expr, symbols); replace_symbolt replace_symbol; for(std::set<exprt>::const_iterator s_it=symbols.begin(); s_it!=symbols.end(); s_it++) { if(s_it->id()==ID_symbol) { const irep_idt identifier= to_symbol_expr(*s_it).get_identifier(); shared_varst::const_iterator v_it=shared_vars.find(identifier); if(v_it!=shared_vars.end()) { index_exprt new_expr; //new_expr.array()=symbol_expr(); //new_expr.index()=symbol_expr(); replace_symbol.insert(identifier, new_expr); } } } }
bool acceleratet::is_underapproximate(path_acceleratort &accelerator) { for(std::set<exprt>::iterator it=accelerator.dirty_vars.begin(); it!=accelerator.dirty_vars.end(); ++it) { if(it->id()==ID_symbol && it->type() == bool_typet()) { const irep_idt &id=to_symbol_expr(*it).get_identifier(); const symbolt &sym=symbol_table.lookup(id); if(sym.module=="scratch") { continue; } } #ifdef DEBUG std::cout << "Underapproximate variable: " << expr2c(*it, ns) << '\n'; #endif return true; } return false; }
void component_exprt::gen_comp_var( exprt &comp_var, const exprt &expr, std::string suffix) { std::string base; if (expr.id()==ID_symbol) base="."+id2string(to_symbol_expr(expr).get_identifier()); else if (expr.id()==ID_constant) base=".const"; else if(id_maps.find(expr.id())!=id_maps.end()) base=".OPERATOR."+id_maps[expr.id()]; else base=".OPERATOR."+id2string(expr.id()); std::string final_name="C."+id2string(source_location.get_line())+"."+i2string(instruction_number)+"_"+i2string(component_cnt)+"_"+i2string(unique_identifier)+base+suffix; to_symbol_expr(comp_var).set_identifier(final_name); }
void uninitialized_domaint::assign(const exprt &lhs) { if(lhs.id()==ID_index) assign(to_index_expr(lhs).array()); else if(lhs.id()==ID_member) assign(to_member_expr(lhs).struct_op()); else if(lhs.id()==ID_symbol) uninitialized.erase(to_symbol_expr(lhs).get_identifier()); }
Forall_goto_program_instructions(i_it, goto_program) { if(i_it->is_function_call()) { code_function_callt &function_call=to_code_function_call(i_it->code); code_typet old_type=to_code_type(function_call.function().type()); // Do we return anything? if(old_type.return_type()!=empty_typet()) { // replace "lhs=f(...)" by "f(...); lhs=f#return_value; DEAD f#return_value;" assert(function_call.function().id()==ID_symbol); const irep_idt function_id= to_symbol_expr(function_call.function()).get_identifier(); // see if we have a body goto_functionst::function_mapt::const_iterator f_it=goto_functions.function_map.find(function_id); if(f_it==goto_functions.function_map.end()) throw "failed to find function `"+id2string(function_id)+"' in function map"; // fix the type to_code_type(function_call.function().type()).return_type()=empty_typet(); if(function_call.lhs().is_not_nil()) { exprt rhs; symbol_exprt return_value; return_value.type()=function_call.lhs().type(); return_value.set_identifier(id2string(function_id)+RETURN_VALUE_SUFFIX); rhs=return_value; goto_programt::targett t_a=goto_program.insert_after(i_it); t_a->make_assignment(); t_a->source_location=i_it->source_location; t_a->code=code_assignt(function_call.lhs(), rhs); t_a->function=i_it->function; // fry the previous assignment function_call.lhs().make_nil(); if(f_it->second.body_available()) { goto_programt::targett t_d=goto_program.insert_after(t_a); t_d->make_dead(); t_d->source_location=i_it->source_location; t_d->code=code_deadt(rhs); t_d->function=i_it->function; } } } } }
void symex_slicet::get_symbols(const exprt &expr) { get_symbols(expr.type()); forall_operands(it, expr) get_symbols(*it); if(expr.id()==ID_symbol) depends.insert(to_symbol_expr(expr).get_identifier()); }
bool pointer_logict::is_dynamic_object(const exprt &expr) const { if(expr.type().get_bool("#dynamic")) return true; if(expr.id()==ID_symbol) if(has_prefix(id2string(to_symbol_expr(expr).get_identifier()), "symex_dynamic::")) return true; return false; }
void summarizer_fw_termt::inline_summaries( const function_namet &function_name, local_SSAt &SSA, exprt precondition, bool context_sensitive, threevalt &calls_terminate, bool &has_function_calls) { for(local_SSAt::nodest::iterator n_it=SSA.nodes.begin(); n_it!=SSA.nodes.end(); n_it++) { for(local_SSAt::nodet::function_callst::iterator f_it= n_it->function_calls.begin(); f_it!=n_it->function_calls.end(); f_it++) { assert(f_it->function().id()==ID_symbol); // no function pointers exprt::operandst c; c.push_back(precondition); get_assertions(SSA, c); // assertions as assumptions precondition=conjunction(c); if(!options.get_bool_option("competition-mode") && !check_call_reachable( function_name, SSA, n_it, f_it, precondition, true)) continue; has_function_calls=true; irep_idt fname=to_symbol_expr(f_it->function()).get_identifier(); if(!check_precondition( function_name, SSA, n_it, f_it, precondition, context_sensitive)) { exprt precondition_call=true_exprt(); if(context_sensitive) precondition_call=compute_calling_context( function_name, SSA, n_it, f_it, precondition, true); status() << "Recursively summarizing function " << fname << eom; compute_summary_rec(fname, precondition_call, context_sensitive); summaries_used++; } // get information about callee termination if(summary_db.exists(fname) && summary_db.get(fname).terminates!=YES) { // cannot propagate NO // because call reachability might be over-approximating calls_terminate=UNKNOWN; break; } } } }
static void build_ssa_identifier_rec( const exprt &expr, const irep_idt &l0, const irep_idt &l1, const irep_idt &l2, std::ostream &os, std::ostream &l1_object_os) { if(expr.id()==ID_member) { const member_exprt &member=to_member_expr(expr); build_ssa_identifier_rec(member.struct_op(), l0, l1, l2, os, l1_object_os); os << '.' << member.get_component_name(); } else if(expr.id()==ID_index) { const index_exprt &index=to_index_expr(expr); build_ssa_identifier_rec(index.array(), l0, l1, l2, os, l1_object_os); mp_integer idx; if(to_integer(to_constant_expr(index.index()), idx)) assert(false); os << '[' << idx << ']'; } else if(expr.id()==ID_symbol) { auto symid=to_symbol_expr(expr).get_identifier(); os << symid; l1_object_os << symid; if(!l0.empty()) { os << '!' << l0; l1_object_os << '!' << l0; } if(!l1.empty()) { os << '@' << l1; l1_object_os << '@' << l1; } if(!l2.empty()) os << '#' << l2; } else assert(false); }
void value_set_dereferencet::valid_check( const exprt &object, const guardt &guard, const modet mode) { if(!options.get_bool_option("pointer-check")) return; const exprt &symbol_expr=get_symbol(object); if(symbol_expr.id()==ID_string_constant) { // always valid, but can't write if(mode==modet::WRITE) { dereference_callback.dereference_failure( "pointer dereference", "write access to string constant", guard); } } else if(symbol_expr.is_nil() || symbol_expr.get_bool(ID_C_invalid_object)) { // always "valid", shut up return; } else if(symbol_expr.id()==ID_symbol) { const irep_idt identifier= is_ssa_expr(symbol_expr)? to_ssa_expr(symbol_expr).get_object_name(): to_symbol_expr(symbol_expr).get_identifier(); const symbolt &symbol=ns.lookup(identifier); if(symbol.type.get_bool(ID_C_is_failed_symbol)) { dereference_callback.dereference_failure( "pointer dereference", "invalid pointer", guard); } #if 0 if(dereference_callback.is_valid_object(identifier)) return; // always ok #endif } }
void string_instrumentationt::do_function_call( goto_programt &dest, goto_programt::targett target) { code_function_callt &call= to_code_function_call(target->code); exprt &function=call.function(); //const exprt &lhs=call.lhs(); if(function.id()=="symbol") { const irep_idt &identifier= to_symbol_expr(function).get_identifier(); if(identifier=="c::strcoll") { } else if(identifier=="c::strncmp") do_strncmp(dest, target, call); else if(identifier=="c::strxfrm") { } else if(identifier=="c::strchr") do_strchr(dest, target, call); else if(identifier=="c::strcspn") { } else if(identifier=="c::strpbrk") { } else if(identifier=="c::strrchr") do_strrchr(dest, target, call); else if(identifier=="c::strspn") { } else if(identifier=="c::strerror") do_strerror(dest, target, call); else if(identifier=="c::strstr") do_strstr(dest, target, call); else if(identifier=="c::strtok") do_strtok(dest, target, call); else if(identifier=="c::sprintf") do_sprintf(dest, target, call); else if(identifier=="c::snprintf") do_snprintf(dest, target, call); else if(identifier=="c::fscanf") do_fscanf(dest, target, call); dest.update(); } }
void remove_return(goto_programt &body, const goto_programt::targett pos) { code_function_callt &call=to_code_function_call(pos->code); const irep_idt &id=to_symbol_expr(call.function()).get_identifier(); const typet &type=call.lhs().type(); const source_locationt &loc=pos->source_location; const irep_idt &func=pos->function; const goto_programt::targett assign=body.insert_after(pos); assign->make_assignment(); assign->source_location=loc; assign->code=code_assignt(call.lhs(), get_ret_val_var(id, type)); assign->function=func; call.lhs().make_nil(); }
const irep_idt &get_affected_variable(const goto_programt::instructiont &instr) { switch (instr.type) { case goto_program_instruction_typet::DECL: return to_code_decl(instr.code).get_identifier(); case goto_program_instruction_typet::ASSIGN: return to_symbol_expr(to_code_assign(instr.code).lhs()).get_identifier(); case goto_program_instruction_typet::DEAD: return to_code_dead(instr.code).get_identifier(); default: assert(!"Only DECL, ASSIGN, DEAD allowed."); } }
void remove_virtual_functionst::get_functions( const exprt &function, functionst &functions) { const irep_idt class_id=function.get(ID_C_class); const irep_idt component_name=function.get(ID_component_name); assert(!class_id.empty()); functiont root_function; // Start from current class, go to parents until something // is found. irep_idt c=class_id; while(!c.empty()) { exprt method=get_method(c, component_name); if(method.is_not_nil()) { root_function.class_id=c; root_function.symbol_expr=to_symbol_expr(method); root_function.symbol_expr.set(ID_C_class, c); break; // abort } const class_hierarchyt::idst &parents= class_hierarchy.class_map[c].parents; if(parents.empty()) break; c=parents.front(); } if(root_function.class_id.empty()) { // No definition here; this is an abstract function. root_function.class_id=class_id; } // iterate over all children, transitively std::set<irep_idt> visited; get_child_functions_rec( class_id, root_function.symbol_expr, component_name, functions, visited); if(root_function.symbol_expr!=symbol_exprt()) functions.push_back(root_function); }
void goto_symext::rewrite_quantifiers(exprt &expr, statet &state) { if(expr.id()==ID_forall) { // forall X. P -> P // we keep the quantified variable unique by means of L2 renaming assert(expr.operands().size()==2); assert(expr.op0().id()==ID_symbol); symbol_exprt tmp0= to_symbol_expr(to_ssa_expr(expr.op0()).get_original_expr()); symex_decl(state, tmp0); exprt tmp=expr.op1(); expr.swap(tmp); } }
void goto_symext::symex_decl(statet &state) { const goto_programt::instructiont &instruction=*state.source.pc; const codet &code=to_code(instruction.code); if(code.operands().size()==2) throw "two-operand decl not supported here"; if(code.operands().size()!=1) throw "decl expects one operand"; if(code.op0().id()!=ID_symbol) throw "decl expects symbol as first operand"; symex_decl(state, to_symbol_expr(code.op0())); }
Forall_goto_program_instructions(i_it, goto_program) { if(i_it->is_function_call()) { code_function_callt &function_call=to_code_function_call(i_it->code); // add x=y for f(y) where x is the parameter assert(function_call.function().id()==ID_symbol); const irep_idt &identifier= to_symbol_expr(function_call.function()).get_identifier(); // see if we have it const namespacet ns(symbol_table); const symbolt &function_symbol=ns.lookup(identifier); const code_typet &code_type=to_code_type(function_symbol.type); goto_programt tmp; for(std::size_t nr=0; nr<code_type.parameters().size(); nr++) { irep_idt p_identifier=code_type.parameters()[nr].get_identifier(); if(p_identifier.empty()) continue; if(nr<function_call.arguments().size()) { goto_programt::targett t=tmp.add_instruction(); t->make_assignment(); t->source_location=i_it->source_location; const symbolt &lhs_symbol=ns.lookup(p_identifier); symbol_exprt lhs=lhs_symbol.symbol_expr(); exprt rhs=function_call.arguments()[nr]; if(rhs.type()!=lhs.type()) rhs.make_typecast(lhs.type()); t->code=code_assignt(lhs, rhs); t->function=i_it->function; } } std::size_t count=tmp.instructions.size(); goto_program.insert_before_swap(i_it, tmp); for(; count!=0; count--) i_it++; } }
void jsil_typecheckt::update_expr_type(exprt &expr, const typet &type) { expr.type()=type; if(expr.id()==ID_symbol) { const irep_idt &id=to_symbol_expr(expr).get_identifier(); if(!symbol_table.has_symbol(id)) throw "Unexpected symbol: "+id2string(id); symbolt &s=symbol_table.lookup(id); if(s.type.id().empty() || s.type.is_nil()) s.type=type; else s.type=jsil_union(s.type, type); } }