xref: /aosp_15_r20/external/clang/test/Analysis/blocks.m (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core -analyzer-store=region -fblocks -analyzer-opt-analyze-nested-blocks -verify %s
2*67e74705SXin Li// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core -analyzer-store=region -fblocks -analyzer-opt-analyze-nested-blocks -verify -x objective-c++ %s
3*67e74705SXin Li
4*67e74705SXin Li//===----------------------------------------------------------------------===//
5*67e74705SXin Li// The following code is reduced using delta-debugging from Mac OS X headers:
6*67e74705SXin Li//===----------------------------------------------------------------------===//
7*67e74705SXin Li
8*67e74705SXin Litypedef __builtin_va_list va_list;
9*67e74705SXin Litypedef unsigned int uint32_t;
10*67e74705SXin Litypedef struct dispatch_queue_s *dispatch_queue_t;
11*67e74705SXin Litypedef struct dispatch_queue_attr_s *dispatch_queue_attr_t;
12*67e74705SXin Litypedef void (^dispatch_block_t)(void);
13*67e74705SXin Livoid dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
14*67e74705SXin Li__attribute__((visibility("default"))) __attribute__((__malloc__)) __attribute__((__warn_unused_result__)) __attribute__((__nothrow__)) dispatch_queue_t dispatch_queue_create(const char *label, dispatch_queue_attr_t attr);
15*67e74705SXin Litypedef long dispatch_once_t;
16*67e74705SXin Livoid dispatch_once(dispatch_once_t *predicate, dispatch_block_t block);
17*67e74705SXin Lidispatch_queue_t
18*67e74705SXin Lidispatch_queue_create(const char *label, dispatch_queue_attr_t attr);
19*67e74705SXin Li
20*67e74705SXin Li
21*67e74705SXin Litypedef signed char BOOL;
22*67e74705SXin Litypedef unsigned long NSUInteger;
23*67e74705SXin Litypedef struct _NSZone NSZone;
24*67e74705SXin Li@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator;
25*67e74705SXin Li@protocol NSObject
26*67e74705SXin Li- (BOOL)isEqual:(id)object;
27*67e74705SXin Li- (oneway void)release;
28*67e74705SXin Li@end
29*67e74705SXin Li@protocol NSCopying  - (id)copyWithZone:(NSZone *)zone; @end
30*67e74705SXin Li@protocol NSMutableCopying  - (id)mutableCopyWithZone:(NSZone *)zone; @end
31*67e74705SXin Li@protocol NSCoding  - (void)encodeWithCoder:(NSCoder *)aCoder; @end
32*67e74705SXin Li@interface NSObject <NSObject> {}
33*67e74705SXin Li+ (id)alloc;
34*67e74705SXin Li- (id)init;
35*67e74705SXin Li- (id)copy;
36*67e74705SXin Li@end
37*67e74705SXin Liextern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone);
38*67e74705SXin Li@interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding>
39*67e74705SXin Li- (NSUInteger)length;
40*67e74705SXin Li- (const char *)UTF8String;
41*67e74705SXin Li- (id)initWithFormat:(NSString *)format arguments:(va_list)argList __attribute__((format(__NSString__, 1, 0)));
42*67e74705SXin Li@end
43*67e74705SXin Li@class NSString, NSData;
44*67e74705SXin Litypedef struct cssm_sample {} CSSM_SAMPLEGROUP, *CSSM_SAMPLEGROUP_PTR;
45*67e74705SXin Litypedef struct __aslclient *aslclient;
46*67e74705SXin Litypedef struct __aslmsg *aslmsg;
47*67e74705SXin Liaslclient asl_open(const char *ident, const char *facility, uint32_t opts);
48*67e74705SXin Liint asl_log(aslclient asl, aslmsg msg, int level, const char *format, ...) __attribute__((__format__ (__printf__, 4, 5)));
49*67e74705SXin Li
50*67e74705SXin Li//===----------------------------------------------------------------------===//
51*67e74705SXin Li// Begin actual test cases.
52*67e74705SXin Li//===----------------------------------------------------------------------===//
53*67e74705SXin Li
54*67e74705SXin Li// test1 - This test case exposed logic that caused the analyzer to crash because of a memory bug
55*67e74705SXin Li//  in BlockDataRegion.  It represents real code that contains two block literals.  Eventually
56*67e74705SXin Li//  via IPA 'logQueue' and 'client' should be updated after the call to 'dispatch_once'.
57*67e74705SXin Livoid test1(NSString *format, ...) {
58*67e74705SXin Li  static dispatch_queue_t logQueue;
59*67e74705SXin Li  static aslclient client;
60*67e74705SXin Li  static dispatch_once_t pred;
61*67e74705SXin Li  do {
62*67e74705SXin Li    if (__builtin_expect(*(&pred), ~0l) != ~0l)
63*67e74705SXin Li      dispatch_once(&pred, ^{
64*67e74705SXin Li        logQueue = dispatch_queue_create("com.mycompany.myproduct.asl", 0);
65*67e74705SXin Li        client = asl_open(((char*)0), "com.mycompany.myproduct", 0);
66*67e74705SXin Li      });
67*67e74705SXin Li  } while (0);
68*67e74705SXin Li
69*67e74705SXin Li  va_list args;
70*67e74705SXin Li  __builtin_va_start(args, format);
71*67e74705SXin Li
72*67e74705SXin Li  NSString *str = [[NSString alloc] initWithFormat:format arguments:args];
73*67e74705SXin Li  dispatch_async(logQueue, ^{ asl_log(client, ((aslmsg)0), 4, "%s", [str UTF8String]); });
74*67e74705SXin Li  [str release];
75*67e74705SXin Li
76*67e74705SXin Li  __builtin_va_end(args);
77*67e74705SXin Li}
78*67e74705SXin Li
79*67e74705SXin Li// test2 - Test that captured variables that are uninitialized are flagged
80*67e74705SXin Li// as such.
81*67e74705SXin Livoid test2() {
82*67e74705SXin Li  static int y = 0;
83*67e74705SXin Li  int x;
84*67e74705SXin Li  ^{ y = x + 1; }();  // expected-warning{{Variable 'x' is uninitialized when captured by block}}
85*67e74705SXin Li}
86*67e74705SXin Li
87*67e74705SXin Livoid test2_b() {
88*67e74705SXin Li  static int y = 0;
89*67e74705SXin Li  __block int x;
90*67e74705SXin Li  ^{ y = x + 1; }(); // expected-warning {{left operand of '+' is a garbage value}}
91*67e74705SXin Li}
92*67e74705SXin Li
93*67e74705SXin Livoid test2_c() {
94*67e74705SXin Li  typedef void (^myblock)(void);
95*67e74705SXin Li  myblock f = ^() { f(); }; // expected-warning{{Variable 'f' is uninitialized when captured by block}}
96*67e74705SXin Li}
97*67e74705SXin Li
98*67e74705SXin Li
99*67e74705SXin Livoid testMessaging() {
100*67e74705SXin Li  // <rdar://problem/12119814>
101*67e74705SXin Li  [[^(){} copy] release];
102*67e74705SXin Li}
103*67e74705SXin Li
104*67e74705SXin Li
105*67e74705SXin Li@interface rdar12415065 : NSObject
106*67e74705SXin Li@end
107*67e74705SXin Li
108*67e74705SXin Li@implementation rdar12415065
109*67e74705SXin Li- (void)test {
110*67e74705SXin Li  // At one point this crashed because we created a path note at a
111*67e74705SXin Li  // PreStmtPurgeDeadSymbols point but only knew how to deal with PostStmt
112*67e74705SXin Li  // points. <rdar://problem/12687586>
113*67e74705SXin Li
114*67e74705SXin Li  extern dispatch_queue_t queue;
115*67e74705SXin Li
116*67e74705SXin Li  if (!queue)
117*67e74705SXin Li    return;
118*67e74705SXin Li
119*67e74705SXin Li  // This previously was a false positive with 'x' being flagged as being
120*67e74705SXin Li  // uninitialized when captured by the exterior block (when it is only
121*67e74705SXin Li  // captured by the interior block).
122*67e74705SXin Li  dispatch_async(queue, ^{
123*67e74705SXin Li    double x = 0.0;
124*67e74705SXin Li    if (24.0f < x) {
125*67e74705SXin Li      dispatch_async(queue, ^{ (void)x; });
126*67e74705SXin Li      [self test];
127*67e74705SXin Li    }
128*67e74705SXin Li  });
129*67e74705SXin Li}
130*67e74705SXin Li@end
131*67e74705SXin Li
132*67e74705SXin Livoid testReturnVariousSignatures() {
133*67e74705SXin Li  (void)^int(){
134*67e74705SXin Li    return 42;
135*67e74705SXin Li  }();
136*67e74705SXin Li
137*67e74705SXin Li  (void)^int{
138*67e74705SXin Li    return 42;
139*67e74705SXin Li  }();
140*67e74705SXin Li
141*67e74705SXin Li  (void)^(){
142*67e74705SXin Li    return 42;
143*67e74705SXin Li  }();
144*67e74705SXin Li
145*67e74705SXin Li  (void)^{
146*67e74705SXin Li    return 42;
147*67e74705SXin Li  }();
148*67e74705SXin Li}
149*67e74705SXin Li
150*67e74705SXin Li// This test used to cause infinite loop in the region invalidation.
151*67e74705SXin Livoid blockCapturesItselfInTheLoop(int x, int m) {
152*67e74705SXin Li  void (^assignData)(int) = ^(int x){
153*67e74705SXin Li    x++;
154*67e74705SXin Li  };
155*67e74705SXin Li  while (m < 0) {
156*67e74705SXin Li    void (^loop)(int);
157*67e74705SXin Li    loop = ^(int x) {
158*67e74705SXin Li      assignData(x);
159*67e74705SXin Li    };
160*67e74705SXin Li    assignData = loop;
161*67e74705SXin Li    m++;
162*67e74705SXin Li  }
163*67e74705SXin Li  assignData(x);
164*67e74705SXin Li}
165*67e74705SXin Li
166*67e74705SXin Li// Blocks that called the function they were contained in that also have
167*67e74705SXin Li// static locals caused crashes.
168*67e74705SXin Li// rdar://problem/21698099
169*67e74705SXin Livoid takeNonnullBlock(void (^)(void)) __attribute__((nonnull));
170*67e74705SXin Livoid takeNonnullIntBlock(int (^)(void)) __attribute__((nonnull));
171*67e74705SXin Li
172*67e74705SXin Livoid testCallContainingWithSignature1()
173*67e74705SXin Li{
174*67e74705SXin Li  takeNonnullBlock(^{
175*67e74705SXin Li    static const char str[] = "Lost connection to sharingd";
176*67e74705SXin Li    testCallContainingWithSignature1();
177*67e74705SXin Li  });
178*67e74705SXin Li}
179*67e74705SXin Li
180*67e74705SXin Livoid testCallContainingWithSignature2()
181*67e74705SXin Li{
182*67e74705SXin Li  takeNonnullBlock(^void{
183*67e74705SXin Li    static const char str[] = "Lost connection to sharingd";
184*67e74705SXin Li    testCallContainingWithSignature2();
185*67e74705SXin Li  });
186*67e74705SXin Li}
187*67e74705SXin Li
188*67e74705SXin Livoid testCallContainingWithSignature3()
189*67e74705SXin Li{
190*67e74705SXin Li  takeNonnullBlock(^void(){
191*67e74705SXin Li    static const char str[] = "Lost connection to sharingd";
192*67e74705SXin Li    testCallContainingWithSignature3();
193*67e74705SXin Li  });
194*67e74705SXin Li}
195*67e74705SXin Li
196*67e74705SXin Livoid testCallContainingWithSignature4()
197*67e74705SXin Li{
198*67e74705SXin Li  takeNonnullBlock(^void(void){
199*67e74705SXin Li    static const char str[] = "Lost connection to sharingd";
200*67e74705SXin Li    testCallContainingWithSignature4();
201*67e74705SXin Li  });
202*67e74705SXin Li}
203*67e74705SXin Li
204*67e74705SXin Livoid testCallContainingWithSignature5()
205*67e74705SXin Li{
206*67e74705SXin Li  takeNonnullIntBlock(^{
207*67e74705SXin Li    static const char str[] = "Lost connection to sharingd";
208*67e74705SXin Li    testCallContainingWithSignature5();
209*67e74705SXin Li    return 0;
210*67e74705SXin Li  });
211*67e74705SXin Li}
212*67e74705SXin Li
213*67e74705SXin Li__attribute__((objc_root_class))
214*67e74705SXin Li@interface SuperClass
215*67e74705SXin Li- (void)someMethod;
216*67e74705SXin Li@end
217*67e74705SXin Li
218*67e74705SXin Li@interface SomeClass : SuperClass
219*67e74705SXin Li@end
220*67e74705SXin Li
221*67e74705SXin Li// Make sure to properly handle super-calls when a block captures
222*67e74705SXin Li// a local variable named 'self'.
223*67e74705SXin Li@implementation SomeClass
224*67e74705SXin Li-(void)foo; {
225*67e74705SXin Li  /*__weak*/ SomeClass *weakSelf = self;
226*67e74705SXin Li  (void)(^(void) {
227*67e74705SXin Li    SomeClass *self = weakSelf;
228*67e74705SXin Li    (void)(^(void) {
229*67e74705SXin Li      (void)self;
230*67e74705SXin Li      [super someMethod]; // no-warning
231*67e74705SXin Li    });
232*67e74705SXin Li  });
233*67e74705SXin Li}
234*67e74705SXin Li@end
235