1 | // RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fms-extensions -rewrite-objc -fobjc-runtime=macosx-fragile-10.5 %s -o %t-rw.cpp |
2 | // 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 |
5 | |
6 | void *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. |
41 | void 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. |
47 | void 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. |
68 | // 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]; |
70 | |
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 | } |
78 | |