1*67e74705SXin Li// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -O2 -std=c++11 -disable-llvm-optzns -o - %s | FileCheck %s 2*67e74705SXin Li 3*67e74705SXin Li// define void @_Z11simple_moveRU8__strongP11objc_objectS2_ 4*67e74705SXin Livoid simple_move(__strong id &x, __strong id &y) { 5*67e74705SXin Li // CHECK: = load i8*, i8** 6*67e74705SXin Li // CHECK: store i8* null 7*67e74705SXin Li // CHECK: = load i8*, i8** 8*67e74705SXin Li // CHECK: store i8* 9*67e74705SXin Li // CHECK-NEXT: call void @objc_release 10*67e74705SXin Li x = static_cast<__strong id&&>(y); 11*67e74705SXin Li // CHECK-NEXT: ret void 12*67e74705SXin Li} 13*67e74705SXin Li 14*67e74705SXin Litemplate<typename T> 15*67e74705SXin Listruct remove_reference { 16*67e74705SXin Li typedef T type; 17*67e74705SXin Li}; 18*67e74705SXin Li 19*67e74705SXin Litemplate<typename T> 20*67e74705SXin Listruct remove_reference<T&> { 21*67e74705SXin Li typedef T type; 22*67e74705SXin Li}; 23*67e74705SXin Li 24*67e74705SXin Litemplate<typename T> 25*67e74705SXin Listruct remove_reference<T&&> { 26*67e74705SXin Li typedef T type; 27*67e74705SXin Li}; 28*67e74705SXin Li 29*67e74705SXin Litemplate<typename T> 30*67e74705SXin Litypename remove_reference<T>::type&& move(T &&x) { 31*67e74705SXin Li return static_cast<typename remove_reference<T>::type&&>(x); 32*67e74705SXin Li} 33*67e74705SXin Li 34*67e74705SXin Li// CHECK-LABEL: define void @_Z12library_moveRU8__strongP11objc_objectS2_ 35*67e74705SXin Livoid library_move(__strong id &x, __strong id &y) { 36*67e74705SXin Li // CHECK: call dereferenceable({{[0-9]+}}) i8** @_Z4moveIRU8__strongP11objc_objectEON16remove_referenceIT_E4typeEOS5_ 37*67e74705SXin Li // CHECK: load i8*, i8** 38*67e74705SXin Li // CHECK: store i8* null, i8** 39*67e74705SXin Li // CHECK: load i8**, i8*** 40*67e74705SXin Li // CHECK-NEXT: load i8*, i8** 41*67e74705SXin Li // CHECK-NEXT: store i8* 42*67e74705SXin Li // CHECK-NEXT: call void @objc_release 43*67e74705SXin Li // CHECK-NEXT: ret void 44*67e74705SXin Li x = move(y); 45*67e74705SXin Li} 46*67e74705SXin Li 47*67e74705SXin Li// CHECK-LABEL: define void @_Z12library_moveRU8__strongP11objc_object 48*67e74705SXin Livoid library_move(__strong id &y) { 49*67e74705SXin Li // CHECK: [[X:%.*]] = alloca i8*, align 8 50*67e74705SXin Li // CHECK: [[I:%.*]] = alloca i32, align 4 51*67e74705SXin Li // CHECK: [[XPTR1:%.*]] = bitcast i8** [[X]] to i8* 52*67e74705SXin Li // CHECK-NEXT: call void @llvm.lifetime.start(i64 8, i8* [[XPTR1]]) 53*67e74705SXin Li // CHECK: [[Y:%[a-zA-Z0-9]+]] = call dereferenceable({{[0-9]+}}) i8** @_Z4moveIRU8__strongP11objc_objectEON16remove_referenceIT_E4typeEOS5_ 54*67e74705SXin Li // Load the object 55*67e74705SXin Li // CHECK-NEXT: [[OBJ:%[a-zA-Z0-9]+]] = load i8*, i8** [[Y]] 56*67e74705SXin Li // Null out y 57*67e74705SXin Li // CHECK-NEXT: store i8* null, i8** [[Y]] 58*67e74705SXin Li // Initialize x with the object 59*67e74705SXin Li // CHECK-NEXT: store i8* [[OBJ]], i8** [[X:%[a-zA-Z0-9]+]] 60*67e74705SXin Li id x = move(y); 61*67e74705SXin Li 62*67e74705SXin Li // CHECK-NEXT: [[IPTR1:%.*]] = bitcast i32* [[I]] to i8* 63*67e74705SXin Li // CHECK-NEXT: call void @llvm.lifetime.start(i64 4, i8* [[IPTR1]]) 64*67e74705SXin Li // CHECK-NEXT: store i32 17 65*67e74705SXin Li int i = 17; 66*67e74705SXin Li // CHECK-NEXT: [[IPTR2:%.*]] = bitcast i32* [[I]] to i8* 67*67e74705SXin Li // CHECK-NEXT: call void @llvm.lifetime.end(i64 4, i8* [[IPTR2]]) 68*67e74705SXin Li // CHECK-NEXT: [[OBJ:%[a-zA-Z0-9]+]] = load i8*, i8** [[X]] 69*67e74705SXin Li // CHECK-NEXT: call void @objc_release(i8* [[OBJ]]) 70*67e74705SXin Li // CHECK-NEXT: [[XPTR2:%.*]] = bitcast i8** [[X]] to i8* 71*67e74705SXin Li // CHECK-NEXT: call void @llvm.lifetime.end(i64 8, i8* [[XPTR2]]) 72*67e74705SXin Li // CHECK-NEXT: ret void 73*67e74705SXin Li} 74*67e74705SXin Li 75*67e74705SXin Li// CHECK-LABEL: define void @_Z10const_moveRU8__strongKP11objc_object( 76*67e74705SXin Livoid const_move(const __strong id &x) { 77*67e74705SXin Li // CHECK: [[Y:%.*]] = alloca i8*, 78*67e74705SXin Li // CHECK: [[X:%.*]] = call dereferenceable({{[0-9]+}}) i8** @_Z4moveIRU8__strongKP11objc_objectEON16remove_referenceIT_E4typeEOS5_( 79*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[X]] 80*67e74705SXin Li // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]]) 81*67e74705SXin Li // CHECK-NEXT: store i8* [[T1]], i8** [[Y]] 82*67e74705SXin Li // CHECK-NEXT: [[T0:%.*]] = load i8*, i8** [[Y]] 83*67e74705SXin Li // CHECK-NEXT: call void @objc_release(i8* [[T0]]) 84*67e74705SXin Li id y = move(x); 85*67e74705SXin Li} 86