Home | History | Annotate | Download | only in inlining
      1 // RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-config suppress-inlined-defensive-checks=true -verify %s
      2 
      3 typedef signed char BOOL;
      4 typedef struct objc_class *Class;
      5 typedef struct objc_object {
      6   Class isa;
      7 } *id;
      8 @protocol NSObject  - (BOOL)isEqual:(id)object; @end
      9 @interface NSObject <NSObject> {}
     10 +(id)alloc;
     11 +(id)new;
     12 -(id)init;
     13 -(id)autorelease;
     14 -(id)copy;
     15 - (Class)class;
     16 -(id)retain;
     17 @end
     18 
     19 // Check that inline defensive checks is triggered for null expressions
     20 // within CompoundLiteralExpr.
     21 typedef union {
     22   struct dispatch_object_s *_do;
     23   struct dispatch_source_s *_ds;
     24 } dispatch_object_t __attribute__((__transparent_union__));
     25 typedef struct dispatch_source_s *dispatch_source_t;
     26 
     27 extern __attribute__((visibility("default"))) __attribute__((__nonnull__)) __attribute__((__nothrow__))
     28 void
     29 dispatch_resume(dispatch_object_t object);
     30 
     31 @interface AppDelegate : NSObject {
     32 @protected
     33 	dispatch_source_t p;
     34 }
     35 @end
     36 @implementation AppDelegate
     37 - (void)updateDeleteTimer {
     38 	if (p != ((void*)0))
     39 		;
     40 }
     41 - (void)createAndStartDeleteTimer {
     42   [self updateDeleteTimer];
     43   dispatch_resume(p); // no warning
     44 }
     45 @end
     46 
     47 // Test nil receiver suppression.
     48 // We only suppress on nil receiver if the nil value is directly causing the bug.
     49 @interface Foo {
     50 @public
     51   int x;
     52 }
     53 - (Foo *)getFooPtr;
     54 @end
     55 
     56 Foo *retNil() {
     57   return 0;
     58 }
     59 
     60 Foo *retInputOrNil(Foo *p) {
     61   if (p)
     62     return p;
     63   return 0;
     64 }
     65 
     66 void idc(Foo *p) {
     67   if (p)
     68     ;
     69 }
     70 
     71 int testNilReceiver(Foo* fPtr) {
     72   if (fPtr)
     73     ;
     74   // On a path where fPtr is nil, mem should be nil.
     75   Foo *mem = [fPtr getFooPtr];
     76   return mem->x; // expected-warning {{Access to instance variable 'x' results in a dereference of a null pointer}}
     77 }
     78 
     79 int suppressNilReceiverRetNullCond(Foo* fPtr) {
     80   unsigned zero = 0;
     81   fPtr = retInputOrNil(fPtr);
     82   // On a path where fPtr is nzil, mem should be nil.
     83   Foo *mem = [fPtr getFooPtr];
     84   return mem->x;
     85 }
     86 
     87 int suppressNilReceiverRetNullCondCast(id fPtr) {
     88   unsigned zero = 0;
     89   fPtr = retInputOrNil(fPtr);
     90   // On a path where fPtr is nzil, mem should be nil.
     91   Foo *mem = ((id)([(Foo*)(fPtr) getFooPtr]));
     92   return mem->x;
     93 }
     94 
     95 int dontSuppressNilReceiverRetNullCond(Foo* fPtr) {
     96   unsigned zero = 0;
     97   fPtr = retInputOrNil(fPtr);
     98   // On a path where fPtr is nil, mem should be nil.
     99   // The warning is not suppressed because the receiver being nil is not
    100   // directly related to the value that triggers the warning.
    101   Foo *mem = [fPtr getFooPtr];
    102   if (!mem)
    103     return 5/zero; // expected-warning {{Division by zero}}
    104   return 0;
    105 }
    106 
    107 int dontSuppressNilReceiverRetNull(Foo* fPtr) {
    108   unsigned zero = 0;
    109   fPtr = retNil();
    110   // On a path where fPtr is nil, mem should be nil.
    111   // The warning is not suppressed because the receiver being nil is not
    112   // directly related to the value that triggers the warning.
    113   Foo *mem = [fPtr getFooPtr];
    114   if (!mem)
    115     return 5/zero; // expected-warning {{Division by zero}}
    116   return 0;
    117 }
    118 
    119 int dontSuppressNilReceiverIDC(Foo* fPtr) {
    120   unsigned zero = 0;
    121   idc(fPtr);
    122   // On a path where fPtr is nil, mem should be nil.
    123   // The warning is not suppressed because the receiver being nil is not
    124   // directly related to the value that triggers the warning.
    125   Foo *mem = [fPtr getFooPtr];
    126   if (!mem)
    127     return 5/zero; // expected-warning {{Division by zero}}
    128   return 0;
    129 }
    130