reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fsyntax-only -fobjc-arc -verify %s
// rdar://12056271

@class Thread;

__attribute__((objc_root_class))
@interface NSObject

- (id)performSelector:(SEL)sel;
- (void)performSelectorInBackground:(SEL)sel withObject:(id)arg;
- (void)performSelectorOnMainThread:(SEL)sel;

- (void)performSelectorOnMainThread:(SEL)aSelector
                           onThread:(Thread *)thread
                         withObject:(id)arg
                      waitUntilDone:(int)wait
                              modes:(id *)array;

@end

typedef struct { int x; int y; int width; int height; } Rectangle;

struct Struct { Rectangle r; };

typedef union { int x; float f; } Union;

@interface Base : NSObject

- (struct Struct)returnsStruct2; // expected-note {{method 'returnsStruct2' that returns 'struct Struct' declared here}}
- (Union)returnsId;

@end

@protocol IP

- (Union)returnsUnion; // expected-note 2 {{method 'returnsUnion' that returns 'Union' declared here}}

@end

typedef __attribute__((__ext_vector_type__(3))) float float3;
typedef int int4 __attribute__ ((vector_size (16)));

@interface I : Base<IP>

- (Rectangle)returnsStruct; // expected-note 4 {{method 'returnsStruct' that returns 'Rectangle' declared here}}
- (id)returnsId; // shadows base 'returnsId'
- (int)returnsInt;
- (I *)returnPtr;
- (float3)returnsExtVector; // expected-note {{method 'returnsExtVector' that returns 'float3' (vector of 3 'float' values) declared here}}
- (int4)returnsVector; // expected-note {{method 'returnsVector' that returns 'int4' (vector of 4 'int' values) declared here}}

+ (Rectangle)returnsStructClass; // expected-note 2 {{method 'returnsStructClass' that returns 'Rectangle' declared here}}
+ (void)returnsUnion; // Not really

@end

void foo(I *i) {
  [i performSelector: @selector(returnsStruct)]; // expected-warning {{'performSelector:' is incompatible with selectors that return a struct type}}
  [i performSelectorInBackground: @selector(returnsStruct) withObject:0]; // expected-warning {{'performSelectorInBackground:withObject:' is incompatible with selectors that return a struct type}}
  [i performSelector: ((@selector(returnsUnion)))]; // expected-warning {{'performSelector:' is incompatible with selectors that return a union type}}
  [i performSelectorOnMainThread: @selector(returnsStruct2)]; // expected-warning {{'performSelectorOnMainThread:' is incompatible with selectors that return a struct type}}
  [I performSelector: (@selector(returnsStructClass))]; // expected-warning {{'performSelector:' is incompatible with selectors that return a struct type}}

  [i performSelector: @selector(returnsId)];
  [i performSelector: @selector(returnsInt)];
  [i performSelector: @selector(returnsPtr)];
  [I performSelector: @selector(returnsUnion)]; // No warning expected

  id obj = i;
  [obj performSelector: @selector(returnsId)];
  [obj performSelector: @selector(returnsStruct)];
}

@interface SubClass: I

@end

@interface SubClass ()
- (struct Struct)returnsSubStructExt; // expected-note {{method 'returnsSubStructExt' that returns 'struct Struct' declared here}} expected-note {{method 'returnsSubStructExt' declared here}}
@end

@implementation SubClass // expected-warning {{method definition for 'returnsSubStructExt' not found}}

- (struct Struct)returnsSubStructImpl { // expected-note {{method 'returnsSubStructImpl' that returns 'struct Struct' declared here}}
  struct Struct Result;
  return Result;
}

- (void)checkPrivateCalls {
  [self performSelector: @selector(returnsSubStructExt)]; // expected-warning {{'performSelector:' is incompatible with selectors that return a struct type}}
  [self performSelector: @selector(returnsSubStructImpl)]; // expected-warning {{'performSelector:' is incompatible with selectors that return a struct type}}
}

- (void)checkSuperCalls {
  [super performSelector: @selector(returnsStruct)]; // expected-warning {{'performSelector:' is incompatible with selectors that return a struct type}}
  [super performSelectorInBackground: @selector(returnsUnion) withObject: self]; // expected-warning {{'performSelectorInBackground:withObject:' is incompatible with selectors that return a union type}}
  [super performSelector: @selector(returnsId)];
}

+ (struct Struct)returnsSubStructClassImpl { // expected-note {{method 'returnsSubStructClassImpl' that returns 'struct Struct' declared here}}
  struct Struct Result;
  return Result;
}

+ (void)checkClassPrivateCalls {
  [self performSelector: @selector(returnsSubStructClassImpl)]; // expected-warning {{'performSelector:' is incompatible with selectors that return a struct type}}
}

+ (void)checkClassSuperCalls {
  [super performSelector: @selector(returnsStructClass)]; // expected-warning {{'performSelector:' is incompatible with selectors that return a struct type}}
  [super performSelector: @selector(returnsUnion)]; // No warning expected
}

@end

@implementation I (LongPerformSelectors)

- (void)checkLongCallsFromCategory {
  [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}}
}

- (void)checkVectorReturn {
  [self performSelector: @selector(returnsExtVector)]; // expected-warning {{'performSelector:' is incompatible with selectors that return a vector type}}
  [self performSelector: @selector(returnsVector)]; // expected-warning {{'performSelector:' is incompatible with selectors that return a vector type}}
}

@end