From e8d8caeecdeb644c6f17b4066a004819fee4d624 Mon Sep 17 00:00:00 2001 From: Mehdi Bouaziz Date: Thu, 6 Sep 2018 15:06:56 -0700 Subject: [PATCH] CFrontend_errors: avoid exposing a global reference Summary: This list is built once only, let's avoid exposing it. Reviewed By: jeremydubreil Differential Revision: D9654091 fbshipit-source-id: d92f91329 --- infer/src/clang/cFrontend_checkers_main.ml | 78 +++++++++++----------- infer/src/clang/cFrontend_errors.ml | 8 +-- infer/src/clang/cFrontend_errors.mli | 12 ++-- infer/src/clang/tableaux.ml | 12 ++-- infer/src/clang/tableaux.mli | 13 +++- 5 files changed, 61 insertions(+), 62 deletions(-) diff --git a/infer/src/clang/cFrontend_checkers_main.ml b/infer/src/clang/cFrontend_checkers_main.ml index ce5df2b8f..fb908feb7 100644 --- a/infer/src/clang/cFrontend_checkers_main.ml +++ b/infer/src/clang/cFrontend_checkers_main.ml @@ -226,11 +226,11 @@ let get_method_body_opt decl = (Clang_ast_proj.get_decl_kind_string decl) -let call_tableaux cxt an map_active = - if CFrontend_config.tableaux_evaluation then Tableaux.build_valuation an cxt map_active +let call_tableaux linters cxt an map_active = + if CFrontend_config.tableaux_evaluation then Tableaux.build_valuation linters an cxt map_active -let rec do_frontend_checks_stmt (context : CLintersContext.context) +let rec do_frontend_checks_stmt linters (context : CLintersContext.context) (map_act : Tableaux.context_linter_map) stmt = let open Clang_ast_t in let an = Ctl_parser_types.Stmt stmt in @@ -239,16 +239,16 @@ let rec do_frontend_checks_stmt (context : CLintersContext.context) let do_all_checks_on_stmts context map_active stmt = ( match stmt with | DeclStmt (_, _, decl_list) -> - List.iter ~f:(do_frontend_checks_decl context map_active) decl_list + List.iter ~f:(do_frontend_checks_decl linters context map_active) decl_list | BlockExpr (_, _, _, decl) -> - List.iter ~f:(do_frontend_checks_decl context map_active) [decl] + List.iter ~f:(do_frontend_checks_decl linters context map_active) [decl] | _ -> () ) ; - do_frontend_checks_stmt context map_active stmt + do_frontend_checks_stmt linters context map_active stmt in - CFrontend_errors.invoke_set_of_checkers_on_node context an ; + CFrontend_errors.invoke_set_of_checkers_on_node linters context an ; (* The map should be visited when we enter the node before visiting children *) - let map_active = Tableaux.update_linter_context_map an map_act in + let map_active = Tableaux.update_linter_context_map linters an map_act in let stmt_context_list = match stmt with | ObjCAtSynchronizedStmt (_, stmt_list) -> @@ -279,16 +279,16 @@ let rec do_frontend_checks_stmt (context : CLintersContext.context) PointerToDecl are not visited during the evaluation of the formula. So we need to visit them diring the general visit of the tree. *) - do_frontend_checks_via_transition context map_active an CTL.PointerToDecl ; + do_frontend_checks_via_transition linters context map_active an CTL.PointerToDecl ; List.iter ~f:(fun (cxt, stmts) -> List.iter ~f:(do_all_checks_on_stmts cxt map_active) stmts ; - call_tableaux cxt an map_active ) + call_tableaux linters cxt an map_active ) stmt_context_list (* Visit nodes via a transition *) -and do_frontend_checks_via_transition context map_active an trans = +and do_frontend_checks_via_transition linters context map_active an trans = let succs = CTL.next_state_via_transition an trans in List.iter ~f:(fun an' -> @@ -298,20 +298,20 @@ and do_frontend_checks_via_transition context map_active an trans = CTL.Debug.pp_transition (Some trans) ;*) match an' with | Ctl_parser_types.Decl d -> - do_frontend_checks_decl context map_active d + do_frontend_checks_decl linters context map_active d | Ctl_parser_types.Stmt st -> - do_frontend_checks_stmt context map_active st ) + do_frontend_checks_stmt linters context map_active st ) succs -and do_frontend_checks_decl (context : CLintersContext.context) +and do_frontend_checks_decl linters (context : CLintersContext.context) (map_act : Tableaux.context_linter_map) decl = let open Clang_ast_t in if CAst_utils.is_implicit_decl decl then () (* do not analyze implicit declarations *) else let an = Ctl_parser_types.Decl decl in (* The map should be visited when we enter the node before visiting children *) - let map_active = Tableaux.update_linter_context_map an map_act in + let map_active = Tableaux.update_linter_context_map linters an map_act in match decl with | FunctionDecl _ | CXXMethodDecl _ @@ -321,39 +321,39 @@ and do_frontend_checks_decl (context : CLintersContext.context) | BlockDecl _ | ObjCMethodDecl _ -> let context' = CLintersContext.update_current_method context decl in - CFrontend_errors.invoke_set_of_checkers_on_node context' an ; + CFrontend_errors.invoke_set_of_checkers_on_node linters context' an ; (* We need to visit explicitly nodes reachable via Parameters transitions because they won't be visited during the evaluation of the formula *) - do_frontend_checks_via_transition context' map_active an CTL.Parameters ; + do_frontend_checks_via_transition linters context' map_active an CTL.Parameters ; ( match get_method_body_opt decl with | Some stmt -> - do_frontend_checks_stmt context' map_active stmt + do_frontend_checks_stmt linters context' map_active stmt | None -> () ) ; - call_tableaux context' an map_active + call_tableaux linters context' an map_active | ObjCImplementationDecl (_, _, decls, _, _) | ObjCInterfaceDecl (_, _, decls, _, _) -> - CFrontend_errors.invoke_set_of_checkers_on_node context an ; + CFrontend_errors.invoke_set_of_checkers_on_node linters context an ; let context' = {context with current_objc_class= Some decl} in - List.iter ~f:(do_frontend_checks_decl context' map_active) decls ; - call_tableaux context' an map_active + List.iter ~f:(do_frontend_checks_decl linters context' map_active) decls ; + call_tableaux linters context' an map_active | ObjCCategoryImplDecl (_, _, decls, _, _) | ObjCCategoryDecl (_, _, decls, _, _) -> - CFrontend_errors.invoke_set_of_checkers_on_node context an ; + CFrontend_errors.invoke_set_of_checkers_on_node linters context an ; let context' = {context with current_objc_category= Some decl} in - List.iter ~f:(do_frontend_checks_decl context' map_active) decls ; - call_tableaux context' an map_active + List.iter ~f:(do_frontend_checks_decl linters context' map_active) decls ; + call_tableaux linters context' an map_active | ObjCProtocolDecl (_, _, decls, _, _) -> - CFrontend_errors.invoke_set_of_checkers_on_node context an ; + CFrontend_errors.invoke_set_of_checkers_on_node linters context an ; let context' = {context with current_objc_protocol= Some decl} in - List.iter ~f:(do_frontend_checks_decl context' map_active) decls ; - call_tableaux context' an map_active + List.iter ~f:(do_frontend_checks_decl linters context' map_active) decls ; + call_tableaux linters context' an map_active | _ -> - CFrontend_errors.invoke_set_of_checkers_on_node context an ; + CFrontend_errors.invoke_set_of_checkers_on_node linters context an ; ( match Clang_ast_proj.get_decl_context_tuple decl with | Some (decls, _) -> - List.iter ~f:(do_frontend_checks_decl context map_active) decls + List.iter ~f:(do_frontend_checks_decl linters context map_active) decls | None -> () ) ; - call_tableaux context an map_active + call_tableaux linters context an map_active let context_with_ck_set context decl_list = @@ -379,27 +379,27 @@ let do_frontend_checks (trans_unit_ctx : CFrontend_config.translation_unit_conte (Pp.comma_seq Format.pp_print_string) linters_files ; CTL.create_ctl_evaluation_tracker trans_unit_ctx.source_file ; - let parsed_linters = parse_ctl_files linters_files in - let filtered_parsed_linters = + let parsed_linters = + let parsed_linters = parse_ctl_files linters_files in CFrontend_errors.filter_parsed_linters parsed_linters trans_unit_ctx.source_file in - CFrontend_errors.parsed_linters := filtered_parsed_linters ; let source_file = trans_unit_ctx.CFrontend_config.source_file in L.(debug Linters Medium) "Start linting file %a with rules: @\n%a@\n" SourceFile.pp source_file - CFrontend_errors.pp_linters filtered_parsed_linters ; + CFrontend_errors.pp_linters parsed_linters ; if Config.print_active_checkers then L.progress "Linting file %a, active linters: @\n%a@\n" SourceFile.pp source_file - CFrontend_errors.pp_linters filtered_parsed_linters ; + CFrontend_errors.pp_linters parsed_linters ; Tableaux.init_global_nodes_valuation () ; match ast with | Clang_ast_t.TranslationUnitDecl (_, decl_list, _, _) -> let context = context_with_ck_set (CLintersContext.empty trans_unit_ctx) decl_list in let allowed_decls = List.filter ~f:(Tableaux.is_decl_allowed context) decl_list in (* We analyze the top level and then all the allowed declarations *) - let active_map : Tableaux.context_linter_map = Tableaux.init_active_map () in - CFrontend_errors.invoke_set_of_checkers_on_node context (Ctl_parser_types.Decl ast) ; - List.iter ~f:(do_frontend_checks_decl context active_map) allowed_decls ; + let active_map : Tableaux.context_linter_map = Tableaux.init_active_map parsed_linters in + CFrontend_errors.invoke_set_of_checkers_on_node parsed_linters context + (Ctl_parser_types.Decl ast) ; + List.iter ~f:(do_frontend_checks_decl parsed_linters context active_map) allowed_decls ; IssueLog.store Config.lint_issues_dir_name source_file ; L.(debug Linters Medium) "End linting file %a@\n" SourceFile.pp source_file ; CTL.save_dotty_when_in_debug_mode trans_unit_ctx.CFrontend_config.source_file diff --git a/infer/src/clang/cFrontend_errors.ml b/infer/src/clang/cFrontend_errors.ml index 037935e18..13923d466 100644 --- a/infer/src/clang/cFrontend_errors.ml +++ b/infer/src/clang/cFrontend_errors.ml @@ -97,10 +97,6 @@ let stmt_single_checkers_list = let stmt_checkers_list = List.map ~f:single_to_multi stmt_single_checkers_list -(* List of checkers that will be filled after parsing them from - input the linter def files *) -let parsed_linters = ref [] - let evaluate_place_holder context ph an = match ph with | "%ivar_name%" -> @@ -508,7 +504,7 @@ let invoke_set_of_parsed_checkers_an parsed_linters context (an : Ctl_parser_typ (* We decouple the hardcoded checkers from the parsed ones *) -let invoke_set_of_checkers_on_node context an = +let invoke_set_of_checkers_on_node parsed_linters context an = ( match an with | Ctl_parser_types.Decl (Clang_ast_t.TranslationUnitDecl _) -> (* Don't run parsed linters on TranslationUnitDecl node. @@ -516,5 +512,5 @@ let invoke_set_of_checkers_on_node context an = () | _ -> if not CFrontend_config.tableaux_evaluation then - invoke_set_of_parsed_checkers_an !parsed_linters context an ) ; + invoke_set_of_parsed_checkers_an parsed_linters context an ) ; if Config.default_linters then invoke_set_of_hard_coded_checkers_an context an diff --git a/infer/src/clang/cFrontend_errors.mli b/infer/src/clang/cFrontend_errors.mli index 9a0a06f2e..9446743ba 100644 --- a/infer/src/clang/cFrontend_errors.mli +++ b/infer/src/clang/cFrontend_errors.mli @@ -25,18 +25,14 @@ val pp_linters : Format.formatter -> linter list -> unit type macros_map = (bool * ALVar.t list * CTL.t) ALVar.FormulaIdMap.t -(* Map a path name to a list of paths. *) - +(** Map a path name to a list of paths. *) type paths_map = ALVar.t list ALVar.VarMap.t -(* List of checkers that will be filled after parsing them from a file *) - -val parsed_linters : linter list ref - (* Module for warnings detected at translation time by the frontend *) -(* Run frontend checkers on an AST node *) -val invoke_set_of_checkers_on_node : CLintersContext.context -> Ctl_parser_types.ast_node -> unit +val invoke_set_of_checkers_on_node : + linter list -> CLintersContext.context -> Ctl_parser_types.ast_node -> unit +(** Run frontend checkers on an AST node *) val build_macros_map : CTL.clause list -> macros_map diff --git a/infer/src/clang/tableaux.ml b/infer/src/clang/tableaux.ml index 9797652eb..37fa8c7bd 100644 --- a/infer/src/clang/tableaux.ml +++ b/infer/src/clang/tableaux.ml @@ -61,12 +61,12 @@ let is_decl_allowed lcxt decl = let is_in_formula phi = match phi with CTL.InNode _ -> true | _ -> false (* Map initialized with false for InNode formula and true for others *) -let init_active_map () = +let init_active_map parsed_linters = List.fold ~f:(fun acc_map linter -> let not_inf = not (is_in_formula linter.CFrontend_errors.condition) in ClosureHashtbl.add linter.CFrontend_errors.condition not_inf acc_map ) - ~init:ClosureHashtbl.empty !CFrontend_errors.parsed_linters + ~init:ClosureHashtbl.empty parsed_linters (* update the context map for formulae of type InNode(tl, phi). When we @@ -74,7 +74,7 @@ let init_active_map () = when we are in a node that is a discendant of a node in tl so that is make sense to keep evaluation phi. Otherwise we can skip the evaluation of phi and its subformulae *) -let update_linter_context_map an linter_context_map = +let update_linter_context_map parsed_linters an linter_context_map = let do_one_linter acc_map linter = let phi = linter.CFrontend_errors.condition in match phi with @@ -91,7 +91,7 @@ let update_linter_context_map an linter_context_map = | _ -> acc_map in - List.fold ~f:do_one_linter ~init:linter_context_map !CFrontend_errors.parsed_linters + List.fold ~f:do_one_linter ~init:linter_context_map parsed_linters (* Takes phi and transform it by an equivalent formula containing @@ -314,7 +314,7 @@ let skip_evaluation_InNode_formula an phi = (* Build valuation, i.e. set of valid subformula for a pair (node, checker) *) -let build_valuation an lcxt linter_map_context = +let build_valuation parsed_linters an lcxt linter_map_context = let open CFrontend_errors in let node_pointer = Ctl_parser_types.ast_node_pointer an in (*L.(debug Linters Medium) @@ -343,4 +343,4 @@ let build_valuation an lcxt linter_map_context = CIssue.should_run_check linter.issue_desc.CIssue.mode && check_linter_map linter_map_context linter.condition then do_one_check linter ) - !parsed_linters + parsed_linters diff --git a/infer/src/clang/tableaux.mli b/infer/src/clang/tableaux.mli index d86f5d285..c40bc067d 100644 --- a/infer/src/clang/tableaux.mli +++ b/infer/src/clang/tableaux.mli @@ -13,12 +13,19 @@ type context_linter_map = bool ClosureHashtbl.t val init_global_nodes_valuation : unit -> unit -val init_active_map : unit -> bool ClosureHashtbl.t +val init_active_map : CFrontend_errors.linter list -> bool ClosureHashtbl.t val update_linter_context_map : - Ctl_parser_types.ast_node -> context_linter_map -> context_linter_map + CFrontend_errors.linter list + -> Ctl_parser_types.ast_node + -> context_linter_map + -> context_linter_map val build_valuation : - Ctl_parser_types.ast_node -> CLintersContext.context -> context_linter_map -> unit + CFrontend_errors.linter list + -> Ctl_parser_types.ast_node + -> CLintersContext.context + -> context_linter_map + -> unit val is_decl_allowed : CLintersContext.context -> Clang_ast_t.decl -> bool