xref: /aosp_15_r20/external/clang/test/Analysis/inlining/false-positive-suppression.c (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li // RUN: %clang_cc1 -analyze -analyzer-eagerly-assume -analyzer-checker=core -analyzer-config suppress-null-return-paths=false -verify %s
2*67e74705SXin Li // RUN: %clang_cc1 -analyze -analyzer-eagerly-assume -analyzer-checker=core -verify -DSUPPRESSED=1 %s
3*67e74705SXin Li // RUN: %clang_cc1 -analyze -analyzer-eagerly-assume -analyzer-checker=core -analyzer-config avoid-suppressing-null-argument-paths=true -DSUPPRESSED=1 -DNULL_ARGS=1 -verify %s
4*67e74705SXin Li 
5*67e74705SXin Li int opaquePropertyCheck(void *object);
6*67e74705SXin Li int coin();
7*67e74705SXin Li 
getNull()8*67e74705SXin Li int *getNull() {
9*67e74705SXin Li   return 0;
10*67e74705SXin Li }
11*67e74705SXin Li 
12*67e74705SXin Li int* getPtr();
13*67e74705SXin Li 
dynCastToInt(void * ptr)14*67e74705SXin Li int *dynCastToInt(void *ptr) {
15*67e74705SXin Li   if (opaquePropertyCheck(ptr))
16*67e74705SXin Li     return (int *)ptr;
17*67e74705SXin Li   return 0;
18*67e74705SXin Li }
19*67e74705SXin Li 
dynCastOrNull(void * ptr)20*67e74705SXin Li int *dynCastOrNull(void *ptr) {
21*67e74705SXin Li   if (!ptr)
22*67e74705SXin Li     return 0;
23*67e74705SXin Li   if (opaquePropertyCheck(ptr))
24*67e74705SXin Li     return (int *)ptr;
25*67e74705SXin Li   return 0;
26*67e74705SXin Li }
27*67e74705SXin Li 
28*67e74705SXin Li 
testDynCast(void * p)29*67e74705SXin Li void testDynCast(void *p) {
30*67e74705SXin Li   int *casted = dynCastToInt(p);
31*67e74705SXin Li   *casted = 1;
32*67e74705SXin Li #ifndef SUPPRESSED
33*67e74705SXin Li   // expected-warning@-2 {{Dereference of null pointer}}
34*67e74705SXin Li #endif
35*67e74705SXin Li }
36*67e74705SXin Li 
testDynCastOrNull(void * p)37*67e74705SXin Li void testDynCastOrNull(void *p) {
38*67e74705SXin Li   int *casted = dynCastOrNull(p);
39*67e74705SXin Li   *casted = 1;
40*67e74705SXin Li #ifndef SUPPRESSED
41*67e74705SXin Li   // expected-warning@-2 {{Dereference of null pointer}}
42*67e74705SXin Li #endif
43*67e74705SXin Li }
44*67e74705SXin Li 
45*67e74705SXin Li 
testBranch(void * p)46*67e74705SXin Li void testBranch(void *p) {
47*67e74705SXin Li   int *casted;
48*67e74705SXin Li 
49*67e74705SXin Li   // Although the report will be suppressed on one branch, it should still be
50*67e74705SXin Li   // valid on the other.
51*67e74705SXin Li   if (coin()) {
52*67e74705SXin Li     casted = dynCastToInt(p);
53*67e74705SXin Li   } else {
54*67e74705SXin Li     if (p)
55*67e74705SXin Li       return;
56*67e74705SXin Li     casted = (int *)p;
57*67e74705SXin Li   }
58*67e74705SXin Li 
59*67e74705SXin Li   *casted = 1; // expected-warning {{Dereference of null pointer}}
60*67e74705SXin Li }
61*67e74705SXin Li 
testBranchReversed(void * p)62*67e74705SXin Li void testBranchReversed(void *p) {
63*67e74705SXin Li   int *casted;
64*67e74705SXin Li 
65*67e74705SXin Li   // Although the report will be suppressed on one branch, it should still be
66*67e74705SXin Li   // valid on the other.
67*67e74705SXin Li   if (coin()) {
68*67e74705SXin Li     if (p)
69*67e74705SXin Li       return;
70*67e74705SXin Li     casted = (int *)p;
71*67e74705SXin Li   } else {
72*67e74705SXin Li     casted = dynCastToInt(p);
73*67e74705SXin Li   }
74*67e74705SXin Li 
75*67e74705SXin Li   *casted = 1; // expected-warning {{Dereference of null pointer}}
76*67e74705SXin Li }
77*67e74705SXin Li 
testMultipleStore(void * p)78*67e74705SXin Li void testMultipleStore(void *p) {
79*67e74705SXin Li   int *casted = 0;
80*67e74705SXin Li   casted = dynCastToInt(p);
81*67e74705SXin Li   *casted = 1;
82*67e74705SXin Li #ifndef SUPPRESSED
83*67e74705SXin Li   // expected-warning@-2 {{Dereference of null pointer}}
84*67e74705SXin Li #endif
85*67e74705SXin Li }
86*67e74705SXin Li 
87*67e74705SXin Li // Test that div by zero does not get suppressed. This is a policy choice.
retZero()88*67e74705SXin Li int retZero() {
89*67e74705SXin Li   return 0;
90*67e74705SXin Li }
triggerDivZero()91*67e74705SXin Li int triggerDivZero () {
92*67e74705SXin Li   int y = retZero();
93*67e74705SXin Li   return 5/y; // expected-warning {{Division by zero}}
94*67e74705SXin Li }
95*67e74705SXin Li 
96*67e74705SXin Li // Treat a function-like macro similarly to an inlined function, so suppress
97*67e74705SXin Li // warnings along paths resulting from inlined checks.
98*67e74705SXin Li #define MACRO_WITH_CHECK(a) ( ((a) != 0) ? *a : 17)
testInlineCheckInMacro(int * p)99*67e74705SXin Li void testInlineCheckInMacro(int *p) {
100*67e74705SXin Li   int i = MACRO_WITH_CHECK(p);
101*67e74705SXin Li   (void)i;
102*67e74705SXin Li 
103*67e74705SXin Li   *p = 1; // no-warning
104*67e74705SXin Li }
105*67e74705SXin Li 
106*67e74705SXin Li #define MACRO_WITH_NESTED_CHECK(a) ( { int j = MACRO_WITH_CHECK(a); j; } )
testInlineCheckInNestedMacro(int * p)107*67e74705SXin Li void testInlineCheckInNestedMacro(int *p) {
108*67e74705SXin Li   int i = MACRO_WITH_NESTED_CHECK(p);
109*67e74705SXin Li   (void)i;
110*67e74705SXin Li 
111*67e74705SXin Li   *p = 1; // no-warning
112*67e74705SXin Li }
113*67e74705SXin Li 
114*67e74705SXin Li // If there is a check in a macro that is not function-like, don't treat
115*67e74705SXin Li // it like a function so don't suppress.
116*67e74705SXin Li #define NON_FUNCTION_MACRO_WITH_CHECK ( ((p) != 0) ? *p : 17)
testNonFunctionMacro(int * p)117*67e74705SXin Li void testNonFunctionMacro(int *p) {
118*67e74705SXin Li   int i = NON_FUNCTION_MACRO_WITH_CHECK ;
119*67e74705SXin Li   (void)i;
120*67e74705SXin Li 
121*67e74705SXin Li   *p = 1; // expected-warning {{Dereference of null pointer (loaded from variable 'p')}}
122*67e74705SXin Li }
123*67e74705SXin Li 
124*67e74705SXin Li 
125*67e74705SXin Li // This macro will dereference its argument if the argument is NULL.
126*67e74705SXin Li #define MACRO_WITH_ERROR(a) ( ((a) != 0) ? 0 : *a)
testErrorInMacro(int * p)127*67e74705SXin Li void testErrorInMacro(int *p) {
128*67e74705SXin Li   int i = MACRO_WITH_ERROR(p); // expected-warning {{Dereference of null pointer (loaded from variable 'p')}}
129*67e74705SXin Li   (void)i;
130*67e74705SXin Li }
131*67e74705SXin Li 
132*67e74705SXin Li // Here the check (the "if") is not in a macro, so we should still warn.
133*67e74705SXin Li #define MACRO_IN_GUARD(a) (!(a))
testMacroUsedAsGuard(int * p)134*67e74705SXin Li void testMacroUsedAsGuard(int *p) {
135*67e74705SXin Li   if (MACRO_IN_GUARD(p))
136*67e74705SXin Li     *p = 1; // expected-warning {{Dereference of null pointer (loaded from variable 'p')}}
137*67e74705SXin Li }
138*67e74705SXin Li 
139*67e74705SXin Li // When a nil case split is introduced in a macro and the macro is in a guard,
140*67e74705SXin Li // we still shouldn't warn.
141*67e74705SXin Li int isNull(int *p);
142*67e74705SXin Li int isEqual(int *p, int *q);
143*67e74705SXin Li #define ISNULL(ptr)    ((ptr) == 0 || isNull(ptr))
144*67e74705SXin Li #define ISEQUAL(a, b)    ((int *)(a) == (int *)(b) || (ISNULL(a) && ISNULL(b)) || isEqual(a,b))
145*67e74705SXin Li #define ISNOTEQUAL(a, b)   (!ISEQUAL(a, b))
testNestedDisjunctiveMacro(int * p,int * q)146*67e74705SXin Li void testNestedDisjunctiveMacro(int *p, int *q) {
147*67e74705SXin Li   if (ISNOTEQUAL(p,q)) {
148*67e74705SXin Li     *p = 1; // no-warning
149*67e74705SXin Li     *q = 1; // no-warning
150*67e74705SXin Li   }
151*67e74705SXin Li 
152*67e74705SXin Li   *p = 1; // no-warning
153*67e74705SXin Li   *q = 1; // no-warning
154*67e74705SXin Li }
155*67e74705SXin Li 
testNestedDisjunctiveMacro2(int * p,int * q)156*67e74705SXin Li void testNestedDisjunctiveMacro2(int *p, int *q) {
157*67e74705SXin Li   if (ISEQUAL(p,q)) {
158*67e74705SXin Li     return;
159*67e74705SXin Li   }
160*67e74705SXin Li 
161*67e74705SXin Li   *p = 1; // no-warning
162*67e74705SXin Li   *q = 1; // no-warning
163*67e74705SXin Li }
164*67e74705SXin Li 
165*67e74705SXin Li 
166*67e74705SXin Li // Here the check is entirely in non-macro code even though the code itself
167*67e74705SXin Li // is a macro argument.
168*67e74705SXin Li #define MACRO_DO_IT(a) (a)
testErrorInArgument(int * p)169*67e74705SXin Li void testErrorInArgument(int *p) {
170*67e74705SXin Li   int i = MACRO_DO_IT((p ? 0 : *p)); // expected-warning {{Dereference of null pointer (loaded from variable 'p')}}c
171*67e74705SXin Li   (void)i;
172*67e74705SXin Li }
173*67e74705SXin Li 
174*67e74705SXin Li // --------------------------
175*67e74705SXin Li // "Suppression suppression"
176*67e74705SXin Li // --------------------------
177*67e74705SXin Li 
testDynCastOrNullOfNull()178*67e74705SXin Li void testDynCastOrNullOfNull() {
179*67e74705SXin Li   // Don't suppress when one of the arguments is NULL.
180*67e74705SXin Li   int *casted = dynCastOrNull(0);
181*67e74705SXin Li   *casted = 1;
182*67e74705SXin Li #if !SUPPRESSED || NULL_ARGS
183*67e74705SXin Li   // expected-warning@-2 {{Dereference of null pointer}}
184*67e74705SXin Li #endif
185*67e74705SXin Li }
186*67e74705SXin Li 
testDynCastOfNull()187*67e74705SXin Li void testDynCastOfNull() {
188*67e74705SXin Li   // Don't suppress when one of the arguments is NULL.
189*67e74705SXin Li   int *casted = dynCastToInt(0);
190*67e74705SXin Li   *casted = 1;
191*67e74705SXin Li #if !SUPPRESSED || NULL_ARGS
192*67e74705SXin Li   // expected-warning@-2 {{Dereference of null pointer}}
193*67e74705SXin Li #endif
194*67e74705SXin Li }
195*67e74705SXin Li 
lookUpInt(int unused)196*67e74705SXin Li int *lookUpInt(int unused) {
197*67e74705SXin Li   if (coin())
198*67e74705SXin Li     return 0;
199*67e74705SXin Li   static int x;
200*67e74705SXin Li   return &x;
201*67e74705SXin Li }
202*67e74705SXin Li 
testZeroIsNotNull()203*67e74705SXin Li void testZeroIsNotNull() {
204*67e74705SXin Li   // /Do/ suppress when the argument is 0 (an integer).
205*67e74705SXin Li   int *casted = lookUpInt(0);
206*67e74705SXin Li   *casted = 1;
207*67e74705SXin Li #ifndef SUPPRESSED
208*67e74705SXin Li   // expected-warning@-2 {{Dereference of null pointer}}
209*67e74705SXin Li #endif
210*67e74705SXin Li }
211*67e74705SXin Li 
testTrackNull()212*67e74705SXin Li void testTrackNull() {
213*67e74705SXin Li   // /Do/ suppress if the null argument came from another call returning null.
214*67e74705SXin Li   int *casted = dynCastOrNull(getNull());
215*67e74705SXin Li   *casted = 1;
216*67e74705SXin Li #ifndef SUPPRESSED
217*67e74705SXin Li   // expected-warning@-2 {{Dereference of null pointer}}
218*67e74705SXin Li #endif
219*67e74705SXin Li }
220*67e74705SXin Li 
testTrackNullVariable()221*67e74705SXin Li void testTrackNullVariable() {
222*67e74705SXin Li   // /Do/ suppress if the null argument came from another call returning null.
223*67e74705SXin Li   int *ptr;
224*67e74705SXin Li   ptr = getNull();
225*67e74705SXin Li   int *casted = dynCastOrNull(ptr);
226*67e74705SXin Li   *casted = 1;
227*67e74705SXin Li #ifndef SUPPRESSED
228*67e74705SXin Li   // expected-warning@-2 {{Dereference of null pointer}}
229*67e74705SXin Li #endif
230*67e74705SXin Li }
231*67e74705SXin Li 
inlinedIsDifferent(int inlined)232*67e74705SXin Li void inlinedIsDifferent(int inlined) {
233*67e74705SXin Li   int i;
234*67e74705SXin Li 
235*67e74705SXin Li   // We were erroneously picking up the inner stack frame's initialization,
236*67e74705SXin Li   // even though the error occurs in the outer stack frame!
237*67e74705SXin Li   int *p = inlined ? &i : getNull();
238*67e74705SXin Li 
239*67e74705SXin Li   if (!inlined)
240*67e74705SXin Li     inlinedIsDifferent(1);
241*67e74705SXin Li 
242*67e74705SXin Li   *p = 1;
243*67e74705SXin Li #ifndef SUPPRESSED
244*67e74705SXin Li   // expected-warning@-2 {{Dereference of null pointer}}
245*67e74705SXin Li #endif
246*67e74705SXin Li }
247*67e74705SXin Li 
testInlinedIsDifferent()248*67e74705SXin Li void testInlinedIsDifferent() {
249*67e74705SXin Li   // <rdar://problem/13787723>
250*67e74705SXin Li   inlinedIsDifferent(0);
251*67e74705SXin Li }
252*67e74705SXin Li 
253*67e74705SXin Li 
254*67e74705SXin Li // ---------------------------------------
255*67e74705SXin Li // FALSE NEGATIVES (over-suppression)
256*67e74705SXin Li // ---------------------------------------
257*67e74705SXin Li 
testNoArguments()258*67e74705SXin Li void testNoArguments() {
259*67e74705SXin Li   // In this case the function has no branches, and MUST return null.
260*67e74705SXin Li   int *casted = getNull();
261*67e74705SXin Li   *casted = 1;
262*67e74705SXin Li #ifndef SUPPRESSED
263*67e74705SXin Li   // expected-warning@-2 {{Dereference of null pointer}}
264*67e74705SXin Li #endif
265*67e74705SXin Li }
266*67e74705SXin Li 
getNullIfNonNull(void * input)267*67e74705SXin Li int *getNullIfNonNull(void *input) {
268*67e74705SXin Li   if (input)
269*67e74705SXin Li     return 0;
270*67e74705SXin Li   static int x;
271*67e74705SXin Li   return &x;
272*67e74705SXin Li }
273*67e74705SXin Li 
testKnownPath(void * input)274*67e74705SXin Li void testKnownPath(void *input) {
275*67e74705SXin Li   if (!input)
276*67e74705SXin Li     return;
277*67e74705SXin Li 
278*67e74705SXin Li   // In this case we have a known value for the argument, and thus the path
279*67e74705SXin Li   // through the function doesn't ever split.
280*67e74705SXin Li   int *casted = getNullIfNonNull(input);
281*67e74705SXin Li   *casted = 1;
282*67e74705SXin Li #ifndef SUPPRESSED
283*67e74705SXin Li   // expected-warning@-2 {{Dereference of null pointer}}
284*67e74705SXin Li #endif
285*67e74705SXin Li }
286*67e74705SXin Li 
alwaysReturnNull(void * input)287*67e74705SXin Li int *alwaysReturnNull(void *input) {
288*67e74705SXin Li   if (opaquePropertyCheck(input))
289*67e74705SXin Li     return 0;
290*67e74705SXin Li   return 0;
291*67e74705SXin Li }
292*67e74705SXin Li 
testAlwaysReturnNull(void * input)293*67e74705SXin Li void testAlwaysReturnNull(void *input) {
294*67e74705SXin Li   // In this case all paths out of the function return 0, but they are all
295*67e74705SXin Li   // dominated by a branch whose condition we don't know!
296*67e74705SXin Li   int *casted = alwaysReturnNull(input);
297*67e74705SXin Li   *casted = 1;
298*67e74705SXin Li #ifndef SUPPRESSED
299*67e74705SXin Li   // expected-warning@-2 {{Dereference of null pointer}}
300*67e74705SXin Li #endif
301*67e74705SXin Li }
302*67e74705SXin Li 
derefArg(int * p)303*67e74705SXin Li int derefArg(int *p) {
304*67e74705SXin Li 	return *p;
305*67e74705SXin Li #ifndef SUPPRESSED
306*67e74705SXin Li   // expected-warning@-2 {{Dereference of null pointer}}
307*67e74705SXin Li #endif
308*67e74705SXin Li }
ternaryArg(char cond)309*67e74705SXin Li void ternaryArg(char cond) {
310*67e74705SXin Li 	static int x;
311*67e74705SXin Li 	derefArg(cond ? &x : getNull());
312*67e74705SXin Li }
313*67e74705SXin Li 
derefArgCast(char * p)314*67e74705SXin Li int derefArgCast(char *p) {
315*67e74705SXin Li 	return *p;
316*67e74705SXin Li #ifndef SUPPRESSED
317*67e74705SXin Li   // expected-warning@-2 {{Dereference of null pointer}}
318*67e74705SXin Li #endif
319*67e74705SXin Li }
ternaryArgCast(char cond)320*67e74705SXin Li void ternaryArgCast(char cond) {
321*67e74705SXin Li 	static int x;
322*67e74705SXin Li 	derefArgCast((char*)((unsigned)cond ? &x : getNull()));
323*67e74705SXin Li }
324*67e74705SXin Li 
derefAssignment(int * p)325*67e74705SXin Li int derefAssignment(int *p) {
326*67e74705SXin Li 	return *p;
327*67e74705SXin Li #ifndef SUPPRESSED
328*67e74705SXin Li   // expected-warning@-2 {{Dereference of null pointer}}
329*67e74705SXin Li #endif
330*67e74705SXin Li }
331*67e74705SXin Li 
ternaryAssignment(char cond)332*67e74705SXin Li void ternaryAssignment(char cond) {
333*67e74705SXin Li   static int x;
334*67e74705SXin Li   int *p = cond ? getNull() : getPtr();
335*67e74705SXin Li   derefAssignment(p);
336*67e74705SXin Li }
337*67e74705SXin Li 
retNull(char cond)338*67e74705SXin Li int *retNull(char cond) {
339*67e74705SXin Li   static int x;
340*67e74705SXin Li   return cond ? &x : getNull();
341*67e74705SXin Li }
ternaryRetNull(char cond)342*67e74705SXin Li int ternaryRetNull(char cond) {
343*67e74705SXin Li   int *p = retNull(cond);
344*67e74705SXin Li   return *p;
345*67e74705SXin Li #ifndef SUPPRESSED
346*67e74705SXin Li   // expected-warning@-2 {{Dereference of null pointer}}
347*67e74705SXin Li #endif
348*67e74705SXin Li }
349*67e74705SXin Li 
350*67e74705SXin Li // Test suppression of nested conditional operators.
testConditionalOperatorSuppress(int x)351*67e74705SXin Li int testConditionalOperatorSuppress(int x) {
352*67e74705SXin Li   return *(x ? getNull() : getPtr());
353*67e74705SXin Li #ifndef SUPPRESSED
354*67e74705SXin Li   // expected-warning@-2 {{Dereference of null pointer}}
355*67e74705SXin Li #endif
356*67e74705SXin Li }
testNestedConditionalOperatorSuppress(int x)357*67e74705SXin Li int testNestedConditionalOperatorSuppress(int x) {
358*67e74705SXin Li   return *(x ? (x ? getNull() : getPtr()) : getPtr());
359*67e74705SXin Li #ifndef SUPPRESSED
360*67e74705SXin Li   // expected-warning@-2 {{Dereference of null pointer}}
361*67e74705SXin Li #endif
362*67e74705SXin Li }
testConditionalOperator(int x)363*67e74705SXin Li int testConditionalOperator(int x) {
364*67e74705SXin Li   return *(x ? 0 : getPtr()); // expected-warning {{Dereference of null pointer}}
365*67e74705SXin Li }
testNestedConditionalOperator(int x)366*67e74705SXin Li int testNestedConditionalOperator(int x) {
367*67e74705SXin Li   return *(x ? (x ? 0 : getPtr()) : getPtr()); // expected-warning {{Dereference of null pointer}}
368*67e74705SXin Li }
369*67e74705SXin Li 
testConditionalOperatorSuppressFloatCond(float x)370*67e74705SXin Li int testConditionalOperatorSuppressFloatCond(float x) {
371*67e74705SXin Li   return *(x ? getNull() : getPtr());
372*67e74705SXin Li #ifndef SUPPRESSED
373*67e74705SXin Li   // expected-warning@-2 {{Dereference of null pointer}}
374*67e74705SXin Li #endif
375*67e74705SXin Li }
376*67e74705SXin Li 
377