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