Home | History | Annotate | Download | only in Analysis
      1 // RUN: %clang_cc1 -analyze -fobjc-arc -analyzer-checker=core,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull -DNOSYSTEMHEADERS=0 -verify %s
      2 // RUN: %clang_cc1 -analyze -fobjc-arc -analyzer-checker=core,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull -analyzer-config nullability:NoDiagnoseCallsToSystemHeaders=true -DNOSYSTEMHEADERS=1 -verify %s
      3 
      4 #include "Inputs/system-header-simulator-for-nullability.h"
      5 
      6 int getRandom();
      7 
      8 typedef struct Dummy { int val; } Dummy;
      9 
     10 void takesNullable(Dummy *_Nullable);
     11 void takesNonnull(Dummy *_Nonnull);
     12 Dummy *_Nullable returnsNullable();
     13 
     14 void testBasicRules() {
     15   // The tracking of nullable values is turned off.
     16   Dummy *p = returnsNullable();
     17   takesNonnull(p); // no warning
     18   Dummy *q = 0;
     19   if (getRandom()) {
     20     takesNullable(q);
     21     takesNonnull(q); // expected-warning {{Null passed to a callee that requires a non-null 1st parameter}}
     22   }
     23 }
     24 
     25 Dummy *_Nonnull testNullReturn() {
     26   Dummy *p = 0;
     27   return p; // expected-warning {{Null is returned from a function that is expected to return a non-null value}}
     28 }
     29 
     30 void onlyReportFirstPreconditionViolationOnPath() {
     31   Dummy *p = 0;
     32   takesNonnull(p); // expected-warning {{Null passed to a callee that requires a non-null 1st parameter}}
     33   takesNonnull(p); // No warning.
     34   // Passing null to nonnull is a sink. Stop the analysis.
     35   int i = 0;
     36   i = 5 / i; // no warning
     37   (void)i;
     38 }
     39 
     40 Dummy *_Nonnull doNotWarnWhenPreconditionIsViolatedInTopFunc(
     41     Dummy *_Nonnull p) {
     42   if (!p) {
     43     Dummy *ret =
     44         0; // avoid compiler warning (which is not generated by the analyzer)
     45     if (getRandom())
     46       return ret; // no warning
     47     else
     48       return p; // no warning
     49   } else {
     50     return p;
     51   }
     52 }
     53 
     54 Dummy *_Nonnull doNotWarnWhenPreconditionIsViolated(Dummy *_Nonnull p) {
     55   if (!p) {
     56     Dummy *ret =
     57         0; // avoid compiler warning (which is not generated by the analyzer)
     58     if (getRandom())
     59       return ret; // no warning
     60     else
     61       return p; // no warning
     62   } else {
     63     return p;
     64   }
     65 }
     66 
     67 void testPreconditionViolationInInlinedFunction(Dummy *p) {
     68   doNotWarnWhenPreconditionIsViolated(p);
     69 }
     70 
     71 void inlinedNullable(Dummy *_Nullable p) {
     72   if (p) return;
     73 }
     74 void inlinedNonnull(Dummy *_Nonnull p) {
     75   if (p) return;
     76 }
     77 void inlinedUnspecified(Dummy *p) {
     78   if (p) return;
     79 }
     80 
     81 Dummy *_Nonnull testDefensiveInlineChecks(Dummy * p) {
     82   switch (getRandom()) {
     83   case 1: inlinedNullable(p); break;
     84   case 2: inlinedNonnull(p); break;
     85   case 3: inlinedUnspecified(p); break;
     86   }
     87   if (getRandom())
     88     takesNonnull(p);
     89   return p;
     90 }
     91 
     92 @interface TestObject : NSObject
     93 @end
     94 
     95 TestObject *_Nonnull getNonnullTestObject();
     96 
     97 void testObjCARCImplicitZeroInitialization() {
     98   TestObject * _Nonnull implicitlyZeroInitialized; // no-warning
     99   implicitlyZeroInitialized = getNonnullTestObject();
    100 }
    101 
    102 void testObjCARCExplicitZeroInitialization() {
    103   TestObject * _Nonnull explicitlyZeroInitialized = nil; // expected-warning {{Null is assigned to a pointer which is expected to have non-null value}}
    104 }
    105 
    106 // Under ARC, returned expressions of ObjC objects types are are implicitly
    107 // cast to _Nonnull when the functions return type is _Nonnull, so make
    108 // sure this doesn't implicit cast doesn't suppress a legitimate warning.
    109 TestObject * _Nonnull returnsNilObjCInstanceIndirectly() {
    110   TestObject *local = 0;
    111   return local; // expected-warning {{Null is returned from a function that is expected to return a non-null value}}
    112 }
    113 
    114 TestObject * _Nonnull returnsNilObjCInstanceIndirectlyWithSupressingCast() {
    115   TestObject *local = 0;
    116   return (TestObject * _Nonnull)local; // no-warning
    117 }
    118 
    119 TestObject * _Nonnull returnsNilObjCInstanceDirectly() {
    120   return nil; // expected-warning {{Null is returned from a function that is expected to return a non-null value}}
    121 }
    122 
    123 TestObject * _Nonnull returnsNilObjCInstanceDirectlyWithSuppressingCast() {
    124   return (TestObject * _Nonnull)nil; // no-warning
    125 }
    126 
    127 @interface SomeClass : NSObject
    128 @end
    129 
    130 @implementation SomeClass (MethodReturn)
    131 - (SomeClass * _Nonnull)testReturnsNilInNonnull {
    132   SomeClass *local = nil;
    133   return local; // expected-warning {{Null is returned from a method that is expected to return a non-null value}}
    134 }
    135 
    136 - (SomeClass * _Nonnull)testReturnsCastSuppressedNilInNonnull {
    137   SomeClass *local = nil;
    138   return (SomeClass * _Nonnull)local; // no-warning
    139 }
    140 
    141 - (SomeClass * _Nonnull)testReturnsNilInNonnullWhenPreconditionViolated:(SomeClass * _Nonnull) p {
    142   SomeClass *local = nil;
    143   if (!p) // Pre-condition violated here.
    144     return local; // no-warning
    145   else
    146     return p; // no-warning
    147 }
    148 @end
    149 
    150 
    151 void callFunctionInSystemHeader() {
    152   NSString *s;
    153   s = nil;
    154 
    155   NSSystemFunctionTakingNonnull(s);
    156   #if !NOSYSTEMHEADERS
    157   // expected-warning@-2{{Null passed to a callee that requires a non-null 1st parameter}}
    158   #endif
    159 }
    160 
    161 void callMethodInSystemHeader() {
    162   NSString *s;
    163   s = nil;
    164 
    165   NSSystemClass *sc = [[NSSystemClass alloc] init];
    166   [sc takesNonnull:s];
    167   #if !NOSYSTEMHEADERS
    168   // expected-warning@-2{{Null passed to a callee that requires a non-null 1st parameter}}
    169   #endif
    170 }
    171