Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / test / CodeGenObjCXX / property-objects.mm
blob500a81698f99c2c650494fdb3724fad5420b9252
1 // RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -std=c++11 -emit-llvm -debug-info-kind=limited -o - | FileCheck %s
3 class S {
4 public:
5         S& operator = (const S&);
6         S (const S&);
7         S ();
8 };
10 struct CGRect {
11         CGRect & operator = (const CGRect &);
14 @interface I {
15   S position;
16   CGRect bounds;
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
29 @implementation I
30 @synthesize position;
31 @synthesize bounds;
32 @synthesize frame;
34 // CHECK: define internal void @"\01-[I setPosition:]"
35 // CHECK: call noundef nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) ptr @_ZN1SaSERKS_
36 // CHECK-NEXT: ret void
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;}
46 - (void)initWithOwner {
47   I* _labelLayer;
48   CGRect labelLayerFrame = self.bounds;
49   labelLayerFrame = self.bounds;
50   _labelLayer.frame = labelLayerFrame;
53 - (void)dealloc
54   {
55       CGRect cgrect = self.extent;
56   }
57 - (struct CGRect)extent {return bounds;}
59 @end
61 // CHECK-LABEL: define{{.*}} i32 @main
62 // CHECK: call void @_ZN1SC1ERKS_(ptr {{[^,]*}} [[AGGTMP:%[a-zA-Z0-9\.]+]], ptr noundef nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) {{%[a-zA-Z0-9\.]+}})
63 // CHECK: call void @objc_msgSend(ptr noundef {{%[a-zA-Z0-9\.]+}}, ptr noundef {{%[a-zA-Z0-9\.]+}}, ptr noundef [[AGGTMP]])
64 // CHECK-NEXT: ret i32 0
65 int main() {
66   I *i;
67   S s1;
68   i.position = s1;
69   return 0;
72 // CHECK-LABEL: define{{.*}} void @_Z1fP1A
73 // CHECK: call void @_ZN1XC1Ev(ptr {{[^,]*}} [[LVTEMP:%[a-zA-Z0-9\.]+]])
74 // CHECK: call void @_ZN1XC1ERKS_(ptr {{[^,]*}} [[AGGTMP:%[a-zA-Z0-9\.]+]], ptr noundef nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) [[LVTEMP]])
75 // CHECK: call void @objc_msgSend({{.*}} ptr noundef [[AGGTMP]])
76 struct X {
77   X();
78   X(const X&);
79   ~X();
82 @interface A {
83   X xval;
85 - (X)x;
86 - (void)setX:(X)x;
87 @end
89 void f(A* a) {
90   a.x = X();
93 //   Ensure that pseudo-objecet expressions that require the RHS to be
94 //   rewritten don't result in crashes or redundant emission of code.
95 struct B0 { long long x; };
96 struct B1 { long long x; }; B1 operator+(B1, B1);
97 struct B2 { B1 x; };
98 struct B3 { B3(); B1 x; operator B1(); };
99 @interface B
100 @property B0 b0;
101 @property B1 b1;
102 @property B2 b2;
103 @property B3 b3;
104 @end
106 int b_makeInt();
108 // Note that there's a promotion from int to long long, so
109 // the syntactic form of the RHS will be bogus.
110 void testB0(B *b) {
111   b.b0 = { b_makeInt() };
113 void testB1(B *b) {
114   b.b1 += { b_makeInt() };
116 // CHECK:    define{{.*}} void @_Z6testB0P1B(ptr
117 // CHECK:      [[BVAR:%.*]] = alloca ptr, align 8
118 // CHECK:      [[TEMP:%.*]] = alloca [[B0:%.*]], align 8
119 // CHECK:      [[X:%.*]] = getelementptr inbounds [[B0]], ptr [[TEMP]], i32 0, i32 0
120 // CHECK-NEXT: [[T0:%.*]] = call noundef i32 @_Z9b_makeIntv()
121 // CHECK-NEXT: [[T1:%.*]] = sext i32 [[T0]] to i64
122 // CHECK-NEXT: store i64 [[T1]], ptr [[X]], align 8
123 // CHECK:      load ptr, ptr [[BVAR]]
124 // CHECK-NOT:  call
125 // CHECK:      call void @llvm.memcpy
126 // CHECK-NOT:  call
127 // CHECK:      call void @objc_msgSend
128 // CHECK-NOT:  call
129 // CHECK:      ret void
131 // CHECK:    define{{.*}} void @_Z6testB1P1B(ptr
132 // CHECK:      [[BVAR:%.*]] = alloca ptr, align 8
133 // CHECK:      load ptr, ptr [[BVAR]]
134 // CHECK-NOT:  call
135 // CHECK:      [[T0:%.*]] = call i64 @objc_msgSend
136 // CHECK-NOT:  call
137 // CHECK:      store i64 [[T0]],
138 // CHECK-NOT:  call
139 // CHECK:      [[T0:%.*]] = call noundef i32 @_Z9b_makeIntv()
140 // CHECK-NEXT: [[T1:%.*]] = sext i32 [[T0]] to i64
141 // CHECK-NEXT: store i64 [[T1]], ptr {{.*}}, align 8
142 // CHECK-NOT:  call
143 // CHECK:      [[T0:%.*]] = call i64 @_Zpl2B1S_
144 // CHECK-NOT:  call
145 // CHECK:      store i64 [[T0]],
146 // CHECK-NOT:  call
147 // CHECK:      call void @llvm.memcpy
148 // CHECK-NOT:  call
149 // CHECK:      call void @objc_msgSend
150 // CHECK-NOT:  call
151 // CHECK:      ret void
153 // Another example of a conversion that needs to be applied
154 // in the semantic form.
155 void testB2(B *b) {
156   b.b2 = { B3() };
159 // CHECK:    define{{.*}} void @_Z6testB2P1B(ptr
160 // CHECK:      [[BVAR:%.*]] = alloca ptr, align 8
161 // CHECK:      call void @llvm.dbg.declare(
162 // CHECK:      call void @_ZN2B3C1Ev(
163 // CHECK-NEXT: [[T0:%.*]] = call i64 @_ZN2B3cv2B1Ev(
164 // CHECK-NOT:  call
165 // CHECK:      store i64 [[T0]],
166 // CHECK:      load ptr, ptr [[BVAR]]
167 // CHECK-NOT:  call
168 // CHECK:      call void @llvm.memcpy
169 // CHECK-NOT:  call
170 // CHECK:      call void @objc_msgSend
171 // CHECK-NOT:  call
172 // CHECK:      ret void
174 // A similar test to B, but using overloaded function references.
175 struct C1 {
176   int x;
177   friend C1 operator+(C1, void(&)());
179 @interface C
180 @property void (*c0)();
181 @property C1 c1;
182 @end
184 void c_helper();
185 void c_helper(int);
187 void testC0(C *c) {
188   c.c0 = c_helper;
189   c.c0 = &c_helper;
191 // CHECK:    define{{.*}} void @_Z6testC0P1C(ptr
192 // CHECK:      [[CVAR:%.*]] = alloca ptr, align 8
193 // CHECK:      load ptr, ptr [[CVAR]]
194 // CHECK-NOT:  call
195 // CHECK:      call void @objc_msgSend({{.*}} @_Z8c_helperv
196 // CHECK-NOT:  call
197 // CHECK:      call void @objc_msgSend({{.*}} @_Z8c_helperv
198 // CHECK-NOT:  call
199 // CHECK:      ret void
201 void testC1(C *c) {
202   c.c1 += c_helper;
204 // CHECK:    define{{.*}} void @_Z6testC1P1C(ptr
205 // CHECK:      [[CVAR:%.*]] = alloca ptr, align 8
206 // CHECK:      load ptr, ptr [[CVAR]]
207 // CHECK-NOT:  call
208 // CHECK:      [[T0:%.*]] = call i32 @objc_msgSend
209 // CHECK-NOT:  call
210 // CHECK:      store i32 [[T0]],
211 // CHECK-NOT:  call
212 // CHECK:      [[T0:%.*]] = call i32 @_Zpl2C1RFvvE({{.*}} @_Z8c_helperv
213 // CHECK-NOT:  call
214 // CHECK:      store i32 [[T0]],
215 // CHECK-NOT:  call
216 // CHECK:      call void @llvm.memcpy
217 // CHECK-NOT:  call
218 // CHECK:      call void @objc_msgSend
219 // CHECK-NOT:  call
220 // CHECK:      ret void