@@ -53,6 +53,7 @@ B::B() {
53
53
B::~B () {
54
54
// CHECK-LABEL: define dso_local x86_thiscallcc void @"??1B@@UAE@XZ"
55
55
// Store initial this:
56
+ // CHECK: %[[THIS:.*]] = alloca %struct.B*
56
57
// CHECK: %[[THIS_ADDR:.*]] = alloca %struct.B*
57
58
// CHECK: store %struct.B* %{{.*}}, %struct.B** %[[THIS_ADDR]], align 4
58
59
// Reload and adjust the this parameter:
@@ -90,15 +91,15 @@ B::~B() {
90
91
// CHECK2: %[[THIS:.*]] = load %struct.B*, %struct.B** {{.*}}
91
92
// CHECK2: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
92
93
// CHECK2: %[[B_i8:.*]] = getelementptr i8, i8* %[[THIS_i8]], i32 8
93
- // CHECK2: %[[B:.*]] = bitcast i8* %[[B_i8]] to %struct.B*
94
- // CHECK2: call x86_thiscallcc void @"??1B@@UAE@XZ"(%struct.B* {{[^,]*}} %[[B]])
94
+ // CHECK2: call x86_thiscallcc void @"??1B@@UAE@XZ"(i8*{{[^,]*}} %[[B_i8]])
95
95
// CHECK2: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
96
96
// CHECK2: %[[VBASE_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_i8]], i32 8
97
97
// CHECK2: %[[VBASE:.*]] = bitcast i8* %[[VBASE_i8]] to %struct.VBase*
98
98
// CHECK2: call x86_thiscallcc void @"??1VBase@@UAE@XZ"(%struct.VBase* {{[^,]*}} %[[VBASE]])
99
99
// CHECK2: ret
100
100
101
101
// CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc noundef i8* @"??_GB@@UAEPAXI@Z"
102
+ // CHECK2: store %struct.B* %{{.*}}, %struct.B** %[[THIS:.*]], align 4
102
103
// CHECK2: store %struct.B* %{{.*}}, %struct.B** %[[THIS_ADDR:.*]], align 4
103
104
// CHECK2: %[[THIS:.*]] = load %struct.B*, %struct.B** %[[THIS_ADDR]]
104
105
// CHECK2: %[[THIS_PARAM_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
@@ -195,8 +196,7 @@ void delete_B(B *obj) {
195
196
// CHECK: %[[VBENTRY:.*]] = getelementptr inbounds i32, i32* %[[VBTABLE]], i32 1
196
197
// CHECK: %[[VBOFFSET32:.*]] = load i32, i32* %[[VBENTRY]]
197
198
// CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]]
198
- // CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
199
- // CHECK: %[[VBASE:.*]] = bitcast i8* %[[VBASE_i8]] to %struct.B*
199
+ // CHECK: %[[VBASE:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
200
200
//
201
201
// CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8*
202
202
// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 0
@@ -206,12 +206,12 @@ void delete_B(B *obj) {
206
206
// CHECK: %[[VBOFFSET32:.*]] = load i32, i32* %[[VBENTRY]]
207
207
// CHECK: %[[VBOFFSET:.*]] = add nsw i32 0, %[[VBOFFSET32]]
208
208
// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
209
- // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VBASE_i8]] to i8* (%struct.B *, i32)***
210
- // CHECK: %[[VFTABLE:.*]] = load i8* (%struct.B *, i32)**, i8* (%struct.B *, i32)*** %[[VFPTR]]
211
- // CHECK: %[[VFUN:.*]] = getelementptr inbounds i8* (%struct.B *, i32)*, i8* (%struct.B *, i32)** %[[VFTABLE]], i64 0
212
- // CHECK: %[[VFUN_VALUE:.*]] = load i8* (%struct.B *, i32)*, i8* (%struct.B *, i32)** %[[VFUN]]
209
+ // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VBASE_i8]] to i8* (i8 *, i32)***
210
+ // CHECK: %[[VFTABLE:.*]] = load i8* (i8 *, i32)**, i8* (i8 *, i32)*** %[[VFPTR]]
211
+ // CHECK: %[[VFUN:.*]] = getelementptr inbounds i8* (i8 *, i32)*, i8* (i8 *, i32)** %[[VFTABLE]], i64 0
212
+ // CHECK: %[[VFUN_VALUE:.*]] = load i8* (i8 *, i32)*, i8* (i8 *, i32)** %[[VFUN]]
213
213
//
214
- // CHECK: call x86_thiscallcc noundef i8* %[[VFUN_VALUE]](%struct.B * {{[^,]*}} %[[VBASE]], i32 noundef 1)
214
+ // CHECK: call x86_thiscallcc noundef i8* %[[VFUN_VALUE]](i8 * {{[^,]*}} %[[VBASE]], i32 noundef 1)
215
215
// CHECK: ret void
216
216
}
217
217
@@ -295,8 +295,9 @@ struct D : virtual Z, B, C {
295
295
} d;
296
296
297
297
D::~D () {
298
- // CHECK-LABEL: define dso_local x86_thiscallcc void @"??1D@diamond@@UAE@XZ"(%"struct.diamond::D" *{{.*}})
298
+ // CHECK-LABEL: define dso_local x86_thiscallcc void @"??1D@diamond@@UAE@XZ"(i8 *{{.*}})
299
299
// Store initial this:
300
+ // CHECK: %[[THIS:.*]] = alloca %"struct.diamond::D"*
300
301
// CHECK: %[[THIS_ADDR:.*]] = alloca %"struct.diamond::D"*
301
302
// CHECK: store %"struct.diamond::D"* %{{.*}}, %"struct.diamond::D"** %[[THIS_ADDR]], align 4
302
303
//
@@ -310,16 +311,13 @@ D::~D() {
310
311
// CHECK: %[[C_i8:.*]] = getelementptr inbounds i8, i8* %[[D_i8]], i32 4
311
312
// CHECK: %[[C:.*]] = bitcast i8* %[[C_i8]] to %"struct.diamond::C"*
312
313
// CHECK: %[[C_i8:.*]] = bitcast %"struct.diamond::C"* %[[C]] to i8*
313
- // CHECK: %[[ARG_i8:.*]] = getelementptr i8, i8* %{{.*}}, i32 16
314
- // FIXME: We might consider changing the dtor this parameter type to i8*.
315
- // CHECK: %[[ARG:.*]] = bitcast i8* %[[ARG_i8]] to %"struct.diamond::C"*
316
- // CHECK: call x86_thiscallcc void @"??1C@diamond@@UAE@XZ"(%"struct.diamond::C"* {{[^,]*}} %[[ARG]])
314
+ // CHECK: %[[ARG:.*]] = getelementptr i8, i8* %{{.*}}, i32 16
315
+ // CHECK: call x86_thiscallcc void @"??1C@diamond@@UAE@XZ"(i8*{{[^,]*}} %[[ARG]])
317
316
318
317
// CHECK: %[[B:.*]] = bitcast %"struct.diamond::D"* %[[THIS]] to %"struct.diamond::B"*
319
318
// CHECK: %[[B_i8:.*]] = bitcast %"struct.diamond::B"* %[[B]] to i8*
320
- // CHECK: %[[ARG_i8:.*]] = getelementptr i8, i8* %[[B_i8]], i32 4
321
- // CHECK: %[[ARG:.*]] = bitcast i8* %[[ARG_i8]] to %"struct.diamond::B"*
322
- // CHECK: call x86_thiscallcc void @"??1B@diamond@@UAE@XZ"(%"struct.diamond::B"* {{[^,]*}} %[[ARG]])
319
+ // CHECK: %[[ARG:.*]] = getelementptr i8, i8* %[[B_i8]], i32 4
320
+ // CHECK: call x86_thiscallcc void @"??1B@diamond@@UAE@XZ"(i8*{{[^,]*}} %[[ARG]])
323
321
// CHECK: ret void
324
322
}
325
323
@@ -443,9 +441,10 @@ struct E : D, B, virtual A {
443
441
};
444
442
445
443
E::~E () {
446
- // CHECK-LABEL: define dso_local x86_thiscallcc void @"??1E@test4@@UAE@XZ"(%"struct.test4::E"* {{[^,]*}} %this)
444
+ // CHECK-LABEL: define dso_local x86_thiscallcc void @"??1E@test4@@UAE@XZ"(i8* {{[^,]*}} %this.coerce )
447
445
448
446
// In this case "this" points to the most derived class, so no GEPs needed.
447
+ // CHECK: bitcast i8* %this.coerce
449
448
// CHECK-NOT: getelementptr
450
449
// CHECK-NOT: bitcast
451
450
// CHECK: %[[VFPTR_i8:.*]] = bitcast %"struct.test4::E"* %{{.*}} to i32 (...)***
@@ -458,16 +457,14 @@ void destroy(E *obj) {
458
457
459
458
// CHECK-NOT: getelementptr
460
459
// CHECK: %[[OBJ_i8:.*]] = bitcast %"struct.test4::E"* %[[OBJ]] to i8*
461
- // CHECK: %[[B_i8:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 4
462
- // FIXME: in fact, the call should take i8* and the bitcast is redundant.
463
- // CHECK: %[[B_as_E:.*]] = bitcast i8* %[[B_i8]] to %"struct.test4::E"*
460
+ // CHECK: %[[THIS_i8:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 4
464
461
// CHECK: %[[OBJ_i8:.*]] = bitcast %"struct.test4::E"* %[[OBJ:.*]] to i8*
465
462
// CHECK: %[[B_i8:.*]] = getelementptr inbounds i8, i8* %[[OBJ_i8]], i32 4
466
- // CHECK: %[[VPTR:.*]] = bitcast i8* %[[B_i8]] to i8* (%"struct.test4::E" *, i32)***
467
- // CHECK: %[[VFTABLE:.*]] = load i8* (%"struct.test4::E" *, i32)**, i8* (%"struct.test4::E" *, i32)*** %[[VPTR]]
468
- // CHECK: %[[VFTENTRY:.*]] = getelementptr inbounds i8* (%"struct.test4::E" *, i32)*, i8* (%"struct.test4::E" *, i32)** %[[VFTABLE]], i64 0
469
- // CHECK: %[[VFUN:.*]] = load i8* (%"struct.test4::E" *, i32)*, i8* (%"struct.test4::E" *, i32)** %[[VFTENTRY]]
470
- // CHECK: call x86_thiscallcc noundef i8* %[[VFUN]](%"struct.test4::E"* {{[^,]*}} %[[B_as_E ]], i32 noundef 1)
463
+ // CHECK: %[[VPTR:.*]] = bitcast i8* %[[B_i8]] to i8* (i8 *, i32)***
464
+ // CHECK: %[[VFTABLE:.*]] = load i8* (i8 *, i32)**, i8* (i8 *, i32)*** %[[VPTR]]
465
+ // CHECK: %[[VFTENTRY:.*]] = getelementptr inbounds i8* (i8 *, i32)*, i8* (i8 *, i32)** %[[VFTABLE]], i64 0
466
+ // CHECK: %[[VFUN:.*]] = load i8* (i8 *, i32)*, i8* (i8 *, i32)** %[[VFTENTRY]]
467
+ // CHECK: call x86_thiscallcc noundef i8* %[[VFUN]](i8* {{[^,]*}} %[[THIS_i8 ]], i32 noundef 1)
471
468
delete obj;
472
469
}
473
470
@@ -549,9 +546,37 @@ struct B {
549
546
struct C : virtual B {};
550
547
struct D : virtual A, C {};
551
548
D d;
552
- // CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc noundef i8* @"??_GD@pr36921@@UAEPAXI@Z"(
553
- // CHECK: %[[THIS:.*]] = load %"struct.pr36921::D"*, %"struct.pr36921::D"**
554
- // CHECK: %[[THIS_UNADJ_i8:.*]] = bitcast %"struct.pr36921::D"* %[[THIS_RELOAD]] to i8*
555
- // CHECK: %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_UNADJ_i8]], i32 -4
556
- // CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_ADJ_i8]] to %"struct.pr36921::D"*
549
+ // CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc noundef i8* @"??_GD@pr36921@@UAEPAXI@Z"(
550
+ // CHECK2: %[[THIS:.*]] = load %"struct.pr36921::D"*, %"struct.pr36921::D"**
551
+ // CHECK2: %[[THIS_RELOAD:.*]] = load %"struct.pr36921::D"*, %"struct.pr36921::D"**
552
+ // CHECK2: %[[THIS_UNADJ_i8:.*]] = bitcast %"struct.pr36921::D"* %[[THIS_RELOAD]] to i8*
553
+ // CHECK2: %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_UNADJ_i8]], i32 -4
554
+ // CHECK2: %[[THIS:.*]] = bitcast i8* %[[THIS_ADJ_i8]] to %"struct.pr36921::D"*
555
+ }
556
+
557
+ namespace issue_60465 {
558
+ // We used to assume the first argument to all destructors was the derived type
559
+ // even when there was a 'this' adjustment.
560
+ struct A {
561
+ virtual ~A ();
562
+ };
563
+
564
+ struct alignas (2 * sizeof (void *)) B : virtual A {
565
+ ~B ();
566
+ void *x, *y;
567
+ };
568
+
569
+ B::~B () {
570
+ // The 'this' parameter should not have a type of %"struct.issue_60465::B"* and
571
+ // must not have 'align 8', since at least B's copy of A is only 'align 4'.
572
+ // CHECK-LABEL: define dso_local x86_thiscallcc void @"??1B@issue_60465@@UAE@XZ"(i8* noundef %this.coerce)
573
+ // CHECK: %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, i8* %{{.*}}, i32 -12
574
+ // CHECK: %[[THIS_ADJ:.*]] = bitcast i8* %[[THIS_ADJ_i8]] to %"struct.issue_60465::B"*
575
+ // CHECK: %[[X:.*]] = getelementptr inbounds %"struct.issue_60465::B", %"struct.issue_60465::B"* %[[THIS_ADJ]], i32 0, i32 1
576
+ // CHECK: store i8* null, i8** %[[X]], align 4
577
+ // CHECK: %[[Y:.*]] = getelementptr inbounds %"struct.issue_60465::B", %"struct.issue_60465::B"* %[[THIS_ADJ]], i32 0, i32 2
578
+ // CHECK: store i8* null, i8** %[[Y]], align 8
579
+ x = nullptr ;
580
+ y = nullptr ;
581
+ }
557
582
}
0 commit comments