diff options
Diffstat (limited to 'test/CodeGenObjCXX')
-rw-r--r-- | test/CodeGenObjCXX/arc-globals.mm | 27 | ||||
-rw-r--r-- | test/CodeGenObjCXX/arc-mangle.mm | 25 | ||||
-rw-r--r-- | test/CodeGenObjCXX/arc-move.mm | 75 | ||||
-rw-r--r-- | test/CodeGenObjCXX/arc-new-delete.mm | 95 | ||||
-rw-r--r-- | test/CodeGenObjCXX/arc-pseudo-destructors.mm | 21 | ||||
-rw-r--r-- | test/CodeGenObjCXX/arc-references.mm | 83 | ||||
-rw-r--r-- | test/CodeGenObjCXX/arc-special-member-functions.mm | 161 | ||||
-rw-r--r-- | test/CodeGenObjCXX/arc.mm | 166 | ||||
-rw-r--r-- | test/CodeGenObjCXX/catch-id-type.mm | 48 | ||||
-rw-r--r-- | test/CodeGenObjCXX/copy.mm | 26 | ||||
-rw-r--r-- | test/CodeGenObjCXX/encode.mm | 14 | ||||
-rw-r--r-- | test/CodeGenObjCXX/gc.mm | 20 | ||||
-rw-r--r-- | test/CodeGenObjCXX/property-object-conditional-exp.mm | 7 | ||||
-rw-r--r-- | test/CodeGenObjCXX/property-objects.mm | 2 |
14 files changed, 766 insertions, 4 deletions
diff --git a/test/CodeGenObjCXX/arc-globals.mm b/test/CodeGenObjCXX/arc-globals.mm new file mode 100644 index 0000000..7167dbc --- /dev/null +++ b/test/CodeGenObjCXX/arc-globals.mm @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-nonfragile-abi -fblocks -fobjc-arc -O2 -disable-llvm-optzns -o - %s | FileCheck %s + +// Test that we're properly retaining lifetime-qualified pointers +// initialized statically and wrapping up those initialization in an +// autorelease pool. +id getObject(); + +// CHECK: define internal void @__cxx_global_var_init +// CHECK: call i8* @_Z9getObjectv +// CHECK-NEXT: call i8* @objc_retainAutoreleasedReturnValue +// CHECK-NEXT: {{store i8*.*@global_obj}} +// CHECK-NEXT: ret void +id global_obj = getObject(); + +// CHECK: define internal void @__cxx_global_var_init +// CHECK: call i8* @_Z9getObjectv +// CHECK-NEXT: call i8* @objc_retainAutoreleasedReturnValue +// CHECK-NEXT: {{store i8*.*@global_obj2}} +// CHECK-NEXT: ret void +id global_obj2 = getObject(); + +// CHECK: define internal void @_GLOBAL__I_a +// CHECK: call i8* @objc_autoreleasePoolPush() +// CHECK-NEXT: call void @__cxx_global_var_init +// CHECK-NEXT: call void @__cxx_global_var_init1 +// CHECK-NEXT: call void @objc_autoreleasePoolPop( +// CHECK-NEXT: ret void diff --git a/test/CodeGenObjCXX/arc-mangle.mm b/test/CodeGenObjCXX/arc-mangle.mm new file mode 100644 index 0000000..1955348 --- /dev/null +++ b/test/CodeGenObjCXX/arc-mangle.mm @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -fobjc-nonfragile-abi -fobjc-arc -fobjc-runtime-has-weak -emit-llvm -o - %s | FileCheck %s + +// CHECK: define void @_Z1fPU8__strongP11objc_object(i8**) +void f(__strong id *) {} +// CHECK: define void @_Z1fPU6__weakP11objc_object(i8**) +void f(__weak id *) {} +// CHECK: define void @_Z1fPU15__autoreleasingP11objc_object(i8**) +void f(__autoreleasing id *) {} +// CHECK: define void @_Z1fPP11objc_object(i8**) +void f(__unsafe_unretained id *) {} +// CHECK: define void @_Z1fPKU8__strongP11objc_object(i8**) +void f(const __strong id *) {} +// CHECK: define void @_Z1fPKU6__weakP11objc_object(i8**) +void f(const __weak id *) {} +// CHECK: define void @_Z1fPKU15__autoreleasingP11objc_object(i8**) +void f(const __autoreleasing id *) {} +// CHECK: define void @_Z1fPKP11objc_object(i8**) +void f(const __unsafe_unretained id *) {} + + +template<unsigned N> struct unsigned_c { }; + +// CHECK: define weak_odr void @_Z1gIKvEvP10unsigned_cIXplszv1U8__bridgecvPT_v1U8__bridgecvP11objc_objectcvS3_Li0ELi1EEE +template<typename T>void g(unsigned_c<sizeof((__bridge T*)(__bridge id)(T*)0) + 1>*) {} +template void g<const void>(unsigned_c<sizeof(id) + 1> *); diff --git a/test/CodeGenObjCXX/arc-move.mm b/test/CodeGenObjCXX/arc-move.mm new file mode 100644 index 0000000..70469e6 --- /dev/null +++ b/test/CodeGenObjCXX/arc-move.mm @@ -0,0 +1,75 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-nonfragile-abi -fblocks -fobjc-arc -O2 -std=c++0x -disable-llvm-optzns -o - %s | FileCheck %s + +// define void @_Z11simple_moveRU8__strongP11objc_objectS2_ +void simple_move(__strong id &x, __strong id &y) { + // CHECK: = load i8** + // CHECK: store i8* null + // CHECK: = load i8** + // CHECK: store i8* + // CHECK-NEXT: call void @objc_release + x = static_cast<__strong id&&>(y); + // CHECK-NEXT: ret void +} + +template<typename T> +struct remove_reference { + typedef T type; +}; + +template<typename T> +struct remove_reference<T&> { + typedef T type; +}; + +template<typename T> +struct remove_reference<T&&> { + typedef T type; +}; + +template<typename T> +typename remove_reference<T>::type&& move(T &&x) { + return static_cast<typename remove_reference<T>::type&&>(x); +} + +// CHECK: define void @_Z12library_moveRU8__strongP11objc_objectS2_ +void library_move(__strong id &x, __strong id &y) { + // CHECK: call i8** @_Z4moveIRU8__strongP11objc_objectEON16remove_referenceIT_E4typeEOS5_ + // CHECK: load i8** + // CHECK: store i8* null, i8** + // CHECK: load i8*** + // CHECK-NEXT: load i8** + // CHECK-NEXT: store i8* + // CHECK-NEXT: call void @objc_release + // CHECK-NEXT: ret void + x = move(y); +} + +// CHECK: define void @_Z12library_moveRU8__strongP11objc_object +void library_move(__strong id &y) { + // CHECK: [[Y:%[a-zA-Z0-9]+]] = call i8** @_Z4moveIRU8__strongP11objc_objectEON16remove_referenceIT_E4typeEOS5_ + // Load the object + // CHECK-NEXT: [[OBJ:%[a-zA-Z0-9]+]] = load i8** [[Y]] + // Null out y + // CHECK-NEXT: store i8* null, i8** [[Y]] + // Initialize x with the object + // CHECK-NEXT: store i8* [[OBJ]], i8** [[X:%[a-zA-Z0-9]+]] + id x = move(y); + + // CHECK-NEXT: store i32 17 + int i = 17; + // CHECK-NEXT: [[OBJ:%[a-zA-Z0-9]+]] = load i8** [[X]] + // CHECK-NEXT: call void @objc_release(i8* [[OBJ]]) + // CHECK-NEXT: ret void +} + +// CHECK: define void @_Z10const_moveRKU8__strongP11objc_object( +void const_move(const __strong id &x) { + // CHECK: [[Y:%.*]] = alloca i8*, + // CHECK: [[X:%.*]] = call i8** @_Z4moveIRKU8__strongP11objc_objectEON16remove_referenceIT_E4typeEOS5_( + // CHECK-NEXT: [[T0:%.*]] = load i8** [[X]] + // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]]) + // CHECK-NEXT: store i8* [[T1]], i8** [[Y]] + // CHECK-NEXT: [[T0:%.*]] = load i8** [[Y]] + // CHECK-NEXT: call void @objc_release(i8* [[T0]]) + id y = move(x); +} diff --git a/test/CodeGenObjCXX/arc-new-delete.mm b/test/CodeGenObjCXX/arc-new-delete.mm new file mode 100644 index 0000000..4597985 --- /dev/null +++ b/test/CodeGenObjCXX/arc-new-delete.mm @@ -0,0 +1,95 @@ +// RUN: %clang_cc1 -fobjc-nonfragile-abi -fobjc-arc -fobjc-runtime-has-weak -fblocks -triple x86_64-apple-darwin10.0.0 -emit-llvm -o - %s | FileCheck %s + +typedef __strong id strong_id; +typedef __weak id weak_id; + +// CHECK: define void @_Z8test_newP11objc_object +void test_new(id invalue) { + // CHECK: alloca i8* + // CHECK-NEXT: call i8* @objc_retain + + // CHECK: call noalias i8* @_Znwm + // CHECK-NEXT: {{bitcast i8\*.*to i8\*\*}} + // CHECK-NEXT: store i8* null, i8** + new strong_id; + // CHECK: call noalias i8* @_Znwm + // CHECK-NEXT: {{bitcast i8\*.*to i8\*\*}} + // CHECK-NEXT: store i8* null, i8** + new weak_id; + + // CHECK: call noalias i8* @_Znwm + // CHECK-NEXT: {{bitcast i8\*.*to i8\*\*}} + // CHECK-NEXT: store i8* null, i8** + new __strong id; + // CHECK: call noalias i8* @_Znwm + // CHECK-NEXT: {{bitcast i8\*.*to i8\*\*}} + // CHECK-NEXT: store i8* null, i8** + new __weak id; + + // CHECK: call noalias i8* @_Znwm + // CHECK: call i8* @objc_retain + // CHECK: store i8* + new __strong id(invalue); + + // CHECK: call noalias i8* @_Znwm + // CHECK: call i8* @objc_initWeak + new __weak id(invalue); + + // CHECK: call void @objc_release + // CHECK: ret void +} + +// CHECK: define void @_Z14test_array_new +void test_array_new() { + // CHECK: call noalias i8* @_Znam + // CHECK: store i64 17, i64* + // CHECK: call void @llvm.memset.p0i8.i64 + new strong_id[17]; + + // CHECK: call noalias i8* @_Znam + // CHECK: store i64 17, i64* + // CHECK: call void @llvm.memset.p0i8.i64 + new weak_id[17]; + // CHECK: ret void +} + +// CHECK: define void @_Z11test_deletePU8__strongP11objc_objectPU6__weakS0_ +void test_delete(__strong id *sptr, __weak id *wptr) { + // CHECK: br i1 + // CHECK: load i8** + // CHECK-NEXT: call void @objc_release + // CHECK: call void @_ZdlPv + delete sptr; + + // CHECK: call void @objc_destroyWeak + // CHECK: call void @_ZdlPv + delete wptr; + + // CHECK: ret void +} + +// CHECK: define void @_Z17test_array_deletePU8__strongP11objc_objectPU6__weakS0_ +void test_array_delete(__strong id *sptr, __weak id *wptr) { + // CHECK: icmp eq i8** [[BEGIN:%.*]], null + // CHECK: [[LEN:%.*]] = load i64* {{%.*}} + // CHECK: [[END:%.*]] = getelementptr inbounds i8** [[BEGIN]], i64 [[LEN]] + // CHECK-NEXT: icmp eq i8** [[BEGIN]], [[END]] + // CHECK: [[PAST:%.*]] = phi i8** [ [[END]], {{%.*}} ], [ [[CUR:%.*]], + // CHECK-NEXT: [[CUR]] = getelementptr inbounds i8** [[PAST]], i64 -1 + // CHECK-NEXT: [[T0:%.*]] = load i8** [[CUR]] + // CHECK-NEXT: call void @objc_release(i8* [[T0]]) + // CHECK-NEXT: icmp eq i8** [[CUR]], [[BEGIN]] + // CHECK: call void @_ZdaPv + delete [] sptr; + + // CHECK: icmp eq i8** [[BEGIN:%.*]], null + // CHECK: [[LEN:%.*]] = load i64* {{%.*}} + // CHECK: [[END:%.*]] = getelementptr inbounds i8** [[BEGIN]], i64 [[LEN]] + // CHECK-NEXT: icmp eq i8** [[BEGIN]], [[END]] + // CHECK: [[PAST:%.*]] = phi i8** [ [[END]], {{%.*}} ], [ [[CUR:%.*]], + // CHECK-NEXT: [[CUR]] = getelementptr inbounds i8** [[PAST]], i64 -1 + // CHECK-NEXT: call void @objc_destroyWeak(i8** [[CUR]]) + // CHECK-NEXT: icmp eq i8** [[CUR]], [[BEGIN]] + // CHECK: call void @_ZdaPv + delete [] wptr; +} diff --git a/test/CodeGenObjCXX/arc-pseudo-destructors.mm b/test/CodeGenObjCXX/arc-pseudo-destructors.mm new file mode 100644 index 0000000..4023e90 --- /dev/null +++ b/test/CodeGenObjCXX/arc-pseudo-destructors.mm @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -fobjc-nonfragile-abi -fobjc-arc -fobjc-runtime-has-weak -fblocks -triple x86_64-apple-darwin10.0.0 -emit-llvm -o - %s | FileCheck %s + +// CHECK: define void @_Z28test_objc_object_pseudo_dtorPU8__strongP11objc_objectPU6__weakS0_ +void test_objc_object_pseudo_dtor(__strong id *ptr, __weak id *wptr) { + // CHECK: load i8*** + // CHECK-NEXT: load i8** + // CHECK-NEXT: call void @objc_release + ptr->~id(); + + // CHECK: call void @objc_destroyWeak(i8** {{%.*}}) + wptr->~id(); + + // CHECK: load i8*** + // CHECK-NEXT: load i8** + // CHECK-NEXT: call void @objc_release + (*ptr).~id(); + + // CHECK: call void @objc_destroyWeak(i8** {{%.*}}) + (*wptr).~id(); + // CHECK: ret void +} diff --git a/test/CodeGenObjCXX/arc-references.mm b/test/CodeGenObjCXX/arc-references.mm new file mode 100644 index 0000000..3d0313d --- /dev/null +++ b/test/CodeGenObjCXX/arc-references.mm @@ -0,0 +1,83 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-nonfragile-abi -fobjc-runtime-has-weak -fblocks -fobjc-arc -O2 -disable-llvm-optzns -o - %s | FileCheck %s + +@interface A +@end + +id getObject(); +void callee(); + +// Lifetime extension for binding a reference to an rvalue +// CHECK: define void @_Z5test0v() +void test0() { + // CHECK: call i8* @_Z9getObjectv + // CHECK-NEXT:: call i8* @objc_retainAutoreleasedReturnValue + const __strong id &ref1 = getObject(); + // CHECK: call void @_Z6calleev + callee(); + // CHECK: call i8* @_Z9getObjectv + // CHECK-NEXT: call i8* @objc_retainAutoreleasedReturnValue + // CHECK-NEXT: call i8* @objc_autorelease + const __autoreleasing id &ref2 = getObject(); + // CHECK: call void @_Z6calleev + callee(); + // CHECK: call void @objc_release + // CHECK-NEXT: ret +} + +// No lifetime extension when we're binding a reference to an lvalue. +// CHECK: define void @_Z5test1RU8__strongP11objc_objectRU6__weakS0_ +void test1(__strong id &x, __weak id &y) { + // CHECK-NOT: release + const __strong id &ref1 = x; + const __autoreleasing id &ref2 = x; + const __weak id &ref3 = y; + // CHECK: ret void +} + +typedef __strong id strong_id; + +//CHECK: define void @_Z5test3v +void test3() { + // CHECK: call i8* @objc_initWeak + // CHECK-NEXT: store i8** + const __weak id &ref = strong_id(); + // CHECK-NEXT: call void @_Z6calleev() + callee(); + // CHECK-NEXT: call void @objc_destroyWeak + // CHECK-NEXT: ret void +} + +// CHECK: define void @_Z5test4RU8__strongP11objc_object +void test4(__strong id &x) { + // CHECK: call i8* @objc_retain + __strong A* const &ar = x; + // CHECK: store i32 17, i32* + int i = 17; + // CHECK: call void @objc_release( + // CHECK: ret void +} + +void sink(__strong A* &&); + +// CHECK: define void @_Z5test5RU8__strongP11objc_object +void test5(__strong id &x) { + // CHECK: [[OBJ_ID:%[a-zA-Z0-9]+]] = call i8* @objc_retain + // CHECK-NEXT: [[OBJ_A:%[a-zA-Z0-9]+]] = bitcast i8* [[OBJ_ID]] to [[A:%[a-zA-Z0-9]+]]* + // CHECK-NEXT: store [[A]]* [[OBJ_A]], [[A]]** [[REFTMP:%[a-zA-Z0-9]+]] + // CHECK-NEXT: call void @_Z4sinkOU8__strongP1A + sink(x); + // CHECK-NEXT: [[OBJ_A:%[a-zA-Z0-9]+]] = load [[A]]** [[REFTMP]] + // CHECK-NEXT: [[OBJ_ID:%[a-zA-Z0-9]+]] = bitcast [[A]]* [[OBJ_A]] to i8* + // CHECK-NEXT: call void @objc_release + // CHECK-NEXT: store i32 17, i32 + int i = 17; + // CHECK-NEXT: ret void +} + +// CHECK: define internal void @__cxx_global_var_init( +// CHECK: call i8* @_Z9getObjectv +// CHECK-NEXT: call i8* @objc_retainAutoreleasedReturnValue +const __strong id &global_ref = getObject(); + +// Note: we intentionally don't release the object. + diff --git a/test/CodeGenObjCXX/arc-special-member-functions.mm b/test/CodeGenObjCXX/arc-special-member-functions.mm new file mode 100644 index 0000000..d88a2bd --- /dev/null +++ b/test/CodeGenObjCXX/arc-special-member-functions.mm @@ -0,0 +1,161 @@ +// RUN: %clang_cc1 -fobjc-nonfragile-abi -fobjc-arc -fblocks -triple x86_64-apple-darwin10.0.0 -emit-llvm -o - %s | FileCheck %s + +struct ObjCMember { + id member; +}; + +struct ObjCArrayMember { + id member[2][3]; +}; + +struct ObjCBlockMember { + int (^bp)(int); +}; + +// CHECK: define void @_Z42test_ObjCMember_default_construct_destructv( +void test_ObjCMember_default_construct_destruct() { + // CHECK: call void @_ZN10ObjCMemberC1Ev + // CHECK: call void @_ZN10ObjCMemberD1Ev + ObjCMember m1; +} + +// CHECK: define void @_Z39test_ObjCMember_copy_construct_destruct10ObjCMember +void test_ObjCMember_copy_construct_destruct(ObjCMember m1) { + // CHECK: call void @_ZN10ObjCMemberC1ERKS_ + // CHECK: call void @_ZN10ObjCMemberD1Ev + ObjCMember m2 = m1; + // CHECK: ret void +} + +// CHECK: define void @_Z27test_ObjCMember_copy_assign10ObjCMemberS_ +void test_ObjCMember_copy_assign(ObjCMember m1, ObjCMember m2) { + // CHECK: {{call.*_ZN10ObjCMemberaSERKS_}} + m1 = m2; + // CHECK-NEXT: ret void +} + +// Implicitly-generated copy assignment operator for ObjCMember +// CHECK: {{define linkonce_odr.*@_ZN10ObjCMemberaSERKS_}} +// CHECK: call void @objc_storeStrong +// CHECK: ret + +// CHECK: define void @_Z47test_ObjCArrayMember_default_construct_destructv +void test_ObjCArrayMember_default_construct_destruct() { + // CHECK: call void @_ZN15ObjCArrayMemberC1Ev + ObjCArrayMember m1; + // CHECK: call void @_ZN15ObjCArrayMemberD1Ev + // CHECK: ret void +} + +// CHECK: define void @_Z44test_ObjCArrayMember_copy_construct_destruct15ObjCArrayMember +void test_ObjCArrayMember_copy_construct_destruct(ObjCArrayMember m1) { + // CHECK: call void @_ZN15ObjCArrayMemberC1ERKS_ + ObjCArrayMember m2 = m1; + // CHECK: call void @_ZN15ObjCArrayMemberD1Ev + // CHECK: ret void +} + +void test_ObjCArrayMember_copy_assign(ObjCArrayMember m1, ObjCArrayMember m2) { + // CHECK: {{call.*@_ZN15ObjCArrayMemberaSERKS_}} + m1 = m2; + // CHECK-NEXT: ret void +} + +// Implicitly-generated copy assignment operator for ObjCArrayMember +// CHECK: {{define linkonce_odr.*@_ZN15ObjCArrayMemberaSERKS_}} +// CHECK: call void @objc_storeStrong +// CHECK-NEXT: br label +// CHECK: ret + +// CHECK: define void @_Z47test_ObjCBlockMember_default_construct_destructv +void test_ObjCBlockMember_default_construct_destruct() { + // CHECK: call void @_ZN15ObjCBlockMemberC1Ev + ObjCBlockMember m; + // CHECK-NEXT: call void @_ZN15ObjCBlockMemberD1Ev + // CHECK-NEXT: ret void +} + +// CHECK: define void @_Z44test_ObjCBlockMember_copy_construct_destruct15ObjCBlockMember +void test_ObjCBlockMember_copy_construct_destruct(ObjCBlockMember m1) { + // CHECK: call void @_ZN15ObjCBlockMemberC1ERKS_ + ObjCBlockMember m2 = m1; + // CHECK-NEXT: call void @_ZN15ObjCBlockMemberD1Ev + // CHECK-NEXT: ret void +} + +// CHECK: define void @_Z32test_ObjCBlockMember_copy_assign15ObjCBlockMemberS_ +void test_ObjCBlockMember_copy_assign(ObjCBlockMember m1, ObjCBlockMember m2) { + // CHECK: {{call.*_ZN15ObjCBlockMemberaSERKS_}} + m1 = m2; + // CHECK-NEXT: ret void +} + +// Implicitly-generated copy assignment operator for ObjCBlockMember +// CHECK: define linkonce_odr {{%.*}}* @_ZN15ObjCBlockMemberaSERKS_( +// CHECK: [[T0:%.*]] = call i8* @objc_retainBlock( +// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to i32 (i32)* +// CHECK-NEXT: [[T2:%.*]] = load {{.*}} [[SLOT:%.*]], +// CHECK: store +// CHECK-NEXT: [[T3:%.*]] = bitcast +// CHECK-NEXT: call void @objc_release(i8* [[T3]]) +// CHECK-NEXT: ret + +// Implicitly-generated copy constructor for ObjCBlockMember +// CHECK: define linkonce_odr void @_ZN15ObjCBlockMemberC2ERKS_ +// CHECK: call i8* @objc_retainBlock +// CHECK: ret + +// Implicitly-generated destructor for ObjCBlockMember +// CHECK: define linkonce_odr void @_ZN15ObjCBlockMemberD2Ev +// CHECK: call void @objc_release(i8* +// CHECK: ret + +// Implicitly-generated default constructor for ObjCBlockMember +// CHECK: define linkonce_odr void @_ZN15ObjCBlockMemberC2Ev +// CHECK: store {{.*}} null, +// CHECK-NEXT: ret void + +// Implicitly-generated copy constructor for ObjCArrayMember +// CHECK: define linkonce_odr void @_ZN15ObjCArrayMemberC2ERKS_ +// CHECK: br i1 +// CHECK: call i8* @objc_retain +// CHECK-NEXT: store i8* +// CHECK-NEXT: br label +// CHECK: ret + +// Implicitly-generated destructor for ObjCArrayMember +// CHECK: define linkonce_odr void @_ZN15ObjCArrayMemberD2Ev +// CHECK: [[BEGIN:%.*]] = getelementptr inbounds [2 x [3 x i8*]]* +// CHECK-NEXT: [[END:%.*]] = getelementptr inbounds i8** [[BEGIN]], i64 6 +// CHECK-NEXT: br label +// CHECK: [[PAST:%.*]] = phi i8** [ [[END]], {{%.*}} ], [ [[CUR:%.*]], {{%.*}} ] +// CHECK-NEXT: [[CUR]] = getelementptr inbounds i8** [[PAST]], i64 -1 +// CHECK-NEXT: [[T0:%.*]] = load i8** [[CUR]] +// CHECK-NEXT: call void @objc_release(i8* [[T0]]) +// CHECK-NEXT: [[T1:%.*]] = icmp eq i8** [[CUR]], [[BEGIN]] +// CHECK-NEXT: br i1 [[T1]], +// CHECK: ret void + +// Implicitly-generated default constructor for ObjCArrayMember +// CHECK: define linkonce_odr void @_ZN15ObjCArrayMemberC2Ev +// CHECK: call void @llvm.memset.p0i8.i64 +// CHECK: ret + +// Implicitly-generated copy constructor for ObjCMember +// CHECK: define linkonce_odr void @_ZN10ObjCMemberC2ERKS_ +// CHECK-NOT: objc_release +// CHECK: call i8* @objc_retain +// CHECK-NEXT: store i8* +// CHECK-NEXT: ret void + +// Implicitly-generated destructor for ObjCMember +// CHECK: define linkonce_odr void @_ZN10ObjCMemberD2Ev +// CHECK: call void @objc_release +// CHECK: ret void + +// Implicitly-generated default constructor for ObjCMember +// CHECK: define linkonce_odr void @_ZN10ObjCMemberC2Ev +// CHECK-NOT: objc_release +// CHECK: store i8* null +// CHECK-NEXT: ret void + diff --git a/test/CodeGenObjCXX/arc.mm b/test/CodeGenObjCXX/arc.mm new file mode 100644 index 0000000..0c5466a --- /dev/null +++ b/test/CodeGenObjCXX/arc.mm @@ -0,0 +1,166 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-nonfragile-abi -fobjc-runtime-has-weak -fblocks -fobjc-arc -O2 -disable-llvm-optzns -o - %s | FileCheck %s + +// rdar://problem/9315552 +// The analogous ObjC testcase test46 in arr.m. +void test0(__weak id *wp, __weak volatile id *wvp) { + extern id test0_helper(void); + + // TODO: this is sub-optimal, we should retain at the actual call site. + // TODO: in the non-volatile case, we do not need to be reloading. + + // CHECK: [[T0:%.*]] = call i8* @_Z12test0_helperv() + // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) + // CHECK-NEXT: [[T2:%.*]] = load i8*** {{%.*}}, align 8 + // CHECK-NEXT: [[T3:%.*]] = call i8* @objc_storeWeak(i8** [[T2]], i8* [[T1]]) + // CHECK-NEXT: [[T4:%.*]] = call i8* @objc_retain(i8* [[T3]]) + // CHECK-NEXT: store i8* [[T4]], i8** + // CHECK-NEXT: call void @objc_release(i8* [[T1]]) + id x = *wp = test0_helper(); + + // CHECK: [[T0:%.*]] = call i8* @_Z12test0_helperv() + // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) + // CHECK-NEXT: [[T2:%.*]] = load i8*** {{%.*}}, align 8 + // CHECK-NEXT: [[T3:%.*]] = call i8* @objc_storeWeak(i8** [[T2]], i8* [[T1]]) + // CHECK-NEXT: [[T4:%.*]] = call i8* @objc_loadWeakRetained(i8** [[T2]]) + // CHECK-NEXT: store i8* [[T4]], i8** + // CHECK-NEXT: call void @objc_release(i8* [[T1]]) + id y = *wvp = test0_helper(); +} + +// rdar://problem/9320648 +struct Test1_helper { Test1_helper(); }; +@interface Test1 @end +@implementation Test1 { Test1_helper x; } @end +// CHECK: define internal i8* @"\01-[Test1 .cxx_construct]"( +// CHECK: call void @_ZN12Test1_helperC1Ev( +// CHECK-NEXT: load +// CHECK-NEXT: bitcast +// CHECK-NEXT: ret i8* + +void test34(int cond) { + __strong id strong; + __weak id weak; + extern void test34_sink(id *); + test34_sink(cond ? &strong : 0); + test34_sink(cond ? &weak : 0); + + // CHECK: define void @_Z6test34i( + // CHECK: [[COND:%.*]] = alloca i32 + // CHECK-NEXT: [[STRONG:%.*]] = alloca i8* + // CHECK-NEXT: [[WEAK:%.*]] = alloca i8* + // CHECK-NEXT: [[TEMP1:%.*]] = alloca i8* + // CHECK-NEXT: [[TEMP2:%.*]] = alloca i8* + // CHECK-NEXT: store i32 + // CHECK-NEXT: store i8* null, i8** [[STRONG]] + // CHECK-NEXT: call i8* @objc_initWeak(i8** [[WEAK]], i8* null) + + // CHECK-NEXT: [[T0:%.*]] = load i32* [[COND]] + // CHECK-NEXT: [[T1:%.*]] = icmp ne i32 [[T0]], 0 + // CHECK: [[ARG:%.*]] = phi i8** + // CHECK-NEXT: [[T0:%.*]] = icmp eq i8** [[ARG]], null + // CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i8** null, i8** [[TEMP1]] + // CHECK-NEXT: br i1 [[T0]], + // CHECK: [[T0:%.*]] = load i8** [[ARG]] + // CHECK-NEXT: store i8* [[T0]], i8** [[TEMP1]] + // CHECK-NEXT: br label + // CHECK: call void @_Z11test34_sinkPU15__autoreleasingP11objc_object(i8** [[T1]]) + // CHECK-NEXT: [[T0:%.*]] = icmp eq i8** [[ARG]], null + // CHECK-NEXT: br i1 [[T0]], + // CHECK: [[T0:%.*]] = load i8** [[TEMP1]] + // CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]]) + // CHECK-NEXT: [[T2:%.*]] = load i8** [[ARG]] + // CHECK-NEXT: store i8* [[T1]], i8** [[ARG]] + // CHECK-NEXT: call void @objc_release(i8* [[T2]]) + // CHECK-NEXT: br label + + // CHECK: [[T0:%.*]] = load i32* [[COND]] + // CHECK-NEXT: [[T1:%.*]] = icmp ne i32 [[T0]], 0 + // CHECK: [[ARG:%.*]] = phi i8** + // CHECK-NEXT: [[T0:%.*]] = icmp eq i8** [[ARG]], null + // CHECK-NEXT: [[T1:%.*]] = select i1 [[T0]], i8** null, i8** [[TEMP2]] + // CHECK-NEXT: br i1 [[T0]], + // CHECK: [[T0:%.*]] = call i8* @objc_loadWeak(i8** [[ARG]]) + // CHECK-NEXT: store i8* [[T0]], i8** [[TEMP2]] + // CHECK-NEXT: br label + // CHECK: call void @_Z11test34_sinkPU15__autoreleasingP11objc_object(i8** [[T1]]) + // CHECK-NEXT: [[T0:%.*]] = icmp eq i8** [[ARG]], null + // CHECK-NEXT: br i1 [[T0]], + // CHECK: [[T0:%.*]] = load i8** [[TEMP2]] + // CHECK-NEXT: call i8* @objc_storeWeak(i8** [[ARG]], i8* [[T0]]) + // CHECK-NEXT: br label + + // CHECK: call void @objc_destroyWeak(i8** [[WEAK]]) + // CHECK: ret void +} + +struct Test35_Helper { + static id makeObject1() __attribute__((ns_returns_retained)); + id makeObject2() __attribute__((ns_returns_retained)); + static id makeObject3(); + id makeObject4(); +}; + +// CHECK: define void @_Z6test3513Test35_HelperPS_ +void test35(Test35_Helper x0, Test35_Helper *x0p) { + // CHECK: call i8* @_ZN13Test35_Helper11makeObject1Ev + // CHECK-NOT: call i8* @objc_retain + id obj1 = Test35_Helper::makeObject1(); + // CHECK: call i8* @_ZN13Test35_Helper11makeObject2Ev + // CHECK-NOT: call i8* @objc_retain + id obj2 = x0.makeObject2(); + // CHECK: call i8* @_ZN13Test35_Helper11makeObject2Ev + // CHECK-NOT: call i8* @objc_retain + id obj3 = x0p->makeObject2(); + id (Test35_Helper::*pmf)() __attribute__((ns_returns_retained)) + = &Test35_Helper::makeObject2; + // CHECK: call i8* % + // CHECK-NOT: call i8* @objc_retain + id obj4 = (x0.*pmf)(); + // CHECK: call i8* % + // CHECK-NOT: call i8* @objc_retain + id obj5 = (x0p->*pmf)(); + + // CHECK: call void @objc_release + // CHECK: call void @objc_release + // CHECK: call void @objc_release + // CHECK: call void @objc_release + // CHECK: call void @objc_release + // CHECK-NEXT: ret void +} + +// CHECK: define void @_Z7test35b13Test35_HelperPS_ +void test35b(Test35_Helper x0, Test35_Helper *x0p) { + // CHECK: call i8* @_ZN13Test35_Helper11makeObject3Ev + // CHECK: call i8* @objc_retain + id obj1 = Test35_Helper::makeObject3(); + // CHECK: call i8* @_ZN13Test35_Helper11makeObject4Ev + // CHECK: call i8* @objc_retain + id obj2 = x0.makeObject4(); + // CHECK: call i8* @_ZN13Test35_Helper11makeObject4Ev + // CHECK: call i8* @objc_retain + id obj3 = x0p->makeObject4(); + id (Test35_Helper::*pmf)() = &Test35_Helper::makeObject4; + // CHECK: call i8* % + // CHECK: call i8* @objc_retain + id obj4 = (x0.*pmf)(); + // CHECK: call i8* % + // CHECK: call i8* @objc_retain + id obj5 = (x0p->*pmf)(); + + // CHECK: call void @objc_release + // CHECK: call void @objc_release + // CHECK: call void @objc_release + // CHECK: call void @objc_release + // CHECK: call void @objc_release + // CHECK-NEXT: ret void +} + +// rdar://problem/9603128 +// CHECK: define i8* @_Z6test36P11objc_object( +id test36(id z) { + // CHECK: objc_retain + // CHECK: objc_retain + // CHECK: objc_release + // CHECK: objc_autoreleaseReturnValue + return z; +} diff --git a/test/CodeGenObjCXX/catch-id-type.mm b/test/CodeGenObjCXX/catch-id-type.mm new file mode 100644 index 0000000..ece342b --- /dev/null +++ b/test/CodeGenObjCXX/catch-id-type.mm @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 -triple i386-apple-macosx10.6.6 -emit-llvm -fobjc-exceptions -fcxx-exceptions -fexceptions -o - %s | FileCheck %s +// rdar://8940528 + +@interface ns_array ++ (id) array; +@end + +@implementation ns_array ++ (id) array { return 0; } +@end + +id Groups(); + +@protocol P @end; + +@interface INTF<P> { + double dd; +} +@end + +id FUNC() { + id groups; + try + { + groups = Groups(); // throws on errors. + } + catch( INTF<P>* error ) + { + Groups(); + } + catch( id error ) + { + // CHECK: call i32 (i8*, i8*, ...)* @llvm.eh.selector({{.*}} @__gxx_personality_v0 {{.*}} @_ZTIP4INTF {{.*}} @_ZTIP11objc_object {{.*}} @_ZTIP10objc_class + error = error; + groups = [ns_array array]; + } + catch (Class cl) { + cl = cl; + groups = [ns_array array]; + } + return groups; + +} + +int main() { + FUNC(); + return 0; +} diff --git a/test/CodeGenObjCXX/copy.mm b/test/CodeGenObjCXX/copy.mm new file mode 100644 index 0000000..133910f --- /dev/null +++ b/test/CodeGenObjCXX/copy.mm @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s + +// rdar://problem/9158302 +// This should not use a memmove_collectable in non-GC mode. +namespace test0 { + struct A { + id x; + }; + + // CHECK: define [[A:%.*]]* @_ZN5test04testENS_1AE( + // CHECK: alloca + // CHECK-NEXT: getelementptr + // CHECK-NEXT: store + // CHECK-NEXT: call noalias i8* @_Znwm( + // CHECK-NEXT: bitcast + // CHECK-NEXT: bitcast + // CHECK-NEXT: call void @llvm.memset.p0i8.i64( + // CHECK-NEXT: bitcast + // CHECK-NEXT: bitcast + // CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64( + // CHECK-NEXT: ret + A *test(A a) { + return new A(a); + } +} + diff --git a/test/CodeGenObjCXX/encode.mm b/test/CodeGenObjCXX/encode.mm index dce3d70..2c10fbc 100644 --- a/test/CodeGenObjCXX/encode.mm +++ b/test/CodeGenObjCXX/encode.mm @@ -91,6 +91,20 @@ namespace rdar9357400 { const char gg[] = @encode(vector4f); } +// rdar://9624314 +namespace rdar9624314 { + struct B2 { int x; }; + struct B3 {}; + struct S : B2, B3 {}; + + // CHECK: @_ZN11rdar9624314L2ggE = internal constant [6 x i8] c"{S=i}\00" + const char gg[] = @encode(S); + + struct S2 { unsigned : 0; int x; unsigned : 0; }; + // CHECK: @_ZN11rdar9624314L2g2E = internal constant [11 x i8] c"{S2=b0ib0}\00" + const char g2[] = @encode(S2); +} + struct Base1 { char x; }; diff --git a/test/CodeGenObjCXX/gc.mm b/test/CodeGenObjCXX/gc.mm new file mode 100644 index 0000000..aa293da --- /dev/null +++ b/test/CodeGenObjCXX/gc.mm @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fobjc-gc -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s + +namespace test0 { + extern id x; + + struct A { + id x; + A(); + }; + A::A() : x(test0::x) {} + +// CHECK: define void @_ZN5test01AC2Ev( +// CHECK: [[THIS:%.*]] = alloca [[TEST0:%.*]]*, align 8 +// CHECK-NEXT: store +// CHECK-NEXT: [[T0:%.*]] = load [[TEST0]]** [[THIS]] +// CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[TEST0]]* [[T0]], i32 0, i32 0 +// CHECK-NEXT: [[T2:%.*]] = load i8** @_ZN5test01xE +// CHECK-NEXT: call i8* @objc_assign_strongCast(i8* [[T2]], i8** [[T1]]) +// CHECK-NEXT: ret void +} diff --git a/test/CodeGenObjCXX/property-object-conditional-exp.mm b/test/CodeGenObjCXX/property-object-conditional-exp.mm index a3c1027..5d8a882 100644 --- a/test/CodeGenObjCXX/property-object-conditional-exp.mm +++ b/test/CodeGenObjCXX/property-object-conditional-exp.mm @@ -22,11 +22,12 @@ extern "C" bool CGRectIsEmpty(CGRect); CGRect dataRect; CGRect virtualBounds; -// CHECK: [[SRC:%.*]] = call %struct.CGRect bitcast (i8* (i8*, i8*, ...)* @objc_msgSend -// CHECK-NEXT:getelementptr %struct.CGRect* [[SRC:%.*]] +// CHECK: [[SRC:%.*]] = call { i8*, i32 } bitcast (i8* (i8*, i8*, ...)* @objc_msgSend +// CHECK-NEXT: bitcast +// CHECK-NEXT:getelementptr { i8*, i32 }* [[SRC:%.*]] // CHECK-NEXT:extractvalue // CHECK-NEXT:store -// CHECK-NEXT:getelementptr %struct.CGRect* [[SRC:%.*]] +// CHECK-NEXT:getelementptr { i8*, i32 }* [[SRC:%.*]] // CHECK-NEXT:extractvalue // CHECK-NEXT:store dataRect = CGRectIsEmpty(virtualBounds) ? self.bounds : virtualBounds; diff --git a/test/CodeGenObjCXX/property-objects.mm b/test/CodeGenObjCXX/property-objects.mm index 8e98b0d..1f43117 100644 --- a/test/CodeGenObjCXX/property-objects.mm +++ b/test/CodeGenObjCXX/property-objects.mm @@ -2,7 +2,7 @@ // CHECK-NOT: callq _objc_msgSend_stret // CHECK: call void @_ZN1SC1ERKS_ // CHECK: call %class.S* @_ZN1SaSERKS_ -// CHECK: call %class.S* @_ZN6CGRectaSERKS_ +// CHECK: call %struct.CGRect* @_ZN6CGRectaSERKS_ class S { public: |