224 lines
6.2 KiB
Plaintext
224 lines
6.2 KiB
Plaintext
// 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 nonnull align {{[0-9]+}} 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* nonnull align {{[0-9]+}} 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* nonnull align {{[0-9]+}} 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: [[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: load [[B]]*, [[B]]** [[BVAR]]
|
|
// 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: call void @llvm.dbg.declare(
|
|
// CHECK: call void @_ZN2B3C1Ev(
|
|
// CHECK-NEXT: [[T0:%.*]] = call i64 @_ZN2B3cv2B1Ev(
|
|
// CHECK-NOT: call
|
|
// CHECK: store i64 [[T0]],
|
|
// CHECK: load [[B]]*, [[B]]** [[BVAR]]
|
|
// 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
|