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