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