From 3e6bd7f063344bad7ec50a0a632a22470d4f9e01 Mon Sep 17 00:00:00 2001 From: Sam Blackshear Date: Thu, 12 Apr 2018 07:39:34 -0700 Subject: [PATCH] [clang] log broken CFGs Reviewed By: dulmarod Differential Revision: D7291180 fbshipit-source-id: 93d0024 --- infer/src/IR/Cfg.ml | 13 +++---------- infer/src/IR/Cfg.mli | 4 ++-- infer/src/clang/ClangLogging.ml | 17 +++++++++++++++++ infer/src/clang/ClangLogging.mli | 2 ++ infer/src/clang/cFrontend.ml | 1 - infer/src/clang/cFrontend_decl.ml | 7 ++++++- 6 files changed, 30 insertions(+), 14 deletions(-) diff --git a/infer/src/IR/Cfg.ml b/infer/src/IR/Cfg.ml index 427bec53c..5220fbb1b 100644 --- a/infer/src/IR/Cfg.ml +++ b/infer/src/IR/Cfg.ml @@ -53,12 +53,11 @@ let iter_all_nodes ?(sorted= false) f cfg = |> List.iter ~f:(fun (d, n) -> f d n) -(** checks whether a cfg is connected or not *) -let check_cfg_connectedness cfg = +let is_proc_cfg_connected proc_desc = let is_exit_node n = match Procdesc.Node.get_kind n with Procdesc.Node.Exit_node _ -> true | _ -> false in - let broken_node n = + let is_broken_node n = let succs = Procdesc.Node.get_succs n in let preds = Procdesc.Node.get_preds n in match Procdesc.Node.get_kind n with @@ -74,13 +73,7 @@ let check_cfg_connectedness cfg = (* if the if brances end with a return *) match succs with [n'] when is_exit_node n' -> false | _ -> Int.equal (List.length preds) 0 in - let do_pdesc pname pd = - let nodes = Procdesc.get_nodes pd in - (* TODO (T20302015): also check the CFGs for the C-like procedures *) - if not Config.keep_going && Typ.Procname.is_java pname && List.exists ~f:broken_node nodes then - L.(die InternalError) "Broken CFG on %a" Typ.Procname.pp pname - in - Typ.Procname.Hash.iter do_pdesc cfg + not (List.exists ~f:is_broken_node (Procdesc.get_nodes proc_desc)) let load_statement = diff --git a/infer/src/IR/Cfg.mli b/infer/src/IR/Cfg.mli index c05e54c8d..6cbdaeb8e 100644 --- a/infer/src/IR/Cfg.mli +++ b/infer/src/IR/Cfg.mli @@ -32,8 +32,8 @@ val create_proc_desc : t -> ProcAttributes.t -> Procdesc.t val iter_all_nodes : ?sorted:bool -> (Procdesc.t -> Procdesc.Node.t -> unit) -> t -> unit (** Iterate over all the nodes in the cfg *) -val check_cfg_connectedness : t -> unit -(** checks whether a cfg is connected or not *) +val is_proc_cfg_connected : Procdesc.t -> bool +(** checks whether a cfg for the given procdesc is connected or not *) val save_attributes : SourceFile.t -> t -> unit (** Save the .attr files for the procedures in the cfg. *) diff --git a/infer/src/clang/ClangLogging.ml b/infer/src/clang/ClangLogging.ml index e1391da79..c384ebbe1 100644 --- a/infer/src/clang/ClangLogging.ml +++ b/infer/src/clang/ClangLogging.ml @@ -21,3 +21,20 @@ let log_caught_exception (trans_unit_ctx: CFrontend_config.translation_unit_cont ; lang= CFrontend_config.string_of_clang_lang trans_unit_ctx.lang } in EventLogger.log caught_exception + + +let log_broken_cfg procdesc exception_triggered_location ~lang = + let proc_location = Procdesc.get_loc procdesc in + let exception_type = + F.asprintf "Broken CFG for %a" Typ.Procname.pp (Procdesc.get_proc_name procdesc) + in + let cfg_exception = + EventLogger.FrontendException + { source_location_start= proc_location + ; source_location_end= proc_location + ; ast_node= None + ; exception_triggered_location + ; exception_type + ; lang } + in + EventLogger.log cfg_exception diff --git a/infer/src/clang/ClangLogging.mli b/infer/src/clang/ClangLogging.mli index 4d29c95fc..90774b49d 100644 --- a/infer/src/clang/ClangLogging.mli +++ b/infer/src/clang/ClangLogging.mli @@ -12,3 +12,5 @@ open! IStd val log_caught_exception : CFrontend_config.translation_unit_context -> string -> Logging.ocaml_pos -> Clang_ast_t.source_location * Clang_ast_t.source_location -> string option -> unit + +val log_broken_cfg : Procdesc.t -> Logging.ocaml_pos -> lang:string -> unit diff --git a/infer/src/clang/cFrontend.ml b/infer/src/clang/cFrontend.ml index 133dd7f07..844826b56 100644 --- a/infer/src/clang/cFrontend.ml +++ b/infer/src/clang/cFrontend.ml @@ -53,7 +53,6 @@ let do_source_file (translation_unit_context: CFrontend_config.translation_unit_ NullabilityPreanalysis.analysis cfg tenv ; SourceFiles.add source_file cfg (FileLocal tenv) ; if Config.debug_mode then Tenv.store_debug_file_for_source source_file tenv ; - if Config.debug_mode then Cfg.check_cfg_connectedness cfg ; if Config.debug_mode || Config.testing_mode || Config.frontend_tests || Option.is_some Config.icfg_dotty_outfile then Dotty.print_icfg_dotty source_file cfg ; diff --git a/infer/src/clang/cFrontend_decl.ml b/infer/src/clang/cFrontend_decl.ml index de25f604f..a108442ac 100644 --- a/infer/src/clang/cFrontend_decl.ml +++ b/infer/src/clang/cFrontend_decl.ml @@ -84,7 +84,12 @@ module CFrontend_decl_funct (T : CModule_type.CTranslation) : CModule_type.CFron let proc_attributes = Procdesc.get_attributes procdesc in Procdesc.Node.add_locals_ret_declaration start_node proc_attributes (Procdesc.get_locals procdesc) ; - Procdesc.node_set_succs_exn procdesc start_node meth_body_nodes [] + Procdesc.node_set_succs_exn procdesc start_node meth_body_nodes [] ; + if not (Cfg.is_proc_cfg_connected procdesc) then + let lang = + CFrontend_config.string_of_clang_lang trans_unit_ctx.CFrontend_config.lang + in + ClangLogging.log_broken_cfg procdesc __POS__ ~lang | _ -> () | exception Not_found ->