Substitute type arguments into uses of Objective-C interface members.
When messaging a method that was defined in an Objective-C class (or
category or extension thereof) that has type parameters, substitute
the type arguments for those type parameters. Similarly, substitute
into property accesses, instance variables, and other references.
This includes general infrastructure for substituting the type
arguments associated with an ObjCObject(Pointer)Type into a type
referenced within a particular context, handling all of the
substitutions required to deal with (e.g.) inheritance involving
parameterized classes. In cases where no type arguments are available
(e.g., because we're messaging via some unspecialized type, id, etc.),
we substitute in the type bounds for the type parameters instead.
Example:
@interface NSSet<T : id<NSCopying>> : NSObject <NSCopying>
- (T)firstObject;
@end
void f(NSSet<NSString *> *stringSet, NSSet *anySet) {
[stringSet firstObject]; // produces NSString*
[anySet firstObject]; // produces id<NSCopying> (the bound)
}
When substituting for the type parameters given an unspecialized
context (i.e., no specific type arguments were given), substituting
the type bounds unconditionally produces type signatures that are too
strong compared to the pre-generics signatures. Instead, use the
following rule:
- In covariant positions, such as method return types, replace type
parameters with “id” or “Class” (the latter only when the type
parameter bound is “Class” or qualified class, e.g,
“Class<NSCopying>”)
- In other positions (e.g., parameter types), replace type
parameters with their type bounds.
- When a specialized Objective-C object or object pointer type
contains a type parameter in its type arguments (e.g.,
NSArray<T>*, but not NSArray<NSString *> *), replace the entire
object/object pointer type with its unspecialized version (e.g.,
NSArray *).
llvm-svn: 241543
2015-07-07 11:57:53 +08:00
|
|
|
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fblocks -fobjc-arc -emit-llvm -o - %s | FileCheck %s
|
|
|
|
|
|
|
|
// Parameterized classes have no effect on code generation; this test
|
|
|
|
// mainly verifies that CodeGen doesn't assert when substituted types
|
|
|
|
// in uses of methods don't line up exactly with the parameterized
|
|
|
|
// types in the method declarations due to type erasure. "Not crash"
|
|
|
|
// is the only interesting criteria here.
|
|
|
|
|
|
|
|
@protocol NSObject
|
|
|
|
@end
|
|
|
|
|
|
|
|
@protocol NSCopying
|
|
|
|
@end
|
|
|
|
|
|
|
|
__attribute__((objc_root_class))
|
|
|
|
@interface NSObject <NSObject>
|
|
|
|
@end
|
|
|
|
|
|
|
|
@interface NSString : NSObject <NSCopying>
|
|
|
|
@end
|
|
|
|
|
|
|
|
@interface NSMutableArray<T> : NSObject <NSCopying>
|
|
|
|
@property (copy,nonatomic) T firstObject;
|
|
|
|
- (void)addObject:(T)object;
|
|
|
|
- (void)sortWithFunction:(int (*)(T, T))function;
|
|
|
|
- (void)getObjects:(T __strong *)objects length:(unsigned*)length;
|
2015-10-02 09:05:29 +08:00
|
|
|
- (T)objectAtIndexedSubscript:(unsigned)index;
|
|
|
|
- (void)setObject:(T)object atIndexedSubscript:(unsigned)index;
|
Substitute type arguments into uses of Objective-C interface members.
When messaging a method that was defined in an Objective-C class (or
category or extension thereof) that has type parameters, substitute
the type arguments for those type parameters. Similarly, substitute
into property accesses, instance variables, and other references.
This includes general infrastructure for substituting the type
arguments associated with an ObjCObject(Pointer)Type into a type
referenced within a particular context, handling all of the
substitutions required to deal with (e.g.) inheritance involving
parameterized classes. In cases where no type arguments are available
(e.g., because we're messaging via some unspecialized type, id, etc.),
we substitute in the type bounds for the type parameters instead.
Example:
@interface NSSet<T : id<NSCopying>> : NSObject <NSCopying>
- (T)firstObject;
@end
void f(NSSet<NSString *> *stringSet, NSSet *anySet) {
[stringSet firstObject]; // produces NSString*
[anySet firstObject]; // produces id<NSCopying> (the bound)
}
When substituting for the type parameters given an unspecialized
context (i.e., no specific type arguments were given), substituting
the type bounds unconditionally produces type signatures that are too
strong compared to the pre-generics signatures. Instead, use the
following rule:
- In covariant positions, such as method return types, replace type
parameters with “id” or “Class” (the latter only when the type
parameter bound is “Class” or qualified class, e.g,
“Class<NSCopying>”)
- In other positions (e.g., parameter types), replace type
parameters with their type bounds.
- When a specialized Objective-C object or object pointer type
contains a type parameter in its type arguments (e.g.,
NSArray<T>*, but not NSArray<NSString *> *), replace the entire
object/object pointer type with its unspecialized version (e.g.,
NSArray *).
llvm-svn: 241543
2015-07-07 11:57:53 +08:00
|
|
|
@end
|
|
|
|
|
|
|
|
NSString *getFirstObjectProp(NSMutableArray<NSString *> *array) {
|
|
|
|
return array.firstObject;
|
|
|
|
}
|
|
|
|
|
|
|
|
NSString *getFirstObjectMethod(NSMutableArray<NSString *> *array) {
|
|
|
|
return [array firstObject];
|
|
|
|
}
|
|
|
|
|
|
|
|
void addObject(NSMutableArray<NSString *> *array, NSString *obj) {
|
|
|
|
[array addObject: obj];
|
|
|
|
}
|
|
|
|
|
|
|
|
int compareStrings(NSString *x, NSString *y) { return 0; }
|
|
|
|
int compareBlocks(NSString * (^x)(NSString *),
|
|
|
|
NSString * (^y)(NSString *)) { return 0; }
|
|
|
|
|
|
|
|
void sortTest(NSMutableArray<NSString *> *array,
|
|
|
|
NSMutableArray<NSString * (^)(NSString *)> *array2) {
|
|
|
|
[array sortWithFunction: &compareStrings];
|
|
|
|
[array2 sortWithFunction: &compareBlocks];
|
|
|
|
}
|
|
|
|
|
|
|
|
void getObjectsTest(NSMutableArray<NSString *> *array) {
|
|
|
|
NSString * __strong *objects;
|
|
|
|
unsigned length;
|
|
|
|
[array getObjects: objects length: &length];
|
|
|
|
}
|
|
|
|
|
|
|
|
void printMe(NSString *name) { }
|
|
|
|
|
2020-12-31 12:45:56 +08:00
|
|
|
// CHECK-LABEL: define{{.*}} void @blockTest
|
Substitute type arguments into uses of Objective-C interface members.
When messaging a method that was defined in an Objective-C class (or
category or extension thereof) that has type parameters, substitute
the type arguments for those type parameters. Similarly, substitute
into property accesses, instance variables, and other references.
This includes general infrastructure for substituting the type
arguments associated with an ObjCObject(Pointer)Type into a type
referenced within a particular context, handling all of the
substitutions required to deal with (e.g.) inheritance involving
parameterized classes. In cases where no type arguments are available
(e.g., because we're messaging via some unspecialized type, id, etc.),
we substitute in the type bounds for the type parameters instead.
Example:
@interface NSSet<T : id<NSCopying>> : NSObject <NSCopying>
- (T)firstObject;
@end
void f(NSSet<NSString *> *stringSet, NSSet *anySet) {
[stringSet firstObject]; // produces NSString*
[anySet firstObject]; // produces id<NSCopying> (the bound)
}
When substituting for the type parameters given an unspecialized
context (i.e., no specific type arguments were given), substituting
the type bounds unconditionally produces type signatures that are too
strong compared to the pre-generics signatures. Instead, use the
following rule:
- In covariant positions, such as method return types, replace type
parameters with “id” or “Class” (the latter only when the type
parameter bound is “Class” or qualified class, e.g,
“Class<NSCopying>”)
- In other positions (e.g., parameter types), replace type
parameters with their type bounds.
- When a specialized Objective-C object or object pointer type
contains a type parameter in its type arguments (e.g.,
NSArray<T>*, but not NSArray<NSString *> *), replace the entire
object/object pointer type with its unspecialized version (e.g.,
NSArray *).
llvm-svn: 241543
2015-07-07 11:57:53 +08:00
|
|
|
void blockTest(NSMutableArray<void (^)(void)> *array, NSString *name) {
|
2015-10-02 09:05:29 +08:00
|
|
|
// CHECK-NOT: ret void
|
2018-12-19 04:33:00 +08:00
|
|
|
// CHECK: call i8* @llvm.objc.retainBlock
|
Substitute type arguments into uses of Objective-C interface members.
When messaging a method that was defined in an Objective-C class (or
category or extension thereof) that has type parameters, substitute
the type arguments for those type parameters. Similarly, substitute
into property accesses, instance variables, and other references.
This includes general infrastructure for substituting the type
arguments associated with an ObjCObject(Pointer)Type into a type
referenced within a particular context, handling all of the
substitutions required to deal with (e.g.) inheritance involving
parameterized classes. In cases where no type arguments are available
(e.g., because we're messaging via some unspecialized type, id, etc.),
we substitute in the type bounds for the type parameters instead.
Example:
@interface NSSet<T : id<NSCopying>> : NSObject <NSCopying>
- (T)firstObject;
@end
void f(NSSet<NSString *> *stringSet, NSSet *anySet) {
[stringSet firstObject]; // produces NSString*
[anySet firstObject]; // produces id<NSCopying> (the bound)
}
When substituting for the type parameters given an unspecialized
context (i.e., no specific type arguments were given), substituting
the type bounds unconditionally produces type signatures that are too
strong compared to the pre-generics signatures. Instead, use the
following rule:
- In covariant positions, such as method return types, replace type
parameters with “id” or “Class” (the latter only when the type
parameter bound is “Class” or qualified class, e.g,
“Class<NSCopying>”)
- In other positions (e.g., parameter types), replace type
parameters with their type bounds.
- When a specialized Objective-C object or object pointer type
contains a type parameter in its type arguments (e.g.,
NSArray<T>*, but not NSArray<NSString *> *), replace the entire
object/object pointer type with its unspecialized version (e.g.,
NSArray *).
llvm-svn: 241543
2015-07-07 11:57:53 +08:00
|
|
|
[array addObject: ^ { printMe(name); }];
|
2015-10-02 09:05:29 +08:00
|
|
|
// CHECK-NOT: ret void
|
|
|
|
array[0] = ^ { printMe(name); };
|
2018-12-19 04:33:00 +08:00
|
|
|
// CHECK: call i8* @llvm.objc.retainBlock
|
2015-10-02 09:05:29 +08:00
|
|
|
// CHECK: ret void
|
Substitute type arguments into uses of Objective-C interface members.
When messaging a method that was defined in an Objective-C class (or
category or extension thereof) that has type parameters, substitute
the type arguments for those type parameters. Similarly, substitute
into property accesses, instance variables, and other references.
This includes general infrastructure for substituting the type
arguments associated with an ObjCObject(Pointer)Type into a type
referenced within a particular context, handling all of the
substitutions required to deal with (e.g.) inheritance involving
parameterized classes. In cases where no type arguments are available
(e.g., because we're messaging via some unspecialized type, id, etc.),
we substitute in the type bounds for the type parameters instead.
Example:
@interface NSSet<T : id<NSCopying>> : NSObject <NSCopying>
- (T)firstObject;
@end
void f(NSSet<NSString *> *stringSet, NSSet *anySet) {
[stringSet firstObject]; // produces NSString*
[anySet firstObject]; // produces id<NSCopying> (the bound)
}
When substituting for the type parameters given an unspecialized
context (i.e., no specific type arguments were given), substituting
the type bounds unconditionally produces type signatures that are too
strong compared to the pre-generics signatures. Instead, use the
following rule:
- In covariant positions, such as method return types, replace type
parameters with “id” or “Class” (the latter only when the type
parameter bound is “Class” or qualified class, e.g,
“Class<NSCopying>”)
- In other positions (e.g., parameter types), replace type
parameters with their type bounds.
- When a specialized Objective-C object or object pointer type
contains a type parameter in its type arguments (e.g.,
NSArray<T>*, but not NSArray<NSString *> *), replace the entire
object/object pointer type with its unspecialized version (e.g.,
NSArray *).
llvm-svn: 241543
2015-07-07 11:57:53 +08:00
|
|
|
}
|
2017-06-02 02:41:25 +08:00
|
|
|
|
|
|
|
// CHECK-LABEL: define internal void @"\01-[Derived setDest:]
|
|
|
|
// CHECK: %[[SELFADDR:.*]] = alloca %[[SELFTY:.*]]*
|
|
|
|
// CHECK: %[[AADDR:.*]] = alloca %[[IVARTY:.*]]*
|
|
|
|
// CHECK: %[[V2:.*]] = load %[[IVARTY]]*, %[[IVARTY]]** %[[AADDR]]
|
|
|
|
// CHECK: %[[V3:.*]] = load %[[SELFTY]]*, %[[SELFTY]]** %[[SELFADDR]]
|
|
|
|
// CHECK: %[[IVAR:.*]] = load i64, i64* @"OBJC_IVAR_$_Base._destination"
|
|
|
|
// CHECK: %[[V4:.*]] = bitcast %[[SELFTY]]* %[[V3]] to i8*
|
|
|
|
// CHECK: %[[ADDPTR:.*]] = getelementptr inbounds i8, i8* %[[V4]], i64 %[[IVAR]]
|
|
|
|
// CHECK: %[[V5:.*]] = bitcast i8* %[[ADDPTR]] to %[[IVARTY]]**
|
|
|
|
// CHECK: %[[V6:.*]] = bitcast %[[IVARTY]]** %[[V5]] to i8**
|
|
|
|
// CHECK: %[[V7:.*]] = bitcast %[[IVARTY]]* %[[V2]] to i8*
|
2018-12-19 04:33:00 +08:00
|
|
|
// CHECK: call void @llvm.objc.storeStrong(i8** %[[V6]], i8* %[[V7]])
|
2017-06-02 02:41:25 +08:00
|
|
|
|
|
|
|
@interface Base<DestType> : NSObject {
|
|
|
|
DestType _destination;
|
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|
|
@interface Derived : Base<NSObject *>
|
|
|
|
- (void)setDest:(NSObject *)a;
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation Derived
|
|
|
|
- (void)setDest:(NSObject *)a {
|
|
|
|
_destination = a;
|
|
|
|
}
|
|
|
|
@end
|
2017-06-28 08:42:48 +08:00
|
|
|
|
|
|
|
// CHECK-LABEL: define internal void @"\01-[C0 foo1]"(
|
|
|
|
// CHECK: {{.*}} = alloca
|
|
|
|
// CHECK: {{.*}} = alloca
|
|
|
|
// CHECK: %[[D:.*]] = alloca %[[TY:.*]]*
|
|
|
|
// CHECK: %[[TEMP:.*]] = alloca %[[TY]]*
|
|
|
|
// CHECK: %[[V4:.*]] = load %[[TY]]*, %[[TY]]** %[[D]]
|
|
|
|
// CHECK: store %[[TY]]* %[[V4]], %[[TY]]** %[[TEMP]]
|
|
|
|
// CHECK: %[[V7:.*]] = bitcast %[[TY]]** %[[TEMP]] to i8**
|
2021-10-15 18:26:07 +08:00
|
|
|
// CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, i8**)*)(i8* noundef %{{.*}}, i8* noundef %{{.*}}, i8** noundef %[[V7]])
|
2017-06-28 08:42:48 +08:00
|
|
|
|
|
|
|
@interface P0<ObjectType> : NSObject
|
|
|
|
- (void)m0:(ObjectType *)first;
|
|
|
|
@end
|
|
|
|
|
|
|
|
@interface C0 : NSObject
|
|
|
|
-(void)foo1;
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation C0 {
|
|
|
|
P0<NSString *> *x;
|
|
|
|
}
|
|
|
|
|
|
|
|
-(void)foo1 {
|
|
|
|
NSString *d;
|
|
|
|
[x m0:&d];
|
|
|
|
}
|
|
|
|
@end
|