|
|
|
(*
|
|
|
|
* 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 CFrontend_utils
|
|
|
|
|
|
|
|
(* List of checkers on properties *)
|
|
|
|
let property_checkers_list = [CFrontend_checkers.strong_delegate_warning]
|
|
|
|
|
|
|
|
(* Invocation of checker belonging to property_checker_list *)
|
|
|
|
let checkers_for_property decl_info pname_info pdi checker =
|
|
|
|
checker decl_info pname_info pdi
|
|
|
|
|
|
|
|
(* 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 context stmt_info dr_name checker =
|
|
|
|
checker context stmt_info dr_name
|
|
|
|
|
|
|
|
(* 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_info captured_vars checker =
|
|
|
|
checker stmt_info captured_vars
|
|
|
|
|
|
|
|
(* Add a frontend warning with a description desc at location loc to the errlog of a proc desc *)
|
|
|
|
let log_frontend_warning pdesc warn_desc =
|
|
|
|
let open CFrontend_checkers in
|
|
|
|
let loc = warn_desc.loc in
|
|
|
|
let errlog = Cfg.Procdesc.get_err_log pdesc in
|
|
|
|
let err_desc =
|
|
|
|
Errdesc.explain_frontend_warning warn_desc.description warn_desc.suggestion loc in
|
|
|
|
let exn = Exceptions.Frontend_warning
|
|
|
|
(warn_desc.name, err_desc, __POS__) in
|
|
|
|
let trace = [
|
|
|
|
{ Errlog.lt_level = 0;
|
|
|
|
Errlog.lt_loc = warn_desc.loc;
|
|
|
|
Errlog.lt_description = "";
|
|
|
|
Errlog.lt_node_tags = []}] in
|
|
|
|
Reporting.log_error_from_errlog errlog exn ~loc:(Some loc) ~ltr:(Some trace)
|
|
|
|
|
|
|
|
(* 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 pdesc checkers =
|
|
|
|
IList.iter (fun checker ->
|
|
|
|
match f checker with
|
|
|
|
| Some warning_desc -> log_frontend_warning pdesc warning_desc
|
|
|
|
| None -> ()) checkers
|
|
|
|
|
|
|
|
(* Call all checkers on properties of class c *)
|
|
|
|
let rec check_for_property_errors cfg cg tenv class_name decl_list =
|
|
|
|
let open Clang_ast_t in
|
|
|
|
let do_one_property decl_info pname_info pdi =
|
|
|
|
let pdesc =
|
|
|
|
CMethod_trans.get_method_for_frontend_checks cfg cg tenv class_name decl_info in
|
|
|
|
let call_property_checker = checkers_for_property decl_info pname_info pdi in
|
|
|
|
invoke_set_of_checkers call_property_checker pdesc property_checkers_list in
|
|
|
|
match decl_list with
|
|
|
|
| [] -> ()
|
|
|
|
| ObjCPropertyDecl (decl_info, pname_info, pdi) :: rest ->
|
|
|
|
do_one_property decl_info pname_info pdi;
|
|
|
|
check_for_property_errors cfg cg tenv class_name rest
|
|
|
|
| _ :: rest ->
|
|
|
|
check_for_property_errors cfg cg tenv class_name rest
|
|
|
|
|
|
|
|
let get_categories_decls decl_ref =
|
|
|
|
match Ast_utils.get_decl_opt_with_decl_ref decl_ref with
|
|
|
|
| Some ObjCCategoryDecl (_, _, decls, _, _)
|
|
|
|
| Some ObjCInterfaceDecl (_, _, decls, _, _) -> decls
|
|
|
|
| _ -> []
|
|
|
|
|
|
|
|
let run_frontend_checkers_on_stmt trans_state instr =
|
|
|
|
let open Clang_ast_t in
|
|
|
|
let context = trans_state.CTrans_utils.context in
|
|
|
|
let pdesc = CContext.get_procdesc context in
|
|
|
|
match instr with
|
|
|
|
| ObjCIvarRefExpr(stmt_info, _, _, obj_c_ivar_ref_expr_info) ->
|
|
|
|
let dr_name = obj_c_ivar_ref_expr_info.Clang_ast_t.ovrei_decl_ref.Clang_ast_t.dr_name in
|
|
|
|
let call_checker_for_ivar = checkers_for_ivar context stmt_info dr_name in
|
|
|
|
invoke_set_of_checkers call_checker_for_ivar pdesc 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 captured_vars = CVar_decl.captured_vars_from_block_info context captured_block_vars in
|
|
|
|
let call_captured_vars_checker = checkers_for_capture_vars stmt_info captured_vars in
|
|
|
|
invoke_set_of_checkers call_captured_vars_checker pdesc captured_vars_checker_list
|
|
|
|
| _ -> ()
|
|
|
|
|
|
|
|
let run_frontend_checkers_on_decl tenv cg cfg dec =
|
|
|
|
let open Clang_ast_t in
|
|
|
|
match dec with
|
|
|
|
| ObjCCategoryImplDecl(_, name_info, decl_list, _, ocidi) ->
|
|
|
|
let name = Ast_utils.get_qualified_name name_info in
|
|
|
|
let curr_class = ObjcCategory_decl.get_curr_class_from_category_impl name ocidi in
|
|
|
|
let decls = (get_categories_decls ocidi.Clang_ast_t.ocidi_category_decl) @ decl_list in
|
|
|
|
let name = CContext.get_curr_class_name curr_class in
|
|
|
|
check_for_property_errors cfg cg tenv name decls
|
|
|
|
| ObjCImplementationDecl(_, _, decl_list, _, idi) ->
|
|
|
|
let curr_class = ObjcInterface_decl.get_curr_class_impl idi in
|
|
|
|
let name = CContext.get_curr_class_name curr_class in
|
|
|
|
let decls = (get_categories_decls idi.Clang_ast_t.oidi_class_interface) @ decl_list in
|
|
|
|
check_for_property_errors cfg cg tenv name decls
|
|
|
|
| _ -> ()
|