diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2012-04-14 14:01:31 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2012-04-14 14:01:31 +0000 |
| commit | dbe13110f59f48b4dbb7552b3ac2935acdeece7f (patch) | |
| tree | be1815eb79b42ff482a8562b13c2dcbf0c5dcbee /test/CodeGenObjCXX | |
| parent | 9da628931ebf2609493570f87824ca22402cc65f (diff) | |
Notes
Diffstat (limited to 'test/CodeGenObjCXX')
| -rw-r--r-- | test/CodeGenObjCXX/Inputs/literal-support.h | 35 | ||||
| -rw-r--r-- | test/CodeGenObjCXX/address-safety-attr.mm | 20 | ||||
| -rw-r--r-- | test/CodeGenObjCXX/arc-exceptions.mm | 85 | ||||
| -rw-r--r-- | test/CodeGenObjCXX/arc.mm | 69 | ||||
| -rw-r--r-- | test/CodeGenObjCXX/copy.mm | 2 | ||||
| -rw-r--r-- | test/CodeGenObjCXX/debug-info.mm | 41 | ||||
| -rw-r--r-- | test/CodeGenObjCXX/lambda-expressions.mm | 39 | ||||
| -rw-r--r-- | test/CodeGenObjCXX/literals.mm | 111 | ||||
| -rw-r--r-- | test/CodeGenObjCXX/lvalue-reference-getter.mm | 28 | ||||
| -rw-r--r-- | test/CodeGenObjCXX/objc-container-subscripting-1.mm | 50 | ||||
| -rw-r--r-- | test/CodeGenObjCXX/objc-container-subscripting.mm | 57 | ||||
| -rw-r--r-- | test/CodeGenObjCXX/property-object-reference-1.mm | 31 | ||||
| -rw-r--r-- | test/CodeGenObjCXX/property-object-reference-2.mm | 56 | ||||
| -rw-r--r-- | test/CodeGenObjCXX/property-object-reference.mm | 12 | ||||
| -rw-r--r-- | test/CodeGenObjCXX/property-reference.mm | 44 |
15 files changed, 664 insertions, 16 deletions
diff --git a/test/CodeGenObjCXX/Inputs/literal-support.h b/test/CodeGenObjCXX/Inputs/literal-support.h new file mode 100644 index 000000000000..5680a20c9fb5 --- /dev/null +++ b/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/test/CodeGenObjCXX/address-safety-attr.mm b/test/CodeGenObjCXX/address-safety-attr.mm new file mode 100644 index 000000000000..a54ca998f818 --- /dev/null +++ b/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/test/CodeGenObjCXX/arc-exceptions.mm b/test/CodeGenObjCXX/arc-exceptions.mm new file mode 100644 index 000000000000..b1fa8ca2403b --- /dev/null +++ b/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/test/CodeGenObjCXX/arc.mm b/test/CodeGenObjCXX/arc.mm index 8f3aa711d65d..45211a2c19ab 100644 --- a/test/CodeGenObjCXX/arc.mm +++ b/test/CodeGenObjCXX/arc.mm @@ -178,6 +178,8 @@ id test36(id z) { // Template instantiation side of rdar://problem/9817306 @interface Test37 ++ alloc; +- init; - (NSArray *) array; @end template <class T> void test37(T *a) { @@ -188,24 +190,65 @@ template <class T> void test37(T *a) { extern template void test37<Test37>(Test37 *a); template void test37<Test37>(Test37 *a); // CHECK: define weak_odr void @_Z6test37I6Test37EvPT_( -// CHECK-LP64: [[T0:%.*]] = call [[NSARRAY]]* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to [[NSARRAY]]* (i8*, i8*)*)( -// CHECK-LP64-NEXT: [[T1:%.*]] = bitcast [[NSARRAY]]* [[T0]] to i8* -// CHECK-LP64-NEXT: [[T2:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T1]]) -// CHECK-LP64-NEXT: [[COLL:%.*]] = bitcast i8* [[T2]] to [[NSARRAY]]* +// 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-LP64-NEXT: load i8** @"\01L_OBJC_SELECTOR_REFERENCES_ -// CHECK-LP64-NEXT: [[T0:%.*]] = bitcast [[NSARRAY]]* [[COLL]] to i8* -// CHECK-LP64-NEXT: @objc_msgSend +// 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-LP64: [[T0:%.*]] = bitcast [[NSARRAY]]* [[COLL]] to i8* -// CHECK-LP64-NEXT: @objc_enumerationMutation +// CHECK: [[T0:%.*]] = bitcast [[NSARRAY]]* [[COLL]] to i8* +// CHECK-NEXT: @objc_enumerationMutation // This bitcast is for the 'next' message send. -// CHECK-LP64: [[T0:%.*]] = bitcast [[NSARRAY]]* [[COLL]] to i8* -// CHECK-LP64-NEXT: @objc_msgSend +// CHECK: [[T0:%.*]] = bitcast [[NSARRAY]]* [[COLL]] to i8* +// CHECK-NEXT: @objc_msgSend // This bitcast is for the final release. -// CHECK-LP64: [[T0:%.*]] = bitcast [[NSARRAY]]* [[COLL]] to i8* -// CHECK-LP64-NEXT: call void @objc_release(i8* [[T0]]) +// 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/test/CodeGenObjCXX/copy.mm b/test/CodeGenObjCXX/copy.mm index a61ccd4e5daa..9382ee870a71 100644 --- a/test/CodeGenObjCXX/copy.mm +++ b/test/CodeGenObjCXX/copy.mm @@ -14,8 +14,6 @@ namespace test0 { // CHECK-NEXT: call noalias i8* @_Znwm( // CHECK-NEXT: bitcast // CHECK-NEXT: bitcast - // CHECK-NEXT: call void @llvm.memset.p0i8.i64( - // CHECK-NEXT: bitcast // CHECK-NEXT: bitcast // CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64( // CHECK-NEXT: ret diff --git a/test/CodeGenObjCXX/debug-info.mm b/test/CodeGenObjCXX/debug-info.mm new file mode 100644 index 000000000000..04cf66f2cd18 --- /dev/null +++ b/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/test/CodeGenObjCXX/lambda-expressions.mm b/test/CodeGenObjCXX/lambda-expressions.mm new file mode 100644 index 000000000000..858cb74aa2a5 --- /dev/null +++ b/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/test/CodeGenObjCXX/literals.mm b/test/CodeGenObjCXX/literals.mm new file mode 100644 index 000000000000..b8946fa3f805 --- /dev/null +++ b/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/test/CodeGenObjCXX/lvalue-reference-getter.mm b/test/CodeGenObjCXX/lvalue-reference-getter.mm new file mode 100644 index 000000000000..83d3b9320b29 --- /dev/null +++ b/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/test/CodeGenObjCXX/objc-container-subscripting-1.mm b/test/CodeGenObjCXX/objc-container-subscripting-1.mm new file mode 100644 index 000000000000..c0dd0f8bae4d --- /dev/null +++ b/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/test/CodeGenObjCXX/objc-container-subscripting.mm b/test/CodeGenObjCXX/objc-container-subscripting.mm new file mode 100644 index 000000000000..dfe48e9d6dc8 --- /dev/null +++ b/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/test/CodeGenObjCXX/property-object-reference-1.mm b/test/CodeGenObjCXX/property-object-reference-1.mm new file mode 100644 index 000000000000..79bf9e4f314a --- /dev/null +++ b/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/test/CodeGenObjCXX/property-object-reference-2.mm b/test/CodeGenObjCXX/property-object-reference-2.mm new file mode 100644 index 000000000000..b150a3e3ea97 --- /dev/null +++ b/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/test/CodeGenObjCXX/property-object-reference.mm b/test/CodeGenObjCXX/property-object-reference.mm index b87ce2303b5e..0bd8fb8b9ff2 100644 --- a/test/CodeGenObjCXX/property-object-reference.mm +++ b/test/CodeGenObjCXX/property-object-reference.mm @@ -2,9 +2,14 @@ // 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 @@ -13,11 +18,18 @@ struct Foo {int i;}; -(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/test/CodeGenObjCXX/property-reference.mm b/test/CodeGenObjCXX/property-reference.mm index bc3bb475f5f7..4897f6d0e8f4 100644 --- a/test/CodeGenObjCXX/property-reference.mm +++ b/test/CodeGenObjCXX/property-reference.mm @@ -35,7 +35,7 @@ namespace test1 { @interface Test1 { test1::A ivar; } -@property const test1::A &prop1; +@property (nonatomic) const test1::A &prop1; @end @implementation Test1 @synthesize prop1 = ivar; @@ -52,3 +52,45 @@ namespace test1 { // 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 |
