Home | History | Annotate | Download | only in SemaObjC
      1 // RUN: %clang_cc1 -verify -Wno-deprecated-declarations -Wno-objc-root-class %s
      2 
      3 @interface Unrelated
      4 @end
      5 
      6 @interface NSObject
      7 + (id)new;
      8 + (id)alloc;
      9 - (NSObject *)init;
     10 
     11 - (id)retain;  // expected-note{{instance method 'retain' is assumed to return an instance of its receiver type ('NSArray *')}}
     12 - autorelease;
     13 
     14 - (id)self;
     15 
     16 - (id)copy;
     17 - (id)mutableCopy;
     18 
     19 // Do not infer when instance/class mismatches
     20 - (id)newNotInferred;
     21 - (id)alloc;
     22 + (id)initWithBlarg;
     23 + (id)self;
     24 
     25 // Do not infer when the return types mismatch.
     26 - (Unrelated *)initAsUnrelated;
     27 @end
     28 
     29 @interface NSString : NSObject
     30 - (id)init;
     31 - (id)initWithCString:(const char*)string;
     32 @end
     33 
     34 @interface NSArray : NSObject
     35 - (unsigned)count;
     36 @end
     37 
     38 @interface NSBlah 
     39 @end
     40 
     41 @interface NSMutableArray : NSArray
     42 @end
     43 
     44 @interface NSBlah ()
     45 + (Unrelated *)newUnrelated;
     46 @end
     47 
     48 void test_inference() {
     49   // Inference based on method family
     50   __typeof__(([[NSString alloc] init])) *str = (NSString**)0;
     51   __typeof__(([[[[NSString new] self] retain] autorelease])) *str2 = (NSString **)0;
     52   __typeof__(([[NSString alloc] initWithCString:"blah"])) *str3 = (NSString**)0;
     53 
     54   // Not inferred
     55   __typeof__(([[NSString new] copy])) *id1 = (id*)0;
     56 
     57   // Not inferred due to instance/class mismatches
     58   __typeof__(([[NSString new] newNotInferred])) *id2 = (id*)0;
     59   __typeof__(([[NSString new] alloc])) *id3 = (id*)0;
     60   __typeof__(([NSString self])) *id4 = (id*)0;
     61   __typeof__(([NSString initWithBlarg])) *id5 = (id*)0;
     62 
     63   // Not inferred due to return type mismatch
     64   __typeof__(([[NSString alloc] initAsUnrelated])) *unrelated = (Unrelated**)0;
     65   __typeof__(([NSBlah newUnrelated])) *unrelated2 = (Unrelated**)0;
     66 
     67   
     68   NSArray *arr = [[NSMutableArray alloc] init];
     69   NSMutableArray *marr = [arr retain]; // expected-warning{{incompatible pointer types initializing 'NSMutableArray *' with an expression of type 'NSArray *'}}
     70 }
     71 
     72 @implementation NSBlah
     73 + (Unrelated *)newUnrelated {
     74   return (Unrelated *)0;
     75 }
     76 @end
     77 
     78 @implementation NSBlah (Cat)
     79 + (Unrelated *)newUnrelated2 {
     80   return (Unrelated *)0;
     81 }
     82 @end
     83 
     84 @interface A
     85 - (id)initBlah; // expected-note 2{{overridden method is part of the 'init' method family}}
     86 @end
     87 
     88 @interface B : A
     89 - (Unrelated *)initBlah; // expected-warning{{method is expected to return an instance of its class type 'B', but is declared to return 'Unrelated *'}}
     90 @end
     91 
     92 @interface C : A
     93 @end
     94 
     95 @implementation C
     96 - (Unrelated *)initBlah {  // expected-warning{{method is expected to return an instance of its class type 'C', but is declared to return 'Unrelated *'}}
     97   return (Unrelated *)0;
     98 }
     99 @end
    100 
    101 @interface D
    102 + (id)newBlarg; // expected-note{{overridden method is part of the 'new' method family}}
    103 @end
    104 
    105 @interface D ()
    106 + alloc; // expected-note{{overridden method is part of the 'alloc' method family}}
    107 @end
    108 
    109 @implementation D
    110 + (Unrelated *)newBlarg { // expected-warning{{method is expected to return an instance of its class type 'D', but is declared to return 'Unrelated *'}}
    111   return (Unrelated *)0;
    112 }
    113 
    114 + (Unrelated *)alloc { // expected-warning{{method is expected to return an instance of its class type 'D', but is declared to return 'Unrelated *'}}
    115   return (Unrelated *)0;
    116 }
    117 @end
    118 
    119 @protocol P1
    120 - (id)initBlah; // expected-note{{overridden method is part of the 'init' method family}}
    121 - (int)initBlarg;
    122 @end
    123 
    124 @protocol P2 <P1>
    125 - (int)initBlah; // expected-warning{{protocol method is expected to return an instance of the implementing class, but is declared to return 'int'}}
    126 - (int)initBlarg;
    127 - (int)initBlech;
    128 @end
    129 
    130 @interface E
    131 - init;
    132 @end
    133 
    134 @implementation E
    135 - init {
    136   return self;
    137 }
    138 @end
    139 
    140 @protocol P3
    141 + (NSString *)newString;
    142 @end
    143 
    144 @interface F<P3>
    145 @end
    146 
    147 @implementation F
    148 + (NSString *)newString { return @"blah"; }
    149 @end
    150 
    151 // <rdar://problem/9340699>
    152 @interface G 
    153 - (id)_ABC_init __attribute__((objc_method_family(init))); // expected-note {{method '_ABC_init' declared here}}
    154 @end
    155 
    156 @interface G (Additions)
    157 - (id)_ABC_init2 __attribute__((objc_method_family(init)));
    158 @end
    159 
    160 @implementation G (Additions)
    161 - (id)_ABC_init { // expected-warning {{category is implementing a method which will also be implemented by its primary class}}
    162   return 0;
    163 }
    164 - (id)_ABC_init2 {
    165   return 0;
    166 }
    167 - (id)_ABC_init3 {
    168   return 0;
    169 }
    170 @end
    171 
    172 // PR12384
    173 @interface Fail @end
    174 @protocol X @end
    175 @implementation Fail
    176 - (id<X>) initWithX
    177 {
    178   return (id)self; // expected-warning {{returning 'Fail *' from a function with incompatible result type 'id<X>'}}
    179 }
    180 @end
    181 
    182 // <rdar://problem/11460990>
    183 
    184 @interface WeirdNSString : NSString
    185 - (id)initWithCString:(const char*)string, void *blah;
    186 @end
    187