diff --git a/infer/src/IR/Cfg.re b/infer/src/IR/Cfg.re index 604c04e86..cf30feec2 100644 --- a/infer/src/IR/Cfg.re +++ b/infer/src/IR/Cfg.re @@ -496,3 +496,9 @@ let specialize_types callee_pdesc resolved_pname args => { }; specialize_types_proc callee_pdesc resolved_pdesc substitutions }; + +let pp_proc_signatures fmt cfg => { + F.fprintf fmt "METHOD SIGNATURES\n@."; + let sorted_procs = List.sort cmp::Procdesc.compare (get_all_procs cfg); + List.iter f::(fun pdesc => F.fprintf fmt "%a@." Procdesc.pp_signature pdesc) sorted_procs +}; diff --git a/infer/src/IR/Cfg.rei b/infer/src/IR/Cfg.rei index 52c0d72c2..3fd8ab523 100644 --- a/infer/src/IR/Cfg.rei +++ b/infer/src/IR/Cfg.rei @@ -67,3 +67,5 @@ let remove_proc_desc: cfg => Procname.t => unit; all the type of the parameters are replaced in the instructions according to the list. The virtual calls are also replaced to match the parameter types */ let specialize_types: Procdesc.t => Procname.t => list (Exp.t, Typ.t) => Procdesc.t; + +let pp_proc_signatures: Format.formatter => cfg => unit; diff --git a/infer/src/IR/Procdesc.re b/infer/src/IR/Procdesc.re index 01847ebe9..1d9ce2efd 100644 --- a/infer/src/IR/Procdesc.re +++ b/infer/src/IR/Procdesc.re @@ -559,3 +559,36 @@ let is_loop_head pdesc (node: Node.t) => { }; NodeSet.mem node lh }; + +let pp_variable_list fmt etl => + if (List.is_empty etl) { + Format.fprintf fmt "None" + } else { + IList.iter + (fun (id, ty) => Format.fprintf fmt " %a:%a" Mangled.pp id (Typ.pp_full Pp.text) ty) etl + }; + +let pp_signature fmt pdesc => { + let pname = get_proc_name pdesc; + let pname_string = Procname.to_string pname; + let defined_string = is_defined pdesc ? "defined" : "undefined"; + Format.fprintf + fmt + "%s [%s, Return type: %s, Formals: %a, Locals: %a" + pname_string + defined_string + (Typ.to_string (get_ret_type pdesc)) + pp_variable_list + (get_formals pdesc) + pp_variable_list + (get_locals pdesc); + if (not (List.is_empty (get_captured pdesc))) { + Format.fprintf fmt ", Captured: %a" pp_variable_list (get_captured pdesc) + }; + let attributes = get_attributes pdesc; + let method_annotation = attributes.ProcAttributes.method_annotation; + if (not (Annot.Method.is_empty method_annotation)) { + Format.fprintf fmt ", Annotation: %a" (Annot.Method.pp pname_string) method_annotation + }; + Format.fprintf fmt "]@\n" +}; diff --git a/infer/src/IR/Procdesc.rei b/infer/src/IR/Procdesc.rei index 8ed820db4..00df8f56e 100644 --- a/infer/src/IR/Procdesc.rei +++ b/infer/src/IR/Procdesc.rei @@ -280,3 +280,5 @@ let set_start_node: t => Node.t => unit; let signal_did_preanalysis: t => unit; let is_loop_head: t => Node.t => bool; + +let pp_signature: Format.formatter => t => unit; diff --git a/infer/src/clang/cFrontend.ml b/infer/src/clang/cFrontend.ml index ea4295e8a..1fe503603 100644 --- a/infer/src/clang/cFrontend.ml +++ b/infer/src/clang/cFrontend.ml @@ -67,5 +67,6 @@ let do_source_file translation_unit_context ast = || Option.is_some Config.icfg_dotty_outfile then (Dotty.print_icfg_dotty source_file cfg; Cg.save_call_graph_dotty source_file Specs.get_specs call_graph); + Logging.out_debug "%a" Cfg.pp_proc_signatures cfg; (* NOTE: nothing should be written to source_dir after this *) DB.mark_file_updated (DB.source_dir_to_string source_dir)