blob: 4a7f96103afd3a21414edd2599d0a6c2196bcce9 [file] [log] [blame]
John McCall260611a2012-06-20 06:18:46 +00001// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fms-extensions -rewrite-objc -fobjc-runtime=macosx-fragile-10.5 %s -o %t-rw.cpp
Fariborz Jahanian43aa1c32012-04-16 22:14:01 +00002// RUN: %clang_cc1 -fsyntax-only -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
3// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fms-extensions -rewrite-objc %s -o %t-modern-rw.cpp
4// RUN: %clang_cc1 -fsyntax-only -Wno-address-of-temporary -D"Class=void*" -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-modern-rw.cpp
Fariborz Jahanian88914802011-09-09 20:35:22 +00005
6void *sel_registerName(const char *);
7
8@interface Root
9+ (instancetype)alloc;
10- (instancetype)init; // expected-note{{overridden method is part of the 'init' method family}}
11- (instancetype)self;
12- (Class)class;
13
14@property (assign) Root *selfProp;
15- (instancetype)selfProp;
16@end
17
18@protocol Proto1
19@optional
20- (instancetype)methodInProto1;
21@end
22
23@protocol Proto2
24@optional
25- (instancetype)methodInProto2; // expected-note{{overridden method returns an instance of its class type}}
26- (instancetype)otherMethodInProto2; // expected-note{{overridden method returns an instance of its class type}}
27@end
28
29@interface Subclass1 : Root
30- (instancetype)initSubclass1;
31- (void)methodOnSubclass1;
32+ (instancetype)allocSubclass1;
33@end
34
35@interface Subclass2 : Root
36- (instancetype)initSubclass2;
37- (void)methodOnSubclass2;
38@end
39
40// Sanity check: the basic initialization pattern.
41void test_instancetype_alloc_init_simple() {
42 Root *r1 = [[Root alloc] init];
43 Subclass1 *sc1 = [[Subclass1 alloc] init];
44}
45
46// Test that message sends to instancetype methods have the right type.
47void test_instancetype_narrow_method_search() {
48 // instancetype on class methods
49 Subclass1 *sc1 = [[Subclass1 alloc] initSubclass2]; // expected-warning{{'Subclass1' may not respond to 'initSubclass2'}}
50 Subclass2 *sc2 = [[Subclass2 alloc] initSubclass2]; // okay
51
52 // instancetype on instance methods
53 [[[Subclass1 alloc] init] methodOnSubclass2]; // expected-warning{{'Subclass1' may not respond to 'methodOnSubclass2'}}
54 [[[Subclass2 alloc] init] methodOnSubclass2];
55
56 // instancetype on class methods using protocols
57 [[Subclass1<Proto1> alloc] methodInProto2]; // expected-warning{{method '-methodInProto2' not found (return type defaults to 'id')}}
58 [[Subclass1<Proto2> alloc] methodInProto2];
59
60 // instancetype on instance methods
61 Subclass1<Proto1> *sc1proto1 = 0;
62 [[sc1proto1 self] methodInProto2]; // expected-warning{{method '-methodInProto2' not found (return type defaults to 'id')}}
63 Subclass1<Proto2> *sc1proto2 = 0;
64 [[sc1proto2 self] methodInProto2];
65
66 // Exact type checks
67 // Message sends to Class.
Fariborz Jahanian3a448fb2011-09-10 17:01:56 +000068 // FIXME. This is not supported due to missing capability in rewriter and not due to instancetype issues
69 // Subclass1<Proto1> *sc1proto1_2 = [[[sc1proto1 class] alloc] init];
Fariborz Jahanian88914802011-09-09 20:35:22 +000070
71 // Property access
72 [sc1proto1.self methodInProto2]; // expected-warning{{method '-methodInProto2' not found (return type defaults to 'id')}}
73 [sc1proto2.self methodInProto2];
74
75 [sc1proto1.selfProp methodInProto2]; // expected-warning{{method '-methodInProto2' not found (return type defaults to 'id')}}
76 [sc1proto2.selfProp methodInProto2];
77}