Removing the dispatcher for linters.

Reviewed By: dulmarod

Differential Revision: D4182551

fbshipit-source-id: af7c88e
master
Dino Distefano 8 years ago committed by Facebook Github Bot
parent 4512fcd8ef
commit 0ed033a32e

@ -64,7 +64,7 @@ and contains_ck_impl decl_list =
const int *z;
const NSString *y;
``` *)
let mutable_local_vars_advice context decl =
let mutable_local_vars_advice context an =
let rec get_referenced_type (qual_type: Clang_ast_t.qual_type) : Clang_ast_t.decl option =
let typ_opt = Ast_utils.get_desugared_type qual_type.qt_type_ptr in
match (typ_opt : Clang_ast_t.c_type option) with
@ -85,8 +85,8 @@ let mutable_local_vars_advice context decl =
IList.mem string_equal ndi.ni_name objc_whitelist
| _ -> false in
match decl with
| Clang_ast_t.VarDecl(decl_info, named_decl_info, qual_type, _) ->
match an with
| CTL.Decl (Clang_ast_t.VarDecl(decl_info, named_decl_info, qual_type, _) as decl)->
let is_const_ref = match Ast_utils.get_type qual_type.qt_type_ptr with
| Some LValueReferenceType (_, {Clang_ast_t.qt_is_const}) ->
qt_is_const
@ -98,33 +98,33 @@ let mutable_local_vars_advice context decl =
&& not (is_of_whitelisted_type qual_type)
&& not decl_info.di_is_implicit in
if condition then
Some {
CTL.True, Some {
CIssue.issue = CIssue.Mutable_local_variable_in_component_file;
CIssue.description = "Local variable '" ^ named_decl_info.ni_name
^ "' should be const to avoid reassignment";
CIssue.suggestion = Some "Add a const (after the asterisk for pointer types).";
CIssue.loc = CFrontend_checkers.location_from_dinfo context decl_info
}
else None
| _ -> assert false (* Should only be called with a VarDecl *)
else CTL.False, None
| _ -> CTL.False, None (* Should only be called with a VarDecl *)
(** Catches functions that should be composite components.
http://componentkit.org/docs/break-out-composites.html
Any static function that returns a subclass of CKComponent will be flagged. *)
let component_factory_function_advice context decl =
let component_factory_function_advice context an =
let is_component_if decl =
Ast_utils.is_objc_if_descendant decl [CFrontend_config.ckcomponent_cl] in
match decl with
| Clang_ast_t.FunctionDecl (decl_info, _, (qual_type: Clang_ast_t.qual_type), _) ->
match an with
| CTL.Decl (Clang_ast_t.FunctionDecl (decl_info, _, (qual_type: Clang_ast_t.qual_type), _) as decl) ->
let objc_interface =
Ast_utils.type_ptr_to_objc_interface qual_type.qt_type_ptr in
let condition =
is_ck_context context decl && is_component_if objc_interface in
if condition then
Some {
CTL.True, Some {
CIssue.issue = CIssue.Component_factory_function;
CIssue.description = "Break out composite components";
CIssue.suggestion = Some (
@ -133,13 +133,13 @@ let component_factory_function_advice context decl =
);
CIssue.loc = CFrontend_checkers.location_from_dinfo context decl_info
}
else None
| _ -> assert false (* Should only be called with FunctionDecl *)
else CTL.False, None
| _ -> CTL.False, None (* Should only be called with FunctionDecl *)
(** Components should not inherit from each other. They should instead
inherit from CKComponent, CKCompositeComponent, or
CKStatefulViewComponent. (Similar rule applies to component controllers.) *)
let component_with_unconventional_superclass_advice context decl =
let component_with_unconventional_superclass_advice context an =
let check_interface if_decl =
match if_decl with
| Clang_ast_t.ObjCInterfaceDecl (_, _, _, _, _) ->
@ -164,7 +164,7 @@ let component_with_unconventional_superclass_advice context decl =
is_component_or_controller_if (Some if_decl)
&& not has_conventional_superclass in
if condition then
Some {
CTL.True, Some {
CIssue.issue = CIssue.Component_with_unconventional_superclass;
CIssue.description = "Never Subclass Components";
CIssue.suggestion = Some (
@ -173,19 +173,19 @@ let component_with_unconventional_superclass_advice context decl =
CIssue.loc = CFrontend_checkers.location_from_decl context if_decl
}
else
None
CTL.False, None
else
None
CTL.False, None
| _ -> assert false in
match decl with
| Clang_ast_t.ObjCImplementationDecl (_, _, _, _, impl_decl_info) ->
match an with
| CTL.Decl (Clang_ast_t.ObjCImplementationDecl (_, _, _, _, impl_decl_info) as decl) ->
let if_decl_opt =
Ast_utils.get_decl_opt_with_decl_ref impl_decl_info.oidi_class_interface in
if Option.is_some if_decl_opt && is_ck_context context decl then
check_interface (Option.get if_decl_opt)
else
None
| _ -> assert false
CTL.False, None
| _ -> CTL.False, None
(** Components should only have one factory method.
@ -197,7 +197,7 @@ let component_with_unconventional_superclass_advice context decl =
it. While its existence is probably not good, I can't think of any reason
there would be factory methods that aren't exposed outside of a class is
not useful if there's only one public factory method. *)
let component_with_multiple_factory_methods_advice context decl =
let component_with_multiple_factory_methods_advice context an =
let is_unavailable_attr attr = match attr with
| Clang_ast_t.UnavailableAttr _ -> true
| _ -> false in
@ -214,7 +214,7 @@ let component_with_multiple_factory_methods_advice context decl =
| Clang_ast_t.ObjCInterfaceDecl (decl_info, _, decls, _, _) ->
let factory_methods = IList.filter (is_available_factory_method if_decl) decls in
if (IList.length factory_methods) > 1 then
Some {
CTL.True, Some {
CIssue.issue = CIssue.Component_with_multiple_factory_methods;
CIssue.description = "Avoid Overrides";
CIssue.suggestion =
@ -223,16 +223,16 @@ let component_with_multiple_factory_methods_advice context decl =
CIssue.loc = CFrontend_checkers.location_from_dinfo context decl_info
}
else
None
CTL.False, None
| _ -> assert false in
match decl with
| Clang_ast_t.ObjCImplementationDecl (_, _, _, _, impl_decl_info) ->
match an with
| CTL.Decl (Clang_ast_t.ObjCImplementationDecl (_, _, _, _, impl_decl_info) as decl) ->
let if_decl_opt =
Ast_utils.get_decl_opt_with_decl_ref impl_decl_info.oidi_class_interface in
(match if_decl_opt with
| Some d when is_ck_context context decl -> check_interface d
| _ -> None)
| _ -> assert false
| _ -> CTL.False, None)
| _ -> CTL.False, None
let in_ck_class (context: CLintersContext.context) =
Option.map_default is_component_or_controller_descendant_impl false context.current_objc_impl
@ -247,7 +247,7 @@ let in_ck_class (context: CLintersContext.context) =
relies on other threads (dispatch_sync). Other side-effects, like reading
of global variables, is not checked by this analyzer, although still an
infraction of the rule. *)
let rec component_initializer_with_side_effects_advice
let rec _component_initializer_with_side_effects_advice
(context: CLintersContext.context) call_stmt =
let condition =
in_ck_class context
@ -258,7 +258,7 @@ let rec component_initializer_with_side_effects_advice
if condition then
match call_stmt with
| Clang_ast_t.ImplicitCastExpr (_, stmt :: _, _, _) ->
component_initializer_with_side_effects_advice context stmt
_component_initializer_with_side_effects_advice context stmt
| Clang_ast_t.DeclRefExpr (_, _, _, decl_ref_expr_info) ->
let refs = [decl_ref_expr_info.drti_decl_ref;
decl_ref_expr_info.drti_found_decl_ref] in
@ -266,15 +266,23 @@ let rec component_initializer_with_side_effects_advice
| Some "dispatch_after"
| Some "dispatch_async"
| Some "dispatch_sync" ->
Some {
CTL.True, Some {
CIssue.issue = CIssue.Component_initializer_with_side_effects;
CIssue.description = "No Side-effects";
CIssue.suggestion = Some "Your +new method should not modify any \
global variables or global state.";
CIssue.loc = CFrontend_checkers.location_from_stmt context call_stmt
}
| _ -> None)
| _ ->
CTL.False, None)
| _->
None
CTL.False, None
else
None
CTL.False, None
let component_initializer_with_side_effects_advice
(context: CLintersContext.context) an =
match an with
| CTL.Stmt (CallExpr (_, called_func_stmt :: _, _)) ->
_component_initializer_with_side_effects_advice context called_func_stmt
| _ -> CTL.False, None (* only to be called in CallExpr *)

@ -15,16 +15,16 @@
val contains_ck_impl : Clang_ast_t.decl list -> bool
val mutable_local_vars_advice :
CLintersContext.context -> Clang_ast_t.decl -> CIssue.issue_desc option
CLintersContext.context -> CTL.ast_node -> CTL.t * CIssue.issue_desc option
val component_factory_function_advice :
CLintersContext.context -> Clang_ast_t.decl -> CIssue.issue_desc option
CLintersContext.context -> CTL.ast_node -> CTL.t * CIssue.issue_desc option
val component_with_unconventional_superclass_advice :
CLintersContext.context -> Clang_ast_t.decl -> CIssue.issue_desc option
CLintersContext.context -> CTL.ast_node -> CTL.t * CIssue.issue_desc option
val component_with_multiple_factory_methods_advice :
CLintersContext.context -> Clang_ast_t.decl -> CIssue.issue_desc option
CLintersContext.context -> CTL.ast_node -> CTL.t * CIssue.issue_desc option
val component_initializer_with_side_effects_advice :
CLintersContext.context -> Clang_ast_t.stmt -> CIssue.issue_desc option
CLintersContext.context -> CTL.ast_node -> CTL.t * CIssue.issue_desc option

@ -36,15 +36,24 @@ let location_from_decl lctx dec =
CLocation.get_sil_location_from_range lctx.CLintersContext.translation_unit_context
info.Clang_ast_t.di_source_range true
let decl_name dec =
match Clang_ast_proj.get_named_decl_tuple dec with
| Some (_, n) -> n.Clang_ast_t.ni_name
| None -> ""
let location_from_an lcxt an =
match an with
| CTL.Stmt st -> location_from_stmt lcxt st
| CTL.Decl d -> location_from_decl lcxt d
let ivar_name stmt =
let decl_name_from_an an =
match an with
| CTL.Decl dec ->
(match Clang_ast_proj.get_named_decl_tuple dec with
| Some (_, n) -> n.Clang_ast_t.ni_name
| None -> "")
| _ -> ""
let ivar_name an =
let open Clang_ast_t in
match stmt with
| ObjCIvarRefExpr (_, _, _, rei) ->
match an with
| CTL.Stmt (ObjCIvarRefExpr (_, _, _, rei)) ->
let dr_ref = rei.ovrei_decl_ref in
let ivar_pointer = dr_ref.dr_decl_pointer in
(match Ast_utils.get_decl ivar_pointer with
@ -53,6 +62,15 @@ let ivar_name stmt =
| _ -> "")
| _ -> ""
let var_descs_name an =
let capt_refs = match an with
| CTL.Stmt (Clang_ast_t.BlockExpr (_, _ , _, decl)) ->
Predicates.captured_variables_cxx_ref decl
| _ -> [] in
let var_desc vars var_named_decl_info =
vars ^ "'" ^ var_named_decl_info.Clang_ast_t.ni_name ^ "'" in
IList.fold_left var_desc "" capt_refs
(* (is_CallExpr /\ not call_function_named) ||
is_CXXTemporaryObjectExpr || is_CXXMemberCallExpr
@ -75,7 +93,7 @@ let ctl_makes_an_expensive_call () =
ET([ObjCMethodDecl][->Body] EF remove_observer) Or
EH([ObjCImplementationDecl, ObjCProtocolDecl] EF remove_observer)
*)
let ctl_ns_notification lctx decl =
let ctl_ns_notification_warning lctx an =
let open CTL in
let exists_method_calling_addObserver =
EF (None, (Atomic ("call_method", ["addObserver:selector:name:object:"]))) in
@ -97,20 +115,21 @@ let ctl_ns_notification lctx decl =
ET(["ObjCImplementationDecl"; "ObjCProtocolDecl"], None,
Or(remove_observer_in_method ,
EH(["ObjCImplementationDecl"; "ObjCProtocolDecl"], remove_observer_in_method))) in
let condition = Not (Implies (eventually_addObserver, eventually_removeObserver)) in
let condition = InNode (["ObjCImplementationDecl"; "ObjCProtocolDecl"],
Not (Implies (eventually_addObserver, eventually_removeObserver))) in
let issue_desc = {
CIssue.issue = CIssue.Registered_observer_being_deallocated;
CIssue.description =
Localise.registered_observer_being_deallocated_str CFrontend_config.self;
CIssue.suggestion =
Some "Consider removing the object from the notification center before its deallocation.";
CIssue.loc = location_from_decl lctx decl;
CIssue.loc = location_from_an lctx an;
} in
condition, issue_desc
condition, Some issue_desc
(* BAD_POINTER_COMPARISON: Fires whenever a NSNumber is dangerously coerced to
a boolean in a comparison *)
let ctl_bad_pointer_comparison_warning lctx stmt =
let ctl_bad_pointer_comparison_warning lctx an =
let open CTL in
let is_binop = Atomic ("is_stmt", ["BinaryOperator"]) in
let is_binop_eq = Atomic ("is_binop_with_kind", ["EQ"]) in
@ -127,8 +146,9 @@ let ctl_bad_pointer_comparison_warning lctx stmt =
*)
let p = Or (is_expr_with_cleanups, Or (is_implicit_cast_expr, Or (is_binop, is_unop_lnot))) in
let p' = And (Not is_binop_neq, p) in
let condition = ETX (["IfStmt"; "ForStmt"; "WhileStmt"; "ConditionalOperator"], Some Cond,
EU (None, p', is_nsnumber)) in
let etx = ETX (["IfStmt"; "ForStmt"; "WhileStmt"; "ConditionalOperator"], Some Cond,
EU (None, p', is_nsnumber)) in
let condition = InNode (["IfStmt"; "ForStmt"; "WhileStmt"; "ConditionalOperator"], etx) in
let issue_desc =
{ CIssue.
issue = CIssue.Bad_pointer_comparison;
@ -137,12 +157,12 @@ let ctl_bad_pointer_comparison_warning lctx stmt =
Some ("Did you mean to compare against the unboxed value instead? " ^
"Please either explicitly compare the NSNumber instance to nil, " ^
"or use one of the NSNumber accessors before the comparison.");
loc = location_from_stmt lctx stmt
loc = location_from_an lctx an
} in
condition, issue_desc
condition, Some issue_desc
(* name_contains_delegate AND not name_contains_queue AND is_strong_property *)
let ctl_strong_delegate lctx dec =
let ctl_strong_delegate_warning lctx an =
let open CTL in
let name_contains_delegate =
Atomic ("property_name_contains_word", ["delegate"]) in
@ -150,22 +170,22 @@ let ctl_strong_delegate lctx dec =
Not(Atomic ("property_name_contains_word", ["queue"])) in
let is_strong_property =
Atomic("is_strong_property", []) in
let condition = ET (["ObjCPropertyDecl"], None, And (name_contains_delegate,
And (name_does_not_contains_queue,
is_strong_property))) in
let condition = InNode (["ObjCPropertyDecl"], And (name_contains_delegate,
And (name_does_not_contains_queue,
is_strong_property))) in
let issue_desc = {
CIssue.issue = CIssue.Strong_delegate_warning;
CIssue.description = Printf.sprintf
"Property or ivar %s declared strong" (decl_name dec);
"Property or ivar %s declared strong" (decl_name_from_an an);
CIssue.suggestion = Some "In general delegates should be declared weak or assign";
CIssue.loc = location_from_decl lctx dec
CIssue.loc = location_from_an lctx an
} in
condition, issue_desc
condition, Some issue_desc
(* (is_ObjC || is_Objc++) /\ is_global_var /\ not is_const_var /\
ET([VarDecl][->InitExpr] EF ctl_makes_an_expensive_call)
*)
let ctl_global_var_init_with_calls_warning lctx decl =
let ctl_global_var_init_with_calls_warning lctx an =
let open CTL in
let ctl_is_global_var =
And (And (Atomic ("is_objc_extension", []), Atomic ("is_global_var", [])),
@ -173,125 +193,70 @@ let ctl_global_var_init_with_calls_warning lctx decl =
let ctl_is_initialized_with_expensive_call =
ET(["VarDecl"], Some InitExpr, EF (None, (ctl_makes_an_expensive_call ()))) in
let condition =
ET (["VarDecl"], None, And (ctl_is_global_var, ctl_is_initialized_with_expensive_call)) in
InNode (["VarDecl"], And (ctl_is_global_var, ctl_is_initialized_with_expensive_call)) in
let issue_desc = {
CIssue.issue = CIssue.Global_variable_initialized_with_function_or_method_call;
CIssue.description = Printf.sprintf
"Global variable %s is initialized using a function or method call"
(decl_name decl);
(decl_name_from_an an);
CIssue.suggestion = Some
"If the function/method call is expensive, it can affect the starting time of the app.";
CIssue.loc = location_from_decl lctx decl
CIssue.loc = location_from_an lctx an
} in
condition, issue_desc
condition, Some issue_desc
(* is_assign_property AND is_property_pointer_type *)
let ctl_assign_pointer_warning lctx decl =
let ctl_assign_pointer_warning lctx an =
let open CTL in
let condition = ET(["ObjCPropertyDecl"], None,
And (Atomic ("is_assign_property", []),
Atomic ("is_property_pointer_type", []))) in
let condition = InNode(["ObjCPropertyDecl"],
And (Atomic ("is_assign_property", []),
Atomic ("is_property_pointer_type", []))) in
let issue_desc =
{ CIssue.issue = CIssue.Assign_pointer_warning;
CIssue.description =
Printf.sprintf
"Property `%s` is a pointer type marked with the `assign` attribute"
(decl_name decl);
(decl_name_from_an an);
CIssue.suggestion = Some "Use a different attribute like `strong` or `weak`.";
CIssue.loc = location_from_decl lctx decl
CIssue.loc = location_from_an lctx an
} in
condition, issue_desc
condition, Some issue_desc
(*
not context_in_synchronized_block /\ not is_method_property_accessor_of_ivar
/\ not is_objc_constructor /\ not is_objc_dealloc
*)
let ctl_direct_atomic_property_access_warning lctx stmt =
let ctl_direct_atomic_property_access_warning lctx an =
let open CTL in
let condition = ET (["ObjCIvarRefExpr"], None,
And (And (And (And (Not (Atomic ("context_in_synchronized_block", [])),
Atomic("is_ivar_atomic", [])),
Not (Atomic ("is_method_property_accessor_of_ivar", []))),
Not (Atomic ("is_objc_constructor", []))),
Not (Atomic ("is_objc_dealloc", [])))) in
let condition = InNode (["ObjCIvarRefExpr"],
And (And (And (And (Not (Atomic ("context_in_synchronized_block", [])),
Atomic("is_ivar_atomic", [])),
Not (Atomic ("is_method_property_accessor_of_ivar", []))),
Not (Atomic ("is_objc_constructor", []))),
Not (Atomic ("is_objc_dealloc", [])))) in
let issue_desc = {
CIssue.issue = CIssue.Direct_atomic_property_access;
CIssue.description = Printf.sprintf
"Direct access to ivar %s of an atomic property" (ivar_name stmt);
"Direct access to ivar %s of an atomic property" (ivar_name an);
CIssue.suggestion =
Some "Accessing an ivar of an atomic property makes the property nonatomic";
CIssue.loc = location_from_stmt lctx stmt
CIssue.loc = location_from_an lctx an
} in
condition, issue_desc
condition, Some issue_desc
let ctl_captured_cxx_ref_in_objc_block_warning lctx stmt =
let ctl_captured_cxx_ref_in_objc_block_warning lctx an =
(* Fire if the list of captured references is not empty *)
let open CTL in
let condition = ET (["BlockDecl"], None, Atomic ("captures_cxx_references", [])) in
let condition = InNode (["BlockDecl"], Atomic ("captures_cxx_references", [])) in
let issue_desc = {
CIssue.issue = CIssue.Cxx_reference_captured_in_objc_block;
CIssue.description = Printf.sprintf
"C++ Reference variable(s) %s captured by Objective-C block"
(Predicates.var_descs_name stmt);
(var_descs_name an);
CIssue.suggestion = Some ("C++ References are unmanaged and may be invalid " ^
"by the time the block executes.");
CIssue.loc = match stmt with
| Clang_ast_t.BlockExpr (_, _ , _, decl) -> location_from_decl lctx decl
| _ -> location_from_stmt lctx stmt;
CIssue.loc = match an with
| Stmt (Clang_ast_t.BlockExpr (_, _ , _, decl)) -> location_from_an lctx (Decl decl)
| _ -> location_from_an lctx an;
} in
condition, issue_desc
(* === Warnings on properties === *)
(* Assing Pointer Warning: a property with a pointer type should not be declared `assign` *)
let assign_pointer_warning lctx decl =
let open CTL in
let condition, issue_desc = ctl_assign_pointer_warning lctx decl in
if CTL.eval_formula condition (Decl decl) lctx then
Some issue_desc
else None
(* Strong Delegate Warning: a property with name delegate should not be declared strong *)
let strong_delegate_warning lctx decl =
let condition, issue_desc = ctl_strong_delegate lctx decl in
if CTL.eval_formula condition (Decl decl) lctx then
Some issue_desc
else None
(* GLOBAL_VARIABLE_INITIALIZED_WITH_FUNCTION_OR_METHOD_CALL warning: *)
(* a global variable initialization should not *)
(* contain calls to functions or methods as these can be expensive an delay the starting time *)
(* of an app *)
let global_var_init_with_calls_warning lctx decl =
let condition, issue_desc = ctl_global_var_init_with_calls_warning lctx decl in
if CTL.eval_formula condition (CTL.Decl decl) lctx then
Some issue_desc
else None
(* Direct Atomic Property access:
a property declared atomic should not be accessed directly via its ivar *)
let direct_atomic_property_access_warning lctx stmt =
let condition, issue_desc = ctl_direct_atomic_property_access_warning lctx stmt in
if CTL.eval_formula condition (CTL.Stmt stmt) lctx then
Some issue_desc
else None
(* CXX_REFERENCE_CAPTURED_IN_OBJC_BLOCK: C++ references
should not be captured in blocks. *)
let captured_cxx_ref_in_objc_block_warning lctx stmt =
let condition, issue_desc = ctl_captured_cxx_ref_in_objc_block_warning lctx stmt in
if CTL.eval_formula condition (CTL.Stmt stmt) lctx then
Some issue_desc
else None
let checker_NSNotificationCenter lctx dec =
let condition, issue_desc = ctl_ns_notification lctx dec in
if CTL.eval_formula condition (CTL.Decl dec) lctx then
Some issue_desc
else None
let bad_pointer_comparison_warning lctx stmt =
let condition, issue_desc = ctl_bad_pointer_comparison_warning lctx stmt in
if CTL.eval_formula condition (CTL.Stmt stmt) lctx then
Some issue_desc
else None
condition, Some issue_desc

@ -12,36 +12,36 @@ open! Utils
(* === Warnings on properties === *)
(* Strong Delegate Warning: a property with name delegate should not be declared strong *)
val strong_delegate_warning :
CLintersContext.context -> Clang_ast_t.decl -> CIssue.issue_desc option
val ctl_strong_delegate_warning :
CLintersContext.context -> CTL.ast_node -> CTL.t * CIssue.issue_desc option
(* Assing Pointer Warning: a property with a pointer type should not be declared `assign` *)
val assign_pointer_warning :
CLintersContext.context -> Clang_ast_t.decl -> CIssue.issue_desc option
val ctl_assign_pointer_warning :
CLintersContext.context -> CTL.ast_node -> CTL.t * CIssue.issue_desc option
(* 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.stmt -> CIssue.issue_desc option
val ctl_direct_atomic_property_access_warning :
CLintersContext.context -> CTL.ast_node -> CTL.t * CIssue.issue_desc option
(* CXX_REFERENCE_CAPTURED_IN_OBJC_BLOCK: C++ references
should not be captured in blocks. *)
val captured_cxx_ref_in_objc_block_warning :
CLintersContext.context -> Clang_ast_t.stmt -> CIssue.issue_desc option
val ctl_captured_cxx_ref_in_objc_block_warning :
CLintersContext.context -> CTL.ast_node -> CTL.t * CIssue.issue_desc option
val bad_pointer_comparison_warning :
CLintersContext.context -> Clang_ast_t.stmt -> CIssue.issue_desc option
val ctl_bad_pointer_comparison_warning :
CLintersContext.context -> CTL.ast_node -> CTL.t * CIssue.issue_desc option
(* REGISTERED_OBSERVER_BEING_DEALLOCATED: an object is registered in a notification center
but not removed before deallocation *)
val checker_NSNotificationCenter :
CLintersContext.context -> Clang_ast_t.decl -> CIssue.issue_desc option
val ctl_ns_notification_warning :
CLintersContext.context -> CTL.ast_node -> CTL.t * CIssue.issue_desc option
(* GLOBAL_VARIABLE_INITIALIZED_WITH_FUNCTION_OR_METHOD_CALL warning: a global variable initialization should not *)
(* contain calls to functions or methods as these can be expensive an delay the starting time *)
(* of a program *)
val global_var_init_with_calls_warning :
CLintersContext.context -> Clang_ast_t.decl -> CIssue.issue_desc option
val ctl_global_var_init_with_calls_warning :
CLintersContext.context -> CTL.ast_node -> CTL.t * CIssue.issue_desc option
val location_from_stmt :
CLintersContext.context -> Clang_ast_t.stmt -> Location.t

@ -49,7 +49,7 @@ let parse_ctl_file filename =
let rec do_frontend_checks_stmt (context:CLintersContext.context) stmt =
let open Clang_ast_t in
let context' = CFrontend_errors.run_frontend_checkers_on_stmt context stmt in
let context' = CFrontend_errors.run_frontend_checkers_on_an context (CTL.Stmt stmt) in
let do_all_checks_on_stmts stmt =
(match stmt with
| DeclStmt (_, _, decl_list) ->
@ -102,7 +102,7 @@ and do_frontend_checks_decl (context: CLintersContext.context) decl =
| None -> ());
context'
| _ -> context) in
let context'' = CFrontend_errors.run_frontend_checkers_on_decl context' decl in
let context'' = CFrontend_errors.run_frontend_checkers_on_an context' (CTL.Decl decl) in
let context_with_orig_current_method =
{context'' with CLintersContext.current_method = context.current_method } in
match Clang_ast_proj.get_decl_context_tuple decl with

@ -12,68 +12,25 @@ 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
let decl_checkers_list = [CFrontend_checkers.ctl_strong_delegate_warning;
CFrontend_checkers.ctl_assign_pointer_warning;
CFrontend_checkers.ctl_ns_notification_warning;
CFrontend_checkers.ctl_global_var_init_with_calls_warning;
ComponentKit.component_with_unconventional_superclass_advice;
ComponentKit.mutable_local_vars_advice;
ComponentKit.component_factory_function_advice;
ComponentKit.component_with_multiple_factory_methods_advice;]
(* 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 ObjCProtocol decls *)
let objc_protocol_checker_list = [CFrontend_checkers.checker_NSNotificationCenter]
(* Invocation of checker belonging to objc_protocol_checker_list *)
let checkers_for_objc_protocol decl checker context =
checker context decl
let stmt_checkers_list = [CFrontend_checkers.ctl_direct_atomic_property_access_warning;
CFrontend_checkers.ctl_captured_cxx_ref_in_objc_block_warning;
CFrontend_checkers.ctl_bad_pointer_comparison_warning;
ComponentKit.component_initializer_with_side_effects_advice;]
(* List of checkers running on ObjCImpl decls *)
let objc_impl_checker_list = [CFrontend_checkers.checker_NSNotificationCenter;
ComponentKit.component_with_multiple_factory_methods_advice;
ComponentKit.component_with_unconventional_superclass_advice]
(* Invocation of checker belonging to objc_impl_checker_list *)
let checkers_for_objc_impl decl checker context =
checker context decl
let call_expr_checker_list = [ComponentKit.component_initializer_with_side_effects_advice]
(* Invocation of checker belonging to call_expr_checker_list *)
let checkers_for_call_expr stmt checker context =
checker context stmt
(* 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 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
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 translation_unit_context method_decl_opt =
let procname = match method_decl_opt with
@ -97,75 +54,25 @@ let log_frontend_issue translation_unit_context method_decl_opt key issue_desc =
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 =
let invoke_set_of_checkers_an an context =
let checkers, key = match an with
| CTL.Decl dec -> decl_checkers_list, Ast_utils.generate_key_decl dec
| CTL.Stmt st -> stmt_checkers_list, Ast_utils.generate_key_stmt st in
IList.iter (fun checker ->
match f checker context with
| Some issue_desc ->
log_frontend_issue context.CLintersContext.translation_unit_context
context.CLintersContext.current_method key issue_desc
| None -> ()) checkers
let condition, issue_desc_opt = checker context an in
match CTL.eval_formula condition an context, issue_desc_opt with
| true, Some issue_desc -> log_frontend_issue context.CLintersContext.translation_unit_context
context.CLintersContext.current_method key issue_desc
| _, _ -> ()) 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 _ | ConditionalOperator _ | ForStmt _ | WhileStmt _ ->
let call_checker = checker_for_if_stmt instr in
let key = Ast_utils.generate_key_stmt instr in
invoke_set_of_checkers call_checker context key if_stmt_checker_list;
context
| CallExpr (_, called_func_stmt :: _, _) ->
let call_checker = checkers_for_call_expr called_func_stmt in
let key = Ast_utils.generate_key_stmt called_func_stmt in
invoke_set_of_checkers call_checker context key call_expr_checker_list;
context
| ObjCAtSynchronizedStmt _ ->
{ context with CLintersContext.in_synchronized_block = true }
| _ -> context
let run_frontend_checkers_on_decl (context: CLintersContext.context) dec =
let run_frontend_checkers_on_an (context: CLintersContext.context) an =
let open Clang_ast_t in
match dec with
| ObjCImplementationDecl _ ->
let call_objc_impl_checker = checkers_for_objc_impl dec in
let key = Ast_utils.generate_key_decl dec in
let context' = {context with current_objc_impl = Some dec} in
invoke_set_of_checkers call_objc_impl_checker context' key objc_impl_checker_list;
context'
| ObjCProtocolDecl _ ->
let call_objc_protocol_checker = checkers_for_objc_protocol dec in
let key = Ast_utils.generate_key_decl dec in
invoke_set_of_checkers call_objc_protocol_checker context key objc_protocol_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
let context' = match an with
| CTL.Decl (ObjCImplementationDecl _ as dec) ->
{context with current_objc_impl = Some dec}
| CTL.Stmt (ObjCAtSynchronizedStmt _ )->
{ context with CLintersContext.in_synchronized_block = true }
| _ -> context in
invoke_set_of_checkers_an an context';
context'

@ -12,10 +12,6 @@ open! Utils
(* Module for warnings detected at translation time by the frontend *)
(* Run frontend checkers on a statement *)
val run_frontend_checkers_on_stmt :
CLintersContext.context -> Clang_ast_t.stmt -> CLintersContext.context
(* Run frontend checkers on a declaration *)
val run_frontend_checkers_on_decl : CLintersContext.context -> Clang_ast_t.decl ->
CLintersContext.context
(* Run frontend checkers on an AST node *)
val run_frontend_checkers_on_an :
CLintersContext.context -> CTL.ast_node -> CLintersContext.context

@ -41,14 +41,6 @@ let captured_variables_cxx_ref dec =
| _ -> [] in
IList.fold_left capture_var_is_cxx_ref [] captured_vars
let var_descs_name stmt =
let capt_refs = match stmt with
| Clang_ast_t.BlockExpr (_, _ , _, decl) ->
captured_variables_cxx_ref decl
| _ -> [] in
let var_desc vars var_named_decl_info =
vars ^ "'" ^ var_named_decl_info.Clang_ast_t.ni_name ^ "'" in
IList.fold_left var_desc "" capt_refs
type t = string * string list (* (name, [param1,...,paramK]) *)

@ -9,7 +9,7 @@
type t = string * string list (* (name, [param1,...,paramK]) *)
val var_descs_name : Clang_ast_t.stmt -> string (* Helper function *)
val captured_variables_cxx_ref : Clang_ast_t.decl -> Clang_ast_t.named_decl_info list
val call_method : string -> Clang_ast_t.stmt -> bool

Loading…
Cancel
Save