Home | History | Annotate | Download | only in Rewriter
      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