diff --git a/infer/src/clang/ComponentKit.ml b/infer/src/clang/ComponentKit.ml index 95f8fc473..5030f6e2c 100644 --- a/infer/src/clang/ComponentKit.ml +++ b/infer/src/clang/ComponentKit.ml @@ -12,52 +12,16 @@ open !Utils (** Recursively go up the inheritance hierarchy of a given ObjCInterfaceDecl. (Returns false on decls other than that one.) *) -let rec is_component_if decl = - match decl with - | Some Clang_ast_t.ObjCInterfaceDecl (_, ndi, _, _, _)-> - let open CFrontend_config in - let whitelist = [ckcomponent_cl] in - let blacklist = [nsobject_cl; nsproxy_cl] in - let in_list some_list = IList.mem string_equal ndi.Clang_ast_t.ni_name some_list in - if in_list whitelist then - true - else if in_list blacklist then - false - else - (match Ast_utils.get_super_if decl with - | Some super_decl -> - is_component_if (Some super_decl) - | None -> false) - | _ -> false - - -(** Recursively go up the inheritance hierarchy of a given ObjCInterfaceDecl. - (Returns false on decls other than that one.) *) -let rec is_component_or_controller_if decl = - match decl with - | Clang_ast_t.ObjCInterfaceDecl (_, ndi, _, _, _)-> - let open CFrontend_config in - let whitelist = [ckcomponent_cl; ckcomponentcontroller_cl] in - let blacklist = [nsobject_cl; nsproxy_cl] in - let in_list some_list = IList.mem string_equal ndi.Clang_ast_t.ni_name some_list in - if in_list whitelist then - true - else if in_list blacklist then - false - else - (match Ast_utils.get_super_if (Some decl) with - | Some super_decl -> - is_component_or_controller_if super_decl - | None -> false) - | _ -> false +let is_component_or_controller_if decl = + let open CFrontend_config in + Ast_utils.is_objc_if_descendant decl [ckcomponent_cl; ckcomponentcontroller_cl] (** True if it's an objc class impl that extends from CKComponent or CKComponentController, false otherwise *) let rec is_component_or_controller_descendant_impl decl = match decl with | Clang_ast_t.ObjCImplementationDecl _ -> - let super_if = Ast_utils.get_super_if (Some decl) in - Option.map_default is_component_or_controller_if false super_if + is_component_or_controller_if (Ast_utils.get_super_if (Some decl)) | Clang_ast_t.LinkageSpecDecl (_, decl_list, _) -> contains_ck_impl decl_list | _ -> false @@ -145,6 +109,8 @@ let mutable_local_vars_advice context decl = Any static function that returns a subclass of CKComponent will be flagged. *) let component_factory_function_advice context decl = + let is_component_if decl = + Ast_utils.is_objc_if_descendant decl [CFrontend_config.ckcomponent_cl] in let rec type_ptr_to_objc_if type_ptr = let typ_opt = Ast_utils.get_desugared_type type_ptr in diff --git a/infer/src/clang/cFrontend_utils.ml b/infer/src/clang/cFrontend_utils.ml index 01950eff0..06616e287 100644 --- a/infer/src/clang/cFrontend_utils.ml +++ b/infer/src/clang/cFrontend_utils.ml @@ -442,6 +442,23 @@ struct let file_opt = (fst decl_info.Clang_ast_t.di_source_range).Clang_ast_t.sl_file in opt_equal string_equal file_opt Config.source_file && Option.is_some file_opt + let rec is_objc_if_descendant if_decl ancestors = + match if_decl with + | Some Clang_ast_t.ObjCInterfaceDecl (_, ndi, _, _, _)-> + let open CFrontend_config in + let blacklist = [nsobject_cl; nsproxy_cl] in + let in_list some_list = IList.mem string_equal ndi.Clang_ast_t.ni_name some_list in + if in_list ancestors then + true + else if in_list blacklist then + false + else + (match get_super_if if_decl with + | Some super_decl -> + is_objc_if_descendant (Some super_decl) ancestors + | None -> false) + | _ -> false + (* let rec getter_attribute_opt attributes = match attributes with diff --git a/infer/src/clang/cFrontend_utils.mli b/infer/src/clang/cFrontend_utils.mli index 47b9f4357..5bd63ad15 100644 --- a/infer/src/clang/cFrontend_utils.mli +++ b/infer/src/clang/cFrontend_utils.mli @@ -160,6 +160,14 @@ sig to the parent decl. *) val is_in_main_file : Clang_ast_t.decl -> bool + (** Recursively go up the inheritance hierarchy of a given ObjCInterfaceDecl. + Returns true if the passed in decl is an objc interface decl that's an + eventual descendant of one of the classes passed in. + Ancestors param is a list of strings that represent the class names. + Will short-circuit on NSObject and NSProxy since those are known to be + common base classes. *) + val is_objc_if_descendant : Clang_ast_t.decl option -> (string) list -> bool + end module General_utils :