(* * Copyright (c) 2015 - present Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. *) open! Utils open CFrontend_utils (* List of checkers on properties *) let property_checkers_list = [CFrontend_checkers.strong_delegate_warning; CFrontend_checkers.assign_pointer_warning;] (* Invocation of checker belonging to property_checker_list *) let checkers_for_property decl checker context = checker context decl (* List of checkers on ivar access *) let ivar_access_checker_list = [CFrontend_checkers.direct_atomic_property_access_warning] (* Invocation of checker belonging to ivar_access_checker_list *) let checkers_for_ivar stmt checker context = checker context stmt (* List of checkers for captured vars in objc blocks *) let captured_vars_checker_list = [CFrontend_checkers.captured_cxx_ref_in_objc_block_warning] (* Invocation of checker belonging to captured_vars_checker_list *) let checkers_for_capture_vars stmt checker context = checker context stmt (* List of checkers on NSNotificationCenter *) let ns_notification_checker_list = [CFrontend_checkers.checker_NSNotificationCenter] (* Invocation of checker belonging to ns_notification_center_list *) let checkers_for_ns decl checker context = checker context decl (* List of checkers on variables *) let var_checker_list = [CFrontend_checkers.global_var_init_with_calls_warning; ComponentKit.mutable_local_vars_advice] (* Invocation of checker belonging to var_checker_list *) let checker_for_var dec checker context = checker context dec (* List of checkers on conditional operator *) let conditional_op_checker_list = [CFrontend_checkers.bad_pointer_comparison_warning] (* Invocation of checker belonging to conditional_op_checker_list *) let checker_for_conditional_op first_stmt checker context = checker context first_stmt (* List of checkers on if-statement *) let if_stmt_checker_list = [CFrontend_checkers.bad_pointer_comparison_warning] (* Invocation of checker belonging to if_stmt_checker_list *) let checker_for_if_stmt cond checker context = checker context cond (* List of checkers on for statement *) let for_stmt_checker_list = [CFrontend_checkers.bad_pointer_comparison_warning] (* Invocation of checker belonging to for_stmt_checker_list *) let checker_for_for_stmt cond checker context = checker context cond (* List of checkers on while statement *) let while_stmt_checker_list = [CFrontend_checkers.bad_pointer_comparison_warning] (* Invocation of checker belonging to while_stmt_checker_list *) let checker_for_while_stmt cond checker context = checker context cond let function_decl_checker_list = [ComponentKit.component_factory_function_advice] let checker_for_function_decl decl checker context = checker context decl let get_err_log method_decl_opt = let procname = match method_decl_opt with | Some method_decl -> General_utils.procname_of_decl method_decl | None -> Procname.Linters_dummy_method in LintIssues.get_err_log procname (* Add a frontend warning with a description desc at location loc to the errlog of a proc desc *) let log_frontend_issue method_decl_opt key issue_desc = let issue = issue_desc.CIssue.issue in let loc = issue_desc.CIssue.loc in let errlog = get_err_log method_decl_opt 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 let exn = Exceptions.Frontend_warning (name, err_desc, __POS__) in let trace = [ { Errlog.lt_level = 0; Errlog.lt_loc = issue_desc.CIssue.loc; Errlog.lt_description = ""; Errlog.lt_node_tags = []}] in let err_kind = CIssue.severity_of_issue issue in let method_name = Ast_utils.full_name_of_decl_opt method_decl_opt in let key = Hashtbl.hash (key ^ method_name) in Reporting.log_issue_from_errlog err_kind errlog exn ~loc ~ltr:trace ~node_id:(0, key) (* General invocation function for checkers Takes 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 context key checkers = IList.iter (fun checker -> match f checker context with | Some issue_desc -> log_frontend_issue context.CLintersContext.current_method key issue_desc | None -> ()) checkers let run_frontend_checkers_on_stmt context instr = let open Clang_ast_t in match instr with | ObjCIvarRefExpr _ -> let call_checker_for_ivar = checkers_for_ivar instr in let key = Ast_utils.generate_key_stmt instr in invoke_set_of_checkers call_checker_for_ivar context key ivar_access_checker_list; context | BlockExpr _ -> let call_captured_vars_checker = checkers_for_capture_vars instr in let key = Ast_utils.generate_key_stmt instr in invoke_set_of_checkers call_captured_vars_checker context key captured_vars_checker_list; context | IfStmt (_, _ :: _ :: cond :: _) -> let call_checker = checker_for_if_stmt cond in let key = Ast_utils.generate_key_stmt cond in invoke_set_of_checkers call_checker context key if_stmt_checker_list; context | ConditionalOperator (_, first_stmt :: _, _) -> let call_checker = checker_for_conditional_op first_stmt in let key = Ast_utils.generate_key_stmt first_stmt in invoke_set_of_checkers call_checker context key conditional_op_checker_list; context | ForStmt (_, [_; _; cond; _; _]) -> let call_checker = checker_for_for_stmt cond in let key = Ast_utils.generate_key_stmt cond in invoke_set_of_checkers call_checker context key for_stmt_checker_list; context | WhileStmt (_, [_; cond; _]) -> let call_checker = checker_for_while_stmt cond in let key = Ast_utils.generate_key_stmt cond in invoke_set_of_checkers call_checker context key while_stmt_checker_list; context | ObjCAtSynchronizedStmt _ -> { context with CLintersContext.in_synchronized_block = true } | _ -> context let run_frontend_checkers_on_decl context dec = let open Clang_ast_t in match dec with | ObjCImplementationDecl _ | ObjCProtocolDecl _ -> let call_ns_checker = checkers_for_ns dec in let key = Ast_utils.generate_key_decl dec in invoke_set_of_checkers call_ns_checker context key ns_notification_checker_list; context | VarDecl _ -> let call_var_checker = checker_for_var dec in let key = Ast_utils.generate_key_decl dec in invoke_set_of_checkers call_var_checker context key var_checker_list; context | FunctionDecl _ -> let call_function_decl_checker = checker_for_function_decl dec in let key = Ast_utils.generate_key_decl dec in invoke_set_of_checkers call_function_decl_checker context key function_decl_checker_list; context | ObjCPropertyDecl _ -> let call_property_checker = checkers_for_property dec in let key = Ast_utils.generate_key_decl dec in invoke_set_of_checkers call_property_checker context key property_checkers_list; context | _ -> context