1// RUN: %clang_cc1 -fblocks -fobjc-arc -fobjc-runtime-has-weak -triple i386-apple-darwin -print-ivar-layout -emit-llvm -o /dev/null %s > %t-32.layout 2// RUN: FileCheck --input-file=%t-32.layout %s 3// rdar://12184410 4// rdar://12752901 5 6void x(id y) {} 7void y(int a) {} 8 9extern id opaque_id(); 10 11void f() { 12 __weak id wid; 13 __block int byref_int = 0; 14 char ch = 'a'; 15 char ch1 = 'b'; 16 char ch2 = 'c'; 17 short sh = 2; 18 const id bar = (id) opaque_id(); 19 id baz = 0; 20 __strong id strong_void_sta; 21 __block id byref_bab = (id)0; 22 __block id bl_var1; 23 int i; double dob; 24 25// The patterns here are a sequence of bytes, each saying first how 26// many sizeof(void*) chunks to skip (high nibble) and then how many 27// to scan (low nibble). A zero byte says that we've reached the end 28// of the pattern. 29// 30// All of these patterns start with 01 3x because the block header on 31// LP64 consists of an isa pointer (which we're supposed to scan for 32// some reason) followed by three words (2 ints, a function pointer, 33// and a descriptor pointer). 34 35// Test 1 36// CHECK: Inline block variable layout: 0x0320, BL_STRONG:3, BL_BYREF:2, BL_OPERATOR:0 37 void (^b)() = ^{ 38 byref_int = sh + ch+ch1+ch2 ; 39 x(bar); 40 x(baz); 41 x((id)strong_void_sta); 42 x(byref_bab); 43 }; 44 b(); 45 46// Test 2 47// CHECK: Inline block variable layout: 0x0331, BL_STRONG:3, BL_BYREF:3, BL_WEAK:1, BL_OPERATOR:0 48 void (^c)() = ^{ 49 byref_int = sh + ch+ch1+ch2 ; 50 x(bar); 51 x(baz); 52 x((id)strong_void_sta); 53 x(wid); 54 bl_var1 = 0; 55 x(byref_bab); 56 }; 57} 58 59@class NSString, NSNumber; 60void g() { 61 NSString *foo; 62 NSNumber *bar; 63 unsigned int bletch; 64 __weak id weak_delegate; 65 unsigned int i; 66 NSString *y; 67 NSString *z; 68// CHECK: Inline block variable layout: 0x0401, BL_STRONG:4, BL_WEAK:1, BL_OPERATOR:0 69 void (^c)() = ^{ 70 int j = i + bletch; 71 x(foo); 72 x(bar); 73 x(weak_delegate); 74 x(y); 75 x(z); 76 }; 77 c(); 78} 79 80// Test 5 (unions/structs and their nesting): 81void h() { 82 struct S5 { 83 int i1; 84 __unsafe_unretained id o1; 85 struct V { 86 int i2; 87 __unsafe_unretained id o2; 88 } v1; 89 int i3; 90 union UI { 91 void * i1; 92 __unsafe_unretained id o1; 93 int i3; 94 __unsafe_unretained id o3; 95 }ui; 96 }; 97 98 union U { 99 void * i1; 100 __unsafe_unretained id o1; 101 int i3; 102 __unsafe_unretained id o3; 103 }ui; 104 105 struct S5 s2; 106 union U u2; 107 __block id block_id; 108 109/** 110block variable layout: BL_NON_OBJECT_WORD:1, BL_UNRETAINE:1, BL_NON_OBJECT_WORD:1, 111 BL_UNRETAINE:1, BL_NON_OBJECT_WORD:3, BL_BYREF:1, BL_OPERATOR:0 112*/ 113// CHECK: Block variable layout: BL_BYREF:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_OPERATOR:0 114 void (^c)() = ^{ 115 x(s2.ui.o1); 116 x(u2.o1); 117 block_id = 0; 118 }; 119 c(); 120} 121 122// Test for array of stuff. 123void arr1() { 124 struct S { 125 __unsafe_unretained id unsafe_unretained_var[4]; 126 } imported_s; 127 128// CHECK: Block variable layout: BL_UNRETAINED:4, BL_OPERATOR:0 129 void (^c)() = ^{ 130 x(imported_s.unsafe_unretained_var[2]); 131 }; 132 133 c(); 134} 135 136// Test2 for array of stuff. 137void arr2() { 138 struct S { 139 int a; 140 __unsafe_unretained id unsafe_unretained_var[4]; 141 } imported_s; 142 143// CHECK: Block variable layout: BL_NON_OBJECT_WORD:1, BL_UNRETAINED:4, BL_OPERATOR:0 144 void (^c)() = ^{ 145 x(imported_s.unsafe_unretained_var[2]); 146 }; 147 148 c(); 149} 150 151// Test3 for array of stuff. 152void arr3() { 153 struct S { 154 int a; 155 __unsafe_unretained id unsafe_unretained_var[0]; 156 } imported_s; 157 158// CHECK: Block variable layout: BL_OPERATOR:0 159 void (^c)() = ^{ 160 int i = imported_s.a; 161 }; 162 163 c(); 164} 165 166 167// Test4 for array of stuff. 168@class B; 169void arr4() { 170 struct S { 171 struct s0 { 172 __unsafe_unretained id s_f0; 173 __unsafe_unretained id s_f1; 174 } f0; 175 176 __unsafe_unretained id f1; 177 178 struct s1 { 179 int *f0; 180 __unsafe_unretained B *f1; 181 } f4[2][2]; 182 } captured_s; 183 184// CHECK: Block variable layout: BL_UNRETAINED:3, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_NON_OBJECT_WORD:1, BL_UNRETAINED:1, BL_OPERATOR:0 185 void (^c)() = ^{ 186 id i = captured_s.f0.s_f1; 187 }; 188 189 c(); 190} 191 192// Test1 bitfield in cpatured aggregate. 193void bf1() { 194 struct S { 195 int flag : 25; 196 int flag1: 7; 197 int flag2 :1; 198 int flag3: 7; 199 int flag4: 24; 200 } s; 201 202// CHECK: Block variable layout: BL_OPERATOR:0 203 int (^c)() = ^{ 204 return s.flag; 205 }; 206 c(); 207} 208 209// Test2 bitfield in cpatured aggregate. 210void bf2() { 211 struct S { 212 int flag : 1; 213 } s; 214 215// CHECK: Block variable layout: BL_OPERATOR:0 216 int (^c)() = ^{ 217 return s.flag; 218 }; 219 c(); 220} 221 222// Test3 bitfield in cpatured aggregate. 223void bf3() { 224 225 struct { 226 unsigned short _reserved : 16; 227 228 unsigned char _draggedNodesAreDeletable: 1; 229 unsigned char _draggedOutsideOutlineView : 1; 230 unsigned char _adapterRespondsTo_addRootPaths : 1; 231 unsigned char _adapterRespondsTo_moveDataNodes : 1; 232 unsigned char _adapterRespondsTo_removeRootDataNode : 1; 233 unsigned char _adapterRespondsTo_doubleClickDataNode : 1; 234 unsigned char _adapterRespondsTo_selectDataNode : 1; 235 unsigned char _adapterRespondsTo_textDidEndEditing : 1; 236 unsigned char _adapterRespondsTo_updateAndSaveRoots : 1; 237 unsigned char _adapterRespondsTo_askToDeleteRootNodes : 1; 238 unsigned char _adapterRespondsTo_contextMenuForSelectedNodes : 1; 239 unsigned char _adapterRespondsTo_pasteboardFilenamesForNodes : 1; 240 unsigned char _adapterRespondsTo_writeItemsToPasteboard : 1; 241 unsigned char _adapterRespondsTo_writeItemsToPasteboardXXXX : 1; 242 243 unsigned int _filler : 32; 244 } _flags; 245 246// CHECK: Block variable layout: BL_OPERATOR:0 247 unsigned char (^c)() = ^{ 248 return _flags._draggedNodesAreDeletable; 249 }; 250 251 c(); 252} 253 254// Test4 unnamed bitfield 255void bf4() { 256 257 struct { 258 unsigned short _reserved : 16; 259 260 unsigned char _draggedNodesAreDeletable: 1; 261 unsigned char _draggedOutsideOutlineView : 1; 262 unsigned char _adapterRespondsTo_addRootPaths : 1; 263 unsigned char _adapterRespondsTo_moveDataNodes : 1; 264 unsigned char _adapterRespondsTo_removeRootDataNode : 1; 265 unsigned char _adapterRespondsTo_doubleClickDataNode : 1; 266 unsigned char _adapterRespondsTo_selectDataNode : 1; 267 unsigned char _adapterRespondsTo_textDidEndEditing : 1; 268 269 unsigned long long : 64; 270 271 unsigned char _adapterRespondsTo_updateAndSaveRoots : 1; 272 unsigned char _adapterRespondsTo_askToDeleteRootNodes : 1; 273 unsigned char _adapterRespondsTo_contextMenuForSelectedNodes : 1; 274 unsigned char _adapterRespondsTo_pasteboardFilenamesForNodes : 1; 275 unsigned char _adapterRespondsTo_writeItemsToPasteboard : 1; 276 unsigned char _adapterRespondsTo_writeItemsToPasteboardXXXX : 1; 277 278 unsigned int _filler : 32; 279 } _flags; 280 281// CHECK: Block variable layout: BL_OPERATOR:0 282 unsigned char (^c)() = ^{ 283 return _flags._draggedNodesAreDeletable; 284 }; 285 286 c(); 287} 288 289 290 291// Test5 unnamed bitfield. 292void bf5() { 293 struct { 294 unsigned char flag : 1; 295 unsigned int : 32; 296 unsigned char flag1 : 1; 297 } _flags; 298 299// CHECK: Block variable layout: BL_OPERATOR:0 300 unsigned char (^c)() = ^{ 301 return _flags.flag; 302 }; 303 304 c(); 305} 306 307 308// Test6 0 length bitfield. 309void bf6() { 310 struct { 311 unsigned char flag : 1; 312 unsigned int : 0; 313 unsigned char flag1 : 1; 314 } _flags; 315 316// CHECK: Block variable layout: BL_OPERATOR:0 317 unsigned char (^c)() = ^{ 318 return _flags.flag; 319 }; 320 321 c(); 322} 323 324// Test7 large number of captured variables. 325void Test7() { 326 __weak id wid; 327 __weak id wid1, wid2, wid3, wid4; 328 __weak id wid5, wid6, wid7, wid8; 329 __weak id wid9, wid10, wid11, wid12; 330 __weak id wid13, wid14, wid15, wid16; 331 const id bar = (id) opaque_id(); 332// CHECK: Block variable layout: BL_STRONG:1, BL_WEAK:16, BL_OPERATOR:0 333 void (^b)() = ^{ 334 x(bar); 335 x(wid1); 336 x(wid2); 337 x(wid3); 338 x(wid4); 339 x(wid5); 340 x(wid6); 341 x(wid7); 342 x(wid8); 343 x(wid9); 344 x(wid10); 345 x(wid11); 346 x(wid12); 347 x(wid13); 348 x(wid14); 349 x(wid15); 350 x(wid16); 351 }; 352} 353 354 355// Test 8 very large number of captured variables. 356void Test8() { 357__weak id wid; 358 __weak id wid1, wid2, wid3, wid4; 359 __weak id wid5, wid6, wid7, wid8; 360 __weak id wid9, wid10, wid11, wid12; 361 __weak id wid13, wid14, wid15, wid16; 362 __weak id w1, w2, w3, w4; 363 __weak id w5, w6, w7, w8; 364 __weak id w9, w10, w11, w12; 365 __weak id w13, w14, w15, w16; 366 const id bar = (id) opaque_id(); 367// CHECK: Block variable layout: BL_STRONG:1, BL_WEAK:16, BL_WEAK:16, BL_WEAK:1, BL_OPERATOR:0 368 void (^b)() = ^{ 369 x(bar); 370 x(wid1); 371 x(wid2); 372 x(wid3); 373 x(wid4); 374 x(wid5); 375 x(wid6); 376 x(wid7); 377 x(wid8); 378 x(wid9); 379 x(wid10); 380 x(wid11); 381 x(wid12); 382 x(wid13); 383 x(wid14); 384 x(wid15); 385 x(wid16); 386 x(w1); 387 x(w2); 388 x(w3); 389 x(w4); 390 x(w5); 391 x(w6); 392 x(w7); 393 x(w8); 394 x(w9); 395 x(w10); 396 x(w11); 397 x(w12); 398 x(w13); 399 x(w14); 400 x(w15); 401 x(w16); 402 x(wid); 403 }; 404} 405