From 291d250b9bfb85c7e6714224de3ceccb03e2be7b Mon Sep 17 00:00:00 2001 From: Sungkeun Cho Date: Wed, 19 May 2021 10:05:06 -0700 Subject: [PATCH] [frontend] Add field for property to the type environment in ObjC Summary: This diff adds fields for ObjC properties to the type environment. For example, ``` property type fieldname; ``` when the property name is "fieldname", this diff adds a struct field of the same name. The missing type information were problematic in inferbo, since its semantics depend on types. Reviewed By: ezgicicek Differential Revision: D28421998 fbshipit-source-id: e24059846 --- infer/src/clang/cField_decl.ml | 24 +++++++++---------- .../objc/frontend/property/aclass.m.dot | 2 +- .../codetoanalyze/objc/performance/MyData.h | 13 ++++++++++ .../codetoanalyze/objc/performance/MyData.m | 13 ++++++++++ .../objc/performance/cost-issues.exp | 3 +++ .../objc/performance/property_test.m | 14 +++++++++++ 6 files changed, 55 insertions(+), 14 deletions(-) create mode 100644 infer/tests/codetoanalyze/objc/performance/MyData.h create mode 100644 infer/tests/codetoanalyze/objc/performance/MyData.m create mode 100644 infer/tests/codetoanalyze/objc/performance/property_test.m diff --git a/infer/src/clang/cField_decl.ml b/infer/src/clang/cField_decl.ml index 48c5c55da..ad58941d0 100644 --- a/infer/src/clang/cField_decl.ml +++ b/infer/src/clang/cField_decl.ml @@ -75,15 +75,16 @@ let get_fields qual_type_to_sil_type tenv class_tname decl_list = in let rec get_field fields decl = match decl with - | ObjCPropertyDecl (_, _, obj_c_property_decl_info) -> ( - let ivar_decl_ref = obj_c_property_decl_info.Clang_ast_t.opdi_ivar_decl in - let property_attributes = obj_c_property_decl_info.Clang_ast_t.opdi_property_attributes in - match CAst_utils.get_decl_opt_with_decl_ref_opt ivar_decl_ref with - | Some (ObjCIvarDecl (_, name_info, qual_type, _, _)) -> - let field = get_sil_field name_info qual_type property_attributes in - CGeneral_utils.add_no_duplicates_fields field fields - | _ -> - fields ) + | ObjCPropertyDecl (_, name_info, {opdi_qual_type; opdi_ivar_decl; opdi_property_attributes}) -> + let name_info, qual_type = + match CAst_utils.get_decl_opt_with_decl_ref_opt opdi_ivar_decl with + | Some (ObjCIvarDecl (_, name_info, qual_type, _, _)) -> + (name_info, qual_type) + | _ -> + (name_info, opdi_qual_type) + in + let field = get_sil_field name_info qual_type opdi_property_attributes in + CGeneral_utils.add_no_duplicates_fields field fields | ObjCPropertyImplDecl (_, obj_c_property_impl_decl_info) -> ( let property_decl_opt = obj_c_property_impl_decl_info.Clang_ast_t.opidi_property_decl in match CAst_utils.get_decl_opt_with_decl_ref_opt property_decl_opt with @@ -114,10 +115,7 @@ let add_missing_fields tenv class_name missing_fields = () -let modelled_fields_in_classes = - [ ("NSData", "_bytes", Typ.mk (Tptr (StdTyp.void, Typ.Pk_pointer))) - ; ("NSArray", "elementData", Typ.mk (Tint Typ.IInt)) ] - +let modelled_fields_in_classes = [("NSArray", "elementData", Typ.mk (Tint Typ.IInt))] let modelled_field class_name_info = let modelled_field_in_class res (class_name, field_name, typ) = diff --git a/infer/tests/codetoanalyze/objc/frontend/property/aclass.m.dot b/infer/tests/codetoanalyze/objc/frontend/property/aclass.m.dot index 6db370b82..98765ace7 100644 --- a/infer/tests/codetoanalyze/objc/frontend/property/aclass.m.dot +++ b/infer/tests/codetoanalyze/objc/frontend/property/aclass.m.dot @@ -7,7 +7,7 @@ digraph cfg { "dealloc#AClass#instance.5339a8e9aec421a1f58ba25e08faeb6b_2" [label="2: Exit AClass.dealloc \n " color=yellow style=filled] -"dealloc#AClass#instance.5339a8e9aec421a1f58ba25e08faeb6b_3" [label="3: Call dealloc \n " shape="box"] +"dealloc#AClass#instance.5339a8e9aec421a1f58ba25e08faeb6b_3" [label="3: Call dealloc \n n$0=*&self:AClass* [line 18, column 1]\n n$1=*n$0.aDynValue:NSObject* [line 18, column 1]\n n$2=_fun_NSObject.dealloc(n$1:NSObject*) [line 18, column 1]\n " shape="box"] "dealloc#AClass#instance.5339a8e9aec421a1f58ba25e08faeb6b_3" -> "dealloc#AClass#instance.5339a8e9aec421a1f58ba25e08faeb6b_2" ; diff --git a/infer/tests/codetoanalyze/objc/performance/MyData.h b/infer/tests/codetoanalyze/objc/performance/MyData.h new file mode 100644 index 000000000..77462ea4a --- /dev/null +++ b/infer/tests/codetoanalyze/objc/performance/MyData.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +#import + +@interface MyData : NSObject + +@property(nonatomic, readonly, copy) NSString* name; + +@end diff --git a/infer/tests/codetoanalyze/objc/performance/MyData.m b/infer/tests/codetoanalyze/objc/performance/MyData.m new file mode 100644 index 000000000..ee88147d6 --- /dev/null +++ b/infer/tests/codetoanalyze/objc/performance/MyData.m @@ -0,0 +1,13 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +#import "MyData.h" + +@implementation MyData + +@synthesize name; + +@end diff --git a/infer/tests/codetoanalyze/objc/performance/cost-issues.exp b/infer/tests/codetoanalyze/objc/performance/cost-issues.exp index 75243fecb..e83addd24 100644 --- a/infer/tests/codetoanalyze/objc/performance/cost-issues.exp +++ b/infer/tests/codetoanalyze/objc/performance/cost-issues.exp @@ -4,6 +4,8 @@ ${XCODE_ISYSROOT}/System/Library/Frameworks/Foundation.framework/Headers/NSArray ${XCODE_ISYSROOT}/System/Library/Frameworks/Foundation.framework/Headers/NSArray.h, NSArray.indexOfObject:inSortedRange:options:usingComparator:[objc_blocknsarray_binary_search_log_FN_1], 0, OnUIThread:false, [] ${XCODE_ISYSROOT}/System/Library/Frameworks/Foundation.framework/Headers/NSAttributedString.h, NSAttributedString.enumerateAttribute:inRange:options:usingBlock:[objc_blockenumerateAttribute_linear_2], 0, OnUIThread:false, [] ${XCODE_ISYSROOT}/System/Library/Frameworks/Foundation.framework/Headers/NSAttributedString.h, NSAttributedString.enumerateAttribute:inRange:options:usingBlock:[objc_blockenumerateAttribute_quadratic_1], 0, OnUIThread:false, [] +codetoanalyze/objc/performance/MyData.h, MyData.name, 3, OnUIThread:false, [] +codetoanalyze/objc/performance/MyData.m, MyData.dealloc, 3, OnUIThread:false, [] codetoanalyze/objc/performance/MyEnumerator.m, MyEnumerator.dealloc, 0, OnUIThread:false, [] codetoanalyze/objc/performance/MyEnumerator.m, MyEnumerator.nextObject, 5 + 3 ⋅ self->n.ub + 3 ⋅ (1+max(0, self->n.ub)), OnUIThread:false, [{1+max(0, self->n.ub)},Loop,{self->n.ub},Loop] codetoanalyze/objc/performance/NSArray.m, MyBlock.call_enumerate_via_block_param_quadratic::, 4 + 3 ⋅ size × x->elements.length.ub + 2 ⋅ x->elements.length.ub + 2 ⋅ x->elements.length.ub × (1+max(0, size)), OnUIThread:false, [{1+max(0, size)},Loop,{x->elements.length.ub},Modeled call to enumerateObjectsUsingBlock:,{x->elements.length.ub},Modeled call to enumerateObjectsUsingBlock:,{size},Loop] @@ -248,6 +250,7 @@ codetoanalyze/objc/performance/mutable_copy_test.m, MyMutableObj.mutableCopyWith codetoanalyze/objc/performance/mutable_copy_test.m, MyMutableObj.objects, 5, OnUIThread:false, [] codetoanalyze/objc/performance/mutable_copy_test.m, MyMutableObj.setMObjects:, 3, OnUIThread:false, [] codetoanalyze/objc/performance/mutable_copy_test.m, loop_over_mutable_copy_linear, 31 + 3 ⋅ b->_mObjects->elements.length.ub + 3 ⋅ (b->_mObjects->elements.length.ub + 1), OnUIThread:false, [{b->_mObjects->elements.length.ub + 1},Loop,{b->_mObjects->elements.length.ub},Loop] +codetoanalyze/objc/performance/property_test.m, getter_property_linear, 7 + 3 ⋅ data->name.length.ub + 3 ⋅ (data->name.length.ub + 1), OnUIThread:false, [{data->name.length.ub + 1},Loop,{data->name.length.ub},Loop] codetoanalyze/objc/performance/purity.m, loop, 6006 + 1000 ⋅ |fun_ptr|, OnUIThread:false, [] codetoanalyze/objc/performance/struct_test.m, __infer_globals_initializer_mSpecs, 4, OnUIThread:false, [] codetoanalyze/objc/performance/struct_test.m, const_struct_field_read_constant, 9, OnUIThread:false, [] diff --git a/infer/tests/codetoanalyze/objc/performance/property_test.m b/infer/tests/codetoanalyze/objc/performance/property_test.m new file mode 100644 index 000000000..7ca3a2afc --- /dev/null +++ b/infer/tests/codetoanalyze/objc/performance/property_test.m @@ -0,0 +1,14 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ +#import +#import "MyData.h" + +void getter_property_linear(MyData* data) { + NSString* dn = data.name; + for (int i = 0; i < dn.length; i++) { + } +}