diff options
author | Timur Iskhodzhanov <timurrrr@google.com> | 2013-10-09 18:16:58 +0000 |
---|---|---|
committer | Timur Iskhodzhanov <timurrrr@google.com> | 2013-10-09 18:16:58 +0000 |
commit | 5bd0d44c8da50f3a629c90fee92ce5cf1e31c9ff (patch) | |
tree | 7e57ad2e294edd4379c6788676ef669e12104b06 /test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp | |
parent | 45d3950e373412f395413c81a0310e8090508608 (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.cpp | 100 |
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 +} + +} |