summaryrefslogtreecommitdiff
path: root/clang/test/CIR/CodeGen/ctor.cpp
blob: 238e4151aeb8144e059217c6fe54f33067a4ee9d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
// RUN: FileCheck --input-file=%t.cir %s

struct Struk {
  int a;
  Struk() {}
};

void baz() {
  Struk s;
}

// CHECK: !rec_Struk = !cir.record<struct "Struk" {!s32i}>

// Note: In the absence of the '-mconstructor-aliases' option, we emit two
//       constructors here. The handling of constructor aliases is currently
//       NYI, but when it is added this test should be updated to add a RUN
//       line that passes '-mconstructor-aliases' to clang_cc1.
// CHECK:   cir.func{{.*}} @_ZN5StrukC2Ev(%arg0: !cir.ptr<!rec_Struk>
// CHECK-NEXT:     %[[THIS_ADDR:.*]] = cir.alloca !cir.ptr<!rec_Struk>, !cir.ptr<!cir.ptr<!rec_Struk>>, ["this", init] {alignment = 8 : i64}
// CHECK-NEXT:     cir.store %arg0, %[[THIS_ADDR]] : !cir.ptr<!rec_Struk>, !cir.ptr<!cir.ptr<!rec_Struk>>
// CHECK-NEXT:     %[[THIS:.*]] = cir.load %[[THIS_ADDR]] : !cir.ptr<!cir.ptr<!rec_Struk>>, !cir.ptr<!rec_Struk>
// CHECK-NEXT:     cir.return

// CHECK:   cir.func{{.*}} @_ZN5StrukC1Ev(%arg0: !cir.ptr<!rec_Struk>
// CHECK-NEXT:     %[[THIS_ADDR:.*]] = cir.alloca !cir.ptr<!rec_Struk>, !cir.ptr<!cir.ptr<!rec_Struk>>, ["this", init] {alignment = 8 : i64}
// CHECK-NEXT:     cir.store %arg0, %[[THIS_ADDR]] : !cir.ptr<!rec_Struk>, !cir.ptr<!cir.ptr<!rec_Struk>>
// CHECK-NEXT:     %[[THIS:.*]] = cir.load %[[THIS_ADDR]] : !cir.ptr<!cir.ptr<!rec_Struk>>, !cir.ptr<!rec_Struk>
// CHECK-NEXT:     cir.call @_ZN5StrukC2Ev(%[[THIS]]) : (!cir.ptr<!rec_Struk>) -> ()
// CHECK-NEXT:     cir.return

// CHECK:   cir.func{{.*}} @_Z3bazv()
// CHECK-NEXT:     %[[S_ADDR:.*]] = cir.alloca !rec_Struk, !cir.ptr<!rec_Struk>, ["s", init] {alignment = 4 : i64}
// CHECK-NEXT:     cir.call @_ZN5StrukC1Ev(%[[S_ADDR]]) : (!cir.ptr<!rec_Struk>) -> ()
// CHECK-NEXT:     cir.return

struct VariadicStruk {
  int a;
  VariadicStruk(int n, ...) { a = n;}
};

void bar() {
  VariadicStruk s(1, 2, 3);
}

// When a variadic constructor is present, we call the C2 constructor directly.

// CHECK-NOT: cir.func{{.*}} @_ZN13VariadicStrukC2Eiz

// CHECK:      cir.func{{.*}} @_ZN13VariadicStrukC1Eiz(%arg0: !cir.ptr<!rec_VariadicStruk>
// CHECK-SAME:                                   %arg1: !s32i
// CHECK-SAME:                                   ...){{.*}} {
// CHECK-NEXT:   %[[THIS_ADDR:.*]] = cir.alloca {{.*}} ["this", init]
// CHECK-NEXT:   %[[N_ADDR:.*]] = cir.alloca {{.*}} ["n", init]
// CHECK-NEXT:   cir.store %arg0, %[[THIS_ADDR]]
// CHECK-NEXT:   cir.store %arg1, %[[N_ADDR]]
// CHECK-NEXT:   %[[THIS:.*]] = cir.load{{.*}} %[[THIS_ADDR]]
// CHECK-NEXT:   %[[N:.*]] = cir.load{{.*}} %[[N_ADDR]]
// CHECK-NEXT:   %[[A_ADDR:.*]] = cir.get_member %[[THIS]][0] {name = "a"}
// CHECK-NEXT:   cir.store{{.*}} %[[N]], %[[A_ADDR]]
// CHECK-NEXT:   cir.return

// CHECK:  cir.func{{.*}} @_Z3barv
// CHECK-NEXT:    %[[S_ADDR:.*]] = cir.alloca !rec_VariadicStruk, !cir.ptr<!rec_VariadicStruk>, ["s", init]
// CHECK-NEXT:    %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT:    %[[TWO:.*]] = cir.const #cir.int<2> : !s32i
// CHECK-NEXT:    %[[THREE:.*]] = cir.const #cir.int<3> : !s32i
// CHECK-NEXT:    cir.call @_ZN13VariadicStrukC1Eiz(%[[S_ADDR]], %[[ONE]], %[[TWO]], %[[THREE]])
// CHECK-NEXT:    cir.return

struct DelegatingStruk {
  int a;
  DelegatingStruk(int n) { a = n; }
  DelegatingStruk() : DelegatingStruk(0) {}
};

void bam() {
  DelegatingStruk s;
}

// CHECK:       cir.func{{.*}} @_ZN15DelegatingStrukC2Ei(%arg0: !cir.ptr<!rec_DelegatingStruk>
// CHECK-SAME:                                     %arg1: !s32i
// CHECK-NEXT:   %[[THIS_ADDR:.*]] = cir.alloca {{.*}} ["this", init]
// CHECK-NEXT:   %[[N_ADDR:.*]] = cir.alloca {{.*}} ["n", init]
// CHECK-NEXT:   cir.store %arg0, %[[THIS_ADDR]]
// CHECK-NEXT:   cir.store %arg1, %[[N_ADDR]]
// CHECK-NEXT:   %[[THIS:.*]] = cir.load{{.*}} %[[THIS_ADDR]]
// CHECK-NEXT:   %[[N:.*]] = cir.load{{.*}} %[[N_ADDR]]
// CHECK-NEXT:   %[[A_ADDR:.*]] = cir.get_member %[[THIS]][0] {name = "a"}
// CHECK-NEXT:   cir.store{{.*}} %[[N]], %[[A_ADDR]]
// CHECK-NEXT:   cir.return

// CHECK:       cir.func{{.*}} @_ZN15DelegatingStrukC1Ei(%arg0: !cir.ptr<!rec_DelegatingStruk>
// CHECK-SAME:                                     %arg1: !s32i
// CHECK-NEXT:   %[[THIS_ADDR:.*]] = cir.alloca {{.*}} ["this", init]
// CHECK-NEXT:   %[[N_ADDR:.*]] = cir.alloca {{.*}} ["n", init]
// CHECK-NEXT:   cir.store %arg0, %[[THIS_ADDR]]
// CHECK-NEXT:   cir.store %arg1, %[[N_ADDR]]
// CHECK-NEXT:   %[[THIS:.*]] = cir.load{{.*}} %[[THIS_ADDR]]
// CHECK-NEXT:   %[[N:.*]] = cir.load{{.*}} %[[N_ADDR]]
// CHECK-NEXT:   cir.call @_ZN15DelegatingStrukC2Ei(%[[THIS]], %[[N]])
// CHECK-NEXT:   cir.return

// CHECK: cir.func{{.*}} @_ZN15DelegatingStrukC1Ev(%arg0: !cir.ptr<!rec_DelegatingStruk>
// CHECK-NEXT:   %[[THIS_ADDR:.*]] = cir.alloca {{.*}} ["this", init]
// CHECK-NEXT:   cir.store %arg0, %[[THIS_ADDR]]
// CHECK-NEXT:   %[[THIS:.*]] = cir.load{{.*}} %[[THIS_ADDR]]
// CHECK-NEXT:   %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i
// CHECK-NEXT:   cir.call @_ZN15DelegatingStrukC1Ei(%[[THIS]], %[[ZERO]])
// CHECK-NEXT:   cir.return

// CHECK: cir.func{{.*}} @_Z3bamv
// CHECK-NEXT:    %[[S_ADDR:.*]] = cir.alloca {{.*}} ["s", init]
// CHECK-NEXT:    cir.call @_ZN15DelegatingStrukC1Ev(%[[S_ADDR]])
// CHECK-NEXT:    cir.return

struct MemberInitStruk {
  int a;
  MemberInitStruk() : a(0) {}
};

void init_member() {
  MemberInitStruk s;
}

// CHECK:      cir.func{{.*}} @_ZN15MemberInitStrukC2Ev(%arg0: !cir.ptr<!rec_MemberInitStruk>
// CHECK-NEXT:   %[[THIS_ADDR:.*]] = cir.alloca {{.*}} ["this", init]
// CHECK-NEXT:   cir.store %arg0, %[[THIS_ADDR]]
// CHECK-NEXT:   %[[THIS:.*]] = cir.load %[[THIS_ADDR]]
// CHECK-NEXT:   %[[A_ADDR:.*]] = cir.get_member %[[THIS]][0] {name = "a"}
// CHECK-NEXT:   %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i
// CHECK-NEXT:   cir.store align(4) %[[ZERO]], %[[A_ADDR]]
// CHECK-NEXT:   cir.return

// CHECK:      cir.func{{.*}} @_ZN15MemberInitStrukC1Ev(%arg0: !cir.ptr<!rec_MemberInitStruk>
// CHECK-NEXT:   %[[THIS_ADDR:.*]] = cir.alloca {{.*}} ["this", init]
// CHECK-NEXT:   cir.store %arg0, %[[THIS_ADDR]]
// CHECK-NEXT:   %[[THIS:.*]] = cir.load %[[THIS_ADDR]]
// CHECK-NEXT:   cir.call @_ZN15MemberInitStrukC2Ev(%[[THIS]])
// CHECK-NEXT:   cir.return

// CHECK: cir.func{{.*}} @_Z11init_memberv
// CHECK-NEXT:    %[[S_ADDR:.*]] = cir.alloca {{.*}} ["s", init]
// CHECK-NEXT:    cir.call @_ZN15MemberInitStrukC1Ev(%[[S_ADDR]])
// CHECK-NEXT:    cir.return

struct ParamMemberInitStruk {
  int a;
  ParamMemberInitStruk(int n) : a(n) {}
};

void init_param_member() {
  ParamMemberInitStruk s(0);
}

// CHECK:      cir.func{{.*}} @_ZN20ParamMemberInitStrukC2Ei(%arg0: !cir.ptr<!rec_ParamMemberInitStruk>
// CHECK-SAME:                                         %arg1: !s32i
// CHECK-NEXT:   %[[THIS_ADDR:.*]] = cir.alloca {{.*}} ["this", init]
// CHECK-NEXT:   %[[N_ADDR:.*]] = cir.alloca {{.*}} ["n", init]
// CHECK-NEXT:   cir.store %arg0, %[[THIS_ADDR]]
// CHECK-NEXT:   cir.store %arg1, %[[N_ADDR]]
// CHECK-NEXT:   %[[THIS:.*]] = cir.load %[[THIS_ADDR]]
// CHECK-NEXT:   %[[A_ADDR:.*]] = cir.get_member %[[THIS]][0] {name = "a"}
// CHECK-NEXT:   %[[N:.*]] = cir.load{{.*}} %[[N_ADDR]]
// CHECK-NEXT:   cir.store{{.*}} %[[N]], %[[A_ADDR]]
// CHECK-NEXT:   cir.return

// CHECK:      cir.func{{.*}} @_ZN20ParamMemberInitStrukC1Ei(%arg0: !cir.ptr<!rec_ParamMemberInitStruk>
// CHECK-SAME:                                         %arg1: !s32i
// CHECK-NEXT:   %[[THIS_ADDR:.*]] = cir.alloca {{.*}} ["this", init]
// CHECK-NEXT:   %[[N_ADDR:.*]] = cir.alloca {{.*}} ["n", init]
// CHECK-NEXT:   cir.store %arg0, %[[THIS_ADDR]]
// CHECK-NEXT:   cir.store %arg1, %[[N_ADDR]]
// CHECK-NEXT:   %[[THIS:.*]] = cir.load %[[THIS_ADDR]]
// CHECK-NEXT:   %[[N:.*]] = cir.load{{.*}} %[[N_ADDR]]
// CHECK-NEXT:   cir.call @_ZN20ParamMemberInitStrukC2Ei(%[[THIS]], %[[N]])
// CHECK-NEXT:   cir.return

// CHECK: cir.func{{.*}} @_Z17init_param_memberv
// CHECK-NEXT:    %[[S_ADDR:.*]] = cir.alloca {{.*}} ["s", init]
// CHECK-NEXT:    %[[ZERO:.*]] = cir.const #cir.int<0>
// CHECK-NEXT:    cir.call @_ZN20ParamMemberInitStrukC1Ei(%[[S_ADDR]], %[[ZERO]])
// CHECK-NEXT:    cir.return

struct UnionInitStruk {
  union {
    int a;
    union {
        float b;
        double c;
    };
  };
  UnionInitStruk() : c(0.0) {}
};

void init_union() {
  UnionInitStruk s;
}

// CHECK:      cir.func{{.*}} @_ZN14UnionInitStrukC2Ev(%arg0: !cir.ptr<!rec_UnionInitStruk>
// CHECK-NEXT:   %[[THIS_ADDR:.*]] = cir.alloca {{.*}} ["this", init]
// CHECK-NEXT:   cir.store %arg0, %[[THIS_ADDR]]
// CHECK-NEXT:   %[[THIS:.*]] = cir.load %[[THIS_ADDR]]
// CHECK-NEXT:   %[[AU1_ADDR:.*]] = cir.get_member %[[THIS]][0] {name = ""}
// CHECK-NEXT:   %[[AU2_ADDR:.*]] = cir.get_member %[[AU1_ADDR]][1] {name = ""}
// CHECK-NEXT:   %[[C_ADDR:.*]] = cir.get_member %[[AU2_ADDR]][1] {name = "c"}
// CHECK-NEXT:   %[[ZERO:.*]] = cir.const #cir.fp<0.000000e+00>
// CHECK-NEXT:   cir.store{{.*}} %[[ZERO]], %[[C_ADDR]]
// CHECK-NEXT:   cir.return

// CHECK:      cir.func{{.*}} @_ZN14UnionInitStrukC1Ev(%arg0: !cir.ptr<!rec_UnionInitStruk>
// CHECK-NEXT:   %[[THIS_ADDR:.*]] = cir.alloca {{.*}} ["this", init]
// CHECK-NEXT:   cir.store %arg0, %[[THIS_ADDR]]
// CHECK-NEXT:   %[[THIS:.*]] = cir.load %[[THIS_ADDR]]
// CHECK-NEXT:   cir.call @_ZN14UnionInitStrukC2Ev
// CHECK-NEXT:   cir.return

// CHECK: cir.func{{.*}} @_Z10init_unionv
// CHECK-NEXT:    %[[S_ADDR:.*]] = cir.alloca {{.*}} ["s", init]
// CHECK-NEXT:    cir.call @_ZN14UnionInitStrukC1Ev(%[[S_ADDR]])
// CHECK-NEXT:    cir.return

struct Base {
  int a;
  Base(int val) : a(val) {}
};

struct Derived : Base {
  Derived(int val) : Base(val) {}
};

void test_derived() {
  Derived d(1);
}

// CHECK: cir.func{{.*}} @_ZN4BaseC2Ei(%arg0: !cir.ptr<!rec_Base> {{.*}}, %arg1: !s32i
// CHECK-NEXT:   %[[THIS_ADDR:.*]] = cir.alloca {{.*}} ["this", init]
// CHECK-NEXT:   %[[VAL_ADDR:.*]] = cir.alloca {{.*}} ["val", init]
// CHECK-NEXT:   cir.store %arg0, %[[THIS_ADDR]]
// CHECK-NEXT:   cir.store %arg1, %[[VAL_ADDR]]
// CHECK-NEXT:   %[[THIS:.*]] = cir.load{{.*}} %[[THIS_ADDR]]
// CHECK-NEXT:   %[[A_ADDR:.*]] = cir.get_member %[[THIS]][0] {name = "a"}
// CHECK-NEXT:   %[[VAL:.*]] = cir.load{{.*}} %[[VAL_ADDR]]
// CHECK-NEXT:   cir.store{{.*}} %[[VAL]], %[[A_ADDR]]
// CHECK-NEXT:   cir.return

// CHECK:      cir.func{{.*}} @_ZN7DerivedC2Ei(%arg0: !cir.ptr<!rec_Derived> {{.*}}, %arg1: !s32i
// CHECK-NEXT:   %[[THIS_ADDR:.*]] = cir.alloca {{.*}} ["this", init]
// CHECK-NEXT:   %[[VAL_ADDR:.*]] = cir.alloca {{.*}} ["val", init]
// CHECK-NEXT:   cir.store %arg0, %[[THIS_ADDR]]
// CHECK-NEXT:   cir.store %arg1, %[[VAL_ADDR]]
// CHECK-NEXT:   %[[THIS:.*]] = cir.load{{.*}} %[[THIS_ADDR]]
// CHECK-NEXT:   %[[BASE:.*]] = cir.base_class_addr %[[THIS]] : !cir.ptr<!rec_Derived> nonnull [0] -> !cir.ptr<!rec_Base>
// CHECK-NEXT:   %[[VAL:.*]] = cir.load{{.*}} %[[VAL_ADDR]]
// CHECK-NEXT:   cir.call @_ZN4BaseC2Ei(%[[BASE]], %[[VAL]])
// CHECK-NEXT:   cir.return

// CHECK:      cir.func{{.*}} @_ZN7DerivedC1Ei(%arg0: !cir.ptr<!rec_Derived> {{.*}}, %arg1: !s32i
// CHECK-NEXT:   %[[THIS_ADDR:.*]] = cir.alloca {{.*}} ["this", init]
// CHECK-NEXT:   %[[VAL_ADDR:.*]] = cir.alloca {{.*}} ["val", init]
// CHECK-NEXT:   cir.store %arg0, %[[THIS_ADDR]]
// CHECK-NEXT:   cir.store %arg1, %[[VAL_ADDR]]
// CHECK-NEXT:   %[[THIS:.*]] = cir.load{{.*}} %[[THIS_ADDR]]
// CHECK-NEXT:   %[[VAL:.*]] = cir.load{{.*}} %[[VAL_ADDR]]
// CHECK-NEXT:   cir.call @_ZN7DerivedC2Ei(%[[THIS]], %[[VAL]])
// CHECK-NEXT:   cir.return

// CHECK: cir.func{{.*}} @_Z12test_derivedv
// CHECK-NEXT:    %[[D_ADDR:.*]] = cir.alloca {{.*}} ["d", init]
// CHECK-NEXT:    %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT:    cir.call @_ZN7DerivedC1Ei(%[[D_ADDR]], %[[ONE]])
// CHECK-NEXT:    cir.return

struct Base2 {
  int b;
  Base2(int val) : b(val) {}
};

struct Derived2 : Base, Base2 {
  int c;
  Derived2(int val1, int val2, int val3) : Base(val1), Base2(val2), c(val3) {}
};

void test_derived2() {
  Derived2 d(1, 2, 3);
}

// CHECK: cir.func{{.*}} @_ZN5Base2C2Ei(%arg0: !cir.ptr<!rec_Base2> {{.*}}, %arg1: !s32i
// CHECK-NEXT:   %[[THIS_ADDR:.*]] = cir.alloca {{.*}} ["this", init]
// CHECK-NEXT:   %[[VAL_ADDR:.*]] = cir.alloca {{.*}} ["val", init]
// CHECK-NEXT:   cir.store %arg0, %[[THIS_ADDR]]
// CHECK-NEXT:   cir.store %arg1, %[[VAL_ADDR]]
// CHECK-NEXT:   %[[THIS:.*]] = cir.load{{.*}} %[[THIS_ADDR]]
// CHECK-NEXT:   %[[B_ADDR:.*]] = cir.get_member %[[THIS]][0] {name = "b"}
// CHECK-NEXT:   %[[VAL:.*]] = cir.load{{.*}} %[[VAL_ADDR]]
// CHECK-NEXT:   cir.store{{.*}} %[[VAL]], %[[B_ADDR]]
// CHECK-NEXT:   cir.return

// CHECK:      cir.func{{.*}} @_ZN8Derived2C2Eiii(%arg0: !cir.ptr<!rec_Derived2>
// CHECK-SAME:                                    %arg1: !s32i
// CHECK-SAME:                                    %arg2: !s32i
// CHECK-SAME:                                    %arg3: !s32i
// CHECK-NEXT:   %[[THIS_ADDR:.*]] = cir.alloca {{.*}} ["this", init]
// CHECK-NEXT:   %[[VAL1_ADDR:.*]] = cir.alloca {{.*}} ["val1", init]
// CHECK-NEXT:   %[[VAL2_ADDR:.*]] = cir.alloca {{.*}} ["val2", init]
// CHECK-NEXT:   %[[VAL3_ADDR:.*]] = cir.alloca {{.*}} ["val3", init]
// CHECK-NEXT:   cir.store %arg0, %[[THIS_ADDR]]
// CHECK-NEXT:   cir.store %arg1, %[[VAL1_ADDR]]
// CHECK-NEXT:   cir.store %arg2, %[[VAL2_ADDR]]
// CHECK-NEXT:   cir.store %arg3, %[[VAL3_ADDR]]
// CHECK-NEXT:   %[[THIS:.*]] = cir.load{{.*}} %[[THIS_ADDR]]
// CHECK-NEXT:   %[[BASE:.*]] = cir.base_class_addr %[[THIS]] : !cir.ptr<!rec_Derived2> nonnull [0] -> !cir.ptr<!rec_Base>
// CHECK-NEXT:   %[[VAL1:.*]] = cir.load{{.*}} %[[VAL1_ADDR]]
// CHECK-NEXT:   cir.call @_ZN4BaseC2Ei(%[[BASE]], %[[VAL1]])
// CHECK-NEXT:   %[[BASE2:.*]] = cir.base_class_addr %[[THIS]] : !cir.ptr<!rec_Derived2> nonnull [4] -> !cir.ptr<!rec_Base2>
// CHECK-NEXT:   %[[VAL2:.*]] = cir.load{{.*}} %[[VAL2_ADDR]]
// CHECK-NEXT:   cir.call @_ZN5Base2C2Ei(%[[BASE2]], %[[VAL2]])
// CHECK-NEXT:   %[[C_ADDR:.*]] = cir.get_member %[[THIS]][2] {name = "c"}
// CHECK-NEXT:   %[[VAL3:.*]] = cir.load{{.*}} %[[VAL3_ADDR]]
// CHECK-NEXT:   cir.store{{.*}} %[[VAL3]], %[[C_ADDR]]
// CHECK-NEXT:   cir.return

// CHECK:      cir.func{{.*}} @_ZN8Derived2C1Eiii(%arg0: !cir.ptr<!rec_Derived2>
// CHECK-SAME:                                    %arg1: !s32i
// CHECK-SAME:                                    %arg2: !s32i
// CHECK-SAME:                                    %arg3: !s32i
// CHECK-NEXT:   %[[THIS_ADDR:.*]] = cir.alloca {{.*}} ["this", init]
// CHECK-NEXT:   %[[VAL1_ADDR:.*]] = cir.alloca {{.*}} ["val1", init]
// CHECK-NEXT:   %[[VAL2_ADDR:.*]] = cir.alloca {{.*}} ["val2", init]
// CHECK-NEXT:   %[[VAL3_ADDR:.*]] = cir.alloca {{.*}} ["val3", init]
// CHECK-NEXT:   cir.store %arg0, %[[THIS_ADDR]]
// CHECK-NEXT:   cir.store %arg1, %[[VAL1_ADDR]]
// CHECK-NEXT:   cir.store %arg2, %[[VAL2_ADDR]]
// CHECK-NEXT:   cir.store %arg3, %[[VAL3_ADDR]]
// CHECK-NEXT:   %[[THIS:.*]] = cir.load{{.*}} %[[THIS_ADDR]]
// CHECK-NEXT:   %[[VAL1:.*]] = cir.load{{.*}} %[[VAL1_ADDR]]
// CHECK-NEXT:   %[[VAL2:.*]] = cir.load{{.*}} %[[VAL2_ADDR]]
// CHECK-NEXT:   %[[VAL3:.*]] = cir.load{{.*}} %[[VAL3_ADDR]]
// CHECK-NEXT:   cir.call @_ZN8Derived2C2Eiii(%[[THIS]], %[[VAL1]], %[[VAL2]], %[[VAL3]])
// CHECK-NEXT:   cir.return

// CHECK: cir.func{{.*}} @_Z13test_derived2v
// CHECK-NEXT:    %[[D_ADDR:.*]] = cir.alloca {{.*}} ["d", init]
// CHECK-NEXT:    %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CHECK-NEXT:    %[[TWO:.*]] = cir.const #cir.int<2> : !s32i
// CHECK-NEXT:    %[[THREE:.*]] = cir.const #cir.int<3> : !s32i
// CHECK-NEXT:    cir.call @_ZN8Derived2C1Eiii(%[[D_ADDR]], %[[ONE]], %[[TWO]], %[[THREE]])
// CHECK-NEXT:    cir.return