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