xref: /minix3/external/bsd/llvm/dist/clang/lib/CodeGen/CGCXXABI.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc //===----- CGCXXABI.cpp - Interface to C++ ABIs ---------------------------===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // This provides an abstract class for C++ code generation. Concrete subclasses
11f4a2713aSLionel Sambuc // of this implement code generation for specific C++ ABIs.
12f4a2713aSLionel Sambuc //
13f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
14f4a2713aSLionel Sambuc 
15f4a2713aSLionel Sambuc #include "CGCXXABI.h"
16f4a2713aSLionel Sambuc 
17f4a2713aSLionel Sambuc using namespace clang;
18f4a2713aSLionel Sambuc using namespace CodeGen;
19f4a2713aSLionel Sambuc 
~CGCXXABI()20f4a2713aSLionel Sambuc CGCXXABI::~CGCXXABI() { }
21f4a2713aSLionel Sambuc 
ErrorUnsupportedABI(CodeGenFunction & CGF,StringRef S)22f4a2713aSLionel Sambuc void CGCXXABI::ErrorUnsupportedABI(CodeGenFunction &CGF, StringRef S) {
23f4a2713aSLionel Sambuc   DiagnosticsEngine &Diags = CGF.CGM.getDiags();
24f4a2713aSLionel Sambuc   unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
25f4a2713aSLionel Sambuc                                           "cannot yet compile %0 in this ABI");
26f4a2713aSLionel Sambuc   Diags.Report(CGF.getContext().getFullLoc(CGF.CurCodeDecl->getLocation()),
27f4a2713aSLionel Sambuc                DiagID)
28f4a2713aSLionel Sambuc     << S;
29f4a2713aSLionel Sambuc }
30f4a2713aSLionel Sambuc 
canCopyArgument(const CXXRecordDecl * RD) const31*0a6a1f1dSLionel Sambuc bool CGCXXABI::canCopyArgument(const CXXRecordDecl *RD) const {
32*0a6a1f1dSLionel Sambuc   // If RD has a non-trivial move or copy constructor, we cannot copy the
33*0a6a1f1dSLionel Sambuc   // argument.
34*0a6a1f1dSLionel Sambuc   if (RD->hasNonTrivialCopyConstructor() || RD->hasNonTrivialMoveConstructor())
35*0a6a1f1dSLionel Sambuc     return false;
36*0a6a1f1dSLionel Sambuc 
37*0a6a1f1dSLionel Sambuc   // If RD has a non-trivial destructor, we cannot copy the argument.
38*0a6a1f1dSLionel Sambuc   if (RD->hasNonTrivialDestructor())
39*0a6a1f1dSLionel Sambuc     return false;
40*0a6a1f1dSLionel Sambuc 
41*0a6a1f1dSLionel Sambuc   // We can only copy the argument if there exists at least one trivial,
42*0a6a1f1dSLionel Sambuc   // non-deleted copy or move constructor.
43*0a6a1f1dSLionel Sambuc   // FIXME: This assumes that all lazily declared copy and move constructors are
44*0a6a1f1dSLionel Sambuc   // not deleted.  This assumption might not be true in some corner cases.
45*0a6a1f1dSLionel Sambuc   bool CopyDeleted = false;
46*0a6a1f1dSLionel Sambuc   bool MoveDeleted = false;
47*0a6a1f1dSLionel Sambuc   for (const CXXConstructorDecl *CD : RD->ctors()) {
48*0a6a1f1dSLionel Sambuc     if (CD->isCopyConstructor() || CD->isMoveConstructor()) {
49*0a6a1f1dSLionel Sambuc       assert(CD->isTrivial());
50*0a6a1f1dSLionel Sambuc       // We had at least one undeleted trivial copy or move ctor.  Return
51*0a6a1f1dSLionel Sambuc       // directly.
52*0a6a1f1dSLionel Sambuc       if (!CD->isDeleted())
53*0a6a1f1dSLionel Sambuc         return true;
54*0a6a1f1dSLionel Sambuc       if (CD->isCopyConstructor())
55*0a6a1f1dSLionel Sambuc         CopyDeleted = true;
56*0a6a1f1dSLionel Sambuc       else
57*0a6a1f1dSLionel Sambuc         MoveDeleted = true;
58*0a6a1f1dSLionel Sambuc     }
59*0a6a1f1dSLionel Sambuc   }
60*0a6a1f1dSLionel Sambuc 
61*0a6a1f1dSLionel Sambuc   // If all trivial copy and move constructors are deleted, we cannot copy the
62*0a6a1f1dSLionel Sambuc   // argument.
63*0a6a1f1dSLionel Sambuc   return !(CopyDeleted && MoveDeleted);
64*0a6a1f1dSLionel Sambuc }
65*0a6a1f1dSLionel Sambuc 
GetBogusMemberPointer(QualType T)66f4a2713aSLionel Sambuc llvm::Constant *CGCXXABI::GetBogusMemberPointer(QualType T) {
67f4a2713aSLionel Sambuc   return llvm::Constant::getNullValue(CGM.getTypes().ConvertType(T));
68f4a2713aSLionel Sambuc }
69f4a2713aSLionel Sambuc 
70f4a2713aSLionel Sambuc llvm::Type *
ConvertMemberPointerType(const MemberPointerType * MPT)71f4a2713aSLionel Sambuc CGCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) {
72f4a2713aSLionel Sambuc   return CGM.getTypes().ConvertType(CGM.getContext().getPointerDiffType());
73f4a2713aSLionel Sambuc }
74f4a2713aSLionel Sambuc 
EmitLoadOfMemberFunctionPointer(CodeGenFunction & CGF,const Expr * E,llvm::Value * & This,llvm::Value * MemPtr,const MemberPointerType * MPT)75*0a6a1f1dSLionel Sambuc llvm::Value *CGCXXABI::EmitLoadOfMemberFunctionPointer(
76*0a6a1f1dSLionel Sambuc     CodeGenFunction &CGF, const Expr *E, llvm::Value *&This,
77*0a6a1f1dSLionel Sambuc     llvm::Value *MemPtr, const MemberPointerType *MPT) {
78f4a2713aSLionel Sambuc   ErrorUnsupportedABI(CGF, "calls through member pointers");
79f4a2713aSLionel Sambuc 
80f4a2713aSLionel Sambuc   const FunctionProtoType *FPT =
81f4a2713aSLionel Sambuc     MPT->getPointeeType()->getAs<FunctionProtoType>();
82f4a2713aSLionel Sambuc   const CXXRecordDecl *RD =
83f4a2713aSLionel Sambuc     cast<CXXRecordDecl>(MPT->getClass()->getAs<RecordType>()->getDecl());
84f4a2713aSLionel Sambuc   llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(
85f4a2713aSLionel Sambuc                               CGM.getTypes().arrangeCXXMethodType(RD, FPT));
86f4a2713aSLionel Sambuc   return llvm::Constant::getNullValue(FTy->getPointerTo());
87f4a2713aSLionel Sambuc }
88f4a2713aSLionel Sambuc 
89*0a6a1f1dSLionel Sambuc llvm::Value *
EmitMemberDataPointerAddress(CodeGenFunction & CGF,const Expr * E,llvm::Value * Base,llvm::Value * MemPtr,const MemberPointerType * MPT)90*0a6a1f1dSLionel Sambuc CGCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF, const Expr *E,
91*0a6a1f1dSLionel Sambuc                                        llvm::Value *Base, llvm::Value *MemPtr,
92f4a2713aSLionel Sambuc                                        const MemberPointerType *MPT) {
93f4a2713aSLionel Sambuc   ErrorUnsupportedABI(CGF, "loads of member pointers");
94f4a2713aSLionel Sambuc   llvm::Type *Ty = CGF.ConvertType(MPT->getPointeeType())->getPointerTo();
95f4a2713aSLionel Sambuc   return llvm::Constant::getNullValue(Ty);
96f4a2713aSLionel Sambuc }
97f4a2713aSLionel Sambuc 
EmitMemberPointerConversion(CodeGenFunction & CGF,const CastExpr * E,llvm::Value * Src)98f4a2713aSLionel Sambuc llvm::Value *CGCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
99f4a2713aSLionel Sambuc                                                    const CastExpr *E,
100f4a2713aSLionel Sambuc                                                    llvm::Value *Src) {
101f4a2713aSLionel Sambuc   ErrorUnsupportedABI(CGF, "member function pointer conversions");
102f4a2713aSLionel Sambuc   return GetBogusMemberPointer(E->getType());
103f4a2713aSLionel Sambuc }
104f4a2713aSLionel Sambuc 
EmitMemberPointerConversion(const CastExpr * E,llvm::Constant * Src)105f4a2713aSLionel Sambuc llvm::Constant *CGCXXABI::EmitMemberPointerConversion(const CastExpr *E,
106f4a2713aSLionel Sambuc                                                       llvm::Constant *Src) {
107f4a2713aSLionel Sambuc   return GetBogusMemberPointer(E->getType());
108f4a2713aSLionel Sambuc }
109f4a2713aSLionel Sambuc 
110f4a2713aSLionel Sambuc llvm::Value *
EmitMemberPointerComparison(CodeGenFunction & CGF,llvm::Value * L,llvm::Value * R,const MemberPointerType * MPT,bool Inequality)111f4a2713aSLionel Sambuc CGCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF,
112f4a2713aSLionel Sambuc                                       llvm::Value *L,
113f4a2713aSLionel Sambuc                                       llvm::Value *R,
114f4a2713aSLionel Sambuc                                       const MemberPointerType *MPT,
115f4a2713aSLionel Sambuc                                       bool Inequality) {
116f4a2713aSLionel Sambuc   ErrorUnsupportedABI(CGF, "member function pointer comparison");
117f4a2713aSLionel Sambuc   return CGF.Builder.getFalse();
118f4a2713aSLionel Sambuc }
119f4a2713aSLionel Sambuc 
120f4a2713aSLionel Sambuc llvm::Value *
EmitMemberPointerIsNotNull(CodeGenFunction & CGF,llvm::Value * MemPtr,const MemberPointerType * MPT)121f4a2713aSLionel Sambuc CGCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
122f4a2713aSLionel Sambuc                                      llvm::Value *MemPtr,
123f4a2713aSLionel Sambuc                                      const MemberPointerType *MPT) {
124f4a2713aSLionel Sambuc   ErrorUnsupportedABI(CGF, "member function pointer null testing");
125f4a2713aSLionel Sambuc   return CGF.Builder.getFalse();
126f4a2713aSLionel Sambuc }
127f4a2713aSLionel Sambuc 
128f4a2713aSLionel Sambuc llvm::Constant *
EmitNullMemberPointer(const MemberPointerType * MPT)129f4a2713aSLionel Sambuc CGCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) {
130f4a2713aSLionel Sambuc   return GetBogusMemberPointer(QualType(MPT, 0));
131f4a2713aSLionel Sambuc }
132f4a2713aSLionel Sambuc 
EmitMemberPointer(const CXXMethodDecl * MD)133f4a2713aSLionel Sambuc llvm::Constant *CGCXXABI::EmitMemberPointer(const CXXMethodDecl *MD) {
134f4a2713aSLionel Sambuc   return GetBogusMemberPointer(
135f4a2713aSLionel Sambuc                          CGM.getContext().getMemberPointerType(MD->getType(),
136f4a2713aSLionel Sambuc                                          MD->getParent()->getTypeForDecl()));
137f4a2713aSLionel Sambuc }
138f4a2713aSLionel Sambuc 
EmitMemberDataPointer(const MemberPointerType * MPT,CharUnits offset)139f4a2713aSLionel Sambuc llvm::Constant *CGCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT,
140f4a2713aSLionel Sambuc                                                 CharUnits offset) {
141f4a2713aSLionel Sambuc   return GetBogusMemberPointer(QualType(MPT, 0));
142f4a2713aSLionel Sambuc }
143f4a2713aSLionel Sambuc 
EmitMemberPointer(const APValue & MP,QualType MPT)144f4a2713aSLionel Sambuc llvm::Constant *CGCXXABI::EmitMemberPointer(const APValue &MP, QualType MPT) {
145f4a2713aSLionel Sambuc   return GetBogusMemberPointer(MPT);
146f4a2713aSLionel Sambuc }
147f4a2713aSLionel Sambuc 
isZeroInitializable(const MemberPointerType * MPT)148f4a2713aSLionel Sambuc bool CGCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
149f4a2713aSLionel Sambuc   // Fake answer.
150f4a2713aSLionel Sambuc   return true;
151f4a2713aSLionel Sambuc }
152f4a2713aSLionel Sambuc 
buildThisParam(CodeGenFunction & CGF,FunctionArgList & params)153*0a6a1f1dSLionel Sambuc void CGCXXABI::buildThisParam(CodeGenFunction &CGF, FunctionArgList &params) {
154f4a2713aSLionel Sambuc   const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());
155f4a2713aSLionel Sambuc 
156f4a2713aSLionel Sambuc   // FIXME: I'm not entirely sure I like using a fake decl just for code
157f4a2713aSLionel Sambuc   // generation. Maybe we can come up with a better way?
158f4a2713aSLionel Sambuc   ImplicitParamDecl *ThisDecl
159*0a6a1f1dSLionel Sambuc     = ImplicitParamDecl::Create(CGM.getContext(), nullptr, MD->getLocation(),
160f4a2713aSLionel Sambuc                                 &CGM.getContext().Idents.get("this"),
161f4a2713aSLionel Sambuc                                 MD->getThisType(CGM.getContext()));
162f4a2713aSLionel Sambuc   params.push_back(ThisDecl);
163f4a2713aSLionel Sambuc   getThisDecl(CGF) = ThisDecl;
164f4a2713aSLionel Sambuc }
165f4a2713aSLionel Sambuc 
EmitThisParam(CodeGenFunction & CGF)166f4a2713aSLionel Sambuc void CGCXXABI::EmitThisParam(CodeGenFunction &CGF) {
167f4a2713aSLionel Sambuc   /// Initialize the 'this' slot.
168f4a2713aSLionel Sambuc   assert(getThisDecl(CGF) && "no 'this' variable for function");
169f4a2713aSLionel Sambuc   getThisValue(CGF)
170f4a2713aSLionel Sambuc     = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(getThisDecl(CGF)),
171f4a2713aSLionel Sambuc                              "this");
172f4a2713aSLionel Sambuc }
173f4a2713aSLionel Sambuc 
EmitReturnFromThunk(CodeGenFunction & CGF,RValue RV,QualType ResultType)174f4a2713aSLionel Sambuc void CGCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF,
175f4a2713aSLionel Sambuc                                    RValue RV, QualType ResultType) {
176f4a2713aSLionel Sambuc   CGF.EmitReturnOfRValue(RV, ResultType);
177f4a2713aSLionel Sambuc }
178f4a2713aSLionel Sambuc 
GetArrayCookieSize(const CXXNewExpr * expr)179f4a2713aSLionel Sambuc CharUnits CGCXXABI::GetArrayCookieSize(const CXXNewExpr *expr) {
180f4a2713aSLionel Sambuc   if (!requiresArrayCookie(expr))
181f4a2713aSLionel Sambuc     return CharUnits::Zero();
182f4a2713aSLionel Sambuc   return getArrayCookieSizeImpl(expr->getAllocatedType());
183f4a2713aSLionel Sambuc }
184f4a2713aSLionel Sambuc 
getArrayCookieSizeImpl(QualType elementType)185f4a2713aSLionel Sambuc CharUnits CGCXXABI::getArrayCookieSizeImpl(QualType elementType) {
186f4a2713aSLionel Sambuc   // BOGUS
187f4a2713aSLionel Sambuc   return CharUnits::Zero();
188f4a2713aSLionel Sambuc }
189f4a2713aSLionel Sambuc 
InitializeArrayCookie(CodeGenFunction & CGF,llvm::Value * NewPtr,llvm::Value * NumElements,const CXXNewExpr * expr,QualType ElementType)190f4a2713aSLionel Sambuc llvm::Value *CGCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
191f4a2713aSLionel Sambuc                                              llvm::Value *NewPtr,
192f4a2713aSLionel Sambuc                                              llvm::Value *NumElements,
193f4a2713aSLionel Sambuc                                              const CXXNewExpr *expr,
194f4a2713aSLionel Sambuc                                              QualType ElementType) {
195f4a2713aSLionel Sambuc   // Should never be called.
196f4a2713aSLionel Sambuc   ErrorUnsupportedABI(CGF, "array cookie initialization");
197*0a6a1f1dSLionel Sambuc   return nullptr;
198f4a2713aSLionel Sambuc }
199f4a2713aSLionel Sambuc 
requiresArrayCookie(const CXXDeleteExpr * expr,QualType elementType)200f4a2713aSLionel Sambuc bool CGCXXABI::requiresArrayCookie(const CXXDeleteExpr *expr,
201f4a2713aSLionel Sambuc                                    QualType elementType) {
202f4a2713aSLionel Sambuc   // If the class's usual deallocation function takes two arguments,
203f4a2713aSLionel Sambuc   // it needs a cookie.
204f4a2713aSLionel Sambuc   if (expr->doesUsualArrayDeleteWantSize())
205f4a2713aSLionel Sambuc     return true;
206f4a2713aSLionel Sambuc 
207f4a2713aSLionel Sambuc   return elementType.isDestructedType();
208f4a2713aSLionel Sambuc }
209f4a2713aSLionel Sambuc 
requiresArrayCookie(const CXXNewExpr * expr)210f4a2713aSLionel Sambuc bool CGCXXABI::requiresArrayCookie(const CXXNewExpr *expr) {
211f4a2713aSLionel Sambuc   // If the class's usual deallocation function takes two arguments,
212f4a2713aSLionel Sambuc   // it needs a cookie.
213f4a2713aSLionel Sambuc   if (expr->doesUsualArrayDeleteWantSize())
214f4a2713aSLionel Sambuc     return true;
215f4a2713aSLionel Sambuc 
216f4a2713aSLionel Sambuc   return expr->getAllocatedType().isDestructedType();
217f4a2713aSLionel Sambuc }
218f4a2713aSLionel Sambuc 
ReadArrayCookie(CodeGenFunction & CGF,llvm::Value * ptr,const CXXDeleteExpr * expr,QualType eltTy,llvm::Value * & numElements,llvm::Value * & allocPtr,CharUnits & cookieSize)219f4a2713aSLionel Sambuc void CGCXXABI::ReadArrayCookie(CodeGenFunction &CGF, llvm::Value *ptr,
220f4a2713aSLionel Sambuc                                const CXXDeleteExpr *expr, QualType eltTy,
221f4a2713aSLionel Sambuc                                llvm::Value *&numElements,
222f4a2713aSLionel Sambuc                                llvm::Value *&allocPtr, CharUnits &cookieSize) {
223f4a2713aSLionel Sambuc   // Derive a char* in the same address space as the pointer.
224f4a2713aSLionel Sambuc   unsigned AS = ptr->getType()->getPointerAddressSpace();
225f4a2713aSLionel Sambuc   llvm::Type *charPtrTy = CGF.Int8Ty->getPointerTo(AS);
226f4a2713aSLionel Sambuc   ptr = CGF.Builder.CreateBitCast(ptr, charPtrTy);
227f4a2713aSLionel Sambuc 
228f4a2713aSLionel Sambuc   // If we don't need an array cookie, bail out early.
229f4a2713aSLionel Sambuc   if (!requiresArrayCookie(expr, eltTy)) {
230f4a2713aSLionel Sambuc     allocPtr = ptr;
231*0a6a1f1dSLionel Sambuc     numElements = nullptr;
232f4a2713aSLionel Sambuc     cookieSize = CharUnits::Zero();
233f4a2713aSLionel Sambuc     return;
234f4a2713aSLionel Sambuc   }
235f4a2713aSLionel Sambuc 
236f4a2713aSLionel Sambuc   cookieSize = getArrayCookieSizeImpl(eltTy);
237f4a2713aSLionel Sambuc   allocPtr = CGF.Builder.CreateConstInBoundsGEP1_64(ptr,
238f4a2713aSLionel Sambuc                                                     -cookieSize.getQuantity());
239f4a2713aSLionel Sambuc   numElements = readArrayCookieImpl(CGF, allocPtr, cookieSize);
240f4a2713aSLionel Sambuc }
241f4a2713aSLionel Sambuc 
readArrayCookieImpl(CodeGenFunction & CGF,llvm::Value * ptr,CharUnits cookieSize)242f4a2713aSLionel Sambuc llvm::Value *CGCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
243f4a2713aSLionel Sambuc                                            llvm::Value *ptr,
244f4a2713aSLionel Sambuc                                            CharUnits cookieSize) {
245f4a2713aSLionel Sambuc   ErrorUnsupportedABI(CGF, "reading a new[] cookie");
246f4a2713aSLionel Sambuc   return llvm::ConstantInt::get(CGF.SizeTy, 0);
247f4a2713aSLionel Sambuc }
248f4a2713aSLionel Sambuc 
249f4a2713aSLionel Sambuc /// Returns the adjustment, in bytes, required for the given
250f4a2713aSLionel Sambuc /// member-pointer operation.  Returns null if no adjustment is
251f4a2713aSLionel Sambuc /// required.
getMemberPointerAdjustment(const CastExpr * E)252f4a2713aSLionel Sambuc llvm::Constant *CGCXXABI::getMemberPointerAdjustment(const CastExpr *E) {
253f4a2713aSLionel Sambuc   assert(E->getCastKind() == CK_DerivedToBaseMemberPointer ||
254f4a2713aSLionel Sambuc          E->getCastKind() == CK_BaseToDerivedMemberPointer);
255f4a2713aSLionel Sambuc 
256f4a2713aSLionel Sambuc   QualType derivedType;
257f4a2713aSLionel Sambuc   if (E->getCastKind() == CK_DerivedToBaseMemberPointer)
258f4a2713aSLionel Sambuc     derivedType = E->getSubExpr()->getType();
259f4a2713aSLionel Sambuc   else
260f4a2713aSLionel Sambuc     derivedType = E->getType();
261f4a2713aSLionel Sambuc 
262f4a2713aSLionel Sambuc   const CXXRecordDecl *derivedClass =
263f4a2713aSLionel Sambuc     derivedType->castAs<MemberPointerType>()->getClass()->getAsCXXRecordDecl();
264f4a2713aSLionel Sambuc 
265f4a2713aSLionel Sambuc   return CGM.GetNonVirtualBaseClassOffset(derivedClass,
266f4a2713aSLionel Sambuc                                           E->path_begin(),
267f4a2713aSLionel Sambuc                                           E->path_end());
268f4a2713aSLionel Sambuc }
269f4a2713aSLionel Sambuc 
getMemberPointerPathAdjustment(const APValue & MP)270f4a2713aSLionel Sambuc CharUnits CGCXXABI::getMemberPointerPathAdjustment(const APValue &MP) {
271f4a2713aSLionel Sambuc   // TODO: Store base specifiers in APValue member pointer paths so we can
272f4a2713aSLionel Sambuc   // easily reuse CGM.GetNonVirtualBaseClassOffset().
273f4a2713aSLionel Sambuc   const ValueDecl *MPD = MP.getMemberPointerDecl();
274f4a2713aSLionel Sambuc   CharUnits ThisAdjustment = CharUnits::Zero();
275f4a2713aSLionel Sambuc   ArrayRef<const CXXRecordDecl*> Path = MP.getMemberPointerPath();
276f4a2713aSLionel Sambuc   bool DerivedMember = MP.isMemberPointerToDerivedMember();
277f4a2713aSLionel Sambuc   const CXXRecordDecl *RD = cast<CXXRecordDecl>(MPD->getDeclContext());
278f4a2713aSLionel Sambuc   for (unsigned I = 0, N = Path.size(); I != N; ++I) {
279f4a2713aSLionel Sambuc     const CXXRecordDecl *Base = RD;
280f4a2713aSLionel Sambuc     const CXXRecordDecl *Derived = Path[I];
281f4a2713aSLionel Sambuc     if (DerivedMember)
282f4a2713aSLionel Sambuc       std::swap(Base, Derived);
283f4a2713aSLionel Sambuc     ThisAdjustment +=
284f4a2713aSLionel Sambuc       getContext().getASTRecordLayout(Derived).getBaseClassOffset(Base);
285f4a2713aSLionel Sambuc     RD = Path[I];
286f4a2713aSLionel Sambuc   }
287f4a2713aSLionel Sambuc   if (DerivedMember)
288f4a2713aSLionel Sambuc     ThisAdjustment = -ThisAdjustment;
289f4a2713aSLionel Sambuc   return ThisAdjustment;
290f4a2713aSLionel Sambuc }
291f4a2713aSLionel Sambuc 
292f4a2713aSLionel Sambuc llvm::BasicBlock *
EmitCtorCompleteObjectHandler(CodeGenFunction & CGF,const CXXRecordDecl * RD)293f4a2713aSLionel Sambuc CGCXXABI::EmitCtorCompleteObjectHandler(CodeGenFunction &CGF,
294f4a2713aSLionel Sambuc                                         const CXXRecordDecl *RD) {
295f4a2713aSLionel Sambuc   if (CGM.getTarget().getCXXABI().hasConstructorVariants())
296f4a2713aSLionel Sambuc     llvm_unreachable("shouldn't be called in this ABI");
297f4a2713aSLionel Sambuc 
298f4a2713aSLionel Sambuc   ErrorUnsupportedABI(CGF, "complete object detection in ctor");
299*0a6a1f1dSLionel Sambuc   return nullptr;
300f4a2713aSLionel Sambuc }
301f4a2713aSLionel Sambuc 
NeedsVTTParameter(GlobalDecl GD)302f4a2713aSLionel Sambuc bool CGCXXABI::NeedsVTTParameter(GlobalDecl GD) {
303f4a2713aSLionel Sambuc   return false;
304f4a2713aSLionel Sambuc }
305