summaryrefslogtreecommitdiffstats
path: root/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
diff options
context:
space:
mode:
authorTimur Iskhodzhanov <timurrrr@google.com>2013-10-09 18:16:58 +0000
committerTimur Iskhodzhanov <timurrrr@google.com>2013-10-09 18:16:58 +0000
commit5bd0d44c8da50f3a629c90fee92ce5cf1e31c9ff (patch)
tree7e57ad2e294edd4379c6788676ef669e12104b06 /test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
parent45d3950e373412f395413c81a0310e8090508608 (diff)
Initialize vtorDisp in class constructors and destructors
Reviewed at http://llvm-reviews.chandlerc.com/D1867 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@192312 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp')
-rw-r--r--test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp100
1 files changed, 93 insertions, 7 deletions
diff --git a/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp b/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
index 3805243c6a..b738aba80b 100644
--- a/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
+++ b/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
@@ -1,6 +1,10 @@
// RUN: %clang_cc1 %s -fno-rtti -cxx-abi microsoft -triple=i386-pc-win32 -emit-llvm -o - | FileCheck %s
+// For now, just make sure x86_64 doesn't crash.
+// RUN: %clang_cc1 %s -fno-rtti -cxx-abi microsoft -triple=x86_64-pc-win32 -emit-llvm -o %t
+
struct VBase {
+ virtual ~VBase();
virtual void foo();
virtual void bar();
int field;
@@ -8,27 +12,74 @@ struct VBase {
struct B : virtual VBase {
B();
+ virtual ~B();
virtual void foo();
virtual void bar();
};
B::B() {
- // CHECK: @"\01??0B@@QAE@XZ"
+ // CHECK-LABEL: define x86_thiscallcc %struct.B* @"\01??0B@@QAE@XZ"
// CHECK: %[[THIS:.*]] = load %struct.B**
// CHECK: br i1 %{{.*}}, label %[[INIT_VBASES:.*]], label %[[SKIP_VBASES:.*]]
+
+ // Don't check the INIT_VBASES case as it's covered by the ctor tests.
+
// CHECK: %[[SKIP_VBASES]]
// CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
// CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 0
+ // ...
+ // CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
+ // CHECK: %[[VFPTR_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 %{{.*}}
+ // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to [3 x i8*]**
+ // CHECK: store [3 x i8*]* @"\01??_7B@@6B@", [3 x i8*]** %[[VFPTR]]
+
+ // Initialize vtorDisp:
+ // CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
+ // CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 0
+ // ...
+ // CHECK: %[[VBASE_OFFSET:.*]] = add nsw i32 0, %{{.*}}
+ // CHECK: %[[VTORDISP_VAL:.*]] = sub i32 %[[VBASE_OFFSET]], 8
+ // CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
+ // CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 %[[VBASE_OFFSET]]
+ // CHECK: %[[VTORDISP_i8:.*]] = getelementptr i8* %[[VBASE_i8]], i32 -4
+ // CHECK: %[[VTORDISP_PTR:.*]] = bitcast i8* %[[VTORDISP_i8]] to i32*
+ // CHECK: store i32 %[[VTORDISP_VAL]], i32* %[[VTORDISP_PTR]]
+
+ // CHECK: ret
+}
+
+B::~B() {
+ // CHECK-LABEL: define x86_thiscallcc void @"\01??1B@@UAE@XZ"
+ // CHECK: %[[THIS:.*]] = load %struct.B**
+
+ // Restore the vfptr that could have been changed by a subclass.
+ // CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
+ // CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 0
+ // ...
// CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
// CHECK: %[[VFPTR_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 %{{.*}}
- // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to [2 x i8*]**
- // CHECK: store [2 x i8*]* @"\01??_7B@@6B@", [2 x i8*]** %[[VFPTR]]
- // FIXME: Should initialize the vtorDisp here.
+ // CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VFPTR_i8]] to [3 x i8*]**
+ // CHECK: store [3 x i8*]* @"\01??_7B@@6B@", [3 x i8*]** %[[VFPTR]]
+
+ // Initialize vtorDisp:
+ // CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
+ // CHECK: %[[VBPTR:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 0
+ // ...
+ // CHECK: %[[VBASE_OFFSET:.*]] = add nsw i32 0, %{{.*}}
+ // CHECK: %[[VTORDISP_VAL:.*]] = sub i32 %[[VBASE_OFFSET]], 8
+ // CHECK: %[[THIS_i8:.*]] = bitcast %struct.B* %[[THIS]] to i8*
+ // CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[THIS_i8]], i32 %[[VBASE_OFFSET]]
+ // CHECK: %[[VTORDISP_i8:.*]] = getelementptr i8* %[[VBASE_i8]], i32 -4
+ // CHECK: %[[VTORDISP_PTR:.*]] = bitcast i8* %[[VTORDISP_i8]] to i32*
+ // CHECK: store i32 %[[VTORDISP_VAL]], i32* %[[VTORDISP_PTR]]
+
+ foo(); // Avoid the "trivial destructor" optimization.
+
// CHECK: ret
}
void B::foo() {
-// CHECK: define x86_thiscallcc void @"\01?foo@B@@UAEXXZ"(i8*
+// CHECK-LABEL: define x86_thiscallcc void @"\01?foo@B@@UAEXXZ"(i8*
//
// B::foo gets 'this' cast to VBase* in ECX (i.e. this+8) so we
// need to adjust 'this' before use.
@@ -58,7 +109,7 @@ void B::foo() {
}
void call_vbase_bar(B *obj) {
-// CHECK: define void @"\01?call_vbase_bar@@YAXPAUB@@@Z"(%struct.B* %obj)
+// CHECK-LABEL: define void @"\01?call_vbase_bar@@YAXPAUB@@@Z"(%struct.B* %obj)
// CHECK: %[[OBJ:.*]] = load %struct.B
obj->bar();
@@ -76,7 +127,7 @@ void call_vbase_bar(B *obj) {
// CHECK: %[[VBASE_i8:.*]] = getelementptr inbounds i8* %[[OBJ_i8]], i32 %[[VBOFFSET]]
// CHECK: %[[VFPTR:.*]] = bitcast i8* %[[VBASE_i8]] to void (i8*)***
// CHECK: %[[VFTABLE:.*]] = load void (i8*)*** %[[VFPTR]]
-// CHECK: %[[VFUN:.*]] = getelementptr inbounds void (i8*)** %[[VFTABLE]], i64 1
+// CHECK: %[[VFUN:.*]] = getelementptr inbounds void (i8*)** %[[VFTABLE]], i64 2
// CHECK: %[[VFUN_VALUE:.*]] = load void (i8*)** %[[VFUN]]
//
// CHECK: %[[OBJ_i8:.*]] = bitcast %struct.B* %[[OBJ]] to i8*
@@ -101,3 +152,38 @@ struct C : B {
// Used to crash on an assertion.
C::C() {}
+
+namespace multiple_vbases {
+struct A {
+ virtual void a();
+};
+
+struct B {
+ virtual void b();
+};
+
+struct C {
+ virtual void c();
+};
+
+struct D : virtual A, virtual B, virtual C {
+ virtual void a();
+ virtual void b();
+ virtual void c();
+ D();
+};
+
+D::D() {
+ // CHECK-LABEL: define x86_thiscallcc %"struct.multiple_vbases::D"* @"\01??0D@multiple_vbases@@QAE@XZ"
+ // Just make sure we emit 3 vtordisps after initializing vfptrs.
+ // CHECK: store [1 x i8*]* @"\01??_7D@multiple_vbases@@6BA@1@@", [1 x i8*]** %{{.*}}
+ // CHECK: store [1 x i8*]* @"\01??_7D@multiple_vbases@@6BB@1@@", [1 x i8*]** %{{.*}}
+ // CHECK: store [1 x i8*]* @"\01??_7D@multiple_vbases@@6BC@1@@", [1 x i8*]** %{{.*}}
+ // ...
+ // CHECK: store i32 %{{.*}}, i32* %{{.*}}
+ // CHECK: store i32 %{{.*}}, i32* %{{.*}}
+ // CHECK: store i32 %{{.*}}, i32* %{{.*}}
+ // CHECK: ret
+}
+
+}