148 lines · plain
1// RUN: %clang_cc1 -triple i386-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-exceptions -fobjc-runtime=macosx-fragile-10.10 -o - %s | FileCheck %s2// 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=GLOBALS3 4@class Opaque;5 6@interface Root {7 Class isa;8}9@end10 11@interface A : Root {12 Opaque *strong;13 __weak Opaque *weak;14}15@end16 17// GLOBALS-LABEL: @OBJC_METACLASS_A18// 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// 0x0400200124// ^ 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 6711705728 29@implementation A30// CHECK-LABEL: define internal void @"\01-[A testStrong]"31// CHECK: [[SELFVAR:%.*]] = alloca ptr, align 432- (void) testStrong {33// CHECK: [[X:%x]] = alloca ptr, align 434// CHECK: [[SELF:%.*]] = load ptr, ptr [[SELFVAR]]35// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr [[SELF]], i32 436// 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 443// 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 void47}48 49// CHECK-LABEL: define internal void @"\01-[A testWeak]"50// CHECK: [[SELFVAR:%.*]] = alloca ptr, align 451- (void) testWeak {52// CHECK: [[X:%x]] = alloca ptr, align 453// CHECK: [[SELF:%.*]] = load ptr, ptr [[SELFVAR]]54// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr [[SELF]], i32 855// 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 861// 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 void65}66 67// CHECK-LABEL: define internal void @"\01-[A .cxx_destruct]"68// CHECK: [[SELFVAR:%.*]] = alloca ptr, align 469// CHECK: [[SELF:%.*]] = load ptr, ptr [[SELFVAR]]70// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr [[SELF]], i32 871// CHECK-NEXT: call void @llvm.objc.destroyWeak(ptr [[T1]])72// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds i8, ptr [[SELF]], i32 473// CHECK-NEXT: call void @llvm.objc.storeStrong(ptr [[T1]], ptr null)74// CHECK-NEXT: ret void75@end76 77// Test case for corner case of ivar layout.78@interface B : A {79 char _b_flag;80}81@end82 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@end91@implementation C @end92 93// Note that these layouts implicitly start at the end of the previous94// class rounded up to pointer alignment.95// GLOBALS-LABEL: @OBJC_METACLASS_C96// Strong layout: skip five, scan four, skip three, scan seven97// 'T' == 0x54, '7' == 0x3798// GLOBALS: @OBJC_CLASS_NAME_{{.*}} = private unnamed_addr constant [3 x i8] c"T7\00"99// Weak layout: skip nine, scan three100// 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 strong105// GLOBALS: @"__block_descriptor{{.*}} = linkonce_odr hidden {{.*}}, i32 256 }106void testBlockLayoutStrong(id x) {107 useBlock(^{ (void) x; });108}109 110// 1 == 0x001 == starts with 1 weak111// 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 4118// CHECK: [[Y:%.*]] = alloca ptr, align 4119// CHECK: call void @objc_exception_try_enter120// CHECK: br i1121// CHECK: call void @checkpoint(i32 noundef 0)122// CHECK: call void @objc_exception_try_exit123// CHECK: br label124// CHECK: call void @checkpoint(i32 noundef 3)125// CHECK: [[EXN:%.*]] = call ptr @objc_exception_extract126// CHECK: call i32 @objc_exception_match(127// CHECK: br i1128// 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 label133// 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