Home | History | Annotate | Download | only in Analysis
      1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,nullability -verify %s
      2 
      3 #define nil 0
      4 
      5 @protocol NSObject
      6 + (id)alloc;
      7 - (id)init;
      8 - (instancetype)autorelease;
      9 - (void)release;
     10 @end
     11 
     12 __attribute__((objc_root_class))
     13 @interface
     14 NSObject<NSObject>
     15 @end
     16 
     17 @interface TestObject : NSObject
     18 @end
     19 
     20 TestObject * _Nonnull returnsNilObjCInstanceIndirectly() {
     21   TestObject *local = 0;
     22   return local; // expected-warning {{Null is returned from a function that is expected to return a non-null value}}
     23 }
     24 
     25 TestObject * _Nonnull returnsNilObjCInstanceIndirectlyWithSupressingCast() {
     26   TestObject *local = 0;
     27   return (TestObject * _Nonnull)local; // no-warning
     28 }
     29 
     30 TestObject * _Nonnull returnsNilObjCInstanceDirectly() {
     31   // The first warning is from Sema. The second is from the static analyzer.
     32   return nil; // expected-warning {{null returned from function that requires a non-null return value}}
     33               // expected-warning@-1 {{Null is returned from a function that is expected to return a non-null value}}
     34 }
     35 
     36 TestObject * _Nonnull returnsNilObjCInstanceDirectlyWithSuppressingCast() {
     37   return (TestObject * _Nonnull)nil; // no-warning
     38 }
     39 
     40 void testObjCNonARCNoInitialization(TestObject * _Nonnull p) {
     41   TestObject * _Nonnull implicitlyZeroInitialized; // no-warning
     42   implicitlyZeroInitialized = p;
     43 }
     44 
     45 void testObjCNonARCExplicitZeroInitialization() {
     46   TestObject * _Nonnull explicitlyZeroInitialized = nil; // expected-warning {{Null is assigned to a pointer which is expected to have non-null value}}
     47 }
     48 
     49 @interface ClassWithInitializers : NSObject
     50 @end
     51 
     52 @implementation ClassWithInitializers
     53 - (instancetype _Nonnull)initWithNonnullReturnAndSelfCheckingIdiom {
     54   // This defensive check is a common-enough idiom that we don't want
     55   // to issue a diagnostic for it.
     56   if (self = [super init]) {
     57   }
     58 
     59   return self; // no-warning
     60 }
     61 
     62 - (instancetype _Nonnull)initWithNonnullReturnAndNilReturnViaLocal {
     63   self = [super init];
     64   // This leaks, but we're not checking for that here.
     65 
     66   ClassWithInitializers *other = nil;
     67   // False negative. Once we have more subtle suppression of defensive checks in
     68   // initializers we should warn here.
     69   return other;
     70 }
     71 
     72 - (instancetype _Nonnull)initWithPreconditionViolation:(int)p {
     73   self = [super init];
     74   if (p < 0) {
     75     [self release];
     76     return (ClassWithInitializers * _Nonnull)nil;
     77   }
     78   return self;
     79 }
     80 
     81 + (instancetype _Nonnull)factoryCallingInitWithNonnullReturnAndSelfCheckingIdiom {
     82   return [[[self alloc] initWithNonnullReturnAndSelfCheckingIdiom] autorelease]; // no-warning
     83 }
     84 
     85 + (instancetype _Nonnull)factoryCallingInitWithNonnullReturnAndNilReturnViaLocal {
     86   return [[[self alloc] initWithNonnullReturnAndNilReturnViaLocal] autorelease]; // no-warning
     87 }
     88 
     89 + (instancetype _Nonnull)initWithPreconditionViolation:(int) p {
     90   return [[[self alloc] initWithPreconditionViolation:p] autorelease]; // no-warning
     91 }
     92 
     93 - (TestObject * _Nonnull) returnsNil {
     94   return (TestObject * _Nonnull)nil;
     95 }
     96 - (TestObject * _Nonnull) inlineOfReturnsNilObjCInstanceDirectlyWithSuppressingCast {
     97   TestObject *o = [self returnsNil];
     98   return o;
     99 }
    100 @end
    101