Home | History | Annotate | Download | only in inlining
      1 // RUN: %clang --analyze -Xanalyzer -analyzer-checker=osx.cocoa.IncompatibleMethodTypes,osx.coreFoundation.CFRetainRelease -Xclang -verify %s
      2 
      3 #include "InlineObjCInstanceMethod.h"
      4 
      5 typedef const struct __CFString * CFStringRef;
      6 typedef const void * CFTypeRef;
      7 extern CFTypeRef CFRetain(CFTypeRef cf);
      8 extern void CFRelease(CFTypeRef cf);
      9 extern CFStringRef getString(void);
     10 
     11 // Method is defined in the parent; called through self.
     12 @interface MyParent : NSObject
     13 - (int)getInt;
     14 - (const struct __CFString *) testCovariantReturnType __attribute__((cf_returns_retained));
     15 @end
     16 @implementation MyParent
     17 - (int)getInt {
     18     return 0;
     19 }
     20 
     21 - (CFStringRef) testCovariantReturnType __attribute__((cf_returns_retained)) {
     22   CFStringRef Str = ((void*)0);
     23   Str = getString();
     24   if (Str) {
     25     CFRetain(Str);
     26   }
     27   return Str;
     28 }
     29 
     30 @end
     31 
     32 @interface MyClass : MyParent
     33 @end
     34 @implementation MyClass
     35 - (int)testDynDispatchSelf {
     36   int y = [self getInt];
     37   return 5/y; // expected-warning {{Division by zero}}
     38 }
     39 
     40 // Get the dynamic type info from a cast (from id to MyClass*).
     41 + (int)testAllocInit {
     42   MyClass *a = [[self alloc] init];
     43   return 5/[a getInt]; // expected-warning {{Division by zero}}
     44 }
     45 
     46 // Method is called on inited object.
     47 + (int)testAllocInit2 {
     48   MyClass *a = [[MyClass alloc] init];
     49   return 5/[a getInt]; // expected-warning {{Division by zero}}
     50 }
     51 
     52 // Method is called on a parameter.
     53 + (int)testParam: (MyClass*) a {
     54   return 5/[a getInt]; // expected-warning {{Division by zero}}
     55 }
     56 
     57 // Method is called on a parameter of unnown type.
     58 + (int)testParamUnknownType: (id) a {
     59   return 5/[a getInt]; // no warning
     60 }
     61 
     62 @end
     63 
     64 // TODO: When method is inlined, the attribute reset should be visible.
     65 @interface TestSettingAnAttributeInCallee : NSObject {
     66   int _attribute;
     67 }
     68   - (void) method2;
     69 @end
     70 
     71 @implementation TestSettingAnAttributeInCallee
     72 - (int) method1 {
     73   [self method2];
     74   return 5/_attribute; // expected-warning {{Division by zero}}
     75 }
     76 
     77 - (void) method2 {
     78   _attribute = 0;
     79 }
     80 @end
     81 
     82 @interface TestSettingAnAttributeInCaller : NSObject {
     83   int _attribute;
     84 }
     85   - (int) method2;
     86 @end
     87 
     88 @implementation TestSettingAnAttributeInCaller
     89 - (void) method1 {
     90   _attribute = 0;
     91   [self method2];
     92 }
     93 
     94 - (int) method2 {
     95   return 5/_attribute; // expected-warning {{Division by zero}}
     96 }
     97 @end
     98 
     99 
    100 // Don't crash if we don't know the receiver's region.
    101 void randomlyMessageAnObject(MyClass *arr[], int i) {
    102   (void)[arr[i] getInt];
    103 }
    104 
    105 
    106 @interface EvilChild : MyParent
    107 - (id)getInt;
    108 - (const struct __CFString *) testCovariantReturnType __attribute__((cf_returns_retained));
    109 @end
    110 
    111 @implementation EvilChild
    112 - (id)getInt { // expected-warning {{types are incompatible}}
    113   return self;
    114 }
    115 - (CFStringRef) testCovariantReturnType __attribute__((cf_returns_retained)) {
    116   CFStringRef Str = ((void*)0);
    117   Str = getString();
    118   if (Str) {
    119     CFRetain(Str);
    120   }
    121   return Str;
    122 }
    123 
    124 @end
    125 
    126 int testNonCovariantReturnType() {
    127   MyParent *obj = [[EvilChild alloc] init];
    128 
    129   // Devirtualization allows us to directly call -[EvilChild getInt], but
    130   // that returns an id, not an int. There is an off-by-default warning for
    131   // this, -Woverriding-method-mismatch, and an on-by-default analyzer warning,
    132   // osx.cocoa.IncompatibleMethodTypes. This code would probably crash at
    133   // runtime, but at least the analyzer shouldn't crash.
    134   int x = 1 + [obj getInt];
    135 
    136   [obj release];
    137   return 5/(x-1); // no-warning
    138 }
    139 
    140 int testCovariantReturnTypeNoErrorSinceTypesMatch() {
    141   MyParent *obj = [[EvilChild alloc] init];
    142 
    143   CFStringRef S = ((void*)0);
    144   S = [obj testCovariantReturnType];
    145   if (S)
    146     CFRelease(S);
    147   CFRelease(obj);
    148 }
    149