]> granicus.if.org Git - clang/commitdiff
[ms-cxxabi] Fix assert in unspecified inheritance memptr emission
authorReid Kleckner <reid@kleckner.net>
Tue, 15 Oct 2013 01:18:02 +0000 (01:18 +0000)
committerReid Kleckner <reid@kleckner.net>
Tue, 15 Oct 2013 01:18:02 +0000 (01:18 +0000)
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
test/CodeGenCXX/microsoft-abi-member-pointers.cpp

index fd677712e78d7ee9813965630b8d441c16eaad1d..9d59160cec8b20d63aa169e1965335463c1cb2a0 100644 (file)
@@ -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.
index ae41f3c391d7db5c0598c7bc76d74f4653190f10..c0dcd3cf831692ce33234a37b46996553ba66003 100644 (file)
@@ -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 {