xref: /aosp_15_r20/external/clang/test/Analysis/inlining/inline-defensive-checks.m (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-config suppress-inlined-defensive-checks=true -verify %s
2*67e74705SXin Li
3*67e74705SXin Litypedef signed char BOOL;
4*67e74705SXin Litypedef struct objc_class *Class;
5*67e74705SXin Litypedef struct objc_object {
6*67e74705SXin Li  Class isa;
7*67e74705SXin Li} *id;
8*67e74705SXin Li@protocol NSObject  - (BOOL)isEqual:(id)object; @end
9*67e74705SXin Li@interface NSObject <NSObject> {}
10*67e74705SXin Li+(id)alloc;
11*67e74705SXin Li+(id)new;
12*67e74705SXin Li-(id)init;
13*67e74705SXin Li-(id)autorelease;
14*67e74705SXin Li-(id)copy;
15*67e74705SXin Li- (Class)class;
16*67e74705SXin Li-(id)retain;
17*67e74705SXin Li@end
18*67e74705SXin Li
19*67e74705SXin Li// Check that inline defensive checks is triggered for null expressions
20*67e74705SXin Li// within CompoundLiteralExpr.
21*67e74705SXin Litypedef union {
22*67e74705SXin Li  struct dispatch_object_s *_do;
23*67e74705SXin Li  struct dispatch_source_s *_ds;
24*67e74705SXin Li} dispatch_object_t __attribute__((__transparent_union__));
25*67e74705SXin Litypedef struct dispatch_source_s *dispatch_source_t;
26*67e74705SXin Li
27*67e74705SXin Liextern __attribute__((visibility("default"))) __attribute__((__nonnull__)) __attribute__((__nothrow__))
28*67e74705SXin Livoid
29*67e74705SXin Lidispatch_resume(dispatch_object_t object);
30*67e74705SXin Li
31*67e74705SXin Li@interface AppDelegate : NSObject {
32*67e74705SXin Li@protected
33*67e74705SXin Li	dispatch_source_t p;
34*67e74705SXin Li}
35*67e74705SXin Li@end
36*67e74705SXin Li@implementation AppDelegate
37*67e74705SXin Li- (void)updateDeleteTimer {
38*67e74705SXin Li	if (p != ((void*)0))
39*67e74705SXin Li		;
40*67e74705SXin Li}
41*67e74705SXin Li- (void)createAndStartDeleteTimer {
42*67e74705SXin Li  [self updateDeleteTimer];
43*67e74705SXin Li  dispatch_resume(p); // no warning
44*67e74705SXin Li}
45*67e74705SXin Li@end
46*67e74705SXin Li
47*67e74705SXin Li// Test nil receiver suppression.
48*67e74705SXin Li// We only suppress on nil receiver if the nil value is directly causing the bug.
49*67e74705SXin Li@interface Foo {
50*67e74705SXin Li@public
51*67e74705SXin Li  int x;
52*67e74705SXin Li}
53*67e74705SXin Li- (Foo *)getFooPtr;
54*67e74705SXin Li@end
55*67e74705SXin Li
56*67e74705SXin LiFoo *retNil() {
57*67e74705SXin Li  return 0;
58*67e74705SXin Li}
59*67e74705SXin Li
60*67e74705SXin LiFoo *retInputOrNil(Foo *p) {
61*67e74705SXin Li  if (p)
62*67e74705SXin Li    return p;
63*67e74705SXin Li  return 0;
64*67e74705SXin Li}
65*67e74705SXin Li
66*67e74705SXin Livoid idc(Foo *p) {
67*67e74705SXin Li  if (p)
68*67e74705SXin Li    ;
69*67e74705SXin Li}
70*67e74705SXin Li
71*67e74705SXin Liint testNilReceiver(Foo* fPtr) {
72*67e74705SXin Li  if (fPtr)
73*67e74705SXin Li    ;
74*67e74705SXin Li  // On a path where fPtr is nil, mem should be nil.
75*67e74705SXin Li  Foo *mem = [fPtr getFooPtr];
76*67e74705SXin Li  return mem->x; // expected-warning {{Access to instance variable 'x' results in a dereference of a null pointer}}
77*67e74705SXin Li}
78*67e74705SXin Li
79*67e74705SXin Liint suppressNilReceiverRetNullCond(Foo* fPtr) {
80*67e74705SXin Li  unsigned zero = 0;
81*67e74705SXin Li  fPtr = retInputOrNil(fPtr);
82*67e74705SXin Li  // On a path where fPtr is nzil, mem should be nil.
83*67e74705SXin Li  Foo *mem = [fPtr getFooPtr];
84*67e74705SXin Li  return mem->x;
85*67e74705SXin Li}
86*67e74705SXin Li
87*67e74705SXin Liint suppressNilReceiverRetNullCondCast(id fPtr) {
88*67e74705SXin Li  unsigned zero = 0;
89*67e74705SXin Li  fPtr = retInputOrNil(fPtr);
90*67e74705SXin Li  // On a path where fPtr is nzil, mem should be nil.
91*67e74705SXin Li  Foo *mem = ((id)([(Foo*)(fPtr) getFooPtr]));
92*67e74705SXin Li  return mem->x;
93*67e74705SXin Li}
94*67e74705SXin Li
95*67e74705SXin Liint dontSuppressNilReceiverRetNullCond(Foo* fPtr) {
96*67e74705SXin Li  unsigned zero = 0;
97*67e74705SXin Li  fPtr = retInputOrNil(fPtr);
98*67e74705SXin Li  // On a path where fPtr is nil, mem should be nil.
99*67e74705SXin Li  // The warning is not suppressed because the receiver being nil is not
100*67e74705SXin Li  // directly related to the value that triggers the warning.
101*67e74705SXin Li  Foo *mem = [fPtr getFooPtr];
102*67e74705SXin Li  if (!mem)
103*67e74705SXin Li    return 5/zero; // expected-warning {{Division by zero}}
104*67e74705SXin Li  return 0;
105*67e74705SXin Li}
106*67e74705SXin Li
107*67e74705SXin Liint dontSuppressNilReceiverRetNull(Foo* fPtr) {
108*67e74705SXin Li  unsigned zero = 0;
109*67e74705SXin Li  fPtr = retNil();
110*67e74705SXin Li  // On a path where fPtr is nil, mem should be nil.
111*67e74705SXin Li  // The warning is not suppressed because the receiver being nil is not
112*67e74705SXin Li  // directly related to the value that triggers the warning.
113*67e74705SXin Li  Foo *mem = [fPtr getFooPtr];
114*67e74705SXin Li  if (!mem)
115*67e74705SXin Li    return 5/zero; // expected-warning {{Division by zero}}
116*67e74705SXin Li  return 0;
117*67e74705SXin Li}
118*67e74705SXin Li
119*67e74705SXin Liint dontSuppressNilReceiverIDC(Foo* fPtr) {
120*67e74705SXin Li  unsigned zero = 0;
121*67e74705SXin Li  idc(fPtr);
122*67e74705SXin Li  // On a path where fPtr is nil, mem should be nil.
123*67e74705SXin Li  // The warning is not suppressed because the receiver being nil is not
124*67e74705SXin Li  // directly related to the value that triggers the warning.
125*67e74705SXin Li  Foo *mem = [fPtr getFooPtr];
126*67e74705SXin Li  if (!mem)
127*67e74705SXin Li    return 5/zero; // expected-warning {{Division by zero}}
128*67e74705SXin Li  return 0;
129*67e74705SXin Li}
130