From c9c4adebc242417f9e410abb4ddbe15045d6d2cf Mon Sep 17 00:00:00 2001 From: Dulma Churchill Date: Fri, 29 Nov 2019 02:40:41 -0800 Subject: [PATCH] [AL] Improve the predicate for checking visibility attribute and example rule for checking macro for category implementation Reviewed By: skcho Differential Revision: D18744625 fbshipit-source-id: 10b0c77b5 --- infer/src/al/cPredicates.ml | 16 +++++++------ .../al_definitions/linters_example.al | 23 +++++++++++++++++- .../linters-for-test-only/cat_macro_example.m | 10 ++++++++ .../objc/linters-for-test-only/issues.exp | 24 +++++++++++++------ .../linters-for-test-only/sibling_example.m | 17 +++++++++++++ 5 files changed, 75 insertions(+), 15 deletions(-) diff --git a/infer/src/al/cPredicates.ml b/infer/src/al/cPredicates.ml index 0ba0a8845..d99b8e8d0 100644 --- a/infer/src/al/cPredicates.ml +++ b/infer/src/al/cPredicates.ml @@ -1391,21 +1391,23 @@ let using_namespace an namespace = false -let rec get_decl_attributes_for_callexpr an = +let rec get_decl_attributes an = let open Clang_ast_t in let open Ctl_parser_types in match an with | Stmt (CallExpr (_, func :: _, _)) -> - get_decl_attributes_for_callexpr (Stmt func) + get_decl_attributes (Stmt func) | Stmt (ImplicitCastExpr (_, [stmt], _, _)) -> - get_decl_attributes_for_callexpr (Stmt stmt) + get_decl_attributes (Stmt stmt) | Stmt (DeclRefExpr (_, _, _, drti)) -> ( match CAst_utils.get_decl_opt_with_decl_ref drti.drti_decl_ref with | Some decl -> - let decl_info = Clang_ast_proj.get_decl_tuple decl in - decl_info.di_attributes + get_decl_attributes (Decl decl) | None -> [] ) + | Decl decl -> + let decl_info = Clang_ast_proj.get_decl_tuple decl in + decl_info.di_attributes | _ -> [] @@ -1452,7 +1454,7 @@ let has_visibility_attribute an visibility = | _ -> false ) in - let attributes = get_decl_attributes_for_callexpr an in + let attributes = get_decl_attributes an in match visibility with ALVar.Const vis -> has_visibility_attr attributes vis | _ -> false @@ -1462,7 +1464,7 @@ let has_no_escape_attribute an = let has_used_attribute an = - let attributes = get_decl_attributes_for_callexpr an in + let attributes = get_decl_attributes an in List.exists ~f:(fun attr -> match attr with `UsedAttr _ -> true | _ -> false) attributes 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 8b2097bb4..d8bb58384 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 @@ -932,5 +932,26 @@ DEFINE-CHECKER CAT_DECL_MACRO = { ) HOLDS-IN-NODE ObjCCategoryDecl; - SET message = "A category is defined without the corrsponding macro"; + SET message = "A category is defined without the corresponding macro"; +}; + +DEFINE-CHECKER CAT_IMPL_MACRO = { + + LET is_linkable_var = + has_visibility_attribute("Default") AND + declaration_has_name(REGEXP("Linkable_.*")) AND + has_type("char"); + + LET var_decls = + HOLDS-NEXT WITH-TRANSITION Sibling + (is_node("VarDecl") AND is_linkable_var()); + + SET report_when = + WHEN + NOT ( + is_node("ObjCCategoryImplDecl") + AND-WITH-WITNESSES var_decls() : decl_name_is_contained_in_name_of_decl() + ) HOLDS-IN-NODE ObjCCategoryImplDecl; + + SET message = "A category is implemented without the corresponding macro"; }; \ No newline at end of file diff --git a/infer/tests/codetoanalyze/objc/linters-for-test-only/cat_macro_example.m b/infer/tests/codetoanalyze/objc/linters-for-test-only/cat_macro_example.m index ee33e3e77..84124c4ff 100644 --- a/infer/tests/codetoanalyze/objc/linters-for-test-only/cat_macro_example.m +++ b/infer/tests/codetoanalyze/objc/linters-for-test-only/cat_macro_example.m @@ -17,8 +17,18 @@ int x; extern const void* const OS_WEAK OS_CONCAT(Link_, NAME); \ OS_USED const void* const OS_WEAK OS_CONCAT(Link_, NAME) = &Linkable_##NAME; +#define LINKABLE(NAME) \ + __attribute__((visibility("default"))) char Linkable_##NAME = 'L'; + LINK_REQUIRE(SiblingExample_Cat2); @interface SiblingExample (Cat2) - (void)foo:(int)themeProvider; +@end + +LINKABLE(SiblingExample) +@implementation SiblingExample (Cat2) + +- (void)foo:(int)themeProvider { +} @end 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 c5d2e5b86..207403be2 100644 --- a/infer/tests/codetoanalyze/objc/linters-for-test-only/issues.exp +++ b/infer/tests/codetoanalyze/objc/linters-for-test-only/issues.exp @@ -26,6 +26,7 @@ codetoanalyze/objc/linters-for-test-only/GenericTestClass.m, Linters_dummy_metho codetoanalyze/objc/linters-for-test-only/GenericTestClass.m, Linters_dummy_method, 76, TEST_IF_IS_CATEGORY_INTERFACE_ON_CLASS_NAMED, no_bucket, WARNING, [] codetoanalyze/objc/linters-for-test-only/GenericTestClass.m, Linters_dummy_method, 76, TEST_IF_IS_CATEGORY_NAMED, no_bucket, WARNING, [] codetoanalyze/objc/linters-for-test-only/GenericTestClass.m, Linters_dummy_method, 76, TEST_IF_IS_CATEGORY_ON_CLASS_NAMED, no_bucket, WARNING, [] +codetoanalyze/objc/linters-for-test-only/GenericTestClass.m, Linters_dummy_method, 82, CAT_IMPL_MACRO, no_bucket, WARNING, [] codetoanalyze/objc/linters-for-test-only/GenericTestClass.m, Linters_dummy_method, 82, TEST_IF_IS_CATEGORY_IMPLEMENTATION_NAMED, no_bucket, WARNING, [] codetoanalyze/objc/linters-for-test-only/GenericTestClass.m, Linters_dummy_method, 82, TEST_IF_IS_CATEGORY_IMPLEMENTATION_ON_CLASS_NAMED, no_bucket, WARNING, [] codetoanalyze/objc/linters-for-test-only/GenericTestClass.m, Linters_dummy_method, 82, TEST_IF_IS_CATEGORY_NAMED, no_bucket, WARNING, [] @@ -33,6 +34,7 @@ codetoanalyze/objc/linters-for-test-only/GenericTestClass.m, Linters_dummy_metho codetoanalyze/objc/linters-for-test-only/GenericTestClass.m, Linters_dummy_method, 183, CAT_DECL_MACRO, no_bucket, WARNING, [] codetoanalyze/objc/linters-for-test-only/GenericTestClass.m, Linters_dummy_method, 183, TEST_IF_IS_CATEGORY_INTERFACE_ON_SUBCLASS_OF, no_bucket, WARNING, [] codetoanalyze/objc/linters-for-test-only/GenericTestClass.m, Linters_dummy_method, 183, TEST_IF_IS_CATEGORY_ON_SUBCLASS_OF, no_bucket, WARNING, [] +codetoanalyze/objc/linters-for-test-only/GenericTestClass.m, Linters_dummy_method, 189, CAT_IMPL_MACRO, no_bucket, WARNING, [] codetoanalyze/objc/linters-for-test-only/GenericTestClass.m, Linters_dummy_method, 189, TEST_IF_IS_CATEGORY_IMPLEMENTATION_ON_SUBCLASS_OF, no_bucket, WARNING, [] codetoanalyze/objc/linters-for-test-only/GenericTestClass.m, Linters_dummy_method, 189, TEST_IF_IS_CATEGORY_ON_SUBCLASS_OF, no_bucket, WARNING, [] codetoanalyze/objc/linters-for-test-only/GenericTestClass.m, MyBaseClass::myBaseClassCategoryMethod, 78, TEST_IF_METHOD_IS_IN_CATEGORY_INTERFACE_NAMED, no_bucket, WARNING, [] @@ -232,8 +234,11 @@ codetoanalyze/objc/linters-for-test-only/PrivateInstanceMethod.m, UselessClass:: codetoanalyze/objc/linters-for-test-only/PrivateInstanceMethod.m, UselessClass::b, 18, TEST_RETURN_METHOD, no_bucket, WARNING, [] codetoanalyze/objc/linters-for-test-only/cat_macro_example.m, Linters_dummy_method, 9, TEST_VAR_TYPE_CHECK, no_bucket, WARNING, [] codetoanalyze/objc/linters-for-test-only/cat_macro_example.m, Linters_dummy_method, 11, CLASS_AND_VAR, no_bucket, WARNING, [] -codetoanalyze/objc/linters-for-test-only/cat_macro_example.m, Linters_dummy_method, 20, CONST_NAMING, no_bucket, WARNING, [] -codetoanalyze/objc/linters-for-test-only/cat_macro_example.m, SiblingExample::foo, 22, TEST_PARAM_TYPE_CHECK2, no_bucket, WARNING, [] +codetoanalyze/objc/linters-for-test-only/cat_macro_example.m, Linters_dummy_method, 23, CONST_NAMING, no_bucket, WARNING, [] +codetoanalyze/objc/linters-for-test-only/cat_macro_example.m, Linters_dummy_method, 29, CAT_IMPL_MACRO, no_bucket, WARNING, [] +codetoanalyze/objc/linters-for-test-only/cat_macro_example.m, SiblingExample::foo, 25, TEST_PARAM_TYPE_CHECK2, no_bucket, WARNING, [] +codetoanalyze/objc/linters-for-test-only/cat_macro_example.m, SiblingExample::foo, 31, TEST_IS_METHOD_EXPOSED, no_bucket, WARNING, [] +codetoanalyze/objc/linters-for-test-only/cat_macro_example.m, SiblingExample::foo, 31, TEST_PARAM_TYPE_CHECK2, no_bucket, WARNING, [] codetoanalyze/objc/linters-for-test-only/const.m, Linters_dummy_method, 7, CONST_NAMING, no_bucket, WARNING, [] codetoanalyze/objc/linters-for-test-only/const.m, Linters_dummy_method, 7, TEST_VAR_TYPE_CHECK, no_bucket, WARNING, [] codetoanalyze/objc/linters-for-test-only/const.m, Linters_dummy_method, 8, CONST_NAMING, no_bucket, WARNING, [] @@ -281,11 +286,16 @@ codetoanalyze/objc/linters-for-test-only/sel.m, fooButtonComponent::newWithActio codetoanalyze/objc/linters-for-test-only/sel.m, fooButtonComponent::newWithAction, 10, TEST_PARAMETER_SEL_TYPE, no_bucket, WARNING, [] codetoanalyze/objc/linters-for-test-only/sibling_example.m, Linters_dummy_method, 9, TEST_VAR_TYPE_CHECK, no_bucket, WARNING, [] codetoanalyze/objc/linters-for-test-only/sibling_example.m, Linters_dummy_method, 11, CLASS_AND_VAR, no_bucket, WARNING, [] -codetoanalyze/objc/linters-for-test-only/sibling_example.m, Linters_dummy_method, 20, CAT_DECL_MACRO, no_bucket, WARNING, [] -codetoanalyze/objc/linters-for-test-only/sibling_example.m, Linters_dummy_method, 25, CONST_NAMING, no_bucket, WARNING, [] -codetoanalyze/objc/linters-for-test-only/sibling_example.m, Linters_dummy_method, 26, CAT_DECL_MACRO, no_bucket, WARNING, [] -codetoanalyze/objc/linters-for-test-only/sibling_example.m, SiblingExample::foo, 21, TEST_PARAM_TYPE_CHECK2, no_bucket, WARNING, [] -codetoanalyze/objc/linters-for-test-only/sibling_example.m, SiblingExample::foo, 27, TEST_PARAM_TYPE_CHECK2, no_bucket, WARNING, [] +codetoanalyze/objc/linters-for-test-only/sibling_example.m, Linters_dummy_method, 23, CAT_DECL_MACRO, no_bucket, WARNING, [] +codetoanalyze/objc/linters-for-test-only/sibling_example.m, Linters_dummy_method, 28, CONST_NAMING, no_bucket, WARNING, [] +codetoanalyze/objc/linters-for-test-only/sibling_example.m, Linters_dummy_method, 29, CAT_DECL_MACRO, no_bucket, WARNING, [] +codetoanalyze/objc/linters-for-test-only/sibling_example.m, Linters_dummy_method, 42, CAT_IMPL_MACRO, no_bucket, WARNING, [] +codetoanalyze/objc/linters-for-test-only/sibling_example.m, SiblingExample::foo, 24, TEST_PARAM_TYPE_CHECK2, no_bucket, WARNING, [] +codetoanalyze/objc/linters-for-test-only/sibling_example.m, SiblingExample::foo, 30, TEST_PARAM_TYPE_CHECK2, no_bucket, WARNING, [] +codetoanalyze/objc/linters-for-test-only/sibling_example.m, SiblingExample::foo, 37, TEST_IS_METHOD_EXPOSED, no_bucket, WARNING, [] +codetoanalyze/objc/linters-for-test-only/sibling_example.m, SiblingExample::foo, 37, TEST_PARAM_TYPE_CHECK2, no_bucket, WARNING, [] +codetoanalyze/objc/linters-for-test-only/sibling_example.m, SiblingExample::foo, 44, TEST_IS_METHOD_EXPOSED, no_bucket, WARNING, [] +codetoanalyze/objc/linters-for-test-only/sibling_example.m, SiblingExample::foo, 44, TEST_PARAM_TYPE_CHECK2, no_bucket, WARNING, [] codetoanalyze/objc/linters-for-test-only/subclassing.m, A::foo, 11, TEST_PARAM_TYPE_CHECK2, no_bucket, WARNING, [] codetoanalyze/objc/linters-for-test-only/subclassing.m, A::foo, 11, TEST_RETURN_METHOD, no_bucket, WARNING, [] codetoanalyze/objc/linters-for-test-only/subclassing.m, A::foo, 17, TEST_IS_METHOD_EXPOSED, no_bucket, WARNING, [] diff --git a/infer/tests/codetoanalyze/objc/linters-for-test-only/sibling_example.m b/infer/tests/codetoanalyze/objc/linters-for-test-only/sibling_example.m index d6d65dbd6..fecb902e1 100644 --- a/infer/tests/codetoanalyze/objc/linters-for-test-only/sibling_example.m +++ b/infer/tests/codetoanalyze/objc/linters-for-test-only/sibling_example.m @@ -17,6 +17,9 @@ int x; extern const void* const OS_WEAK OS_CONCAT(Link_, NAME); \ OS_USED const void* const OS_WEAK OS_CONCAT(Link_, NAME) = &Linkable_##NAME; +#define LINKABLE(NAME) \ + __attribute__((visibility("default"))) char Linkable_##NAME = 'L'; + @interface SiblingExample (Cat1) - (void)foo:(int)themeProvider; @@ -27,3 +30,17 @@ LINK_REQUIRE(SiblingExampl); - (void)foo:(int)themeProvider; @end + +LINKABLE(SiblingExample_Cat2) +@implementation SiblingExample (Cat2) + +- (void)foo:(int)themeProvider { +} + +@end + +@implementation SiblingExample (Cat1) + +- (void)foo:(int)themeProvider { +} +@end