1f4a2713aSLionel Sambuc //===--- CGCXX.cpp - Emit LLVM Code for declarations ----------------------===//
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 contains code dealing with C++ code generation.
11f4a2713aSLionel Sambuc //
12f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
13f4a2713aSLionel Sambuc
14f4a2713aSLionel Sambuc // We might split this into multiple files if it gets too unwieldy
15f4a2713aSLionel Sambuc
16f4a2713aSLionel Sambuc #include "CodeGenModule.h"
17f4a2713aSLionel Sambuc #include "CGCXXABI.h"
18f4a2713aSLionel Sambuc #include "CodeGenFunction.h"
19f4a2713aSLionel Sambuc #include "clang/AST/ASTContext.h"
20f4a2713aSLionel Sambuc #include "clang/AST/Decl.h"
21f4a2713aSLionel Sambuc #include "clang/AST/DeclCXX.h"
22f4a2713aSLionel Sambuc #include "clang/AST/DeclObjC.h"
23f4a2713aSLionel Sambuc #include "clang/AST/Mangle.h"
24f4a2713aSLionel Sambuc #include "clang/AST/RecordLayout.h"
25f4a2713aSLionel Sambuc #include "clang/AST/StmtCXX.h"
26f4a2713aSLionel Sambuc #include "clang/Frontend/CodeGenOptions.h"
27f4a2713aSLionel Sambuc #include "llvm/ADT/StringExtras.h"
28f4a2713aSLionel Sambuc using namespace clang;
29f4a2713aSLionel Sambuc using namespace CodeGen;
30f4a2713aSLionel Sambuc
31f4a2713aSLionel Sambuc /// Try to emit a base destructor as an alias to its primary
32f4a2713aSLionel Sambuc /// base-class destructor.
TryEmitBaseDestructorAsAlias(const CXXDestructorDecl * D)33f4a2713aSLionel Sambuc bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) {
34f4a2713aSLionel Sambuc if (!getCodeGenOpts().CXXCtorDtorAliases)
35f4a2713aSLionel Sambuc return true;
36f4a2713aSLionel Sambuc
37f4a2713aSLionel Sambuc // Producing an alias to a base class ctor/dtor can degrade debug quality
38*0a6a1f1dSLionel Sambuc // as the debugger cannot tell them apart.
39f4a2713aSLionel Sambuc if (getCodeGenOpts().OptimizationLevel == 0)
40f4a2713aSLionel Sambuc return true;
41f4a2713aSLionel Sambuc
42f4a2713aSLionel Sambuc // If the destructor doesn't have a trivial body, we have to emit it
43f4a2713aSLionel Sambuc // separately.
44f4a2713aSLionel Sambuc if (!D->hasTrivialBody())
45f4a2713aSLionel Sambuc return true;
46f4a2713aSLionel Sambuc
47f4a2713aSLionel Sambuc const CXXRecordDecl *Class = D->getParent();
48f4a2713aSLionel Sambuc
49*0a6a1f1dSLionel Sambuc // We are going to instrument this destructor, so give up even if it is
50*0a6a1f1dSLionel Sambuc // currently empty.
51*0a6a1f1dSLionel Sambuc if (Class->mayInsertExtraPadding())
52*0a6a1f1dSLionel Sambuc return true;
53*0a6a1f1dSLionel Sambuc
54f4a2713aSLionel Sambuc // If we need to manipulate a VTT parameter, give up.
55f4a2713aSLionel Sambuc if (Class->getNumVBases()) {
56f4a2713aSLionel Sambuc // Extra Credit: passing extra parameters is perfectly safe
57f4a2713aSLionel Sambuc // in many calling conventions, so only bail out if the ctor's
58f4a2713aSLionel Sambuc // calling convention is nonstandard.
59f4a2713aSLionel Sambuc return true;
60f4a2713aSLionel Sambuc }
61f4a2713aSLionel Sambuc
62f4a2713aSLionel Sambuc // If any field has a non-trivial destructor, we have to emit the
63f4a2713aSLionel Sambuc // destructor separately.
64*0a6a1f1dSLionel Sambuc for (const auto *I : Class->fields())
65f4a2713aSLionel Sambuc if (I->getType().isDestructedType())
66f4a2713aSLionel Sambuc return true;
67f4a2713aSLionel Sambuc
68f4a2713aSLionel Sambuc // Try to find a unique base class with a non-trivial destructor.
69*0a6a1f1dSLionel Sambuc const CXXRecordDecl *UniqueBase = nullptr;
70*0a6a1f1dSLionel Sambuc for (const auto &I : Class->bases()) {
71f4a2713aSLionel Sambuc
72f4a2713aSLionel Sambuc // We're in the base destructor, so skip virtual bases.
73*0a6a1f1dSLionel Sambuc if (I.isVirtual()) continue;
74f4a2713aSLionel Sambuc
75f4a2713aSLionel Sambuc // Skip base classes with trivial destructors.
76*0a6a1f1dSLionel Sambuc const auto *Base =
77*0a6a1f1dSLionel Sambuc cast<CXXRecordDecl>(I.getType()->getAs<RecordType>()->getDecl());
78f4a2713aSLionel Sambuc if (Base->hasTrivialDestructor()) continue;
79f4a2713aSLionel Sambuc
80f4a2713aSLionel Sambuc // If we've already found a base class with a non-trivial
81f4a2713aSLionel Sambuc // destructor, give up.
82f4a2713aSLionel Sambuc if (UniqueBase) return true;
83f4a2713aSLionel Sambuc UniqueBase = Base;
84f4a2713aSLionel Sambuc }
85f4a2713aSLionel Sambuc
86f4a2713aSLionel Sambuc // If we didn't find any bases with a non-trivial destructor, then
87f4a2713aSLionel Sambuc // the base destructor is actually effectively trivial, which can
88f4a2713aSLionel Sambuc // happen if it was needlessly user-defined or if there are virtual
89f4a2713aSLionel Sambuc // bases with non-trivial destructors.
90f4a2713aSLionel Sambuc if (!UniqueBase)
91f4a2713aSLionel Sambuc return true;
92f4a2713aSLionel Sambuc
93f4a2713aSLionel Sambuc // If the base is at a non-zero offset, give up.
94f4a2713aSLionel Sambuc const ASTRecordLayout &ClassLayout = Context.getASTRecordLayout(Class);
95f4a2713aSLionel Sambuc if (!ClassLayout.getBaseClassOffset(UniqueBase).isZero())
96f4a2713aSLionel Sambuc return true;
97f4a2713aSLionel Sambuc
98*0a6a1f1dSLionel Sambuc // Give up if the calling conventions don't match. We could update the call,
99*0a6a1f1dSLionel Sambuc // but it is probably not worth it.
100f4a2713aSLionel Sambuc const CXXDestructorDecl *BaseD = UniqueBase->getDestructor();
101*0a6a1f1dSLionel Sambuc if (BaseD->getType()->getAs<FunctionType>()->getCallConv() !=
102*0a6a1f1dSLionel Sambuc D->getType()->getAs<FunctionType>()->getCallConv())
103*0a6a1f1dSLionel Sambuc return true;
104*0a6a1f1dSLionel Sambuc
105f4a2713aSLionel Sambuc return TryEmitDefinitionAsAlias(GlobalDecl(D, Dtor_Base),
106f4a2713aSLionel Sambuc GlobalDecl(BaseD, Dtor_Base),
107f4a2713aSLionel Sambuc false);
108f4a2713aSLionel Sambuc }
109f4a2713aSLionel Sambuc
110f4a2713aSLionel Sambuc /// Try to emit a definition as a global alias for another definition.
111f4a2713aSLionel Sambuc /// If \p InEveryTU is true, we know that an equivalent alias can be produced
112f4a2713aSLionel Sambuc /// in every translation unit.
TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,GlobalDecl TargetDecl,bool InEveryTU)113f4a2713aSLionel Sambuc bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
114f4a2713aSLionel Sambuc GlobalDecl TargetDecl,
115f4a2713aSLionel Sambuc bool InEveryTU) {
116f4a2713aSLionel Sambuc if (!getCodeGenOpts().CXXCtorDtorAliases)
117f4a2713aSLionel Sambuc return true;
118f4a2713aSLionel Sambuc
119*0a6a1f1dSLionel Sambuc // The alias will use the linkage of the referent. If we can't
120f4a2713aSLionel Sambuc // support aliases with that linkage, fail.
121f4a2713aSLionel Sambuc llvm::GlobalValue::LinkageTypes Linkage = getFunctionLinkage(AliasDecl);
122f4a2713aSLionel Sambuc
123f4a2713aSLionel Sambuc // We can't use an alias if the linkage is not valid for one.
124f4a2713aSLionel Sambuc if (!llvm::GlobalAlias::isValidLinkage(Linkage))
125f4a2713aSLionel Sambuc return true;
126f4a2713aSLionel Sambuc
127*0a6a1f1dSLionel Sambuc // Don't create a weak alias for a dllexport'd symbol.
128*0a6a1f1dSLionel Sambuc if (AliasDecl.getDecl()->hasAttr<DLLExportAttr>() &&
129*0a6a1f1dSLionel Sambuc llvm::GlobalValue::isWeakForLinker(Linkage))
130*0a6a1f1dSLionel Sambuc return true;
131*0a6a1f1dSLionel Sambuc
132f4a2713aSLionel Sambuc llvm::GlobalValue::LinkageTypes TargetLinkage =
133f4a2713aSLionel Sambuc getFunctionLinkage(TargetDecl);
134f4a2713aSLionel Sambuc
135f4a2713aSLionel Sambuc // Check if we have it already.
136f4a2713aSLionel Sambuc StringRef MangledName = getMangledName(AliasDecl);
137f4a2713aSLionel Sambuc llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
138f4a2713aSLionel Sambuc if (Entry && !Entry->isDeclaration())
139f4a2713aSLionel Sambuc return false;
140f4a2713aSLionel Sambuc if (Replacements.count(MangledName))
141f4a2713aSLionel Sambuc return false;
142f4a2713aSLionel Sambuc
143f4a2713aSLionel Sambuc // Derive the type for the alias.
144f4a2713aSLionel Sambuc llvm::PointerType *AliasType
145f4a2713aSLionel Sambuc = getTypes().GetFunctionType(AliasDecl)->getPointerTo();
146f4a2713aSLionel Sambuc
147*0a6a1f1dSLionel Sambuc // Find the referent. Some aliases might require a bitcast, in
148f4a2713aSLionel Sambuc // which case the caller is responsible for ensuring the soundness
149f4a2713aSLionel Sambuc // of these semantics.
150*0a6a1f1dSLionel Sambuc auto *Ref = cast<llvm::GlobalValue>(GetAddrOfGlobal(TargetDecl));
151f4a2713aSLionel Sambuc llvm::Constant *Aliasee = Ref;
152f4a2713aSLionel Sambuc if (Ref->getType() != AliasType)
153f4a2713aSLionel Sambuc Aliasee = llvm::ConstantExpr::getBitCast(Ref, AliasType);
154f4a2713aSLionel Sambuc
155f4a2713aSLionel Sambuc // Instead of creating as alias to a linkonce_odr, replace all of the uses
156*0a6a1f1dSLionel Sambuc // of the aliasee.
157f4a2713aSLionel Sambuc if (llvm::GlobalValue::isDiscardableIfUnused(Linkage) &&
158f4a2713aSLionel Sambuc (TargetLinkage != llvm::GlobalValue::AvailableExternallyLinkage ||
159f4a2713aSLionel Sambuc !TargetDecl.getDecl()->hasAttr<AlwaysInlineAttr>())) {
160*0a6a1f1dSLionel Sambuc // FIXME: An extern template instantiation will create functions with
161f4a2713aSLionel Sambuc // linkage "AvailableExternally". In libc++, some classes also define
162f4a2713aSLionel Sambuc // members with attribute "AlwaysInline" and expect no reference to
163f4a2713aSLionel Sambuc // be generated. It is desirable to reenable this optimisation after
164f4a2713aSLionel Sambuc // corresponding LLVM changes.
165f4a2713aSLionel Sambuc Replacements[MangledName] = Aliasee;
166f4a2713aSLionel Sambuc return false;
167f4a2713aSLionel Sambuc }
168f4a2713aSLionel Sambuc
169f4a2713aSLionel Sambuc if (!InEveryTU) {
170*0a6a1f1dSLionel Sambuc // If we don't have a definition for the destructor yet, don't
171*0a6a1f1dSLionel Sambuc // emit. We can't emit aliases to declarations; that's just not
172*0a6a1f1dSLionel Sambuc // how aliases work.
173f4a2713aSLionel Sambuc if (Ref->isDeclaration())
174f4a2713aSLionel Sambuc return true;
175f4a2713aSLionel Sambuc }
176f4a2713aSLionel Sambuc
177f4a2713aSLionel Sambuc // Don't create an alias to a linker weak symbol. This avoids producing
178f4a2713aSLionel Sambuc // different COMDATs in different TUs. Another option would be to
179f4a2713aSLionel Sambuc // output the alias both for weak_odr and linkonce_odr, but that
180f4a2713aSLionel Sambuc // requires explicit comdat support in the IL.
181f4a2713aSLionel Sambuc if (llvm::GlobalValue::isWeakForLinker(TargetLinkage))
182f4a2713aSLionel Sambuc return true;
183f4a2713aSLionel Sambuc
184f4a2713aSLionel Sambuc // Create the alias with no name.
185*0a6a1f1dSLionel Sambuc auto *Alias = llvm::GlobalAlias::create(AliasType->getElementType(), 0,
186*0a6a1f1dSLionel Sambuc Linkage, "", Aliasee, &getModule());
187f4a2713aSLionel Sambuc
188f4a2713aSLionel Sambuc // Switch any previous uses to the alias.
189f4a2713aSLionel Sambuc if (Entry) {
190f4a2713aSLionel Sambuc assert(Entry->getType() == AliasType &&
191f4a2713aSLionel Sambuc "declaration exists with different type");
192f4a2713aSLionel Sambuc Alias->takeName(Entry);
193f4a2713aSLionel Sambuc Entry->replaceAllUsesWith(Alias);
194f4a2713aSLionel Sambuc Entry->eraseFromParent();
195f4a2713aSLionel Sambuc } else {
196f4a2713aSLionel Sambuc Alias->setName(MangledName);
197f4a2713aSLionel Sambuc }
198f4a2713aSLionel Sambuc
199f4a2713aSLionel Sambuc // Finally, set up the alias with its proper name and attributes.
200*0a6a1f1dSLionel Sambuc setAliasAttributes(cast<NamedDecl>(AliasDecl.getDecl()), Alias);
201f4a2713aSLionel Sambuc
202f4a2713aSLionel Sambuc return false;
203f4a2713aSLionel Sambuc }
204f4a2713aSLionel Sambuc
codegenCXXStructor(const CXXMethodDecl * MD,StructorType Type)205*0a6a1f1dSLionel Sambuc llvm::Function *CodeGenModule::codegenCXXStructor(const CXXMethodDecl *MD,
206*0a6a1f1dSLionel Sambuc StructorType Type) {
207*0a6a1f1dSLionel Sambuc const CGFunctionInfo &FnInfo =
208*0a6a1f1dSLionel Sambuc getTypes().arrangeCXXStructorDeclaration(MD, Type);
209*0a6a1f1dSLionel Sambuc auto *Fn = cast<llvm::Function>(
210*0a6a1f1dSLionel Sambuc getAddrOfCXXStructor(MD, Type, &FnInfo, nullptr, true));
211*0a6a1f1dSLionel Sambuc
212*0a6a1f1dSLionel Sambuc GlobalDecl GD;
213*0a6a1f1dSLionel Sambuc if (const auto *DD = dyn_cast<CXXDestructorDecl>(MD)) {
214*0a6a1f1dSLionel Sambuc GD = GlobalDecl(DD, toCXXDtorType(Type));
215*0a6a1f1dSLionel Sambuc } else {
216*0a6a1f1dSLionel Sambuc const auto *CD = cast<CXXConstructorDecl>(MD);
217*0a6a1f1dSLionel Sambuc GD = GlobalDecl(CD, toCXXCtorType(Type));
218f4a2713aSLionel Sambuc }
219f4a2713aSLionel Sambuc
220*0a6a1f1dSLionel Sambuc setFunctionLinkage(GD, Fn);
221*0a6a1f1dSLionel Sambuc CodeGenFunction(*this).GenerateCode(GD, Fn, FnInfo);
222*0a6a1f1dSLionel Sambuc setFunctionDefinitionAttributes(MD, Fn);
223*0a6a1f1dSLionel Sambuc SetLLVMFunctionAttributesForDefinition(MD, Fn);
224*0a6a1f1dSLionel Sambuc return Fn;
225f4a2713aSLionel Sambuc }
226f4a2713aSLionel Sambuc
getAddrOfCXXStructor(const CXXMethodDecl * MD,StructorType Type,const CGFunctionInfo * FnInfo,llvm::FunctionType * FnType,bool DontDefer)227*0a6a1f1dSLionel Sambuc llvm::GlobalValue *CodeGenModule::getAddrOfCXXStructor(
228*0a6a1f1dSLionel Sambuc const CXXMethodDecl *MD, StructorType Type, const CGFunctionInfo *FnInfo,
229*0a6a1f1dSLionel Sambuc llvm::FunctionType *FnType, bool DontDefer) {
230*0a6a1f1dSLionel Sambuc GlobalDecl GD;
231*0a6a1f1dSLionel Sambuc if (auto *CD = dyn_cast<CXXConstructorDecl>(MD)) {
232*0a6a1f1dSLionel Sambuc GD = GlobalDecl(CD, toCXXCtorType(Type));
233*0a6a1f1dSLionel Sambuc } else {
234*0a6a1f1dSLionel Sambuc auto *DD = dyn_cast<CXXDestructorDecl>(MD);
235*0a6a1f1dSLionel Sambuc GD = GlobalDecl(DD, toCXXDtorType(Type));
236f4a2713aSLionel Sambuc }
237f4a2713aSLionel Sambuc
238*0a6a1f1dSLionel Sambuc StringRef Name = getMangledName(GD);
239*0a6a1f1dSLionel Sambuc if (llvm::GlobalValue *Existing = GetGlobalValue(Name))
240*0a6a1f1dSLionel Sambuc return Existing;
241*0a6a1f1dSLionel Sambuc
242*0a6a1f1dSLionel Sambuc if (!FnType) {
243*0a6a1f1dSLionel Sambuc if (!FnInfo)
244*0a6a1f1dSLionel Sambuc FnInfo = &getTypes().arrangeCXXStructorDeclaration(MD, Type);
245*0a6a1f1dSLionel Sambuc FnType = getTypes().GetFunctionType(*FnInfo);
246f4a2713aSLionel Sambuc }
247f4a2713aSLionel Sambuc
248*0a6a1f1dSLionel Sambuc return cast<llvm::Function>(GetOrCreateLLVMFunction(Name, FnType, GD,
249*0a6a1f1dSLionel Sambuc /*ForVTable=*/false,
250*0a6a1f1dSLionel Sambuc DontDefer));
251f4a2713aSLionel Sambuc }
252f4a2713aSLionel Sambuc
BuildAppleKextVirtualCall(CodeGenFunction & CGF,GlobalDecl GD,llvm::Type * Ty,const CXXRecordDecl * RD)253f4a2713aSLionel Sambuc static llvm::Value *BuildAppleKextVirtualCall(CodeGenFunction &CGF,
254f4a2713aSLionel Sambuc GlobalDecl GD,
255f4a2713aSLionel Sambuc llvm::Type *Ty,
256f4a2713aSLionel Sambuc const CXXRecordDecl *RD) {
257f4a2713aSLionel Sambuc assert(!CGF.CGM.getTarget().getCXXABI().isMicrosoft() &&
258f4a2713aSLionel Sambuc "No kext in Microsoft ABI");
259f4a2713aSLionel Sambuc GD = GD.getCanonicalDecl();
260f4a2713aSLionel Sambuc CodeGenModule &CGM = CGF.CGM;
261f4a2713aSLionel Sambuc llvm::Value *VTable = CGM.getCXXABI().getAddrOfVTable(RD, CharUnits());
262f4a2713aSLionel Sambuc Ty = Ty->getPointerTo()->getPointerTo();
263f4a2713aSLionel Sambuc VTable = CGF.Builder.CreateBitCast(VTable, Ty);
264f4a2713aSLionel Sambuc assert(VTable && "BuildVirtualCall = kext vtbl pointer is null");
265f4a2713aSLionel Sambuc uint64_t VTableIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(GD);
266f4a2713aSLionel Sambuc uint64_t AddressPoint =
267f4a2713aSLionel Sambuc CGM.getItaniumVTableContext().getVTableLayout(RD)
268f4a2713aSLionel Sambuc .getAddressPoint(BaseSubobject(RD, CharUnits::Zero()));
269f4a2713aSLionel Sambuc VTableIndex += AddressPoint;
270f4a2713aSLionel Sambuc llvm::Value *VFuncPtr =
271f4a2713aSLionel Sambuc CGF.Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfnkxt");
272f4a2713aSLionel Sambuc return CGF.Builder.CreateLoad(VFuncPtr);
273f4a2713aSLionel Sambuc }
274f4a2713aSLionel Sambuc
275f4a2713aSLionel Sambuc /// BuildAppleKextVirtualCall - This routine is to support gcc's kext ABI making
276f4a2713aSLionel Sambuc /// indirect call to virtual functions. It makes the call through indexing
277f4a2713aSLionel Sambuc /// into the vtable.
278f4a2713aSLionel Sambuc llvm::Value *
BuildAppleKextVirtualCall(const CXXMethodDecl * MD,NestedNameSpecifier * Qual,llvm::Type * Ty)279f4a2713aSLionel Sambuc CodeGenFunction::BuildAppleKextVirtualCall(const CXXMethodDecl *MD,
280f4a2713aSLionel Sambuc NestedNameSpecifier *Qual,
281f4a2713aSLionel Sambuc llvm::Type *Ty) {
282f4a2713aSLionel Sambuc assert((Qual->getKind() == NestedNameSpecifier::TypeSpec) &&
283f4a2713aSLionel Sambuc "BuildAppleKextVirtualCall - bad Qual kind");
284f4a2713aSLionel Sambuc
285f4a2713aSLionel Sambuc const Type *QTy = Qual->getAsType();
286f4a2713aSLionel Sambuc QualType T = QualType(QTy, 0);
287f4a2713aSLionel Sambuc const RecordType *RT = T->getAs<RecordType>();
288f4a2713aSLionel Sambuc assert(RT && "BuildAppleKextVirtualCall - Qual type must be record");
289*0a6a1f1dSLionel Sambuc const auto *RD = cast<CXXRecordDecl>(RT->getDecl());
290f4a2713aSLionel Sambuc
291*0a6a1f1dSLionel Sambuc if (const auto *DD = dyn_cast<CXXDestructorDecl>(MD))
292f4a2713aSLionel Sambuc return BuildAppleKextVirtualDestructorCall(DD, Dtor_Complete, RD);
293f4a2713aSLionel Sambuc
294f4a2713aSLionel Sambuc return ::BuildAppleKextVirtualCall(*this, MD, Ty, RD);
295f4a2713aSLionel Sambuc }
296f4a2713aSLionel Sambuc
297f4a2713aSLionel Sambuc /// BuildVirtualCall - This routine makes indirect vtable call for
298f4a2713aSLionel Sambuc /// call to virtual destructors. It returns 0 if it could not do it.
299f4a2713aSLionel Sambuc llvm::Value *
BuildAppleKextVirtualDestructorCall(const CXXDestructorDecl * DD,CXXDtorType Type,const CXXRecordDecl * RD)300f4a2713aSLionel Sambuc CodeGenFunction::BuildAppleKextVirtualDestructorCall(
301f4a2713aSLionel Sambuc const CXXDestructorDecl *DD,
302f4a2713aSLionel Sambuc CXXDtorType Type,
303f4a2713aSLionel Sambuc const CXXRecordDecl *RD) {
304*0a6a1f1dSLionel Sambuc const auto *MD = cast<CXXMethodDecl>(DD);
305f4a2713aSLionel Sambuc // FIXME. Dtor_Base dtor is always direct!!
306f4a2713aSLionel Sambuc // It need be somehow inline expanded into the caller.
307f4a2713aSLionel Sambuc // -O does that. But need to support -O0 as well.
308f4a2713aSLionel Sambuc if (MD->isVirtual() && Type != Dtor_Base) {
309f4a2713aSLionel Sambuc // Compute the function type we're calling.
310*0a6a1f1dSLionel Sambuc const CGFunctionInfo &FInfo = CGM.getTypes().arrangeCXXStructorDeclaration(
311*0a6a1f1dSLionel Sambuc DD, StructorType::Complete);
312f4a2713aSLionel Sambuc llvm::Type *Ty = CGM.getTypes().GetFunctionType(FInfo);
313f4a2713aSLionel Sambuc return ::BuildAppleKextVirtualCall(*this, GlobalDecl(DD, Type), Ty, RD);
314f4a2713aSLionel Sambuc }
315*0a6a1f1dSLionel Sambuc return nullptr;
316f4a2713aSLionel Sambuc }
317