| 1 | // RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -std=c++11 -emit-llvm -debug-info-kind=limited -o - | FileCheck %s |
| 2 | |
| 3 | class S { |
| 4 | public: |
| 5 | S& operator = (const S&); |
| 6 | S (const S&); |
| 7 | S (); |
| 8 | }; |
| 9 | |
| 10 | struct CGRect { |
| 11 | CGRect & operator = (const CGRect &); |
| 12 | }; |
| 13 | |
| 14 | @interface I { |
| 15 | S position; |
| 16 | CGRect bounds; |
| 17 | } |
| 18 | |
| 19 | @property(assign, nonatomic) S position; |
| 20 | @property CGRect bounds; |
| 21 | @property CGRect frame; |
| 22 | - (void)setFrame:(CGRect)frameRect; |
| 23 | - (CGRect)frame; |
| 24 | - (void) initWithOwner; |
| 25 | - (CGRect)extent; |
| 26 | - (void)dealloc; |
| 27 | @end |
| 28 | |
| 29 | @implementation I |
| 30 | @synthesize position; |
| 31 | @synthesize bounds; |
| 32 | @synthesize frame; |
| 33 | |
| 34 | // CHECK: define internal void @"\01-[I setPosition:]" |
| 35 | // CHECK: call dereferenceable({{[0-9]+}}) %class.S* @_ZN1SaSERKS_ |
| 36 | // CHECK-NEXT: ret void |
| 37 | |
| 38 | // Don't attach debug locations to the prologue instructions. These were |
| 39 | // leaking over from the previous function emission by accident. |
| 40 | // CHECK: define internal void @"\01-[I setBounds:]"({{.*}} { |
| 41 | // CHECK-NOT: !dbg |
| 42 | // CHECK: call void @llvm.dbg.declare |
| 43 | - (void)setFrame:(CGRect)frameRect {} |
| 44 | - (CGRect)frame {return bounds;} |
| 45 | |
| 46 | - (void)initWithOwner { |
| 47 | I* _labelLayer; |
| 48 | CGRect labelLayerFrame = self.bounds; |
| 49 | labelLayerFrame = self.bounds; |
| 50 | _labelLayer.frame = labelLayerFrame; |
| 51 | } |
| 52 | |
| 53 | // rdar://8366604 |
| 54 | - (void)dealloc |
| 55 | { |
| 56 | CGRect cgrect = self.extent; |
| 57 | } |
| 58 | - (struct CGRect)extent {return bounds;} |
| 59 | |
| 60 | @end |
| 61 | |
| 62 | // CHECK-LABEL: define i32 @main |
| 63 | // CHECK: call void @_ZN1SC1ERKS_(%class.S* [[AGGTMP:%[a-zA-Z0-9\.]+]], %class.S* dereferenceable({{[0-9]+}}) {{%[a-zA-Z0-9\.]+}}) |
| 64 | // 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]]) |
| 65 | // CHECK-NEXT: ret i32 0 |
| 66 | int main() { |
| 67 | I *i; |
| 68 | S s1; |
| 69 | i.position = s1; |
| 70 | return 0; |
| 71 | } |
| 72 | |
| 73 | // rdar://8379892 |
| 74 | // CHECK-LABEL: define void @_Z1fP1A |
| 75 | // CHECK: call void @_ZN1XC1Ev(%struct.X* [[LVTEMP:%[a-zA-Z0-9\.]+]]) |
| 76 | // CHECK: call void @_ZN1XC1ERKS_(%struct.X* [[AGGTMP:%[a-zA-Z0-9\.]+]], %struct.X* dereferenceable({{[0-9]+}}) [[LVTEMP]]) |
| 77 | // CHECK: call void bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to void (i8*, i8*, %struct.X*)*)({{.*}} %struct.X* [[AGGTMP]]) |
| 78 | struct X { |
| 79 | X(); |
| 80 | X(const X&); |
| 81 | ~X(); |
| 82 | }; |
| 83 | |
| 84 | @interface A { |
| 85 | X xval; |
| 86 | } |
| 87 | - (X)x; |
| 88 | - (void)setX:(X)x; |
| 89 | @end |
| 90 | |
| 91 | void f(A* a) { |
| 92 | a.x = X(); |
| 93 | } |
| 94 | |
| 95 | // rdar://21801088 |
| 96 | // Ensure that pseudo-objecet expressions that require the RHS to be |
| 97 | // rewritten don't result in crashes or redundant emission of code. |
| 98 | struct B0 { long long x; }; |
| 99 | struct B1 { long long x; }; B1 operator+(B1, B1); |
| 100 | struct B2 { B1 x; }; |
| 101 | struct B3 { B3(); B1 x; operator B1(); }; |
| 102 | @interface B |
| 103 | @property B0 b0; |
| 104 | @property B1 b1; |
| 105 | @property B2 b2; |
| 106 | @property B3 b3; |
| 107 | @end |
| 108 | |
| 109 | int b_makeInt(); |
| 110 | |
| 111 | // Note that there's a promotion from int to long long, so |
| 112 | // the syntactic form of the RHS will be bogus. |
| 113 | void testB0(B *b) { |
| 114 | b.b0 = { b_makeInt() }; |
| 115 | } |
| 116 | void testB1(B *b) { |
| 117 | b.b1 += { b_makeInt() }; |
| 118 | } |
| 119 | // CHECK: define void @_Z6testB0P1B([[B:%.*]]* |
| 120 | // CHECK: [[BVAR:%.*]] = alloca [[B]]*, align 8 |
| 121 | // CHECK: [[TEMP:%.*]] = alloca [[B0:%.*]], align 8 |
| 122 | // CHECK: [[X:%.*]] = getelementptr inbounds [[B0]], [[B0]]* [[TEMP]], i32 0, i32 0 |
| 123 | // CHECK-NEXT: [[T0:%.*]] = call i32 @_Z9b_makeIntv() |
| 124 | // CHECK-NEXT: [[T1:%.*]] = sext i32 [[T0]] to i64 |
| 125 | // CHECK-NEXT: store i64 [[T1]], i64* [[X]], align 8 |
| 126 | // CHECK: load [[B]]*, [[B]]** [[BVAR]] |
| 127 | // CHECK-NOT: call |
| 128 | // CHECK: call void @llvm.memcpy |
| 129 | // CHECK-NOT: call |
| 130 | // CHECK: call void bitcast {{.*}} @objc_msgSend |
| 131 | // CHECK-NOT: call |
| 132 | // CHECK: ret void |
| 133 | |
| 134 | // CHECK: define void @_Z6testB1P1B([[B]]* |
| 135 | // CHECK: [[BVAR:%.*]] = alloca [[B]]*, align 8 |
| 136 | // CHECK: load [[B]]*, [[B]]** [[BVAR]] |
| 137 | // CHECK-NOT: call |
| 138 | // CHECK: [[T0:%.*]] = call i64 bitcast {{.*}} @objc_msgSend |
| 139 | // CHECK-NOT: call |
| 140 | // CHECK: store i64 [[T0]], |
| 141 | // CHECK-NOT: call |
| 142 | // CHECK: [[T0:%.*]] = call i32 @_Z9b_makeIntv() |
| 143 | // CHECK-NEXT: [[T1:%.*]] = sext i32 [[T0]] to i64 |
| 144 | // CHECK-NEXT: store i64 [[T1]], i64* {{.*}}, align 8 |
| 145 | // CHECK-NOT: call |
| 146 | // CHECK: [[T0:%.*]] = call i64 @_Zpl2B1S_ |
| 147 | // CHECK-NOT: call |
| 148 | // CHECK: store i64 [[T0]], |
| 149 | // CHECK-NOT: call |
| 150 | // CHECK: call void @llvm.memcpy |
| 151 | // CHECK-NOT: call |
| 152 | // CHECK: call void bitcast {{.*}} @objc_msgSend |
| 153 | // CHECK-NOT: call |
| 154 | // CHECK: ret void |
| 155 | |
| 156 | // Another example of a conversion that needs to be applied |
| 157 | // in the semantic form. |
| 158 | void testB2(B *b) { |
| 159 | b.b2 = { B3() }; |
| 160 | } |
| 161 | |
| 162 | // CHECK: define void @_Z6testB2P1B([[B]]* |
| 163 | // CHECK: [[BVAR:%.*]] = alloca [[B]]*, align 8 |
| 164 | // CHECK: call void @llvm.dbg.declare( |
| 165 | // CHECK: call void @_ZN2B3C1Ev( |
| 166 | // CHECK-NEXT: [[T0:%.*]] = call i64 @_ZN2B3cv2B1Ev( |
| 167 | // CHECK-NOT: call |
| 168 | // CHECK: store i64 [[T0]], |
| 169 | // CHECK: load [[B]]*, [[B]]** [[BVAR]] |
| 170 | // CHECK-NOT: call |
| 171 | // CHECK: call void @llvm.memcpy |
| 172 | // CHECK-NOT: call |
| 173 | // CHECK: call void bitcast {{.*}} @objc_msgSend |
| 174 | // CHECK-NOT: call |
| 175 | // CHECK: ret void |
| 176 | |
| 177 | // A similar test to B, but using overloaded function references. |
| 178 | struct C1 { |
| 179 | int x; |
| 180 | friend C1 operator+(C1, void(&)()); |
| 181 | }; |
| 182 | @interface C |
| 183 | @property void (*c0)(); |
| 184 | @property C1 c1; |
| 185 | @end |
| 186 | |
| 187 | void c_helper(); |
| 188 | void c_helper(int); |
| 189 | |
| 190 | void testC0(C *c) { |
| 191 | c.c0 = c_helper; |
| 192 | c.c0 = &c_helper; |
| 193 | } |
| 194 | // CHECK: define void @_Z6testC0P1C([[C:%.*]]* |
| 195 | // CHECK: [[CVAR:%.*]] = alloca [[C]]*, align 8 |
| 196 | // CHECK: load [[C]]*, [[C]]** [[CVAR]] |
| 197 | // CHECK-NOT: call |
| 198 | // CHECK: call void bitcast {{.*}} @objc_msgSend {{.*}} @_Z8c_helperv |
| 199 | // CHECK-NOT: call |
| 200 | // CHECK: call void bitcast {{.*}} @objc_msgSend {{.*}} @_Z8c_helperv |
| 201 | // CHECK-NOT: call |
| 202 | // CHECK: ret void |
| 203 | |
| 204 | void testC1(C *c) { |
| 205 | c.c1 += c_helper; |
| 206 | } |
| 207 | // CHECK: define void @_Z6testC1P1C([[C]]* |
| 208 | // CHECK: [[CVAR:%.*]] = alloca [[C]]*, align 8 |
| 209 | // CHECK: load [[C]]*, [[C]]** [[CVAR]] |
| 210 | // CHECK-NOT: call |
| 211 | // CHECK: [[T0:%.*]] = call i32 bitcast {{.*}} @objc_msgSend |
| 212 | // CHECK-NOT: call |
| 213 | // CHECK: store i32 [[T0]], |
| 214 | // CHECK-NOT: call |
| 215 | // CHECK: [[T0:%.*]] = call i32 @_Zpl2C1RFvvE({{.*}} @_Z8c_helperv |
| 216 | // CHECK-NOT: call |
| 217 | // CHECK: store i32 [[T0]], |
| 218 | // CHECK-NOT: call |
| 219 | // CHECK: call void @llvm.memcpy |
| 220 | // CHECK-NOT: call |
| 221 | // CHECK: call void bitcast {{.*}} @objc_msgSend |
| 222 | // CHECK-NOT: call |
| 223 | // CHECK: ret void |
| 224 | |