[PATCH] Fix PR19408 -- Missing static this adjustment in a vtordisp thunk

Timur Iskhodzhanov timurrrr at google.com
Wed Apr 16 06:53:05 PDT 2014


Hi rnk,

http://reviews.llvm.org/D3400

Files:
  lib/AST/VTableBuilder.cpp
  test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp

Index: lib/AST/VTableBuilder.cpp
===================================================================
--- lib/AST/VTableBuilder.cpp
+++ lib/AST/VTableBuilder.cpp
@@ -2734,9 +2734,22 @@
 
   const CXXRecordDecl *OverriderVBase =
       ComputeBaseOffset(Context, OverriderRD, MostDerivedClass).VirtualBase;
-  if (!OverriderVBase || OverriderVBase == WhichVFPtr.getVBaseWithVPtr())
+  if (OverriderVBase == WhichVFPtr.getVBaseWithVPtr())
     return;
 
+  if (!OverriderVBase) {
+    MethodVFTableLocation ML = VTables.getMethodVFTableLocation(Overrider.Method);
+    assert(ML.VBase && "why would we need a vtordisp if we can call the method "
+                       "without a vfptr of a vbase?");
+    // We need to offset the this parameter if the offset of the vbase is
+    // different between the overrider class and the most derived class.
+    const ASTRecordLayout &OverriderRDLayout =
+        Context.getASTRecordLayout(OverriderRD);
+    TA.NonVirtual = (OverriderRDLayout.getVBaseClassOffset(ML.VBase) +
+                     ML.VFPtrOffset - ThisOffset).getQuantity();
+    return;
+  }
+
   // Otherwise, we need to do use the dynamic offset of the final overrider
   // in order to get "this" adjustment right.
   TA.Virtual.Microsoft.VBPtrOffset =
Index: test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp
===================================================================
--- test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp
+++ test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp
@@ -355,6 +355,40 @@
 void use(A *obj) { delete obj; }
 }
 
+namespace pr19408 {
+// In this test, the vptr used to vcall D::f() is located in the A vbase.
+// The offset of A in different in C and D, so the D vtordisp thunk should
+// adjust "this" so C::f gets the right value.
+struct A {
+  A();
+  virtual void f();
+  int a;
+};
+
+struct B : virtual A {
+  B();
+  int b;
+};
+
+struct C : B {
+  C();
+  virtual void f();
+  int c;
+};
+
+struct D : C {
+  // CHECK-LABEL: VFTable for 'pr19408::A' in 'pr19408::B' in 'pr19408::C' in 'pr19408::D' (1 entry).
+  // CHECK-NEXT:   0 | void pr19408::C::f()
+  // CHECK-NEXT:       [this adjustment: vtordisp at -4, -4 non-virtual]
+
+  // MANGLING-DAG: @"\01?f at C@pr19408@@$4PPPPPPPM at 3AEXXZ"
+  D();
+  int d;
+};
+
+D::D() {}
+}
+
 namespace access {
 struct A {
   virtual ~A();
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D3400.1.patch
Type: text/x-patch
Size: 2398 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140416/1443834c/attachment.bin>


More information about the cfe-commits mailing list