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