Summary: In ObjC, `NSObject.copy` returns the object returned by `copyWithZone:` on the given class. This method must be implemented if the class complies with `NSCopying` protocol. Since we don't have access to `NSObject`'s code, to follow calls into `copyWithZone:`, we replace such `copy` calls with calls to `copyWithZone:` when a) such a method exists in the class and b) the class conforms to `NSCopying` protocol. This is done in the preanalysis because - we need to know if there is a `copyWithZone:` method in the class. - so that other analyses also benefit (as opposed to doing this in cost and inferbo models). Note that `NSObject` doesn't itself conform to `NSCopying` but all its subclasses must confrom to the protocol and support the same behavior as above. https://developer.apple.com/documentation/objectivec/nsobject/1418807-copy Similarly for `mutableCopy` -> `mutableCopyWithZone:` for classes implementing `NSMutableCopying` protocol. Reviewed By: skcho Differential Revision: D24218102 fbshipit-source-id: 42900760emaster
parent
84e9bea312
commit
cbe796e541
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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 <Foundation/Foundation.h>
|
||||
|
||||
@interface MyCopyObj : NSObject<NSCopying>
|
||||
@property(nonatomic, strong, nonnull) NSArray* mObjects;
|
||||
@end
|
||||
|
||||
@implementation MyCopyObj
|
||||
|
||||
- (NSArray*)objects {
|
||||
return self.mObjects;
|
||||
}
|
||||
|
||||
- (id)copyWithZone:(NSZone*)zone {
|
||||
MyCopyObj* copy = [[MyCopyObj alloc] init];
|
||||
if (copy != nil) {
|
||||
NSArray* arr = [NSArray new];
|
||||
[arr initWithArray:self.mObjects copyItems:YES];
|
||||
copy->_mObjects = arr;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
void loop_over_copied_objects_linear(MyCopyObj* b) {
|
||||
MyCopyObj* c = [b copy]; // calls into copyWithZone:
|
||||
NSArray* objects = c.objects;
|
||||
for (int i = 0; i < objects.count; i++) {
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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 <Foundation/Foundation.h>
|
||||
|
||||
@interface MyObj : NSObject
|
||||
@property(nonatomic, strong, nonnull) NSArray* mObjects;
|
||||
@end
|
||||
|
||||
@implementation MyObj
|
||||
|
||||
- (NSArray*)objects {
|
||||
return self.mObjects;
|
||||
}
|
||||
|
||||
- (id)copyWithZone:(NSZone*)zone {
|
||||
MyObj* copy = [[MyObj alloc] init];
|
||||
if (copy != nil) {
|
||||
NSArray* arr = [NSArray new];
|
||||
[arr initWithArray:self.mObjects copyItems:YES];
|
||||
copy->_mObjects = arr;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
void loop_over_copied_myobj_linear(MyObj* b) {
|
||||
MyObj* c = [b copy]; // calls into copyWithZone:
|
||||
NSArray* objects = c.objects;
|
||||
for (int i = 0; i < objects.count; i++) {
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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 <Foundation/Foundation.h>
|
||||
|
||||
@interface MyMutableObj : NSObject<NSMutableCopying>
|
||||
@property(nonatomic, strong, nonnull) NSArray* mObjects;
|
||||
@end
|
||||
|
||||
@implementation MyMutableObj
|
||||
|
||||
- (NSArray*)objects {
|
||||
return self.mObjects;
|
||||
}
|
||||
|
||||
- (id)mutableCopyWithZone:(NSZone*)zone {
|
||||
MyMutableObj* copy = [[MyMutableObj alloc] init];
|
||||
if (copy != nil) {
|
||||
NSArray* arr = [NSArray new];
|
||||
[arr initWithArray:self.mObjects copyItems:YES];
|
||||
copy->_mObjects = arr;
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
void loop_over_mutable_copy_linear(MyMutableObj* b) {
|
||||
MyMutableObj* c = [b mutableCopy]; // calls into mutableCopyWithZone:
|
||||
NSArray* objects = c.objects;
|
||||
for (int i = 0; i < objects.count; i++) {
|
||||
}
|
||||
}
|
Loading…
Reference in new issue