pointer_logict::pointer_logict(const namespacet &_ns):ns(_ns) { // add NULL null_object=objects.number(exprt(ID_NULL)); assert(null_object==0); // add INVALID invalid_object=objects.number(exprt("INVALID")); }
exprt pointer_logict::pointer_expr( const pointert &pointer, const typet &type) const { if(pointer.object==null_object) // NULL? { if(pointer.offset==0) { constant_exprt result(type); result.set_value(ID_NULL); return result; } else { constant_exprt null(type); null.set_value(ID_NULL); return plus_exprt(null, from_integer(pointer.offset, pointer_diff_type())); } } else if(pointer.object==invalid_object) // INVALID? { constant_exprt result(type); result.set_value("INVALID"); return result; } if(pointer.object>=objects.size()) { constant_exprt result(type); result.set_value("INVALID-"+std::to_string(pointer.object)); return result; } const exprt &object_expr=objects[pointer.object]; exprt deep_object=object_rec(pointer.offset, type, object_expr); exprt result; if(type.id()==ID_pointer) result=exprt(ID_address_of, type); else if(type.id()==ID_reference) result=exprt("reference_to", type); else assert(0); result.copy_to_operands(deep_object); return result; }
void xml_typecheckt::convert_xmi_class(const xmlt &xml) { const xmlt &class_name= get(xml, "Foundation.Core.ModelElement.name"); const xmlt &Ns= get(xml, "Foundation.Core.Namespace.ownedElement"); symbolt symbol; symbol.base_name=class_name.data; symbol.name="xml::xmi::class::"+id2string(symbol.base_name); symbol.type=typet("class"); for(xmlt::elementst::const_iterator n_it=Ns.elements.begin(); n_it!=Ns.elements.end(); n_it++) { if(n_it->name=="Behavioral_Elements.State_Machines.StateMachine") { symbol.value.copy_to_operands(exprt()); convert_xmi_StateMachine(*n_it, symbol.value.operands().back()); } else throw "unexpected XMI: "+n_it->name; } if(symbol_table.move(symbol)) { str << "class already in symbol table: " << symbol.name; throw 0; } }
void modelchecker_smvt::instantiate_expression(exprt &expr) { Forall_operands(it, expr) instantiate_expression(*it); if(expr.id()==ID_predicate_symbol) { unsigned p=atoi(expr.get(ID_identifier).c_str()); expr.id(ID_symbol); expr.set(ID_identifier, variable_names[p]); } else if(expr.id()==ID_predicate_next_symbol) { unsigned p=atoi(expr.get(ID_identifier).c_str()); expr.id(ID_next_symbol); expr.set(ID_identifier, variable_names[p]); } else if(expr.id()==ID_nondet_symbol) { nondet_symbolst::const_iterator it= nondet_symbols.find( static_cast<const exprt &>(expr.find("expression"))); if(it==nondet_symbols.end()) throw "failed to find nondet_symbol"; typet type=expr.type(); expr=exprt(ID_symbol, type); expr.set(ID_identifier, it->second); } }
void cpp_typecheckt::new_temporary( const source_locationt &source_location, const typet &type, const exprt::operandst &ops, exprt &temporary) { // create temporary object exprt tmp_object_expr=exprt(ID_side_effect, type); tmp_object_expr.set(ID_statement, ID_temporary_object); tmp_object_expr.add_source_location()= source_location; exprt new_object(ID_new_object); new_object.add_source_location()=tmp_object_expr.source_location(); new_object.set(ID_C_lvalue, true); new_object.type()=tmp_object_expr.type(); already_typechecked(new_object); codet new_code = cpp_constructor(source_location, new_object, ops); if(new_code.is_not_nil()) { if(new_code.get(ID_statement)==ID_assign) tmp_object_expr.move_to_operands(new_code.op1()); else tmp_object_expr.add(ID_initializer)=new_code; } temporary.swap(tmp_object_expr); }
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); } }
void cpp_typecheckt::find_constructor( const typet &start_dest_type, exprt &constructor_expr) { constructor_expr.make_nil(); source_locationt source_location=start_dest_type.source_location(); typet dest_type(start_dest_type); follow_symbol(dest_type); if(dest_type.id()!=ID_struct) return; const struct_typet::componentst &components= to_struct_type(dest_type).components(); for(struct_typet::componentst::const_iterator it=components.begin(); it!=components.end(); it++) { const struct_typet::componentt &component=*it; const typet &type=component.type(); if(type.find(ID_return_type).id()==ID_constructor) { const irept::subt ¶meters= type.find(ID_parameters).get_sub(); namespacet ns(symbol_table); if(parameters.size()==1) { const exprt ¶meter=(exprt &)parameters.front(); const typet &arg_type=parameter.type(); if(arg_type.id()==ID_pointer && type_eq(arg_type.subtype(), dest_type, ns)) { // found! const irep_idt &identifier= component.get(ID_name); if(identifier=="") throw "constructor without identifier"; constructor_expr=exprt(ID_symbol, type); constructor_expr.set(ID_identifier, identifier); constructor_expr.add_source_location()=source_location; return; } } } } }
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); }
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 xml_typecheckt::convert_xmi_StateMachine( const xmlt &xml, exprt &dest) { dest=exprt("StateMachine"); // const xmlt &top= // get(xml, "Behavioral_Elements.State_Machines.StateMachine.top"); // const xmlt &transitions= // get(xml, "Behavioral_Elements.State_Machines.StateMachine.transitions"); }
exprt gen_one(const typet &type) { const irep_idt type_id=type.id(); exprt result=constant_exprt(type); if(type_id==ID_bool || type_id==ID_rational || type_id==ID_real || type_id==ID_integer || type_id==ID_natural) { result.set(ID_value, ID_1); } else if(type_id==ID_unsignedbv || type_id==ID_signedbv || type_id==ID_c_enum) { std::string value; unsigned width=to_bitvector_type(type).get_width(); for(unsigned i=0; i<width-1; i++) value+='0'; value+='1'; result.set(ID_value, value); } else if(type_id==ID_fixedbv) { fixedbvt fixedbv; fixedbv.spec=to_fixedbv_type(type); fixedbv.from_integer(1); result=fixedbv.to_expr(); } else if(type_id==ID_floatbv) { ieee_floatt ieee_float; ieee_float.spec=to_floatbv_type(type); ieee_float.from_integer(1); result=ieee_float.to_expr(); } else if(type_id==ID_complex) { result=exprt(ID_complex, type); result.operands().resize(2); result.op0()=gen_one(type.subtype()); result.op1()=gen_zero(type.subtype()); } else result.make_nil(); return result; }
exprt gen_zero(const typet &type) { exprt result; const irep_idt type_id=type.id(); result=constant_exprt(type); if(type_id==ID_rational || type_id==ID_real || type_id==ID_integer || type_id==ID_natural || type_id==ID_complex || type_id==ID_c_enum) { result.set(ID_value, ID_0); } else if(type_id==ID_unsignedbv || type_id==ID_signedbv || type_id==ID_verilogbv || type_id==ID_floatbv || type_id==ID_fixedbv) { std::string value; unsigned width=to_bitvector_type(type).get_width(); for(unsigned i=0; i<width; i++) value+='0'; result.set(ID_value, value); } else if(type_id==ID_complex) { result=exprt(ID_complex, type); exprt sub_zero=gen_zero(type.subtype()); result.operands().resize(2, sub_zero); } else if(type_id==ID_bool) { result.make_false(); } else if(type_id==ID_pointer) { result.set(ID_value, ID_NULL); } else result.make_nil(); return result; }
void goto_checkt::add_guarded_claim( const exprt &_expr, const std::string &comment, const std::string &property_class, const source_locationt &source_location, const exprt &src_expr, const guardt &guard) { exprt expr(_expr); // first try simplifier on it if(enable_simplify) simplify(expr, ns); // throw away trivial properties? if(!retain_trivial && expr.is_true()) return; // add the guard exprt guard_expr=guard.as_expr(); exprt new_expr; if(guard_expr.is_true()) new_expr.swap(expr); else { new_expr=exprt(ID_implies, bool_typet()); new_expr.move_to_operands(guard_expr, expr); } if(assertions.insert(new_expr).second) { goto_program_instruction_typet type= enable_assert_to_assume?ASSUME:ASSERT; goto_programt::targett t=new_code.add_instruction(type); std::string source_expr_string=from_expr(ns, "", src_expr); t->guard.swap(new_expr); t->source_location=source_location; t->source_location.set_comment(comment+" in "+source_expr_string); t->source_location.set_property_class(property_class); } }
exprt guardt::as_expr(guard_listt::const_iterator it) const { if(it==guard_list.end()) return true_exprt(); else if(it==--guard_list.end()) return guard_list.back(); exprt dest; dest=exprt(ID_and, typet(ID_bool)); dest.reserve_operands(guard_list.size()); for(; it!=guard_list.end(); it++) { if(!it->is_boolean()) throw "guard is expected to be Boolean"; dest.copy_to_operands(*it); } return dest; }
void goto_checkt::add_guarded_claim(const exprt &_expr, const std::string &comment, const std::string &property, const locationt &location, const guardt &guard) { bool all_claims = options.get_bool_option("all-claims"); exprt expr(_expr); // first try simplifier on it if (!options.get_bool_option("no-simplify")) { expr2tc tmpexpr; migrate_expr(expr, tmpexpr); base_type(tmpexpr, ns); expr = migrate_expr_back(tmpexpr); simplify(expr); } if (!all_claims && expr.is_true()) return; // add the guard exprt guard_expr = migrate_expr_back(guard.as_expr()); exprt new_expr; if (guard_expr.is_true()) new_expr.swap(expr); else { new_expr = exprt("=>", bool_typet()); new_expr.move_to_operands(guard_expr, expr); } if (assertions.insert(new_expr).second) { goto_programt::targett t = new_code.add_instruction(ASSERT); migrate_expr(new_expr, t->guard); t->location = location; t->location.comment(comment); t->location.property(property); } }
exprt gen_zero(const typet &type) { exprt result; const std::string type_id=type.id_string(); result=exprt("constant", type); if(type_id=="rational" || type_id=="real" || type_id=="integer" || type_id=="natural" || type_id=="complex") { result.value("0"); } else if(type_id=="unsignedbv" || type_id=="signedbv" || type_id=="floatbv" || type_id=="fixedbv" || type_id=="c_enum") { std::string value; unsigned width=bv_width(type); for(unsigned i=0; i<width; i++) value+='0'; result.value(value); } else if(type_id=="bool") { result.make_false(); } else if(type_id=="pointer") { result.value("NULL"); } else result.make_nil(); return result; }
const exprt qbf_squolem_coret::f_get_dnf(WitnessStack *wsp) { Clause *p=wsp->posWits; if(!p) return exprt(ID_false, typet(ID_bool)); exprt::operandst operands; while(p!=NULL) { exprt cube=and_exprt(); for(unsigned i=0; i<p->size; i++) { const Literal &lit=p->literals[i]; exprt subf = f_get(literalt(var(lit), !isPositive(lit))); if(find(cube.operands().begin(), cube.operands().end(), subf)== cube.operands().end()) cube.move_to_operands(subf); simplify_extractbits(cube); } if(cube.operands().empty()) cube=true_exprt(); else if(cube.operands().size()==1) { const exprt tmp=cube.op0(); cube=tmp; } #if 0 std::cout << "CUBE: " << cube << std::endl; #endif operands.push_back(cube); p=p->next; } return or_exprt(operands); }
exprt ranking_synthesis_satt::coefficient(const exprt &expr) { assert(expr.id()==ID_symbol); exprt &entry = coefficient_map[expr]; if(entry==exprt()) { irep_idt ident=expr.get_string(ID_identifier) + "$C"; // set up a new coefficient entry.id(ID_symbol); entry.set(ID_identifier, ident); // adjust the coefficient type entry.type()=signedbv_typet(2); //expr.type(); } return entry; }
const exprt qbf_squolem_coret::f_get_cnf(WitnessStack *wsp) { Clause *p=wsp->negWits; if(!p) return exprt(ID_true, typet(ID_bool)); exprt::operandst operands; while(p!=NULL) { exprt clause=or_exprt(); for(unsigned i=0; i<p->size; i++) { const Literal &lit=p->literals[i]; exprt subf = f_get(literalt(var(lit), isPositive(lit))); // negated! if(find(clause.operands().begin(), clause.operands().end(), subf)== clause.operands().end()) clause.move_to_operands(subf); } if(clause.operands().empty()) clause=false_exprt(); else if(clause.operands().size()==1) { const exprt tmp=clause.op0(); clause=tmp; } #if 0 std::cout << "CLAUSE: " << clause << std::endl; #endif operands.push_back(clause); p=p->next; } return and_exprt(operands); }
exprt gen_one(const typet &type) { const std::string &type_id=type.id_string(); exprt result=exprt("constant", type); if(type_id=="bool" || type_id=="rational" || type_id=="real" || type_id=="integer" || type_id=="natural" || type_id=="complex") { result.value("1"); } else if(type_id=="unsignedbv" || type_id=="signedbv") { std::string value; for(int i=0; i<atoi(type.width().c_str())-1; i++) value+='0'; value+='1'; result.value(value); } else if(type_id=="fixedbv") { fixedbvt fixedbv; fixedbv.spec=to_fixedbv_type(type); fixedbv.from_integer(1); result=fixedbv.to_expr(); } else if(type_id=="floatbv") { std::cerr << "floatbv unsupported, sorry" << std::endl; abort(); } else result.make_nil(); return result; }
void make_it_a_predicate( const predicatest &predicates, exprt &expr, const namespacet &ns) { bool negation; canonicalize(expr, negation, ns); // see if we have it unsigned nr; if(predicates.find(expr, nr)) { // yes, we do! // see if it is a constant if(predicates[nr].is_true()) expr.make_true(); else if(predicates[nr].is_false()) expr.make_false(); else { expr=exprt(ID_predicate_symbol, typet(ID_bool)); expr.set(ID_identifier, nr); } if(negation) expr.make_not(); } else { // nah, we don't // make it nondeterministic choice exprt tmp(ID_nondet_symbol, typet(ID_bool)); tmp.add(ID_expression).swap(expr); expr.swap(tmp); } }
void ansi_c_convert_typet::read_rec(const typet &type) { if(type.id()==ID_merged_type) { forall_subtypes(it, type) read_rec(*it); } else if(type.id()==ID_signed) signed_cnt++; else if(type.id()==ID_unsigned) unsigned_cnt++; else if(type.id()==ID_ptr32) c_qualifiers.is_ptr32=true; else if(type.id()==ID_ptr64) c_qualifiers.is_ptr64=true; else if(type.id()==ID_volatile) c_qualifiers.is_volatile=true; else if(type.id()==ID_asm) { // These are called 'asm labels' by GCC. // ignore for now } else if(type.id()==ID_const) c_qualifiers.is_constant=true; else if(type.id()==ID_restrict) c_qualifiers.is_restricted=true; else if(type.id()==ID_atomic) c_qualifiers.is_atomic=true; else if(type.id()==ID_atomic_type_specifier) { // this gets turned into the qualifier, uh c_qualifiers.is_atomic=true; read_rec(type.subtype()); } else if(type.id()==ID_char) char_cnt++; else if(type.id()==ID_int) int_cnt++; else if(type.id()==ID_int8) int8_cnt++; else if(type.id()==ID_int16) int16_cnt++; else if(type.id()==ID_int32) int32_cnt++; else if(type.id()==ID_int64) int64_cnt++; else if(type.id()==ID_gcc_float128) gcc_float128_cnt++; else if(type.id()==ID_gcc_int128) gcc_int128_cnt++; else if(type.id()==ID_gcc_attribute_mode) { gcc_attribute_mode=type; } else if(type.id()==ID_gcc_attribute) { } else if(type.id()==ID_msc_based) { const exprt &as_expr=static_cast<const exprt &>(static_cast<const irept &>(type)); assert(as_expr.operands().size()==1); msc_based=as_expr.op0(); } else if(type.id()==ID_custom_bv) { bv_cnt++; const exprt &size_expr= static_cast<const exprt &>(type.find(ID_size)); bv_width=size_expr; } else if(type.id()==ID_custom_floatbv) { floatbv_cnt++; const exprt &size_expr= static_cast<const exprt &>(type.find(ID_size)); const exprt &fsize_expr= static_cast<const exprt &>(type.find(ID_f)); bv_width=size_expr; fraction_width=fsize_expr; } else if(type.id()==ID_custom_fixedbv) { fixedbv_cnt++; const exprt &size_expr= static_cast<const exprt &>(type.find(ID_size)); const exprt &fsize_expr= static_cast<const exprt &>(type.find(ID_f)); bv_width=size_expr; fraction_width=fsize_expr; } else if(type.id()==ID_short) short_cnt++; else if(type.id()==ID_long) long_cnt++; else if(type.id()==ID_double) double_cnt++; else if(type.id()==ID_float) float_cnt++; else if(type.id()==ID_c_bool) c_bool_cnt++; else if(type.id()==ID_proper_bool) proper_bool_cnt++; else if(type.id()==ID_complex) complex_cnt++; else if(type.id()==ID_static) c_storage_spec.is_static=true; else if(type.id()==ID_thread_local) c_storage_spec.is_thread_local=true; else if(type.id()==ID_inline) c_storage_spec.is_inline=true; else if(type.id()==ID_extern) c_storage_spec.is_extern=true; else if(type.id()==ID_typedef) c_storage_spec.is_typedef=true; else if(type.id()==ID_register) c_storage_spec.is_register=true; else if(type.id()==ID_auto) { // ignore } else if(type.id()==ID_packed) packed=true; else if(type.id()==ID_aligned) { aligned=true; // may come with size or not if(type.find(ID_size).is_nil()) alignment=exprt(ID_default); else alignment=static_cast<const exprt &>(type.find(ID_size)); } else if(type.id()==ID_transparent_union) { c_qualifiers.is_transparent_union=true; } else if(type.id()==ID_vector) vector_size=to_vector_type(type).size(); else if(type.id()==ID_void) { // we store 'void' as 'empty' typet tmp=type; tmp.id(ID_empty); other.push_back(tmp); } else if(type.id()==ID_msc_declspec) { const exprt &as_expr= static_cast<const exprt &>(static_cast<const irept &>(type)); forall_operands(it, as_expr) { // these are symbols const irep_idt &id=it->get(ID_identifier); if(id=="thread") c_storage_spec.is_thread_local=true; else if(id=="align") { assert(it->operands().size()==1); aligned=true; alignment=it->op0(); } } } else
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); }
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"; // We increase the L2 renaming to make these non-deterministic. // We also prevent propagation of old values. const irep_idt &identifier= to_symbol_expr(code.op0()).get_identifier(); const irep_idt l1_identifier= state.rename(identifier, ns, goto_symex_statet::L1); // prevent propagation state.propagation.remove(l1_identifier); // L2 renaming unsigned new_count=state.level2.current_count(l1_identifier)+1; state.level2.rename(l1_identifier, new_count); // 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); symbol_exprt l1_lhs; l1_lhs.type()=code.op0().type(); l1_lhs.set_identifier(l1_identifier); state.rename(rhs, ns, goto_symex_statet::L1); state.value_set.assign(l1_lhs, rhs, ns); } // record the declaration symbol_exprt original_lhs=to_symbol_expr(code.op0()); symbol_exprt ssa_lhs=original_lhs; state.rename(ssa_lhs, ns); target.decl( state.guard, ssa_lhs, original_lhs, state.source); }
void value_sett::get_value_set_rec( const exprt &expr, object_mapt &dest, const std::string &suffix, const typet &original_type, const namespacet &ns) const { #if 0 std::cout << "GET_VALUE_SET_REC EXPR: " << from_expr(ns, "", expr) << "\n"; std::cout << "GET_VALUE_SET_REC SUFFIX: " << suffix << std::endl; #endif const typet &expr_type=ns.follow(expr.type()); if(expr.id()==ID_unknown || expr.id()==ID_invalid) { insert(dest, exprt(ID_unknown, original_type)); } else if(expr.id()==ID_index) { assert(expr.operands().size()==2); const typet &type=ns.follow(expr.op0().type()); assert(type.id()==ID_array || type.id()==ID_incomplete_array); get_value_set_rec(expr.op0(), dest, "[]"+suffix, original_type, ns); } else if(expr.id()==ID_member) { assert(expr.operands().size()==1); const typet &type=ns.follow(expr.op0().type()); assert(type.id()==ID_struct || type.id()==ID_union || type.id()==ID_incomplete_struct || type.id()==ID_incomplete_union); const std::string &component_name= expr.get_string(ID_component_name); get_value_set_rec(expr.op0(), dest, "."+component_name+suffix, original_type, ns); } else if(expr.id()==ID_symbol) { irep_idt identifier=to_symbol_expr(expr).get_identifier(); // is it a pointer, integer, array or struct? if(expr_type.id()==ID_pointer || expr_type.id()==ID_signedbv || expr_type.id()==ID_unsignedbv || expr_type.id()==ID_struct || expr_type.id()==ID_union || expr_type.id()==ID_array) { // look it up valuest::const_iterator v_it= values.find(id2string(identifier)+suffix); // try first component name as suffix if not yet found if(v_it==values.end() && (expr_type.id()==ID_struct || expr_type.id()==ID_union)) { const struct_union_typet &struct_union_type= to_struct_union_type(expr_type); const std::string first_component_name= struct_union_type.components().front().get_string(ID_name); v_it=values.find( id2string(identifier)+"."+first_component_name+suffix); } // not found? try without suffix if(v_it==values.end()) v_it=values.find(identifier); if(v_it!=values.end()) make_union(dest, v_it->second.object_map); else insert(dest, exprt(ID_unknown, original_type)); } else insert(dest, exprt(ID_unknown, original_type)); } else if(expr.id()==ID_if) { if(expr.operands().size()!=3) throw "if takes three operands"; get_value_set_rec(expr.op1(), dest, suffix, original_type, ns); get_value_set_rec(expr.op2(), dest, suffix, original_type, ns); } else if(expr.id()==ID_address_of) { if(expr.operands().size()!=1) throw expr.id_string()+" expected to have one operand"; get_reference_set(expr.op0(), dest, ns); } else if(expr.id()==ID_dereference) { object_mapt reference_set; get_reference_set(expr, reference_set, ns); const object_map_dt &object_map=reference_set.read(); if(object_map.begin()==object_map.end()) insert(dest, exprt(ID_unknown, original_type)); else { for(object_map_dt::const_iterator it1=object_map.begin(); it1!=object_map.end(); it1++) { const exprt &object=object_numbering[it1->first]; get_value_set_rec(object, dest, suffix, original_type, ns); } } } else if(expr.id()=="reference_to") { // old stuff, will go away object_mapt reference_set; get_reference_set(expr, reference_set, ns); const object_map_dt &object_map=reference_set.read(); if(object_map.begin()==object_map.end()) insert(dest, exprt(ID_unknown, original_type)); else { for(object_map_dt::const_iterator it=object_map.begin(); it!=object_map.end(); it++) { const exprt &object=object_numbering[it->first]; get_value_set_rec(object, dest, suffix, original_type, ns); } } } else if(expr.is_constant()) { // check if NULL if(expr.get(ID_value)==ID_NULL && expr_type.id()==ID_pointer) { insert(dest, exprt("NULL-object", expr_type.subtype()), 0); } else if(expr_type.id()==ID_unsignedbv || expr_type.id()==ID_signedbv) { // an integer constant got turned into a pointer insert(dest, exprt(ID_integer_address, unsigned_char_type())); } else insert(dest, exprt(ID_unknown, original_type)); } else if(expr.id()==ID_typecast) { if(expr.operands().size()!=1) throw "typecast takes one operand"; // let's see what gets converted to what const typet &op_type=ns.follow(expr.op0().type()); if(op_type.id()==ID_pointer) { // pointer-to-pointer -- we just ignore these get_value_set_rec(expr.op0(), dest, suffix, original_type, ns); } else if(op_type.id()==ID_unsignedbv || op_type.id()==ID_signedbv) { // integer-to-pointer if(expr.op0().is_zero()) insert(dest, exprt("NULL-object", expr_type.subtype()), 0); else { // see if we have something for the integer object_mapt tmp; get_value_set_rec(expr.op0(), tmp, suffix, original_type, ns); if(tmp.read().size()==0) { // if not, throw in integer insert(dest, exprt(ID_integer_address, unsigned_char_type())); } else if(tmp.read().size()==1 && object_numbering[tmp.read().begin()->first].id()==ID_unknown) { // if not, throw in integer insert(dest, exprt(ID_integer_address, unsigned_char_type())); } else { // use as is dest.write().insert(tmp.read().begin(), tmp.read().end()); } } } else insert(dest, exprt(ID_unknown, original_type)); } else if(expr.id()==ID_plus || expr.id()==ID_minus) { if(expr.operands().size()<2) throw expr.id_string()+" expected to have at least two operands"; object_mapt pointer_expr_set; mp_integer i; bool i_is_set=false; // special case for pointer+integer if(expr.operands().size()==2 && expr_type.id()==ID_pointer) { exprt ptr_operand; if(expr.op0().type().id()!=ID_pointer && expr.op0().is_constant()) { i_is_set=!to_integer(expr.op0(), i); ptr_operand=expr.op1(); } else { i_is_set=!to_integer(expr.op1(), i); ptr_operand=expr.op0(); } if(i_is_set) { i*=pointer_offset_size(ptr_operand.type().subtype(), ns); if(expr.id()==ID_minus) i.negate(); } get_value_set_rec( ptr_operand, pointer_expr_set, "", ptr_operand.type(), ns); } else { // we get the points-to for all operands, even integers forall_operands(it, expr) { get_value_set_rec( *it, pointer_expr_set, "", it->type(), ns); } } for(object_map_dt::const_iterator it=pointer_expr_set.read().begin(); it!=pointer_expr_set.read().end(); it++) { objectt object=it->second; // adjust by offset if(object.offset_is_zero() && i_is_set) object.offset=i; else object.offset_is_set=false; insert(dest, it->first, object); } }
exprt boolbvt::bv_get_rec( const bvt &bv, const std::vector<bool> &unknown, std::size_t offset, const typet &type) const { if(type.id()==ID_symbol) return bv_get_rec(bv, unknown, offset, ns.follow(type)); std::size_t width=boolbv_width(type); assert(bv.size()==unknown.size()); assert(bv.size()>=offset+width); if(type.id()==ID_bool) { if(!unknown[offset]) { switch(prop.l_get(bv[offset]).get_value()) { case tvt::tv_enumt::TV_FALSE: return false_exprt(); case tvt::tv_enumt::TV_TRUE: return true_exprt(); default: return false_exprt(); // default } } return nil_exprt(); } bvtypet bvtype=get_bvtype(type); if(bvtype==IS_UNKNOWN) { if(type.id()==ID_array) { const typet &subtype=type.subtype(); std::size_t sub_width=boolbv_width(subtype); if(sub_width!=0) { exprt::operandst op; op.reserve(width/sub_width); for(std::size_t new_offset=0; new_offset<width; new_offset+=sub_width) { op.push_back( bv_get_rec(bv, unknown, offset+new_offset, subtype)); } exprt dest=exprt(ID_array, type); dest.operands().swap(op); return dest; } } else if(type.id()==ID_struct_tag) { return bv_get_rec(bv, unknown, offset, ns.follow_tag(to_struct_tag_type(type))); } else if(type.id()==ID_union_tag) { return bv_get_rec(bv, unknown, offset, ns.follow_tag(to_union_tag_type(type))); } else if(type.id()==ID_struct) { const struct_typet &struct_type=to_struct_type(type); const struct_typet::componentst &components=struct_type.components(); std::size_t new_offset=0; exprt::operandst op; op.reserve(components.size()); for(struct_typet::componentst::const_iterator it=components.begin(); it!=components.end(); it++) { const typet &subtype=ns.follow(it->type()); op.push_back(nil_exprt()); std::size_t sub_width=boolbv_width(subtype); if(sub_width!=0) { op.back()=bv_get_rec(bv, unknown, offset+new_offset, subtype); new_offset+=sub_width; } } struct_exprt dest(type); dest.operands().swap(op); return dest; } else if(type.id()==ID_union) { const union_typet &union_type=to_union_type(type); const union_typet::componentst &components=union_type.components(); assert(!components.empty()); // Any idea that's better than just returning the first component? std::size_t component_nr=0; union_exprt value(union_type); value.set_component_name( components[component_nr].get_name()); const typet &subtype=components[component_nr].type(); value.op()=bv_get_rec(bv, unknown, offset, subtype); return value; } else if(type.id()==ID_vector) { const typet &subtype=ns.follow(type.subtype()); std::size_t sub_width=boolbv_width(subtype); if(sub_width!=0 && width%sub_width==0) { std::size_t size=width/sub_width; exprt value(ID_vector, type); value.operands().resize(size); for(std::size_t i=0; i<size; i++) value.operands()[i]= bv_get_rec(bv, unknown, i*sub_width, subtype); return value; } } else if(type.id()==ID_complex) { const typet &subtype=ns.follow(type.subtype()); std::size_t sub_width=boolbv_width(subtype); if(sub_width!=0 && width==sub_width*2) { exprt value(ID_complex, type); value.operands().resize(2); value.op0()=bv_get_rec(bv, unknown, 0*sub_width, subtype); value.op1()=bv_get_rec(bv, unknown, 1*sub_width, subtype); return value; } } } std::string value; for(std::size_t bit_nr=offset; bit_nr<offset+width; bit_nr++) { char ch; if(unknown[bit_nr]) ch='0'; else switch(prop.l_get(bv[bit_nr]).get_value()) { case tvt::tv_enumt::TV_FALSE: ch='0'; break; case tvt::tv_enumt::TV_TRUE: ch='1'; break; case tvt::tv_enumt::TV_UNKNOWN: ch='0'; break; default: assert(false); } value=ch+value; } switch(bvtype) { case IS_UNKNOWN: if(type.id()==ID_string) { mp_integer int_value=binary2integer(value, false); irep_idt s; if(int_value>=string_numbering.size()) s=irep_idt(); else s=string_numbering[int_value.to_long()]; return constant_exprt(s, type); } break; case IS_RANGE: { mp_integer int_value=binary2integer(value, false); mp_integer from=string2integer(type.get_string(ID_from)); constant_exprt value_expr(type); value_expr.set_value(integer2string(int_value+from)); return value_expr; } break; default: case IS_C_ENUM: constant_exprt value_expr(type); value_expr.set_value(value); return value_expr; } return nil_exprt(); }
exprt boolbvt::bv_get_unbounded_array(const exprt &expr) const { // first, try to get size const typet &type=expr.type(); const exprt &size_expr=to_array_type(type).size(); exprt size=simplify_expr(get(size_expr), ns); // no size, give up if(size.is_nil()) return nil_exprt(); // get the numeric value, unless it's infinity mp_integer size_mpint; if(size.id()!=ID_infinity) { if(to_integer(size, size_mpint)) return nil_exprt(); // simple sanity check if(size_mpint<0) return nil_exprt(); } else size_mpint=0; // search array indices typedef std::map<mp_integer, exprt> valuest; valuest values; { std::size_t number; if(arrays.get_number(expr, number)) return nil_exprt(); // get root number=arrays.find_number(number); assert(number<index_map.size()); index_mapt::const_iterator it=index_map.find(number); assert(it!=index_map.end()); const index_sett &index_set=it->second; for(index_sett::const_iterator it1= index_set.begin(); it1!=index_set.end(); it1++) { index_exprt index; index.type()=type.subtype(); index.array()=expr; index.index()=*it1; exprt value=bv_get_cache(index); exprt index_value=bv_get_cache(*it1); if(!index_value.is_nil()) { mp_integer index_mpint; if(!to_integer(index_value, index_mpint)) { if(value.is_nil()) values[index_mpint]=exprt(ID_unknown, type.subtype()); else values[index_mpint]=value; } } } } exprt result; if(size_mpint>100 || size.id()==ID_infinity) { result=exprt("array-list", type); result.type().set(ID_size, integer2string(size_mpint)); result.operands().reserve(values.size()*2); for(valuest::const_iterator it=values.begin(); it!=values.end(); it++) { exprt index=from_integer(it->first, size.type()); result.copy_to_operands(index, it->second); } } else { // set the size result=exprt(ID_array, type); result.type().set(ID_size, size); std::size_t size_int=integer2size_t(size_mpint); // allocate operands result.operands().resize(size_int); for(std::size_t i=0; i<size_int; i++) result.operands()[i]=exprt(ID_unknown); // search uninterpreted functions for(valuest::iterator it=values.begin(); it!=values.end(); it++) if(it->first>=0 && it->first<size_mpint) result.operands()[integer2size_t(it->first)].swap(it->second); } return result; }
exprt convert_float_literal(const std::string &src) { mp_integer significand; mp_integer exponent; bool is_float, is_long, is_imaginary; bool is_decimal, is_float80, is_float128; // GCC extensions unsigned base; parse_float(src, significand, exponent, base, is_float, is_long, is_imaginary, is_decimal, is_float80, is_float128); exprt result=exprt(ID_constant); result.set(ID_C_cformat, src); // In ANSI-C, float literals are double by default, // unless marked with 'f'. // All of these can be complex as well. // This can be overriden with // config.ansi_c.single_precision_constant. if(is_float) result.type()=float_type(); else if(is_long) result.type()=long_double_type(); else if(is_float80) { result.type()=ieee_float_spect(64, 15).to_type(); result.type().set(ID_C_c_type, ID_long_double); } else if(is_float128) { result.type()=ieee_float_spect::quadruple_precision().to_type(); result.type().set(ID_C_c_type, ID_gcc_float128); } else { // default if(config.ansi_c.single_precision_constant) result.type()=float_type(); // default else result.type()=double_type(); // default } if(is_decimal) { // TODO - should set ID_gcc_decimal32/ID_gcc_decimal64/ID_gcc_decimal128, // but these aren't handled anywhere } if(config.ansi_c.use_fixed_for_float) { unsigned width=result.type().get_int(ID_width); unsigned fraction_bits; const irep_idt integer_bits=result.type().get(ID_integer_bits); assert(width!=0); if(integer_bits==irep_idt()) fraction_bits=width/2; // default else fraction_bits=width-safe_string2int(id2string(integer_bits)); mp_integer factor=mp_integer(1)<<fraction_bits; mp_integer value=significand*factor; if(value!=0) { if(exponent<0) value/=power(base, -exponent); else { value*=power(base, exponent); if(value>=power(2, width-1)) { // saturate: use "biggest value" value=power(2, width-1)-1; } else if(value<=-power(2, width-1)-1) { // saturate: use "smallest value" value=-power(2, width-1); } } } result.set(ID_value, integer2binary(value, width)); } else { ieee_floatt a; a.spec=to_floatbv_type(result.type()); if(base==10) a.from_base10(significand, exponent); else if(base==2) // hex a.build(significand, exponent); else assert(false); result.set(ID_value, integer2binary(a.pack(), a.spec.width())); } if(is_imaginary) { complex_typet complex_type; complex_type.subtype()=result.type(); exprt complex_expr(ID_complex, complex_type); complex_expr.operands().resize(2); complex_expr.op0()=gen_zero(result.type()); complex_expr.op1()=result; return complex_expr; } return result; }
void jsil_typecheckt::typecheck_function_call( code_function_callt &call) { if(call.operands().size()!=3) throw "function call expected to have three operands"; exprt &lhs=call.lhs(); typecheck_expr(lhs); exprt &f=call.function(); typecheck_expr(f); for(auto &arg : call.arguments()) typecheck_expr(arg); // Look for a function declaration symbol in the symbol table if(f.id()==ID_symbol) { const irep_idt &id=to_symbol_expr(f).get_identifier(); if(symbol_table.has_symbol(id)) { symbolt &s=symbol_table.lookup(id); if(s.type.id()==ID_code) { code_typet &codet=to_code_type(s.type); for(std::size_t i=0; i<codet.parameters().size(); i++) { if(i>=call.arguments().size()) break; const typet ¶m_type=codet.parameters()[i].type(); if(!param_type.id().empty() && param_type.is_not_nil()) { // check argument's type if parameter's type is given make_type_compatible(call.arguments()[i], param_type, true); } } // if there are too few arguments, add undefined if(codet.parameters().size()>call.arguments().size()) { for(std::size_t i=call.arguments().size(); i<codet.parameters().size(); ++i) call.arguments().push_back( exprt("undefined", jsil_undefined_type())); } // if there are too many arguments, remove while(codet.parameters().size()<call.arguments().size()) call.arguments().pop_back(); // check return type if exists if(!codet.return_type().id().empty() && codet.return_type().is_not_nil()) make_type_compatible(lhs, codet.return_type(), true); else make_type_compatible(lhs, jsil_any_type(), true); } else { // TODO: a symbol can be a variable evaluating to a string // which corresponds to a function identifier make_type_compatible(lhs, jsil_any_type(), true); } } else { // Should be function, declaration not found yet symbolt new_symbol; new_symbol.name=id; new_symbol.type=code_typet(); new_symbol.mode="jsil"; new_symbol.is_type=false; new_symbol.value=exprt("no-body-just-yet"); make_type_compatible(lhs, jsil_any_type(), true); if(symbol_table.add(new_symbol)) throw "failed to add expression symbol to symbol table"; } } else { // TODO: this might be a string literal // which corresponds to a function identifier make_type_compatible(lhs, jsil_any_type(), true); } }
void predicate_image_satqe( message_handlert &message_handler, const std::vector<exprt> &deref_curr_predicates, const std::vector<exprt> &deref_next_predicates, const std::list<exprt> &constraints, symex_target_equationt &equation, const namespacet &ns, abstract_transition_relationt & abstract_transition_relation) { const std::set<unsigned> &from_predicates= abstract_transition_relation.from_predicates; const std::set<unsigned> &to_predicates= abstract_transition_relation.to_predicates; assert(to_predicates.size()!=0); // create SAT solver object satqe_satcheckt satqe; bv_pointerst solver(satqe); solver.unbounded_array=boolbvt::U_ALL; solver.set_message_handler(message_handler); // turn equation into CNF equation.convert(solver); for(std::set<unsigned>::const_iterator it=from_predicates.begin(); it!=from_predicates.end(); it++) { unsigned i=*it; literalt li=make_pos(ns, solver, deref_curr_predicates[i]); satqe.quantify(li); } for(std::set<unsigned>::const_iterator it=to_predicates.begin(); it!=to_predicates.end(); it++) { unsigned i=*it; literalt lo=make_pos(ns, solver, deref_next_predicates[i]); satqe.quantify(lo); } // we want cubes cube_sett cube_set; satqe.set_cube_set(cube_set); // solve it switch(solver.dec_solve()) { case decision_proceduret::D_UNSATISFIABLE: // OK, this is what we expect break; default: throw "unexpected result from satqe.solve()"; } message_handler.print(9, "Generated "+ i2string(cube_set.no_insertions())+" cube(s)"); #if 0 std::cout << cube_set; #endif exprt constraint_cubes_disj = true_exprt(); // convert the cubes into constraints for(cubest::star_mapt::const_iterator it=cube_set.star_map.begin(); it!=cube_set.star_map.end(); it++) { for(cubest::bitssett::const_iterator it2=it->second.begin(); it2!=it->second.end(); it2++) { exprt constraint_cube_conj; unsigned bit=0; unsigned i=0; /* Assume it->first[i] is true iff the i-th predicate is in the cube. Assume predicates are stored in it->first in the order of from_predicates followed by to_predicates. Scan it->first and from/to_predicates in parallel to get the cube. */ for(std::set<unsigned>::const_iterator it3=from_predicates.begin(); it3!=from_predicates.end(); it3++) { unsigned id=*it3; if(!it->first[i]) { constraint_cube_conj.operands().push_back(exprt()); exprt &e=constraint_cube_conj.operands().back(); e=exprt(ID_predicate_symbol, typet(ID_bool)); e.set(ID_identifier, id); if(!(*it2)[bit]) e.make_not(); bit++; #if 0 std::cout << "C: " << from_expr(ns, "", e) << std::endl; #endif } i++; } for(std::set<unsigned>::const_iterator it3=to_predicates.begin(); it3!=to_predicates.end(); it3++) { unsigned id=*it3; if(!it->first[i]) { constraint_cube_conj.operands().push_back(exprt()); exprt &e=constraint_cube_conj.operands().back(); e=exprt(ID_predicate_next_symbol, typet(ID_bool)); e.set(ID_identifier, id); if(!(*it2)[bit]) e.make_not(); bit++; #if 0 std::cout << "C: " << from_expr(ns, "", e) << std::endl; #endif } i++; } assert(i==it->first.size()); /* Convert the cube into a conjunct. */ gen_and(constraint_cube_conj); /* Add the conjunct in disjunction to previous cubes. */ if(constraint_cubes_disj.is_true()) constraint_cubes_disj=constraint_cube_conj; else constraint_cubes_disj=gen_or( constraint_cubes_disj, constraint_cube_conj); } } /* Add the cubes to the contraints of the abstract transition relation. Warning: we may want to remove old constrains. */ abstract_transition_relation.constraints.push_back(constraint_cubes_disj); }