Start transitioning logging of frontend bugs into a map of errlogs rather than in procdescs

Reviewed By: akotulski

Differential Revision: D3562290

fbshipit-source-id: e51f2ff
master
Dulma Churchill 8 years ago committed by Facebook Github Bot 4
parent b8044c6b65
commit 62da495510

@ -127,6 +127,8 @@ let inferconfig_file = ".inferconfig"
let ivar_attributes = "ivar_attributes"
let linters_mode_enabled = false
(** letters used in the analysis output *)
let log_analysis_file = "F"
let log_analysis_procedure = "."

@ -79,6 +79,7 @@ val idempotent_getters : bool
val incremental_procs : bool
val initial_analysis_time : float
val ivar_attributes : string
val linters_mode_enabled : bool
val load_average : float option
val log_analysis_crash : string
val log_analysis_file : string

@ -102,7 +102,7 @@ struct
let field_name = General_utils.mk_class_field_name named_decl_info in
let process_accessor pointer ~getter =
(match Ast_utils.get_decl_opt_with_decl_ref pointer with
| Some ObjCMethodDecl (decl_info, name_info, mdi) ->
| Some (ObjCMethodDecl (decl_info, _, _) as d) ->
let source_range = decl_info.Clang_ast_t.di_source_range in
let loc = CLocation.get_sil_location_from_range source_range true in
let property_accessor =
@ -110,8 +110,7 @@ struct
Some (ProcAttributes.Objc_getter field_name)
else
Some (ProcAttributes.Objc_setter field_name) in
let class_name = Ast_utils.get_class_name_from_member name_info in
let procname = CMethod_trans.get_objc_method_name name_info mdi class_name in
let procname = General_utils.procname_of_decl d in
let attrs = { (ProcAttributes.default procname Config.Clang) with
loc = loc;
objc_accessor = property_accessor; } in

@ -47,12 +47,26 @@ let global_var_checker_list = [CFrontend_checkers.global_var_init_with_calls_war
let checker_for_global_var dec checker =
checker dec
let errLogMap = ref Procname.Map.empty
let get_err_log cfg cg method_decl_opt loc =
if Config.linters_mode_enabled then
let procname = match method_decl_opt with
| Some method_decl -> General_utils.procname_of_decl method_decl
| None -> General_utils.get_procname_for_frontend_checks loc in
try Procname.Map.find procname !errLogMap
with Not_found ->
let errlog = Errlog.empty () in
errLogMap := Procname.Map.add procname errlog !errLogMap; errlog
else
let pdesc = CMethod_trans.get_method_for_frontend_checks cfg cg loc in
Cfg.Procdesc.get_err_log pdesc
(* Add a frontend warning with a description desc at location loc to the errlog of a proc desc *)
let log_frontend_issue cfg cg issue_desc =
let log_frontend_issue cfg cg method_decl_opt issue_desc =
let issue = issue_desc.CIssue.issue in
let loc = issue_desc.CIssue.loc in
let pdesc = CMethod_trans.get_method_for_frontend_checks cfg cg loc in
let errlog = Cfg.Procdesc.get_err_log pdesc in
let errlog = get_err_log cfg cg method_decl_opt loc in
let err_desc = Errdesc.explain_frontend_warning issue_desc.CIssue.description
issue_desc.CIssue.suggestion loc in
let name = CIssue.to_string issue in
@ -70,10 +84,10 @@ let log_frontend_issue cfg cg issue_desc =
1. f a particular way to apply a checker, it's a partial function
2. context
3. the list of checkers to be applied *)
let invoke_set_of_checkers f cfg cg checkers =
let invoke_set_of_checkers f cfg cg method_decl_opt checkers =
IList.iter (fun checker ->
match f checker with
| Some issue_desc -> log_frontend_issue cfg cg issue_desc
| Some issue_desc -> log_frontend_issue cfg cg method_decl_opt issue_desc
| None -> ()) checkers
(* Call all checkers on properties of class c *)
@ -81,7 +95,7 @@ let rec check_for_property_errors cfg cg decl_list =
let open Clang_ast_t in
let do_one_property decl_info pname_info pdi =
let call_property_checker = checkers_for_property decl_info pname_info pdi in
invoke_set_of_checkers call_property_checker cfg cg property_checkers_list in
invoke_set_of_checkers call_property_checker cfg cg None property_checkers_list in
match decl_list with
| [] -> ()
| ObjCPropertyDecl (decl_info, pname_info, pdi) :: rest ->
@ -102,11 +116,13 @@ let run_frontend_checkers_on_stmt cfg cg method_decl instr =
| ObjCIvarRefExpr(stmt_info, _, _, obj_c_ivar_ref_expr_info) ->
let dr_ref = obj_c_ivar_ref_expr_info.Clang_ast_t.ovrei_decl_ref in
let call_checker_for_ivar = checkers_for_ivar method_decl stmt_info dr_ref in
invoke_set_of_checkers call_checker_for_ivar cfg cg ivar_access_checker_list
let method_decl_opt = Some method_decl in
invoke_set_of_checkers call_checker_for_ivar cfg cg method_decl_opt ivar_access_checker_list
| BlockExpr(stmt_info, _ , _, Clang_ast_t.BlockDecl (_, block_decl_info)) ->
let captured_block_vars = block_decl_info.Clang_ast_t.bdi_captured_variables in
let call_captured_vars_checker = checkers_for_capture_vars stmt_info captured_block_vars in
invoke_set_of_checkers call_captured_vars_checker cfg cg captured_vars_checker_list
let decl_opt = Some method_decl in
invoke_set_of_checkers call_captured_vars_checker cfg cg decl_opt captured_vars_checker_list
| _ -> ()
let rec run_frontend_checkers_on_decl cfg cg dec =
@ -122,14 +138,14 @@ let rec run_frontend_checkers_on_decl cfg cg dec =
let decls = (get_categories_decls idi.Clang_ast_t.oidi_class_interface) @ decl_list in
check_for_property_errors cfg cg decls;
let call_ns_checker = checkers_for_ns decl_info decl_list in
invoke_set_of_checkers call_ns_checker cfg cg ns_notification_checker_list;
invoke_set_of_checkers call_ns_checker cfg cg None ns_notification_checker_list;
IList.iter (run_frontend_checkers_on_decl cfg cg) decl_list
| ObjCProtocolDecl (decl_info, _, decl_list, _, _) ->
check_for_property_errors cfg cg decl_list;
let call_ns_checker = checkers_for_ns decl_info decl_list in
invoke_set_of_checkers call_ns_checker cfg cg ns_notification_checker_list;
invoke_set_of_checkers call_ns_checker cfg cg None ns_notification_checker_list;
IList.iter (run_frontend_checkers_on_decl cfg cg) decl_list
| VarDecl _ ->
let call_global_checker = checker_for_global_var dec in
invoke_set_of_checkers call_global_checker cfg cg global_var_checker_list
invoke_set_of_checkers call_global_checker cfg cg None global_var_checker_list
| _ -> ()

@ -18,3 +18,4 @@ val run_frontend_checkers_on_stmt : Cfg.cfg -> Cg.t -> Clang_ast_t.decl -> Clang
(* Run frontend checkers on a declaration *)
val run_frontend_checkers_on_decl : Cfg.cfg -> Cg.t -> Clang_ast_t.decl -> unit
val errLogMap : Errlog.t Procname.Map.t ref

@ -640,6 +640,34 @@ struct
Procname.ObjC_Cpp
(Procname.objc_cpp class_name method_name mangled_opt)
let get_objc_method_name name_info mdi class_name =
let method_name = name_info.Clang_ast_t.ni_name in
let is_instance = mdi.Clang_ast_t.omdi_is_instance_method in
let method_kind = Procname.objc_method_kind_of_bool is_instance in
mk_procname_from_objc_method class_name method_name method_kind
let procname_of_decl meth_decl =
let open Clang_ast_t in
match meth_decl with
| FunctionDecl (decl_info, name_info, _, fdi) ->
let name = Ast_utils.get_qualified_name name_info in
let language = Config.clang_lang in
let function_info = Some (decl_info, fdi) in
mk_procname_from_function name function_info language
| CXXMethodDecl (_, name_info, _, fdi, mdi)
| CXXConstructorDecl (_, name_info, _, fdi, mdi)
| CXXConversionDecl (_, name_info, _, fdi, mdi)
| CXXDestructorDecl (_, name_info, _, fdi, mdi) ->
let mangled = get_mangled_method_name fdi mdi in
let method_name = Ast_utils.get_unqualified_name name_info in
let class_name = Ast_utils.get_class_name_from_member name_info in
mk_procname_from_cpp_method class_name method_name mangled
| ObjCMethodDecl (_, name_info, mdi) ->
let class_name = Ast_utils.get_class_name_from_member name_info in
get_objc_method_name name_info mdi class_name
| _ -> assert false
let get_var_name_mangled name_info var_decl_info =
let clang_name = Ast_utils.get_qualified_name name_info in
let param_idx_opt = var_decl_info.Clang_ast_t.vdi_parm_index_in_function in
@ -675,4 +703,8 @@ struct
Pvar.mk mangled_name procname
| None -> Pvar.mk (Mangled.from_string name_string) procname
let get_procname_for_frontend_checks loc =
let mangled = string_crc_hex32 (DB.source_file_to_string loc.Location.file) in
Procname.from_string_c_fun ("frontend_checks_" ^ mangled)
end

@ -209,6 +209,10 @@ sig
val mk_procname_from_cpp_method : string -> string -> string option-> Procname.t
val procname_of_decl : Clang_ast_t.decl -> Procname.t
val get_procname_for_frontend_checks : Location.t -> Procname.t
val mk_class_field_name : Clang_ast_t.named_decl_info -> Ident.fieldname
val get_var_name_mangled : Clang_ast_t.named_decl_info -> Clang_ast_t.var_decl_info ->

@ -156,32 +156,21 @@ let get_init_list_instrs method_decl_info =
let create_custom_instr construct_instr = `CXXConstructorInit construct_instr in
IList.map create_custom_instr method_decl_info.Clang_ast_t.xmdi_cxx_ctor_initializers
let get_objc_method_name name_info mdi class_name =
let method_name = name_info.Clang_ast_t.ni_name in
let is_instance = mdi.Clang_ast_t.omdi_is_instance_method in
let method_kind = Procname.objc_method_kind_of_bool is_instance in
General_utils.mk_procname_from_objc_method class_name method_name method_kind
let method_signature_of_decl tenv meth_decl block_data_opt =
let open Clang_ast_t in
match meth_decl, block_data_opt with
| FunctionDecl (decl_info, name_info, tp, fdi), _ ->
let name = Ast_utils.get_qualified_name name_info in
| FunctionDecl (decl_info, _, tp, fdi), _ ->
let language = Config.clang_lang in
let func_decl = Func_decl_info (fdi, tp, language) in
let function_info = Some (decl_info, fdi) in
let procname = General_utils.mk_procname_from_function name function_info language in
let procname = General_utils.procname_of_decl meth_decl in
let ms = build_method_signature tenv decl_info procname func_decl None None in
let extra_instrs = get_assume_not_null_calls fdi.Clang_ast_t.fdi_parameters in
ms, fdi.Clang_ast_t.fdi_body, extra_instrs
| CXXMethodDecl (decl_info, name_info, tp, fdi, mdi), _
| CXXConstructorDecl (decl_info, name_info, tp, fdi, mdi), _
| CXXConversionDecl (decl_info, name_info, tp, fdi, mdi), _
| CXXDestructorDecl (decl_info, name_info, tp, fdi, mdi), _ ->
let method_name = Ast_utils.get_unqualified_name name_info in
let class_name = Ast_utils.get_class_name_from_member name_info in
let mangled = General_utils.get_mangled_method_name fdi mdi in
let procname = General_utils.mk_procname_from_cpp_method class_name method_name mangled in
| CXXMethodDecl (decl_info, _, tp, fdi, mdi), _
| CXXConstructorDecl (decl_info, _, tp, fdi, mdi), _
| CXXConversionDecl (decl_info, _, tp, fdi, mdi), _
| CXXDestructorDecl (decl_info, _, tp, fdi, mdi), _ ->
let procname = General_utils.procname_of_decl meth_decl in
let parent_ptr = Option.get decl_info.di_parent_pointer in
let method_decl = Cpp_Meth_decl_info (fdi, mdi, parent_ptr, tp) in
let parent_pointer = decl_info.Clang_ast_t.di_parent_pointer in
@ -189,9 +178,8 @@ let method_signature_of_decl tenv meth_decl block_data_opt =
let non_null_instrs = get_assume_not_null_calls fdi.Clang_ast_t.fdi_parameters in
let init_list_instrs = get_init_list_instrs mdi in (* it will be empty for methods *)
ms, fdi.Clang_ast_t.fdi_body, (init_list_instrs @ non_null_instrs)
| ObjCMethodDecl (decl_info, name_info, mdi), _ ->
let class_name = Ast_utils.get_class_name_from_member name_info in
let procname = get_objc_method_name name_info mdi class_name in
| ObjCMethodDecl (decl_info, _, mdi), _ ->
let procname = General_utils.procname_of_decl meth_decl in
let parent_ptr = Option.get decl_info.di_parent_pointer in
let method_decl = ObjC_Meth_decl_info (mdi, parent_ptr) in
let parent_pointer = decl_info.Clang_ast_t.di_parent_pointer in
@ -451,8 +439,7 @@ let create_procdesc_with_pointer context pointer class_name_opt name =
callee_name
let get_method_for_frontend_checks cfg cg loc =
let mangled = string_crc_hex32 (DB.source_file_to_string loc.Location.file) in
let proc_name = Procname.from_string_c_fun ("frontend_checks_" ^ mangled) in
let proc_name = General_utils.get_procname_for_frontend_checks loc in
match Cfg.Procdesc.find_from_name cfg proc_name with
| Some pdesc -> pdesc
| None ->

@ -55,6 +55,3 @@ val get_method_for_frontend_checks : Cfg.cfg -> Cg.t -> Location.t -> Cfg.Procde
val add_default_method_for_class : string -> Clang_ast_t.decl_info -> unit
val get_procname_from_cpp_lambda : CContext.t -> Clang_ast_t.decl -> Procname.t
val get_objc_method_name : Clang_ast_t.named_decl_info -> Clang_ast_t.obj_c_method_decl_info ->
string -> Procname.t

Loading…
Cancel
Save