1// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fsyntax-only -fobjc-arc -verify %s
2// rdar://12056271
3
4@class Thread;
5
6__attribute__((objc_root_class))
7@interface NSObject
8
9- (id)performSelector:(SEL)sel;
10- (void)performSelectorInBackground:(SEL)sel withObject:(id)arg;
11- (void)performSelectorOnMainThread:(SEL)sel;
12
13- (void)performSelectorOnMainThread:(SEL)aSelector
14                           onThread:(Thread *)thread
15                         withObject:(id)arg
16                      waitUntilDone:(int)wait
17                              modes:(id *)array;
18
19@end
20
21typedef struct { int x; int y; int width; int height; } Rectangle;
22
23struct Struct { Rectangle r; };
24
25typedef union { int x; float f; } Union;
26
27@interface Base : NSObject
28
29- (struct Struct)returnsStruct2; // expected-note {{method 'returnsStruct2' that returns 'struct Struct' declared here}}
30- (Union)returnsId;
31
32@end
33
34@protocol IP
35
36- (Union)returnsUnion; // expected-note 2 {{method 'returnsUnion' that returns 'Union' declared here}}
37
38@end
39
40typedef __attribute__((__ext_vector_type__(3))) float float3;
41typedef int int4 __attribute__ ((vector_size (16)));
42
43@interface I : Base<IP>
44
45- (Rectangle)returnsStruct; // expected-note 4 {{method 'returnsStruct' that returns 'Rectangle' declared here}}
46- (id)returnsId; // shadows base 'returnsId'
47- (int)returnsInt;
48- (I *)returnPtr;
49- (float3)returnsExtVector; // expected-note {{method 'returnsExtVector' that returns 'float3' (vector of 3 'float' values) declared here}}
50- (int4)returnsVector; // expected-note {{method 'returnsVector' that returns 'int4' (vector of 4 'int' values) declared here}}
51
52+ (Rectangle)returnsStructClass; // expected-note 2 {{method 'returnsStructClass' that returns 'Rectangle' declared here}}
53+ (void)returnsUnion; // Not really
54
55@end
56
57void foo(I *i) {
58  [i performSelector: @selector(returnsStruct)]; // expected-warning {{'performSelector:' is incompatible with selectors that return a struct type}}
59  [i performSelectorInBackground: @selector(returnsStruct) withObject:0]; // expected-warning {{'performSelectorInBackground:withObject:' is incompatible with selectors that return a struct type}}
60  [i performSelector: ((@selector(returnsUnion)))]; // expected-warning {{'performSelector:' is incompatible with selectors that return a union type}}
61  [i performSelectorOnMainThread: @selector(returnsStruct2)]; // expected-warning {{'performSelectorOnMainThread:' is incompatible with selectors that return a struct type}}
62  [I performSelector: (@selector(returnsStructClass))]; // expected-warning {{'performSelector:' is incompatible with selectors that return a struct type}}
63
64  [i performSelector: @selector(returnsId)];
65  [i performSelector: @selector(returnsInt)];
66  [i performSelector: @selector(returnsPtr)];
67  [I performSelector: @selector(returnsUnion)]; // No warning expected
68
69  id obj = i;
70  [obj performSelector: @selector(returnsId)];
71  [obj performSelector: @selector(returnsStruct)];
72}
73
74@interface SubClass: I
75
76@end
77
78@interface SubClass ()
79- (struct Struct)returnsSubStructExt; // expected-note {{method 'returnsSubStructExt' that returns 'struct Struct' declared here}} expected-note {{method 'returnsSubStructExt' declared here}}
80@end
81
82@implementation SubClass // expected-warning {{method definition for 'returnsSubStructExt' not found}}
83
84- (struct Struct)returnsSubStructImpl { // expected-note {{method 'returnsSubStructImpl' that returns 'struct Struct' declared here}}
85  struct Struct Result;
86  return Result;
87}
88
89- (void)checkPrivateCalls {
90  [self performSelector: @selector(returnsSubStructExt)]; // expected-warning {{'performSelector:' is incompatible with selectors that return a struct type}}
91  [self performSelector: @selector(returnsSubStructImpl)]; // expected-warning {{'performSelector:' is incompatible with selectors that return a struct type}}
92}
93
94- (void)checkSuperCalls {
95  [super performSelector: @selector(returnsStruct)]; // expected-warning {{'performSelector:' is incompatible with selectors that return a struct type}}
96  [super performSelectorInBackground: @selector(returnsUnion) withObject: self]; // expected-warning {{'performSelectorInBackground:withObject:' is incompatible with selectors that return a union type}}
97  [super performSelector: @selector(returnsId)];
98}
99
100+ (struct Struct)returnsSubStructClassImpl { // expected-note {{method 'returnsSubStructClassImpl' that returns 'struct Struct' declared here}}
101  struct Struct Result;
102  return Result;
103}
104
105+ (void)checkClassPrivateCalls {
106  [self performSelector: @selector(returnsSubStructClassImpl)]; // expected-warning {{'performSelector:' is incompatible with selectors that return a struct type}}
107}
108
109+ (void)checkClassSuperCalls {
110  [super performSelector: @selector(returnsStructClass)]; // expected-warning {{'performSelector:' is incompatible with selectors that return a struct type}}
111  [super performSelector: @selector(returnsUnion)]; // No warning expected
112}
113
114@end
115
116@implementation I (LongPerformSelectors)
117
118- (void)checkLongCallsFromCategory {
119  [self performSelectorOnMainThread: @selector(returnsStruct) onThread:0 withObject:self waitUntilDone:1 modes:0]; // expected-warning {{'performSelectorOnMainThread:onThread:withObject:waitUntilDone:modes:' is incompatible with selectors that return a struct type}}
120}
121
122- (void)checkVectorReturn {
123  [self performSelector: @selector(returnsExtVector)]; // expected-warning {{'performSelector:' is incompatible with selectors that return a vector type}}
124  [self performSelector: @selector(returnsVector)]; // expected-warning {{'performSelector:' is incompatible with selectors that return a vector type}}
125}
126
127@end
128