1// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -fobjc-runtime-has-weak -o - %s | FileCheck %s 2 3// CHECK: %[[STRUCT_TRIVIAL:.*]] = type { i32 } 4// CHECK: %[[STRUCT_TRIVIALBIG:.*]] = type { [64 x i32] } 5// CHECK: %[[STRUCT_STRONG:.*]] = type { i8* } 6// CHECK: %[[STRUCT_WEAK:.*]] = type { i8* } 7 8typedef struct { 9 int x; 10} Trivial; 11 12typedef struct { 13 int x[64]; 14} TrivialBig; 15 16typedef struct { 17 id x; 18} Strong; 19 20typedef struct { 21 __weak id x; 22} Weak; 23 24// CHECK: define i32 @testTrivial() 25// CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_TRIVIAL]], align 4 26// CHECK-NEXT: call void @func0(%[[STRUCT_TRIVIAL]]* %[[RETVAL]]) 27// CHECK-NOT: memcpy 28// CHECK: ret i32 % 29 30void func0(Trivial *); 31 32Trivial testTrivial(void) { 33 Trivial a; 34 func0(&a); 35 return a; 36} 37 38void func1(TrivialBig *); 39 40// CHECK: define void @testTrivialBig(%[[STRUCT_TRIVIALBIG]]* noalias sret %[[AGG_RESULT:.*]]) 41// CHECK: call void @func1(%[[STRUCT_TRIVIALBIG]]* %[[AGG_RESULT]]) 42// CHECK-NEXT: ret void 43 44TrivialBig testTrivialBig(void) { 45 TrivialBig a; 46 func1(&a); 47 return a; 48} 49 50// CHECK: define i8* @testStrong() 51// CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_STRONG]], align 8 52// CHECK: %[[NRVO:.*]] = alloca i1, align 1 53// CHECK: %[[V0:.*]] = bitcast %[[STRUCT_STRONG]]* %[[RETVAL]] to i8** 54// CHECK: call void @__default_constructor_8_s0(i8** %[[V0]]) 55// CHECK: store i1 true, i1* %[[NRVO]], align 1 56// CHECK: %[[NRVO_VAL:.*]] = load i1, i1* %[[NRVO]], align 1 57// CHECK: br i1 %[[NRVO_VAL]], 58 59// CHECK: %[[V1:.*]] = bitcast %[[STRUCT_STRONG]]* %[[RETVAL]] to i8** 60// CHECK: call void @__destructor_8_s0(i8** %[[V1]]) 61// CHECK: br 62 63// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_STRONG]], %[[STRUCT_STRONG]]* %[[RETVAL]], i32 0, i32 0 64// CHECK: %[[V2:.*]] = load i8*, i8** %[[COERCE_DIVE]], align 8 65// CHECK: ret i8* %[[V2]] 66 67Strong testStrong(void) { 68 Strong a; 69 return a; 70} 71 72// CHECK: define void @testWeak(%[[STRUCT_WEAK]]* noalias sret %[[AGG_RESULT:.*]]) 73// CHECK: %[[NRVO:.*]] = alloca i1, align 1 74// CHECK: %[[V0:.*]] = bitcast %[[STRUCT_WEAK]]* %[[AGG_RESULT]] to i8** 75// CHECK: call void @__default_constructor_8_w0(i8** %[[V0]]) 76// CHECK: store i1 true, i1* %[[NRVO]], align 1 77// CHECK: %[[NRVO_VAL:.*]] = load i1, i1* %[[NRVO]], align 1 78// CHECK: br i1 %[[NRVO_VAL]], 79 80// CHECK: %[[V1:.*]] = bitcast %[[STRUCT_WEAK]]* %[[AGG_RESULT]] to i8** 81// CHECK: call void @__destructor_8_w0(i8** %[[V1]]) 82// CHECK: br 83 84// CHECK-NOT: call 85// CHECK: ret void 86 87Weak testWeak(void) { 88 Weak a; 89 return a; 90} 91 92// CHECK: define void @testWeak2( 93// CHECK: call void @__default_constructor_8_w0( 94// CHECK: call void @__default_constructor_8_w0( 95// CHECK: call void @__copy_constructor_8_8_w0( 96// CHECK: call void @__copy_constructor_8_8_w0( 97// CHECK: call void @__destructor_8_w0( 98// CHECK: call void @__destructor_8_w0( 99 100Weak testWeak2(int c) { 101 Weak a, b; 102 if (c) 103 return a; 104 else 105 return b; 106} 107 108// CHECK: define internal void @"\01-[C1 foo1]"(%[[STRUCT_WEAK]]* noalias sret %[[AGG_RESULT:.*]], %{{.*}}* %{{.*}}, i8* %{{.*}}) 109// CHECK: %[[NRVO:.*]] = alloca i1, align 1 110// CHECK: %[[V0:.*]] = bitcast %[[STRUCT_WEAK]]* %[[AGG_RESULT]] to i8** 111// CHECK: call void @__default_constructor_8_w0(i8** %[[V0]]) 112// CHECK: store i1 true, i1* %[[NRVO]], align 1 113// CHECK: %[[NRVO_VAL:.*]] = load i1, i1* %[[NRVO]], align 1 114// CHECK: br i1 %[[NRVO_VAL]], 115 116// CHECK: %[[V1:.*]] = bitcast %[[STRUCT_WEAK]]* %[[AGG_RESULT]] to i8** 117// CHECK: call void @__destructor_8_w0(i8** %[[V1]]) 118// CHECK: br 119 120// CHECK-NOT: call 121// CHECK: ret void 122 123__attribute__((objc_root_class)) 124@interface C1 125- (Weak)foo1; 126@end 127 128@implementation C1 129- (Weak)foo1 { 130 Weak a; 131 return a; 132} 133@end 134