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 | |
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 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 {{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. |
109 | TestObject * _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 | |
114 | TestObject * _Nonnull returnsNilObjCInstanceIndirectlyWithSupressingCast() { |
115 | TestObject *local = nil; |
116 | return (TestObject * _Nonnull)local; // no-warning |
117 | } |
118 | |
119 | TestObject * _Nonnull returnsNilObjCInstanceDirectly() { |
120 | return nil; // expected-warning {{nil 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 {{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 | |
151 | void 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 | |
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{{nil passed to a callee that requires a non-null 1st parameter}} |
169 | #endif |
170 | } |
171 | |