lebedev.ri updated this revision to Diff 339757.
lebedev.ri added a comment.

@rsmith i was able to make some forward progress here.
What do you think about this?

(I haven't updated all tests because i don't want to waste hours doing that if 
this is still wrong)


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D100388/new/

https://reviews.llvm.org/D100388

Files:
  clang/include/clang/AST/VTableBuilder.h
  clang/include/clang/Basic/ABI.h
  clang/include/clang/Basic/Thunk.h
  clang/lib/AST/ItaniumMangle.cpp
  clang/lib/AST/MicrosoftMangle.cpp
  clang/lib/AST/VTableBuilder.cpp
  clang/lib/CodeGen/CGVTables.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/MicrosoftCXXABI.cpp
  clang/test/CodeGen/available-externally-hidden.cpp
  clang/test/CodeGenCXX/RelativeVTablesABI/diamond-inheritance.cpp
  clang/test/CodeGenCXX/RelativeVTablesABI/multiple-inheritance.cpp
  clang/test/CodeGenCXX/thunk-linkonce-odr.cpp
  clang/test/CodeGenCXX/thunk-returning-memptr.cpp
  clang/test/CodeGenCXX/thunk-wrong-return-type.cpp
  clang/test/CodeGenCXX/thunk-wrong-this.cpp
  clang/test/CodeGenCXX/thunks.cpp

Index: clang/test/CodeGenCXX/thunks.cpp
===================================================================
--- clang/test/CodeGenCXX/thunks.cpp
+++ clang/test/CodeGenCXX/thunks.cpp
@@ -410,7 +410,7 @@
   // CHECK: getelementptr inbounds i8, i8* {{.*}}, i64 -32
   // CHECK: getelementptr inbounds i8, i8* {{.*}}, i64 -24
   // CHECK: getelementptr inbounds i8, i8* {{.*}}, i64 8
-  // CHECK: ret %"struct.Test13::D"*
+  // CHECK: ret %"struct.Test13::B1"*
 
   // WIN64-LABEL: define weak_odr dso_local nonnull align 8 dereferenceable(8) %"struct.Test13::D"* @"?foo1@D@Test13@@$4PPPPPPPE@A@EAAAEAUB1@2@XZ"(
   //    This adjustment.
Index: clang/test/CodeGenCXX/thunk-wrong-this.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenCXX/thunk-wrong-this.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -emit-llvm-only -triple %itanium_abi_triple %s -emit-llvm -o - %s | FileCheck %s
+
+class Base1 {
+  virtual void Foo1();
+};
+
+class Base2 {
+  virtual void Foo2();
+};
+
+class alignas(16) Obj : public Base1, public Base2 {
+  void Foo1() override;
+  void Foo2() override;
+  ~Obj();
+};
+
+void Obj::Foo1() {}
+void Obj::Foo2() {}
+
+// CHECK: define dso_local void @_ZThn8_N3Obj4Foo2Ev(%class.Base2.2* nonnull dereferenceable(8) %this) #1 align 2 {
+// CHECK: tail call void @_ZN3Obj4Foo2Ev(%class.Obj.0* nonnull dereferenceable(16) %3)
Index: clang/test/CodeGenCXX/thunk-wrong-return-type.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenCXX/thunk-wrong-return-type.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -emit-llvm-only -triple %itanium_abi_triple %s -emit-llvm -o - %s | FileCheck %s
+
+struct A {};
+struct alignas(32) B : virtual A {
+  char c[32];
+};
+struct Pad {
+  char c[7];
+};
+struct C : B, Pad, virtual A {};
+
+struct X {
+  virtual A &f();
+};
+struct U {
+  virtual ~U();
+};
+C c;
+struct Y : U, X {
+  virtual B &f() override { return c; }
+};
+
+Y y;
+
+// CHECK: define linkonce_odr nonnull align 1 dereferenceable(1) %struct.A.8* @_ZTchn8_v0_n24_N1Y1fEv(%struct.X.7* nonnull dereferenceable(8) %this.coerce) #1 comdat align 2 {
Index: clang/test/CodeGenCXX/thunk-returning-memptr.cpp
===================================================================
--- clang/test/CodeGenCXX/thunk-returning-memptr.cpp
+++ clang/test/CodeGenCXX/thunk-returning-memptr.cpp
@@ -23,5 +23,5 @@
 // Because of the tail call, the return value cannot be copied into a local
 // alloca. (PR39901)
 
-// CHECK-LABEL: define linkonce_odr void @_ZThn4_N1C1fEv({ i32, i32 }* noalias sret({ i32, i32 }) align 4 %agg.result, %struct.C* {{[^,]*}} %this)
+// CHECK-LABEL: define linkonce_odr void @_ZThn4_N1C1fEv({ i32, i32 }* noalias sret({ i32, i32 }) align 4 %agg.result, %struct.B* {{[^,]*}} %this.coerce)
 // CHECK: tail call void @_ZN1C1fEv({ i32, i32 }* sret({ i32, i32 }) align 4 %agg.result
Index: clang/test/CodeGenCXX/thunk-linkonce-odr.cpp
===================================================================
--- clang/test/CodeGenCXX/thunk-linkonce-odr.cpp
+++ clang/test/CodeGenCXX/thunk-linkonce-odr.cpp
@@ -29,5 +29,5 @@
 
 // Thunks should be marked as "linkonce ODR" not "weak".
 //
-// CHECK: define linkonce_odr i32 @_ZThn{{[48]}}_N1D1fEv
 // CHECK: define linkonce_odr i32 @_ZThn{{[48]}}_N1C1fEv
+// CHECK: define linkonce_odr i32 @_ZThn{{[48]}}_N1D1fEv
Index: clang/test/CodeGenCXX/RelativeVTablesABI/multiple-inheritance.cpp
===================================================================
--- clang/test/CodeGenCXX/RelativeVTablesABI/multiple-inheritance.cpp
+++ clang/test/CodeGenCXX/RelativeVTablesABI/multiple-inheritance.cpp
@@ -9,7 +9,7 @@
 // VTable for C contains 2 sub-vtables (represented as 2 structs). The first contains the components for B and the second contains the components for C. The RTTI ptr in both arrays still point to the RTTI struct for C.
 // The component for bar() instead points to a thunk which redirects to C::bar() which overrides B::bar().
 // Now that we have a class with 2 parents, the offset to top in the second array is non-zero.
-// CHECK: @_ZTV1C.local = private unnamed_addr constant { [4 x i32], [3 x i32] } { [4 x i32] [i32 0, i32 trunc (i64 sub (i64 ptrtoint ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64 }** @_ZTI1C.rtti_proxy to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [4 x i32], [3 x i32] }, { [4 x i32], [3 x i32] }* @_ZTV1C.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.C*)* dso_local_equivalent @_ZN1C3fooEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [4 x i32], [3 x i32] }, { [4 x i32], [3 x i32] }* @_ZTV1C.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.C*)* dso_local_equivalent @_ZN1C3barEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [4 x i32], [3 x i32] }, { [4 x i32], [3 x i32] }* @_ZTV1C.local, i32 0, i32 0, i32 2) to i64)) to i32)], [3 x i32] [i32 -8, i32 trunc (i64 sub (i64 ptrtoint ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64 }** @_ZTI1C.rtti_proxy to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [4 x i32], [3 x i32] }, { [4 x i32], [3 x i32] }* @_ZTV1C.local, i32 0, i32 1, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.C*)* dso_local_equivalent @_ZThn8_N1C3barEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [4 x i32], [3 x i32] }, { [4 x i32], [3 x i32] }* @_ZTV1C.local, i32 0, i32 1, i32 2) to i64)) to i32)] }, align 4
+// CHECK: @_ZTV1C.local = private unnamed_addr constant { [4 x i32], [3 x i32] } { [4 x i32] [i32 0, i32 trunc (i64 sub (i64 ptrtoint ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64 }** @_ZTI1C.rtti_proxy to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [4 x i32], [3 x i32] }, { [4 x i32], [3 x i32] }* @_ZTV1C.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.C*)* dso_local_equivalent @_ZN1C3fooEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [4 x i32], [3 x i32] }, { [4 x i32], [3 x i32] }* @_ZTV1C.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.C*)* dso_local_equivalent @_ZN1C3barEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [4 x i32], [3 x i32] }, { [4 x i32], [3 x i32] }* @_ZTV1C.local, i32 0, i32 0, i32 2) to i64)) to i32)], [3 x i32] [i32 -8, i32 trunc (i64 sub (i64 ptrtoint ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64 }** @_ZTI1C.rtti_proxy to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [4 x i32], [3 x i32] }, { [4 x i32], [3 x i32] }* @_ZTV1C.local, i32 0, i32 1, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.B*)* dso_local_equivalent @_ZThn8_N1C3barEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [4 x i32], [3 x i32] }, { [4 x i32], [3 x i32] }* @_ZTV1C.local, i32 0, i32 1, i32 2) to i64)) to i32)] }, align 4
 
 // CHECK: @_ZTV1C ={{.*}} unnamed_addr alias { [4 x i32], [3 x i32] }, { [4 x i32], [3 x i32] }* @_ZTV1C.local
 
Index: clang/test/CodeGenCXX/RelativeVTablesABI/diamond-inheritance.cpp
===================================================================
--- clang/test/CodeGenCXX/RelativeVTablesABI/diamond-inheritance.cpp
+++ clang/test/CodeGenCXX/RelativeVTablesABI/diamond-inheritance.cpp
@@ -18,7 +18,7 @@
 // vtable contains 2 inner vtables:
 // - 1st table containing D::foo(), B::barB(), and D::baz().
 // - 2nd table containing a thunk to D::foo() and C::barC().
-// CHECK: @_ZTV1D.local = private unnamed_addr constant { [5 x i32], [4 x i32] } { [5 x i32] [i32 0, i32 trunc (i64 sub (i64 ptrtoint ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64 }** @_ZTI1D.rtti_proxy to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [5 x i32], [4 x i32] }, { [5 x i32], [4 x i32] }* @_ZTV1D.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.D*)* dso_local_equivalent @_ZN1D3fooEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [5 x i32], [4 x i32] }, { [5 x i32], [4 x i32] }* @_ZTV1D.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.B*)* dso_local_equivalent @_ZN1B4barBEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [5 x i32], [4 x i32] }, { [5 x i32], [4 x i32] }* @_ZTV1D.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.D*)* dso_local_equivalent @_ZN1D3bazEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [5 x i32], [4 x i32] }, { [5 x i32], [4 x i32] }* @_ZTV1D.local, i32 0, i32 0, i32 2) to i64)) to i32)], [4 x i32] [i32 -8, i32 trunc (i64 sub (i64 ptrtoint ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64 }** @_ZTI1D.rtti_proxy to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [5 x i32], [4 x i32] }, { [5 x i32], [4 x i32] }* @_ZTV1D.local, i32 0, i32 1, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.D*)* dso_local_equivalent @_ZThn8_N1D3fooEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [5 x i32], [4 x i32] }, { [5 x i32], [4 x i32] }* @_ZTV1D.local, i32 0, i32 1, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.C*)* dso_local_equivalent @_ZN1C4barCEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [5 x i32], [4 x i32] }, { [5 x i32], [4 x i32] }* @_ZTV1D.local, i32 0, i32 1, i32 2) to i64)) to i32)] }, align 4
+// CHECK: @_ZTV1D.local = private unnamed_addr constant { [5 x i32], [4 x i32] } { [5 x i32] [i32 0, i32 trunc (i64 sub (i64 ptrtoint ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64 }** @_ZTI1D.rtti_proxy to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [5 x i32], [4 x i32] }, { [5 x i32], [4 x i32] }* @_ZTV1D.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.D*)* dso_local_equivalent @_ZN1D3fooEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [5 x i32], [4 x i32] }, { [5 x i32], [4 x i32] }* @_ZTV1D.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.B*)* dso_local_equivalent @_ZN1B4barBEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [5 x i32], [4 x i32] }, { [5 x i32], [4 x i32] }* @_ZTV1D.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.D*)* dso_local_equivalent @_ZN1D3bazEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [5 x i32], [4 x i32] }, { [5 x i32], [4 x i32] }* @_ZTV1D.local, i32 0, i32 0, i32 2) to i64)) to i32)], [4 x i32] [i32 -8, i32 trunc (i64 sub (i64 ptrtoint ({ i8*, i8*, i32, i32, i8*, i64, i8*, i64 }** @_ZTI1D.rtti_proxy to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [5 x i32], [4 x i32] }, { [5 x i32], [4 x i32] }* @_ZTV1D.local, i32 0, i32 1, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.A*)* dso_local_equivalent @_ZThn8_N1D3fooEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [5 x i32], [4 x i32] }, { [5 x i32], [4 x i32] }* @_ZTV1D.local, i32 0, i32 1, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.C*)* dso_local_equivalent @_ZN1C4barCEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [5 x i32], [4 x i32] }, { [5 x i32], [4 x i32] }* @_ZTV1D.local, i32 0, i32 1, i32 2) to i64)) to i32)] }, align 4
 
 // @_ZTV1B ={{.*}} unnamed_addr alias { [4 x i32] }, { [4 x i32] }* @_ZTV1B.local
 // @_ZTV1C ={{.*}} unnamed_addr alias { [4 x i32] }, { [4 x i32] }* @_ZTV1C.local
Index: clang/test/CodeGen/available-externally-hidden.cpp
===================================================================
--- clang/test/CodeGen/available-externally-hidden.cpp
+++ clang/test/CodeGen/available-externally-hidden.cpp
@@ -21,6 +21,7 @@
 class SyncMessageFilter : public Filter, public Sender {
  public:
   bool Send(Message* message) override;
+  // expected-error@-1 {{cannot compile this thunk for forward declaration yet}}
 };
 
 class TestSyncMessageFilter : public SyncMessageFilter {
Index: clang/lib/CodeGen/MicrosoftCXXABI.cpp
===================================================================
--- clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -2084,7 +2084,7 @@
     CGF.Builder.CreateAlignedLoad(ThunkTy->getPointerTo(), VFuncPtr,
                                   CGF.getPointerAlign());
 
-  CGF.EmitMustTailThunk(MD, getThisValue(CGF), {ThunkTy, Callee});
+  CGF.EmitMustTailThunk(MD, getThisValue(CGF), FnInfo, {ThunkTy, Callee});
 
   return ThunkFn;
 }
Index: clang/lib/CodeGen/CodeGenFunction.h
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.h
+++ clang/lib/CodeGen/CodeGenFunction.h
@@ -2170,18 +2170,21 @@
                   const CGFunctionInfo &FnInfo, bool IsUnprototyped);
 
   void EmitCallAndReturnForThunk(llvm::FunctionCallee Callee,
-                                 const ThunkInfo *Thunk, bool IsUnprototyped);
+                                 const CGFunctionInfo &CalleeFnInfo,
+                                 GlobalDecl CalleeGD, const ThunkInfo *Thunk,
+                                 bool IsUnprototyped);
 
   void FinishThunk();
 
   /// Emit a musttail call for a thunk with a potentially adjusted this pointer.
-  void EmitMustTailThunk(GlobalDecl GD, llvm::Value *AdjustedThisPtr,
+  void EmitMustTailThunk(GlobalDecl CalleeGD, llvm::Value *AdjustedThisPtr,
+                         const CGFunctionInfo &CalleeFnInfo,
                          llvm::FunctionCallee Callee);
 
   /// Generate a thunk for the given method.
-  void generateThunk(llvm::Function *Fn, const CGFunctionInfo &FnInfo,
-                     GlobalDecl GD, const ThunkInfo &Thunk,
-                     bool IsUnprototyped);
+  void generateThunk(llvm::Function *ThunkFn, const CGFunctionInfo &ThunkFnInfo,
+                     GlobalDecl ThunkGD, GlobalDecl CalleeGD,
+                     const ThunkInfo &Thunk, bool IsUnprototyped);
 
   llvm::Function *GenerateVarArgsThunk(llvm::Function *Fn,
                                        const CGFunctionInfo &FnInfo,
Index: clang/lib/CodeGen/CGVTables.cpp
===================================================================
--- clang/lib/CodeGen/CGVTables.cpp
+++ clang/lib/CodeGen/CGVTables.cpp
@@ -163,8 +163,12 @@
 
   // Get the original function
   assert(FnInfo.isVariadic());
-  llvm::Type *Ty = CGM.getTypes().GetFunctionType(FnInfo);
-  llvm::Value *Callee = CGM.GetAddrOfFunction(GD, Ty, /*ForVTable=*/true);
+
+  const CGFunctionInfo &CalleeFnInfo =
+      CGM.getTypes().arrangeGlobalDeclaration(GD);
+  llvm::FunctionType *CalleeFnTy = CGM.getTypes().GetFunctionType(CalleeFnInfo);
+  llvm::Constant *Callee =
+      CGM.GetAddrOfFunction(GD, CalleeFnTy, /*ForVTable=*/true);
   llvm::Function *BaseFn = cast<llvm::Function>(Callee);
 
   // Cloning can't work if we don't have a definition. The Microsoft ABI may
@@ -183,7 +187,7 @@
   // Ensure that the value mapper does not encounter any of them.
   resolveTopLevelMetadata(BaseFn, VMap);
   llvm::Function *NewFn = llvm::CloneFunction(BaseFn, VMap);
-  Fn->replaceAllUsesWith(NewFn);
+  Fn->replaceAllUsesWith(llvm::ConstantExpr::getBitCast(NewFn, Fn->getType()));
   NewFn->takeName(Fn);
   Fn->eraseFromParent();
   Fn = NewFn;
@@ -289,9 +293,9 @@
   FinishFunction();
 }
 
-void CodeGenFunction::EmitCallAndReturnForThunk(llvm::FunctionCallee Callee,
-                                                const ThunkInfo *Thunk,
-                                                bool IsUnprototyped) {
+void CodeGenFunction::EmitCallAndReturnForThunk(
+    llvm::FunctionCallee Callee, const CGFunctionInfo &CalleeFnInfo,
+    GlobalDecl CalleeGD, const ThunkInfo *Thunk, bool IsUnprototyped) {
   assert(isa<CXXMethodDecl>(CurGD.getDecl()) &&
          "Please use a new CGF for this thunk");
   const CXXMethodDecl *MD = cast<CXXMethodDecl>(CurGD.getDecl());
@@ -317,14 +321,15 @@
         CGM.ErrorUnsupported(
             MD, "non-trivial argument copy for return-adjusting thunk");
     }
-    EmitMustTailThunk(CurGD, AdjustedThisPtr, Callee);
+    EmitMustTailThunk(CalleeGD, AdjustedThisPtr, CalleeFnInfo, Callee);
     return;
   }
 
   // Start building CallArgs.
   CallArgList CallArgs;
-  QualType ThisType = MD->getThisType();
-  CallArgs.add(RValue::get(AdjustedThisPtr), ThisType);
+  QualType CalleeThisType =
+      cast<CXXMethodDecl>(CalleeGD.getDecl())->getThisType();
+  CallArgs.add(RValue::get(AdjustedThisPtr), CalleeThisType);
 
   if (isa<CXXDestructorDecl>(MD))
     CGM.getCXXABI().adjustCallArgsForDestructorThunk(*this, CurGD, CallArgs);
@@ -356,11 +361,10 @@
 #endif
 
   // Determine whether we have a return value slot to use.
-  QualType ResultType = CGM.getCXXABI().HasThisReturn(CurGD)
-                            ? ThisType
-                            : CGM.getCXXABI().hasMostDerivedReturn(CurGD)
-                                  ? CGM.getContext().VoidPtrTy
-                                  : FPT->getReturnType();
+  QualType ResultType = CGM.getCXXABI().HasThisReturn(CurGD) ? CalleeThisType
+                        : CGM.getCXXABI().hasMostDerivedReturn(CurGD)
+                            ? CGM.getContext().VoidPtrTy
+                            : FPT->getReturnType();
   ReturnValueSlot Slot;
   if (!ResultType->isVoidType() &&
       (CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect ||
@@ -370,8 +374,8 @@
 
   // Now emit our call.
   llvm::CallBase *CallOrInvoke;
-  RValue RV = EmitCall(*CurFnInfo, CGCallee::forDirect(Callee, CurGD), Slot,
-                       CallArgs, &CallOrInvoke);
+  RValue RV = EmitCall(CalleeFnInfo, CGCallee::forDirect(Callee, CalleeGD),
+                       Slot, CallArgs, &CallOrInvoke);
 
   // Consider return adjustment if we have ThunkInfo.
   if (Thunk && !Thunk->Return.isEmpty())
@@ -380,8 +384,12 @@
     Call->setTailCallKind(llvm::CallInst::TCK_Tail);
 
   // Emit return.
-  if (!ResultType->isVoidType() && Slot.isNull())
+  if (!ResultType->isVoidType() && Slot.isNull()) {
+    if (RV.getScalarVal())
+      RV = RValue::get(
+          Builder.CreateBitCast(RV.getScalarVal(), CurFn->getReturnType()));
     CGM.getCXXABI().EmitReturnFromThunk(*this, RV, ResultType);
+  }
 
   // Disable the final ARC autorelease.
   AutoreleaseResult = false;
@@ -389,8 +397,9 @@
   FinishThunk();
 }
 
-void CodeGenFunction::EmitMustTailThunk(GlobalDecl GD,
+void CodeGenFunction::EmitMustTailThunk(GlobalDecl CalleeGD,
                                         llvm::Value *AdjustedThisPtr,
+                                        const CGFunctionInfo &CalleeFnInfo,
                                         llvm::FunctionCallee Callee) {
   // Emitting a musttail call thunk doesn't use any of the CGCall.cpp machinery
   // to translate AST arguments into LLVM IR arguments.  For thunks, we know
@@ -401,11 +410,11 @@
     Args.push_back(&A);
 
   // Set the adjusted 'this' pointer.
-  const ABIArgInfo &ThisAI = CurFnInfo->arg_begin()->info;
+  const ABIArgInfo &ThisAI = CalleeFnInfo.arg_begin()->info;
   if (ThisAI.isDirect()) {
-    const ABIArgInfo &RetAI = CurFnInfo->getReturnInfo();
+    const ABIArgInfo &RetAI = CalleeFnInfo.getReturnInfo();
     int ThisArgNo = RetAI.isIndirect() && !RetAI.isSRetAfterThis() ? 1 : 0;
-    llvm::Type *ThisType = Args[ThisArgNo]->getType();
+    llvm::Type *ThisType = Callee.getFunctionType()->getParamType(ThisArgNo);
     if (ThisType != AdjustedThisPtr->getType())
       AdjustedThisPtr = Builder.CreateBitCast(AdjustedThisPtr, ThisType);
     Args[ThisArgNo] = AdjustedThisPtr;
@@ -426,15 +435,16 @@
   // Apply the standard set of call attributes.
   unsigned CallingConv;
   llvm::AttributeList Attrs;
-  CGM.ConstructAttributeList(Callee.getCallee()->getName(), *CurFnInfo, GD,
-                             Attrs, CallingConv, /*AttrOnCallSite=*/true);
+  CGM.ConstructAttributeList(Callee.getCallee()->getName(), CalleeFnInfo,
+                             CalleeGD, Attrs, CallingConv,
+                             /*AttrOnCallSite=*/true);
   Call->setAttributes(Attrs);
   Call->setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv));
 
   if (Call->getType()->isVoidTy())
     Builder.CreateRetVoid();
   else
-    Builder.CreateRet(Call);
+    Builder.CreateRet(Builder.CreateBitCast(Call, CurFn->getReturnType()));
 
   // Finish the function to maintain CodeGenFunction invariants.
   // FIXME: Don't emit unreachable code.
@@ -443,31 +453,34 @@
   FinishThunk();
 }
 
-void CodeGenFunction::generateThunk(llvm::Function *Fn,
-                                    const CGFunctionInfo &FnInfo, GlobalDecl GD,
+void CodeGenFunction::generateThunk(llvm::Function *ThunkFn,
+                                    const CGFunctionInfo &ThunkFnInfo,
+                                    GlobalDecl ThunkGD, GlobalDecl CalleeGD,
                                     const ThunkInfo &Thunk,
                                     bool IsUnprototyped) {
-  StartThunk(Fn, GD, FnInfo, IsUnprototyped);
+  StartThunk(ThunkFn, ThunkGD, ThunkFnInfo, IsUnprototyped);
   // Create a scope with an artificial location for the body of this function.
   auto AL = ApplyDebugLocation::CreateArtificial(*this);
 
-  // Get our callee. Use a placeholder type if this method is unprototyped so
-  // that CodeGenModule doesn't try to set attributes.
-  llvm::Type *Ty;
-  if (IsUnprototyped)
-    Ty = llvm::StructType::get(getLLVMContext());
-  else
-    Ty = CGM.getTypes().GetFunctionType(FnInfo);
+  auto *CalleeMD = cast<CXXMethodDecl>(CalleeGD.getDecl());
+  if (!CalleeMD->isDefined()) {
+    CGM.ErrorUnsupported(ThunkGD.getDecl(), "thunk for forward declaration");
+    return;
+  }
 
-  llvm::Constant *Callee = CGM.GetAddrOfFunction(GD, Ty, /*ForVTable=*/true);
+  const CGFunctionInfo &CalleeFnInfo =
+      CGM.getTypes().arrangeGlobalDeclaration(CalleeGD);
+  llvm::FunctionType *CalleeFnTy = CGM.getTypes().GetFunctionType(CalleeFnInfo);
+  llvm::Constant *Callee =
+      CGM.GetAddrOfFunction(CalleeGD, CalleeFnTy, /*ForVTable=*/true);
 
   // Fix up the function type for an unprototyped musttail call.
   if (IsUnprototyped)
-    Callee = llvm::ConstantExpr::getBitCast(Callee, Fn->getType());
+    Callee = llvm::ConstantExpr::getBitCast(Callee, CalleeFnTy);
 
   // Make the call and return the result.
-  EmitCallAndReturnForThunk(llvm::FunctionCallee(Fn->getFunctionType(), Callee),
-                            &Thunk, IsUnprototyped);
+  EmitCallAndReturnForThunk(llvm::FunctionCallee(CalleeFnTy, Callee),
+                            CalleeFnInfo, CalleeGD, &Thunk, IsUnprototyped);
 }
 
 static bool shouldEmitVTableThunk(CodeGenModule &CGM, const CXXMethodDecl *MD,
@@ -503,21 +516,25 @@
     MCtx.mangleCXXDtorThunk(DD, GD.getDtorType(), TI.This, Out);
   else
     MCtx.mangleThunk(MD, TI, Out);
+
   llvm::Type *ThunkVTableTy = CGM.getTypes().GetFunctionTypeForVTable(GD);
   llvm::Constant *Thunk = CGM.GetAddrOfThunk(Name, ThunkVTableTy, GD);
 
   // If we don't need to emit a definition, return this declaration as is.
   bool IsUnprototyped = !CGM.getTypes().isFuncTypeConvertible(
-      MD->getType()->castAs<FunctionType>());
+      cast<CXXMethodDecl>(TI.BaseMethod.getDecl())
+          ->getType()
+          ->castAs<FunctionType>());
   if (!shouldEmitVTableThunk(CGM, MD, IsUnprototyped, ForVTable))
     return Thunk;
 
-  // Arrange a function prototype appropriate for a function definition. In some
+  // Arrange a thunk function prototype appropriate for a function def. In some
   // cases in the MS ABI, we may need to build an unprototyped musttail thunk.
-  const CGFunctionInfo &FnInfo =
-      IsUnprototyped ? CGM.getTypes().arrangeUnprototypedMustTailThunk(MD)
-                     : CGM.getTypes().arrangeGlobalDeclaration(GD);
-  llvm::FunctionType *ThunkFnTy = CGM.getTypes().GetFunctionType(FnInfo);
+  const CGFunctionInfo &ThunkFnInfo =
+      IsUnprototyped ? CGM.getTypes().arrangeUnprototypedMustTailThunk(
+                           cast<CXXMethodDecl>(TI.BaseMethod.getDecl()))
+                     : CGM.getTypes().arrangeGlobalDeclaration(TI.BaseMethod);
+  llvm::FunctionType *ThunkFnTy = CGM.getTypes().GetFunctionType(ThunkFnInfo);
 
   // If the type of the underlying GlobalValue is wrong, we'll have to replace
   // it. It should be a declaration.
@@ -525,13 +542,15 @@
   if (ThunkFn->getFunctionType() != ThunkFnTy) {
     llvm::GlobalValue *OldThunkFn = ThunkFn;
 
-    assert(OldThunkFn->isDeclaration() && "Shouldn't replace non-declaration");
+    // FIXME: ???
+    // assert(OldThunkFn->isDeclaration() && "Shouldn't replace
+    // non-declaration");
 
     // Remove the name from the old thunk function and get a new thunk.
     OldThunkFn->setName(StringRef());
     ThunkFn = llvm::Function::Create(ThunkFnTy, llvm::Function::ExternalLinkage,
                                      Name.str(), &CGM.getModule());
-    CGM.SetLLVMFunctionAttributes(MD, FnInfo, ThunkFn);
+    CGM.SetLLVMFunctionAttributes(GD, ThunkFnInfo, ThunkFn);
 
     // If needed, replace the old thunk with a bitcast.
     if (!OldThunkFn->use_empty()) {
@@ -564,7 +583,7 @@
   if (IsUnprototyped)
     ThunkFn->addFnAttr("thunk");
 
-  CGM.SetLLVMFunctionAttributesForDefinition(GD.getDecl(), ThunkFn);
+  CGM.SetLLVMFunctionAttributesForDefinition(MD, ThunkFn);
 
   // Thunks for variadic methods are special because in general variadic
   // arguments cannot be perfectly forwarded. In the general case, clang
@@ -591,10 +610,11 @@
     if (UseAvailableExternallyLinkage)
       return ThunkFn;
     ThunkFn =
-        CodeGenFunction(CGM).GenerateVarArgsThunk(ThunkFn, FnInfo, GD, TI);
+        CodeGenFunction(CGM).GenerateVarArgsThunk(ThunkFn, ThunkFnInfo, GD, TI);
   } else {
     // Normal thunk body generation.
-    CodeGenFunction(CGM).generateThunk(ThunkFn, FnInfo, GD, TI, IsUnprototyped);
+    CodeGenFunction(CGM).generateThunk(ThunkFn, ThunkFnInfo, TI.BaseMethod, GD,
+                                       TI, IsUnprototyped);
   }
 
   setThunkProperties(CGM, TI, ThunkFn, ForVTable, GD);
@@ -727,22 +747,7 @@
   case VTableComponent::CK_FunctionPointer:
   case VTableComponent::CK_CompleteDtorPointer:
   case VTableComponent::CK_DeletingDtorPointer: {
-    GlobalDecl GD;
-
-    // Get the right global decl.
-    switch (component.getKind()) {
-    default:
-      llvm_unreachable("Unexpected vtable component kind");
-    case VTableComponent::CK_FunctionPointer:
-      GD = component.getFunctionDecl();
-      break;
-    case VTableComponent::CK_CompleteDtorPointer:
-      GD = GlobalDecl(component.getDestructorDecl(), Dtor_Complete);
-      break;
-    case VTableComponent::CK_DeletingDtorPointer:
-      GD = GlobalDecl(component.getDestructorDecl(), Dtor_Deleting);
-      break;
-    }
+    GlobalDecl GD = component.getGlobalDecl();
 
     if (CGM.getLangOpts().CUDA) {
       // Emit NULL for methods we can't codegen on this
Index: clang/lib/AST/VTableBuilder.cpp
===================================================================
--- clang/lib/AST/VTableBuilder.cpp
+++ clang/lib/AST/VTableBuilder.cpp
@@ -913,7 +913,8 @@
 
   /// AddMethod - Add a single virtual member function to the vtable
   /// components vector.
-  void AddMethod(const CXXMethodDecl *MD, ReturnAdjustment ReturnAdjustment);
+  void AddMethod(const CXXMethodDecl *BaseMethod, const CXXMethodDecl *MD,
+                 ReturnAdjustment ReturnAdjustment);
 
   /// IsOverriderUsed - Returns whether the overrider will ever be used in this
   /// part of the vtable.
@@ -1115,10 +1116,12 @@
 
     // Ignore adjustments for unused function pointers.
     uint64_t VTableIndex = MethodInfo.VTableIndex;
-    if (Components[VTableIndex].getKind() ==
-        VTableComponent::CK_UnusedFunctionPointer)
+    const VTableComponent &component = Components[VTableIndex];
+    if (component.getKind() == VTableComponent::CK_UnusedFunctionPointer)
       continue;
 
+    GlobalDecl GD = component.getGlobalDecl();
+
     // Get the final overrider for this method.
     FinalOverriders::OverriderInfo Overrider =
       Overriders.getOverrider(MD, MethodInfo.BaseOffset);
@@ -1130,7 +1133,8 @@
       // While the thunk itself might be needed by vtables in subclasses or
       // in construction vtables, there doesn't seem to be a reason for using
       // the thunk in this vtable. Still, we do so to match gcc.
-      if (VTableThunks.lookup(VTableIndex).Return.isEmpty())
+      auto it = VTableThunks.find(VTableIndex);
+      if (it == VTableThunks.end() || it->second.Return.isEmpty())
         continue;
     }
 
@@ -1140,12 +1144,33 @@
     if (ThisAdjustment.isEmpty())
       continue;
 
-    // Add it.
-    VTableThunks[VTableIndex].This = ThisAdjustment;
+    auto ApplyThisAdjustment = [&](unsigned Idx) {
+      Optional<ThunkInfo> TI;
+
+      auto it = VTableThunks.find(Idx);
+      if (it != VTableThunks.end()) {
+        TI = it->second;
+        TI->This = ThisAdjustment;
+      } else {
+        GlobalDecl BaseMethod;
+        if (auto *DD = dyn_cast<CXXDestructorDecl>(MD))
+          BaseMethod = GlobalDecl(DD, GD.getDtorType());
+        else
+          BaseMethod = MD;
+
+        TI = {BaseMethod, ThisAdjustment, ReturnAdjustment()};
+      }
+
+      // Override it. Note that there may or may not be a thunk already.
+      VTableThunks.erase(Idx);
+      VTableThunks.insert({Idx, *TI});
+    };
+
+    ApplyThisAdjustment(VTableIndex);
 
     if (isa<CXXDestructorDecl>(MD)) {
       // Add an adjustment for the deleting destructor as well.
-      VTableThunks[VTableIndex + 1].This = ThisAdjustment;
+      ApplyThisAdjustment(VTableIndex + 1);
     }
   }
 
@@ -1300,7 +1325,8 @@
   return Adjustment;
 }
 
-void ItaniumVTableBuilder::AddMethod(const CXXMethodDecl *MD,
+void ItaniumVTableBuilder::AddMethod(const CXXMethodDecl *BaseMethod,
+                                     const CXXMethodDecl *MD,
                                      ReturnAdjustment ReturnAdjustment) {
   if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
     assert(ReturnAdjustment.isEmpty() &&
@@ -1311,8 +1337,13 @@
     Components.push_back(VTableComponent::MakeDeletingDtor(DD));
   } else {
     // Add the return adjustment if necessary.
-    if (!ReturnAdjustment.isEmpty())
-      VTableThunks[Components.size()].Return = ReturnAdjustment;
+    if (!ReturnAdjustment.isEmpty()) {
+      assert(VTableThunks.find(Components.size()) == VTableThunks.end() &&
+             "ZZZ");
+      VTableThunks.insert(
+          {Components.size(),
+           ThunkInfo(BaseMethod, ThisAdjustment(), ReturnAdjustment)});
+    }
 
     // Add the function.
     Components.push_back(VTableComponent::MakeFunction(MD));
@@ -1513,6 +1544,10 @@
         MethodInfo MethodInfo(Base.getBaseOffset(), BaseOffsetInLayoutClass,
                               OverriddenMethodInfo.VTableIndex);
 
+        uint64_t VTableIndex = MethodInfo.VTableIndex;
+        const VTableComponent &component = Components[VTableIndex];
+        GlobalDecl GD = component.getGlobalDecl();
+
         assert(!MethodInfoMap.count(MD) &&
                "Should not have method info for this method yet!");
 
@@ -1540,9 +1575,15 @@
             ReturnAdjustment ReturnAdjustment =
               ComputeReturnAdjustment(ReturnAdjustmentOffset);
 
+            GlobalDecl BaseMethod;
+            if (auto *DD = dyn_cast<CXXDestructorDecl>(MD))
+              BaseMethod = GlobalDecl(DD, GD.getDtorType());
+            else
+              BaseMethod = MD;
+
             // This is a virtual thunk for the most derived class, add it.
             AddThunk(Overrider.Method,
-                     ThunkInfo(ThisAdjustment, ReturnAdjustment));
+                     ThunkInfo(BaseMethod, ThisAdjustment, ReturnAdjustment));
           }
         }
 
@@ -1608,7 +1649,7 @@
     ReturnAdjustment ReturnAdjustment =
       ComputeReturnAdjustment(ReturnAdjustmentOffset);
 
-    AddMethod(Overrider.Method, ReturnAdjustment);
+    AddMethod(MD, Overrider.Method, ReturnAdjustment);
   }
 }
 
@@ -1958,8 +1999,9 @@
       if (MD->isDeleted())
         Out << " [deleted]";
 
-      ThunkInfo Thunk = VTableThunks.lookup(I);
-      if (!Thunk.isEmpty()) {
+      auto it = VTableThunks.find(I);
+      if (it != VTableThunks.end()) {
+        ThunkInfo Thunk = it->second;
         // If this function pointer has a return adjustment, dump it.
         if (!Thunk.Return.isEmpty()) {
           Out << "\n       [return adjustment: ";
@@ -2006,8 +2048,9 @@
       if (DD->isPure())
         Out << " [pure]";
 
-      ThunkInfo Thunk = VTableThunks.lookup(I);
-      if (!Thunk.isEmpty()) {
+      auto it = VTableThunks.find(I);
+      if (it != VTableThunks.end()) {
+        ThunkInfo Thunk = it->second;
         // If this destructor has a 'this' pointer adjustment, dump it.
         if (!Thunk.This.isEmpty()) {
           Out << "\n       [this adjustment: ";
@@ -2120,7 +2163,6 @@
 
       ThunkInfoVectorTy ThunksVector = Thunks[MD];
       llvm::sort(ThunksVector, [](const ThunkInfo &LHS, const ThunkInfo &RHS) {
-        assert(LHS.Method == nullptr && RHS.Method == nullptr);
         return std::tie(LHS.This, LHS.Return) < std::tie(RHS.This, RHS.Return);
       });
 
@@ -2513,18 +2555,29 @@
 
   /// AddMethod - Add a single virtual member function to the vftable
   /// components vector.
-  void AddMethod(const CXXMethodDecl *MD, ThunkInfo TI) {
-    if (!TI.isEmpty()) {
-      VTableThunks[Components.size()] = TI;
-      AddThunk(MD, TI);
-    }
+  void AddMethod(const CXXMethodDecl *BaseMD, const CXXMethodDecl *MD,
+                 ThisAdjustment This, ReturnAdjustment Return) {
     if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
-      assert(TI.Return.isEmpty() &&
-             "Destructor can't have return adjustment!");
+      assert(Return.isEmpty() && "Destructor can't have return adjustment!");
       Components.push_back(VTableComponent::MakeDeletingDtor(DD));
     } else {
       Components.push_back(VTableComponent::MakeFunction(MD));
     }
+
+    GlobalDecl GD;
+    if (isa<CXXDestructorDecl>(BaseMD))
+      GD = GlobalDecl(cast<CXXDestructorDecl>(BaseMD),
+                      CXXDtorType::Dtor_Deleting);
+    else
+      GD = BaseMD;
+
+    ThunkInfo TI(GD, This, Return);
+    if (!TI.isEmpty()) {
+      assert(VTableThunks.find(Components.size() - 1) == VTableThunks.end() &&
+             "ZZZ");
+      VTableThunks.insert({Components.size() - 1, TI});
+      AddThunk(MD, TI);
+    }
   }
 
   /// AddMethods - Add the methods of this base subobject and the relevant
@@ -3091,9 +3144,7 @@
       }
     }
 
-    AddMethod(FinalOverriderMD,
-              ThunkInfo(ThisAdjustmentOffset, ReturnAdjustment,
-                        ForceReturnAdjustmentMangling ? MD : nullptr));
+    AddMethod(MD, FinalOverriderMD, ThisAdjustmentOffset, ReturnAdjustment);
   }
 }
 
@@ -3111,11 +3162,14 @@
   const ReturnAdjustment &R = TI.Return;
   bool Multiline = false;
   const char *LinePrefix = "\n       ";
-  if (!R.isEmpty() || TI.Method) {
+  if (!R.isEmpty()) {
     if (!ContinueFirstLine)
       Out << LinePrefix;
     Out << "[return adjustment (to type '"
-        << TI.Method->getReturnType().getCanonicalType().getAsString()
+        << cast<CXXMethodDecl>(TI.BaseMethod.getDecl())
+               ->getReturnType()
+               .getCanonicalType()
+               .getAsString()
         << "'): ";
     if (R.Virtual.Microsoft.VBPtrOffset)
       Out << "vbptr at offset " << R.Virtual.Microsoft.VBPtrOffset << ", ";
@@ -3179,9 +3233,11 @@
       if (MD->isDeleted())
         Out << " [deleted]";
 
-      ThunkInfo Thunk = VTableThunks.lookup(I);
-      if (!Thunk.isEmpty())
+      auto it = VTableThunks.find(I);
+      if (it != VTableThunks.end()) {
+        ThunkInfo Thunk = it->second;
         dumpMicrosoftThunkAdjustment(Thunk, Out, /*ContinueFirstLine=*/false);
+      }
 
       break;
     }
@@ -3195,8 +3251,9 @@
       if (DD->isPure())
         Out << " [pure]";
 
-      ThunkInfo Thunk = VTableThunks.lookup(I);
-      if (!Thunk.isEmpty()) {
+      auto it = VTableThunks.find(I);
+      if (it != VTableThunks.end()) {
+        ThunkInfo Thunk = it->second;
         assert(Thunk.Return.isEmpty() &&
                "No return adjustment needed for destructors!");
         dumpMicrosoftThunkAdjustment(Thunk, Out, /*ContinueFirstLine=*/false);
Index: clang/lib/AST/MicrosoftMangle.cpp
===================================================================
--- clang/lib/AST/MicrosoftMangle.cpp
+++ clang/lib/AST/MicrosoftMangle.cpp
@@ -3466,13 +3466,10 @@
   AccessSpecifier AS = Thunk.Return.isEmpty() ? MD->getAccess() : AS_public;
   mangleThunkThisAdjustment(AS, Thunk.This, Mangler, MHO);
 
-  if (!Thunk.Return.isEmpty())
-    assert(Thunk.Method != nullptr &&
-           "Thunk info should hold the overridee decl");
-
-  const CXXMethodDecl *DeclForFPT = Thunk.Method ? Thunk.Method : MD;
-  Mangler.mangleFunctionType(
-      DeclForFPT->getType()->castAs<FunctionProtoType>(), MD);
+  Mangler.mangleFunctionType(cast<FunctionDecl>(Thunk.BaseMethod.getDecl())
+                                 ->getType()
+                                 ->castAs<FunctionProtoType>(),
+                             MD);
 }
 
 void MicrosoftMangleContextImpl::mangleCXXDtorThunk(
Index: clang/lib/AST/ItaniumMangle.cpp
===================================================================
--- clang/lib/AST/ItaniumMangle.cpp
+++ clang/lib/AST/ItaniumMangle.cpp
@@ -14,7 +14,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "clang/AST/Mangle.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Attr.h"
 #include "clang/AST/Decl.h"
@@ -23,14 +22,16 @@
 #include "clang/AST/DeclOpenMP.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/Expr.h"
-#include "clang/AST/ExprConcepts.h"
 #include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprConcepts.h"
 #include "clang/AST/ExprObjC.h"
+#include "clang/AST/Mangle.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/Basic/ABI.h"
 #include "clang/Basic/Module.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/Thunk.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/raw_ostream.h"
Index: clang/include/clang/Basic/Thunk.h
===================================================================
--- /dev/null
+++ clang/include/clang/Basic/Thunk.h
@@ -0,0 +1,181 @@
+//===----- Thunk.h - Declarations related to VTable Thunks ------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Enums/classes describing THUNK related information about constructors,
+/// destructors and thunks.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_THUNK_H
+#define LLVM_CLANG_BASIC_THUNK_H
+
+#include "clang/AST/GlobalDecl.h"
+
+namespace clang {
+
+/// A return adjustment.
+struct ReturnAdjustment {
+  /// The non-virtual adjustment from the derived object to its
+  /// nearest virtual base.
+  int64_t NonVirtual;
+
+  /// Holds the ABI-specific information about the virtual return
+  /// adjustment, if needed.
+  union VirtualAdjustment {
+    // Itanium ABI
+    struct {
+      /// The offset (in bytes), relative to the address point
+      /// of the virtual base class offset.
+      int64_t VBaseOffsetOffset;
+    } Itanium;
+
+    // Microsoft ABI
+    struct {
+      /// The offset (in bytes) of the vbptr, relative to the beginning
+      /// of the derived class.
+      uint32_t VBPtrOffset;
+
+      /// Index of the virtual base in the vbtable.
+      uint32_t VBIndex;
+    } Microsoft;
+
+    VirtualAdjustment() { memset(this, 0, sizeof(*this)); }
+
+    bool Equals(const VirtualAdjustment &Other) const {
+      return memcmp(this, &Other, sizeof(Other)) == 0;
+    }
+
+    bool isEmpty() const {
+      VirtualAdjustment Zero;
+      return Equals(Zero);
+    }
+
+    bool Less(const VirtualAdjustment &RHS) const {
+      return memcmp(this, &RHS, sizeof(RHS)) < 0;
+    }
+  } Virtual;
+
+  ReturnAdjustment() : NonVirtual(0) {}
+
+  bool isEmpty() const { return !NonVirtual && Virtual.isEmpty(); }
+
+  friend bool operator==(const ReturnAdjustment &LHS,
+                         const ReturnAdjustment &RHS) {
+    return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Equals(RHS.Virtual);
+  }
+
+  friend bool operator!=(const ReturnAdjustment &LHS,
+                         const ReturnAdjustment &RHS) {
+    return !(LHS == RHS);
+  }
+
+  friend bool operator<(const ReturnAdjustment &LHS,
+                        const ReturnAdjustment &RHS) {
+    if (LHS.NonVirtual < RHS.NonVirtual)
+      return true;
+
+    return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Less(RHS.Virtual);
+  }
+};
+
+/// A \c this pointer adjustment.
+struct ThisAdjustment {
+  /// The non-virtual adjustment from the derived object to its
+  /// nearest virtual base.
+  int64_t NonVirtual;
+
+  /// Holds the ABI-specific information about the virtual this
+  /// adjustment, if needed.
+  union VirtualAdjustment {
+    // Itanium ABI
+    struct {
+      /// The offset (in bytes), relative to the address point,
+      /// of the virtual call offset.
+      int64_t VCallOffsetOffset;
+    } Itanium;
+
+    struct {
+      /// The offset of the vtordisp (in bytes), relative to the ECX.
+      int32_t VtordispOffset;
+
+      /// The offset of the vbptr of the derived class (in bytes),
+      /// relative to the ECX after vtordisp adjustment.
+      int32_t VBPtrOffset;
+
+      /// The offset (in bytes) of the vbase offset in the vbtable.
+      int32_t VBOffsetOffset;
+    } Microsoft;
+
+    VirtualAdjustment() { memset(this, 0, sizeof(*this)); }
+
+    bool Equals(const VirtualAdjustment &Other) const {
+      return memcmp(this, &Other, sizeof(Other)) == 0;
+    }
+
+    bool isEmpty() const {
+      VirtualAdjustment Zero;
+      return Equals(Zero);
+    }
+
+    bool Less(const VirtualAdjustment &RHS) const {
+      return memcmp(this, &RHS, sizeof(RHS)) < 0;
+    }
+  } Virtual;
+
+  ThisAdjustment() : NonVirtual(0) {}
+
+  bool isEmpty() const { return !NonVirtual && Virtual.isEmpty(); }
+
+  friend bool operator==(const ThisAdjustment &LHS, const ThisAdjustment &RHS) {
+    return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Equals(RHS.Virtual);
+  }
+
+  friend bool operator!=(const ThisAdjustment &LHS, const ThisAdjustment &RHS) {
+    return !(LHS == RHS);
+  }
+
+  friend bool operator<(const ThisAdjustment &LHS, const ThisAdjustment &RHS) {
+    if (LHS.NonVirtual < RHS.NonVirtual)
+      return true;
+
+    return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Less(RHS.Virtual);
+  }
+};
+
+/// The \c this pointer adjustment as well as an optional return
+/// adjustment for a thunk.
+struct ThunkInfo {
+  /// Holds a pointer to the overridden (i.e. base) method this thunk is for.
+  /// CAUTION: In the unlikely event you need to sort ThunkInfos, consider using
+  /// an ABI-specific comparator.
+  GlobalDecl BaseMethod;
+
+  /// The \c this pointer adjustment.
+  ThisAdjustment This;
+
+  /// The return adjustment.
+  ReturnAdjustment Return;
+
+  ThunkInfo() = delete;
+
+  ThunkInfo(GlobalDecl BaseMethod, const ThisAdjustment &This,
+            const ReturnAdjustment &Return)
+      : BaseMethod(BaseMethod), This(This), Return(Return) {}
+
+  friend bool operator==(const ThunkInfo &LHS, const ThunkInfo &RHS) {
+    return LHS.BaseMethod == RHS.BaseMethod && LHS.This == RHS.This &&
+           LHS.Return == RHS.Return;
+  }
+
+  bool isEmpty() const { return This.isEmpty() && Return.isEmpty(); }
+};
+
+} // end namespace clang
+
+#endif
Index: clang/include/clang/Basic/ABI.h
===================================================================
--- clang/include/clang/Basic/ABI.h
+++ clang/include/clang/Basic/ABI.h
@@ -37,174 +37,6 @@
     Dtor_Comdat    ///< The COMDAT used for dtors
 };
 
-/// A return adjustment.
-struct ReturnAdjustment {
-  /// The non-virtual adjustment from the derived object to its
-  /// nearest virtual base.
-  int64_t NonVirtual;
-
-  /// Holds the ABI-specific information about the virtual return
-  /// adjustment, if needed.
-  union VirtualAdjustment {
-    // Itanium ABI
-    struct {
-      /// The offset (in bytes), relative to the address point
-      /// of the virtual base class offset.
-      int64_t VBaseOffsetOffset;
-    } Itanium;
-
-    // Microsoft ABI
-    struct {
-      /// The offset (in bytes) of the vbptr, relative to the beginning
-      /// of the derived class.
-      uint32_t VBPtrOffset;
-
-      /// Index of the virtual base in the vbtable.
-      uint32_t VBIndex;
-    } Microsoft;
-
-    VirtualAdjustment() {
-      memset(this, 0, sizeof(*this));
-    }
-
-    bool Equals(const VirtualAdjustment &Other) const {
-      return memcmp(this, &Other, sizeof(Other)) == 0;
-    }
-
-    bool isEmpty() const {
-      VirtualAdjustment Zero;
-      return Equals(Zero);
-    }
-
-    bool Less(const VirtualAdjustment &RHS) const {
-      return memcmp(this, &RHS, sizeof(RHS)) < 0;
-    }
-  } Virtual;
-
-  ReturnAdjustment() : NonVirtual(0) {}
-
-  bool isEmpty() const { return !NonVirtual && Virtual.isEmpty(); }
-
-  friend bool operator==(const ReturnAdjustment &LHS,
-                         const ReturnAdjustment &RHS) {
-    return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Equals(RHS.Virtual);
-  }
-
-  friend bool operator!=(const ReturnAdjustment &LHS, const ReturnAdjustment &RHS) {
-    return !(LHS == RHS);
-  }
-
-  friend bool operator<(const ReturnAdjustment &LHS,
-                        const ReturnAdjustment &RHS) {
-    if (LHS.NonVirtual < RHS.NonVirtual)
-      return true;
-
-    return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Less(RHS.Virtual);
-  }
-};
-
-/// A \c this pointer adjustment.
-struct ThisAdjustment {
-  /// The non-virtual adjustment from the derived object to its
-  /// nearest virtual base.
-  int64_t NonVirtual;
-
-  /// Holds the ABI-specific information about the virtual this
-  /// adjustment, if needed.
-  union VirtualAdjustment {
-    // Itanium ABI
-    struct {
-      /// The offset (in bytes), relative to the address point,
-      /// of the virtual call offset.
-      int64_t VCallOffsetOffset;
-    } Itanium;
-
-    struct {
-      /// The offset of the vtordisp (in bytes), relative to the ECX.
-      int32_t VtordispOffset;
-
-      /// The offset of the vbptr of the derived class (in bytes),
-      /// relative to the ECX after vtordisp adjustment.
-      int32_t VBPtrOffset;
-
-      /// The offset (in bytes) of the vbase offset in the vbtable.
-      int32_t VBOffsetOffset;
-    } Microsoft;
-
-    VirtualAdjustment() {
-      memset(this, 0, sizeof(*this));
-    }
-
-    bool Equals(const VirtualAdjustment &Other) const {
-      return memcmp(this, &Other, sizeof(Other)) == 0;
-    }
-
-    bool isEmpty() const {
-      VirtualAdjustment Zero;
-      return Equals(Zero);
-    }
-
-    bool Less(const VirtualAdjustment &RHS) const {
-      return memcmp(this, &RHS, sizeof(RHS)) < 0;
-    }
-  } Virtual;
-
-  ThisAdjustment() : NonVirtual(0) { }
-
-  bool isEmpty() const { return !NonVirtual && Virtual.isEmpty(); }
-
-  friend bool operator==(const ThisAdjustment &LHS,
-                         const ThisAdjustment &RHS) {
-    return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Equals(RHS.Virtual);
-  }
-
-  friend bool operator!=(const ThisAdjustment &LHS, const ThisAdjustment &RHS) {
-    return !(LHS == RHS);
-  }
-
-  friend bool operator<(const ThisAdjustment &LHS,
-                        const ThisAdjustment &RHS) {
-    if (LHS.NonVirtual < RHS.NonVirtual)
-      return true;
-
-    return LHS.NonVirtual == RHS.NonVirtual && LHS.Virtual.Less(RHS.Virtual);
-  }
-};
-
-class CXXMethodDecl;
-
-/// The \c this pointer adjustment as well as an optional return
-/// adjustment for a thunk.
-struct ThunkInfo {
-  /// The \c this pointer adjustment.
-  ThisAdjustment This;
-
-  /// The return adjustment.
-  ReturnAdjustment Return;
-
-  /// Holds a pointer to the overridden method this thunk is for,
-  /// if needed by the ABI to distinguish different thunks with equal
-  /// adjustments. Otherwise, null.
-  /// CAUTION: In the unlikely event you need to sort ThunkInfos, consider using
-  /// an ABI-specific comparator.
-  const CXXMethodDecl *Method;
-
-  ThunkInfo() : Method(nullptr) { }
-
-  ThunkInfo(const ThisAdjustment &This, const ReturnAdjustment &Return,
-            const CXXMethodDecl *Method = nullptr)
-      : This(This), Return(Return), Method(Method) {}
-
-  friend bool operator==(const ThunkInfo &LHS, const ThunkInfo &RHS) {
-    return LHS.This == RHS.This && LHS.Return == RHS.Return &&
-           LHS.Method == RHS.Method;
-  }
-
-  bool isEmpty() const {
-    return This.isEmpty() && Return.isEmpty() && Method == nullptr;
-  }
-};
-
 } // end namespace clang
 
 #endif
Index: clang/include/clang/AST/VTableBuilder.h
===================================================================
--- clang/include/clang/AST/VTableBuilder.h
+++ clang/include/clang/AST/VTableBuilder.h
@@ -18,6 +18,7 @@
 #include "clang/AST/GlobalDecl.h"
 #include "clang/AST/RecordLayout.h"
 #include "clang/Basic/ABI.h"
+#include "clang/Basic/Thunk.h"
 #include "llvm/ADT/DenseMap.h"
 #include <memory>
 #include <utility>
@@ -253,7 +254,7 @@
   OwningArrayRef<VTableComponent> VTableComponents;
 
   /// Contains thunks needed by vtables, sorted by indices.
-  OwningArrayRef<VTableThunkTy> VTableThunks;
+  std::vector<VTableThunkTy> VTableThunks;
 
   /// Address points for all vtables.
   AddressPointsMapTy AddressPoints;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to