From 42090d6d786accb3551097f0ef1f15d44713982c Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Tue, 15 Oct 2013 01:18:02 +0000 Subject: [PATCH] [ms-cxxabi] Fix assert in unspecified inheritance memptr emission If a class is using the unspecified inheritance model for member pointers and later we find the class is defined to use single inheritance, zero out the vbptr offset field of the member pointer when it is formed. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@192664 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MicrosoftCXXABI.cpp | 6 ++++-- test/CodeGenCXX/microsoft-abi-member-pointers.cpp | 11 +++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp index fd677712e7..9d59160cec 100644 --- a/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/lib/CodeGen/MicrosoftCXXABI.cpp @@ -1156,8 +1156,10 @@ MicrosoftCXXABI::EmitFullMemberPointer(llvm::Constant *FirstField, CGM.IntTy, NonVirtualBaseAdjustment.getQuantity())); if (hasVBPtrOffsetField(Inheritance)) { - fields.push_back(llvm::ConstantInt::get( - CGM.IntTy, GetVBPtrOffsetFromBases(RD).getQuantity())); + CharUnits Offs = CharUnits::Zero(); + if (RD->getNumVBases()) + Offs = GetVBPtrOffsetFromBases(RD); + fields.push_back(llvm::ConstantInt::get(CGM.IntTy, Offs.getQuantity())); } // The rest of the fields are adjusted by conversions to a more derived class. diff --git a/test/CodeGenCXX/microsoft-abi-member-pointers.cpp b/test/CodeGenCXX/microsoft-abi-member-pointers.cpp index ae41f3c391..c0dcd3cf83 100644 --- a/test/CodeGenCXX/microsoft-abi-member-pointers.cpp +++ b/test/CodeGenCXX/microsoft-abi-member-pointers.cpp @@ -42,6 +42,7 @@ struct NonZeroVBPtr : POD, Virtual { }; struct Unspecified; +struct UnspecSingle; // Check that we can lower the LLVM types and get the null initializers right. int Single ::*s_d_memptr; @@ -50,6 +51,7 @@ int Multiple ::*m_d_memptr; int Virtual ::*v_d_memptr; int NonZeroVBPtr::*n_d_memptr; int Unspecified::*u_d_memptr; +int UnspecSingle::*us_d_memptr; // CHECK: @"\01?s_d_memptr@@3PQSingle@@HQ1@" = global i32 -1, align 4 // CHECK: @"\01?p_d_memptr@@3PQPolymorphic@@HQ1@" = global i32 0, align 4 // CHECK: @"\01?m_d_memptr@@3PQMultiple@@HQ1@" = global i32 -1, align 4 @@ -59,6 +61,8 @@ int Unspecified::*u_d_memptr; // CHECK: { i32 0, i32 -1 }, align 4 // CHECK: @"\01?u_d_memptr@@3PQUnspecified@@HQ1@" = global { i32, i32, i32 } // CHECK: { i32 0, i32 0, i32 -1 }, align 4 +// CHECK: @"\01?us_d_memptr@@3PQUnspecSingle@@HQ1@" = global { i32, i32, i32 } +// CHECK: { i32 0, i32 0, i32 -1 }, align 4 void (Single ::*s_f_memptr)(); void (Multiple::*m_f_memptr)(); @@ -73,12 +77,17 @@ struct Unspecified : Multiple, Virtual { int u; }; +struct UnspecSingle { + void foo(); +}; + // Test memptr emission in a constant expression. namespace Const { void (Single ::*s_f_mp)() = &Single::foo; void (Multiple ::*m_f_mp)() = &B2::foo; void (Virtual ::*v_f_mp)() = &Virtual::foo; void (Unspecified::*u_f_mp)() = &Unspecified::foo; +void (UnspecSingle::*us_f_mp)() = &UnspecSingle::foo; // CHECK: @"\01?s_f_mp@Const@@3P8Single@@AEXXZQ2@" = // CHECK: global i8* bitcast ({{.*}} @"\01?foo@Single@@QAEXXZ" to i8*), align 4 // CHECK: @"\01?m_f_mp@Const@@3P8Multiple@@AEXXZQ2@" = @@ -87,6 +96,8 @@ void (Unspecified::*u_f_mp)() = &Unspecified::foo; // CHECK: global { i8*, i32, i32 } { i8* bitcast ({{.*}} @"\01?foo@Virtual@@QAEXXZ" to i8*), i32 0, i32 0 }, align 4 // CHECK: @"\01?u_f_mp@Const@@3P8Unspecified@@AEXXZQ2@" = // CHECK: global { i8*, i32, i32, i32 } { i8* bitcast ({{.*}} @"\01?foo@Unspecified@@QAEXXZ" to i8*), i32 0, i32 12, i32 0 }, align 4 +// CHECK: @"\01?us_f_mp@Const@@3P8UnspecSingle@@AEXXZQ2@" = +// CHECK: global { i8*, i32, i32, i32 } { i8* bitcast ({{.*}} @"\01?foo@UnspecSingle@@QAEXXZ" to i8*), i32 0, i32 0, i32 0 }, align 4 } namespace CastParam { -- 2.40.0