| // RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -std=c++11 -emit-llvm -debug-info-kind=limited -o - | FileCheck %s |
| |
| 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; |
| - (CGRect)extent; |
| - (void)dealloc; |
| @end |
| |
| @implementation I |
| @synthesize position; |
| @synthesize bounds; |
| @synthesize frame; |
| |
| // CHECK: define internal void @"\01-[I setPosition:]" |
| // CHECK: call dereferenceable({{[0-9]+}}) %class.S* @_ZN1SaSERKS_ |
| // CHECK-NEXT: ret void |
| |
| // Don't attach debug locations to the prologue instructions. These were |
| // leaking over from the previous function emission by accident. |
| // CHECK: define internal void @"\01-[I setBounds:]"({{.*}} { |
| // CHECK-NOT: !dbg |
| // CHECK: call void @llvm.dbg.declare |
| - (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 |
| |
| // CHECK-LABEL: define i32 @main |
| // CHECK: call void @_ZN1SC1ERKS_(%class.S* [[AGGTMP:%[a-zA-Z0-9\.]+]], %class.S* dereferenceable({{[0-9]+}}) {{%[a-zA-Z0-9\.]+}}) |
| // CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, %class.S*)*)(i8* {{%[a-zA-Z0-9\.]+}}, i8* {{%[a-zA-Z0-9\.]+}}, %class.S* [[AGGTMP]]) |
| // CHECK-NEXT: ret i32 0 |
| int main() { |
| I *i; |
| S s1; |
| i.position = s1; |
| return 0; |
| } |
| |
| // rdar://8379892 |
| // CHECK-LABEL: define void @_Z1fP1A |
| // CHECK: call void @_ZN1XC1Ev(%struct.X* [[LVTEMP:%[a-zA-Z0-9\.]+]]) |
| // CHECK: call void @_ZN1XC1ERKS_(%struct.X* [[AGGTMP:%[a-zA-Z0-9\.]+]], %struct.X* dereferenceable({{[0-9]+}}) [[LVTEMP]]) |
| // CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, %struct.X*)*)({{.*}} %struct.X* [[AGGTMP]]) |
| 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(); |
| } |
| |
| // rdar://21801088 |
| // Ensure that pseudo-objecet expressions that require the RHS to be |
| // rewritten don't result in crashes or redundant emission of code. |
| struct B0 { long long x; }; |
| struct B1 { long long x; }; B1 operator+(B1, B1); |
| struct B2 { B1 x; }; |
| struct B3 { B3(); B1 x; operator B1(); }; |
| @interface B |
| @property B0 b0; |
| @property B1 b1; |
| @property B2 b2; |
| @property B3 b3; |
| @end |
| |
| int b_makeInt(); |
| |
| // Note that there's a promotion from int to long long, so |
| // the syntactic form of the RHS will be bogus. |
| void testB0(B *b) { |
| b.b0 = { b_makeInt() }; |
| } |
| void testB1(B *b) { |
| b.b1 += { b_makeInt() }; |
| } |
| // CHECK: define void @_Z6testB0P1B([[B:%.*]]* |
| // CHECK: [[BVAR:%.*]] = alloca [[B]]*, align 8 |
| // CHECK: [[TEMP:%.*]] = alloca [[B0:%.*]], align 8 |
| // CHECK: load [[B]]*, [[B]]** [[BVAR]] |
| // CHECK-NEXT: [[X:%.*]] = getelementptr inbounds [[B0]], [[B0]]* [[TEMP]], i32 0, i32 0 |
| // CHECK-NEXT: [[T0:%.*]] = call i32 @_Z9b_makeIntv() |
| // CHECK-NEXT: [[T1:%.*]] = sext i32 [[T0]] to i64 |
| // CHECK-NEXT: store i64 [[T1]], i64* [[X]], align 8 |
| // CHECK-NOT: call |
| // CHECK: call void @llvm.memcpy |
| // CHECK-NOT: call |
| // CHECK: call void bitcast {{.*}} @objc_msgSend |
| // CHECK-NOT: call |
| // CHECK: ret void |
| |
| // CHECK: define void @_Z6testB1P1B([[B]]* |
| // CHECK: [[BVAR:%.*]] = alloca [[B]]*, align 8 |
| // CHECK: load [[B]]*, [[B]]** [[BVAR]] |
| // CHECK-NOT: call |
| // CHECK: [[T0:%.*]] = call i64 bitcast {{.*}} @objc_msgSend |
| // CHECK-NOT: call |
| // CHECK: store i64 [[T0]], |
| // CHECK-NOT: call |
| // CHECK: [[T0:%.*]] = call i32 @_Z9b_makeIntv() |
| // CHECK-NEXT: [[T1:%.*]] = sext i32 [[T0]] to i64 |
| // CHECK-NEXT: store i64 [[T1]], i64* {{.*}}, align 8 |
| // CHECK-NOT: call |
| // CHECK: [[T0:%.*]] = call i64 @_Zpl2B1S_ |
| // CHECK-NOT: call |
| // CHECK: store i64 [[T0]], |
| // CHECK-NOT: call |
| // CHECK: call void @llvm.memcpy |
| // CHECK-NOT: call |
| // CHECK: call void bitcast {{.*}} @objc_msgSend |
| // CHECK-NOT: call |
| // CHECK: ret void |
| |
| // Another example of a conversion that needs to be applied |
| // in the semantic form. |
| void testB2(B *b) { |
| b.b2 = { B3() }; |
| } |
| |
| // CHECK: define void @_Z6testB2P1B([[B]]* |
| // CHECK: [[BVAR:%.*]] = alloca [[B]]*, align 8 |
| // CHECK: load [[B]]*, [[B]]** [[BVAR]] |
| // CHECK-NOT: call |
| // CHECK: call void @_ZN2B3C1Ev( |
| // CHECK-NEXT: [[T0:%.*]] = call i64 @_ZN2B3cv2B1Ev( |
| // CHECK-NOT: call |
| // CHECK: store i64 [[T0]], |
| // CHECK-NOT: call |
| // CHECK: call void @llvm.memcpy |
| // CHECK-NOT: call |
| // CHECK: call void bitcast {{.*}} @objc_msgSend |
| // CHECK-NOT: call |
| // CHECK: ret void |
| |
| // A similar test to B, but using overloaded function references. |
| struct C1 { |
| int x; |
| friend C1 operator+(C1, void(&)()); |
| }; |
| @interface C |
| @property void (*c0)(); |
| @property C1 c1; |
| @end |
| |
| void c_helper(); |
| void c_helper(int); |
| |
| void testC0(C *c) { |
| c.c0 = c_helper; |
| c.c0 = &c_helper; |
| } |
| // CHECK: define void @_Z6testC0P1C([[C:%.*]]* |
| // CHECK: [[CVAR:%.*]] = alloca [[C]]*, align 8 |
| // CHECK: load [[C]]*, [[C]]** [[CVAR]] |
| // CHECK-NOT: call |
| // CHECK: call void bitcast {{.*}} @objc_msgSend {{.*}} @_Z8c_helperv |
| // CHECK-NOT: call |
| // CHECK: call void bitcast {{.*}} @objc_msgSend {{.*}} @_Z8c_helperv |
| // CHECK-NOT: call |
| // CHECK: ret void |
| |
| void testC1(C *c) { |
| c.c1 += c_helper; |
| } |
| // CHECK: define void @_Z6testC1P1C([[C]]* |
| // CHECK: [[CVAR:%.*]] = alloca [[C]]*, align 8 |
| // CHECK: load [[C]]*, [[C]]** [[CVAR]] |
| // CHECK-NOT: call |
| // CHECK: [[T0:%.*]] = call i32 bitcast {{.*}} @objc_msgSend |
| // CHECK-NOT: call |
| // CHECK: store i32 [[T0]], |
| // CHECK-NOT: call |
| // CHECK: [[T0:%.*]] = call i32 @_Zpl2C1RFvvE({{.*}} @_Z8c_helperv |
| // CHECK-NOT: call |
| // CHECK: store i32 [[T0]], |
| // CHECK-NOT: call |
| // CHECK: call void @llvm.memcpy |
| // CHECK-NOT: call |
| // CHECK: call void bitcast {{.*}} @objc_msgSend |
| // CHECK-NOT: call |
| // CHECK: ret void |