Put current method in context

Reviewed By: jvillard

Differential Revision: D3741728

fbshipit-source-id: 6710016
master
Dulma Churchill 9 years ago committed by Facebook Github Bot 1
parent 2da8940a80
commit 07bf714d91

@ -8,6 +8,7 @@
*)
type context = {
current_method : Clang_ast_t.decl option;
in_synchronized_block: bool;
is_ck_translation_unit: bool;
(** True if the translation unit contains an ObjC class impl that's a subclass
@ -15,6 +16,7 @@ type context = {
}
let empty = {
current_method = None;
in_synchronized_block = false;
is_ck_translation_unit = false;
}

@ -217,10 +217,10 @@ let global_var_init_with_calls_warning _ decl =
(* Direct Atomic Property access:
a property declared atomic should not be accessed directly via its ivar *)
let direct_atomic_property_access_warning context method_decl stmt_info ivar_decl_ref =
let direct_atomic_property_access_warning context stmt_info ivar_decl_ref =
let ivar_pointer = ivar_decl_ref.Clang_ast_t.dr_decl_pointer in
match Ast_utils.get_decl ivar_pointer with
| Some (ObjCIvarDecl (_, named_decl_info, _, _, _) as d) ->
match Ast_utils.get_decl ivar_pointer, context.CLintersContext.current_method with
| Some (ObjCIvarDecl (_, named_decl_info, _, _, _) as d), Some method_decl ->
let method_name = match Clang_ast_proj.get_named_decl_tuple method_decl with
| Some (_, method_named_decl) -> method_named_decl.Clang_ast_t.ni_name
| _ -> "" in

@ -24,8 +24,8 @@ val assign_pointer_warning :
(* Direct Atomic Property access:
a property declared atomic should not be accesses directly via its iva *)
val direct_atomic_property_access_warning :
CLintersContext.context -> Clang_ast_t.decl -> Clang_ast_t.stmt_info ->
Clang_ast_t.decl_ref -> CIssue.issue_desc option
CLintersContext.context -> Clang_ast_t.stmt_info -> Clang_ast_t.decl_ref ->
CIssue.issue_desc option
(* CXX_REFERENCE_CAPTURED_IN_OBJC_BLOCK: C++ references
should not be captured in blocks. *)

@ -7,15 +7,20 @@
* of patent rights can be found in the PATENTS file in the same directory.
*)
let rec do_frontend_checks_stmt (context:CLintersContext.context) cfg cg method_decl stmt =
let context' = CFrontend_errors.run_frontend_checkers_on_stmt context cfg cg method_decl stmt in
let stmts = CFrontend_utils.Ast_utils.get_stmts_from_stmt stmt in
open CFrontend_utils
let rec do_frontend_checks_stmt (context:CLintersContext.context) cfg cg stmt =
let open Clang_ast_t in
let context' = CFrontend_errors.run_frontend_checkers_on_stmt context cfg cg stmt in
let do_all_checks_on_stmts stmt =
(match stmt with
| Clang_ast_t.DeclStmt (_, _, decl_list) ->
| DeclStmt (_, _, decl_list) ->
IList.iter (do_frontend_checks_decl context' cfg cg) decl_list
| BlockExpr (_, _, _, decl) ->
IList.iter (do_frontend_checks_decl context' cfg cg) [decl]
| _ -> ());
do_frontend_checks_stmt context' cfg cg method_decl stmt in
do_frontend_checks_stmt context' cfg cg stmt in
let stmts = Ast_utils.get_stmts_from_stmt stmt in
IList.iter (do_all_checks_on_stmts) stmts
and do_frontend_checks_decl context cfg cg decl =
@ -29,11 +34,21 @@ and do_frontend_checks_decl context cfg cg decl =
| CXXConversionDecl (_, _, _, fdi, _)
| CXXDestructorDecl (_, _, _, fdi, _) ->
(match fdi.Clang_ast_t.fdi_body with
| Some stmt -> do_frontend_checks_stmt context cfg cg decl stmt
| Some stmt ->
let context = {context with CLintersContext.current_method = Some decl } in
do_frontend_checks_stmt context cfg cg stmt
| None -> ())
| ObjCMethodDecl (_, _, mdi) ->
(match mdi.Clang_ast_t.omdi_body with
| Some stmt -> do_frontend_checks_stmt context cfg cg decl stmt
| Some stmt ->
let context = {context with CLintersContext.current_method = Some decl } in
do_frontend_checks_stmt context cfg cg stmt
| None -> ())
| BlockDecl (_, block_decl_info) ->
(match block_decl_info.Clang_ast_t.bdi_body with
| Some stmt ->
let context = {context with CLintersContext.current_method = Some decl } in
do_frontend_checks_stmt context cfg cg stmt
| None -> ())
| _ -> ());
let context' = CFrontend_errors.run_frontend_checkers_on_decl context cfg cg decl in

@ -23,8 +23,8 @@ let checkers_for_property decl_info pname_info pdi checker context =
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_info method_decl ivar_decl_ref checker context =
checker context stmt_info method_decl ivar_decl_ref
let checkers_for_ivar stmt_info ivar_decl_ref checker context =
checker context stmt_info ivar_decl_ref
(* List of checkers for captured vars in objc blocks *)
let captured_vars_checker_list = [CFrontend_checkers.captured_cxx_ref_in_objc_block_warning]
@ -40,12 +40,12 @@ let ns_notification_checker_list = [CFrontend_checkers.checker_NSNotificationCen
let checkers_for_ns decl_info impl_decl_info decls checker context =
checker context decl_info impl_decl_info decls
(* List of checkers on global variables *)
let global_var_checker_list = [CFrontend_checkers.global_var_init_with_calls_warning;
(* 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 global_var_checker_list *)
let checker_for_global_var dec checker context =
(* Invocation of checker belonging to var_checker_list *)
let checker_for_var dec checker context =
checker context dec
(* List of checkers on conditional operator *)
@ -111,49 +111,49 @@ let log_frontend_issue cfg cg method_decl_opt key 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 context cfg cg method_decl_opt key checkers =
let invoke_set_of_checkers f context cfg cg key checkers =
IList.iter (fun checker ->
match f checker context with
| Some issue_desc -> log_frontend_issue cfg cg method_decl_opt key issue_desc
| Some issue_desc ->
log_frontend_issue cfg cg context.CLintersContext.current_method key issue_desc
| None -> ()) checkers
let run_frontend_checkers_on_stmt context cfg cg method_decl instr =
let run_frontend_checkers_on_stmt context cfg cg instr =
let open Clang_ast_t in
let decl_opt = Some method_decl in
match instr with
| 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
let call_checker_for_ivar = checkers_for_ivar stmt_info dr_ref in
let key = Ast_utils.generate_key_stmt instr in
invoke_set_of_checkers
call_checker_for_ivar context cfg cg decl_opt key ivar_access_checker_list;
call_checker_for_ivar context cfg cg key ivar_access_checker_list;
context
| 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
let key = Ast_utils.generate_key_stmt instr in
invoke_set_of_checkers call_captured_vars_checker context cfg cg decl_opt key
invoke_set_of_checkers call_captured_vars_checker context cfg cg key
captured_vars_checker_list;
context
| IfStmt (stmt_info, _ :: cond :: _) ->
let call_checker = checker_for_if_stmt stmt_info [cond] in
let key = Ast_utils.generate_key_stmt cond in
invoke_set_of_checkers call_checker context cfg cg decl_opt key if_stmt_checker_list;
invoke_set_of_checkers call_checker context cfg cg key if_stmt_checker_list;
context
| ConditionalOperator (stmt_info, first_stmt :: _, _) ->
let call_checker = checker_for_conditional_op stmt_info [first_stmt] in
let key = Ast_utils.generate_key_stmt first_stmt in
invoke_set_of_checkers call_checker context cfg cg decl_opt key conditional_op_checker_list;
invoke_set_of_checkers call_checker context cfg cg key conditional_op_checker_list;
context
| ForStmt (stmt_info, [_; _; cond; _; _]) ->
let call_checker = checker_for_for_stmt stmt_info [cond] in
let key = Ast_utils.generate_key_stmt cond in
invoke_set_of_checkers call_checker context cfg cg decl_opt key for_stmt_checker_list;
invoke_set_of_checkers call_checker context cfg cg key for_stmt_checker_list;
context
| WhileStmt (stmt_info, [_; cond; _]) ->
let call_checker = checker_for_while_stmt stmt_info [cond] in
let key = Ast_utils.generate_key_stmt cond in
invoke_set_of_checkers call_checker context cfg cg decl_opt key while_stmt_checker_list;
invoke_set_of_checkers call_checker context cfg cg key while_stmt_checker_list;
context
| ObjCAtSynchronizedStmt _ ->
{ context with CLintersContext.in_synchronized_block = true }
@ -171,17 +171,17 @@ let run_frontend_checkers_on_decl context cfg cg dec =
| _ -> None in
let call_ns_checker = checkers_for_ns decl_info idi decl_list in
let key = Ast_utils.generate_key_decl dec in
invoke_set_of_checkers call_ns_checker context cfg cg None key ns_notification_checker_list;
invoke_set_of_checkers call_ns_checker context cfg cg key ns_notification_checker_list;
context
| VarDecl _ ->
let call_global_checker = checker_for_global_var dec in
let call_var_checker = checker_for_var dec in
let key = Ast_utils.generate_key_decl dec in
invoke_set_of_checkers call_global_checker context cfg cg None key global_var_checker_list;
invoke_set_of_checkers call_var_checker context cfg cg key var_checker_list;
context
| ObjCPropertyDecl (decl_info, pname_info, pdi) ->
let call_property_checker = checkers_for_property decl_info pname_info pdi in
let key = Ast_utils.generate_key_decl dec in
invoke_set_of_checkers call_property_checker context cfg cg None key property_checkers_list;
invoke_set_of_checkers call_property_checker context cfg cg key property_checkers_list;
context
| _ -> context
else context

@ -15,7 +15,7 @@ open! Utils
(* Run frontend checkers on a statement *)
val run_frontend_checkers_on_stmt :
CLintersContext.context ->
Cfg.cfg -> Cg.t -> Clang_ast_t.decl -> Clang_ast_t.stmt -> CLintersContext.context
Cfg.cfg -> Cg.t -> Clang_ast_t.stmt -> CLintersContext.context
(* Run frontend checkers on a declaration *)
val run_frontend_checkers_on_decl : CLintersContext.context -> Cfg.cfg -> Cg.t ->

@ -11,6 +11,7 @@ package endtoend.objcpp.componentkit;
import static org.hamcrest.MatcherAssert.assertThat;
import static utils.matchers.ResultContainsLineNumbers.containsLines;
import static utils.matchers.ResultContainsErrorInMethod.contains;
import com.google.common.collect.ImmutableList;
@ -52,4 +53,14 @@ public class MutableLocalVariableTest {
inferResults,
containsLines(new int[]{58, 69, 74, 76, 80, 85}));
}
@Test
public void MLVsInNewWithString()
throws InterruptedException, IOException, InferException {
InferResults inferResults = InferRunner.runInferObjC(inferCmd);
assertThat(
"Results should contain " + MUTABLE_LOCAL_VARIABLE_IN_COMPONENT_FILE,
inferResults,
contains(MUTABLE_LOCAL_VARIABLE_IN_COMPONENT_FILE, FILE, "newWithString:"));
}
}

Loading…
Cancel
Save