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