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