1// RUN: %clang_cc1 -triple i386-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-exceptions -fobjc-runtime=macosx-fragile-10.10 -o - %s | FileCheck %s 2// RUN: %clang_cc1 -triple i386-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-exceptions -fobjc-runtime=macosx-fragile-10.10 -o - %s | FileCheck %s -check-prefix=GLOBALS 3 4@class Opaque; 5 6@interface Root { 7 Class isa; 8} 9@end 10 11@interface A : Root { 12 Opaque *strong; 13 __weak Opaque *weak; 14} 15@end 16 17// GLOBALS-LABEL: @OBJC_METACLASS_A 18// Strong layout: scan the first word. 19// GLOBALS: @OBJC_CLASS_NAME_{{.*}} = private unnamed_addr constant [2 x i8] c"\01\00" 20// Weak layout: skip the first word, scan the second word. 21// GLOBALS: @OBJC_CLASS_NAME_{{.*}} = private unnamed_addr constant [2 x i8] c"\11\00" 22 23// 0x04002001 24// ^ is compiled by ARC (controls interpretation of layouts) 25// ^ has C++ structors (no distinction for zero-initializable) 26// ^ factory (always set on non-metaclasses) 27// GLOBALS: @OBJC_CLASS_A = private global {{.*}} i32 67117057 28 29@implementation A 30// CHECK-LABEL: define internal void @"\01-[A testStrong]" 31// CHECK: [[SELFVAR:%.*]] = alloca ptr, align 4 32- (void) testStrong { 33// CHECK: [[X:%x]] = alloca ptr, align 4 34// CHECK: [[SELF:%.*]] = load ptr, ptr [[SELFVAR]] 35// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr [[SELF]], i32 4 36// CHECK-NEXT: [[T0:%.*]] = load ptr, ptr [[T1]] 37// CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.retain(ptr [[T0]]) 38// CHECK-NEXT: store ptr [[T2]], ptr [[X]] 39 Opaque *x = strong; 40// CHECK-NEXT: [[VALUE:%.*]] = load ptr, ptr [[X]] 41// CHECK-NEXT: [[SELF:%.*]] = load ptr, ptr [[SELFVAR]] 42// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr [[SELF]], i32 4 43// CHECK-NEXT: call void @llvm.objc.storeStrong(ptr [[T1]], ptr [[VALUE]]) 44 strong = x; 45// CHECK-NEXT: call void @llvm.objc.storeStrong(ptr [[X]], ptr null) 46// CHECK-NEXT: ret void 47} 48 49// CHECK-LABEL: define internal void @"\01-[A testWeak]" 50// CHECK: [[SELFVAR:%.*]] = alloca ptr, align 4 51- (void) testWeak { 52// CHECK: [[X:%x]] = alloca ptr, align 4 53// CHECK: [[SELF:%.*]] = load ptr, ptr [[SELFVAR]] 54// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr [[SELF]], i32 8 55// CHECK-NEXT: [[T2:%.*]] = call ptr @llvm.objc.loadWeakRetained(ptr [[T1]]) 56// CHECK-NEXT: store ptr [[T2]], ptr [[X]] 57 Opaque *x = weak; 58// CHECK-NEXT: [[VALUE:%.*]] = load ptr, ptr [[X]] 59// CHECK-NEXT: [[SELF:%.*]] = load ptr, ptr [[SELFVAR]] 60// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr [[SELF]], i32 8 61// CHECK-NEXT: call ptr @llvm.objc.storeWeak(ptr [[T1]], ptr [[VALUE]]) 62 weak = x; 63// CHECK-NEXT: call void @llvm.objc.storeStrong(ptr [[X]], ptr null) 64// CHECK-NEXT: ret void 65} 66 67// CHECK-LABEL: define internal void @"\01-[A .cxx_destruct]" 68// CHECK: [[SELFVAR:%.*]] = alloca ptr, align 4 69// CHECK: [[SELF:%.*]] = load ptr, ptr [[SELFVAR]] 70// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr [[SELF]], i32 8 71// CHECK-NEXT: call void @llvm.objc.destroyWeak(ptr [[T1]]) 72// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr [[SELF]], i32 4 73// CHECK-NEXT: call void @llvm.objc.storeStrong(ptr [[T1]], ptr null) 74// CHECK-NEXT: ret void 75@end 76 77// Test case for corner case of ivar layout. 78@interface B : A { 79 char _b_flag; 80} 81@end 82 83@interface C : B { 84 char _c_flag; 85 __unsafe_unretained id c_unsafe[5]; 86 id c_strong[4]; 87 __weak id c_weak[3]; 88 id c_strong2[7]; 89} 90@end 91@implementation C @end 92 93// Note that these layouts implicitly start at the end of the previous 94// class rounded up to pointer alignment. 95// GLOBALS-LABEL: @OBJC_METACLASS_C 96// Strong layout: skip five, scan four, skip three, scan seven 97// 'T' == 0x54, '7' == 0x37 98// GLOBALS: @OBJC_CLASS_NAME_{{.*}} = private unnamed_addr constant [3 x i8] c"T7\00" 99// Weak layout: skip nine, scan three 100// GLOBALS: @OBJC_CLASS_NAME_{{.*}} = private unnamed_addr constant [2 x i8] c"\93\00" 101 102extern void useBlock(void (^block)(void)); 103 104// 256 == 0x100 == starts with 1 strong 105// GLOBALS: @"__block_descriptor{{.*}} = linkonce_odr hidden {{.*}}, i32 256 } 106void testBlockLayoutStrong(id x) { 107 useBlock(^{ (void) x; }); 108} 109 110// 1 == 0x001 == starts with 1 weak 111// GLOBALS: @"__block_descriptor{{.*}} = linkonce_odr hidden {{.*}}, i32 1 } 112void testBlockLayoutWeak(__weak id x) { 113 useBlock(^{ (void) x; }); 114} 115 116// CHECK-LABEL: define{{.*}} void @testCatch() 117// CHECK: [[X:%.*]] = alloca ptr, align 4 118// CHECK: [[Y:%.*]] = alloca ptr, align 4 119// CHECK: call void @objc_exception_try_enter 120// CHECK: br i1 121// CHECK: call void @checkpoint(i32 noundef 0) 122// CHECK: call void @objc_exception_try_exit 123// CHECK: br label 124// CHECK: call void @checkpoint(i32 noundef 3) 125// CHECK: [[EXN:%.*]] = call ptr @objc_exception_extract 126// CHECK: call i32 @objc_exception_match( 127// CHECK: br i1 128// CHECK: [[T2:%.*]] = call ptr @llvm.objc.retain(ptr [[EXN]]) 129// CHECK: store ptr [[T2]], ptr [[X]] 130// CHECK: call void @checkpoint(i32 noundef 1) 131// CHECK: call void @llvm.objc.storeStrong(ptr [[X]], ptr null) 132// CHECK: br label 133// CHECK: [[T0:%.*]] = call ptr @llvm.objc.retain(ptr [[EXN]]) 134// CHECK: store ptr [[T0]], ptr [[Y]] 135// CHECK: call void @checkpoint(i32 noundef 2) 136// CHECK: call void @llvm.objc.storeStrong(ptr [[Y]], ptr null) 137extern void checkpoint(int n); 138void testCatch(void) { 139 @try { 140 checkpoint(0); 141 } @catch (A *x) { 142 checkpoint(1); 143 } @catch (id y) { 144 checkpoint(2); 145 } 146 checkpoint(3); 147} 148