1// RUN: %clang_analyze_cc1 -fobjc-arc -analyzer-checker=core,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull -DNOSYSTEMHEADERS=0 -verify %s
2// RUN: %clang_analyze_cc1 -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
6int getRandom();
7
8typedef struct Dummy { int val; } Dummy;
9
10void takesNullable(Dummy *_Nullable);
11void takesNonnull(Dummy *_Nonnull);
12Dummy *_Nullable returnsNullable();
13
14void 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
25Dummy *_Nonnull testNullReturn() {
26  Dummy *p = 0;
27  return p; // expected-warning {{Null returned from a function that is expected to return a non-null value}}
28}
29
30void 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
40Dummy *_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
54Dummy *_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
67void testPreconditionViolationInInlinedFunction(Dummy *p) {
68  doNotWarnWhenPreconditionIsViolated(p);
69}
70
71void inlinedNullable(Dummy *_Nullable p) {
72  if (p) return;
73}
74void inlinedNonnull(Dummy *_Nonnull p) {
75  if (p) return;
76}
77void inlinedUnspecified(Dummy *p) {
78  if (p) return;
79}
80
81Dummy *_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
95TestObject *_Nonnull getNonnullTestObject();
96
97void testObjCARCImplicitZeroInitialization() {
98  TestObject * _Nonnull implicitlyZeroInitialized; // no-warning
99  implicitlyZeroInitialized = getNonnullTestObject();
100}
101
102void testObjCARCExplicitZeroInitialization() {
103  TestObject * _Nonnull explicitlyZeroInitialized = nil; // expected-warning {{nil 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.
109TestObject * _Nonnull returnsNilObjCInstanceIndirectly() {
110  TestObject *local = nil;
111  return local; // expected-warning {{nil returned from a function that is expected to return a non-null value}}
112}
113
114TestObject * _Nonnull returnsNilObjCInstanceIndirectlyWithSupressingCast() {
115  TestObject *local = nil;
116  return (TestObject * _Nonnull)local; // no-warning
117}
118
119TestObject * _Nonnull returnsNilObjCInstanceDirectly() {
120  return nil; // expected-warning {{nil returned from a function that is expected to return a non-null value}}
121}
122
123TestObject * _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 {{nil 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
151void callFunctionInSystemHeader() {
152  NSString *s;
153  s = nil;
154
155  NSSystemFunctionTakingNonnull(s);
156  #if !NOSYSTEMHEADERS
157  // expected-warning@-2{{nil passed to a callee that requires a non-null 1st parameter}}
158  #endif
159}
160
161void 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{{nil passed to a callee that requires a non-null 1st parameter}}
169  #endif
170}
171