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