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
master
Mehdi Bouaziz 6 years ago committed by Facebook Github Bot
parent 35eba40452
commit e8d8caeecd

@ -226,11 +226,11 @@ let get_method_body_opt decl =
(Clang_ast_proj.get_decl_kind_string decl) (Clang_ast_proj.get_decl_kind_string decl)
let call_tableaux cxt an map_active = let call_tableaux linters cxt an map_active =
if CFrontend_config.tableaux_evaluation then Tableaux.build_valuation an cxt 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 = (map_act : Tableaux.context_linter_map) stmt =
let open Clang_ast_t in let open Clang_ast_t in
let an = Ctl_parser_types.Stmt stmt 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 = let do_all_checks_on_stmts context map_active stmt =
( match stmt with ( match stmt with
| DeclStmt (_, _, decl_list) -> | 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) -> | 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 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 *) (* 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 = let stmt_context_list =
match stmt with match stmt with
| ObjCAtSynchronizedStmt (_, stmt_list) -> | ObjCAtSynchronizedStmt (_, stmt_list) ->
@ -279,16 +279,16 @@ let rec do_frontend_checks_stmt (context : CLintersContext.context)
PointerToDecl are not visited PointerToDecl are not visited
during the evaluation of the formula. So we need to visit during the evaluation of the formula. So we need to visit
them diring the general visit of the tree. *) 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 List.iter
~f:(fun (cxt, stmts) -> ~f:(fun (cxt, stmts) ->
List.iter ~f:(do_all_checks_on_stmts cxt map_active) 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 stmt_context_list
(* Visit nodes via a transition *) (* 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 let succs = CTL.next_state_via_transition an trans in
List.iter List.iter
~f:(fun an' -> ~f:(fun an' ->
@ -298,20 +298,20 @@ and do_frontend_checks_via_transition context map_active an trans =
CTL.Debug.pp_transition (Some trans) ;*) CTL.Debug.pp_transition (Some trans) ;*)
match an' with match an' with
| Ctl_parser_types.Decl d -> | 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 -> | Ctl_parser_types.Stmt st ->
do_frontend_checks_stmt context map_active st ) do_frontend_checks_stmt linters context map_active st )
succs 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 = (map_act : Tableaux.context_linter_map) decl =
let open Clang_ast_t in let open Clang_ast_t in
if CAst_utils.is_implicit_decl decl then () (* do not analyze implicit declarations *) if CAst_utils.is_implicit_decl decl then () (* do not analyze implicit declarations *)
else else
let an = Ctl_parser_types.Decl decl in let an = Ctl_parser_types.Decl decl in
(* The map should be visited when we enter the node before visiting children *) (* 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 match decl with
| FunctionDecl _ | FunctionDecl _
| CXXMethodDecl _ | CXXMethodDecl _
@ -321,39 +321,39 @@ and do_frontend_checks_decl (context : CLintersContext.context)
| BlockDecl _ | BlockDecl _
| ObjCMethodDecl _ -> | ObjCMethodDecl _ ->
let context' = CLintersContext.update_current_method context decl in 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 (* We need to visit explicitly nodes reachable via Parameters transitions
because they won't be visited during the evaluation of the formula *) 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 ( match get_method_body_opt decl with
| Some stmt -> | Some stmt ->
do_frontend_checks_stmt context' map_active stmt do_frontend_checks_stmt linters context' map_active stmt
| None -> | None ->
() ) ; () ) ;
call_tableaux context' an map_active call_tableaux linters context' an map_active
| ObjCImplementationDecl (_, _, decls, _, _) | ObjCInterfaceDecl (_, _, decls, _, _) -> | 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 let context' = {context with current_objc_class= Some decl} in
List.iter ~f:(do_frontend_checks_decl context' map_active) decls ; List.iter ~f:(do_frontend_checks_decl linters context' map_active) decls ;
call_tableaux context' an map_active call_tableaux linters context' an map_active
| ObjCCategoryImplDecl (_, _, decls, _, _) | ObjCCategoryDecl (_, _, decls, _, _) -> | 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 let context' = {context with current_objc_category= Some decl} in
List.iter ~f:(do_frontend_checks_decl context' map_active) decls ; List.iter ~f:(do_frontend_checks_decl linters context' map_active) decls ;
call_tableaux context' an map_active call_tableaux linters context' an map_active
| ObjCProtocolDecl (_, _, decls, _, _) -> | 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 let context' = {context with current_objc_protocol= Some decl} in
List.iter ~f:(do_frontend_checks_decl context' map_active) decls ; List.iter ~f:(do_frontend_checks_decl linters context' map_active) decls ;
call_tableaux context' an map_active 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 ( match Clang_ast_proj.get_decl_context_tuple decl with
| Some (decls, _) -> | 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 -> | None ->
() ) ; () ) ;
call_tableaux context an map_active call_tableaux linters context an map_active
let context_with_ck_set context decl_list = 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) (Pp.comma_seq Format.pp_print_string)
linters_files ; linters_files ;
CTL.create_ctl_evaluation_tracker trans_unit_ctx.source_file ; CTL.create_ctl_evaluation_tracker trans_unit_ctx.source_file ;
let parsed_linters =
let parsed_linters = parse_ctl_files linters_files in let parsed_linters = parse_ctl_files linters_files in
let filtered_parsed_linters =
CFrontend_errors.filter_parsed_linters parsed_linters trans_unit_ctx.source_file CFrontend_errors.filter_parsed_linters parsed_linters trans_unit_ctx.source_file
in in
CFrontend_errors.parsed_linters := filtered_parsed_linters ;
let source_file = trans_unit_ctx.CFrontend_config.source_file in let source_file = trans_unit_ctx.CFrontend_config.source_file in
L.(debug Linters Medium) L.(debug Linters Medium)
"Start linting file %a with rules: @\n%a@\n" SourceFile.pp source_file "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 if Config.print_active_checkers then
L.progress "Linting file %a, active linters: @\n%a@\n" SourceFile.pp source_file 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 () ; Tableaux.init_global_nodes_valuation () ;
match ast with match ast with
| Clang_ast_t.TranslationUnitDecl (_, decl_list, _, _) -> | Clang_ast_t.TranslationUnitDecl (_, decl_list, _, _) ->
let context = context_with_ck_set (CLintersContext.empty trans_unit_ctx) decl_list in 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 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 *) (* We analyze the top level and then all the allowed declarations *)
let active_map : Tableaux.context_linter_map = Tableaux.init_active_map () in let active_map : Tableaux.context_linter_map = Tableaux.init_active_map parsed_linters in
CFrontend_errors.invoke_set_of_checkers_on_node context (Ctl_parser_types.Decl ast) ; CFrontend_errors.invoke_set_of_checkers_on_node parsed_linters context
List.iter ~f:(do_frontend_checks_decl context active_map) allowed_decls ; (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 ; IssueLog.store Config.lint_issues_dir_name source_file ;
L.(debug Linters Medium) "End linting file %a@\n" SourceFile.pp 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 CTL.save_dotty_when_in_debug_mode trans_unit_ctx.CFrontend_config.source_file

@ -97,10 +97,6 @@ let stmt_single_checkers_list =
let stmt_checkers_list = List.map ~f:single_to_multi 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 = let evaluate_place_holder context ph an =
match ph with match ph with
| "%ivar_name%" -> | "%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 *) (* 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 ( match an with
| Ctl_parser_types.Decl (Clang_ast_t.TranslationUnitDecl _) -> | Ctl_parser_types.Decl (Clang_ast_t.TranslationUnitDecl _) ->
(* Don't run parsed linters on TranslationUnitDecl node. (* 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 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 if Config.default_linters then invoke_set_of_hard_coded_checkers_an context an

@ -25,18 +25,14 @@ val pp_linters : Format.formatter -> linter list -> unit
type macros_map = (bool * ALVar.t list * CTL.t) ALVar.FormulaIdMap.t 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 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 *) (* 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 val build_macros_map : CTL.clause list -> macros_map

@ -61,12 +61,12 @@ let is_decl_allowed lcxt decl =
let is_in_formula phi = match phi with CTL.InNode _ -> true | _ -> false let is_in_formula phi = match phi with CTL.InNode _ -> true | _ -> false
(* Map initialized with false for InNode formula and true for others *) (* Map initialized with false for InNode formula and true for others *)
let init_active_map () = let init_active_map parsed_linters =
List.fold List.fold
~f:(fun acc_map linter -> ~f:(fun acc_map linter ->
let not_inf = not (is_in_formula linter.CFrontend_errors.condition) in let not_inf = not (is_in_formula linter.CFrontend_errors.condition) in
ClosureHashtbl.add linter.CFrontend_errors.condition not_inf acc_map ) 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 (* 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 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 sense to keep evaluation phi. Otherwise we can skip the evaluation of phi and
its subformulae *) 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 do_one_linter acc_map linter =
let phi = linter.CFrontend_errors.condition in let phi = linter.CFrontend_errors.condition in
match phi with match phi with
@ -91,7 +91,7 @@ let update_linter_context_map an linter_context_map =
| _ -> | _ ->
acc_map acc_map
in 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 (* 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) *) (* 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 open CFrontend_errors in
let node_pointer = Ctl_parser_types.ast_node_pointer an in let node_pointer = Ctl_parser_types.ast_node_pointer an in
(*L.(debug Linters Medium) (*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 CIssue.should_run_check linter.issue_desc.CIssue.mode
&& check_linter_map linter_map_context linter.condition && check_linter_map linter_map_context linter.condition
then do_one_check linter ) then do_one_check linter )
!parsed_linters parsed_linters

@ -13,12 +13,19 @@ type context_linter_map = bool ClosureHashtbl.t
val init_global_nodes_valuation : unit -> unit 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 : 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 : 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 val is_decl_allowed : CLintersContext.context -> Clang_ast_t.decl -> bool

Loading…
Cancel
Save