From: Reid Kleckner Date: Tue, 15 Oct 2013 01:18:02 +0000 (+0000) Subject: [ms-cxxabi] Fix assert in unspecified inheritance memptr emission X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=42090d6d786accb3551097f0ef1f15d44713982c;p=clang [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 --- 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 {