forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			405 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			Objective-C
		
	
	
	
			
		
		
	
	
			405 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			Objective-C
		
	
	
	
// 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
 | 
						|
// RUN: FileCheck --input-file=%t-32.layout %s
 | 
						|
// rdar://12184410
 | 
						|
// rdar://12752901
 | 
						|
 | 
						|
void x(id y) {}
 | 
						|
void y(int a) {}
 | 
						|
 | 
						|
extern id opaque_id();
 | 
						|
 | 
						|
void f() {
 | 
						|
    __weak id wid;
 | 
						|
    __block int byref_int = 0;
 | 
						|
    char ch = 'a';
 | 
						|
    char ch1 = 'b';
 | 
						|
    char ch2 = 'c';
 | 
						|
    short sh = 2;
 | 
						|
    const id bar = (id) opaque_id();
 | 
						|
    id baz = 0;
 | 
						|
    __strong id strong_void_sta;
 | 
						|
    __block id byref_bab = (id)0;
 | 
						|
    __block id bl_var1;
 | 
						|
    int i; double dob;
 | 
						|
 | 
						|
// The patterns here are a sequence of bytes, each saying first how
 | 
						|
// many sizeof(void*) chunks to skip (high nibble) and then how many
 | 
						|
// to scan (low nibble).  A zero byte says that we've reached the end
 | 
						|
// of the pattern.
 | 
						|
//
 | 
						|
// All of these patterns start with 01 3x because the block header on
 | 
						|
// LP64 consists of an isa pointer (which we're supposed to scan for
 | 
						|
// some reason) followed by three words (2 ints, a function pointer,
 | 
						|
// and a descriptor pointer).
 | 
						|
 | 
						|
// Test 1
 | 
						|
// CHECK: Inline block variable layout: 0x0320, BL_STRONG:3, BL_BYREF:2, BL_OPERATOR:0
 | 
						|
    void (^b)() = ^{
 | 
						|
        byref_int = sh + ch+ch1+ch2 ;
 | 
						|
        x(bar);
 | 
						|
        x(baz);
 | 
						|
        x((id)strong_void_sta);
 | 
						|
        x(byref_bab);
 | 
						|
    };    
 | 
						|
    b();
 | 
						|
 | 
						|
// Test 2
 | 
						|
// CHECK: Inline block variable layout: 0x0331, BL_STRONG:3, BL_BYREF:3, BL_WEAK:1, BL_OPERATOR:0
 | 
						|
    void (^c)() = ^{
 | 
						|
        byref_int = sh + ch+ch1+ch2 ;
 | 
						|
        x(bar);
 | 
						|
        x(baz);
 | 
						|
        x((id)strong_void_sta);
 | 
						|
        x(wid);
 | 
						|
        bl_var1 = 0;
 | 
						|
        x(byref_bab);
 | 
						|
    };    
 | 
						|
}
 | 
						|
 | 
						|
@class NSString, NSNumber;
 | 
						|
void g() {
 | 
						|
  NSString *foo;
 | 
						|
   NSNumber *bar;
 | 
						|
   unsigned int bletch;
 | 
						|
   __weak id weak_delegate;
 | 
						|
  unsigned int i;
 | 
						|
  NSString *y;
 | 
						|
  NSString *z;
 | 
						|
// CHECK: Inline block variable layout: 0x0401, BL_STRONG:4, BL_WEAK:1, BL_OPERATOR:0
 | 
						|
  void (^c)() = ^{
 | 
						|
   int j = i + bletch;
 | 
						|
   x(foo);
 | 
						|
   x(bar);
 | 
						|
   x(weak_delegate);
 | 
						|
   x(y);
 | 
						|
   x(z); 
 | 
						|
  };
 | 
						|
  c();
 | 
						|
}
 | 
						|
 | 
						|
// Test 5 (unions/structs and their nesting):
 | 
						|
void h() {
 | 
						|
  struct S5 {
 | 
						|
    int i1;
 | 
						|
    __unsafe_unretained id o1;
 | 
						|
    struct V {
 | 
						|
     int i2;
 | 
						|
     __unsafe_unretained id o2;
 | 
						|
    } v1;
 | 
						|
    int i3;
 | 
						|
    union UI {
 | 
						|
        void * i1;
 | 
						|
        __unsafe_unretained id o1;
 | 
						|
        int i3;
 | 
						|
        __unsafe_unretained id o3;
 | 
						|
    }ui;
 | 
						|
  };
 | 
						|
 | 
						|
  union U {
 | 
						|
        void * i1;
 | 
						|
        __unsafe_unretained id o1;
 | 
						|
        int i3;
 | 
						|
        __unsafe_unretained id o3;
 | 
						|
  }ui;
 | 
						|
 | 
						|
  struct S5 s2;
 | 
						|
  union U u2;
 | 
						|
  __block id block_id;
 | 
						|
 | 
						|
/**
 | 
						|
block variable layout: BL_NON_OBJECT_WORD:1, BL_UNRETAINE:1, BL_NON_OBJECT_WORD:1, 
 | 
						|
                       BL_UNRETAINE:1, BL_NON_OBJECT_WORD:3, BL_BYREF:1, BL_OPERATOR:0
 | 
						|
*/
 | 
						|
// 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
 | 
						|
  void (^c)() = ^{
 | 
						|
    x(s2.ui.o1);
 | 
						|
    x(u2.o1);
 | 
						|
    block_id = 0;
 | 
						|
  };
 | 
						|
  c();
 | 
						|
}
 | 
						|
 | 
						|
// Test for array of stuff.
 | 
						|
void arr1() {
 | 
						|
  struct S {
 | 
						|
    __unsafe_unretained id unsafe_unretained_var[4];
 | 
						|
 } imported_s;
 | 
						|
 | 
						|
// CHECK: Block variable layout: BL_UNRETAINED:4, BL_OPERATOR:0
 | 
						|
    void (^c)() = ^{
 | 
						|
        x(imported_s.unsafe_unretained_var[2]);
 | 
						|
    };    
 | 
						|
 | 
						|
   c();
 | 
						|
}
 | 
						|
 | 
						|
// Test2 for array of stuff.
 | 
						|
void arr2() {
 | 
						|
  struct S {
 | 
						|
   int a;
 | 
						|
    __unsafe_unretained id unsafe_unretained_var[4];
 | 
						|
 } imported_s;
 | 
						|
 | 
						|
// CHECK: Block variable layout: BL_NON_OBJECT_WORD:1, BL_UNRETAINED:4, BL_OPERATOR:0
 | 
						|
    void (^c)() = ^{
 | 
						|
        x(imported_s.unsafe_unretained_var[2]);
 | 
						|
    };    
 | 
						|
 | 
						|
   c();
 | 
						|
}
 | 
						|
 | 
						|
// Test3 for array of stuff.
 | 
						|
void arr3() {
 | 
						|
  struct S {
 | 
						|
   int a;
 | 
						|
    __unsafe_unretained id unsafe_unretained_var[0];
 | 
						|
 } imported_s;
 | 
						|
 | 
						|
// CHECK: Block variable layout: BL_OPERATOR:0
 | 
						|
    void (^c)() = ^{
 | 
						|
      int i = imported_s.a;
 | 
						|
    };    
 | 
						|
 | 
						|
   c();
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// Test4 for array of stuff.
 | 
						|
@class B;
 | 
						|
void arr4() {
 | 
						|
  struct S {
 | 
						|
    struct s0 {
 | 
						|
      __unsafe_unretained id s_f0;
 | 
						|
      __unsafe_unretained id s_f1;
 | 
						|
    } f0;
 | 
						|
 | 
						|
    __unsafe_unretained id f1;
 | 
						|
 | 
						|
    struct s1 {
 | 
						|
      int *f0;
 | 
						|
      __unsafe_unretained B *f1;
 | 
						|
    } f4[2][2];
 | 
						|
  } captured_s;
 | 
						|
 | 
						|
// 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
 | 
						|
  void (^c)() = ^{
 | 
						|
      id i = captured_s.f0.s_f1;
 | 
						|
  };
 | 
						|
 | 
						|
   c();
 | 
						|
}
 | 
						|
 | 
						|
// Test1 bitfield in cpatured aggregate.
 | 
						|
void bf1() {
 | 
						|
  struct S {
 | 
						|
    int flag : 25;
 | 
						|
    int flag1: 7;
 | 
						|
    int flag2 :1;
 | 
						|
    int flag3: 7;
 | 
						|
    int flag4: 24;
 | 
						|
  } s;
 | 
						|
 | 
						|
// CHECK:  Block variable layout: BL_OPERATOR:0
 | 
						|
  int (^c)() = ^{
 | 
						|
      return s.flag;
 | 
						|
  };
 | 
						|
  c();
 | 
						|
}
 | 
						|
 | 
						|
// Test2 bitfield in cpatured aggregate.
 | 
						|
void bf2() {
 | 
						|
  struct S {
 | 
						|
    int flag : 1;
 | 
						|
  } s;
 | 
						|
 | 
						|
// CHECK: Block variable layout: BL_OPERATOR:0
 | 
						|
  int (^c)() = ^{
 | 
						|
      return s.flag;
 | 
						|
  };
 | 
						|
  c();
 | 
						|
}
 | 
						|
 | 
						|
// Test3 bitfield in cpatured aggregate.
 | 
						|
void bf3() {
 | 
						|
 | 
						|
     struct {
 | 
						|
        unsigned short _reserved : 16;
 | 
						|
 | 
						|
        unsigned char _draggedNodesAreDeletable: 1;
 | 
						|
        unsigned char _draggedOutsideOutlineView : 1;
 | 
						|
        unsigned char _adapterRespondsTo_addRootPaths : 1;
 | 
						|
        unsigned char _adapterRespondsTo_moveDataNodes : 1;
 | 
						|
        unsigned char _adapterRespondsTo_removeRootDataNode : 1;
 | 
						|
        unsigned char _adapterRespondsTo_doubleClickDataNode : 1;
 | 
						|
        unsigned char _adapterRespondsTo_selectDataNode : 1;
 | 
						|
        unsigned char _adapterRespondsTo_textDidEndEditing : 1;
 | 
						|
        unsigned char _adapterRespondsTo_updateAndSaveRoots : 1;
 | 
						|
        unsigned char _adapterRespondsTo_askToDeleteRootNodes : 1;
 | 
						|
        unsigned char _adapterRespondsTo_contextMenuForSelectedNodes : 1;
 | 
						|
        unsigned char _adapterRespondsTo_pasteboardFilenamesForNodes : 1;
 | 
						|
        unsigned char _adapterRespondsTo_writeItemsToPasteboard : 1;
 | 
						|
        unsigned char _adapterRespondsTo_writeItemsToPasteboardXXXX : 1;
 | 
						|
 | 
						|
        unsigned int _filler : 32;
 | 
						|
    } _flags;
 | 
						|
 | 
						|
// CHECK: Block variable layout: BL_OPERATOR:0
 | 
						|
  unsigned char (^c)() = ^{
 | 
						|
      return _flags._draggedNodesAreDeletable;
 | 
						|
  };
 | 
						|
 | 
						|
   c();
 | 
						|
}
 | 
						|
 | 
						|
// Test4 unnamed bitfield
 | 
						|
void bf4() {
 | 
						|
 | 
						|
     struct {
 | 
						|
        unsigned short _reserved : 16;
 | 
						|
 | 
						|
        unsigned char _draggedNodesAreDeletable: 1;
 | 
						|
        unsigned char _draggedOutsideOutlineView : 1;
 | 
						|
        unsigned char _adapterRespondsTo_addRootPaths : 1;
 | 
						|
        unsigned char _adapterRespondsTo_moveDataNodes : 1;
 | 
						|
        unsigned char _adapterRespondsTo_removeRootDataNode : 1;
 | 
						|
        unsigned char _adapterRespondsTo_doubleClickDataNode : 1;
 | 
						|
        unsigned char _adapterRespondsTo_selectDataNode : 1;
 | 
						|
        unsigned char _adapterRespondsTo_textDidEndEditing : 1;
 | 
						|
 | 
						|
        unsigned long long : 64;
 | 
						|
 | 
						|
        unsigned char _adapterRespondsTo_updateAndSaveRoots : 1;
 | 
						|
        unsigned char _adapterRespondsTo_askToDeleteRootNodes : 1;
 | 
						|
        unsigned char _adapterRespondsTo_contextMenuForSelectedNodes : 1;
 | 
						|
        unsigned char _adapterRespondsTo_pasteboardFilenamesForNodes : 1;
 | 
						|
        unsigned char _adapterRespondsTo_writeItemsToPasteboard : 1;
 | 
						|
        unsigned char _adapterRespondsTo_writeItemsToPasteboardXXXX : 1;
 | 
						|
 | 
						|
        unsigned int _filler : 32;
 | 
						|
    } _flags;
 | 
						|
 | 
						|
// CHECK:  Block variable layout: BL_OPERATOR:0
 | 
						|
  unsigned char (^c)() = ^{
 | 
						|
      return _flags._draggedNodesAreDeletable;
 | 
						|
  };
 | 
						|
 | 
						|
   c();
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
// Test5 unnamed bitfield.
 | 
						|
void bf5() {
 | 
						|
     struct {
 | 
						|
        unsigned char flag : 1;
 | 
						|
        unsigned int  : 32;
 | 
						|
        unsigned char flag1 : 1;
 | 
						|
    } _flags;
 | 
						|
 | 
						|
// CHECK:  Block variable layout: BL_OPERATOR:0
 | 
						|
  unsigned char (^c)() = ^{
 | 
						|
      return _flags.flag;
 | 
						|
  };
 | 
						|
 | 
						|
   c();
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// Test6 0 length bitfield.
 | 
						|
void bf6() {
 | 
						|
     struct {
 | 
						|
        unsigned char flag : 1;
 | 
						|
        unsigned int  : 0;
 | 
						|
        unsigned char flag1 : 1;
 | 
						|
    } _flags;
 | 
						|
 | 
						|
// CHECK: Block variable layout: BL_OPERATOR:0
 | 
						|
  unsigned char (^c)() = ^{
 | 
						|
      return _flags.flag;
 | 
						|
  };
 | 
						|
 | 
						|
   c();
 | 
						|
}
 | 
						|
 | 
						|
// Test7 large number of captured variables.
 | 
						|
void Test7() {
 | 
						|
    __weak id wid;
 | 
						|
    __weak id wid1, wid2, wid3, wid4;
 | 
						|
    __weak id wid5, wid6, wid7, wid8;
 | 
						|
    __weak id wid9, wid10, wid11, wid12;
 | 
						|
    __weak id wid13, wid14, wid15, wid16;
 | 
						|
    const id bar = (id) opaque_id();
 | 
						|
// CHECK: Block variable layout: BL_STRONG:1, BL_WEAK:16, BL_OPERATOR:0
 | 
						|
    void (^b)() = ^{
 | 
						|
      x(bar);
 | 
						|
      x(wid1);
 | 
						|
      x(wid2);
 | 
						|
      x(wid3);
 | 
						|
      x(wid4);
 | 
						|
      x(wid5);
 | 
						|
      x(wid6);
 | 
						|
      x(wid7);
 | 
						|
      x(wid8);
 | 
						|
      x(wid9);
 | 
						|
      x(wid10);
 | 
						|
      x(wid11);
 | 
						|
      x(wid12);
 | 
						|
      x(wid13);
 | 
						|
      x(wid14);
 | 
						|
      x(wid15);
 | 
						|
      x(wid16);
 | 
						|
    };    
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// Test 8 very large number of captured variables.
 | 
						|
void Test8() {
 | 
						|
__weak id wid;
 | 
						|
    __weak id wid1, wid2, wid3, wid4;
 | 
						|
    __weak id wid5, wid6, wid7, wid8;
 | 
						|
    __weak id wid9, wid10, wid11, wid12;
 | 
						|
    __weak id wid13, wid14, wid15, wid16;
 | 
						|
    __weak id w1, w2, w3, w4;
 | 
						|
    __weak id w5, w6, w7, w8;
 | 
						|
    __weak id w9, w10, w11, w12;
 | 
						|
    __weak id w13, w14, w15, w16;
 | 
						|
    const id bar = (id) opaque_id();
 | 
						|
// CHECK: Block variable layout: BL_STRONG:1, BL_WEAK:16, BL_WEAK:16, BL_WEAK:1, BL_OPERATOR:0
 | 
						|
    void (^b)() = ^{
 | 
						|
      x(bar);
 | 
						|
      x(wid1);
 | 
						|
      x(wid2);
 | 
						|
      x(wid3);
 | 
						|
      x(wid4);
 | 
						|
      x(wid5);
 | 
						|
      x(wid6);
 | 
						|
      x(wid7);
 | 
						|
      x(wid8);
 | 
						|
      x(wid9);
 | 
						|
      x(wid10);
 | 
						|
      x(wid11);
 | 
						|
      x(wid12);
 | 
						|
      x(wid13);
 | 
						|
      x(wid14);
 | 
						|
      x(wid15);
 | 
						|
      x(wid16);
 | 
						|
      x(w1);
 | 
						|
      x(w2);
 | 
						|
      x(w3);
 | 
						|
      x(w4);
 | 
						|
      x(w5);
 | 
						|
      x(w6);
 | 
						|
      x(w7);
 | 
						|
      x(w8);
 | 
						|
      x(w9);
 | 
						|
      x(w10);
 | 
						|
      x(w11);
 | 
						|
      x(w12);
 | 
						|
      x(w13);
 | 
						|
      x(w14);
 | 
						|
      x(w15);
 | 
						|
      x(w16);
 | 
						|
      x(wid);
 | 
						|
    };  
 | 
						|
}
 |