diff --git a/infer/src/IR/Cfg.ml b/infer/src/IR/Cfg.ml index b6aefecf5..f8244b63b 100644 --- a/infer/src/IR/Cfg.ml +++ b/infer/src/IR/Cfg.ml @@ -293,12 +293,54 @@ let store_cfg_to_file ~source_file (filename: DB.filename) (cfg: cfg) = Serialization.write_to_file cfg_serializer filename ~data:cfg -(** clone a procedure description and apply the type substitutions where - the parameters are used *) -let specialize_types_proc callee_pdesc resolved_pdesc substitutions = +(** Applies convert_instr_list to all the instructions in all the nodes of the cfg *) +let convert_cfg ~callee_pdesc ~resolved_pdesc convert_instr_list = let resolved_pname = Procdesc.get_proc_name resolved_pdesc and callee_start_node = Procdesc.get_start_node callee_pdesc and callee_exit_node = Procdesc.get_exit_node callee_pdesc in + let convert_node_kind = function + | Procdesc.Node.Start_node _ -> + Procdesc.Node.Start_node resolved_pname + | Procdesc.Node.Exit_node _ -> + Procdesc.Node.Exit_node resolved_pname + | node_kind -> + node_kind + in + let node_map = ref Procdesc.NodeMap.empty in + let rec convert_node node = + let loc = Procdesc.Node.get_loc node + and kind = convert_node_kind (Procdesc.Node.get_kind node) + and instrs = convert_instr_list (Procdesc.Node.get_instrs node) in + Procdesc.create_node resolved_pdesc loc kind instrs + and loop callee_nodes = + match callee_nodes with + | [] -> + [] + | node :: other_node -> + let converted_node = + try Procdesc.NodeMap.find node !node_map + with Not_found -> + let new_node = convert_node node + and successors = Procdesc.Node.get_succs node + and exn_nodes = Procdesc.Node.get_exn node in + node_map := Procdesc.NodeMap.add node new_node !node_map ; + if Procdesc.Node.equal node callee_start_node then + Procdesc.set_start_node resolved_pdesc new_node ; + if Procdesc.Node.equal node callee_exit_node then + Procdesc.set_exit_node resolved_pdesc new_node ; + Procdesc.node_set_succs_exn callee_pdesc new_node (loop successors) (loop exn_nodes) ; + new_node + in + converted_node :: loop other_node + in + ignore (loop [callee_start_node]) ; + resolved_pdesc + + +(** clone a procedure description and apply the type substitutions where + the parameters are used *) +let specialize_types_proc callee_pdesc resolved_pdesc substitutions = + let resolved_pname = Procdesc.get_proc_name resolved_pdesc in let convert_pvar pvar = Pvar.mk (Pvar.get_name pvar) resolved_pname in let mk_ptr_typ typename = (* Only consider pointers from Java objects for now *) @@ -377,43 +419,8 @@ let specialize_types_proc callee_pdesc resolved_pdesc substitutions = (* these are generated instructions that will be replaced by the preanalysis *) instrs in - let convert_node_kind = function - | Procdesc.Node.Start_node _ -> - Procdesc.Node.Start_node resolved_pname - | Procdesc.Node.Exit_node _ -> - Procdesc.Node.Exit_node resolved_pname - | node_kind -> - node_kind - in - let node_map = ref Procdesc.NodeMap.empty in - let rec convert_node node = - let loc = Procdesc.Node.get_loc node - and kind = convert_node_kind (Procdesc.Node.get_kind node) - and instrs = List.fold ~f:convert_instr ~init:[] (Procdesc.Node.get_instrs node) |> List.rev in - Procdesc.create_node resolved_pdesc loc kind instrs - and loop callee_nodes = - match callee_nodes with - | [] -> - [] - | node :: other_node -> - let converted_node = - try Procdesc.NodeMap.find node !node_map - with Not_found -> - let new_node = convert_node node - and successors = Procdesc.Node.get_succs node - and exn_nodes = Procdesc.Node.get_exn node in - node_map := Procdesc.NodeMap.add node new_node !node_map ; - if Procdesc.Node.equal node callee_start_node then - Procdesc.set_start_node resolved_pdesc new_node ; - if Procdesc.Node.equal node callee_exit_node then - Procdesc.set_exit_node resolved_pdesc new_node ; - Procdesc.node_set_succs_exn callee_pdesc new_node (loop successors) (loop exn_nodes) ; - new_node - in - converted_node :: loop other_node - in - ignore (loop [callee_start_node]) ; - resolved_pdesc + let convert_instr_list instrs = List.fold ~f:convert_instr ~init:[] instrs |> List.rev in + convert_cfg ~callee_pdesc ~resolved_pdesc convert_instr_list (** Creates a copy of a procedure description and a list of type substitutions of the form