1// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-runtime-has-weak -fblocks -fobjc-arc -O2 -disable-llvm-optzns -o - %s | FileCheck %s 2 3@interface A 4@end 5 6id getObject(); 7void callee(); 8 9// Lifetime extension for binding a reference to an rvalue 10// CHECK-LABEL: define void @_Z5test0v() 11void test0() { 12 // CHECK: call i8* @_Z9getObjectv 13 // CHECK-NEXT: call i8* @objc_retainAutoreleasedReturnValue 14 const __strong id &ref1 = getObject(); 15 // CHECK: call void @_Z6calleev 16 callee(); 17 // CHECK: call i8* @_Z9getObjectv 18 // CHECK-NEXT: call i8* @objc_retainAutoreleasedReturnValue 19 // CHECK-NEXT: call i8* @objc_autorelease 20 const __autoreleasing id &ref2 = getObject(); 21 // CHECK: call void @_Z6calleev 22 callee(); 23 // CHECK: call void @objc_release 24 // CHECK-NEXT: ret 25} 26 27// No lifetime extension when we're binding a reference to an lvalue. 28// CHECK-LABEL: define void @_Z5test1RU8__strongP11objc_objectRU6__weakS0_ 29void test1(__strong id &x, __weak id &y) { 30 // CHECK-NOT: release 31 const __strong id &ref1 = x; 32 const __autoreleasing id &ref2 = x; 33 const __weak id &ref3 = y; 34 // CHECK: ret void 35} 36 37typedef __strong id strong_id; 38 39//CHECK: define void @_Z5test3v 40void test3() { 41 // CHECK: [[REF:%.*]] = alloca i8**, align 8 42 // CHECK: call i8* @objc_initWeak 43 // CHECK-NEXT: store i8** 44 const __weak id &ref = strong_id(); 45 // CHECK-NEXT: call void @_Z6calleev() 46 callee(); 47 // CHECK-NEXT: [[PTR:%.*]] = bitcast i8*** [[REF]] to i8* 48 // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[PTR]]) 49 // CHECK-NEXT: call void @objc_destroyWeak 50 // CHECK-NEXT: ret void 51} 52 53// CHECK-LABEL: define void @_Z5test4RU8__strongP11objc_object 54void test4(__strong id &x) { 55 // CHECK: call i8* @objc_retain 56 __strong A* const &ar = x; 57 // CHECK: store i32 17, i32* 58 int i = 17; 59 // CHECK: call void @objc_release( 60 // CHECK: ret void 61} 62 63void sink(__strong A* &&); 64 65// CHECK-LABEL: define void @_Z5test5RU8__strongP11objc_object 66void test5(__strong id &x) { 67 // CHECK: [[REFTMP:%.*]] = alloca {{%.*}}*, align 8 68 // CHECK: [[I:%.*]] = alloca i32, align 4 69 // CHECK: [[OBJ_ID:%.*]] = call i8* @objc_retain( 70 // CHECK-NEXT: [[OBJ_A:%.*]] = bitcast i8* [[OBJ_ID]] to [[A:%[a-zA-Z0-9]+]]* 71 // CHECK-NEXT: store [[A]]* [[OBJ_A]], [[A]]** [[REFTMP:%[a-zA-Z0-9]+]] 72 // CHECK-NEXT: call void @_Z4sinkOU8__strongP1A 73 sink(x); 74 // CHECK-NEXT: [[OBJ_A:%[a-zA-Z0-9]+]] = load [[A]]*, [[A]]** [[REFTMP]] 75 // CHECK-NEXT: [[OBJ_ID:%[a-zA-Z0-9]+]] = bitcast [[A]]* [[OBJ_A]] to i8* 76 // CHECK-NEXT: call void @objc_release 77 // CHECK-NEXT: [[IPTR1:%.*]] = bitcast i32* [[I]] to i8* 78 // CHECK-NEXT: call void @llvm.lifetime.start(i64 4, i8* [[IPTR1]]) 79 // CHECK-NEXT: store i32 17, i32 80 int i = 17; 81 // CHECK-NEXT: [[IPTR2:%.*]] = bitcast i32* [[I]] to i8* 82 // CHECK-NEXT: call void @llvm.lifetime.end(i64 4, i8* [[IPTR2]]) 83 // CHECK-NEXT: ret void 84} 85 86// CHECK-LABEL: define internal void @__cxx_global_var_init( 87// CHECK: call i8* @_Z9getObjectv 88// CHECK-NEXT: call i8* @objc_retainAutoreleasedReturnValue 89const __strong id &global_ref = getObject(); 90 91// Note: we intentionally don't release the object. 92 93