]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - test/Analysis/inlining/false-positive-suppression.c
Vendor import of clang release_34 branch r197841 (effectively, 3.4 RC3):
[FreeBSD/FreeBSD.git] / test / Analysis / inlining / false-positive-suppression.c
1 // RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-config suppress-null-return-paths=false -verify %s
2 // RUN: %clang_cc1 -analyze -analyzer-checker=core -verify -DSUPPRESSED=1 %s
3 // RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-config avoid-suppressing-null-argument-paths=true -DSUPPRESSED=1 -DNULL_ARGS=1 -verify %s
4
5 int opaquePropertyCheck(void *object);
6 int coin();
7
8 int *getNull() {
9   return 0;
10 }
11
12 int* getPtr();
13
14 int *dynCastToInt(void *ptr) {
15   if (opaquePropertyCheck(ptr))
16     return (int *)ptr;
17   return 0;
18 }
19
20 int *dynCastOrNull(void *ptr) {
21   if (!ptr)
22     return 0;
23   if (opaquePropertyCheck(ptr))
24     return (int *)ptr;
25   return 0;
26 }
27
28
29 void testDynCast(void *p) {
30   int *casted = dynCastToInt(p);
31   *casted = 1;
32 #ifndef SUPPRESSED
33   // expected-warning@-2 {{Dereference of null pointer}}
34 #endif
35 }
36
37 void testDynCastOrNull(void *p) {
38   int *casted = dynCastOrNull(p);
39   *casted = 1;
40 #ifndef SUPPRESSED
41   // expected-warning@-2 {{Dereference of null pointer}}
42 #endif
43 }
44
45
46 void testBranch(void *p) {
47   int *casted;
48
49   // Although the report will be suppressed on one branch, it should still be
50   // valid on the other.
51   if (coin()) {
52     casted = dynCastToInt(p);
53   } else {
54     if (p)
55       return;
56     casted = (int *)p;
57   }
58
59   *casted = 1; // expected-warning {{Dereference of null pointer}}
60 }
61
62 void testBranchReversed(void *p) {
63   int *casted;
64
65   // Although the report will be suppressed on one branch, it should still be
66   // valid on the other.
67   if (coin()) {
68     if (p)
69       return;
70     casted = (int *)p;
71   } else {
72     casted = dynCastToInt(p);
73   }
74
75   *casted = 1; // expected-warning {{Dereference of null pointer}}
76 }
77
78 void testMultipleStore(void *p) {
79   int *casted = 0;
80   casted = dynCastToInt(p);
81   *casted = 1;
82 #ifndef SUPPRESSED
83   // expected-warning@-2 {{Dereference of null pointer}}
84 #endif
85 }
86
87 // Test that div by zero does not get suppressed. This is a policy choice.
88 int retZero() {
89   return 0;
90 }
91 int triggerDivZero () {
92   int y = retZero();
93   return 5/y; // expected-warning {{Division by zero}}
94 }
95
96 // --------------------------
97 // "Suppression suppression"
98 // --------------------------
99
100 void testDynCastOrNullOfNull() {
101   // Don't suppress when one of the arguments is NULL.
102   int *casted = dynCastOrNull(0);
103   *casted = 1;
104 #if !SUPPRESSED || NULL_ARGS
105   // expected-warning@-2 {{Dereference of null pointer}}
106 #endif
107 }
108
109 void testDynCastOfNull() {
110   // Don't suppress when one of the arguments is NULL.
111   int *casted = dynCastToInt(0);
112   *casted = 1;
113 #if !SUPPRESSED || NULL_ARGS
114   // expected-warning@-2 {{Dereference of null pointer}}
115 #endif
116 }
117
118 int *lookUpInt(int unused) {
119   if (coin())
120     return 0;
121   static int x;
122   return &x;
123 }
124
125 void testZeroIsNotNull() {
126   // /Do/ suppress when the argument is 0 (an integer).
127   int *casted = lookUpInt(0);
128   *casted = 1;
129 #ifndef SUPPRESSED
130   // expected-warning@-2 {{Dereference of null pointer}}
131 #endif
132 }
133
134 void testTrackNull() {
135   // /Do/ suppress if the null argument came from another call returning null.
136   int *casted = dynCastOrNull(getNull());
137   *casted = 1;
138 #ifndef SUPPRESSED
139   // expected-warning@-2 {{Dereference of null pointer}}
140 #endif
141 }
142
143 void testTrackNullVariable() {
144   // /Do/ suppress if the null argument came from another call returning null.
145   int *ptr;
146   ptr = getNull();
147   int *casted = dynCastOrNull(ptr);
148   *casted = 1;
149 #ifndef SUPPRESSED
150   // expected-warning@-2 {{Dereference of null pointer}}
151 #endif
152 }
153
154 void inlinedIsDifferent(int inlined) {
155   int i;
156
157   // We were erroneously picking up the inner stack frame's initialization,
158   // even though the error occurs in the outer stack frame!
159   int *p = inlined ? &i : getNull();
160
161   if (!inlined)
162     inlinedIsDifferent(1);
163
164   *p = 1;
165 #ifndef SUPPRESSED
166   // expected-warning@-2 {{Dereference of null pointer}}
167 #endif
168 }
169
170 void testInlinedIsDifferent() {
171   // <rdar://problem/13787723>
172   inlinedIsDifferent(0);
173 }
174
175
176 // ---------------------------------------
177 // FALSE NEGATIVES (over-suppression)
178 // ---------------------------------------
179
180 void testNoArguments() {
181   // In this case the function has no branches, and MUST return null.
182   int *casted = getNull();
183   *casted = 1;
184 #ifndef SUPPRESSED
185   // expected-warning@-2 {{Dereference of null pointer}}
186 #endif
187 }
188
189 int *getNullIfNonNull(void *input) {
190   if (input)
191     return 0;
192   static int x;
193   return &x;
194 }
195
196 void testKnownPath(void *input) {
197   if (!input)
198     return;
199
200   // In this case we have a known value for the argument, and thus the path
201   // through the function doesn't ever split.
202   int *casted = getNullIfNonNull(input);
203   *casted = 1;
204 #ifndef SUPPRESSED
205   // expected-warning@-2 {{Dereference of null pointer}}
206 #endif
207 }
208
209 int *alwaysReturnNull(void *input) {
210   if (opaquePropertyCheck(input))
211     return 0;
212   return 0;
213 }
214
215 void testAlwaysReturnNull(void *input) {
216   // In this case all paths out of the function return 0, but they are all
217   // dominated by a branch whose condition we don't know!
218   int *casted = alwaysReturnNull(input);
219   *casted = 1;
220 #ifndef SUPPRESSED
221   // expected-warning@-2 {{Dereference of null pointer}}
222 #endif
223 }
224
225 int derefArg(int *p) {
226         return *p;
227 #ifndef SUPPRESSED
228   // expected-warning@-2 {{Dereference of null pointer}}
229 #endif
230 }
231 void ternaryArg(char cond) {
232         static int x;
233         derefArg(cond ? &x : getNull());
234 }
235
236 int derefArgCast(char *p) {
237         return *p;
238 #ifndef SUPPRESSED
239   // expected-warning@-2 {{Dereference of null pointer}}
240 #endif
241 }
242 void ternaryArgCast(char cond) {
243         static int x;
244         derefArgCast((char*)((unsigned)cond ? &x : getNull()));
245 }
246
247 int derefAssignment(int *p) {
248         return *p;
249 #ifndef SUPPRESSED
250   // expected-warning@-2 {{Dereference of null pointer}}
251 #endif
252 }
253
254 void ternaryAssignment(char cond) {
255   static int x;
256   int *p = cond ? getNull() : getPtr();
257   derefAssignment(p);
258 }
259
260 int *retNull(char cond) {
261   static int x;
262   return cond ? &x : getNull();
263 }
264 int ternaryRetNull(char cond) {
265   int *p = retNull(cond);
266   return *p;
267 #ifndef SUPPRESSED
268   // expected-warning@-2 {{Dereference of null pointer}}
269 #endif
270 }
271
272 // Test suppression of nested conditional operators.
273 int testConditionalOperatorSuppress(int x) {
274   return *(x ? getNull() : getPtr());
275 #ifndef SUPPRESSED
276   // expected-warning@-2 {{Dereference of null pointer}}
277 #endif
278 }
279 int testNestedConditionalOperatorSuppress(int x) {
280   return *(x ? (x ? getNull() : getPtr()) : getPtr());
281 #ifndef SUPPRESSED
282   // expected-warning@-2 {{Dereference of null pointer}}
283 #endif
284 }
285 int testConditionalOperator(int x) {
286   return *(x ? 0 : getPtr()); // expected-warning {{Dereference of null pointer}}
287 }
288 int testNestedConditionalOperator(int x) {
289   return *(x ? (x ? 0 : getPtr()) : getPtr()); // expected-warning {{Dereference of null pointer}}
290 }
291
292 int testConditionalOperatorSuppressFloatCond(float x) {
293   return *(x ? getNull() : getPtr());
294 #ifndef SUPPRESSED
295   // expected-warning@-2 {{Dereference of null pointer}}
296 #endif
297 }
298