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; }
std::string from_type(const typet &type) { symbol_tablet symbol_table; return from_type(namespacet(symbol_table), "", type); }
void convert( const namespacet &ns, const goto_tracet &goto_trace, jsont &dest) { json_arrayt &dest_array=dest.make_array(); source_locationt previous_source_location; for(const auto &step : goto_trace.steps) { const source_locationt &source_location=step.pc->source_location; jsont json_location; if(source_location.is_not_nil() && source_location.get_file()!="") json_location=json(source_location); else json_location=json_nullt(); switch(step.type) { case goto_trace_stept::typet::ASSERT: if(!step.cond_value) { irep_idt property_id; if(step.pc->is_assert()) property_id=source_location.get_property_id(); else if(step.pc->is_goto()) // unwinding, we suspect { property_id= id2string(step.pc->source_location.get_function())+ ".unwind."+std::to_string(step.pc->loop_number); } json_objectt &json_failure=dest_array.push_back().make_object(); json_failure["stepType"]=json_stringt("failure"); json_failure["hidden"]=jsont::json_boolean(step.hidden); json_failure["thread"]=json_numbert(std::to_string(step.thread_nr)); json_failure["reason"]=json_stringt(id2string(step.comment)); json_failure["property"]=json_stringt(id2string(property_id)); if(!json_location.is_null()) json_failure["sourceLocation"]=json_location; } break; case goto_trace_stept::typet::ASSIGNMENT: case goto_trace_stept::typet::DECL: { irep_idt identifier=step.lhs_object.get_identifier(); json_objectt &json_assignment=dest_array.push_back().make_object(); json_assignment["stepType"]=json_stringt("assignment"); if(!json_location.is_null()) json_assignment["sourceLocation"]=json_location; std::string value_string, binary_string, type_string, full_lhs_string; json_objectt full_lhs_value; if(step.full_lhs.is_not_nil()) full_lhs_string=from_expr(ns, identifier, step.full_lhs); #if 0 if(it.full_lhs_value.is_not_nil()) full_lhs_value_string=from_expr(ns, identifier, it.full_lhs_value); #endif if(step.full_lhs_value.is_not_nil()) full_lhs_value = json(step.full_lhs_value, ns); const symbolt *symbol; irep_idt base_name, display_name; if(!ns.lookup(identifier, symbol)) { base_name=symbol->base_name; display_name=symbol->display_name(); if(type_string=="") type_string=from_type(ns, identifier, symbol->type); json_assignment["mode"]=json_stringt(id2string(symbol->mode)); } json_assignment["value"]=full_lhs_value; json_assignment["lhs"]=json_stringt(full_lhs_string); json_assignment["hidden"]=jsont::json_boolean(step.hidden); json_assignment["thread"]=json_numbert(std::to_string(step.thread_nr)); json_assignment["assignmentType"]= json_stringt( step.assignment_type== goto_trace_stept::assignment_typet::ACTUAL_PARAMETER? "actual-parameter": "variable"); } break; case goto_trace_stept::typet::OUTPUT: { json_objectt &json_output=dest_array.push_back().make_object(); json_output["stepType"]=json_stringt("output"); json_output["hidden"]=jsont::json_boolean(step.hidden); json_output["thread"]=json_numbert(std::to_string(step.thread_nr)); json_output["outputID"]=json_stringt(id2string(step.io_id)); json_arrayt &json_values=json_output["values"].make_array(); for(const auto &arg : step.io_args) { if(arg.is_nil()) json_values.push_back(json_stringt("")); else json_values.push_back(json(arg, ns)); } if(!json_location.is_null()) json_output["sourceLocation"]=json_location; } break; case goto_trace_stept::typet::INPUT: { json_objectt &json_input=dest_array.push_back().make_object(); json_input["stepType"]=json_stringt("input"); json_input["hidden"]=jsont::json_boolean(step.hidden); json_input["thread"]=json_numbert(std::to_string(step.thread_nr)); json_input["inputID"]=json_stringt(id2string(step.io_id)); json_arrayt &json_values=json_input["values"].make_array(); for(const auto &arg : step.io_args) { if(arg.is_nil()) json_values.push_back(json_stringt("")); else json_values.push_back(json(arg, ns)); } if(!json_location.is_null()) json_input["sourceLocation"]=json_location; } break; case goto_trace_stept::typet::FUNCTION_CALL: case goto_trace_stept::typet::FUNCTION_RETURN: { std::string tag= (step.type==goto_trace_stept::typet::FUNCTION_CALL)? "function-call":"function-return"; json_objectt &json_call_return=dest_array.push_back().make_object(); json_call_return["stepType"]=json_stringt(tag); json_call_return["hidden"]=jsont::json_boolean(step.hidden); json_call_return["thread"]=json_numbert(std::to_string(step.thread_nr)); const symbolt &symbol=ns.lookup(step.identifier); json_objectt &json_function=json_call_return["function"].make_object(); json_function["displayName"]= json_stringt(id2string(symbol.display_name())); json_function["identifier"]=json_stringt(id2string(step.identifier)); json_function["sourceLocation"]=json(symbol.location); if(!json_location.is_null()) json_call_return["sourceLocation"]=json_location; } break; default: if(source_location!=previous_source_location) { // just the source location if(!json_location.is_null()) { json_objectt &json_location_only=dest_array.push_back().make_object(); json_location_only["stepType"]=json_stringt("location-only"); json_location_only["hidden"]=jsont::json_boolean(step.hidden); json_location_only["thread"]= json_numbert(std::to_string(step.thread_nr)); json_location_only["sourceLocation"]=json_location; } } } if(source_location.is_not_nil() && source_location.get_file()!="") previous_source_location=source_location; } }
/****************************************************************************** * TranslateColors [MSCMS.@] * * Perform color translation. * * PARAMS * transform [I] Handle to a color transform. * input [I] Array of input colors. * number [I] Number of colors to translate. * input_type [I] Input color format. * output [O] Array of output colors. * output_type [I] Output color format. * * RETURNS * Success: TRUE * Failure: FALSE */ BOOL WINAPI TranslateColors( HTRANSFORM handle, PCOLOR in, DWORD count, COLORTYPE input_type, PCOLOR out, COLORTYPE output_type ) { #ifdef HAVE_LCMS2 BOOL ret = TRUE; struct transform *transform = grab_transform( handle ); cmsHTRANSFORM xfrm; unsigned int i; TRACE( "( %p, %p, %d, %d, %p, %d )\n", handle, in, count, input_type, out, output_type ); if (!transform) return FALSE; xfrm = transform->cmstransform; if (!cmsChangeBuffersFormat( xfrm, from_type(input_type), from_type(output_type) )) return FALSE; switch (input_type) { case COLOR_RGB: { switch (output_type) { case COLOR_RGB: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].rgb, &out[i].rgb, 1 ); goto done; case COLOR_Lab: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].rgb, &out[i].Lab, 1 ); goto done; case COLOR_GRAY: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].rgb, &out[i].gray, 1 ); goto done; case COLOR_CMYK: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].rgb, &out[i].cmyk, 1 ); goto done; case COLOR_XYZ: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].rgb, &out[i].XYZ, 1 ); goto done; default: FIXME("unhandled input/output pair: %d/%d\n", input_type, output_type); ret = FALSE; break; } break; } case COLOR_Lab: { switch (output_type) { case COLOR_RGB: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].Lab, &out[i].rgb, 1 ); goto done; case COLOR_Lab: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].Lab, &out[i].Lab, 1 ); goto done; case COLOR_GRAY: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].Lab, &out[i].gray, 1 ); goto done; case COLOR_CMYK: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].Lab, &out[i].cmyk, 1 ); goto done; case COLOR_XYZ: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].Lab, &out[i].XYZ, 1 ); goto done; default: FIXME("unhandled input/output pair: %d/%d\n", input_type, output_type); ret = FALSE; break; } break; } case COLOR_GRAY: { switch (output_type) { case COLOR_RGB: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].gray, &out[i].rgb, 1 ); goto done; case COLOR_Lab: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].gray, &out[i].Lab, 1 ); goto done; case COLOR_GRAY: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].gray, &out[i].gray, 1 ); goto done; case COLOR_CMYK: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].gray, &out[i].cmyk, 1 ); goto done; case COLOR_XYZ: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].gray, &out[i].XYZ, 1 ); goto done; default: FIXME("unhandled input/output pair: %d/%d\n", input_type, output_type); ret = FALSE; break; } break; } case COLOR_CMYK: { switch (output_type) { case COLOR_RGB: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].cmyk, &out[i].rgb, 1 ); goto done; case COLOR_Lab: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].cmyk, &out[i].Lab, 1 ); goto done; case COLOR_GRAY: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].cmyk, &out[i].gray, 1 ); goto done; case COLOR_CMYK: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].cmyk, &out[i].cmyk, 1 ); goto done; case COLOR_XYZ: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].cmyk, &out[i].XYZ, 1 ); goto done; default: FIXME("unhandled input/output pair: %d/%d\n", input_type, output_type); ret = FALSE; break; } break; } case COLOR_XYZ: { switch (output_type) { case COLOR_RGB: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].XYZ, &out[i].rgb, 1 ); goto done; case COLOR_Lab: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].XYZ, &out[i].Lab, 1 ); goto done; case COLOR_GRAY: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].XYZ, &out[i].gray, 1 ); goto done; case COLOR_CMYK: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].XYZ, &out[i].cmyk, 1 ); goto done; case COLOR_XYZ: for (i = 0; i < count; i++) cmsDoTransform( xfrm, &in[i].XYZ, &out[i].XYZ, 1 ); goto done; default: FIXME("unhandled input/output pair: %d/%d\n", input_type, output_type); ret = FALSE; break; } break; } default: FIXME("unhandled input/output pair: %d/%d\n", input_type, output_type); ret = FALSE; break; } done: release_transform( transform ); return ret; #else /* HAVE_LCMS2 */ return FALSE; #endif /* HAVE_LCMS2 */ }
void value_sett::output( const namespacet &ns, std::ostream &out) const { for(valuest::const_iterator v_it=values.begin(); v_it!=values.end(); v_it++) { irep_idt identifier, display_name; const entryt &e=v_it->second; if(has_prefix(id2string(e.identifier), "value_set::dynamic_object")) { display_name=id2string(e.identifier)+e.suffix; identifier=""; } else if(e.identifier=="value_set::return_value") { display_name="RETURN_VALUE"+e.suffix; identifier=""; } else { #if 0 const symbolt &symbol=ns.lookup(e.identifier); display_name=symbol.display_name()+e.suffix; identifier=symbol.name; #else identifier=id2string(e.identifier); display_name=id2string(identifier)+e.suffix; #endif } out << display_name; out << " = { "; const object_map_dt &object_map=e.object_map.read(); std::size_t width=0; for(object_map_dt::const_iterator o_it=object_map.begin(); o_it!=object_map.end(); o_it++) { const exprt &o=object_numbering[o_it->first]; std::string result; if(o.id()==ID_invalid || o.id()==ID_unknown) result=from_expr(ns, identifier, o); else { result="<"+from_expr(ns, identifier, o)+", "; if(o_it->second.offset_is_set) result+=integer2string(o_it->second.offset)+""; else result+='*'; if(o.type().is_nil()) result+=", ?"; else result+=", "+from_type(ns, identifier, o.type()); result+='>'; } out << result; width+=result.size(); object_map_dt::const_iterator next(o_it); next++; if(next!=object_map.end()) { out << ", "; if(width>=40) out << "\n "; } } out << " } " << std::endl; } }
void goto_inlinet::parameter_assignments( const locationt &location, const code_typet &code_type, const exprt::operandst &arguments, goto_programt &dest) { // iterates over the operands exprt::operandst::const_iterator it1=arguments.begin(); goto_programt::local_variablest local_variables; const code_typet::argumentst &argument_types= code_type.arguments(); // iterates over the types of the arguments for(code_typet::argumentst::const_iterator it2=argument_types.begin(); it2!=argument_types.end(); it2++) { // if you run out of actual arguments there was a mismatch if(it1==arguments.end()) { err_location(location); throw "function call: not enough arguments"; } const exprt &argument=static_cast<const exprt &>(*it2); // this is the type the n-th argument should be const typet &arg_type=ns.follow(argument.type()); const irep_idt &identifier=argument.cmt_identifier(); if(identifier=="") { err_location(location); throw "no identifier for function argument"; } { const symbolt &symbol=ns.lookup(identifier); goto_programt::targett decl=dest.add_instruction(); decl->make_other(); exprt tmp = code_declt(symbol_expr(symbol)); migrate_expr(tmp, decl->code); decl->location=location; decl->function=location.get_function(); decl->local_variables=local_variables; } local_variables.insert(identifier); // nil means "don't assign" if(it1->is_nil()) { } else { // this is the actual parameter exprt actual(*it1); // it should be the same exact type type2tc arg_type_2, actual_type_2; migrate_type(arg_type, arg_type_2); migrate_type(actual.type(), actual_type_2); if (!base_type_eq(arg_type_2, actual_type_2, ns)) { const typet &f_argtype = ns.follow(arg_type); const typet &f_acttype = ns.follow(actual.type()); // we are willing to do some conversion if((f_argtype.id()=="pointer" && f_acttype.id()=="pointer") || (f_argtype.is_array() && f_acttype.id()=="pointer" && f_argtype.subtype()==f_acttype.subtype())) { actual.make_typecast(arg_type); } else if((f_argtype.id()=="signedbv" || f_argtype.id()=="unsignedbv" || f_argtype.is_bool()) && (f_acttype.id()=="signedbv" || f_acttype.id()=="unsignedbv" || f_acttype.is_bool())) { actual.make_typecast(arg_type); } else { err_location(location); str << "function call: argument `" << identifier << "' type mismatch: got " << from_type(ns, identifier, it1->type()) << ", expected " << from_type(ns, identifier, arg_type); throw 0; } } // adds an assignment of the actual parameter to the formal parameter code_assignt assignment(symbol_exprt(identifier, arg_type), actual); assignment.location()=location; dest.add_instruction(ASSIGN); dest.instructions.back().location=location; migrate_expr(assignment, dest.instructions.back().code); dest.instructions.back().local_variables=local_variables; dest.instructions.back().function=location.get_function(); } it1++; } if(it1!=arguments.end()) { // too many arguments -- we just ignore that, no harm done } }
value_set_dereferencet::valuet value_set_dereferencet::build_reference_to( const exprt &what, const modet mode, const exprt &pointer_expr, const guardt &guard) { const typet &dereference_type= ns.follow(pointer_expr.type()).subtype(); if(what.id()==ID_unknown || what.id()==ID_invalid) { invalid_pointer(pointer_expr, guard); return valuet(); } if(what.id()!=ID_object_descriptor) throw "unknown points-to: "+what.id_string(); const object_descriptor_exprt &o=to_object_descriptor_expr(what); const exprt &root_object=o.root_object(); const exprt &object=o.object(); #if 0 std::cout << "O: " << from_expr(ns, "", root_object) << '\n'; #endif valuet result; if(root_object.id()=="NULL-object") { if(options.get_bool_option("pointer-check")) { guardt tmp_guard(guard); if(o.offset().is_zero()) { tmp_guard.add(null_pointer(pointer_expr)); dereference_callback.dereference_failure( "pointer dereference", "NULL pointer", tmp_guard); } else { tmp_guard.add(null_object(pointer_expr)); dereference_callback.dereference_failure( "pointer dereference", "NULL plus offset pointer", tmp_guard); } } } else if(root_object.id()==ID_dynamic_object) { // const dynamic_object_exprt &dynamic_object= // to_dynamic_object_expr(root_object); // the object produced by malloc exprt malloc_object= ns.lookup(CPROVER_PREFIX "malloc_object").symbol_expr(); exprt is_malloc_object=same_object(pointer_expr, malloc_object); // constraint that it actually is a dynamic object exprt dynamic_object_expr(ID_dynamic_object, bool_typet()); dynamic_object_expr.copy_to_operands(pointer_expr); // this is also our guard result.pointer_guard=dynamic_object_expr; // can't remove here, turn into *p result.value=dereference_exprt(pointer_expr, dereference_type); if(options.get_bool_option("pointer-check")) { // if(!dynamic_object.valid().is_true()) { // check if it is still alive guardt tmp_guard(guard); tmp_guard.add(deallocated(pointer_expr, ns)); dereference_callback.dereference_failure( "pointer dereference", "dynamic object deallocated", tmp_guard); } if(options.get_bool_option("bounds-check")) { if(!o.offset().is_zero()) { // check lower bound guardt tmp_guard(guard); tmp_guard.add(is_malloc_object); tmp_guard.add( dynamic_object_lower_bound( pointer_expr, ns, nil_exprt())); dereference_callback.dereference_failure( "pointer dereference", "dynamic object lower bound", tmp_guard); } { // check upper bound // we check SAME_OBJECT(__CPROVER_malloc_object, p) && // POINTER_OFFSET(p)+size>__CPROVER_malloc_size guardt tmp_guard(guard); tmp_guard.add(is_malloc_object); tmp_guard.add( dynamic_object_upper_bound( pointer_expr, dereference_type, ns, size_of_expr(dereference_type, ns))); dereference_callback.dereference_failure( "pointer dereference", "dynamic object upper bound", tmp_guard); } } } } else if(root_object.id()==ID_integer_address) { // This is stuff like *((char *)5). // This is turned into an access to __CPROVER_memory[...]. if(language_mode==ID_java) { result.value=nil_exprt(); return result; } const symbolt &memory_symbol=ns.lookup(CPROVER_PREFIX "memory"); exprt symbol_expr=symbol_exprt(memory_symbol.name, memory_symbol.type); if(base_type_eq( ns.follow(memory_symbol.type).subtype(), dereference_type, ns)) { // Types match already, what a coincidence! // We can use an index expression. exprt index_expr=index_exprt(symbol_expr, pointer_offset(pointer_expr)); index_expr.type()=ns.follow(memory_symbol.type).subtype(); result.value=index_expr; } else if(dereference_type_compare( ns.follow(memory_symbol.type).subtype(), dereference_type)) { exprt index_expr=index_exprt(symbol_expr, pointer_offset(pointer_expr)); index_expr.type()=ns.follow(memory_symbol.type).subtype(); result.value=typecast_exprt(index_expr, dereference_type); } else { // We need to use byte_extract. // Won't do this without a commitment to an endianness. if(config.ansi_c.endianness==configt::ansi_ct::endiannesst::NO_ENDIANNESS) { } else { exprt byte_extract(byte_extract_id(), dereference_type); byte_extract.copy_to_operands( symbol_expr, pointer_offset(pointer_expr)); result.value=byte_extract; } } } else { // something generic -- really has to be a symbol address_of_exprt object_pointer(object); if(o.offset().is_zero()) { equal_exprt equality(pointer_expr, object_pointer); if(ns.follow(equality.lhs().type())!=ns.follow(equality.rhs().type())) equality.lhs().make_typecast(equality.rhs().type()); result.pointer_guard=equality; } else { result.pointer_guard=same_object(pointer_expr, object_pointer); } guardt tmp_guard(guard); tmp_guard.add(result.pointer_guard); valid_check(object, tmp_guard, mode); const typet &object_type=ns.follow(object.type()); const exprt &root_object=o.root_object(); const typet &root_object_type=ns.follow(root_object.type()); exprt root_object_subexpression=root_object; if(dereference_type_compare(object_type, dereference_type) && o.offset().is_zero()) { // The simplest case: types match, and offset is zero! // This is great, we are almost done. result.value=object; if(object_type!=ns.follow(dereference_type)) result.value.make_typecast(dereference_type); } else if(root_object_type.id()==ID_array && dereference_type_compare( root_object_type.subtype(), dereference_type)) { // We have an array with a subtype that matches // the dereferencing type. // We will require well-alignedness! exprt offset; // this should work as the object is essentially the root object if(o.offset().is_constant()) offset=o.offset(); else offset=pointer_offset(pointer_expr); exprt adjusted_offset; // are we doing a byte? mp_integer element_size= dereference_type.id()==ID_empty? pointer_offset_size(char_type(), ns): pointer_offset_size(dereference_type, ns); if(element_size==1) { // no need to adjust offset adjusted_offset=offset; } else if(element_size<=0) { throw "unknown or invalid type size of:\n"+dereference_type.pretty(); } else { exprt element_size_expr= from_integer(element_size, offset.type()); adjusted_offset=binary_exprt( offset, ID_div, element_size_expr, offset.type()); // TODO: need to assert well-alignedness } index_exprt index_expr= index_exprt(root_object, adjusted_offset, root_object_type.subtype()); bounds_check(index_expr, tmp_guard); result.value=index_expr; if(ns.follow(result.value.type())!=ns.follow(dereference_type)) result.value.make_typecast(dereference_type); } else if(get_subexpression_at_offset( root_object_subexpression, o.offset(), dereference_type, ns)) { // Successfully found a member, array index, or combination thereof // that matches the desired type and offset: result.value=root_object_subexpression; } else { // we extract something from the root object result.value=o.root_object(); // this is relative to the root object const exprt offset=pointer_offset(pointer_expr); if(memory_model(result.value, dereference_type, tmp_guard, offset)) { // ok, done } else { if(options.get_bool_option("pointer-check")) { std::string msg="memory model not applicable (got `"; msg+=from_type(ns, "", result.value.type()); msg+="', expected `"; msg+=from_type(ns, "", dereference_type); msg+="')"; dereference_callback.dereference_failure( "pointer dereference", msg, tmp_guard); } return valuet(); // give up, no way that this is ok } } } return result; }
goto_program_coverage_recordt::goto_program_coverage_recordt( const namespacet &ns, goto_functionst::function_mapt::const_iterator gf_it, const symex_coveraget::coveraget &coverage): coverage_recordt("method") { assert(gf_it->second.body_available()); // identify the file name, inlined functions aren't properly // accounted for goto_programt::const_targett end_function= --gf_it->second.body.instructions.end(); assert(end_function->is_end_function()); file_name=end_function->source_location.get_file(); assert(!file_name.empty()); // compute the maximum coverage of individual source-code lines coverage_lines_mapt coverage_lines_map; compute_coverage_lines( gf_it->second.body, file_name, coverage, coverage_lines_map); // <method name="foo" signature="int(int)" line-rate="1.0" branch-rate="1.0"> // <lines> // <line number="23" hits="1" branch="false"/> // <line number="24" hits="1" branch="false"/> // <line number="25" hits="1" branch="false"/> // <line number="26" hits="1" branch="false"/> // <line number="27" hits="1" branch="false"/> // <line number="28" hits="1" branch="false"/> // <line number="29" hits="1" branch="false"/> // <line number="30" hits="1" branch="false"/> // </lines> // </method> xml.set_attribute("name", id2string(gf_it->first)); code_typet sig_type= original_return_type(ns.get_symbol_table(), gf_it->first); if(sig_type.is_nil()) sig_type=gf_it->second.type; xml.set_attribute("signature", from_type(ns, gf_it->first, sig_type)); xml.set_attribute("line-rate", rate_detailed(lines_covered, lines_total)); xml.set_attribute("branch-rate", rate(branches_covered, branches_total)); xmlt &lines=xml.new_element("lines"); for(const auto &cov_line : coverage_lines_map) { xmlt &line=lines.new_element("line"); line.set_attribute("number", std::to_string(cov_line.first)); line.set_attribute("hits", std::to_string(cov_line.second.hits)); if(cov_line.second.conditions.empty()) line.set_attribute("branch", "false"); else { line.set_attribute("branch", "true"); xmlt &conditions=line.new_element("conditions"); std::size_t number=0, total_taken=0; for(const auto &c : cov_line.second.conditions) { // <condition number="0" type="jump" coverage="50%"/> xmlt &condition=conditions.new_element("condition"); condition.set_attribute("number", std::to_string(number++)); condition.set_attribute("type", "jump"); unsigned taken=c.second.false_taken+c.second.true_taken; total_taken+=taken; condition.set_attribute("coverage", rate(taken, 2, true)); } line.set_attribute( "condition-coverage", rate_detailed(total_taken, number*2, true)); } } }
void goto_inlinet::parameter_assignments( const source_locationt &source_location, const irep_idt &function_name, const code_typet &code_type, const exprt::operandst &arguments, goto_programt &dest) { // iterates over the operands exprt::operandst::const_iterator it1=arguments.begin(); const code_typet::parameterst ¶meter_types= code_type.parameters(); // iterates over the types of the parameters for(code_typet::parameterst::const_iterator it2=parameter_types.begin(); it2!=parameter_types.end(); it2++) { const code_typet::parametert ¶meter=*it2; // this is the type the n-th argument should be const typet &par_type=ns.follow(parameter.type()); const irep_idt &identifier=parameter.get_identifier(); if(identifier==irep_idt()) { error().source_location=source_location; error() << "no identifier for function parameter" << eom; throw 0; } { const symbolt &symbol=ns.lookup(identifier); goto_programt::targett decl=dest.add_instruction(); decl->make_decl(); decl->code=code_declt(symbol.symbol_expr()); decl->code.add_source_location()=source_location; decl->source_location=source_location; decl->function=function_name; } // this is the actual parameter exprt actual; // if you run out of actual arguments there was a mismatch if(it1==arguments.end()) { warning().source_location=source_location; warning() << "call to `" << function_name << "': " << "not enough arguments, " << "inserting non-deterministic value" << eom; actual=side_effect_expr_nondett(par_type); } else actual=*it1; // nil means "don't assign" if(actual.is_nil()) { } else { // it should be the same exact type as the parameter, // subject to some exceptions if(!base_type_eq(par_type, actual.type(), ns)) { const typet &f_partype = ns.follow(par_type); const typet &f_acttype = ns.follow(actual.type()); // we are willing to do some conversion if((f_partype.id()==ID_pointer && f_acttype.id()==ID_pointer) || (f_partype.id()==ID_pointer && f_acttype.id()==ID_array && f_partype.subtype()==f_acttype.subtype())) { actual.make_typecast(par_type); } else if((f_partype.id()==ID_signedbv || f_partype.id()==ID_unsignedbv || f_partype.id()==ID_bool) && (f_acttype.id()==ID_signedbv || f_acttype.id()==ID_unsignedbv || f_acttype.id()==ID_bool)) { actual.make_typecast(par_type); } else { error().source_location=actual.find_source_location(); error() << "function call: argument `" << identifier << "' type mismatch: argument is `" // << from_type(ns, identifier, actual.type()) << actual.type().pretty() << "', parameter is `" << from_type(ns, identifier, par_type) << "'" << eom; throw 0; } } // adds an assignment of the actual parameter to the formal parameter code_assignt assignment(symbol_exprt(identifier, par_type), actual); assignment.add_source_location()=source_location; dest.add_instruction(ASSIGN); dest.instructions.back().source_location=source_location; dest.instructions.back().code.swap(assignment); dest.instructions.back().function=function_name; } if(it1!=arguments.end()) ++it1; } if(it1!=arguments.end()) { // too many arguments -- we just ignore that, no harm done } }
void convert( const namespacet &ns, const goto_tracet &goto_trace, xmlt &dest) { dest=xmlt("goto_trace"); source_locationt previous_source_location; for(const auto & it : goto_trace.steps) { const source_locationt &source_location=it.pc->source_location; xmlt xml_location; if(source_location.is_not_nil() && source_location.get_file()!="") xml_location=xml(source_location); switch(it.type) { case goto_trace_stept::ASSERT: if(!it.cond_value) { irep_idt property_id; if(it.pc->is_assert()) property_id=source_location.get_property_id(); else if(it.pc->is_goto()) // unwinding, we suspect { property_id= id2string(it.pc->source_location.get_function())+".unwind."+ i2string(it.pc->loop_number); } xmlt &xml_failure=dest.new_element("failure"); xml_failure.set_attribute_bool("hidden", it.hidden); xml_failure.set_attribute("thread", i2string(it.thread_nr)); xml_failure.set_attribute("step_nr", i2string(it.step_nr)); xml_failure.set_attribute("reason", id2string(it.comment)); xml_failure.set_attribute("property", id2string(property_id)); if(xml_location.name!="") xml_failure.new_element().swap(xml_location); } break; case goto_trace_stept::ASSIGNMENT: case goto_trace_stept::DECL: { irep_idt identifier=it.lhs_object.get_identifier(); xmlt &xml_assignment=dest.new_element("assignment"); if(xml_location.name!="") xml_assignment.new_element().swap(xml_location); std::string value_string, binary_string, type_string, full_lhs_string, full_lhs_value_string; if(it.lhs_object_value.is_not_nil()) value_string=from_expr(ns, identifier, it.lhs_object_value); if(it.full_lhs.is_not_nil()) full_lhs_string=from_expr(ns, identifier, it.full_lhs); if(it.full_lhs_value.is_not_nil()) full_lhs_value_string=from_expr(ns, identifier, it.full_lhs_value); if(it.lhs_object_value.type().is_not_nil()) type_string=from_type(ns, identifier, it.lhs_object_value.type()); const symbolt *symbol; irep_idt base_name, display_name; if(!ns.lookup(identifier, symbol)) { base_name=symbol->base_name; display_name=symbol->display_name(); if(type_string=="") type_string=from_type(ns, identifier, symbol->type); xml_assignment.set_attribute("mode", id2string(symbol->mode)); } xml_assignment.new_element("type").data=type_string; xml_assignment.new_element("full_lhs").data=full_lhs_string; xml_assignment.new_element("full_lhs_value").data=full_lhs_value_string; xml_assignment.new_element("value").data=value_string; xml_assignment.set_attribute_bool("hidden", it.hidden); xml_assignment.set_attribute("thread", i2string(it.thread_nr)); xml_assignment.set_attribute("identifier", id2string(identifier)); xml_assignment.set_attribute("base_name", id2string(base_name)); xml_assignment.set_attribute("display_name", id2string(display_name)); xml_assignment.set_attribute("step_nr", i2string(it.step_nr)); xml_assignment.set_attribute("assignment_type", it.assignment_type==goto_trace_stept::ACTUAL_PARAMETER?"actual_parameter": "state"); if(it.lhs_object_value.is_not_nil()) xml_assignment.new_element("value_expression").new_element(xml(it.lhs_object_value, ns)); } break; case goto_trace_stept::OUTPUT: { printf_formattert printf_formatter(ns); printf_formatter(id2string(it.format_string), it.io_args); std::string text=printf_formatter.as_string(); xmlt &xml_output=dest.new_element("output"); xml_output.new_element("text").data=text; xml_output.set_attribute_bool("hidden", it.hidden); xml_output.set_attribute("thread", i2string(it.thread_nr)); xml_output.set_attribute("step_nr", i2string(it.step_nr)); if(xml_location.name!="") xml_output.new_element().swap(xml_location); for(const auto l_it : it.io_args) { xml_output.new_element("value").data=from_expr(ns, "", l_it); xml_output.new_element("value_expression"). new_element(xml(l_it, ns)); } } break; case goto_trace_stept::INPUT: { xmlt &xml_input=dest.new_element("input"); xml_input.new_element("input_id").data=id2string(it.io_id); xml_input.set_attribute_bool("hidden", it.hidden); xml_input.set_attribute("thread", i2string(it.thread_nr)); xml_input.set_attribute("step_nr", i2string(it.step_nr)); for(const auto & l_it : it.io_args) { xml_input.new_element("value").data=from_expr(ns, "", l_it); xml_input.new_element("value_expression"). new_element(xml(l_it, ns)); } if(xml_location.name!="") xml_input.new_element().swap(xml_location); } break; case goto_trace_stept::FUNCTION_CALL: case goto_trace_stept::FUNCTION_RETURN: { std::string tag= (it.type==goto_trace_stept::FUNCTION_CALL)?"function_call":"function_return"; xmlt &xml_call_return=dest.new_element(tag); xml_call_return.set_attribute_bool("hidden", it.hidden); xml_call_return.set_attribute("thread", i2string(it.thread_nr)); xml_call_return.set_attribute("step_nr", i2string(it.step_nr)); const symbolt &symbol=ns.lookup(it.identifier); xmlt &xml_function=xml_call_return.new_element("function"); xml_function.set_attribute("display_name", id2string(symbol.display_name())); xml_function.set_attribute("identifier", id2string(it.identifier)); xml_function.new_element()=xml(symbol.location); if(xml_location.name!="") xml_call_return.new_element().swap(xml_location); } break; default: if(source_location!=previous_source_location) { // just the source location if(xml_location.name!="") { xmlt &xml_location_only=dest.new_element("location-only"); xml_location_only.set_attribute_bool("hidden", it.hidden); xml_location_only.set_attribute("thread", i2string(it.thread_nr)); xml_location_only.set_attribute("step_nr", i2string(it.step_nr)); xml_location_only.new_element().swap(xml_location); } } } if(source_location.is_not_nil() && source_location.get_file()!="") previous_source_location=source_location; } }