diff options
Diffstat (limited to 'clang/test/CodeGenObjCXX')
53 files changed, 2959 insertions, 0 deletions
diff --git a/clang/test/CodeGenObjCXX/2007-10-03-MetadataPointers.mm b/clang/test/CodeGenObjCXX/2007-10-03-MetadataPointers.mm new file mode 100644 index 0000000..2564d67 --- /dev/null +++ b/clang/test/CodeGenObjCXX/2007-10-03-MetadataPointers.mm @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -emit-llvm %s -o /dev/null + +@class NSImage; +void bork() { + NSImage *nsimage; + [nsimage release]; +} diff --git a/clang/test/CodeGenObjCXX/2010-08-04-Template.mm b/clang/test/CodeGenObjCXX/2010-08-04-Template.mm new file mode 100644 index 0000000..c53e3cb --- /dev/null +++ b/clang/test/CodeGenObjCXX/2010-08-04-Template.mm @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -emit-llvm %s -o - +struct TRunSoon { + template <class P1> static void Post() {} +}; + +@implementation TPrivsTableViewMainController +- (void) applyToEnclosed { + TRunSoon::Post<int>(); +} +@end diff --git a/clang/test/CodeGenObjCXX/2010-08-06-X.Y-syntax.mm b/clang/test/CodeGenObjCXX/2010-08-06-X.Y-syntax.mm new file mode 100644 index 0000000..290aaf6 --- /dev/null +++ b/clang/test/CodeGenObjCXX/2010-08-06-X.Y-syntax.mm @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -emit-llvm %s -o - +struct TFENode { + TFENode(const TFENode& inNode); +}; + +@interface TIconViewController +- (const TFENode&) target; +@end + +void sortAllChildrenForNode(const TFENode&node); + +@implementation TIconViewController +- (void) setArrangeBy { + sortAllChildrenForNode(self.target); +} +@end diff --git a/clang/test/CodeGenObjCXX/Inputs/literal-support.h b/clang/test/CodeGenObjCXX/Inputs/literal-support.h new file mode 100644 index 0000000..5680a20 --- /dev/null +++ b/clang/test/CodeGenObjCXX/Inputs/literal-support.h @@ -0,0 +1,35 @@ +#ifndef OBJC_LITERAL_SUPPORT_H +#define OBJC_LITERAL_SUPPORT_H + +typedef unsigned char BOOL; + +@interface NSNumber @end + +@interface NSNumber (NSNumberCreation) ++ (NSNumber *)numberWithChar:(char)value; ++ (NSNumber *)numberWithUnsignedChar:(unsigned char)value; ++ (NSNumber *)numberWithShort:(short)value; ++ (NSNumber *)numberWithUnsignedShort:(unsigned short)value; ++ (NSNumber *)numberWithInt:(int)value; ++ (NSNumber *)numberWithUnsignedInt:(unsigned int)value; ++ (NSNumber *)numberWithLong:(long)value; ++ (NSNumber *)numberWithUnsignedLong:(unsigned long)value; ++ (NSNumber *)numberWithLongLong:(long long)value; ++ (NSNumber *)numberWithUnsignedLongLong:(unsigned long long)value; ++ (NSNumber *)numberWithFloat:(float)value; ++ (NSNumber *)numberWithDouble:(double)value; ++ (NSNumber *)numberWithBool:(BOOL)value; +@end + +@interface NSArray +@end + +@interface NSArray (NSArrayCreation) ++ (id)arrayWithObjects:(const id [])objects count:(unsigned long)cnt; +@end + +@interface NSDictionary ++ (id)dictionaryWithObjects:(const id [])objects forKeys:(const id [])keys count:(unsigned long)cnt; +@end + +#endif // OBJC_LITERAL_SUPPORT_H diff --git a/clang/test/CodeGenObjCXX/address-safety-attr.mm b/clang/test/CodeGenObjCXX/address-safety-attr.mm new file mode 100644 index 0000000..a54ca99 --- /dev/null +++ b/clang/test/CodeGenObjCXX/address-safety-attr.mm @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -emit-llvm -o - %s -faddress-sanitizer | FileCheck -check-prefix ASAN %s + +@interface MyClass ++ (int) addressSafety:(int*)a; +@end + +@implementation MyClass + +// CHECK-NOT: +[MyClass load]{{.*}} address_safety +// CHECK: +[MyClass load]{{.*}} +// ASAN: +[MyClass load]{{.*}} address_safety ++(void) load { } + +// CHECK-NOT: +[MyClass addressSafety:]{{.*}} address_safety +// CHECK: +[MyClass addressSafety:]{{.*}} +// ASAN: +[MyClass addressSafety:]{{.*}} address_safety ++ (int) addressSafety:(int*)a { return *a; } + +@end diff --git a/clang/test/CodeGenObjCXX/arc-exceptions.mm b/clang/test/CodeGenObjCXX/arc-exceptions.mm new file mode 100644 index 0000000..b1fa8ca --- /dev/null +++ b/clang/test/CodeGenObjCXX/arc-exceptions.mm @@ -0,0 +1,85 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime-has-weak -o - %s | FileCheck %s + +@class Ety; + +// These first four tests are all PR11732 / rdar://problem/10667070. + +void test0_helper(void); +void test0(void) { + @try { + test0_helper(); + } @catch (Ety *e) { + } +} +// CHECK: define void @_Z5test0v() +// CHECK: [[E:%.*]] = alloca [[ETY:%.*]]*, align 8 +// CHECK-NEXT: invoke void @_Z12test0_helperv() +// CHECK: [[T0:%.*]] = call i8* @objc_begin_catch( +// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[ETY]]* +// CHECK-NEXT: [[T2:%.*]] = bitcast [[ETY]]* [[T1]] to i8* +// CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]]) nounwind +// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to [[ETY]]* +// CHECK-NEXT: store [[ETY]]* [[T4]], [[ETY]]** [[E]] +// CHECK-NEXT: [[T0:%.*]] = load [[ETY]]** [[E]] +// CHECK-NEXT: [[T1:%.*]] = bitcast [[ETY]]* [[T0]] to i8* +// CHECK-NEXT: call void @objc_release(i8* [[T1]]) nounwind +// CHECK-NEXT: call void @objc_end_catch() nounwind + +void test1_helper(void); +void test1(void) { + @try { + test1_helper(); + } @catch (__weak Ety *e) { + } +} +// CHECK: define void @_Z5test1v() +// CHECK: [[E:%.*]] = alloca [[ETY:%.*]]*, align 8 +// CHECK-NEXT: invoke void @_Z12test1_helperv() +// CHECK: [[T0:%.*]] = call i8* @objc_begin_catch( +// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[ETY]]* +// CHECK-NEXT: [[T2:%.*]] = bitcast [[ETY]]** [[E]] to i8** +// CHECK-NEXT: [[T3:%.*]] = bitcast [[ETY]]* [[T1]] to i8* +// CHECK-NEXT: call i8* @objc_initWeak(i8** [[T2]], i8* [[T3]]) nounwind +// CHECK-NEXT: [[T0:%.*]] = bitcast [[ETY]]** [[E]] to i8** +// CHECK-NEXT: call void @objc_destroyWeak(i8** [[T0]]) nounwind +// CHECK-NEXT: call void @objc_end_catch() nounwind + +void test2_helper(void); +void test2(void) { + try { + test2_helper(); + } catch (Ety *e) { + } +} +// CHECK: define void @_Z5test2v() +// CHECK: [[E:%.*]] = alloca [[ETY:%.*]]*, align 8 +// CHECK-NEXT: invoke void @_Z12test2_helperv() +// CHECK: [[T0:%.*]] = call i8* @__cxa_begin_catch( +// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[ETY]]* +// CHECK-NEXT: [[T2:%.*]] = bitcast [[ETY]]* [[T1]] to i8* +// CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]]) nounwind +// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to [[ETY]]* +// CHECK-NEXT: store [[ETY]]* [[T4]], [[ETY]]** [[E]] +// CHECK-NEXT: [[T0:%.*]] = load [[ETY]]** [[E]] +// CHECK-NEXT: [[T1:%.*]] = bitcast [[ETY]]* [[T0]] to i8* +// CHECK-NEXT: call void @objc_release(i8* [[T1]]) nounwind +// CHECK-NEXT: call void @__cxa_end_catch() nounwind + +void test3_helper(void); +void test3(void) { + try { + test3_helper(); + } catch (Ety * __weak e) { + } +} +// CHECK: define void @_Z5test3v() +// CHECK: [[E:%.*]] = alloca [[ETY:%.*]]*, align 8 +// CHECK-NEXT: invoke void @_Z12test3_helperv() +// CHECK: [[T0:%.*]] = call i8* @__cxa_begin_catch( +// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[ETY]]* +// CHECK-NEXT: [[T2:%.*]] = bitcast [[ETY]]** [[E]] to i8** +// CHECK-NEXT: [[T3:%.*]] = bitcast [[ETY]]* [[T1]] to i8* +// CHECK-NEXT: call i8* @objc_initWeak(i8** [[T2]], i8* [[T3]]) nounwind +// CHECK-NEXT: [[T0:%.*]] = bitcast [[ETY]]** [[E]] to i8** +// CHECK-NEXT: call void @objc_destroyWeak(i8** [[T0]]) nounwind +// CHECK-NEXT: call void @__cxa_end_catch() nounwind diff --git a/clang/test/CodeGenObjCXX/arc-globals.mm b/clang/test/CodeGenObjCXX/arc-globals.mm new file mode 100644 index 0000000..958d1d8 --- /dev/null +++ b/clang/test/CodeGenObjCXX/arc-globals.mm @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -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/clang/test/CodeGenObjCXX/arc-mangle.mm b/clang/test/CodeGenObjCXX/arc-mangle.mm new file mode 100644 index 0000000..c2b5817 --- /dev/null +++ b/clang/test/CodeGenObjCXX/arc-mangle.mm @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -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/clang/test/CodeGenObjCXX/arc-move.mm b/clang/test/CodeGenObjCXX/arc-move.mm new file mode 100644 index 0000000..cf3051d --- /dev/null +++ b/clang/test/CodeGenObjCXX/arc-move.mm @@ -0,0 +1,75 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -O2 -std=c++11 -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/clang/test/CodeGenObjCXX/arc-new-delete.mm b/clang/test/CodeGenObjCXX/arc-new-delete.mm new file mode 100644 index 0000000..a778bca --- /dev/null +++ b/clang/test/CodeGenObjCXX/arc-new-delete.mm @@ -0,0 +1,95 @@ +// RUN: %clang_cc1 -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/clang/test/CodeGenObjCXX/arc-pseudo-destructors.mm b/clang/test/CodeGenObjCXX/arc-pseudo-destructors.mm new file mode 100644 index 0000000..2f8d9e1 --- /dev/null +++ b/clang/test/CodeGenObjCXX/arc-pseudo-destructors.mm @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -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/clang/test/CodeGenObjCXX/arc-references.mm b/clang/test/CodeGenObjCXX/arc-references.mm new file mode 100644 index 0000000..954c02a --- /dev/null +++ b/clang/test/CodeGenObjCXX/arc-references.mm @@ -0,0 +1,84 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -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: [[REFTMP:%.*]] = alloca {{%.*}}*, align 8 + // CHECK: [[OBJ_ID:%.*]] = call i8* @objc_retain( + // CHECK-NEXT: [[OBJ_A:%.*]] = 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/clang/test/CodeGenObjCXX/arc-returns-inner-reference-ptr.mm b/clang/test/CodeGenObjCXX/arc-returns-inner-reference-ptr.mm new file mode 100644 index 0000000..c4ab34e --- /dev/null +++ b/clang/test/CodeGenObjCXX/arc-returns-inner-reference-ptr.mm @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -o - %s | FileCheck %s +// rdar://10139365 + +@interface Test58 +- (char* &) interior __attribute__((objc_returns_inner_pointer)); +- (int&)reference_to_interior_int __attribute__((objc_returns_inner_pointer)); +@end + +void foo() { + Test58 *ptr; + char *c = [(ptr) interior]; + + int i = [(ptr) reference_to_interior_int]; +} + +// CHECK: [[T0:%.*]] = load {{%.*}} {{%.*}}, align 8 +// CHECK: [[T1:%.*]] = bitcast {{%.*}} [[T0]] to i8* +// call i8* @objc_retainAutorelease(i8* [[T1]]) nounwind +// CHECK: [[T2:%.*]] = load {{%.*}} {{%.*}}, align 8 +// CHECK: [[T3:%.*]] = bitcast {{%.*}} [[T2]] to i8* +// call i8* @objc_retainAutorelease(i8* [[T3]]) nounwind + diff --git a/clang/test/CodeGenObjCXX/arc-special-member-functions.mm b/clang/test/CodeGenObjCXX/arc-special-member-functions.mm new file mode 100644 index 0000000..421a9fe --- /dev/null +++ b/clang/test/CodeGenObjCXX/arc-special-member-functions.mm @@ -0,0 +1,165 @@ +// RUN: %clang_cc1 -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:%.*]] = getelementptr inbounds [[T:%.*]]* {{%.*}}, i32 0, i32 0 +// CHECK-NEXT: [[T1:%.*]] = load i32 (i32)** [[T0]], align 8 +// CHECK-NEXT: [[T2:%.*]] = bitcast i32 (i32)* [[T1]] to i8* +// CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retainBlock(i8* [[T2]]) +// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to i32 (i32)* +// CHECK-NEXT: [[T5:%.*]] = getelementptr inbounds [[T]]* {{%.*}}, i32 0, i32 0 +// CHECK-NEXT: [[T6:%.*]] = load i32 (i32)** [[T5]], align 8 +// CHECK-NEXT: store i32 (i32)* [[T4]], i32 (i32)** [[T5]] +// CHECK-NEXT: [[T7:%.*]] = bitcast i32 (i32)* [[T6]] to i8* +// CHECK-NEXT: call void @objc_release(i8* [[T7]]) +// 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/clang/test/CodeGenObjCXX/arc.mm b/clang/test/CodeGenObjCXX/arc.mm new file mode 100644 index 0000000..45211a2 --- /dev/null +++ b/clang/test/CodeGenObjCXX/arc.mm @@ -0,0 +1,254 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-runtime-has-weak -fblocks -fobjc-arc -O2 -disable-llvm-optzns -o - %s | FileCheck %s + +struct NSFastEnumerationState; +@interface NSArray +- (unsigned long) countByEnumeratingWithState: (struct NSFastEnumerationState*) state + objects: (id*) buffer + count: (unsigned long) bufferSize; +@end; +NSArray *nsarray() { return 0; } +// CHECK: define [[NSARRAY:%.*]]* @_Z7nsarrayv() + +void use(id); + +// 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; +} + +// Template instantiation side of rdar://problem/9817306 +@interface Test37 ++ alloc; +- init; +- (NSArray *) array; +@end +template <class T> void test37(T *a) { + for (id x in a.array) { + use(x); + } +} +extern template void test37<Test37>(Test37 *a); +template void test37<Test37>(Test37 *a); +// CHECK: define weak_odr void @_Z6test37I6Test37EvPT_( +// CHECK: [[T0:%.*]] = call [[NSARRAY]]* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to [[NSARRAY]]* (i8*, i8*)*)( +// CHECK-NEXT: [[T1:%.*]] = bitcast [[NSARRAY]]* [[T0]] to i8* +// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]]) +// CHECK-NEXT: [[COLL:%.*]] = bitcast i8* [[T2]] to [[NSARRAY]]* + +// Make sure it's not immediately released before starting the iteration. +// CHECK-NEXT: load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ +// CHECK-NEXT: [[T0:%.*]] = bitcast [[NSARRAY]]* [[COLL]] to i8* +// CHECK-NEXT: @objc_msgSend + +// This bitcast is for the mutation check. +// CHECK: [[T0:%.*]] = bitcast [[NSARRAY]]* [[COLL]] to i8* +// CHECK-NEXT: @objc_enumerationMutation + +// This bitcast is for the 'next' message send. +// CHECK: [[T0:%.*]] = bitcast [[NSARRAY]]* [[COLL]] to i8* +// CHECK-NEXT: @objc_msgSend + +// This bitcast is for the final release. +// CHECK: [[T0:%.*]] = bitcast [[NSARRAY]]* [[COLL]] to i8* +// CHECK-NEXT: call void @objc_release(i8* [[T0]]) + +template<typename T> +void send_release() { + [Test37 array]; +} + +// CHECK: define weak_odr void @_Z12send_releaseIiEvv( +// CHECK: call %0* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend +// CHECK-NEXT: bitcast +// CHECK-NEXT: call i8* @objc_retainAutoreleasedReturnValue +// CHECK-NEXT: bitcast +// CHECK-NEXT: bitcast +// CHECK-NEXT: call void @objc_release +// CHECK-NEXT: ret void +template void send_release<int>(); + +template<typename T> +Test37 *instantiate_init() { + Test37 *result = [[Test37 alloc] init]; + return result; +} + +// CHECK: define weak_odr %2* @_Z16instantiate_initIiEP6Test37v +// CHECK: call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend +// CHECK: call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend +// CHECK: call i8* @objc_retain +// CHECK: call void @objc_release +// CHECK: call i8* @objc_autoreleaseReturnValue +template Test37* instantiate_init<int>(); + +// Just make sure that the AST invariants hold properly here, +// i.e. that we don't crash. +// The block should get bound in the full-expression outside +// the statement-expression. +template <class T> class Test38 { + void test(T x) { + ^{ (void) x; }, ({ x; }); + } +}; +// CHECK: define weak_odr void @_ZN6Test38IiE4testEi( +template class Test38<int>; diff --git a/clang/test/CodeGenObjCXX/block-in-template-inst.mm b/clang/test/CodeGenObjCXX/block-in-template-inst.mm new file mode 100644 index 0000000..93a0e49 --- /dev/null +++ b/clang/test/CodeGenObjCXX/block-in-template-inst.mm @@ -0,0 +1,71 @@ +// RUN: %clang_cc1 -emit-llvm-only -std=c++11 -fblocks -o - -triple x86_64-apple-darwin10 -fobjc-fragile-abi %s +// rdar://9362021 + +@class DYFuture; +@interface NSCache +- (void)setObject:(id)obj forKey:(id)key; +@end + +template <typename T> +class ResourceManager +{ +public: + ~ResourceManager(); + DYFuture* XXX(); + NSCache* _spDeviceCache; +}; + +template <typename T> +DYFuture* ResourceManager<T>::XXX() +{ + ^ { + [_spDeviceCache setObject:0 forKey:0]; + }(); + + return 0; +} + +struct AnalyzerBaseObjectTypes { }; + +void FUNC() +{ + ResourceManager<AnalyzerBaseObjectTypes> *rm; + ^(void) { rm->XXX(); }(); +} + +namespace PR9982 { + template<typename T> struct Curry; + + template<typename R, typename Arg0, typename Arg1, typename Arg2> + struct Curry<R (^)(Arg0, Arg1, Arg2)> + { + typedef R (^FType)(Arg0, Arg1, Arg2); + + Curry(FType _f) : f(_f) {} + ~Curry() {;} + + R (^(^operator()(Arg0 a))(Arg1))(Arg2) + { + auto block = ^(Arg1 b) { + auto inner_block = ^(Arg2 c) { + return f(a, b, c); + }; + return inner_block; + }; + return block; + } + + private: + FType f; + }; + + auto add = ^(int a, int b, int c) + { + return a + b + c; + }; + + void curry() { + Curry<__decltype(add)> c = Curry<__decltype(add)>(add); + auto t = c(1)(10)(100); + } +} diff --git a/clang/test/CodeGenObjCXX/block-var-layout.mm b/clang/test/CodeGenObjCXX/block-var-layout.mm new file mode 100644 index 0000000..a8f8be0 --- /dev/null +++ b/clang/test/CodeGenObjCXX/block-var-layout.mm @@ -0,0 +1,157 @@ +// RUN: %clang_cc1 -x objective-c++ -fblocks -fobjc-gc -triple x86_64-apple-darwin -fobjc-fragile-abi -emit-llvm %s -o %t-64.ll +// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.ll %s + +// See commentary in test/CodeGenObjC/block-var-layout.m, from which +// this is largely cloned. + +struct S { + int i1; + id o1; + struct V { + int i2; + id o2; + } v1; + int i3; + id o3; +}; + +__weak id wid; +void x(id y) {} +void y(int a) {} + +extern id opaque_id(); + +void f() { + __block int byref_int = 0; + char ch = 'a'; + char ch1 = 'b'; + char ch2 = 'c'; + short sh = 2; + const id bar = (id) opaque_id(); + id baz = 0; + __strong void *strong_void_sta; + __block id byref_bab = (id)0; + __block void *bl_var1; + int i; double dob; + +// Test 1 +// byref int, short, char, char, char, id, id, strong void*, byref id +// 01 35 10 00 +// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [4 x i8] c"\015\10\00" + void (^b)() = ^{ + byref_int = sh + ch+ch1+ch2 ; + x(bar); + x(baz); + x((id)strong_void_sta); + x(byref_bab); + }; + b(); + +// Test 2 +// byref int, short, char, char, char, id, id, strong void*, byref void*, byref id +// 01 36 10 00 +// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [4 x i8] c"\016\10\00" + void (^c)() = ^{ + byref_int = sh + ch+ch1+ch2 ; + x(bar); + x(baz); + x((id)strong_void_sta); + x(wid); + bl_var1 = 0; + x(byref_bab); + }; + c(); + +// Test 3 +// byref int, short, char, char, char, id, id, byref void*, int, double, byref id +// 01 34 11 30 00 +// FIXME: we'd get a better format here if we sorted by scannability, not just alignment +// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [5 x i8] c"\014\11 \00" +void (^d)() = ^{ + byref_int = sh + ch+ch1+ch2 ; + x(bar); + x(baz); + x(wid); + bl_var1 = 0; + y(i + dob); + x(byref_bab); + }; + d(); + +// Test4 +// struct S (int, id, int, id, int, id) +// 01 41 11 11 +// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [5 x i8] c"\01A\11\11\00" + struct S s2; + void (^e)() = ^{ + x(s2.o1); + }; + e(); +} + +// Test 5 (unions/structs and their nesting): +void Test5() { + struct S5 { + int i1; + id o1; + struct V { + int i2; + id o2; + } v1; + int i3; + union UI { + void * i1; + id o1; + int i3; + id o3; + }ui; + }; + + union U { + void * i1; + id o1; + int i3; + id o3; + }ui; + + struct S5 s2; + union U u2; + +// struct s2 (int, id, int, id, int, id?), union u2 (id?) +// 01 41 11 12 70 00 +// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [6 x i8] c"\01A\11\12p\00" + void (^c)() = ^{ + x(s2.ui.o1); + x(u2.o1); + }; + c(); + +} + +// rdar: //8417746 +void CFRelease(id); +void notifyBlock(id dependentBlock) { + id singleObservationToken; + id token; + void (^b)(); + +// id, id, void(^)() +// 01 33 00 +// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [3 x i8] c"\013\00" + void (^wrapperBlock)() = ^() { + CFRelease(singleObservationToken); + CFRelease(singleObservationToken); + CFRelease(token); + CFRelease(singleObservationToken); + b(); + }; + wrapperBlock(); +} + +void test_empty_block() { +// 01 00 +// CHECK-LP64: @"\01L_OBJC_CLASS_NAME_{{.*}}" = internal global [2 x i8] c"\01\00" + void (^wrapperBlock)() = ^() { + }; + wrapperBlock(); +} diff --git a/clang/test/CodeGenObjCXX/blocks.mm b/clang/test/CodeGenObjCXX/blocks.mm new file mode 100644 index 0000000..126931d --- /dev/null +++ b/clang/test/CodeGenObjCXX/blocks.mm @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 -x objective-c++ -fblocks -triple x86_64-apple-darwin -fobjc-fragile-abi %s -verify -emit-llvm -o %t +// rdar://8979379 + +@interface A +@end + +@interface B : A +@end + +void f(int (^bl)(B* b)); + +// Test1 +void g() { + f(^(A* a) { return 0; }); +} + +// Test2 +void g1() { + int (^bl)(B* b) = ^(A* a) { return 0; }; +} + +// Test3 +@protocol NSObject; + +void bar(id(^)(void)); + +void foo(id <NSObject>(^objectCreationBlock)(void)) { + return bar(objectCreationBlock); +} + +// Test4 +struct S { + S *(^a)() = ^{ // expected-warning {{C++11}} + return this; + }; +}; +S s; + +// Test5 +struct X { + void f() { + ^ { + struct Nested { Nested *ptr = this; }; // expected-warning {{C++11}} + } (); + }; +}; diff --git a/clang/test/CodeGenObjCXX/catch-id-type.mm b/clang/test/CodeGenObjCXX/catch-id-type.mm new file mode 100644 index 0000000..a5fa3e7 --- /dev/null +++ b/clang/test/CodeGenObjCXX/catch-id-type.mm @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 -triple i386-apple-macosx10.6.6 -fobjc-fragile-abi -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: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) + // CHECK-NEXT: catch i8* bitcast ({ i8*, i8*, i32, i8* }* @_ZTIP4INTF to i8*) + // CHECK-NEXT: catch i8* bitcast ({ i8*, i8*, i32, i8* }* @_ZTIP11objc_object to i8*) + // CHECK-NEXT: catch i8* bitcast ({ i8*, i8*, i32, i8* }* @_ZTIP10objc_class to i8*) + 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/clang/test/CodeGenObjCXX/copy.mm b/clang/test/CodeGenObjCXX/copy.mm new file mode 100644 index 0000000..9382ee8 --- /dev/null +++ b/clang/test/CodeGenObjCXX/copy.mm @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-fragile-abi -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: bitcast + // CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64( + // CHECK-NEXT: ret + A *test(A a) { + return new A(a); + } +} + + +// rdar://9780211 +@protocol bork +@end + +namespace test1 { +template<typename T> struct RetainPtr { + RetainPtr() {} +}; + + +RetainPtr<id<bork> > x; +RetainPtr<id> y; + +} diff --git a/clang/test/CodeGenObjCXX/copyable-property-object.mm b/clang/test/CodeGenObjCXX/copyable-property-object.mm new file mode 100644 index 0000000..03c0c06 --- /dev/null +++ b/clang/test/CodeGenObjCXX/copyable-property-object.mm @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -fobjc-gc -triple x86_64-apple-darwin10 -fobjc-fragile-abi -emit-llvm -o - %s | FileCheck %s + +struct POD { + int array[3][4]; + id objc_obj; +}; + +struct D { + POD pod_array[2][3]; +}; + +@interface I +{ + D Property1; +} +@property D Property1; +- (D) val; +- (void) set : (D) d1; +@end + +@implementation I +@synthesize Property1; +- (D) val { return Property1; } +- (void) set : (D) d1 { Property1 = d1; } +@end +// CHECK: {{call.*@objc_memmove_collectable}} +// CHECK: {{call.*@objc_memmove_collectable}} + diff --git a/clang/test/CodeGenObjCXX/debug-info.mm b/clang/test/CodeGenObjCXX/debug-info.mm new file mode 100644 index 0000000..04cf66f --- /dev/null +++ b/clang/test/CodeGenObjCXX/debug-info.mm @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -g -emit-llvm %s -o /dev/null + +// This test passes if clang doesn't crash. + +template <class C> class scoped_ptr { +public: + C* operator->() const { return 0; } +}; + +@class NSWindow; +@class NSImage; +@interface NSWindow { + NSImage *_miniIcon; +} +-(id)windowController; +@end + +class AutomationResourceTracker { +public: + NSWindow* GetResource(int handle) { return 0; } +}; + +# 13 "automation/automation_window_tracker.h" +class AutomationWindowTracker : public AutomationResourceTracker { }; + +template<typename NST> class scoped_nsobject { }; + +@interface TabStripController{ + scoped_nsobject<NSImage> defaultFavicon_; +} +@end + +@interface BrowserWindowController { + TabStripController* tabStripController_; +} +@end + +void WindowGetViewBounds(scoped_ptr<AutomationWindowTracker> window_tracker_) { + NSWindow* window = window_tracker_->GetResource(42); + BrowserWindowController* controller = [window windowController]; +} diff --git a/clang/test/CodeGenObjCXX/encode.mm b/clang/test/CodeGenObjCXX/encode.mm new file mode 100644 index 0000000..8391c04 --- /dev/null +++ b/clang/test/CodeGenObjCXX/encode.mm @@ -0,0 +1,189 @@ +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s + +// CHECK: v17@0:8{vector<float, float, float>=}16 +// CHECK: {vector<float, float, float>=} +// CHECK: v24@0:816 + +template <typename T1, typename T2, typename T3> struct vector { + vector(); + vector(T1,T2,T3); +}; + +typedef vector< float, float, float > vector3f; + +@interface SceneNode +{ + vector3f position; +} + +@property (assign, nonatomic) vector3f position; + +@end + +@interface MyOpenGLView +{ +@public + vector3f position; +} +@property vector3f position; +@end + +@implementation MyOpenGLView + +@synthesize position; + +-(void)awakeFromNib { + SceneNode *sn; + vector3f VF3(1.0, 1.0, 1.0); + [sn setPosition:VF3]; +} +@end + + +class Int3 { int x, y, z; }; + +// Enforce @encoding for member pointers. +@interface MemPtr {} +- (void) foo: (int (Int3::*)) member; +@end +@implementation MemPtr +- (void) foo: (int (Int3::*)) member { +} +@end + +// rdar: // 8519948 +typedef float HGVec4f __attribute__ ((vector_size(16))); + +@interface RedBalloonHGXFormWrapper { + HGVec4f m_Transform[4]; +} +@end + +@implementation RedBalloonHGXFormWrapper +@end + +// rdar://9357400 +namespace rdar9357400 { + template<int Dim1 = -1, int Dim2 = -1> struct fixed { + template<int D> struct rebind { typedef fixed<D> other; }; + }; + + template<typename Element, int Size> + class fixed_1D + { + public: + typedef Element value_type; + typedef value_type array_impl[Size]; + protected: + array_impl m_data; + }; + + template<typename Element, typename Alloc> + class vector; + + template<typename Element, int Size> + class vector< Element, fixed<Size> > + : public fixed_1D<Element,Size> { }; + + typedef vector< float, fixed<4> > vector4f; + + // CHECK: @_ZN11rdar9357400L2ggE = internal constant [49 x i8] c"{vector<float, rdar9357400::fixed<4, -1> >=[4f]}\00" + 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); +} + +namespace test { + class Foo { + public: + virtual void f() {}; + }; + + class Bar { + public: + virtual void g() {}; + }; + + class Zoo : virtual public Foo, virtual public Bar { + public: + int x; + int y; + }; + + // CHECK: @_ZN4testL3ecdE = internal constant [15 x i8] c"{Zoo=^^?ii^^?}\00" + const char ecd[] = @encode(Zoo); +} + +struct Base1 { + char x; +}; + +struct DBase : public Base1 { + double x; + virtual ~DBase(); +}; + +struct Sub_with_virt : virtual DBase { + long x; +}; + +struct Sub2 : public Sub_with_virt, public Base1, virtual DBase { + float x; +}; + +// CHECK: @_ZL2g1 = internal constant [10 x i8] c"{Base1=c}\00" +const char g1[] = @encode(Base1); + +// CHECK: @_ZL2g2 = internal constant [14 x i8] c"{DBase=^^?cd}\00" +const char g2[] = @encode(DBase); + +// CHECK: @_ZL2g3 = internal constant [26 x i8] c"{Sub_with_virt=^^?q^^?cd}\00" +const char g3[] = @encode(Sub_with_virt); + +// CHECK: @_ZL2g4 = internal constant [19 x i8] c"{Sub2=^^?qcf^^?cd}\00" +const char g4[] = @encode(Sub2); + +// http://llvm.org/PR9927 +class allocator { +}; +class basic_string { +struct _Alloc_hider : allocator { +char* _M_p; +}; +_Alloc_hider _M_dataplus; +}; + +// CHECK: @_ZL2g5 = internal constant [32 x i8] c"{basic_string={_Alloc_hider=*}}\00" +const char g5[] = @encode(basic_string); + + +// PR10990 +class CefBase { + virtual ~CefBase() {} +}; +class CefBrowser : public virtual CefBase {}; +class CefBrowserImpl : public CefBrowser {}; +// CHECK: @_ZL2g6 = internal constant [21 x i8] c"{CefBrowserImpl=^^?}\00" +const char g6[] = @encode(CefBrowserImpl); + +// PR10990_2 +class CefBase2 { + virtual ~CefBase2() {} + int i; +}; +class CefBrowser2 : public virtual CefBase2 {}; +class CefBrowserImpl2 : public CefBrowser2 {}; +// CHECK: @_ZL2g7 = internal constant [26 x i8] c"{CefBrowserImpl2=^^?^^?i}\00" +const char g7[] = @encode(CefBrowserImpl2); diff --git a/clang/test/CodeGenObjCXX/exceptions.mm b/clang/test/CodeGenObjCXX/exceptions.mm new file mode 100644 index 0000000..ce6d20a --- /dev/null +++ b/clang/test/CodeGenObjCXX/exceptions.mm @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fcxx-exceptions -fexceptions -o - %s | FileCheck %s + +@interface OCType @end +void opaque(); + +namespace test0 { + + // CHECK: define void @_ZN5test03fooEv + void foo() { + try { + // CHECK: invoke void @_Z6opaquev + opaque(); + } catch (OCType *T) { + // CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*) + // CHECK-NEXT: catch %struct._objc_typeinfo* @"OBJC_EHTYPE_$_OCType" + } + } +} diff --git a/clang/test/CodeGenObjCXX/foreach-statement.mm b/clang/test/CodeGenObjCXX/foreach-statement.mm new file mode 100644 index 0000000..d0ad5b3 --- /dev/null +++ b/clang/test/CodeGenObjCXX/foreach-statement.mm @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s +// rdar: // 8027844 + +// CHECK: call void @llvm.memset + +int main() { + id foo; + for (id a in foo) { + } +} diff --git a/clang/test/CodeGenObjCXX/gc.mm b/clang/test/CodeGenObjCXX/gc.mm new file mode 100644 index 0000000..1e9fe00 --- /dev/null +++ b/clang/test/CodeGenObjCXX/gc.mm @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fobjc-gc -triple x86_64-apple-darwin10 -fobjc-fragile-abi -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/clang/test/CodeGenObjCXX/implicit-copy-assign-operator.mm b/clang/test/CodeGenObjCXX/implicit-copy-assign-operator.mm new file mode 100644 index 0000000..0a6e08e --- /dev/null +++ b/clang/test/CodeGenObjCXX/implicit-copy-assign-operator.mm @@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -fobjc-gc -emit-llvm -triple x86_64-apple-darwin10.0.0 -fobjc-fragile-abi -o - %s | FileCheck %s +struct A { + A &operator=(const A&); + A &operator=(A&); +}; + +struct B { + B &operator=(B&); +}; + +struct C { + virtual C& operator=(const C&); +}; + +struct POD { + id myobjc; + int array[3][4]; +}; + +struct CopyByValue { + CopyByValue(const CopyByValue&); + CopyByValue &operator=(CopyByValue); +}; + +struct D : A, B, virtual C { + int scalar; + int scalar_array[2][3]; + B class_member; + C class_member_array[2][3]; + POD pod_array[2][3]; + + union { + int x; + float f[3]; + }; + + CopyByValue by_value; +}; + +void test_D(D d1, D d2) { + d1 = d2; +} + +// CHECK: define linkonce_odr %struct.D* @_ZN1DaSERS_ +// CHECK: {{call.*_ZN1AaSERS_}} +// CHECK: {{call.*_ZN1BaSERS_}} +// CHECK: {{call.*_ZN1CaSERKS_}} +// CHECK: {{call void @llvm.memcpy.p0i8.p0i8.i64.*i64 24}} +// CHECK: {{call.*_ZN1BaSERS_}} +// CHECK: br +// CHECK: {{call.*_ZN1CaSERKS_}} +// CHECK: {{call.*@objc_memmove_collectable}} +// CHECK: {{call void @llvm.memcpy.p0i8.p0i8.i64.*i64 12}} +// CHECK: call void @_ZN11CopyByValueC1ERKS_ +// CHECK: {{call.*_ZN11CopyByValueaSES_}} +// CHECK: ret + diff --git a/clang/test/CodeGenObjCXX/implicit-copy-constructor.mm b/clang/test/CodeGenObjCXX/implicit-copy-constructor.mm new file mode 100644 index 0000000..63dd4f0 --- /dev/null +++ b/clang/test/CodeGenObjCXX/implicit-copy-constructor.mm @@ -0,0 +1,73 @@ +// RUN: %clang_cc1 -fobjc-gc -triple x86_64-apple-darwin10 -fobjc-fragile-abi -emit-llvm -o - %s | FileCheck %s + +struct A { + A(); + A(const A&); + A(A&); + ~A(); +}; + +struct B { + B(); + B(B&); +}; + +struct C { + C() {} + C(C& other, A a = A()); + int i, j; +}; + +struct POD { + id myobjc; + int array[3][4]; +}; + +struct D : A, B, virtual C { + D(); + int scalar; + int scalar_array[2][3]; + B class_member; + C class_member_array[2][3]; + POD pod_array[2][3]; + + union { + int x; + float f[3]; + }; +}; + +void f(D d) { + D d2(d); +} + +// CHECK: define linkonce_odr void @_ZN1DC1ERS_(%struct.D* %this, %struct.D*) unnamed_addr +// CHECK: call void @_ZN1AC1Ev +// CHECK: call void @_ZN1CC2ERS_1A +// CHECK: call void @_ZN1AD1Ev +// CHECK: call void @_ZN1AC2ERS_ +// CHECK: call void @_ZN1BC2ERS_ +// CHECK: {{call void @llvm.memcpy.p0i8.p0i8.i64.*i64 24}} +// CHECK: call void @_ZN1BC1ERS_ +// CHECK: br +// CHECK: {{icmp ult.*, 2}} +// CHECK: {{icmp ult.*, 3}} +// CHECK: call void @_ZN1AC1Ev +// CHECK: call void @_ZN1CC1ERS_1A +// CHECK: call void @_ZN1AD1Ev +// CHECK: {{call.*@objc_memmove_collectable}} +// CHECK: {{call void @llvm.memcpy.p0i8.p0i8.i64.*i64 12}} +// CHECK: ret void + + +template<class T> struct X0 { void f0(T * ) { } }; +template <class > struct X1 { X1( X1& , int = 0 ) { } }; +struct X2 { X1<int> result; }; +void test_X2() +{ + typedef X2 impl; + typedef X0<impl> pimpl; + impl* i; + pimpl pdata; + pdata.f0( new impl(*i)); +} diff --git a/clang/test/CodeGenObjCXX/ivar-objects.mm b/clang/test/CodeGenObjCXX/ivar-objects.mm new file mode 100644 index 0000000..d05763b --- /dev/null +++ b/clang/test/CodeGenObjCXX/ivar-objects.mm @@ -0,0 +1,104 @@ +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s +// CHECK: -[A .cxx_construct] +// CHECK: -[A .cxx_destruct] +// CHECK: -[B .cxx_construct] +// CHECK-NOT: -[B .cxx_destruct] +// CHECK-NOT: -[C .cxx_construct] +// CHECK: -[C .cxx_destruct] + +@interface NSObject +- alloc; +- init; +- (void) release; +@end + +extern "C" int printf(const char *, ...); + +int count = 17; +struct X { + X() : value(count++) { printf( "X::X()\n"); } + ~X() { printf( "X::~X()\n"); } + int value; +}; + +struct Y { + Y() : value(count++) { printf( "Y::Y()\n"); } + ~Y() { printf( "Y::~Y()\n"); } + int value; +}; + +@interface Super : NSObject { + Y yvar; + Y yvar1; + Y ya[3]; +} +- (void)finalize; +@end + +@interface A : Super { + X xvar; + X xvar1; + X xvar2; + X xa[2][2]; +} + +- (void)print; +- (void)finalize; +@end + +@implementation Super +- (void)print { + printf( "yvar.value = %d\n", yvar.value); + printf( "yvar1.value = %d\n", yvar1.value); + printf( "ya[0..2] = %d %d %d\n", ya[0].value, ya[1].value, ya[2].value); +} +- (void)finalize {} +@end + +@implementation A +- (void)print { + printf( "xvar.value = %d\n", xvar.value); + printf( "xvar1.value = %d\n", xvar1.value); + printf( "xvar2.value = %d\n", xvar2.value); + printf( "xa[0..1][0..1] = %d %d %d %d\n", + xa[0][0].value, xa[0][1].value, xa[1][0].value, xa[1][1].value); + [super print]; +} +- (void)finalize { [super finalize]; } +@end + +int main() { + A *a = [[A alloc] init]; + [a print]; + [a release]; +} + +// rdar: // 7468090 +class S { +public: + S& operator = (const S&); +}; + +@interface I { + S position; +} +@property(assign, nonatomic) S position; +@end + +@implementation I + @synthesize position; +@end + +// This class should have a .cxx_construct but no .cxx_destruct. +namespace test3 { struct S { S(); }; } +@implementation B { + test3::S s; +} +@end + +// This class should have a .cxx_destruct but no .cxx_construct. +namespace test4 { struct S { ~S(); }; } +@implementation C { + test4::S s; +} +@end diff --git a/clang/test/CodeGenObjCXX/lambda-expressions.mm b/clang/test/CodeGenObjCXX/lambda-expressions.mm new file mode 100644 index 0000000..858cb74 --- /dev/null +++ b/clang/test/CodeGenObjCXX/lambda-expressions.mm @@ -0,0 +1,39 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -emit-llvm -o - %s -fexceptions -std=c++11 -fblocks -fobjc-arc | FileCheck -check-prefix=ARC %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -emit-llvm -o - %s -fexceptions -std=c++11 -fblocks | FileCheck -check-prefix=MRC %s + +typedef int (^fp)(); +fp f() { auto x = []{ return 3; }; return x; } + +// MRC: @"\01L_OBJC_METH_VAR_NAME{{.*}}" = internal global [5 x i8] c"copy\00" +// MRC: @"\01L_OBJC_METH_VAR_NAME{{.*}}" = internal global [12 x i8] c"autorelease\00" +// MRC: define i32 ()* @_Z1fv( +// MRC: define internal i32 ()* @"_ZZ1fvENK3$_0cvU13block_pointerFivEEv" +// MRC: store i8* bitcast (i8** @_NSConcreteStackBlock to i8*) +// MRC: store i8* bitcast (i32 (i8*)* @"___ZZ1fvENK3$_0cvU13block_pointerFivEEv_block_invoke_0" to i8*) +// MRC: call i32 ()* (i8*, i8*)* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i32 ()* (i8*, i8*)*) +// MRC: call i32 ()* (i8*, i8*)* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i32 ()* (i8*, i8*)*) +// MRC: ret i32 ()* + +// ARC: define i32 ()* @_Z1fv( +// ARC: define internal i32 ()* @"_ZZ1fvENK3$_0cvU13block_pointerFivEEv" +// ARC: store i8* bitcast (i8** @_NSConcreteStackBlock to i8*) +// ARC: store i8* bitcast (i32 (i8*)* @"___ZZ1fvENK3$_0cvU13block_pointerFivEEv_block_invoke_0" to i8*) +// ARC: call i8* @objc_retainBlock +// ARC: call i8* @objc_autoreleaseReturnValue + +typedef int (^fp)(); +fp global; +void f2() { global = []{ return 3; }; } + +// MRC: define void @_Z2f2v() nounwind { +// MRC: store i8* bitcast (i32 (i8*)* @__f2_block_invoke_0 to i8*), +// MRC-NOT: call +// MRC: ret void +// ("global" contains a dangling pointer after this function runs.) + +// ARC: define void @_Z2f2v() nounwind { +// ARC: store i8* bitcast (i32 (i8*)* @__f2_block_invoke_0 to i8*), +// ARC: call i8* @objc_retainBlock +// ARC: call void @objc_release +// ARC: define internal i32 @__f2_block_invoke_0 +// ARC: call i32 @"_ZZ2f2vENK3$_1clEv diff --git a/clang/test/CodeGenObjCXX/literals.mm b/clang/test/CodeGenObjCXX/literals.mm new file mode 100644 index 0000000..b8946fa --- /dev/null +++ b/clang/test/CodeGenObjCXX/literals.mm @@ -0,0 +1,111 @@ +// RUN: %clang_cc1 -I %S/Inputs -triple x86_64-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime-has-weak -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-arc-exceptions -O2 -disable-llvm-optzns -o - %s | FileCheck %s + +#include "literal-support.h" + +struct X { + X(); + ~X(); + operator id() const; +}; + +struct Y { + Y(); + ~Y(); + operator id() const; +}; + +// CHECK: define void @_Z10test_arrayv +void test_array() { + // CHECK: [[OBJECTS:%[a-zA-Z0-9.]+]] = alloca [2 x i8*] + + // Initializing first element + // CHECK: [[ELEMENT0:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*]* [[OBJECTS]], i32 0, i32 0 + // CHECK-NEXT: call void @_ZN1XC1Ev + // CHECK-NEXT: [[OBJECT0:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1XcvP11objc_objectEv + // CHECK: [[RET0:%[a-zA-Z0-9.]+]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[OBJECT0]]) + // CHECK: store i8* [[RET0]], i8** [[ELEMENT0]] + + // Initializing the second element + // CHECK: [[ELEMENT1:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*]* [[OBJECTS]], i32 0, i32 1 + // CHECK-NEXT: invoke void @_ZN1YC1Ev + // CHECK: [[OBJECT1:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1YcvP11objc_objectEv + // CHECK: [[RET1:%[a-zA-Z0-9.]+]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[OBJECT1]]) + // CHECK: store i8* [[RET1]], i8** [[ELEMENT1]] + + // Build the array + // CHECK: {{invoke.*@objc_msgSend}} + // CHECK: call i8* @objc_retainAutoreleasedReturnValue + id arr = @[ X(), Y() ]; + + // Destroy temporaries + // CHECK-NOT: ret void + // CHECK: call void @objc_release + // CHECK-NOT: ret void + // CHECK: invoke void @_ZN1YD1Ev + // CHECK-NOT: ret void + // CHECK: call void @objc_release + // CHECK-NEXT: call void @_ZN1XD1Ev + // CHECK-NOT: ret void + // CHECK: call void @objc_release + // CHECK-NEXT: ret void + + // Check cleanups + // CHECK: call void @objc_release + // CHECK-NOT: call void @objc_release + // CHECK: invoke void @_ZN1YD1Ev + // CHECK: call void @objc_release + // CHECK-NOT: call void @objc_release + // CHECK: invoke void @_ZN1XD1Ev + // CHECK-NOT: call void @objc_release + // CHECK: unreachable +} + +// CHECK: define weak_odr void @_Z24test_array_instantiationIiEvv +template<typename T> +void test_array_instantiation() { + // CHECK: [[OBJECTS:%[a-zA-Z0-9.]+]] = alloca [2 x i8*] + + // Initializing first element + // CHECK: [[ELEMENT0:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*]* [[OBJECTS]], i32 0, i32 0 + // CHECK-NEXT: call void @_ZN1XC1Ev + // CHECK-NEXT: [[OBJECT0:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1XcvP11objc_objectEv + // CHECK: [[RET0:%[a-zA-Z0-9.]+]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[OBJECT0]]) + // CHECK: store i8* [[RET0]], i8** [[ELEMENT0]] + + // Initializing the second element + // CHECK: [[ELEMENT1:%[a-zA-Z0-9.]+]] = getelementptr inbounds [2 x i8*]* [[OBJECTS]], i32 0, i32 1 + // CHECK-NEXT: invoke void @_ZN1YC1Ev + // CHECK: [[OBJECT1:%[a-zA-Z0-9.]+]] = invoke i8* @_ZNK1YcvP11objc_objectEv + // CHECK: [[RET1:%[a-zA-Z0-9.]+]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[OBJECT1]]) + // CHECK: store i8* [[RET1]], i8** [[ELEMENT1]] + + // Build the array + // CHECK: {{invoke.*@objc_msgSend}} + // CHECK: call i8* @objc_retainAutoreleasedReturnValue + id arr = @[ X(), Y() ]; + + // Destroy temporaries + // CHECK-NOT: ret void + // CHECK: call void @objc_release + // CHECK-NOT: ret void + // CHECK: invoke void @_ZN1YD1Ev + // CHECK-NOT: ret void + // CHECK: call void @objc_release + // CHECK-NEXT: call void @_ZN1XD1Ev + // CHECK-NOT: ret void + // CHECK: call void @objc_release + // CHECK-NEXT: ret void + + // Check cleanups + // CHECK: call void @objc_release + // CHECK-NOT: call void @objc_release + // CHECK: invoke void @_ZN1YD1Ev + // CHECK: call void @objc_release + // CHECK-NOT: call void @objc_release + // CHECK: invoke void @_ZN1XD1Ev + // CHECK-NOT: call void @objc_release + // CHECK: unreachable +} + +template void test_array_instantiation<int>(); + diff --git a/clang/test/CodeGenObjCXX/lvalue-reference-getter.mm b/clang/test/CodeGenObjCXX/lvalue-reference-getter.mm new file mode 100644 index 0000000..83d3b93 --- /dev/null +++ b/clang/test/CodeGenObjCXX/lvalue-reference-getter.mm @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s +// rdar://10153365 + +static int gint; +struct SetSection { + int & at(int __n) { return gint; } + const int& at(int __n) const { return gint; } +}; + +static SetSection gSetSection; + +@interface SetShow +- (SetSection&)sections; +@end + +@implementation SetShow +- (SetSection&) sections { +// [self sections].at(100); + self.sections.at(100); + return gSetSection; +} +@end + +// CHECK: [[SELF:%.*]] = alloca [[T6:%.*]]*, align +// CHECK: [[T0:%.*]] = load {{.*}}* [[SELF]], align +// CHECK: [[T1:%.*]] = load {{.*}}* @"\01L_OBJC_SELECTOR_REFERENCES_" +// CHECK: [[C:%.*]] = call %struct.SetSection* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend +// CHECK: call i32* @_ZN10SetSection2atEi(%struct.SetSection* [[C]] diff --git a/clang/test/CodeGenObjCXX/mangle-blocks.mm b/clang/test/CodeGenObjCXX/mangle-blocks.mm new file mode 100644 index 0000000..fcbc608 --- /dev/null +++ b/clang/test/CodeGenObjCXX/mangle-blocks.mm @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -emit-llvm -fblocks -o - -triple x86_64-apple-darwin10 -fobjc-fragile-abi %s | FileCheck %s + +// CHECK: @_ZGVN3foo20__foo_block_invoke_05valueE = internal global i64 0 + +int f(); + +void foo() { + // CHECK: define internal i32 @__foo_block_invoke_0 + // CHECK: call i32 @__cxa_guard_acquire(i64* @_ZGVN3foo20__foo_block_invoke_05value + (void)^(int x) { + static int value = f(); + return x + value; + }; +} + +// CHECK: define internal i32 @__block_global_0 +int i = ^(int x) { return x;}(i); + +@interface A +- (void)method; +@end + +@implementation A +- (void)method { + // CHECK: define internal signext i8 @"__11-[A method]_block_invoke_0" + (void)^(int x) { + // CHECK: @"_ZN11-[A method]30__11-[A method]_block_invoke_04nameE" + static const char *name = "hello"; + return name[x]; + }; +} +@end + +void foo(int) { + (void)^(int x) { + static const char *name = "hello"; + return name[x]; + }; +} + +namespace N { + // CHECK: define internal signext i8 @__bar_block_invoke_0 + void bar() { + (void)^(int x) { + // CHECK: @_ZN1N3bar20__bar_block_invoke_04nameE + static const char *name = "hello"; + return name[x]; + }; + } +} diff --git a/clang/test/CodeGenObjCXX/mangle.mm b/clang/test/CodeGenObjCXX/mangle.mm new file mode 100644 index 0000000..2521c60 --- /dev/null +++ b/clang/test/CodeGenObjCXX/mangle.mm @@ -0,0 +1,56 @@ +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s + +// CHECK: @"_ZZ11+[A shared]E1a" = internal global +// CHECK: @"_ZZ11-[A(Foo) f]E1a" = internal global +// CHECK: v56@0:8i16i20i24i28i32i36i40i44^i48 + +@interface A +@end + +@implementation A + ++ (A *)shared { + static A* a; + + return a; +} + +@end + +@interface A(Foo) +@end + +@implementation A(Foo) +- (int)f { + // FIXME: Add a member function to s and make sure that it's mangled correctly. + struct s { + }; + + static s a; + + return 0; +} +@end + +// PR6468 +@interface Test +- (void) process: (int)r3 :(int)r4 :(int)r5 :(int)r6 :(int)r7 :(int)r8 :(int)r9 :(int)r10 :(int &)i; +@end + +@implementation Test +- (void) process: (int)r3 :(int)r4 :(int)r5 :(int)r6 :(int)r7 :(int)r8 :(int)r9 :(int)r10 :(int &)i { +} +@end + +// rdar://9566314 +@interface NX +- (void)Meth; +@end + +@implementation NX +- (void)Meth { + void uiIsVisible(); +// CHECK: call void @_Z11uiIsVisiblev + uiIsVisible(); +} +@end diff --git a/clang/test/CodeGenObjCXX/message-reference.mm b/clang/test/CodeGenObjCXX/message-reference.mm new file mode 100644 index 0000000..fa41fef --- /dev/null +++ b/clang/test/CodeGenObjCXX/message-reference.mm @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -fobjc-fragile-abi -emit-llvm -o - %s | FileCheck %s +// rdar://8604515 + +@interface I {} +-(unsigned int&)referenceCount; +@end + +@interface MyClass ++(int)writeBlip:(I*)srcBlip; +@end + +@implementation MyClass ++(int)writeBlip:(I*)srcBlip{ + return ([srcBlip referenceCount] == 0); +} +@end + +// CHECK: [[T:%.*]] = call i32* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend +// CHECK: [[U:%.*]] = load i32* [[T]] +// CHECK [[V:%.*]] = icmp eq i32 [[U]], 0 diff --git a/clang/test/CodeGenObjCXX/method-local-extern-mangle.mm b/clang/test/CodeGenObjCXX/method-local-extern-mangle.mm new file mode 100644 index 0000000..794075d --- /dev/null +++ b/clang/test/CodeGenObjCXX/method-local-extern-mangle.mm @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s + +// CHECK: @gGlobals = external global + +@interface I +- (int) Meth; +@end + +@implementation I +- (int) Meth { + extern int gGlobals; + return gGlobals; +} +@end diff --git a/clang/test/CodeGenObjCXX/nrvo.mm b/clang/test/CodeGenObjCXX/nrvo.mm new file mode 100644 index 0000000..ef5052e --- /dev/null +++ b/clang/test/CodeGenObjCXX/nrvo.mm @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -emit-llvm -o - -fblocks %s -O1 -triple x86_64-apple-darwin10.0.0 -fobjc-fragile-abi | FileCheck %s + +// PR10835 / <rdar://problem/10050178> +struct X { + X(); + X(const X&); + ~X(); +}; + +@interface NRVO +@end + +@implementation NRVO +// CHECK: define internal void @"\01-[NRVO getNRVO]" +- (X)getNRVO { + X x; + // CHECK: tail call void @_ZN1XC1Ev + // CHECK-NEXT: ret void + return x; +} +@end + +X blocksNRVO() { + return ^{ + // CHECK: define internal void @__blocksNRVO_block_invoke_0 + X x; + // CHECK: tail call void @_ZN1XC1Ev + // CHECK-NEXT: ret void + return x; + }() ; +} + diff --git a/clang/test/CodeGenObjCXX/objc-container-subscripting-1.mm b/clang/test/CodeGenObjCXX/objc-container-subscripting-1.mm new file mode 100644 index 0000000..c0dd0f8 --- /dev/null +++ b/clang/test/CodeGenObjCXX/objc-container-subscripting-1.mm @@ -0,0 +1,50 @@ +// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin -o - %s | FileCheck %s + +typedef unsigned int size_t; +@protocol P @end +@protocol NSCopying @end + +@interface NSMutableArray +- (id)objectAtIndexedSubscript:(size_t)index; +- (void)setObject:(id)object atIndexedSubscript:(size_t)index; +@end + +struct S { + operator unsigned int (); + operator id (); +}; + +@interface NSMutableDictionary +- (id)objectForKeyedSubscript:(id<NSCopying>)key; +- (void)setObject:(id)object forKeyedSubscript:(id<NSCopying>)key; +@end + +int main() { + NSMutableArray<P> * array; + S s; + id oldObject = array[(int)s]; + + NSMutableDictionary<P> *dict; + dict[(id)s] = oldObject; + oldObject = dict[(id)s]; + +} + +template <class T> void test2(NSMutableArray *a) { + a[10] = 0; +} +template void test2<int>(NSMutableArray*); +// CHECK: define weak_odr void @_Z5test2IiEvP14NSMutableArray +// CHECK: @objc_msgSend +// CHECK: ret void + + +template <class T> void test3(NSMutableArray *a) { + a[sizeof(T)] = 0; +} + +template void test3<int>(NSMutableArray*); +// CHECK: define weak_odr void @_Z5test3IiEvP14NSMutableArray +// CHECK: @objc_msgSend +// CHECK: ret void + diff --git a/clang/test/CodeGenObjCXX/objc-container-subscripting.mm b/clang/test/CodeGenObjCXX/objc-container-subscripting.mm new file mode 100644 index 0000000..dfe48e9 --- /dev/null +++ b/clang/test/CodeGenObjCXX/objc-container-subscripting.mm @@ -0,0 +1,57 @@ +// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin -o - %s | FileCheck %s + +typedef unsigned int size_t; +@protocol P @end + +@interface NSMutableArray +- (id)objectAtIndexedSubscript:(size_t)index; +- (void)setObject:(id)object atIndexedSubscript:(size_t)index; +@end + +struct S { + operator unsigned int (); + operator id (); +}; + +@interface NSMutableDictionary +- (id)objectForKeyedSubscript:(id)key; +- (void)setObject:(id)object forKeyedSubscript:(id)key; +@end + +int main() { + NSMutableArray<P> * array; + S s; + id oldObject = array[(int)s]; + + NSMutableDictionary<P> *dict; + dict[(id)s] = oldObject; + oldObject = dict[(id)s]; + +} + +template <class T> void test2(NSMutableArray *a) { + a[10] = 0; +} +template void test2<int>(NSMutableArray*); +// CHECK: define weak_odr void @_Z5test2IiEvP14NSMutableArray +// CHECK: @objc_msgSend +// CHECK: ret void + + +template <class T> void test3(NSMutableArray *a) { + a[sizeof(T)] = 0; +} + +template void test3<int>(NSMutableArray*); +// CHECK: define weak_odr void @_Z5test3IiEvP14NSMutableArray +// CHECK: @objc_msgSend +// CHECK: ret void + +// CHECK: define void @_Z11static_dataP14NSMutableArray +void static_data(NSMutableArray *array) { + // CHECK: call i32 @__cxa_guard_acquire + // CHECK: {{call i8*.*@objc_msgSend }} + // CHECK: call void @__cxa_guard_release + static id x = array[4]; + // CHECK: ret void +} diff --git a/clang/test/CodeGenObjCXX/property-derived-to-base-conv.mm b/clang/test/CodeGenObjCXX/property-derived-to-base-conv.mm new file mode 100644 index 0000000..ddca857 --- /dev/null +++ b/clang/test/CodeGenObjCXX/property-derived-to-base-conv.mm @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -fobjc-gc -triple x86_64-apple-darwin10 -fobjc-fragile-abi -emit-llvm -o - %s +// rdar: // 7501812 + +struct A { + int member; + void foo(); + A *operator->(); +}; +struct B : A { }; + +@interface BInt { +@private + B *b; +} +- (B)value; +- (void)setValue : (B) arg; +@property B value; +@end + +void g(BInt *bint) { + bint.value.foo(); + bint.value->member = 17; + int x = bint.value.member; +} + diff --git a/clang/test/CodeGenObjCXX/property-dot-copy.mm b/clang/test/CodeGenObjCXX/property-dot-copy.mm new file mode 100644 index 0000000..c0ff258 --- /dev/null +++ b/clang/test/CodeGenObjCXX/property-dot-copy.mm @@ -0,0 +1,68 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s +// rdar://8427922 + +struct Vector3D +{ + float x, y, z; + Vector3D(); + Vector3D(const Vector3D &inVector); + Vector3D(float initX, float initY, float initZ); + Vector3D &operator=(const Vector3D & rhs); +}; + +@interface Object3D +{ + Vector3D position; + Vector3D length; +} +@property (assign) Vector3D position; +- (Vector3D) length; +- (void) setLength: (Vector3D)arg; +@end + +int main () +{ + Object3D *myObject; + Vector3D V3D(1.0f, 1.0f, 1.0f); +// CHECK: call void @_ZN8Vector3DC1ERKS_ + myObject.position = V3D; + +// CHECK: call void @_ZN8Vector3DC1ERKS_ + myObject.length = V3D; + + return 0; +} + +// rdar: // 8437253 +extern "C" void exit(...); + +struct CGPoint { + float x; + float y; +}; +typedef struct CGPoint CGPoint; + +extern "C" const CGPoint CGPointZero; + +bool operator==(const CGPoint& a, const CGPoint& b); + +@interface TIconViewSettings +@property (assign, nonatomic) CGPoint gridOffset; +@end + +@implementation TIconViewSettings +- (CGPoint) gridOffset +{ + return CGPointZero; +} + +- (void) foo +{ + if ((self.gridOffset) == CGPointZero) + exit(1); + + if (self.gridOffset == CGPointZero) + exit(1); +} +@end + diff --git a/clang/test/CodeGenObjCXX/property-dot-reference.mm b/clang/test/CodeGenObjCXX/property-dot-reference.mm new file mode 100644 index 0000000..e64b397 --- /dev/null +++ b/clang/test/CodeGenObjCXX/property-dot-reference.mm @@ -0,0 +1,62 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fexceptions -o - %s | FileCheck %s +// rdar://8409336 + +struct TFENode { +void GetURL() const; +}; + +@interface TNodeIconAndNameCell +- (const TFENode&) node; +@end + +@implementation TNodeIconAndNameCell +- (const TFENode&) node { +// CHECK: call %struct.TFENode* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend +// CHECK-NEXT: call void @_ZNK7TFENode6GetURLEv(%struct.TFENode* %{{.*}}) + self.node.GetURL(); +} // expected-warning {{control reaches end of non-void function}} +@end + +// rdar://8437240 +struct X { + int x; +}; + +void f0(const X &parent); +@interface A +- (const X&) target; +@end +void f1(A *a) { +// CHECK: [[PRP:%.*]] = call %struct.X* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend +// CHECK-NEXT:call void @_Z2f0RK1X(%struct.X* [[PRP]]) + f0(a.target); + +// CHECK: [[MSG:%.*]] = call %struct.X* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend +// CHECK-NEXT:call void @_Z2f0RK1X(%struct.X* [[MSG]]) + f0([a target]); +} + +@interface Test2 +@property (readonly) int myProperty; +- (int) myProperty; +- (double) myGetter; +@end +void test2() { + Test2 *obj; + (void) obj.myProperty; + (void) obj.myGetter; + static_cast<void>(obj.myProperty); + static_cast<void>(obj.myGetter); + void(obj.myProperty); + void(obj.myGetter); +} +// CHECK: define void @_Z5test2v() +// CHECK: call i32 bitcast +// CHECK: call double bitcast +// CHECK: call i32 bitcast +// CHECK: call double bitcast +// CHECK: call i32 bitcast +// CHECK: call double bitcast + +// PR8751 +int test3(Test2 *obj) { return obj.myProperty; } diff --git a/clang/test/CodeGenObjCXX/property-object-conditional-exp.mm b/clang/test/CodeGenObjCXX/property-object-conditional-exp.mm new file mode 100644 index 0000000..281076e --- /dev/null +++ b/clang/test/CodeGenObjCXX/property-object-conditional-exp.mm @@ -0,0 +1,44 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-fragile-abi -emit-llvm -o - %s | FileCheck %s + +struct CGRect { + char* origin; + unsigned size; +}; +typedef struct CGRect CGRect; + +extern "C" bool CGRectIsEmpty(CGRect); + +@interface Foo { + CGRect out; +} +@property CGRect bounds; +- (CGRect) out; +@end + + +@implementation Foo + +- (void)bar { + CGRect dataRect; + CGRect virtualBounds; + +// 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 { i8*, i32 }* [[SRC:%.*]] +// CHECK-NEXT:extractvalue +// CHECK-NEXT:store + dataRect = CGRectIsEmpty(virtualBounds) ? self.bounds : virtualBounds; + dataRect = CGRectIsEmpty(virtualBounds) ? [self bounds] : virtualBounds; + dataRect = CGRectIsEmpty(virtualBounds) ? virtualBounds : self.bounds; + + dataRect = CGRectIsEmpty(virtualBounds) ? self.out : virtualBounds; + dataRect = CGRectIsEmpty(virtualBounds) ? [self out] : virtualBounds; + dataRect = CGRectIsEmpty(virtualBounds) ? virtualBounds : self.out; +} + +@dynamic bounds; +- (CGRect) out { return out; } +@end diff --git a/clang/test/CodeGenObjCXX/property-object-reference-1.mm b/clang/test/CodeGenObjCXX/property-object-reference-1.mm new file mode 100644 index 0000000..79bf9e4 --- /dev/null +++ b/clang/test/CodeGenObjCXX/property-object-reference-1.mm @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -x objective-c++ %s -triple x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s +// rdar://6137845 + +struct TCPPObject +{ + TCPPObject(const TCPPObject& inObj); + TCPPObject(); + ~TCPPObject(); + int filler[64]; +}; + + +@interface MyDocument +{ +@private + TCPPObject _cppObject; +} +@property (atomic, assign, readwrite) const TCPPObject& cppObject; +@end + +@implementation MyDocument + +@synthesize cppObject = _cppObject; + +@end + +// CHECK: [[cppObjectaddr:%.*]] = alloca %struct.TCPPObject*, align 8 +// CHECK: store %struct.TCPPObject* [[cppObject:%.*]], %struct.TCPPObject** [[cppObjectaddr]], align 8 +// CHECK: [[THREE:%.*]] = load %struct.TCPPObject** [[cppObjectaddr]], align 8 +// CHECK: [[FOUR:%.*]] = bitcast %struct.TCPPObject* [[THREE]] to i8* +// CHECK: call void @objc_copyStruct(i8* [[TWO:%.*]], i8* [[FOUR]], i64 256, i1 zeroext true, i1 zeroext false) diff --git a/clang/test/CodeGenObjCXX/property-object-reference-2.mm b/clang/test/CodeGenObjCXX/property-object-reference-2.mm new file mode 100644 index 0000000..b150a3e --- /dev/null +++ b/clang/test/CodeGenObjCXX/property-object-reference-2.mm @@ -0,0 +1,56 @@ +// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s +// rdar://6137845 + +extern int DEFAULT(); + +struct TCPPObject +{ + TCPPObject(); + ~TCPPObject(); + TCPPObject(const TCPPObject& inObj, int i = DEFAULT()); + TCPPObject& operator=(const TCPPObject& inObj); + int filler[64]; +}; + + +@interface MyDocument +{ +@private + TCPPObject _cppObject; + TCPPObject _cppObject1; +} +@property (assign, readwrite, atomic) const TCPPObject MyProperty; +@property (assign, readwrite, atomic) const TCPPObject MyProperty1; +@end + +@implementation MyDocument + @synthesize MyProperty = _cppObject; + @synthesize MyProperty1 = _cppObject1; +@end + +// CHECK: define internal void @__copy_helper_atomic_property_( +// CHECK: [[TWO:%.*]] = load %struct.TCPPObject** [[ADDR:%.*]], align 8 +// CHECK: [[THREE:%.*]] = load %struct.TCPPObject** [[ADDR1:%.*]], align 8 +// CHECK: [[CALL:%.*]] = call i32 @_Z7DEFAULTv() +// CHECK: call void @_ZN10TCPPObjectC1ERKS_i(%struct.TCPPObject* [[TWO]], %struct.TCPPObject* [[THREE]], i32 [[CALL]]) +// CHECK: ret void + +// CHECK: define internal void @"\01-[MyDocument MyProperty]"( +// CHECK: [[ONE:%.*]] = bitcast i8* [[ADDPTR:%.*]] to %struct.TCPPObject* +// CHECK: [[TWO:%.*]] = bitcast %struct.TCPPObject* [[ONE]] to i8* +// CHECK: [[THREE:%.*]] = bitcast %struct.TCPPObject* [[AGGRESULT:%.*]] to i8* +// CHECK: call void @objc_copyCppObjectAtomic(i8* [[THREE]], i8* [[TWO]], i8* bitcast (void (%struct.TCPPObject*, %struct.TCPPObject*)* @__copy_helper_atomic_property_ to i8*)) +// CHECK: ret void + +// CHECK: define internal void @__assign_helper_atomic_property_( +// CHECK: [[TWO:%.*]] = load %struct.TCPPObject** [[ADDR:%.*]], align 8 +// CHECK: [[THREE:%.*]] = load %struct.TCPPObject** [[ADDR1:%.*]], align 8 +// CHECK: [[CALL:%.*]] = call %struct.TCPPObject* @_ZN10TCPPObjectaSERKS_(%struct.TCPPObject* [[TWO]], %struct.TCPPObject* [[THREE]]) +// CHECK: ret void + +// CHECK: define internal void @"\01-[MyDocument setMyProperty:]"( +// CHECK: [[ONE:%.*]] = bitcast i8* [[ADDRPTR:%.*]] to %struct.TCPPObject* +// CHECK: [[TWO:%.*]] = bitcast %struct.TCPPObject* [[ONE]] to i8* +// CHECK: [[THREE:%.*]] = bitcast %struct.TCPPObject* [[MYPROPERTY:%.*]] to i8* +// CHECK: call void @objc_copyCppObjectAtomic(i8* [[TWO]], i8* [[THREE]], i8* bitcast (void (%struct.TCPPObject*, %struct.TCPPObject*)* @__assign_helper_atomic_property_ to i8*)) +// CHECK: ret void diff --git a/clang/test/CodeGenObjCXX/property-object-reference.mm b/clang/test/CodeGenObjCXX/property-object-reference.mm new file mode 100644 index 0000000..0bd8fb8 --- /dev/null +++ b/clang/test/CodeGenObjCXX/property-object-reference.mm @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -fobjc-fragile-abi -emit-llvm -o - | FileCheck %s +// rdar://10188258 + +struct Foo {int i;}; +static Foo gFoo; + + +@interface ObjCTest { } +@property (nonatomic, readonly) Foo& FooRefProperty; +@property (nonatomic) Foo FooProperty; +- (Foo &) FooProperty; +- (void)setFooProperty : (Foo &) arg; +@end + + +@implementation ObjCTest +@dynamic FooRefProperty; + +-(void) test { + Foo& f = self.FooRefProperty; + Foo& f1 = self.FooProperty; +} +- (Foo &) FooProperty { return gFoo; } +- (void)setFooProperty : (Foo &) arg { }; +@end + +// CHECK: [[T0:%.*]] = load {{%.*}} [[S0:%.*]] +// CHECK: load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ +// CHECK: [[T2:%.*]] = bitcast {{%.*}} [[T0]] to i8* +// CHECK: @objc_msgSend +// CHECK: [[R0:%.*]] = load {{%.*}} [[U0:%.*]] +// CHECK: load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ +// CHECK: [[R2:%.*]] = bitcast {{%.*}} [[R0]] to i8* +// CHECK: @objc_msgSend + diff --git a/clang/test/CodeGenObjCXX/property-objects.mm b/clang/test/CodeGenObjCXX/property-objects.mm new file mode 100644 index 0000000..6dfcc27 --- /dev/null +++ b/clang/test/CodeGenObjCXX/property-objects.mm @@ -0,0 +1,78 @@ +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s +// CHECK-NOT: callq _objc_msgSend_stret +// CHECK: call void @_ZN1SC1ERKS_ +// CHECK: call %class.S* @_ZN1SaSERKS_ +// CHECK: call %struct.CGRect* @_ZN6CGRectaSERKS_ + +class S { +public: + S& operator = (const S&); + S (const S&); + S (); +}; + +struct CGRect { + CGRect & operator = (const CGRect &); +}; + +@interface I { + S position; + CGRect bounds; +} +@property(assign, nonatomic) S position; +@property CGRect bounds; +@property CGRect frame; +- (void)setFrame:(CGRect)frameRect; +- (CGRect)frame; +- (void) initWithOwner; +- (struct CGRect)extent; +- (void)dealloc; +@end + +@implementation I +@synthesize position; +@synthesize bounds; +@synthesize frame; +- (void)setFrame:(CGRect)frameRect {} +- (CGRect)frame {return bounds;} + +- (void)initWithOwner { + I* _labelLayer; + CGRect labelLayerFrame = self.bounds; + labelLayerFrame = self.bounds; + _labelLayer.frame = labelLayerFrame; +} +// rdar://8366604 +- (void)dealloc + { + CGRect cgrect = self.extent; + } +- (struct CGRect)extent {return bounds;} +@end + +int main() { + I *i; + S s1; + i.position = s1; + return 0; +} + +// rdar://8379892 +// CHECK: define void @_Z1fP1A +// CHECK: @objc_msgSend to void +struct X { + X(); + X(const X&); + ~X(); +}; + +@interface A { + X xval; +} +- (X)x; +- (void)setX:(X)x; +@end + +void f(A* a) { + a.x = X(); +} diff --git a/clang/test/CodeGenObjCXX/property-reference.mm b/clang/test/CodeGenObjCXX/property-reference.mm new file mode 100644 index 0000000..4897f6d --- /dev/null +++ b/clang/test/CodeGenObjCXX/property-reference.mm @@ -0,0 +1,96 @@ +// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -fobjc-fragile-abi -emit-llvm -o - | FileCheck %s +// rdar://9208606 + +struct MyStruct { + int x; + int y; + int z; +}; + +@interface MyClass { + MyStruct _foo; +} + +@property (assign, readwrite) const MyStruct& foo; + +- (const MyStruct&) foo; +- (void) setFoo:(const MyStruct&)inFoo; +@end + +void test0() { + MyClass* myClass; + MyStruct myStruct; + + myClass.foo = myStruct; + + const MyStruct& currentMyStruct = myClass.foo; +} + +// CHECK: [[C:%.*]] = call %struct.MyStruct* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend +// CHECK: store %struct.MyStruct* [[C]], %struct.MyStruct** [[D:%.*]] + +namespace test1 { + struct A { A(); A(const A&); A&operator=(const A&); ~A(); }; +} +@interface Test1 { + test1::A ivar; +} +@property (nonatomic) const test1::A &prop1; +@end +@implementation Test1 +@synthesize prop1 = ivar; +@end +// CHECK: define internal [[A:%.*]]* @"\01-[Test1 prop1]"( +// CHECK: [[SELF:%.*]] = alloca [[TEST1:%.*]]*, align 8 +// CHECK: [[T0:%.*]] = load [[TEST1]]** [[SELF]] +// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST1]]* [[T0]] to i8* +// CHECK-NEXT: [[T2:%.*]] = getelementptr inbounds i8* [[T1]], i64 0 +// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A]]* +// CHECK-NEXT: ret [[A]]* [[T3]] + +// CHECK: define internal void @"\01-[Test1 setProp1:]"( +// CHECK: call [[A]]* @_ZN5test11AaSERKS0_( +// CHECK-NEXT: ret void + +// rdar://problem/10497174 +@interface Test2 +@property int prop; +@end + +// The fact that these are all non-dependent is critical. +template <class T> void test2(Test2 *a) { + int x = a.prop; + a.prop = x; + a.prop += x; +} +template void test2<int>(Test2*); +// CHECK: define weak_odr void @_Z5test2IiEvP5Test2( +// CHECK: [[X:%.*]] = alloca i32, +// CHECK: @objc_msgSend +// CHECK: store i32 {{%.*}}, i32* [[X]], +// CHECK: load i32* [[X]], +// CHECK: @objc_msgSend +// CHECK: @objc_msgSend +// CHECK: load i32* [[X]], +// CHECK-NEXT: add nsw +// CHECK: @objc_msgSend +// CHECK-NEXT: ret void + +// Same as the previous test, but instantiation-dependent. +template <class T> void test3(Test2 *a) { + int x = (sizeof(T), a).prop; + a.prop = (sizeof(T), x); + a.prop += (sizeof(T), x); +} +template void test3<int>(Test2*); +// CHECK: define weak_odr void @_Z5test3IiEvP5Test2( +// CHECK: [[X:%.*]] = alloca i32, +// CHECK: @objc_msgSend +// CHECK: store i32 {{%.*}}, i32* [[X]], +// CHECK: load i32* [[X]], +// CHECK: @objc_msgSend +// CHECK: @objc_msgSend +// CHECK: load i32* [[X]], +// CHECK-NEXT: add nsw +// CHECK: @objc_msgSend +// CHECK-NEXT: ret void diff --git a/clang/test/CodeGenObjCXX/refence-assign-write-barrier.mm b/clang/test/CodeGenObjCXX/refence-assign-write-barrier.mm new file mode 100644 index 0000000..206ecb0 --- /dev/null +++ b/clang/test/CodeGenObjCXX/refence-assign-write-barrier.mm @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -fobjc-gc -triple x86_64-apple-darwin10 -fobjc-fragile-abi -emit-llvm -o - %s | FileCheck %s +// rdar://8681766 + +@interface NSArray +- (NSArray*) retain; +- (void) release; +@end + +void NSAssignArray(NSArray*& target, NSArray* newValue) +{ + if (target == newValue) + return; + + NSArray* oldValue = target; + + target = [newValue retain]; + + [oldValue release]; +} +// CHECK: {{call.* @objc_assign_strongCast}} diff --git a/clang/test/CodeGenObjCXX/references.mm b/clang/test/CodeGenObjCXX/references.mm new file mode 100644 index 0000000..6265c7b --- /dev/null +++ b/clang/test/CodeGenObjCXX/references.mm @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s + +struct A { ~A(); }; + +@interface B { + A a; +} + +- (const A&)getA; +@end + +@implementation B + +- (const A&)getA { + return a; +} + +@end + +// CHECK: define void @_Z1fP1B +// CHECK: objc_msgSend to +// CHECK-NOT: call void @_ZN1AD1Ev +// CHECK: ret void +void f(B* b) { + (void)[b getA]; +} + +// PR7741 +@protocol P1 @end +@protocol P2 @end +@protocol P3 @end +@interface foo<P1> {} @end +@interface bar : foo <P1, P2, P3> {} @end +typedef bar baz; +void f5(foo&); +void f5b(foo<P1>&); +void f5c(foo<P2>&); +void f5d(foo<P3>&); +void f6(baz* x) { + f5(*x); + f5b(*x); + f5c(*x); + f5d(*x); + (void)((foo&)*x); +} diff --git a/clang/test/CodeGenObjCXX/rtti.mm b/clang/test/CodeGenObjCXX/rtti.mm new file mode 100644 index 0000000..72de3ac --- /dev/null +++ b/clang/test/CodeGenObjCXX/rtti.mm @@ -0,0 +1,52 @@ +// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s + +// PR7864. This all follows GCC's lead. + +namespace std { class type_info; } + +// CHECK: @_ZTI1A = linkonce_odr unnamed_addr constant {{.*}}@_ZTVN10__cxxabiv117__class_type_infoE{{.*}}@_ZTS1A +@interface A +@end + +// CHECK: @_ZTI1B = linkonce_odr unnamed_addr constant {{.*}}@_ZTVN10__cxxabiv120__si_class_type_infoE{{.*}}@_ZTS1B{{.*}}@_ZTI1A +@interface B : A +@end + +// CHECK: @_ZTIP1B = linkonce_odr unnamed_addr constant {{.*}}@_ZTVN10__cxxabiv119__pointer_type_infoE{{.*}}@_ZTSP1B{{.*}}), i32 0, {{.*}}@_ZTI1B +// CHECK: @_ZTI11objc_object = linkonce_odr unnamed_addr constant {{.*}}@_ZTVN10__cxxabiv117__class_type_infoE{{.*}}@_ZTS11objc_object +// CHECK: @_ZTIP11objc_object = linkonce_odr unnamed_addr constant {{.*}}@_ZTVN10__cxxabiv119__pointer_type_infoE{{.*}}@_ZTSP11objc_object{{.*}}@_ZTI11objc_object +// CHECK: @_ZTI10objc_class = linkonce_odr unnamed_addr constant {{.*}}@_ZTVN10__cxxabiv117__class_type_infoE{{.*}}@_ZTS10objc_class +// CHECK: @_ZTIP10objc_class = linkonce_odr unnamed_addr constant {{.*}}@_ZTVN10__cxxabiv119__pointer_type_infoE{{.*}}@_ZTSP10objc_class{{.*}}@_ZTI10objc_class + +@protocol P; + +int main() { + // CHECK: store {{.*}} @_ZTIP1B + // CHECK: store {{.*}} @_ZTI1B + const std::type_info &t1 = typeid(B*); + const std::type_info &t2 = typeid(B); + + // CHECK: store {{.*}} @_ZTIP11objc_object + // CHECK: store {{.*}} @_ZTI11objc_object + id i = 0; + const std::type_info &t3 = typeid(i); + const std::type_info &t4 = typeid(*i); + + // CHECK: store {{.*}} @_ZTIP10objc_class + // CHECK: store {{.*}} @_ZTI10objc_class + Class c = 0; + const std::type_info &t5 = typeid(c); + const std::type_info &t6 = typeid(*c); + + // CHECK: store {{.*}} @_ZTIP11objc_object + // CHECK: store {{.*}} @_ZTI11objc_object + id<P> i2 = 0; + const std::type_info &t7 = typeid(i2); + const std::type_info &t8 = typeid(*i2); + + // CHECK: store {{.*}} @_ZTIP10objc_class + // CHECK: store {{.*}} @_ZTI10objc_class + Class<P> c2 = 0; + const std::type_info &t9 = typeid(c2); + const std::type_info &t10 = typeid(*c2); +} diff --git a/clang/test/CodeGenObjCXX/selector-expr-lvalue.mm b/clang/test/CodeGenObjCXX/selector-expr-lvalue.mm new file mode 100644 index 0000000..3e3bf4e --- /dev/null +++ b/clang/test/CodeGenObjCXX/selector-expr-lvalue.mm @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-fragile-abi -emit-llvm -o - %s +// PR7390 + +@interface NSObject {} +- (void)respondsToSelector:(const SEL&)s : (SEL*)s1; +- (void) setPriority:(int)p; +- (void)Meth; +@end + +@implementation NSObject +- (void)Meth { + [self respondsToSelector:@selector(setPriority:) : &@selector(setPriority:)]; +} +- (void) setPriority:(int)p{} +- (void)respondsToSelector:(const SEL&)s : (SEL*)s1 {} +@end diff --git a/clang/test/CodeGenObjCXX/write-barrier-global-assign.mm b/clang/test/CodeGenObjCXX/write-barrier-global-assign.mm new file mode 100644 index 0000000..cb563f3 --- /dev/null +++ b/clang/test/CodeGenObjCXX/write-barrier-global-assign.mm @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -fobjc-gc -triple x86_64-apple-darwin10 -fobjc-fragile-abi -emit-llvm -o - %s | FileCheck %s +// rdar://8761767 + +@class CPDestUser; + +CPDestUser* FUNC(); + +// CHECK: {{call.* @objc_assign_global}} +CPDestUser* globalUser = FUNC(); + +// CHECK: {{call.* @objc_assign_weak}} +__weak CPDestUser* weakUser = FUNC(); + + +// CHECK: {{call.* @objc_assign_global}} +static CPDestUser* staticUser = FUNC(); + +CPDestUser* GetDestUser() +{ +// CHECK: {{call.* @objc_assign_global}} + static CPDestUser* gUser = FUNC(); +// CHECK: {{call.* @objc_assign_weak}} + static __weak CPDestUser* wUser = FUNC(); + if (wUser) + return wUser; + if (staticUser) + return staticUser; + return gUser; +} |