From 275f4c3a8c8ad568af52e4d5aa00928b65aac62c Mon Sep 17 00:00:00 2001 From: Brandon Kieft Date: Fri, 4 May 2018 07:30:00 -0700 Subject: [PATCH] Add predicates to check for protocols Reviewed By: dulmarod Differential Revision: D7867975 fbshipit-source-id: 20d599d --- infer/src/clang/cPredicates.ml | 16 +++++++++++++++ infer/src/clang/cPredicates.mli | 12 +++++++++++ infer/src/clang/cTL.ml | 4 ++++ .../al_definitions/linters_example.al | 20 +++++++++++++++++++ .../objc/linters-for-test-only/issues.exp | 3 +++ 5 files changed, 55 insertions(+) diff --git a/infer/src/clang/cPredicates.ml b/infer/src/clang/cPredicates.ml index 5a8e37fdc..d40a52cc8 100644 --- a/infer/src/clang/cPredicates.ml +++ b/infer/src/clang/cPredicates.ml @@ -281,6 +281,14 @@ let is_objc_category_named an re = is_objc_category_interface_named an re || is_objc_category_implementation_named an re +let is_objc_protocol_named an re = + match an with + | Ctl_parser_types.Decl (Clang_ast_t.ObjCProtocolDecl _) -> + declaration_has_name an re + | _ -> + false + + let is_objc_method_named an name = match an with | Ctl_parser_types.Decl (Clang_ast_t.ObjCMethodDecl _) -> @@ -763,6 +771,14 @@ let is_in_objc_category_named context name = false +let is_in_objc_protocol_named context name = + match context.CLintersContext.current_objc_protocol with + | Some protocol -> + is_objc_protocol_named (Decl protocol) name + | None -> + false + + let captures_cxx_references an = List.length (captured_variables_cxx_ref an) > 0 let is_binop_with_kind an alexp_kind = diff --git a/infer/src/clang/cPredicates.mli b/infer/src/clang/cPredicates.mli index bb571d874..905dcad9d 100644 --- a/infer/src/clang/cPredicates.mli +++ b/infer/src/clang/cPredicates.mli @@ -187,6 +187,12 @@ val is_objc_category_implementation_on_subclass_of : * inherits from a class whose name matches the provided REGEXP *) +val is_objc_protocol_named : Ctl_parser_types.ast_node -> ALVar.alexp -> bool +(** + * Checks if the current node is an ObjCProtocolDecl node + * whose name matches the provided REGEXP + *) + val is_objc_method_named : Ctl_parser_types.ast_node -> ALVar.alexp -> bool (** * Checks if the current node is an ObjCMethodDecl node @@ -281,6 +287,12 @@ val is_in_objc_category_named : CLintersContext.context -> ALVar.alexp -> bool * ObjCCategoryImplDecl node whose name matches the provided REGEXP *) +val is_in_objc_protocol_named : CLintersContext.context -> ALVar.alexp -> bool +(** + * Checks if the current node is a subnode of an ObjCProtocolDecl + * node whose name matches the provided REGEXP + *) + val is_in_objc_method : CLintersContext.context -> ALVar.alexp -> bool (** * Checks if the current node, or a parent node, is an ObjCMethodDecl node diff --git a/infer/src/clang/cTL.ml b/infer/src/clang/cTL.ml index d92fb1975..138a03a26 100644 --- a/infer/src/clang/cTL.ml +++ b/infer/src/clang/cTL.ml @@ -1044,6 +1044,8 @@ let rec eval_Atomic pred_name_ args an lcxt = CPredicates.is_in_objc_category_implementation_named lcxt name | "is_in_objc_category_named", [name], _ -> CPredicates.is_in_objc_category_named lcxt name + | "is_in_objc_protocol_named", [name], _ -> + CPredicates.is_in_objc_protocol_named lcxt name | "is_ivar_atomic", [], an -> CPredicates.is_ivar_atomic an | "is_method_property_accessor_of_ivar", [], an -> @@ -1080,6 +1082,8 @@ let rec eval_Atomic pred_name_ args an lcxt = CPredicates.is_objc_category_implementation_on_subclass_of an name | "is_objc_category_on_subclass_of", [name], an -> CPredicates.is_objc_category_on_subclass_of an name + | "is_objc_protocol_named", [name], an -> + CPredicates.is_objc_protocol_named an name | "is_objc_method_named", [name], an -> CPredicates.is_objc_method_named an name | "is_objc_method_overriding", [], an -> diff --git a/infer/tests/codetoanalyze/objc/linters-for-test-only/al_definitions/linters_example.al b/infer/tests/codetoanalyze/objc/linters-for-test-only/al_definitions/linters_example.al index c2ac4e12e..d326eff00 100644 --- a/infer/tests/codetoanalyze/objc/linters-for-test-only/al_definitions/linters_example.al +++ b/infer/tests/codetoanalyze/objc/linters-for-test-only/al_definitions/linters_example.al @@ -576,6 +576,17 @@ DEFINE-CHECKER TEST_IF_METHOD_IS_IN_CATEGORY_ON_SUBCLASS_OF = { }; +DEFINE-CHECKER TEST_IF_METHOD_IS_IN_PROTOCOL_NAMED = { + + SET report_when = + WHEN + is_in_objc_protocol_named("MyBaseClassProtocol") + HOLDS-IN-NODE ObjCMethodDecl; + + SET message = "Method %name% is in the protocol named MyBaseClassProtocol."; + +}; + DEFINE-CHECKER TEST_IF_IS_CATEGORY_INTERFACE_NAMED = { SET report_when = @@ -676,6 +687,15 @@ DEFINE-CHECKER TEST_IF_IS_CLASS_NAMED = { }; +DEFINE-CHECKER TEST_IF_IS_PROTOCOL_NAMED = { + + SET report_when = + is_objc_protocol_named("MyBaseClassProtocol"); + + SET message = "Node is a protocol named MyBaseClassProtocol."; + +}; + DEFINE-CHECKER TEST_IF_IS_METHOD_NAMED = { SET report_when = diff --git a/infer/tests/codetoanalyze/objc/linters-for-test-only/issues.exp b/infer/tests/codetoanalyze/objc/linters-for-test-only/issues.exp index 5c70cbb5a..40f0d50d5 100644 --- a/infer/tests/codetoanalyze/objc/linters-for-test-only/issues.exp +++ b/infer/tests/codetoanalyze/objc/linters-for-test-only/issues.exp @@ -7,6 +7,7 @@ codetoanalyze/objc/linters-for-test-only/CallingAMethodWithSelf.m, CallingAMetho codetoanalyze/objc/linters-for-test-only/CallingAMethodWithSelf.m, CallingAMethodWithSelf_testView, 44, TEST_IS_METHOD_EXPOSED, WARNING, [] codetoanalyze/objc/linters-for-test-only/CallingAMethodWithSelf.m, CallingAMethodWithSelf_testView, 44, TEST_IS_OVERRIDING_METHOD, WARNING, [] codetoanalyze/objc/linters-for-test-only/CallingAMethodWithSelf.m, CallingAMethodWithSelf_testView, 45, TEST_VAR_TYPE_CHECK, WARNING, [] +codetoanalyze/objc/linters-for-test-only/GenericTestClass.m, Linters_dummy_method, 7, TEST_IF_IS_PROTOCOL_NAMED, WARNING, [] codetoanalyze/objc/linters-for-test-only/GenericTestClass.m, Linters_dummy_method, 14, TEST_IF_IS_CLASS_NAMED, WARNING, [] codetoanalyze/objc/linters-for-test-only/GenericTestClass.m, Linters_dummy_method, 21, TEST_IF_IS_CATEGORY_INTERFACE_ON_CLASS_NAMED, WARNING, [] codetoanalyze/objc/linters-for-test-only/GenericTestClass.m, Linters_dummy_method, 21, TEST_IF_IS_CATEGORY_ON_CLASS_NAMED, WARNING, [] @@ -24,6 +25,8 @@ codetoanalyze/objc/linters-for-test-only/GenericTestClass.m, Linters_dummy_metho codetoanalyze/objc/linters-for-test-only/GenericTestClass.m, Linters_dummy_method, 134, TEST_IF_IS_CATEGORY_ON_SUBCLASS_OF, WARNING, [] codetoanalyze/objc/linters-for-test-only/GenericTestClass.m, Linters_dummy_method, 140, TEST_IF_IS_CATEGORY_IMPLEMENTATION_ON_SUBCLASS_OF, WARNING, [] codetoanalyze/objc/linters-for-test-only/GenericTestClass.m, Linters_dummy_method, 140, TEST_IF_IS_CATEGORY_ON_SUBCLASS_OF, WARNING, [] +codetoanalyze/objc/linters-for-test-only/GenericTestClass.m, MyBaseClassProtocol_myBaseClassProtocolOptionalMethod, 11, TEST_IF_METHOD_IS_IN_PROTOCOL_NAMED, WARNING, [] +codetoanalyze/objc/linters-for-test-only/GenericTestClass.m, MyBaseClassProtocol_myBaseClassProtocolRequiredMethod, 9, TEST_IF_METHOD_IS_IN_PROTOCOL_NAMED, WARNING, [] codetoanalyze/objc/linters-for-test-only/GenericTestClass.m, MyBaseClass_myBaseClassCategoryMethod, 47, TEST_IF_METHOD_IS_IN_CATEGORY_INTERFACE_NAMED, WARNING, [] codetoanalyze/objc/linters-for-test-only/GenericTestClass.m, MyBaseClass_myBaseClassCategoryMethod, 47, TEST_IF_METHOD_IS_IN_CATEGORY_INTERFACE_ON_CLASS_NAMED, WARNING, [] codetoanalyze/objc/linters-for-test-only/GenericTestClass.m, MyBaseClass_myBaseClassCategoryMethod, 47, TEST_IF_METHOD_IS_IN_CATEGORY_NAMED, WARNING, []