diff --git a/infer/src/clang/cPredicates.ml b/infer/src/clang/cPredicates.ml index 7a6dfe050..34986a4ec 100644 --- a/infer/src/clang/cPredicates.ml +++ b/infer/src/clang/cPredicates.ml @@ -1400,6 +1400,18 @@ let has_used_attribute an = List.exists ~f:(fun attr -> match attr with UsedAttr _ -> true | _ -> false) attributes +(* true is a declaration has an Unavailable attribute *) +let has_unavailable_attribute an = + let open Clang_ast_t in + let is_unavailable_attr attr = match attr with UnavailableAttr _ -> true | _ -> false in + match an with + | Ctl_parser_types.Decl d -> + let attrs = (Clang_ast_proj.get_decl_tuple d).di_attributes in + List.exists attrs ~f:is_unavailable_attr + | _ -> + false + + let has_value an al_exp = let open Clang_ast_t in let open Ctl_parser_types in diff --git a/infer/src/clang/cPredicates.mli b/infer/src/clang/cPredicates.mli index 6c2fe5829..e8f29953a 100644 --- a/infer/src/clang/cPredicates.mli +++ b/infer/src/clang/cPredicates.mli @@ -528,3 +528,6 @@ val is_init_expr_cxx11_constant : Ctl_parser_types.ast_node -> bool val cxx_construct_expr_has_no_parameters : Ctl_parser_types.ast_node -> bool (** true if a construct expr has no subexpressions *) + +val has_unavailable_attribute : Ctl_parser_types.ast_node -> bool +(** true is a declaration has an Unavailable attribute *) diff --git a/infer/src/clang/cTL.ml b/infer/src/clang/cTL.ml index 35d7c578d..ac5026dd9 100644 --- a/infer/src/clang/cTL.ml +++ b/infer/src/clang/cTL.ml @@ -1183,6 +1183,8 @@ let rec eval_Atomic pred_name_ args an lcxt = CPredicates.has_visibility_attribute an vis | "has_used_attribute", [], an -> CPredicates.has_used_attribute an + | "has_unavailable_attribute", [], an -> + CPredicates.has_unavailable_attribute an | "within_available_class_block", [], an -> CPredicates.within_available_class_block lcxt an | "is_method_called_by_superclass", [], 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 f8b579c1c..268b0253f 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 @@ -857,3 +857,12 @@ LET dereference_self_in_method_decl = SET severity = "ERROR"; SET mode = "ON"; }; + +DEFINE-CHECKER TEST_UNAVAILABLE_ATTR = { + + SET report_when = + has_unavailable_attribute; + + SET message = "This node has unavailable attribute"; + +}; 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 69764d880..6034c7d06 100644 --- a/infer/tests/codetoanalyze/objc/linters-for-test-only/issues.exp +++ b/infer/tests/codetoanalyze/objc/linters-for-test-only/issues.exp @@ -313,6 +313,11 @@ codetoanalyze/objc/linters-for-test-only/subclassing.m, TestType::m7, 77, TEST_B codetoanalyze/objc/linters-for-test-only/subclassing.m, TestType::m8, 78, TEST_BUILTIN_TYPE, no_bucket, WARNING, [] codetoanalyze/objc/linters-for-test-only/subclassing.m, TestType::m9, 79, TEST_BUILTIN_TYPE, no_bucket, WARNING, [] codetoanalyze/objc/linters-for-test-only/subclassing.m, bar, 127, TEST_NTH_PARAM_TYPE_CHECK_FUNCTION, no_bucket, LIKE, [] +codetoanalyze/objc/linters-for-test-only/unavailable.m, FooClass::new, 12, TEST_INSTANCE_TYPE, no_bucket, WARNING, [] +codetoanalyze/objc/linters-for-test-only/unavailable.m, FooClass::new, 12, TEST_IS_METHOD_EXPOSED, no_bucket, WARNING, [] +codetoanalyze/objc/linters-for-test-only/unavailable.m, FooClass::new, 12, TEST_IS_OVERRIDING_METHOD, no_bucket, WARNING, [] +codetoanalyze/objc/linters-for-test-only/unavailable.m, FooClass::new, 12, TEST_UNAVAILABLE_ATTR, no_bucket, WARNING, [] +codetoanalyze/objc/linters-for-test-only/unavailable.m, FooClass::newWithFoo, 13, TEST_INSTANCE_TYPE, no_bucket, WARNING, [] codetoanalyze/objc/linters-for-test-only/visibility.c, bar, 29, TEST_DEFAULT_VISIBILITY, no_bucket, WARNING, [] codetoanalyze/objc/linters-for-test-only/visibility.c, bar, 30, TEST_DEFAULT_VISIBILITY, no_bucket, WARNING, [] codetoanalyze/objc/linters-for-test-only/visibility.c, bar, 31, TEST_HIDDEN_VISIBILITY, no_bucket, WARNING, [] diff --git a/infer/tests/codetoanalyze/objc/linters-for-test-only/unavailable.m b/infer/tests/codetoanalyze/objc/linters-for-test-only/unavailable.m new file mode 100644 index 000000000..91af1adcf --- /dev/null +++ b/infer/tests/codetoanalyze/objc/linters-for-test-only/unavailable.m @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2019-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +#import + +@interface FooClass : NSObject + +// this should be flagged via `has_unavailable_attribute` ++ (instancetype)new NS_UNAVAILABLE; ++ (instancetype)newWithFoo:(id)foo; + +@end + +@implementation FooClass +@end