145b53394SDimitry Andric //===--- CGClass.cpp - Emit LLVM Code for C++ classes -----------*- C++ -*-===//
21569ce68SRoman Divacky //
322989816SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
422989816SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
522989816SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61569ce68SRoman Divacky //
71569ce68SRoman Divacky //===----------------------------------------------------------------------===//
81569ce68SRoman Divacky //
91569ce68SRoman Divacky // This contains code dealing with C++ code generation of classes
101569ce68SRoman Divacky //
111569ce68SRoman Divacky //===----------------------------------------------------------------------===//
121569ce68SRoman Divacky
13ac9a064cSDimitry Andric #include "ABIInfoImpl.h"
14dbe13110SDimitry Andric #include "CGBlocks.h"
159f4dbff6SDimitry Andric #include "CGCXXABI.h"
163d1dcd9bSDimitry Andric #include "CGDebugInfo.h"
17809500fcSDimitry Andric #include "CGRecordLayout.h"
181569ce68SRoman Divacky #include "CodeGenFunction.h"
19676fbe81SDimitry Andric #include "TargetInfo.h"
20706b4fc4SDimitry Andric #include "clang/AST/Attr.h"
211569ce68SRoman Divacky #include "clang/AST/CXXInheritance.h"
22b60736ecSDimitry Andric #include "clang/AST/CharUnits.h"
23bfef3995SDimitry Andric #include "clang/AST/DeclTemplate.h"
24bca07a45SDimitry Andric #include "clang/AST/EvaluatedExprVisitor.h"
251569ce68SRoman Divacky #include "clang/AST/RecordLayout.h"
2679ade4e0SRoman Divacky #include "clang/AST/StmtCXX.h"
27676fbe81SDimitry Andric #include "clang/Basic/CodeGenOptions.h"
28809500fcSDimitry Andric #include "clang/Basic/TargetBuiltins.h"
29bfef3995SDimitry Andric #include "clang/CodeGen/CGFunctionInfo.h"
305e20cdd8SDimitry Andric #include "llvm/IR/Intrinsics.h"
3145b53394SDimitry Andric #include "llvm/IR/Metadata.h"
32b1c73532SDimitry Andric #include "llvm/Support/SaveAndRestore.h"
332b6b257fSDimitry Andric #include "llvm/Transforms/Utils/SanitizerStats.h"
34e3b55780SDimitry Andric #include <optional>
351569ce68SRoman Divacky
361569ce68SRoman Divacky using namespace clang;
371569ce68SRoman Divacky using namespace CodeGen;
381569ce68SRoman Divacky
3945b53394SDimitry Andric /// Return the best known alignment for an unknown pointer to a
4045b53394SDimitry Andric /// particular class.
getClassPointerAlignment(const CXXRecordDecl * RD)4145b53394SDimitry Andric CharUnits CodeGenModule::getClassPointerAlignment(const CXXRecordDecl *RD) {
42cfca06d7SDimitry Andric if (!RD->hasDefinition())
4345b53394SDimitry Andric return CharUnits::One(); // Hopefully won't be used anywhere.
4445b53394SDimitry Andric
4545b53394SDimitry Andric auto &layout = getContext().getASTRecordLayout(RD);
4645b53394SDimitry Andric
4745b53394SDimitry Andric // If the class is final, then we know that the pointer points to an
4845b53394SDimitry Andric // object of that type and can use the full alignment.
49cfca06d7SDimitry Andric if (RD->isEffectivelyFinal())
5045b53394SDimitry Andric return layout.getAlignment();
5145b53394SDimitry Andric
5245b53394SDimitry Andric // Otherwise, we have to assume it could be a subclass.
5345b53394SDimitry Andric return layout.getNonVirtualAlignment();
5445b53394SDimitry Andric }
55cfca06d7SDimitry Andric
56cfca06d7SDimitry Andric /// Return the smallest possible amount of storage that might be allocated
57cfca06d7SDimitry Andric /// starting from the beginning of an object of a particular class.
58cfca06d7SDimitry Andric ///
59cfca06d7SDimitry Andric /// This may be smaller than sizeof(RD) if RD has virtual base classes.
getMinimumClassObjectSize(const CXXRecordDecl * RD)60cfca06d7SDimitry Andric CharUnits CodeGenModule::getMinimumClassObjectSize(const CXXRecordDecl *RD) {
61cfca06d7SDimitry Andric if (!RD->hasDefinition())
62cfca06d7SDimitry Andric return CharUnits::One();
63cfca06d7SDimitry Andric
64cfca06d7SDimitry Andric auto &layout = getContext().getASTRecordLayout(RD);
65cfca06d7SDimitry Andric
66cfca06d7SDimitry Andric // If the class is final, then we know that the pointer points to an
67cfca06d7SDimitry Andric // object of that type and can use the full alignment.
68cfca06d7SDimitry Andric if (RD->isEffectivelyFinal())
69cfca06d7SDimitry Andric return layout.getSize();
70cfca06d7SDimitry Andric
71cfca06d7SDimitry Andric // Otherwise, we have to assume it could be a subclass.
72cfca06d7SDimitry Andric return std::max(layout.getNonVirtualSize(), CharUnits::One());
7345b53394SDimitry Andric }
7445b53394SDimitry Andric
7545b53394SDimitry Andric /// Return the best known alignment for a pointer to a virtual base,
7645b53394SDimitry Andric /// given the alignment of a pointer to the derived class.
getVBaseAlignment(CharUnits actualDerivedAlign,const CXXRecordDecl * derivedClass,const CXXRecordDecl * vbaseClass)7745b53394SDimitry Andric CharUnits CodeGenModule::getVBaseAlignment(CharUnits actualDerivedAlign,
7845b53394SDimitry Andric const CXXRecordDecl *derivedClass,
7945b53394SDimitry Andric const CXXRecordDecl *vbaseClass) {
8045b53394SDimitry Andric // The basic idea here is that an underaligned derived pointer might
8145b53394SDimitry Andric // indicate an underaligned base pointer.
8245b53394SDimitry Andric
8345b53394SDimitry Andric assert(vbaseClass->isCompleteDefinition());
8445b53394SDimitry Andric auto &baseLayout = getContext().getASTRecordLayout(vbaseClass);
8545b53394SDimitry Andric CharUnits expectedVBaseAlign = baseLayout.getNonVirtualAlignment();
8645b53394SDimitry Andric
8745b53394SDimitry Andric return getDynamicOffsetAlignment(actualDerivedAlign, derivedClass,
8845b53394SDimitry Andric expectedVBaseAlign);
8945b53394SDimitry Andric }
9045b53394SDimitry Andric
9145b53394SDimitry Andric CharUnits
getDynamicOffsetAlignment(CharUnits actualBaseAlign,const CXXRecordDecl * baseDecl,CharUnits expectedTargetAlign)9245b53394SDimitry Andric CodeGenModule::getDynamicOffsetAlignment(CharUnits actualBaseAlign,
9345b53394SDimitry Andric const CXXRecordDecl *baseDecl,
9445b53394SDimitry Andric CharUnits expectedTargetAlign) {
9545b53394SDimitry Andric // If the base is an incomplete type (which is, alas, possible with
9645b53394SDimitry Andric // member pointers), be pessimistic.
9745b53394SDimitry Andric if (!baseDecl->isCompleteDefinition())
9845b53394SDimitry Andric return std::min(actualBaseAlign, expectedTargetAlign);
9945b53394SDimitry Andric
10045b53394SDimitry Andric auto &baseLayout = getContext().getASTRecordLayout(baseDecl);
10145b53394SDimitry Andric CharUnits expectedBaseAlign = baseLayout.getNonVirtualAlignment();
10245b53394SDimitry Andric
10345b53394SDimitry Andric // If the class is properly aligned, assume the target offset is, too.
10445b53394SDimitry Andric //
10545b53394SDimitry Andric // This actually isn't necessarily the right thing to do --- if the
10645b53394SDimitry Andric // class is a complete object, but it's only properly aligned for a
10745b53394SDimitry Andric // base subobject, then the alignments of things relative to it are
10845b53394SDimitry Andric // probably off as well. (Note that this requires the alignment of
10945b53394SDimitry Andric // the target to be greater than the NV alignment of the derived
11045b53394SDimitry Andric // class.)
11145b53394SDimitry Andric //
11245b53394SDimitry Andric // However, our approach to this kind of under-alignment can only
11345b53394SDimitry Andric // ever be best effort; after all, we're never going to propagate
11445b53394SDimitry Andric // alignments through variables or parameters. Note, in particular,
11545b53394SDimitry Andric // that constructing a polymorphic type in an address that's less
11645b53394SDimitry Andric // than pointer-aligned will generally trap in the constructor,
11745b53394SDimitry Andric // unless we someday add some sort of attribute to change the
11845b53394SDimitry Andric // assumed alignment of 'this'. So our goal here is pretty much
11945b53394SDimitry Andric // just to allow the user to explicitly say that a pointer is
1202b6b257fSDimitry Andric // under-aligned and then safely access its fields and vtables.
12145b53394SDimitry Andric if (actualBaseAlign >= expectedBaseAlign) {
12245b53394SDimitry Andric return expectedTargetAlign;
12345b53394SDimitry Andric }
12445b53394SDimitry Andric
12545b53394SDimitry Andric // Otherwise, we might be offset by an arbitrary multiple of the
12645b53394SDimitry Andric // actual alignment. The correct adjustment is to take the min of
12745b53394SDimitry Andric // the two alignments.
12845b53394SDimitry Andric return std::min(actualBaseAlign, expectedTargetAlign);
12945b53394SDimitry Andric }
13045b53394SDimitry Andric
LoadCXXThisAddress()13145b53394SDimitry Andric Address CodeGenFunction::LoadCXXThisAddress() {
13245b53394SDimitry Andric assert(CurFuncDecl && "loading 'this' without a func declaration?");
13377fc4c14SDimitry Andric auto *MD = cast<CXXMethodDecl>(CurFuncDecl);
13445b53394SDimitry Andric
13545b53394SDimitry Andric // Lazily compute CXXThisAlignment.
13645b53394SDimitry Andric if (CXXThisAlignment.isZero()) {
13745b53394SDimitry Andric // Just use the best known alignment for the parent.
13845b53394SDimitry Andric // TODO: if we're currently emitting a complete-object ctor/dtor,
13945b53394SDimitry Andric // we can always use the complete-object alignment.
14077fc4c14SDimitry Andric CXXThisAlignment = CGM.getClassPointerAlignment(MD->getParent());
14145b53394SDimitry Andric }
14245b53394SDimitry Andric
143ac9a064cSDimitry Andric return makeNaturalAddressForPointer(
144ac9a064cSDimitry Andric LoadCXXThis(), MD->getFunctionObjectParameterType(), CXXThisAlignment,
145ac9a064cSDimitry Andric false, nullptr, nullptr, KnownNonNull);
14645b53394SDimitry Andric }
14745b53394SDimitry Andric
14845b53394SDimitry Andric /// Emit the address of a field using a member data pointer.
14945b53394SDimitry Andric ///
15045b53394SDimitry Andric /// \param E Only used for emergency diagnostics
15145b53394SDimitry Andric Address
EmitCXXMemberDataPointerAddress(const Expr * E,Address base,llvm::Value * memberPtr,const MemberPointerType * memberPtrType,LValueBaseInfo * BaseInfo,TBAAAccessInfo * TBAAInfo)15245b53394SDimitry Andric CodeGenFunction::EmitCXXMemberDataPointerAddress(const Expr *E, Address base,
15345b53394SDimitry Andric llvm::Value *memberPtr,
15445b53394SDimitry Andric const MemberPointerType *memberPtrType,
155461a67faSDimitry Andric LValueBaseInfo *BaseInfo,
156461a67faSDimitry Andric TBAAAccessInfo *TBAAInfo) {
15745b53394SDimitry Andric // Ask the ABI to compute the actual address.
15845b53394SDimitry Andric llvm::Value *ptr =
15945b53394SDimitry Andric CGM.getCXXABI().EmitMemberDataPointerAddress(*this, E, base,
16045b53394SDimitry Andric memberPtr, memberPtrType);
16145b53394SDimitry Andric
16245b53394SDimitry Andric QualType memberType = memberPtrType->getPointeeType();
163cfca06d7SDimitry Andric CharUnits memberAlign =
164cfca06d7SDimitry Andric CGM.getNaturalTypeAlignment(memberType, BaseInfo, TBAAInfo);
16545b53394SDimitry Andric memberAlign =
16645b53394SDimitry Andric CGM.getDynamicOffsetAlignment(base.getAlignment(),
16745b53394SDimitry Andric memberPtrType->getClass()->getAsCXXRecordDecl(),
16845b53394SDimitry Andric memberAlign);
169ecbca9f5SDimitry Andric return Address(ptr, ConvertTypeForMem(memberPtrType->getPointeeType()),
170ecbca9f5SDimitry Andric memberAlign);
17145b53394SDimitry Andric }
17245b53394SDimitry Andric
computeNonVirtualBaseClassOffset(const CXXRecordDecl * DerivedClass,CastExpr::path_const_iterator Start,CastExpr::path_const_iterator End)173c192b3dcSDimitry Andric CharUnits CodeGenModule::computeNonVirtualBaseClassOffset(
174c192b3dcSDimitry Andric const CXXRecordDecl *DerivedClass, CastExpr::path_const_iterator Start,
1753d1dcd9bSDimitry Andric CastExpr::path_const_iterator End) {
17601af97d3SDimitry Andric CharUnits Offset = CharUnits::Zero();
1771569ce68SRoman Divacky
178c192b3dcSDimitry Andric const ASTContext &Context = getContext();
1790883ccd9SRoman Divacky const CXXRecordDecl *RD = DerivedClass;
1800883ccd9SRoman Divacky
1813d1dcd9bSDimitry Andric for (CastExpr::path_const_iterator I = Start; I != End; ++I) {
1820883ccd9SRoman Divacky const CXXBaseSpecifier *Base = *I;
1830883ccd9SRoman Divacky assert(!Base->isVirtual() && "Should not see virtual bases here!");
1841569ce68SRoman Divacky
1851569ce68SRoman Divacky // Get the layout.
1860883ccd9SRoman Divacky const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
1871569ce68SRoman Divacky
188519fc96cSDimitry Andric const auto *BaseDecl =
189519fc96cSDimitry Andric cast<CXXRecordDecl>(Base->getType()->castAs<RecordType>()->getDecl());
1901569ce68SRoman Divacky
1911569ce68SRoman Divacky // Add the offset.
19201af97d3SDimitry Andric Offset += Layout.getBaseClassOffset(BaseDecl);
1930883ccd9SRoman Divacky
1940883ccd9SRoman Divacky RD = BaseDecl;
1951569ce68SRoman Divacky }
1961569ce68SRoman Divacky
19701af97d3SDimitry Andric return Offset;
1981569ce68SRoman Divacky }
1991569ce68SRoman Divacky
2001569ce68SRoman Divacky llvm::Constant *
GetNonVirtualBaseClassOffset(const CXXRecordDecl * ClassDecl,CastExpr::path_const_iterator PathBegin,CastExpr::path_const_iterator PathEnd)2010883ccd9SRoman Divacky CodeGenModule::GetNonVirtualBaseClassOffset(const CXXRecordDecl *ClassDecl,
2023d1dcd9bSDimitry Andric CastExpr::path_const_iterator PathBegin,
2033d1dcd9bSDimitry Andric CastExpr::path_const_iterator PathEnd) {
2043d1dcd9bSDimitry Andric assert(PathBegin != PathEnd && "Base path should not be empty!");
2051569ce68SRoman Divacky
20601af97d3SDimitry Andric CharUnits Offset =
207c192b3dcSDimitry Andric computeNonVirtualBaseClassOffset(ClassDecl, PathBegin, PathEnd);
20801af97d3SDimitry Andric if (Offset.isZero())
2099f4dbff6SDimitry Andric return nullptr;
2101569ce68SRoman Divacky
21136981b17SDimitry Andric llvm::Type *PtrDiffTy =
212e6b73279SDimitry Andric getTypes().ConvertType(getContext().getPointerDiffType());
2131569ce68SRoman Divacky
21401af97d3SDimitry Andric return llvm::ConstantInt::get(PtrDiffTy, Offset.getQuantity());
2151569ce68SRoman Divacky }
2161569ce68SRoman Divacky
2170883ccd9SRoman Divacky /// Gets the address of a direct base class within a complete object.
218ecb7e5c8SRoman Divacky /// This should only be used for (1) non-virtual bases or (2) virtual bases
219ecb7e5c8SRoman Divacky /// when the type is known to be complete (e.g. in complete destructors).
220ecb7e5c8SRoman Divacky ///
221ecb7e5c8SRoman Divacky /// The object pointed to by 'This' is assumed to be non-null.
22245b53394SDimitry Andric Address
GetAddressOfDirectBaseInCompleteClass(Address This,const CXXRecordDecl * Derived,const CXXRecordDecl * Base,bool BaseIsVirtual)22345b53394SDimitry Andric CodeGenFunction::GetAddressOfDirectBaseInCompleteClass(Address This,
224ecb7e5c8SRoman Divacky const CXXRecordDecl *Derived,
2250883ccd9SRoman Divacky const CXXRecordDecl *Base,
2260883ccd9SRoman Divacky bool BaseIsVirtual) {
227ecb7e5c8SRoman Divacky // 'this' must be a pointer (in some address space) to Derived.
22845b53394SDimitry Andric assert(This.getElementType() == ConvertType(Derived));
229ecb7e5c8SRoman Divacky
230ecb7e5c8SRoman Divacky // Compute the offset of the virtual base.
23101af97d3SDimitry Andric CharUnits Offset;
232ecb7e5c8SRoman Divacky const ASTRecordLayout &Layout = getContext().getASTRecordLayout(Derived);
2330883ccd9SRoman Divacky if (BaseIsVirtual)
23401af97d3SDimitry Andric Offset = Layout.getVBaseClassOffset(Base);
235ecb7e5c8SRoman Divacky else
23601af97d3SDimitry Andric Offset = Layout.getBaseClassOffset(Base);
237ecb7e5c8SRoman Divacky
238ecb7e5c8SRoman Divacky // Shift and cast down to the base type.
239ecb7e5c8SRoman Divacky // TODO: for complete types, this should be possible with a GEP.
24045b53394SDimitry Andric Address V = This;
24145b53394SDimitry Andric if (!Offset.isZero()) {
2427fa27ce4SDimitry Andric V = V.withElementType(Int8Ty);
24345b53394SDimitry Andric V = Builder.CreateConstInBoundsByteGEP(V, Offset);
244ecb7e5c8SRoman Divacky }
2457fa27ce4SDimitry Andric return V.withElementType(ConvertType(Base));
246ecb7e5c8SRoman Divacky }
247ecb7e5c8SRoman Divacky
24845b53394SDimitry Andric static Address
ApplyNonVirtualAndVirtualOffset(CodeGenFunction & CGF,Address addr,CharUnits nonVirtualOffset,llvm::Value * virtualOffset,const CXXRecordDecl * derivedClass,const CXXRecordDecl * nearestVBase)24945b53394SDimitry Andric ApplyNonVirtualAndVirtualOffset(CodeGenFunction &CGF, Address addr,
25056d91b49SDimitry Andric CharUnits nonVirtualOffset,
25145b53394SDimitry Andric llvm::Value *virtualOffset,
25245b53394SDimitry Andric const CXXRecordDecl *derivedClass,
25345b53394SDimitry Andric const CXXRecordDecl *nearestVBase) {
25456d91b49SDimitry Andric // Assert that we have something to do.
2559f4dbff6SDimitry Andric assert(!nonVirtualOffset.isZero() || virtualOffset != nullptr);
2560883ccd9SRoman Divacky
25756d91b49SDimitry Andric // Compute the offset from the static and dynamic components.
25856d91b49SDimitry Andric llvm::Value *baseOffset;
25956d91b49SDimitry Andric if (!nonVirtualOffset.isZero()) {
260cfca06d7SDimitry Andric llvm::Type *OffsetType =
261cfca06d7SDimitry Andric (CGF.CGM.getTarget().getCXXABI().isItaniumFamily() &&
262cfca06d7SDimitry Andric CGF.CGM.getItaniumVTableContext().isRelativeLayout())
263cfca06d7SDimitry Andric ? CGF.Int32Ty
264cfca06d7SDimitry Andric : CGF.PtrDiffTy;
265cfca06d7SDimitry Andric baseOffset =
266cfca06d7SDimitry Andric llvm::ConstantInt::get(OffsetType, nonVirtualOffset.getQuantity());
26756d91b49SDimitry Andric if (virtualOffset) {
26856d91b49SDimitry Andric baseOffset = CGF.Builder.CreateAdd(virtualOffset, baseOffset);
26956d91b49SDimitry Andric }
27056d91b49SDimitry Andric } else {
27156d91b49SDimitry Andric baseOffset = virtualOffset;
27256d91b49SDimitry Andric }
2730883ccd9SRoman Divacky
2740883ccd9SRoman Divacky // Apply the base offset.
275ac9a064cSDimitry Andric llvm::Value *ptr = addr.emitRawPointer(CGF);
276344a3780SDimitry Andric ptr = CGF.Builder.CreateInBoundsGEP(CGF.Int8Ty, ptr, baseOffset, "add.ptr");
27745b53394SDimitry Andric
27845b53394SDimitry Andric // If we have a virtual component, the alignment of the result will
27945b53394SDimitry Andric // be relative only to the known alignment of that vbase.
28045b53394SDimitry Andric CharUnits alignment;
28145b53394SDimitry Andric if (virtualOffset) {
28245b53394SDimitry Andric assert(nearestVBase && "virtual offset without vbase?");
28345b53394SDimitry Andric alignment = CGF.CGM.getVBaseAlignment(addr.getAlignment(),
28445b53394SDimitry Andric derivedClass, nearestVBase);
28545b53394SDimitry Andric } else {
28645b53394SDimitry Andric alignment = addr.getAlignment();
28745b53394SDimitry Andric }
28845b53394SDimitry Andric alignment = alignment.alignmentAtOffset(nonVirtualOffset);
28945b53394SDimitry Andric
29077fc4c14SDimitry Andric return Address(ptr, CGF.Int8Ty, alignment);
2910883ccd9SRoman Divacky }
2920883ccd9SRoman Divacky
GetAddressOfBaseClass(Address Value,const CXXRecordDecl * Derived,CastExpr::path_const_iterator PathBegin,CastExpr::path_const_iterator PathEnd,bool NullCheckValue,SourceLocation Loc)29345b53394SDimitry Andric Address CodeGenFunction::GetAddressOfBaseClass(
29445b53394SDimitry Andric Address Value, const CXXRecordDecl *Derived,
2953d1dcd9bSDimitry Andric CastExpr::path_const_iterator PathBegin,
29606d4ba38SDimitry Andric CastExpr::path_const_iterator PathEnd, bool NullCheckValue,
29706d4ba38SDimitry Andric SourceLocation Loc) {
2983d1dcd9bSDimitry Andric assert(PathBegin != PathEnd && "Base path should not be empty!");
2991569ce68SRoman Divacky
3003d1dcd9bSDimitry Andric CastExpr::path_const_iterator Start = PathBegin;
3019f4dbff6SDimitry Andric const CXXRecordDecl *VBase = nullptr;
3020883ccd9SRoman Divacky
30356d91b49SDimitry Andric // Sema has done some convenient canonicalization here: if the
30456d91b49SDimitry Andric // access path involved any virtual steps, the conversion path will
30556d91b49SDimitry Andric // *start* with a step down to the correct virtual base subobject,
30656d91b49SDimitry Andric // and hence will not require any further steps.
3070883ccd9SRoman Divacky if ((*Start)->isVirtual()) {
308519fc96cSDimitry Andric VBase = cast<CXXRecordDecl>(
309519fc96cSDimitry Andric (*Start)->getType()->castAs<RecordType>()->getDecl());
3100883ccd9SRoman Divacky ++Start;
311ecb7e5c8SRoman Divacky }
312ecb7e5c8SRoman Divacky
31356d91b49SDimitry Andric // Compute the static offset of the ultimate destination within its
31456d91b49SDimitry Andric // allocating subobject (the virtual base, if there is one, or else
31556d91b49SDimitry Andric // the "complete" object that we see).
316c192b3dcSDimitry Andric CharUnits NonVirtualOffset = CGM.computeNonVirtualBaseClassOffset(
317c192b3dcSDimitry Andric VBase ? VBase : Derived, Start, PathEnd);
318ecb7e5c8SRoman Divacky
31956d91b49SDimitry Andric // If there's a virtual step, we can sometimes "devirtualize" it.
32056d91b49SDimitry Andric // For now, that's limited to when the derived type is final.
32156d91b49SDimitry Andric // TODO: "devirtualize" this for accesses to known-complete objects.
32256d91b49SDimitry Andric if (VBase && Derived->hasAttr<FinalAttr>()) {
32356d91b49SDimitry Andric const ASTRecordLayout &layout = getContext().getASTRecordLayout(Derived);
32456d91b49SDimitry Andric CharUnits vBaseOffset = layout.getVBaseClassOffset(VBase);
32556d91b49SDimitry Andric NonVirtualOffset += vBaseOffset;
3269f4dbff6SDimitry Andric VBase = nullptr; // we no longer have a virtual step
32756d91b49SDimitry Andric }
32856d91b49SDimitry Andric
3290883ccd9SRoman Divacky // Get the base pointer type.
33077fc4c14SDimitry Andric llvm::Type *BaseValueTy = ConvertType((PathEnd[-1])->getType());
3317fa27ce4SDimitry Andric llvm::Type *PtrTy = llvm::PointerType::get(
3327fa27ce4SDimitry Andric CGM.getLLVMContext(), Value.getType()->getPointerAddressSpace());
3330883ccd9SRoman Divacky
33406d4ba38SDimitry Andric QualType DerivedTy = getContext().getRecordType(Derived);
33545b53394SDimitry Andric CharUnits DerivedAlign = CGM.getClassPointerAlignment(Derived);
33606d4ba38SDimitry Andric
33756d91b49SDimitry Andric // If the static offset is zero and we don't have a virtual step,
33856d91b49SDimitry Andric // just do a bitcast; null checks are unnecessary.
33901af97d3SDimitry Andric if (NonVirtualOffset.isZero() && !VBase) {
34006d4ba38SDimitry Andric if (sanitizePerformTypeCheck()) {
3417442d6faSDimitry Andric SanitizerSet SkippedChecks;
3427442d6faSDimitry Andric SkippedChecks.set(SanitizerKind::Null, !NullCheckValue);
343ac9a064cSDimitry Andric EmitTypeCheck(TCK_Upcast, Loc, Value.emitRawPointer(*this), DerivedTy,
344ac9a064cSDimitry Andric DerivedAlign, SkippedChecks);
34506d4ba38SDimitry Andric }
3467fa27ce4SDimitry Andric return Value.withElementType(BaseValueTy);
3471569ce68SRoman Divacky }
3481569ce68SRoman Divacky
3499f4dbff6SDimitry Andric llvm::BasicBlock *origBB = nullptr;
3509f4dbff6SDimitry Andric llvm::BasicBlock *endBB = nullptr;
3511569ce68SRoman Divacky
35256d91b49SDimitry Andric // Skip over the offset (and the vtable load) if we're supposed to
35356d91b49SDimitry Andric // null-check the pointer.
3541569ce68SRoman Divacky if (NullCheckValue) {
35556d91b49SDimitry Andric origBB = Builder.GetInsertBlock();
35656d91b49SDimitry Andric llvm::BasicBlock *notNullBB = createBasicBlock("cast.notnull");
35756d91b49SDimitry Andric endBB = createBasicBlock("cast.end");
3581569ce68SRoman Divacky
359ac9a064cSDimitry Andric llvm::Value *isNull = Builder.CreateIsNull(Value);
36056d91b49SDimitry Andric Builder.CreateCondBr(isNull, endBB, notNullBB);
36156d91b49SDimitry Andric EmitBlock(notNullBB);
3621569ce68SRoman Divacky }
3631569ce68SRoman Divacky
36406d4ba38SDimitry Andric if (sanitizePerformTypeCheck()) {
3657442d6faSDimitry Andric SanitizerSet SkippedChecks;
3667442d6faSDimitry Andric SkippedChecks.set(SanitizerKind::Null, true);
36745b53394SDimitry Andric EmitTypeCheck(VBase ? TCK_UpcastToVirtualBase : TCK_Upcast, Loc,
368ac9a064cSDimitry Andric Value.emitRawPointer(*this), DerivedTy, DerivedAlign,
369ac9a064cSDimitry Andric SkippedChecks);
37006d4ba38SDimitry Andric }
37106d4ba38SDimitry Andric
37256d91b49SDimitry Andric // Compute the virtual offset.
3739f4dbff6SDimitry Andric llvm::Value *VirtualOffset = nullptr;
374bca07a45SDimitry Andric if (VBase) {
375bfef3995SDimitry Andric VirtualOffset =
376bfef3995SDimitry Andric CGM.getCXXABI().GetVirtualBaseClassOffset(*this, Value, Derived, VBase);
377bca07a45SDimitry Andric }
3781569ce68SRoman Divacky
37956d91b49SDimitry Andric // Apply both offsets.
38045b53394SDimitry Andric Value = ApplyNonVirtualAndVirtualOffset(*this, Value, NonVirtualOffset,
38145b53394SDimitry Andric VirtualOffset, Derived, VBase);
3821569ce68SRoman Divacky
38356d91b49SDimitry Andric // Cast to the destination type.
3847fa27ce4SDimitry Andric Value = Value.withElementType(BaseValueTy);
3851569ce68SRoman Divacky
38656d91b49SDimitry Andric // Build a phi if we needed a null check.
3871569ce68SRoman Divacky if (NullCheckValue) {
38856d91b49SDimitry Andric llvm::BasicBlock *notNullBB = Builder.GetInsertBlock();
38956d91b49SDimitry Andric Builder.CreateBr(endBB);
39056d91b49SDimitry Andric EmitBlock(endBB);
3911569ce68SRoman Divacky
3927fa27ce4SDimitry Andric llvm::PHINode *PHI = Builder.CreatePHI(PtrTy, 2, "cast.result");
393ac9a064cSDimitry Andric PHI->addIncoming(Value.emitRawPointer(*this), notNullBB);
3947fa27ce4SDimitry Andric PHI->addIncoming(llvm::Constant::getNullValue(PtrTy), origBB);
3957fa27ce4SDimitry Andric Value = Value.withPointer(PHI, NotKnownNonNull);
3961569ce68SRoman Divacky }
3971569ce68SRoman Divacky
3981569ce68SRoman Divacky return Value;
3991569ce68SRoman Divacky }
4001569ce68SRoman Divacky
40145b53394SDimitry Andric Address
GetAddressOfDerivedClass(Address BaseAddr,const CXXRecordDecl * Derived,CastExpr::path_const_iterator PathBegin,CastExpr::path_const_iterator PathEnd,bool NullCheckValue)40245b53394SDimitry Andric CodeGenFunction::GetAddressOfDerivedClass(Address BaseAddr,
4030883ccd9SRoman Divacky const CXXRecordDecl *Derived,
4043d1dcd9bSDimitry Andric CastExpr::path_const_iterator PathBegin,
4053d1dcd9bSDimitry Andric CastExpr::path_const_iterator PathEnd,
4061569ce68SRoman Divacky bool NullCheckValue) {
4073d1dcd9bSDimitry Andric assert(PathBegin != PathEnd && "Base path should not be empty!");
4080883ccd9SRoman Divacky
4091569ce68SRoman Divacky QualType DerivedTy =
4100883ccd9SRoman Divacky getContext().getCanonicalType(getContext().getTagDeclType(Derived));
41177fc4c14SDimitry Andric llvm::Type *DerivedValueTy = ConvertType(DerivedTy);
4121569ce68SRoman Divacky
413ecb7e5c8SRoman Divacky llvm::Value *NonVirtualOffset =
4143d1dcd9bSDimitry Andric CGM.GetNonVirtualBaseClassOffset(Derived, PathBegin, PathEnd);
415ecb7e5c8SRoman Divacky
416ecb7e5c8SRoman Divacky if (!NonVirtualOffset) {
417ecb7e5c8SRoman Divacky // No offset, we can just cast back.
4187fa27ce4SDimitry Andric return BaseAddr.withElementType(DerivedValueTy);
419ecb7e5c8SRoman Divacky }
420ecb7e5c8SRoman Divacky
4219f4dbff6SDimitry Andric llvm::BasicBlock *CastNull = nullptr;
4229f4dbff6SDimitry Andric llvm::BasicBlock *CastNotNull = nullptr;
4239f4dbff6SDimitry Andric llvm::BasicBlock *CastEnd = nullptr;
4241569ce68SRoman Divacky
4251569ce68SRoman Divacky if (NullCheckValue) {
4261569ce68SRoman Divacky CastNull = createBasicBlock("cast.null");
4271569ce68SRoman Divacky CastNotNull = createBasicBlock("cast.notnull");
4281569ce68SRoman Divacky CastEnd = createBasicBlock("cast.end");
4291569ce68SRoman Divacky
430ac9a064cSDimitry Andric llvm::Value *IsNull = Builder.CreateIsNull(BaseAddr);
4311569ce68SRoman Divacky Builder.CreateCondBr(IsNull, CastNull, CastNotNull);
4321569ce68SRoman Divacky EmitBlock(CastNotNull);
4331569ce68SRoman Divacky }
4341569ce68SRoman Divacky
4351569ce68SRoman Divacky // Apply the offset.
436ac9a064cSDimitry Andric Address Addr = BaseAddr.withElementType(Int8Ty);
437ac9a064cSDimitry Andric Addr = Builder.CreateInBoundsGEP(
438ac9a064cSDimitry Andric Addr, Builder.CreateNeg(NonVirtualOffset), Int8Ty,
439ac9a064cSDimitry Andric CGM.getClassPointerAlignment(Derived), "sub.ptr");
440ac9a064cSDimitry Andric
441ac9a064cSDimitry Andric // Just cast.
442ac9a064cSDimitry Andric Addr = Addr.withElementType(DerivedValueTy);
443ecb7e5c8SRoman Divacky
44445b53394SDimitry Andric // Produce a PHI if we had a null-check.
4451569ce68SRoman Divacky if (NullCheckValue) {
4461569ce68SRoman Divacky Builder.CreateBr(CastEnd);
4471569ce68SRoman Divacky EmitBlock(CastNull);
4481569ce68SRoman Divacky Builder.CreateBr(CastEnd);
4491569ce68SRoman Divacky EmitBlock(CastEnd);
4501569ce68SRoman Divacky
451ac9a064cSDimitry Andric llvm::Value *Value = Addr.emitRawPointer(*this);
45201af97d3SDimitry Andric llvm::PHINode *PHI = Builder.CreatePHI(Value->getType(), 2);
4531569ce68SRoman Divacky PHI->addIncoming(Value, CastNotNull);
45445b53394SDimitry Andric PHI->addIncoming(llvm::Constant::getNullValue(Value->getType()), CastNull);
455ac9a064cSDimitry Andric return Address(PHI, Addr.getElementType(),
456ac9a064cSDimitry Andric CGM.getClassPointerAlignment(Derived));
4571569ce68SRoman Divacky }
4581569ce68SRoman Divacky
459ac9a064cSDimitry Andric return Addr;
4601569ce68SRoman Divacky }
461abe15e55SRoman Divacky
GetVTTParameter(GlobalDecl GD,bool ForVirtualBase,bool Delegating)462809500fcSDimitry Andric llvm::Value *CodeGenFunction::GetVTTParameter(GlobalDecl GD,
463809500fcSDimitry Andric bool ForVirtualBase,
464809500fcSDimitry Andric bool Delegating) {
465bfef3995SDimitry Andric if (!CGM.getCXXABI().NeedsVTTParameter(GD)) {
466ee791ddeSRoman Divacky // This constructor/destructor does not need a VTT parameter.
4679f4dbff6SDimitry Andric return nullptr;
468ee791ddeSRoman Divacky }
469ee791ddeSRoman Divacky
4706a037251SDimitry Andric const CXXRecordDecl *RD = cast<CXXMethodDecl>(CurCodeDecl)->getParent();
471ee791ddeSRoman Divacky const CXXRecordDecl *Base = cast<CXXMethodDecl>(GD.getDecl())->getParent();
472ee791ddeSRoman Divacky
47379ade4e0SRoman Divacky uint64_t SubVTTIndex;
47479ade4e0SRoman Divacky
475809500fcSDimitry Andric if (Delegating) {
476809500fcSDimitry Andric // If this is a delegating constructor call, just load the VTT.
477809500fcSDimitry Andric return LoadCXXVTT();
478809500fcSDimitry Andric } else if (RD == Base) {
47979ade4e0SRoman Divacky // If the record matches the base, this is the complete ctor/dtor
48079ade4e0SRoman Divacky // variant calling the base variant in a class with virtual bases.
481bfef3995SDimitry Andric assert(!CGM.getCXXABI().NeedsVTTParameter(CurGD) &&
48279ade4e0SRoman Divacky "doing no-op VTT offset in base dtor/ctor?");
4830883ccd9SRoman Divacky assert(!ForVirtualBase && "Can't have same class as virtual base!");
48479ade4e0SRoman Divacky SubVTTIndex = 0;
48579ade4e0SRoman Divacky } else {
486809500fcSDimitry Andric const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
48701af97d3SDimitry Andric CharUnits BaseOffset = ForVirtualBase ?
48801af97d3SDimitry Andric Layout.getVBaseClassOffset(Base) :
48901af97d3SDimitry Andric Layout.getBaseClassOffset(Base);
4900883ccd9SRoman Divacky
4910883ccd9SRoman Divacky SubVTTIndex =
492809500fcSDimitry Andric CGM.getVTables().getSubVTTIndex(RD, BaseSubobject(Base, BaseOffset));
493ee791ddeSRoman Divacky assert(SubVTTIndex != 0 && "Sub-VTT index must be greater than zero!");
49479ade4e0SRoman Divacky }
495ee791ddeSRoman Divacky
496bfef3995SDimitry Andric if (CGM.getCXXABI().NeedsVTTParameter(CurGD)) {
497ee791ddeSRoman Divacky // A VTT parameter was passed to the constructor, use it.
498344a3780SDimitry Andric llvm::Value *VTT = LoadCXXVTT();
499344a3780SDimitry Andric return Builder.CreateConstInBoundsGEP1_64(VoidPtrTy, VTT, SubVTTIndex);
500ee791ddeSRoman Divacky } else {
501ee791ddeSRoman Divacky // We're the complete constructor, so get the VTT by name.
502344a3780SDimitry Andric llvm::GlobalValue *VTT = CGM.getVTables().GetAddrOfVTT(RD);
503344a3780SDimitry Andric return Builder.CreateConstInBoundsGEP2_64(
504344a3780SDimitry Andric VTT->getValueType(), VTT, 0, SubVTTIndex);
505ee791ddeSRoman Divacky }
506ee791ddeSRoman Divacky }
507ee791ddeSRoman Divacky
5083d1dcd9bSDimitry Andric namespace {
5093d1dcd9bSDimitry Andric /// Call the destructor for a direct base class.
51045b53394SDimitry Andric struct CallBaseDtor final : EHScopeStack::Cleanup {
5113d1dcd9bSDimitry Andric const CXXRecordDecl *BaseClass;
5123d1dcd9bSDimitry Andric bool BaseIsVirtual;
CallBaseDtor__anonf1d54d130111::CallBaseDtor5133d1dcd9bSDimitry Andric CallBaseDtor(const CXXRecordDecl *Base, bool BaseIsVirtual)
5143d1dcd9bSDimitry Andric : BaseClass(Base), BaseIsVirtual(BaseIsVirtual) {}
5153d1dcd9bSDimitry Andric
Emit__anonf1d54d130111::CallBaseDtor5169f4dbff6SDimitry Andric void Emit(CodeGenFunction &CGF, Flags flags) override {
5173d1dcd9bSDimitry Andric const CXXRecordDecl *DerivedClass =
5183d1dcd9bSDimitry Andric cast<CXXMethodDecl>(CGF.CurCodeDecl)->getParent();
5193d1dcd9bSDimitry Andric
5203d1dcd9bSDimitry Andric const CXXDestructorDecl *D = BaseClass->getDestructor();
52122989816SDimitry Andric // We are already inside a destructor, so presumably the object being
52222989816SDimitry Andric // destroyed should have the expected type.
523b1c73532SDimitry Andric QualType ThisTy = D->getFunctionObjectParameterType();
52445b53394SDimitry Andric Address Addr =
52545b53394SDimitry Andric CGF.GetAddressOfDirectBaseInCompleteClass(CGF.LoadCXXThisAddress(),
5263d1dcd9bSDimitry Andric DerivedClass, BaseClass,
5273d1dcd9bSDimitry Andric BaseIsVirtual);
528809500fcSDimitry Andric CGF.EmitCXXDestructorCall(D, Dtor_Base, BaseIsVirtual,
52922989816SDimitry Andric /*Delegating=*/false, Addr, ThisTy);
5303d1dcd9bSDimitry Andric }
5313d1dcd9bSDimitry Andric };
532bca07a45SDimitry Andric
533bca07a45SDimitry Andric /// A visitor which checks whether an initializer uses 'this' in a
534bca07a45SDimitry Andric /// way which requires the vtable to be properly set.
5352e645aa5SDimitry Andric struct DynamicThisUseChecker : ConstEvaluatedExprVisitor<DynamicThisUseChecker> {
5362e645aa5SDimitry Andric typedef ConstEvaluatedExprVisitor<DynamicThisUseChecker> super;
537bca07a45SDimitry Andric
538bca07a45SDimitry Andric bool UsesThis;
539bca07a45SDimitry Andric
DynamicThisUseChecker__anonf1d54d130111::DynamicThisUseChecker5402e645aa5SDimitry Andric DynamicThisUseChecker(const ASTContext &C) : super(C), UsesThis(false) {}
541bca07a45SDimitry Andric
542bca07a45SDimitry Andric // Black-list all explicit and implicit references to 'this'.
543bca07a45SDimitry Andric //
544bca07a45SDimitry Andric // Do we need to worry about external references to 'this' derived
545bca07a45SDimitry Andric // from arbitrary code? If so, then anything which runs arbitrary
546bca07a45SDimitry Andric // external code might potentially access the vtable.
VisitCXXThisExpr__anonf1d54d130111::DynamicThisUseChecker5472e645aa5SDimitry Andric void VisitCXXThisExpr(const CXXThisExpr *E) { UsesThis = true; }
548bca07a45SDimitry Andric };
54945b53394SDimitry Andric } // end anonymous namespace
550bca07a45SDimitry Andric
BaseInitializerUsesThis(ASTContext & C,const Expr * Init)551bca07a45SDimitry Andric static bool BaseInitializerUsesThis(ASTContext &C, const Expr *Init) {
552bca07a45SDimitry Andric DynamicThisUseChecker Checker(C);
5532e645aa5SDimitry Andric Checker.Visit(Init);
554bca07a45SDimitry Andric return Checker.UsesThis;
5553d1dcd9bSDimitry Andric }
5563d1dcd9bSDimitry Andric
EmitBaseInitializer(CodeGenFunction & CGF,const CXXRecordDecl * ClassDecl,CXXCtorInitializer * BaseInit)557abe15e55SRoman Divacky static void EmitBaseInitializer(CodeGenFunction &CGF,
558abe15e55SRoman Divacky const CXXRecordDecl *ClassDecl,
55922989816SDimitry Andric CXXCtorInitializer *BaseInit) {
560abe15e55SRoman Divacky assert(BaseInit->isBaseInitializer() &&
561abe15e55SRoman Divacky "Must have base initializer!");
562abe15e55SRoman Divacky
56345b53394SDimitry Andric Address ThisPtr = CGF.LoadCXXThisAddress();
564abe15e55SRoman Divacky
565abe15e55SRoman Divacky const Type *BaseType = BaseInit->getBaseClass();
566519fc96cSDimitry Andric const auto *BaseClassDecl =
567519fc96cSDimitry Andric cast<CXXRecordDecl>(BaseType->castAs<RecordType>()->getDecl());
568abe15e55SRoman Divacky
5690883ccd9SRoman Divacky bool isBaseVirtual = BaseInit->isBaseVirtual();
570abe15e55SRoman Divacky
571bca07a45SDimitry Andric // If the initializer for the base (other than the constructor
572bca07a45SDimitry Andric // itself) accesses 'this' in any way, we need to initialize the
573bca07a45SDimitry Andric // vtables.
574bca07a45SDimitry Andric if (BaseInitializerUsesThis(CGF.getContext(), BaseInit->getInit()))
575bca07a45SDimitry Andric CGF.InitializeVTablePointers(ClassDecl);
576bca07a45SDimitry Andric
577ecb7e5c8SRoman Divacky // We can pretend to be a complete class because it only matters for
578ecb7e5c8SRoman Divacky // virtual bases, and we only do virtual bases for complete ctors.
57945b53394SDimitry Andric Address V =
5800883ccd9SRoman Divacky CGF.GetAddressOfDirectBaseInCompleteClass(ThisPtr, ClassDecl,
5810883ccd9SRoman Divacky BaseClassDecl,
5823d1dcd9bSDimitry Andric isBaseVirtual);
58336981b17SDimitry Andric AggValueSlot AggSlot =
58448675466SDimitry Andric AggValueSlot::forAddr(
58548675466SDimitry Andric V, Qualifiers(),
58636981b17SDimitry Andric AggValueSlot::IsDestructed,
58736981b17SDimitry Andric AggValueSlot::DoesNotNeedGCBarriers,
58848675466SDimitry Andric AggValueSlot::IsNotAliased,
58922989816SDimitry Andric CGF.getOverlapForBaseInit(ClassDecl, BaseClassDecl, isBaseVirtual));
590ecb7e5c8SRoman Divacky
591bca07a45SDimitry Andric CGF.EmitAggExpr(BaseInit->getInit(), AggSlot);
592bca07a45SDimitry Andric
593dbe13110SDimitry Andric if (CGF.CGM.getLangOpts().Exceptions &&
594bca07a45SDimitry Andric !BaseClassDecl->hasTrivialDestructor())
5953d1dcd9bSDimitry Andric CGF.EHStack.pushCleanup<CallBaseDtor>(EHCleanup, BaseClassDecl,
5963d1dcd9bSDimitry Andric isBaseVirtual);
597abe15e55SRoman Divacky }
598abe15e55SRoman Divacky
isMemcpyEquivalentSpecialMember(const CXXMethodDecl * D)5995e20cdd8SDimitry Andric static bool isMemcpyEquivalentSpecialMember(const CXXMethodDecl *D) {
6005e20cdd8SDimitry Andric auto *CD = dyn_cast<CXXConstructorDecl>(D);
6015e20cdd8SDimitry Andric if (!(CD && CD->isCopyOrMoveConstructor()) &&
6025e20cdd8SDimitry Andric !D->isCopyAssignmentOperator() && !D->isMoveAssignmentOperator())
6035e20cdd8SDimitry Andric return false;
6045e20cdd8SDimitry Andric
6055e20cdd8SDimitry Andric // We can emit a memcpy for a trivial copy or move constructor/assignment.
6065e20cdd8SDimitry Andric if (D->isTrivial() && !D->getParent()->mayInsertExtraPadding())
6075e20cdd8SDimitry Andric return true;
6085e20cdd8SDimitry Andric
6095e20cdd8SDimitry Andric // We *must* emit a memcpy for a defaulted union copy or move op.
6105e20cdd8SDimitry Andric if (D->getParent()->isUnion() && D->isDefaulted())
6115e20cdd8SDimitry Andric return true;
6125e20cdd8SDimitry Andric
6135e20cdd8SDimitry Andric return false;
6145e20cdd8SDimitry Andric }
6155e20cdd8SDimitry Andric
EmitLValueForAnyFieldInitialization(CodeGenFunction & CGF,CXXCtorInitializer * MemberInit,LValue & LHS)61651ece4aaSDimitry Andric static void EmitLValueForAnyFieldInitialization(CodeGenFunction &CGF,
61751ece4aaSDimitry Andric CXXCtorInitializer *MemberInit,
61851ece4aaSDimitry Andric LValue &LHS) {
61951ece4aaSDimitry Andric FieldDecl *Field = MemberInit->getAnyMember();
62051ece4aaSDimitry Andric if (MemberInit->isIndirectMemberInitializer()) {
62151ece4aaSDimitry Andric // If we are initializing an anonymous union field, drill down to the field.
62251ece4aaSDimitry Andric IndirectFieldDecl *IndirectField = MemberInit->getIndirectMember();
62351ece4aaSDimitry Andric for (const auto *I : IndirectField->chain())
62451ece4aaSDimitry Andric LHS = CGF.EmitLValueForFieldInitialization(LHS, cast<FieldDecl>(I));
62551ece4aaSDimitry Andric } else {
62651ece4aaSDimitry Andric LHS = CGF.EmitLValueForFieldInitialization(LHS, Field);
62751ece4aaSDimitry Andric }
62851ece4aaSDimitry Andric }
62951ece4aaSDimitry Andric
EmitMemberInitializer(CodeGenFunction & CGF,const CXXRecordDecl * ClassDecl,CXXCtorInitializer * MemberInit,const CXXConstructorDecl * Constructor,FunctionArgList & Args)630abe15e55SRoman Divacky static void EmitMemberInitializer(CodeGenFunction &CGF,
631abe15e55SRoman Divacky const CXXRecordDecl *ClassDecl,
632bca07a45SDimitry Andric CXXCtorInitializer *MemberInit,
633d7279c4cSRoman Divacky const CXXConstructorDecl *Constructor,
634d7279c4cSRoman Divacky FunctionArgList &Args) {
635ec12bbe3SDimitry Andric ApplyDebugLocation Loc(CGF, MemberInit->getSourceLocation());
636bca07a45SDimitry Andric assert(MemberInit->isAnyMemberInitializer() &&
637abe15e55SRoman Divacky "Must have member initializer!");
63829cafa66SDimitry Andric assert(MemberInit->getInit() && "Must have initializer!");
639abe15e55SRoman Divacky
640abe15e55SRoman Divacky // non-static data member initializers.
641bca07a45SDimitry Andric FieldDecl *Field = MemberInit->getAnyMember();
642dbe13110SDimitry Andric QualType FieldType = Field->getType();
643abe15e55SRoman Divacky
644abe15e55SRoman Divacky llvm::Value *ThisPtr = CGF.LoadCXXThis();
6456b9a6e39SDimitry Andric QualType RecordTy = CGF.getContext().getTypeDeclType(ClassDecl);
64648675466SDimitry Andric LValue LHS;
64748675466SDimitry Andric
64848675466SDimitry Andric // If a base constructor is being emitted, create an LValue that has the
64948675466SDimitry Andric // non-virtual alignment.
65048675466SDimitry Andric if (CGF.CurGD.getCtorType() == Ctor_Base)
65148675466SDimitry Andric LHS = CGF.MakeNaturalAlignPointeeAddrLValue(ThisPtr, RecordTy);
65248675466SDimitry Andric else
65348675466SDimitry Andric LHS = CGF.MakeNaturalAlignAddrLValue(ThisPtr, RecordTy);
654abe15e55SRoman Divacky
65551ece4aaSDimitry Andric EmitLValueForAnyFieldInitialization(CGF, MemberInit, LHS);
656abe15e55SRoman Divacky
657dbe13110SDimitry Andric // Special case: if we are in a copy or move constructor, and we are copying
658dbe13110SDimitry Andric // an array of PODs or classes with trivial copy constructors, ignore the
659dbe13110SDimitry Andric // AST and perform the copy we know is equivalent.
660dbe13110SDimitry Andric // FIXME: This is hacky at best... if we had a bit more explicit information
661dbe13110SDimitry Andric // in the AST, we could generalize it more easily.
662d7279c4cSRoman Divacky const ConstantArrayType *Array
663d7279c4cSRoman Divacky = CGF.getContext().getAsConstantArrayType(FieldType);
664bfef3995SDimitry Andric if (Array && Constructor->isDefaulted() &&
66536981b17SDimitry Andric Constructor->isCopyOrMoveConstructor()) {
666d7279c4cSRoman Divacky QualType BaseElementTy = CGF.getContext().getBaseElementType(Array);
66713cc256eSDimitry Andric CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(MemberInit->getInit());
668180abc3dSDimitry Andric if (BaseElementTy.isPODType(CGF.getContext()) ||
6695e20cdd8SDimitry Andric (CE && isMemcpyEquivalentSpecialMember(CE->getConstructor()))) {
67006d4ba38SDimitry Andric unsigned SrcArgIndex =
67106d4ba38SDimitry Andric CGF.CGM.getCXXABI().getSrcArgforCopyCtor(Constructor, Args);
672d7279c4cSRoman Divacky llvm::Value *SrcPtr
67301af97d3SDimitry Andric = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(Args[SrcArgIndex]));
6746b9a6e39SDimitry Andric LValue ThisRHSLV = CGF.MakeNaturalAlignAddrLValue(SrcPtr, RecordTy);
6756b9a6e39SDimitry Andric LValue Src = CGF.EmitLValueForFieldInitialization(ThisRHSLV, Field);
676d7279c4cSRoman Divacky
677d7279c4cSRoman Divacky // Copy the aggregate.
67822989816SDimitry Andric CGF.EmitAggregateCopy(LHS, Src, FieldType, CGF.getOverlapForFieldInit(Field),
679d7279c4cSRoman Divacky LHS.isVolatileQualified());
68051ece4aaSDimitry Andric // Ensure that we destroy the objects if an exception is thrown later in
68151ece4aaSDimitry Andric // the constructor.
68251ece4aaSDimitry Andric QualType::DestructionKind dtorKind = FieldType.isDestructedType();
68351ece4aaSDimitry Andric if (CGF.needsEHCleanup(dtorKind))
684ac9a064cSDimitry Andric CGF.pushEHDestroy(dtorKind, LHS.getAddress(), FieldType);
685d7279c4cSRoman Divacky return;
686d7279c4cSRoman Divacky }
687d7279c4cSRoman Divacky }
688d7279c4cSRoman Divacky
689bab175ecSDimitry Andric CGF.EmitInitializerForField(Field, LHS, MemberInit->getInit());
690dbe13110SDimitry Andric }
691ecb7e5c8SRoman Divacky
EmitInitializerForField(FieldDecl * Field,LValue LHS,Expr * Init)69245b53394SDimitry Andric void CodeGenFunction::EmitInitializerForField(FieldDecl *Field, LValue LHS,
693bab175ecSDimitry Andric Expr *Init) {
694dbe13110SDimitry Andric QualType FieldType = Field->getType();
695809500fcSDimitry Andric switch (getEvaluationKind(FieldType)) {
696809500fcSDimitry Andric case TEK_Scalar:
697dbe13110SDimitry Andric if (LHS.isSimple()) {
698dbe13110SDimitry Andric EmitExprAsInit(Init, Field, LHS, false);
699dbe13110SDimitry Andric } else {
700dbe13110SDimitry Andric RValue RHS = RValue::get(EmitScalarExpr(Init));
701dbe13110SDimitry Andric EmitStoreThroughLValue(RHS, LHS);
702dbe13110SDimitry Andric }
703809500fcSDimitry Andric break;
704809500fcSDimitry Andric case TEK_Complex:
705809500fcSDimitry Andric EmitComplexExprIntoLValue(Init, LHS, /*isInit*/ true);
706809500fcSDimitry Andric break;
707809500fcSDimitry Andric case TEK_Aggregate: {
708706b4fc4SDimitry Andric AggValueSlot Slot = AggValueSlot::forLValue(
709ac9a064cSDimitry Andric LHS, AggValueSlot::IsDestructed, AggValueSlot::DoesNotNeedGCBarriers,
710ac9a064cSDimitry Andric AggValueSlot::IsNotAliased, getOverlapForFieldInit(Field),
711ac9a064cSDimitry Andric AggValueSlot::IsNotZeroed,
712c7e70c43SDimitry Andric // Checks are made by the code that calls constructor.
713c7e70c43SDimitry Andric AggValueSlot::IsSanitizerChecked);
714bab175ecSDimitry Andric EmitAggExpr(Init, Slot);
715bab175ecSDimitry Andric break;
716abe15e55SRoman Divacky }
717abe15e55SRoman Divacky }
718abe15e55SRoman Divacky
719809500fcSDimitry Andric // Ensure that we destroy this object if an exception is thrown
720809500fcSDimitry Andric // later in the constructor.
721809500fcSDimitry Andric QualType::DestructionKind dtorKind = FieldType.isDestructedType();
722809500fcSDimitry Andric if (needsEHCleanup(dtorKind))
723ac9a064cSDimitry Andric pushEHDestroy(dtorKind, LHS.getAddress(), FieldType);
724809500fcSDimitry Andric }
725809500fcSDimitry Andric
72679ade4e0SRoman Divacky /// Checks whether the given constructor is a valid subject for the
72779ade4e0SRoman Divacky /// complete-to-base constructor delegation optimization, i.e.
72879ade4e0SRoman Divacky /// emitting the complete constructor as a simple call to the base
72979ade4e0SRoman Divacky /// constructor.
IsConstructorDelegationValid(const CXXConstructorDecl * Ctor)7307442d6faSDimitry Andric bool CodeGenFunction::IsConstructorDelegationValid(
7317442d6faSDimitry Andric const CXXConstructorDecl *Ctor) {
73279ade4e0SRoman Divacky
73379ade4e0SRoman Divacky // Currently we disable the optimization for classes with virtual
73479ade4e0SRoman Divacky // bases because (1) the addresses of parameter variables need to be
73579ade4e0SRoman Divacky // consistent across all initializers but (2) the delegate function
73679ade4e0SRoman Divacky // call necessarily creates a second copy of the parameter variable.
73779ade4e0SRoman Divacky //
73879ade4e0SRoman Divacky // The limiting example (purely theoretical AFAIK):
73979ade4e0SRoman Divacky // struct A { A(int &c) { c++; } };
74079ade4e0SRoman Divacky // struct B : virtual A {
74179ade4e0SRoman Divacky // B(int count) : A(count) { printf("%d\n", count); }
74279ade4e0SRoman Divacky // };
74379ade4e0SRoman Divacky // ...although even this example could in principle be emitted as a
74479ade4e0SRoman Divacky // delegation since the address of the parameter doesn't escape.
74579ade4e0SRoman Divacky if (Ctor->getParent()->getNumVBases()) {
74679ade4e0SRoman Divacky // TODO: white-list trivial vbase initializers. This case wouldn't
74779ade4e0SRoman Divacky // be subject to the restrictions below.
74879ade4e0SRoman Divacky
74979ade4e0SRoman Divacky // TODO: white-list cases where:
75079ade4e0SRoman Divacky // - there are no non-reference parameters to the constructor
75179ade4e0SRoman Divacky // - the initializers don't access any non-reference parameters
75279ade4e0SRoman Divacky // - the initializers don't take the address of non-reference
75379ade4e0SRoman Divacky // parameters
75479ade4e0SRoman Divacky // - etc.
75579ade4e0SRoman Divacky // If we ever add any of the above cases, remember that:
756cfca06d7SDimitry Andric // - function-try-blocks will always exclude this optimization
75779ade4e0SRoman Divacky // - we need to perform the constructor prologue and cleanup in
75879ade4e0SRoman Divacky // EmitConstructorBody.
75979ade4e0SRoman Divacky
76079ade4e0SRoman Divacky return false;
76179ade4e0SRoman Divacky }
76279ade4e0SRoman Divacky
76379ade4e0SRoman Divacky // We also disable the optimization for variadic functions because
76479ade4e0SRoman Divacky // it's impossible to "re-pass" varargs.
765519fc96cSDimitry Andric if (Ctor->getType()->castAs<FunctionProtoType>()->isVariadic())
76679ade4e0SRoman Divacky return false;
76779ade4e0SRoman Divacky
76801af97d3SDimitry Andric // FIXME: Decide if we can do a delegation of a delegating constructor.
76901af97d3SDimitry Andric if (Ctor->isDelegatingConstructor())
77001af97d3SDimitry Andric return false;
77101af97d3SDimitry Andric
77279ade4e0SRoman Divacky return true;
77379ade4e0SRoman Divacky }
77479ade4e0SRoman Divacky
77506d4ba38SDimitry Andric // Emit code in ctor (Prologue==true) or dtor (Prologue==false)
77606d4ba38SDimitry Andric // to poison the extra field paddings inserted under
77706d4ba38SDimitry Andric // -fsanitize-address-field-padding=1|2.
EmitAsanPrologueOrEpilogue(bool Prologue)77806d4ba38SDimitry Andric void CodeGenFunction::EmitAsanPrologueOrEpilogue(bool Prologue) {
77906d4ba38SDimitry Andric ASTContext &Context = getContext();
78006d4ba38SDimitry Andric const CXXRecordDecl *ClassDecl =
78106d4ba38SDimitry Andric Prologue ? cast<CXXConstructorDecl>(CurGD.getDecl())->getParent()
78206d4ba38SDimitry Andric : cast<CXXDestructorDecl>(CurGD.getDecl())->getParent();
78306d4ba38SDimitry Andric if (!ClassDecl->mayInsertExtraPadding()) return;
78406d4ba38SDimitry Andric
78506d4ba38SDimitry Andric struct SizeAndOffset {
78606d4ba38SDimitry Andric uint64_t Size;
78706d4ba38SDimitry Andric uint64_t Offset;
78806d4ba38SDimitry Andric };
78906d4ba38SDimitry Andric
79006d4ba38SDimitry Andric unsigned PtrSize = CGM.getDataLayout().getPointerSizeInBits();
79106d4ba38SDimitry Andric const ASTRecordLayout &Info = Context.getASTRecordLayout(ClassDecl);
79206d4ba38SDimitry Andric
79306d4ba38SDimitry Andric // Populate sizes and offsets of fields.
79406d4ba38SDimitry Andric SmallVector<SizeAndOffset, 16> SSV(Info.getFieldCount());
79506d4ba38SDimitry Andric for (unsigned i = 0, e = Info.getFieldCount(); i != e; ++i)
79606d4ba38SDimitry Andric SSV[i].Offset =
79706d4ba38SDimitry Andric Context.toCharUnitsFromBits(Info.getFieldOffset(i)).getQuantity();
79806d4ba38SDimitry Andric
79906d4ba38SDimitry Andric size_t NumFields = 0;
80006d4ba38SDimitry Andric for (const auto *Field : ClassDecl->fields()) {
80106d4ba38SDimitry Andric const FieldDecl *D = Field;
802b60736ecSDimitry Andric auto FieldInfo = Context.getTypeInfoInChars(D->getType());
803b60736ecSDimitry Andric CharUnits FieldSize = FieldInfo.Width;
80406d4ba38SDimitry Andric assert(NumFields < SSV.size());
80506d4ba38SDimitry Andric SSV[NumFields].Size = D->isBitField() ? 0 : FieldSize.getQuantity();
80606d4ba38SDimitry Andric NumFields++;
80706d4ba38SDimitry Andric }
80806d4ba38SDimitry Andric assert(NumFields == SSV.size());
80906d4ba38SDimitry Andric if (SSV.size() <= 1) return;
81006d4ba38SDimitry Andric
81106d4ba38SDimitry Andric // We will insert calls to __asan_* run-time functions.
81206d4ba38SDimitry Andric // LLVM AddressSanitizer pass may decide to inline them later.
81306d4ba38SDimitry Andric llvm::Type *Args[2] = {IntPtrTy, IntPtrTy};
81406d4ba38SDimitry Andric llvm::FunctionType *FTy =
81506d4ba38SDimitry Andric llvm::FunctionType::get(CGM.VoidTy, Args, false);
81622989816SDimitry Andric llvm::FunctionCallee F = CGM.CreateRuntimeFunction(
81706d4ba38SDimitry Andric FTy, Prologue ? "__asan_poison_intra_object_redzone"
81806d4ba38SDimitry Andric : "__asan_unpoison_intra_object_redzone");
81906d4ba38SDimitry Andric
82006d4ba38SDimitry Andric llvm::Value *ThisPtr = LoadCXXThis();
82106d4ba38SDimitry Andric ThisPtr = Builder.CreatePtrToInt(ThisPtr, IntPtrTy);
82206d4ba38SDimitry Andric uint64_t TypeSize = Info.getNonVirtualSize().getQuantity();
82306d4ba38SDimitry Andric // For each field check if it has sufficient padding,
82406d4ba38SDimitry Andric // if so (un)poison it with a call.
82506d4ba38SDimitry Andric for (size_t i = 0; i < SSV.size(); i++) {
82606d4ba38SDimitry Andric uint64_t AsanAlignment = 8;
82706d4ba38SDimitry Andric uint64_t NextField = i == SSV.size() - 1 ? TypeSize : SSV[i + 1].Offset;
82806d4ba38SDimitry Andric uint64_t PoisonSize = NextField - SSV[i].Offset - SSV[i].Size;
82906d4ba38SDimitry Andric uint64_t EndOffset = SSV[i].Offset + SSV[i].Size;
83006d4ba38SDimitry Andric if (PoisonSize < AsanAlignment || !SSV[i].Size ||
83106d4ba38SDimitry Andric (NextField % AsanAlignment) != 0)
83206d4ba38SDimitry Andric continue;
8335e20cdd8SDimitry Andric Builder.CreateCall(
8345e20cdd8SDimitry Andric F, {Builder.CreateAdd(ThisPtr, Builder.getIntN(PtrSize, EndOffset)),
8355e20cdd8SDimitry Andric Builder.getIntN(PtrSize, PoisonSize)});
83606d4ba38SDimitry Andric }
83706d4ba38SDimitry Andric }
83806d4ba38SDimitry Andric
83979ade4e0SRoman Divacky /// EmitConstructorBody - Emits the body of the current constructor.
EmitConstructorBody(FunctionArgList & Args)84079ade4e0SRoman Divacky void CodeGenFunction::EmitConstructorBody(FunctionArgList &Args) {
84106d4ba38SDimitry Andric EmitAsanPrologueOrEpilogue(true);
84279ade4e0SRoman Divacky const CXXConstructorDecl *Ctor = cast<CXXConstructorDecl>(CurGD.getDecl());
84379ade4e0SRoman Divacky CXXCtorType CtorType = CurGD.getCtorType();
84479ade4e0SRoman Divacky
8459f4dbff6SDimitry Andric assert((CGM.getTarget().getCXXABI().hasConstructorVariants() ||
8469f4dbff6SDimitry Andric CtorType == Ctor_Complete) &&
8479f4dbff6SDimitry Andric "can only generate complete ctor for this ABI");
8489f4dbff6SDimitry Andric
84979ade4e0SRoman Divacky // Before we go any further, try the complete->base constructor
85079ade4e0SRoman Divacky // delegation optimization.
85156d91b49SDimitry Andric if (CtorType == Ctor_Complete && IsConstructorDelegationValid(Ctor) &&
8526a037251SDimitry Andric CGM.getTarget().getCXXABI().hasConstructorVariants()) {
853676fbe81SDimitry Andric EmitDelegateCXXConstructorCall(Ctor, Ctor_Base, Args, Ctor->getEndLoc());
85479ade4e0SRoman Divacky return;
85579ade4e0SRoman Divacky }
85679ade4e0SRoman Divacky
85745b53394SDimitry Andric const FunctionDecl *Definition = nullptr;
85806d4ba38SDimitry Andric Stmt *Body = Ctor->getBody(Definition);
85906d4ba38SDimitry Andric assert(Definition == Ctor && "emitting wrong constructor body");
86079ade4e0SRoman Divacky
86179ade4e0SRoman Divacky // Enter the function-try-block before the constructor prologue if
86279ade4e0SRoman Divacky // applicable.
863ac9a064cSDimitry Andric bool IsTryBody = isa_and_nonnull<CXXTryStmt>(Body);
86479ade4e0SRoman Divacky if (IsTryBody)
8654ba67500SRoman Divacky EnterCXXTryStmt(*cast<CXXTryStmt>(Body), true);
86679ade4e0SRoman Divacky
8675e20cdd8SDimitry Andric incrementProfileCounter(Body);
868aca2e42cSDimitry Andric maybeCreateMCDCCondBitmap();
8699f4dbff6SDimitry Andric
870bfef3995SDimitry Andric RunCleanupsScope RunCleanups(*this);
87179ade4e0SRoman Divacky
872dbe13110SDimitry Andric // TODO: in restricted cases, we can emit the vbase initializers of
873dbe13110SDimitry Andric // a complete ctor and then delegate to the base ctor.
874dbe13110SDimitry Andric
87579ade4e0SRoman Divacky // Emit the constructor prologue, i.e. the base and member
87679ade4e0SRoman Divacky // initializers.
877d7279c4cSRoman Divacky EmitCtorPrologue(Ctor, CtorType, Args);
87879ade4e0SRoman Divacky
87979ade4e0SRoman Divacky // Emit the body of the statement.
88079ade4e0SRoman Divacky if (IsTryBody)
88179ade4e0SRoman Divacky EmitStmt(cast<CXXTryStmt>(Body)->getTryBlock());
88279ade4e0SRoman Divacky else if (Body)
88379ade4e0SRoman Divacky EmitStmt(Body);
88479ade4e0SRoman Divacky
88579ade4e0SRoman Divacky // Emit any cleanup blocks associated with the member or base
88679ade4e0SRoman Divacky // initializers, which includes (along the exceptional path) the
88779ade4e0SRoman Divacky // destructors for those members and bases that were fully
88879ade4e0SRoman Divacky // constructed.
889bfef3995SDimitry Andric RunCleanups.ForceCleanup();
89079ade4e0SRoman Divacky
89179ade4e0SRoman Divacky if (IsTryBody)
8924ba67500SRoman Divacky ExitCXXTryStmt(*cast<CXXTryStmt>(Body), true);
89379ade4e0SRoman Divacky }
89479ade4e0SRoman Divacky
895809500fcSDimitry Andric namespace {
896bfef3995SDimitry Andric /// RAII object to indicate that codegen is copying the value representation
897bfef3995SDimitry Andric /// instead of the object representation. Useful when copying a struct or
898bfef3995SDimitry Andric /// class which has uninitialized members and we're only performing
899bfef3995SDimitry Andric /// lvalue-to-rvalue conversion on the object but not its members.
900bfef3995SDimitry Andric class CopyingValueRepresentation {
901bfef3995SDimitry Andric public:
CopyingValueRepresentation(CodeGenFunction & CGF)902bfef3995SDimitry Andric explicit CopyingValueRepresentation(CodeGenFunction &CGF)
90306d4ba38SDimitry Andric : CGF(CGF), OldSanOpts(CGF.SanOpts) {
90406d4ba38SDimitry Andric CGF.SanOpts.set(SanitizerKind::Bool, false);
90506d4ba38SDimitry Andric CGF.SanOpts.set(SanitizerKind::Enum, false);
906bfef3995SDimitry Andric }
~CopyingValueRepresentation()907bfef3995SDimitry Andric ~CopyingValueRepresentation() {
908bfef3995SDimitry Andric CGF.SanOpts = OldSanOpts;
909bfef3995SDimitry Andric }
910bfef3995SDimitry Andric private:
911bfef3995SDimitry Andric CodeGenFunction &CGF;
91206d4ba38SDimitry Andric SanitizerSet OldSanOpts;
913bfef3995SDimitry Andric };
9142b6b257fSDimitry Andric } // end anonymous namespace
915bfef3995SDimitry Andric
916bfef3995SDimitry Andric namespace {
917809500fcSDimitry Andric class FieldMemcpyizer {
918809500fcSDimitry Andric public:
FieldMemcpyizer(CodeGenFunction & CGF,const CXXRecordDecl * ClassDecl,const VarDecl * SrcRec)919809500fcSDimitry Andric FieldMemcpyizer(CodeGenFunction &CGF, const CXXRecordDecl *ClassDecl,
920809500fcSDimitry Andric const VarDecl *SrcRec)
921809500fcSDimitry Andric : CGF(CGF), ClassDecl(ClassDecl), SrcRec(SrcRec),
922809500fcSDimitry Andric RecLayout(CGF.getContext().getASTRecordLayout(ClassDecl)),
9239f4dbff6SDimitry Andric FirstField(nullptr), LastField(nullptr), FirstFieldOffset(0),
9249f4dbff6SDimitry Andric LastFieldOffset(0), LastAddedFieldIndex(0) {}
925809500fcSDimitry Andric
isMemcpyableField(FieldDecl * F) const92606d4ba38SDimitry Andric bool isMemcpyableField(FieldDecl *F) const {
92706d4ba38SDimitry Andric // Never memcpy fields when we are adding poisoned paddings.
92806d4ba38SDimitry Andric if (CGF.getContext().getLangOpts().SanitizeAddressFieldPadding)
92906d4ba38SDimitry Andric return false;
930809500fcSDimitry Andric Qualifiers Qual = F->getType().getQualifiers();
931809500fcSDimitry Andric if (Qual.hasVolatile() || Qual.hasObjCLifetime())
932809500fcSDimitry Andric return false;
933809500fcSDimitry Andric return true;
934809500fcSDimitry Andric }
935809500fcSDimitry Andric
addMemcpyableField(FieldDecl * F)936809500fcSDimitry Andric void addMemcpyableField(FieldDecl *F) {
937ac9a064cSDimitry Andric if (isEmptyFieldForLayout(CGF.getContext(), F))
938706b4fc4SDimitry Andric return;
9399f4dbff6SDimitry Andric if (!FirstField)
940809500fcSDimitry Andric addInitialField(F);
941809500fcSDimitry Andric else
942809500fcSDimitry Andric addNextField(F);
943809500fcSDimitry Andric }
944809500fcSDimitry Andric
getMemcpySize(uint64_t FirstByteOffset) const94506d4ba38SDimitry Andric CharUnits getMemcpySize(uint64_t FirstByteOffset) const {
94648675466SDimitry Andric ASTContext &Ctx = CGF.getContext();
947809500fcSDimitry Andric unsigned LastFieldSize =
94848675466SDimitry Andric LastField->isBitField()
94948675466SDimitry Andric ? LastField->getBitWidthValue(Ctx)
95048675466SDimitry Andric : Ctx.toBits(
951b60736ecSDimitry Andric Ctx.getTypeInfoDataSizeInChars(LastField->getType()).Width);
95248675466SDimitry Andric uint64_t MemcpySizeBits = LastFieldOffset + LastFieldSize -
95348675466SDimitry Andric FirstByteOffset + Ctx.getCharWidth() - 1;
95448675466SDimitry Andric CharUnits MemcpySize = Ctx.toCharUnitsFromBits(MemcpySizeBits);
955809500fcSDimitry Andric return MemcpySize;
956809500fcSDimitry Andric }
957809500fcSDimitry Andric
emitMemcpy()958809500fcSDimitry Andric void emitMemcpy() {
959809500fcSDimitry Andric // Give the subclass a chance to bail out if it feels the memcpy isn't
960809500fcSDimitry Andric // worth it (e.g. Hasn't aggregated enough data).
9619f4dbff6SDimitry Andric if (!FirstField) {
962809500fcSDimitry Andric return;
963809500fcSDimitry Andric }
964809500fcSDimitry Andric
96506d4ba38SDimitry Andric uint64_t FirstByteOffset;
966809500fcSDimitry Andric if (FirstField->isBitField()) {
967809500fcSDimitry Andric const CGRecordLayout &RL =
968809500fcSDimitry Andric CGF.getTypes().getCGRecordLayout(FirstField->getParent());
969809500fcSDimitry Andric const CGBitFieldInfo &BFInfo = RL.getBitFieldInfo(FirstField);
97006d4ba38SDimitry Andric // FirstFieldOffset is not appropriate for bitfields,
97151ece4aaSDimitry Andric // we need to use the storage offset instead.
97251ece4aaSDimitry Andric FirstByteOffset = CGF.getContext().toBits(BFInfo.StorageOffset);
973809500fcSDimitry Andric } else {
97406d4ba38SDimitry Andric FirstByteOffset = FirstFieldOffset;
975809500fcSDimitry Andric }
976809500fcSDimitry Andric
97706d4ba38SDimitry Andric CharUnits MemcpySize = getMemcpySize(FirstByteOffset);
978809500fcSDimitry Andric QualType RecordTy = CGF.getContext().getTypeDeclType(ClassDecl);
97945b53394SDimitry Andric Address ThisPtr = CGF.LoadCXXThisAddress();
98045b53394SDimitry Andric LValue DestLV = CGF.MakeAddrLValue(ThisPtr, RecordTy);
981809500fcSDimitry Andric LValue Dest = CGF.EmitLValueForFieldInitialization(DestLV, FirstField);
982809500fcSDimitry Andric llvm::Value *SrcPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(SrcRec));
983809500fcSDimitry Andric LValue SrcLV = CGF.MakeNaturalAlignAddrLValue(SrcPtr, RecordTy);
984809500fcSDimitry Andric LValue Src = CGF.EmitLValueForFieldInitialization(SrcLV, FirstField);
985809500fcSDimitry Andric
986706b4fc4SDimitry Andric emitMemcpyIR(
987ac9a064cSDimitry Andric Dest.isBitField() ? Dest.getBitFieldAddress() : Dest.getAddress(),
988ac9a064cSDimitry Andric Src.isBitField() ? Src.getBitFieldAddress() : Src.getAddress(),
98945b53394SDimitry Andric MemcpySize);
990809500fcSDimitry Andric reset();
991809500fcSDimitry Andric }
992809500fcSDimitry Andric
reset()993809500fcSDimitry Andric void reset() {
9949f4dbff6SDimitry Andric FirstField = nullptr;
995809500fcSDimitry Andric }
996809500fcSDimitry Andric
997809500fcSDimitry Andric protected:
998809500fcSDimitry Andric CodeGenFunction &CGF;
999809500fcSDimitry Andric const CXXRecordDecl *ClassDecl;
1000809500fcSDimitry Andric
1001809500fcSDimitry Andric private:
emitMemcpyIR(Address DestPtr,Address SrcPtr,CharUnits Size)100245b53394SDimitry Andric void emitMemcpyIR(Address DestPtr, Address SrcPtr, CharUnits Size) {
10037fa27ce4SDimitry Andric DestPtr = DestPtr.withElementType(CGF.Int8Ty);
10047fa27ce4SDimitry Andric SrcPtr = SrcPtr.withElementType(CGF.Int8Ty);
100545b53394SDimitry Andric CGF.Builder.CreateMemCpy(DestPtr, SrcPtr, Size.getQuantity());
1006809500fcSDimitry Andric }
1007809500fcSDimitry Andric
addInitialField(FieldDecl * F)1008809500fcSDimitry Andric void addInitialField(FieldDecl *F) {
1009809500fcSDimitry Andric FirstField = F;
1010809500fcSDimitry Andric LastField = F;
1011809500fcSDimitry Andric FirstFieldOffset = RecLayout.getFieldOffset(F->getFieldIndex());
1012809500fcSDimitry Andric LastFieldOffset = FirstFieldOffset;
1013809500fcSDimitry Andric LastAddedFieldIndex = F->getFieldIndex();
1014809500fcSDimitry Andric }
1015809500fcSDimitry Andric
addNextField(FieldDecl * F)1016809500fcSDimitry Andric void addNextField(FieldDecl *F) {
1017bfef3995SDimitry Andric // For the most part, the following invariant will hold:
1018bfef3995SDimitry Andric // F->getFieldIndex() == LastAddedFieldIndex + 1
1019bfef3995SDimitry Andric // The one exception is that Sema won't add a copy-initializer for an
1020bfef3995SDimitry Andric // unnamed bitfield, which will show up here as a gap in the sequence.
1021bfef3995SDimitry Andric assert(F->getFieldIndex() >= LastAddedFieldIndex + 1 &&
1022bfef3995SDimitry Andric "Cannot aggregate fields out of order.");
1023809500fcSDimitry Andric LastAddedFieldIndex = F->getFieldIndex();
1024809500fcSDimitry Andric
1025809500fcSDimitry Andric // The 'first' and 'last' fields are chosen by offset, rather than field
1026809500fcSDimitry Andric // index. This allows the code to support bitfields, as well as regular
1027809500fcSDimitry Andric // fields.
1028809500fcSDimitry Andric uint64_t FOffset = RecLayout.getFieldOffset(F->getFieldIndex());
1029809500fcSDimitry Andric if (FOffset < FirstFieldOffset) {
1030809500fcSDimitry Andric FirstField = F;
1031809500fcSDimitry Andric FirstFieldOffset = FOffset;
103222989816SDimitry Andric } else if (FOffset >= LastFieldOffset) {
1033809500fcSDimitry Andric LastField = F;
1034809500fcSDimitry Andric LastFieldOffset = FOffset;
1035809500fcSDimitry Andric }
1036809500fcSDimitry Andric }
1037809500fcSDimitry Andric
1038809500fcSDimitry Andric const VarDecl *SrcRec;
1039809500fcSDimitry Andric const ASTRecordLayout &RecLayout;
1040809500fcSDimitry Andric FieldDecl *FirstField;
1041809500fcSDimitry Andric FieldDecl *LastField;
1042809500fcSDimitry Andric uint64_t FirstFieldOffset, LastFieldOffset;
1043809500fcSDimitry Andric unsigned LastAddedFieldIndex;
1044809500fcSDimitry Andric };
1045809500fcSDimitry Andric
1046809500fcSDimitry Andric class ConstructorMemcpyizer : public FieldMemcpyizer {
1047809500fcSDimitry Andric private:
1048809500fcSDimitry Andric /// Get source argument for copy constructor. Returns null if not a copy
1049809500fcSDimitry Andric /// constructor.
getTrivialCopySource(CodeGenFunction & CGF,const CXXConstructorDecl * CD,FunctionArgList & Args)105006d4ba38SDimitry Andric static const VarDecl *getTrivialCopySource(CodeGenFunction &CGF,
105106d4ba38SDimitry Andric const CXXConstructorDecl *CD,
1052809500fcSDimitry Andric FunctionArgList &Args) {
1053bfef3995SDimitry Andric if (CD->isCopyOrMoveConstructor() && CD->isDefaulted())
105406d4ba38SDimitry Andric return Args[CGF.CGM.getCXXABI().getSrcArgforCopyCtor(CD, Args)];
10559f4dbff6SDimitry Andric return nullptr;
1056809500fcSDimitry Andric }
1057809500fcSDimitry Andric
1058809500fcSDimitry Andric // Returns true if a CXXCtorInitializer represents a member initialization
1059809500fcSDimitry Andric // that can be rolled into a memcpy.
isMemberInitMemcpyable(CXXCtorInitializer * MemberInit) const1060809500fcSDimitry Andric bool isMemberInitMemcpyable(CXXCtorInitializer *MemberInit) const {
1061809500fcSDimitry Andric if (!MemcpyableCtor)
1062809500fcSDimitry Andric return false;
1063809500fcSDimitry Andric FieldDecl *Field = MemberInit->getMember();
10649f4dbff6SDimitry Andric assert(Field && "No field for member init.");
1065809500fcSDimitry Andric QualType FieldType = Field->getType();
1066809500fcSDimitry Andric CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(MemberInit->getInit());
1067809500fcSDimitry Andric
10685e20cdd8SDimitry Andric // Bail out on non-memcpyable, not-trivially-copyable members.
10695e20cdd8SDimitry Andric if (!(CE && isMemcpyEquivalentSpecialMember(CE->getConstructor())) &&
1070809500fcSDimitry Andric !(FieldType.isTriviallyCopyableType(CGF.getContext()) ||
1071809500fcSDimitry Andric FieldType->isReferenceType()))
1072809500fcSDimitry Andric return false;
1073809500fcSDimitry Andric
1074809500fcSDimitry Andric // Bail out on volatile fields.
1075809500fcSDimitry Andric if (!isMemcpyableField(Field))
1076809500fcSDimitry Andric return false;
1077809500fcSDimitry Andric
1078809500fcSDimitry Andric // Otherwise we're good.
1079809500fcSDimitry Andric return true;
1080809500fcSDimitry Andric }
1081809500fcSDimitry Andric
1082809500fcSDimitry Andric public:
ConstructorMemcpyizer(CodeGenFunction & CGF,const CXXConstructorDecl * CD,FunctionArgList & Args)1083809500fcSDimitry Andric ConstructorMemcpyizer(CodeGenFunction &CGF, const CXXConstructorDecl *CD,
1084809500fcSDimitry Andric FunctionArgList &Args)
108506d4ba38SDimitry Andric : FieldMemcpyizer(CGF, CD->getParent(), getTrivialCopySource(CGF, CD, Args)),
1086809500fcSDimitry Andric ConstructorDecl(CD),
1087bfef3995SDimitry Andric MemcpyableCtor(CD->isDefaulted() &&
1088809500fcSDimitry Andric CD->isCopyOrMoveConstructor() &&
1089809500fcSDimitry Andric CGF.getLangOpts().getGC() == LangOptions::NonGC),
1090809500fcSDimitry Andric Args(Args) { }
1091809500fcSDimitry Andric
addMemberInitializer(CXXCtorInitializer * MemberInit)1092809500fcSDimitry Andric void addMemberInitializer(CXXCtorInitializer *MemberInit) {
1093809500fcSDimitry Andric if (isMemberInitMemcpyable(MemberInit)) {
1094809500fcSDimitry Andric AggregatedInits.push_back(MemberInit);
1095809500fcSDimitry Andric addMemcpyableField(MemberInit->getMember());
1096809500fcSDimitry Andric } else {
1097809500fcSDimitry Andric emitAggregatedInits();
1098809500fcSDimitry Andric EmitMemberInitializer(CGF, ConstructorDecl->getParent(), MemberInit,
1099809500fcSDimitry Andric ConstructorDecl, Args);
1100809500fcSDimitry Andric }
1101809500fcSDimitry Andric }
1102809500fcSDimitry Andric
emitAggregatedInits()1103809500fcSDimitry Andric void emitAggregatedInits() {
1104809500fcSDimitry Andric if (AggregatedInits.size() <= 1) {
1105809500fcSDimitry Andric // This memcpy is too small to be worthwhile. Fall back on default
1106809500fcSDimitry Andric // codegen.
1107bfef3995SDimitry Andric if (!AggregatedInits.empty()) {
1108bfef3995SDimitry Andric CopyingValueRepresentation CVR(CGF);
1109809500fcSDimitry Andric EmitMemberInitializer(CGF, ConstructorDecl->getParent(),
1110bfef3995SDimitry Andric AggregatedInits[0], ConstructorDecl, Args);
111151ece4aaSDimitry Andric AggregatedInits.clear();
1112809500fcSDimitry Andric }
1113809500fcSDimitry Andric reset();
1114809500fcSDimitry Andric return;
1115809500fcSDimitry Andric }
1116809500fcSDimitry Andric
1117809500fcSDimitry Andric pushEHDestructors();
1118809500fcSDimitry Andric emitMemcpy();
1119809500fcSDimitry Andric AggregatedInits.clear();
1120809500fcSDimitry Andric }
1121809500fcSDimitry Andric
pushEHDestructors()1122809500fcSDimitry Andric void pushEHDestructors() {
112345b53394SDimitry Andric Address ThisPtr = CGF.LoadCXXThisAddress();
1124809500fcSDimitry Andric QualType RecordTy = CGF.getContext().getTypeDeclType(ClassDecl);
112545b53394SDimitry Andric LValue LHS = CGF.MakeAddrLValue(ThisPtr, RecordTy);
1126809500fcSDimitry Andric
1127809500fcSDimitry Andric for (unsigned i = 0; i < AggregatedInits.size(); ++i) {
112851ece4aaSDimitry Andric CXXCtorInitializer *MemberInit = AggregatedInits[i];
112951ece4aaSDimitry Andric QualType FieldType = MemberInit->getAnyMember()->getType();
1130809500fcSDimitry Andric QualType::DestructionKind dtorKind = FieldType.isDestructedType();
113151ece4aaSDimitry Andric if (!CGF.needsEHCleanup(dtorKind))
113251ece4aaSDimitry Andric continue;
113351ece4aaSDimitry Andric LValue FieldLHS = LHS;
113451ece4aaSDimitry Andric EmitLValueForAnyFieldInitialization(CGF, MemberInit, FieldLHS);
1135ac9a064cSDimitry Andric CGF.pushEHDestroy(dtorKind, FieldLHS.getAddress(), FieldType);
1136809500fcSDimitry Andric }
1137809500fcSDimitry Andric }
1138809500fcSDimitry Andric
finish()1139809500fcSDimitry Andric void finish() {
1140809500fcSDimitry Andric emitAggregatedInits();
1141809500fcSDimitry Andric }
1142809500fcSDimitry Andric
1143809500fcSDimitry Andric private:
1144809500fcSDimitry Andric const CXXConstructorDecl *ConstructorDecl;
1145809500fcSDimitry Andric bool MemcpyableCtor;
1146809500fcSDimitry Andric FunctionArgList &Args;
1147809500fcSDimitry Andric SmallVector<CXXCtorInitializer*, 16> AggregatedInits;
1148809500fcSDimitry Andric };
1149809500fcSDimitry Andric
1150809500fcSDimitry Andric class AssignmentMemcpyizer : public FieldMemcpyizer {
1151809500fcSDimitry Andric private:
1152809500fcSDimitry Andric // Returns the memcpyable field copied by the given statement, if one
1153bfef3995SDimitry Andric // exists. Otherwise returns null.
getMemcpyableField(Stmt * S)1154809500fcSDimitry Andric FieldDecl *getMemcpyableField(Stmt *S) {
1155809500fcSDimitry Andric if (!AssignmentsMemcpyable)
11569f4dbff6SDimitry Andric return nullptr;
1157809500fcSDimitry Andric if (BinaryOperator *BO = dyn_cast<BinaryOperator>(S)) {
1158809500fcSDimitry Andric // Recognise trivial assignments.
1159809500fcSDimitry Andric if (BO->getOpcode() != BO_Assign)
11609f4dbff6SDimitry Andric return nullptr;
1161809500fcSDimitry Andric MemberExpr *ME = dyn_cast<MemberExpr>(BO->getLHS());
1162809500fcSDimitry Andric if (!ME)
11639f4dbff6SDimitry Andric return nullptr;
1164809500fcSDimitry Andric FieldDecl *Field = dyn_cast<FieldDecl>(ME->getMemberDecl());
1165809500fcSDimitry Andric if (!Field || !isMemcpyableField(Field))
11669f4dbff6SDimitry Andric return nullptr;
1167809500fcSDimitry Andric Stmt *RHS = BO->getRHS();
1168809500fcSDimitry Andric if (ImplicitCastExpr *EC = dyn_cast<ImplicitCastExpr>(RHS))
1169809500fcSDimitry Andric RHS = EC->getSubExpr();
1170809500fcSDimitry Andric if (!RHS)
11719f4dbff6SDimitry Andric return nullptr;
11727442d6faSDimitry Andric if (MemberExpr *ME2 = dyn_cast<MemberExpr>(RHS)) {
11737442d6faSDimitry Andric if (ME2->getMemberDecl() == Field)
1174809500fcSDimitry Andric return Field;
11757442d6faSDimitry Andric }
11767442d6faSDimitry Andric return nullptr;
1177809500fcSDimitry Andric } else if (CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(S)) {
1178809500fcSDimitry Andric CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MCE->getCalleeDecl());
11795e20cdd8SDimitry Andric if (!(MD && isMemcpyEquivalentSpecialMember(MD)))
11809f4dbff6SDimitry Andric return nullptr;
1181809500fcSDimitry Andric MemberExpr *IOA = dyn_cast<MemberExpr>(MCE->getImplicitObjectArgument());
1182809500fcSDimitry Andric if (!IOA)
11839f4dbff6SDimitry Andric return nullptr;
1184809500fcSDimitry Andric FieldDecl *Field = dyn_cast<FieldDecl>(IOA->getMemberDecl());
1185809500fcSDimitry Andric if (!Field || !isMemcpyableField(Field))
11869f4dbff6SDimitry Andric return nullptr;
1187809500fcSDimitry Andric MemberExpr *Arg0 = dyn_cast<MemberExpr>(MCE->getArg(0));
1188809500fcSDimitry Andric if (!Arg0 || Field != dyn_cast<FieldDecl>(Arg0->getMemberDecl()))
11899f4dbff6SDimitry Andric return nullptr;
1190809500fcSDimitry Andric return Field;
1191809500fcSDimitry Andric } else if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
1192809500fcSDimitry Andric FunctionDecl *FD = dyn_cast<FunctionDecl>(CE->getCalleeDecl());
1193809500fcSDimitry Andric if (!FD || FD->getBuiltinID() != Builtin::BI__builtin_memcpy)
11949f4dbff6SDimitry Andric return nullptr;
1195809500fcSDimitry Andric Expr *DstPtr = CE->getArg(0);
1196809500fcSDimitry Andric if (ImplicitCastExpr *DC = dyn_cast<ImplicitCastExpr>(DstPtr))
1197809500fcSDimitry Andric DstPtr = DC->getSubExpr();
1198809500fcSDimitry Andric UnaryOperator *DUO = dyn_cast<UnaryOperator>(DstPtr);
1199809500fcSDimitry Andric if (!DUO || DUO->getOpcode() != UO_AddrOf)
12009f4dbff6SDimitry Andric return nullptr;
1201809500fcSDimitry Andric MemberExpr *ME = dyn_cast<MemberExpr>(DUO->getSubExpr());
1202809500fcSDimitry Andric if (!ME)
12039f4dbff6SDimitry Andric return nullptr;
1204809500fcSDimitry Andric FieldDecl *Field = dyn_cast<FieldDecl>(ME->getMemberDecl());
1205809500fcSDimitry Andric if (!Field || !isMemcpyableField(Field))
12069f4dbff6SDimitry Andric return nullptr;
1207809500fcSDimitry Andric Expr *SrcPtr = CE->getArg(1);
1208809500fcSDimitry Andric if (ImplicitCastExpr *SC = dyn_cast<ImplicitCastExpr>(SrcPtr))
1209809500fcSDimitry Andric SrcPtr = SC->getSubExpr();
1210809500fcSDimitry Andric UnaryOperator *SUO = dyn_cast<UnaryOperator>(SrcPtr);
1211809500fcSDimitry Andric if (!SUO || SUO->getOpcode() != UO_AddrOf)
12129f4dbff6SDimitry Andric return nullptr;
1213809500fcSDimitry Andric MemberExpr *ME2 = dyn_cast<MemberExpr>(SUO->getSubExpr());
1214809500fcSDimitry Andric if (!ME2 || Field != dyn_cast<FieldDecl>(ME2->getMemberDecl()))
12159f4dbff6SDimitry Andric return nullptr;
1216809500fcSDimitry Andric return Field;
1217809500fcSDimitry Andric }
1218809500fcSDimitry Andric
12199f4dbff6SDimitry Andric return nullptr;
1220809500fcSDimitry Andric }
1221809500fcSDimitry Andric
1222809500fcSDimitry Andric bool AssignmentsMemcpyable;
1223809500fcSDimitry Andric SmallVector<Stmt*, 16> AggregatedStmts;
1224809500fcSDimitry Andric
1225809500fcSDimitry Andric public:
AssignmentMemcpyizer(CodeGenFunction & CGF,const CXXMethodDecl * AD,FunctionArgList & Args)1226809500fcSDimitry Andric AssignmentMemcpyizer(CodeGenFunction &CGF, const CXXMethodDecl *AD,
1227809500fcSDimitry Andric FunctionArgList &Args)
1228809500fcSDimitry Andric : FieldMemcpyizer(CGF, AD->getParent(), Args[Args.size() - 1]),
1229809500fcSDimitry Andric AssignmentsMemcpyable(CGF.getLangOpts().getGC() == LangOptions::NonGC) {
1230809500fcSDimitry Andric assert(Args.size() == 2);
1231809500fcSDimitry Andric }
1232809500fcSDimitry Andric
emitAssignment(Stmt * S)1233809500fcSDimitry Andric void emitAssignment(Stmt *S) {
1234809500fcSDimitry Andric FieldDecl *F = getMemcpyableField(S);
1235809500fcSDimitry Andric if (F) {
1236809500fcSDimitry Andric addMemcpyableField(F);
1237809500fcSDimitry Andric AggregatedStmts.push_back(S);
1238809500fcSDimitry Andric } else {
1239809500fcSDimitry Andric emitAggregatedStmts();
1240809500fcSDimitry Andric CGF.EmitStmt(S);
1241809500fcSDimitry Andric }
1242809500fcSDimitry Andric }
1243809500fcSDimitry Andric
emitAggregatedStmts()1244809500fcSDimitry Andric void emitAggregatedStmts() {
1245809500fcSDimitry Andric if (AggregatedStmts.size() <= 1) {
1246bfef3995SDimitry Andric if (!AggregatedStmts.empty()) {
1247bfef3995SDimitry Andric CopyingValueRepresentation CVR(CGF);
1248bfef3995SDimitry Andric CGF.EmitStmt(AggregatedStmts[0]);
1249bfef3995SDimitry Andric }
1250809500fcSDimitry Andric reset();
1251809500fcSDimitry Andric }
1252809500fcSDimitry Andric
1253809500fcSDimitry Andric emitMemcpy();
1254809500fcSDimitry Andric AggregatedStmts.clear();
1255809500fcSDimitry Andric }
1256809500fcSDimitry Andric
finish()1257809500fcSDimitry Andric void finish() {
1258809500fcSDimitry Andric emitAggregatedStmts();
1259809500fcSDimitry Andric }
1260809500fcSDimitry Andric };
126145b53394SDimitry Andric } // end anonymous namespace
1262809500fcSDimitry Andric
isInitializerOfDynamicClass(const CXXCtorInitializer * BaseInit)126345b53394SDimitry Andric static bool isInitializerOfDynamicClass(const CXXCtorInitializer *BaseInit) {
126445b53394SDimitry Andric const Type *BaseType = BaseInit->getBaseClass();
126545b53394SDimitry Andric const auto *BaseClassDecl =
1266519fc96cSDimitry Andric cast<CXXRecordDecl>(BaseType->castAs<RecordType>()->getDecl());
126745b53394SDimitry Andric return BaseClassDecl->isDynamicClass();
1268809500fcSDimitry Andric }
1269809500fcSDimitry Andric
1270abe15e55SRoman Divacky /// EmitCtorPrologue - This routine generates necessary code to initialize
1271abe15e55SRoman Divacky /// base classes and non-static data members belonging to this constructor.
EmitCtorPrologue(const CXXConstructorDecl * CD,CXXCtorType CtorType,FunctionArgList & Args)1272abe15e55SRoman Divacky void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
1273d7279c4cSRoman Divacky CXXCtorType CtorType,
1274d7279c4cSRoman Divacky FunctionArgList &Args) {
127501af97d3SDimitry Andric if (CD->isDelegatingConstructor())
127601af97d3SDimitry Andric return EmitDelegatingCXXConstructorCall(CD, Args);
127701af97d3SDimitry Andric
1278abe15e55SRoman Divacky const CXXRecordDecl *ClassDecl = CD->getParent();
1279abe15e55SRoman Divacky
1280809500fcSDimitry Andric CXXConstructorDecl::init_const_iterator B = CD->init_begin(),
1281abe15e55SRoman Divacky E = CD->init_end();
1282abe15e55SRoman Divacky
128322989816SDimitry Andric // Virtual base initializers first, if any. They aren't needed if:
128422989816SDimitry Andric // - This is a base ctor variant
128522989816SDimitry Andric // - There are no vbases
128622989816SDimitry Andric // - The class is abstract, so a complete object of it cannot be constructed
128722989816SDimitry Andric //
128822989816SDimitry Andric // The check for an abstract class is necessary because sema may not have
128922989816SDimitry Andric // marked virtual base destructors referenced.
129022989816SDimitry Andric bool ConstructVBases = CtorType != Ctor_Base &&
129122989816SDimitry Andric ClassDecl->getNumVBases() != 0 &&
129222989816SDimitry Andric !ClassDecl->isAbstract();
129322989816SDimitry Andric
129422989816SDimitry Andric // In the Microsoft C++ ABI, there are no constructor variants. Instead, the
129522989816SDimitry Andric // constructor of a class with virtual bases takes an additional parameter to
129622989816SDimitry Andric // conditionally construct the virtual bases. Emit that check here.
12979f4dbff6SDimitry Andric llvm::BasicBlock *BaseCtorContinueBB = nullptr;
129822989816SDimitry Andric if (ConstructVBases &&
1299809500fcSDimitry Andric !CGM.getTarget().getCXXABI().hasConstructorVariants()) {
1300bfef3995SDimitry Andric BaseCtorContinueBB =
1301bfef3995SDimitry Andric CGM.getCXXABI().EmitCtorCompleteObjectHandler(*this, ClassDecl);
1302809500fcSDimitry Andric assert(BaseCtorContinueBB);
130329cafa66SDimitry Andric }
1304809500fcSDimitry Andric
1305809500fcSDimitry Andric for (; B != E && (*B)->isBaseInitializer() && (*B)->isBaseVirtual(); B++) {
130622989816SDimitry Andric if (!ConstructVBases)
130722989816SDimitry Andric continue;
1308b1c73532SDimitry Andric SaveAndRestore ThisRAII(CXXThisValue);
130945b53394SDimitry Andric if (CGM.getCodeGenOpts().StrictVTablePointers &&
131045b53394SDimitry Andric CGM.getCodeGenOpts().OptimizationLevel > 0 &&
131145b53394SDimitry Andric isInitializerOfDynamicClass(*B))
131248675466SDimitry Andric CXXThisValue = Builder.CreateLaunderInvariantGroup(LoadCXXThis());
131322989816SDimitry Andric EmitBaseInitializer(*this, ClassDecl, *B);
1314809500fcSDimitry Andric }
1315809500fcSDimitry Andric
1316809500fcSDimitry Andric if (BaseCtorContinueBB) {
1317809500fcSDimitry Andric // Complete object handler should continue to the remaining initializers.
1318809500fcSDimitry Andric Builder.CreateBr(BaseCtorContinueBB);
1319809500fcSDimitry Andric EmitBlock(BaseCtorContinueBB);
1320809500fcSDimitry Andric }
1321809500fcSDimitry Andric
1322809500fcSDimitry Andric // Then, non-virtual base initializers.
1323809500fcSDimitry Andric for (; B != E && (*B)->isBaseInitializer(); B++) {
1324809500fcSDimitry Andric assert(!(*B)->isBaseVirtual());
1325b1c73532SDimitry Andric SaveAndRestore ThisRAII(CXXThisValue);
132645b53394SDimitry Andric if (CGM.getCodeGenOpts().StrictVTablePointers &&
132745b53394SDimitry Andric CGM.getCodeGenOpts().OptimizationLevel > 0 &&
132845b53394SDimitry Andric isInitializerOfDynamicClass(*B))
132948675466SDimitry Andric CXXThisValue = Builder.CreateLaunderInvariantGroup(LoadCXXThis());
133022989816SDimitry Andric EmitBaseInitializer(*this, ClassDecl, *B);
1331abe15e55SRoman Divacky }
1332abe15e55SRoman Divacky
133311d2b2d2SRoman Divacky InitializeVTablePointers(ClassDecl);
1334ecb7e5c8SRoman Divacky
1335809500fcSDimitry Andric // And finally, initialize class members.
133645b53394SDimitry Andric FieldConstructionScope FCS(*this, LoadCXXThisAddress());
1337809500fcSDimitry Andric ConstructorMemcpyizer CM(*this, CD, Args);
1338809500fcSDimitry Andric for (; B != E; B++) {
1339809500fcSDimitry Andric CXXCtorInitializer *Member = (*B);
1340809500fcSDimitry Andric assert(!Member->isBaseInitializer());
1341809500fcSDimitry Andric assert(Member->isAnyMemberInitializer() &&
1342809500fcSDimitry Andric "Delegating initializer on non-delegating constructor");
1343809500fcSDimitry Andric CM.addMemberInitializer(Member);
1344809500fcSDimitry Andric }
1345809500fcSDimitry Andric CM.finish();
1346ecb7e5c8SRoman Divacky }
1347abe15e55SRoman Divacky
134829cafa66SDimitry Andric static bool
134929cafa66SDimitry Andric FieldHasTrivialDestructorBody(ASTContext &Context, const FieldDecl *Field);
135029cafa66SDimitry Andric
135129cafa66SDimitry Andric static bool
HasTrivialDestructorBody(ASTContext & Context,const CXXRecordDecl * BaseClassDecl,const CXXRecordDecl * MostDerivedClassDecl)135229cafa66SDimitry Andric HasTrivialDestructorBody(ASTContext &Context,
135329cafa66SDimitry Andric const CXXRecordDecl *BaseClassDecl,
135429cafa66SDimitry Andric const CXXRecordDecl *MostDerivedClassDecl)
135529cafa66SDimitry Andric {
135629cafa66SDimitry Andric // If the destructor is trivial we don't have to check anything else.
135729cafa66SDimitry Andric if (BaseClassDecl->hasTrivialDestructor())
135829cafa66SDimitry Andric return true;
135929cafa66SDimitry Andric
136029cafa66SDimitry Andric if (!BaseClassDecl->getDestructor()->hasTrivialBody())
136129cafa66SDimitry Andric return false;
136229cafa66SDimitry Andric
136329cafa66SDimitry Andric // Check fields.
13649f4dbff6SDimitry Andric for (const auto *Field : BaseClassDecl->fields())
136529cafa66SDimitry Andric if (!FieldHasTrivialDestructorBody(Context, Field))
136629cafa66SDimitry Andric return false;
136729cafa66SDimitry Andric
136829cafa66SDimitry Andric // Check non-virtual bases.
13699f4dbff6SDimitry Andric for (const auto &I : BaseClassDecl->bases()) {
13709f4dbff6SDimitry Andric if (I.isVirtual())
137129cafa66SDimitry Andric continue;
137229cafa66SDimitry Andric
137329cafa66SDimitry Andric const CXXRecordDecl *NonVirtualBase =
13749f4dbff6SDimitry Andric cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl());
137529cafa66SDimitry Andric if (!HasTrivialDestructorBody(Context, NonVirtualBase,
137629cafa66SDimitry Andric MostDerivedClassDecl))
137729cafa66SDimitry Andric return false;
137829cafa66SDimitry Andric }
137929cafa66SDimitry Andric
138029cafa66SDimitry Andric if (BaseClassDecl == MostDerivedClassDecl) {
138129cafa66SDimitry Andric // Check virtual bases.
13829f4dbff6SDimitry Andric for (const auto &I : BaseClassDecl->vbases()) {
138329cafa66SDimitry Andric const CXXRecordDecl *VirtualBase =
13849f4dbff6SDimitry Andric cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl());
138529cafa66SDimitry Andric if (!HasTrivialDestructorBody(Context, VirtualBase,
138629cafa66SDimitry Andric MostDerivedClassDecl))
138729cafa66SDimitry Andric return false;
138829cafa66SDimitry Andric }
138929cafa66SDimitry Andric }
139029cafa66SDimitry Andric
139129cafa66SDimitry Andric return true;
139229cafa66SDimitry Andric }
139329cafa66SDimitry Andric
139429cafa66SDimitry Andric static bool
FieldHasTrivialDestructorBody(ASTContext & Context,const FieldDecl * Field)139529cafa66SDimitry Andric FieldHasTrivialDestructorBody(ASTContext &Context,
139629cafa66SDimitry Andric const FieldDecl *Field)
139729cafa66SDimitry Andric {
139829cafa66SDimitry Andric QualType FieldBaseElementType = Context.getBaseElementType(Field->getType());
139929cafa66SDimitry Andric
140029cafa66SDimitry Andric const RecordType *RT = FieldBaseElementType->getAs<RecordType>();
140129cafa66SDimitry Andric if (!RT)
140229cafa66SDimitry Andric return true;
140329cafa66SDimitry Andric
140429cafa66SDimitry Andric CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
1405c192b3dcSDimitry Andric
1406c192b3dcSDimitry Andric // The destructor for an implicit anonymous union member is never invoked.
1407c192b3dcSDimitry Andric if (FieldClassDecl->isUnion() && FieldClassDecl->isAnonymousStructOrUnion())
1408ac9a064cSDimitry Andric return true;
1409c192b3dcSDimitry Andric
141029cafa66SDimitry Andric return HasTrivialDestructorBody(Context, FieldClassDecl, FieldClassDecl);
141129cafa66SDimitry Andric }
141229cafa66SDimitry Andric
141329cafa66SDimitry Andric /// CanSkipVTablePointerInitialization - Check whether we need to initialize
141429cafa66SDimitry Andric /// any vtable pointers before calling this destructor.
CanSkipVTablePointerInitialization(CodeGenFunction & CGF,const CXXDestructorDecl * Dtor)141545b53394SDimitry Andric static bool CanSkipVTablePointerInitialization(CodeGenFunction &CGF,
141629cafa66SDimitry Andric const CXXDestructorDecl *Dtor) {
141745b53394SDimitry Andric const CXXRecordDecl *ClassDecl = Dtor->getParent();
141845b53394SDimitry Andric if (!ClassDecl->isDynamicClass())
141945b53394SDimitry Andric return true;
142045b53394SDimitry Andric
1421c0981da4SDimitry Andric // For a final class, the vtable pointer is known to already point to the
1422c0981da4SDimitry Andric // class's vtable.
1423c0981da4SDimitry Andric if (ClassDecl->isEffectivelyFinal())
1424c0981da4SDimitry Andric return true;
1425c0981da4SDimitry Andric
142629cafa66SDimitry Andric if (!Dtor->hasTrivialBody())
142729cafa66SDimitry Andric return false;
142829cafa66SDimitry Andric
142929cafa66SDimitry Andric // Check the fields.
14309f4dbff6SDimitry Andric for (const auto *Field : ClassDecl->fields())
143145b53394SDimitry Andric if (!FieldHasTrivialDestructorBody(CGF.getContext(), Field))
143229cafa66SDimitry Andric return false;
143329cafa66SDimitry Andric
143429cafa66SDimitry Andric return true;
143529cafa66SDimitry Andric }
143629cafa66SDimitry Andric
143779ade4e0SRoman Divacky /// EmitDestructorBody - Emits the body of the current destructor.
EmitDestructorBody(FunctionArgList & Args)143879ade4e0SRoman Divacky void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
143979ade4e0SRoman Divacky const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CurGD.getDecl());
144079ade4e0SRoman Divacky CXXDtorType DtorType = CurGD.getDtorType();
144179ade4e0SRoman Divacky
14427442d6faSDimitry Andric // For an abstract class, non-base destructors are never used (and can't
14437442d6faSDimitry Andric // be emitted in general, because vbase dtors may not have been validated
14447442d6faSDimitry Andric // by Sema), but the Itanium ABI doesn't make them optional and Clang may
14457442d6faSDimitry Andric // in fact emit references to them from other compilations, so emit them
14467442d6faSDimitry Andric // as functions containing a trap instruction.
14477442d6faSDimitry Andric if (DtorType != Dtor_Base && Dtor->getParent()->isAbstract()) {
14487442d6faSDimitry Andric llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap);
14497442d6faSDimitry Andric TrapCall->setDoesNotReturn();
14507442d6faSDimitry Andric TrapCall->setDoesNotThrow();
14517442d6faSDimitry Andric Builder.CreateUnreachable();
14527442d6faSDimitry Andric Builder.ClearInsertionPoint();
14537442d6faSDimitry Andric return;
14547442d6faSDimitry Andric }
14557442d6faSDimitry Andric
14565e20cdd8SDimitry Andric Stmt *Body = Dtor->getBody();
1457aca2e42cSDimitry Andric if (Body) {
14585e20cdd8SDimitry Andric incrementProfileCounter(Body);
1459aca2e42cSDimitry Andric maybeCreateMCDCCondBitmap();
1460aca2e42cSDimitry Andric }
14615e20cdd8SDimitry Andric
14623d1dcd9bSDimitry Andric // The call to operator delete in a deleting destructor happens
14633d1dcd9bSDimitry Andric // outside of the function-try-block, which means it's always
14643d1dcd9bSDimitry Andric // possible to delegate the destructor body to the complete
14653d1dcd9bSDimitry Andric // destructor. Do so.
14663d1dcd9bSDimitry Andric if (DtorType == Dtor_Deleting) {
1467461a67faSDimitry Andric RunCleanupsScope DtorEpilogue(*this);
14683d1dcd9bSDimitry Andric EnterDtorCleanups(Dtor, Dtor_Deleting);
146922989816SDimitry Andric if (HaveInsertPoint()) {
1470b1c73532SDimitry Andric QualType ThisTy = Dtor->getFunctionObjectParameterType();
14713d1dcd9bSDimitry Andric EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false,
147222989816SDimitry Andric /*Delegating=*/false, LoadCXXThisAddress(), ThisTy);
147322989816SDimitry Andric }
14743d1dcd9bSDimitry Andric return;
14753d1dcd9bSDimitry Andric }
14763d1dcd9bSDimitry Andric
147779ade4e0SRoman Divacky // If the body is a function-try-block, enter the try before
14783d1dcd9bSDimitry Andric // anything else.
1479ac9a064cSDimitry Andric bool isTryBody = isa_and_nonnull<CXXTryStmt>(Body);
148079ade4e0SRoman Divacky if (isTryBody)
14814ba67500SRoman Divacky EnterCXXTryStmt(*cast<CXXTryStmt>(Body), true);
148206d4ba38SDimitry Andric EmitAsanPrologueOrEpilogue(false);
148379ade4e0SRoman Divacky
14843d1dcd9bSDimitry Andric // Enter the epilogue cleanups.
14853d1dcd9bSDimitry Andric RunCleanupsScope DtorEpilogue(*this);
148679ade4e0SRoman Divacky
148779ade4e0SRoman Divacky // If this is the complete variant, just invoke the base variant;
148879ade4e0SRoman Divacky // the epilogue will destruct the virtual bases. But we can't do
148979ade4e0SRoman Divacky // this optimization if the body is a function-try-block, because
1490bfef3995SDimitry Andric // we'd introduce *two* handler blocks. In the Microsoft ABI, we
1491bfef3995SDimitry Andric // always delegate because we might not have a definition in this TU.
14923d1dcd9bSDimitry Andric switch (DtorType) {
14937442d6faSDimitry Andric case Dtor_Comdat: llvm_unreachable("not expecting a COMDAT");
14943d1dcd9bSDimitry Andric case Dtor_Deleting: llvm_unreachable("already handled deleting case");
14953d1dcd9bSDimitry Andric
14963d1dcd9bSDimitry Andric case Dtor_Complete:
1497bfef3995SDimitry Andric assert((Body || getTarget().getCXXABI().isMicrosoft()) &&
1498bfef3995SDimitry Andric "can't emit a dtor without a body for non-Microsoft ABIs");
1499bfef3995SDimitry Andric
15003d1dcd9bSDimitry Andric // Enter the cleanup scopes for virtual bases.
15013d1dcd9bSDimitry Andric EnterDtorCleanups(Dtor, Dtor_Complete);
15023d1dcd9bSDimitry Andric
1503bfef3995SDimitry Andric if (!isTryBody) {
1504b1c73532SDimitry Andric QualType ThisTy = Dtor->getFunctionObjectParameterType();
15050883ccd9SRoman Divacky EmitCXXDestructorCall(Dtor, Dtor_Base, /*ForVirtualBase=*/false,
150622989816SDimitry Andric /*Delegating=*/false, LoadCXXThisAddress(), ThisTy);
15073d1dcd9bSDimitry Andric break;
150879ade4e0SRoman Divacky }
15097442d6faSDimitry Andric
15103d1dcd9bSDimitry Andric // Fallthrough: act like we're in the base variant.
1511e3b55780SDimitry Andric [[fallthrough]];
151279ade4e0SRoman Divacky
15133d1dcd9bSDimitry Andric case Dtor_Base:
1514bfef3995SDimitry Andric assert(Body);
1515bfef3995SDimitry Andric
15163d1dcd9bSDimitry Andric // Enter the cleanup scopes for fields and non-virtual bases.
15173d1dcd9bSDimitry Andric EnterDtorCleanups(Dtor, Dtor_Base);
15183d1dcd9bSDimitry Andric
15193d1dcd9bSDimitry Andric // Initialize the vtable pointers before entering the body.
152045b53394SDimitry Andric if (!CanSkipVTablePointerInitialization(*this, Dtor)) {
152148675466SDimitry Andric // Insert the llvm.launder.invariant.group intrinsic before initializing
152245b53394SDimitry Andric // the vptrs to cancel any previous assumptions we might have made.
152345b53394SDimitry Andric if (CGM.getCodeGenOpts().StrictVTablePointers &&
152445b53394SDimitry Andric CGM.getCodeGenOpts().OptimizationLevel > 0)
152548675466SDimitry Andric CXXThisValue = Builder.CreateLaunderInvariantGroup(LoadCXXThis());
15263d1dcd9bSDimitry Andric InitializeVTablePointers(Dtor->getParent());
152745b53394SDimitry Andric }
15283d1dcd9bSDimitry Andric
15293d1dcd9bSDimitry Andric if (isTryBody)
153079ade4e0SRoman Divacky EmitStmt(cast<CXXTryStmt>(Body)->getTryBlock());
153179ade4e0SRoman Divacky else if (Body)
153279ade4e0SRoman Divacky EmitStmt(Body);
153379ade4e0SRoman Divacky else {
153479ade4e0SRoman Divacky assert(Dtor->isImplicit() && "bodyless dtor not implicit");
153579ade4e0SRoman Divacky // nothing to do besides what's in the epilogue
153679ade4e0SRoman Divacky }
1537bca07a45SDimitry Andric // -fapple-kext must inline any call to this dtor into
1538bca07a45SDimitry Andric // the caller's body.
153913cc256eSDimitry Andric if (getLangOpts().AppleKext)
1540809500fcSDimitry Andric CurFn->addFnAttr(llvm::Attribute::AlwaysInline);
154145b53394SDimitry Andric
15423d1dcd9bSDimitry Andric break;
15433d1dcd9bSDimitry Andric }
154479ade4e0SRoman Divacky
15453d1dcd9bSDimitry Andric // Jump out through the epilogue cleanups.
15463d1dcd9bSDimitry Andric DtorEpilogue.ForceCleanup();
154779ade4e0SRoman Divacky
154879ade4e0SRoman Divacky // Exit the try if applicable.
154979ade4e0SRoman Divacky if (isTryBody)
15504ba67500SRoman Divacky ExitCXXTryStmt(*cast<CXXTryStmt>(Body), true);
155179ade4e0SRoman Divacky }
155279ade4e0SRoman Divacky
emitImplicitAssignmentOperatorBody(FunctionArgList & Args)1553809500fcSDimitry Andric void CodeGenFunction::emitImplicitAssignmentOperatorBody(FunctionArgList &Args) {
1554809500fcSDimitry Andric const CXXMethodDecl *AssignOp = cast<CXXMethodDecl>(CurGD.getDecl());
1555809500fcSDimitry Andric const Stmt *RootS = AssignOp->getBody();
1556809500fcSDimitry Andric assert(isa<CompoundStmt>(RootS) &&
1557809500fcSDimitry Andric "Body of an implicit assignment operator should be compound stmt.");
1558809500fcSDimitry Andric const CompoundStmt *RootCS = cast<CompoundStmt>(RootS);
1559809500fcSDimitry Andric
1560809500fcSDimitry Andric LexicalScope Scope(*this, RootCS->getSourceRange());
1561809500fcSDimitry Andric
15622b6b257fSDimitry Andric incrementProfileCounter(RootCS);
1563aca2e42cSDimitry Andric maybeCreateMCDCCondBitmap();
1564809500fcSDimitry Andric AssignmentMemcpyizer AM(*this, AssignOp, Args);
15659f4dbff6SDimitry Andric for (auto *I : RootCS->body())
15669f4dbff6SDimitry Andric AM.emitAssignment(I);
1567809500fcSDimitry Andric AM.finish();
1568809500fcSDimitry Andric }
1569809500fcSDimitry Andric
15703d1dcd9bSDimitry Andric namespace {
LoadThisForDtorDelete(CodeGenFunction & CGF,const CXXDestructorDecl * DD)1571461a67faSDimitry Andric llvm::Value *LoadThisForDtorDelete(CodeGenFunction &CGF,
1572461a67faSDimitry Andric const CXXDestructorDecl *DD) {
1573461a67faSDimitry Andric if (Expr *ThisArg = DD->getOperatorDeleteThisArg())
1574461a67faSDimitry Andric return CGF.EmitScalarExpr(ThisArg);
1575461a67faSDimitry Andric return CGF.LoadCXXThis();
1576461a67faSDimitry Andric }
1577461a67faSDimitry Andric
15783d1dcd9bSDimitry Andric /// Call the operator delete associated with the current destructor.
157945b53394SDimitry Andric struct CallDtorDelete final : EHScopeStack::Cleanup {
CallDtorDelete__anonf1d54d130411::CallDtorDelete15803d1dcd9bSDimitry Andric CallDtorDelete() {}
15813d1dcd9bSDimitry Andric
Emit__anonf1d54d130411::CallDtorDelete15829f4dbff6SDimitry Andric void Emit(CodeGenFunction &CGF, Flags flags) override {
15833d1dcd9bSDimitry Andric const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CGF.CurCodeDecl);
15843d1dcd9bSDimitry Andric const CXXRecordDecl *ClassDecl = Dtor->getParent();
1585461a67faSDimitry Andric CGF.EmitDeleteCall(Dtor->getOperatorDelete(),
1586461a67faSDimitry Andric LoadThisForDtorDelete(CGF, Dtor),
15873d1dcd9bSDimitry Andric CGF.getContext().getTagDeclType(ClassDecl));
15883d1dcd9bSDimitry Andric }
15893d1dcd9bSDimitry Andric };
15903d1dcd9bSDimitry Andric
EmitConditionalDtorDeleteCall(CodeGenFunction & CGF,llvm::Value * ShouldDeleteCondition,bool ReturnAfterDelete)1591461a67faSDimitry Andric void EmitConditionalDtorDeleteCall(CodeGenFunction &CGF,
1592461a67faSDimitry Andric llvm::Value *ShouldDeleteCondition,
1593461a67faSDimitry Andric bool ReturnAfterDelete) {
1594461a67faSDimitry Andric llvm::BasicBlock *callDeleteBB = CGF.createBasicBlock("dtor.call_delete");
1595461a67faSDimitry Andric llvm::BasicBlock *continueBB = CGF.createBasicBlock("dtor.continue");
1596461a67faSDimitry Andric llvm::Value *ShouldCallDelete
1597461a67faSDimitry Andric = CGF.Builder.CreateIsNull(ShouldDeleteCondition);
1598461a67faSDimitry Andric CGF.Builder.CreateCondBr(ShouldCallDelete, continueBB, callDeleteBB);
1599461a67faSDimitry Andric
1600461a67faSDimitry Andric CGF.EmitBlock(callDeleteBB);
1601461a67faSDimitry Andric const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CGF.CurCodeDecl);
1602461a67faSDimitry Andric const CXXRecordDecl *ClassDecl = Dtor->getParent();
1603461a67faSDimitry Andric CGF.EmitDeleteCall(Dtor->getOperatorDelete(),
1604461a67faSDimitry Andric LoadThisForDtorDelete(CGF, Dtor),
1605461a67faSDimitry Andric CGF.getContext().getTagDeclType(ClassDecl));
1606461a67faSDimitry Andric assert(Dtor->getOperatorDelete()->isDestroyingOperatorDelete() ==
1607461a67faSDimitry Andric ReturnAfterDelete &&
1608461a67faSDimitry Andric "unexpected value for ReturnAfterDelete");
1609461a67faSDimitry Andric if (ReturnAfterDelete)
1610461a67faSDimitry Andric CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
1611461a67faSDimitry Andric else
1612461a67faSDimitry Andric CGF.Builder.CreateBr(continueBB);
1613461a67faSDimitry Andric
1614461a67faSDimitry Andric CGF.EmitBlock(continueBB);
1615461a67faSDimitry Andric }
1616461a67faSDimitry Andric
161745b53394SDimitry Andric struct CallDtorDeleteConditional final : EHScopeStack::Cleanup {
1618809500fcSDimitry Andric llvm::Value *ShouldDeleteCondition;
16192b6b257fSDimitry Andric
1620809500fcSDimitry Andric public:
CallDtorDeleteConditional__anonf1d54d130411::CallDtorDeleteConditional1621809500fcSDimitry Andric CallDtorDeleteConditional(llvm::Value *ShouldDeleteCondition)
1622809500fcSDimitry Andric : ShouldDeleteCondition(ShouldDeleteCondition) {
16239f4dbff6SDimitry Andric assert(ShouldDeleteCondition != nullptr);
1624809500fcSDimitry Andric }
1625809500fcSDimitry Andric
Emit__anonf1d54d130411::CallDtorDeleteConditional16269f4dbff6SDimitry Andric void Emit(CodeGenFunction &CGF, Flags flags) override {
1627461a67faSDimitry Andric EmitConditionalDtorDeleteCall(CGF, ShouldDeleteCondition,
1628461a67faSDimitry Andric /*ReturnAfterDelete*/false);
1629809500fcSDimitry Andric }
1630809500fcSDimitry Andric };
1631809500fcSDimitry Andric
163245b53394SDimitry Andric class DestroyField final : public EHScopeStack::Cleanup {
1633180abc3dSDimitry Andric const FieldDecl *field;
1634dbe13110SDimitry Andric CodeGenFunction::Destroyer *destroyer;
1635180abc3dSDimitry Andric bool useEHCleanupForArray;
16363d1dcd9bSDimitry Andric
1637180abc3dSDimitry Andric public:
DestroyField(const FieldDecl * field,CodeGenFunction::Destroyer * destroyer,bool useEHCleanupForArray)1638180abc3dSDimitry Andric DestroyField(const FieldDecl *field, CodeGenFunction::Destroyer *destroyer,
1639180abc3dSDimitry Andric bool useEHCleanupForArray)
1640dbe13110SDimitry Andric : field(field), destroyer(destroyer),
1641180abc3dSDimitry Andric useEHCleanupForArray(useEHCleanupForArray) {}
16423d1dcd9bSDimitry Andric
Emit(CodeGenFunction & CGF,Flags flags)16439f4dbff6SDimitry Andric void Emit(CodeGenFunction &CGF, Flags flags) override {
1644180abc3dSDimitry Andric // Find the address of the field.
164545b53394SDimitry Andric Address thisValue = CGF.LoadCXXThisAddress();
16466b9a6e39SDimitry Andric QualType RecordTy = CGF.getContext().getTagDeclType(field->getParent());
16476b9a6e39SDimitry Andric LValue ThisLV = CGF.MakeAddrLValue(thisValue, RecordTy);
16486b9a6e39SDimitry Andric LValue LV = CGF.EmitLValueForField(ThisLV, field);
1649180abc3dSDimitry Andric assert(LV.isSimple());
16503d1dcd9bSDimitry Andric
1651ac9a064cSDimitry Andric CGF.emitDestroy(LV.getAddress(), field->getType(), destroyer,
1652180abc3dSDimitry Andric flags.isForNormalCleanup() && useEHCleanupForArray);
16533d1dcd9bSDimitry Andric }
16543d1dcd9bSDimitry Andric };
165545b53394SDimitry Andric
1656e3b55780SDimitry Andric class DeclAsInlineDebugLocation {
1657e3b55780SDimitry Andric CGDebugInfo *DI;
1658e3b55780SDimitry Andric llvm::MDNode *InlinedAt;
1659e3b55780SDimitry Andric std::optional<ApplyDebugLocation> Location;
1660e3b55780SDimitry Andric
1661e3b55780SDimitry Andric public:
DeclAsInlineDebugLocation(CodeGenFunction & CGF,const NamedDecl & Decl)1662e3b55780SDimitry Andric DeclAsInlineDebugLocation(CodeGenFunction &CGF, const NamedDecl &Decl)
1663e3b55780SDimitry Andric : DI(CGF.getDebugInfo()) {
1664e3b55780SDimitry Andric if (!DI)
1665e3b55780SDimitry Andric return;
1666e3b55780SDimitry Andric InlinedAt = DI->getInlinedAt();
1667e3b55780SDimitry Andric DI->setInlinedAt(CGF.Builder.getCurrentDebugLocation());
1668e3b55780SDimitry Andric Location.emplace(CGF, Decl.getLocation());
1669e3b55780SDimitry Andric }
1670e3b55780SDimitry Andric
~DeclAsInlineDebugLocation()1671e3b55780SDimitry Andric ~DeclAsInlineDebugLocation() {
1672e3b55780SDimitry Andric if (!DI)
1673e3b55780SDimitry Andric return;
1674e3b55780SDimitry Andric Location.reset();
1675e3b55780SDimitry Andric DI->setInlinedAt(InlinedAt);
1676e3b55780SDimitry Andric }
1677e3b55780SDimitry Andric };
1678e3b55780SDimitry Andric
EmitSanitizerDtorCallback(CodeGenFunction & CGF,StringRef Name,llvm::Value * Ptr,std::optional<CharUnits::QuantityType> PoisonSize={})1679e3b55780SDimitry Andric static void EmitSanitizerDtorCallback(
1680e3b55780SDimitry Andric CodeGenFunction &CGF, StringRef Name, llvm::Value *Ptr,
1681e3b55780SDimitry Andric std::optional<CharUnits::QuantityType> PoisonSize = {}) {
1682461a67faSDimitry Andric CodeGenFunction::SanitizerScope SanScope(&CGF);
168345b53394SDimitry Andric // Pass in void pointer and size of region as arguments to runtime
168445b53394SDimitry Andric // function
1685b1c73532SDimitry Andric SmallVector<llvm::Value *, 2> Args = {Ptr};
1686e3b55780SDimitry Andric SmallVector<llvm::Type *, 2> ArgTypes = {CGF.VoidPtrTy};
168745b53394SDimitry Andric
1688e3b55780SDimitry Andric if (PoisonSize.has_value()) {
1689e3b55780SDimitry Andric Args.emplace_back(llvm::ConstantInt::get(CGF.SizeTy, *PoisonSize));
1690e3b55780SDimitry Andric ArgTypes.emplace_back(CGF.SizeTy);
1691e3b55780SDimitry Andric }
169245b53394SDimitry Andric
169345b53394SDimitry Andric llvm::FunctionType *FnType =
169445b53394SDimitry Andric llvm::FunctionType::get(CGF.VoidTy, ArgTypes, false);
1695e3b55780SDimitry Andric llvm::FunctionCallee Fn = CGF.CGM.CreateRuntimeFunction(FnType, Name);
1696e3b55780SDimitry Andric
169745b53394SDimitry Andric CGF.EmitNounwindRuntimeCall(Fn, Args);
16983d1dcd9bSDimitry Andric }
16993d1dcd9bSDimitry Andric
1700e3b55780SDimitry Andric static void
EmitSanitizerDtorFieldsCallback(CodeGenFunction & CGF,llvm::Value * Ptr,CharUnits::QuantityType PoisonSize)1701e3b55780SDimitry Andric EmitSanitizerDtorFieldsCallback(CodeGenFunction &CGF, llvm::Value *Ptr,
1702e3b55780SDimitry Andric CharUnits::QuantityType PoisonSize) {
1703e3b55780SDimitry Andric EmitSanitizerDtorCallback(CGF, "__sanitizer_dtor_callback_fields", Ptr,
1704e3b55780SDimitry Andric PoisonSize);
1705e3b55780SDimitry Andric }
1706e3b55780SDimitry Andric
1707145449b1SDimitry Andric /// Poison base class with a trivial destructor.
1708145449b1SDimitry Andric struct SanitizeDtorTrivialBase final : EHScopeStack::Cleanup {
1709145449b1SDimitry Andric const CXXRecordDecl *BaseClass;
1710145449b1SDimitry Andric bool BaseIsVirtual;
SanitizeDtorTrivialBase__anonf1d54d130411::SanitizeDtorTrivialBase1711145449b1SDimitry Andric SanitizeDtorTrivialBase(const CXXRecordDecl *Base, bool BaseIsVirtual)
1712145449b1SDimitry Andric : BaseClass(Base), BaseIsVirtual(BaseIsVirtual) {}
1713145449b1SDimitry Andric
Emit__anonf1d54d130411::SanitizeDtorTrivialBase1714145449b1SDimitry Andric void Emit(CodeGenFunction &CGF, Flags flags) override {
1715145449b1SDimitry Andric const CXXRecordDecl *DerivedClass =
1716145449b1SDimitry Andric cast<CXXMethodDecl>(CGF.CurCodeDecl)->getParent();
1717145449b1SDimitry Andric
1718145449b1SDimitry Andric Address Addr = CGF.GetAddressOfDirectBaseInCompleteClass(
1719145449b1SDimitry Andric CGF.LoadCXXThisAddress(), DerivedClass, BaseClass, BaseIsVirtual);
1720145449b1SDimitry Andric
1721145449b1SDimitry Andric const ASTRecordLayout &BaseLayout =
1722145449b1SDimitry Andric CGF.getContext().getASTRecordLayout(BaseClass);
1723145449b1SDimitry Andric CharUnits BaseSize = BaseLayout.getSize();
1724145449b1SDimitry Andric
1725145449b1SDimitry Andric if (!BaseSize.isPositive())
1726145449b1SDimitry Andric return;
1727145449b1SDimitry Andric
1728e3b55780SDimitry Andric // Use the base class declaration location as inline DebugLocation. All
1729e3b55780SDimitry Andric // fields of the class are destroyed.
1730e3b55780SDimitry Andric DeclAsInlineDebugLocation InlineHere(CGF, *BaseClass);
1731ac9a064cSDimitry Andric EmitSanitizerDtorFieldsCallback(CGF, Addr.emitRawPointer(CGF),
1732e3b55780SDimitry Andric BaseSize.getQuantity());
1733145449b1SDimitry Andric
1734145449b1SDimitry Andric // Prevent the current stack frame from disappearing from the stack trace.
1735145449b1SDimitry Andric CGF.CurFn->addFnAttr("disable-tail-calls", "true");
1736145449b1SDimitry Andric }
1737145449b1SDimitry Andric };
1738145449b1SDimitry Andric
1739145449b1SDimitry Andric class SanitizeDtorFieldRange final : public EHScopeStack::Cleanup {
174045b53394SDimitry Andric const CXXDestructorDecl *Dtor;
1741145449b1SDimitry Andric unsigned StartIndex;
1742145449b1SDimitry Andric unsigned EndIndex;
174345b53394SDimitry Andric
174445b53394SDimitry Andric public:
SanitizeDtorFieldRange(const CXXDestructorDecl * Dtor,unsigned StartIndex,unsigned EndIndex)1745145449b1SDimitry Andric SanitizeDtorFieldRange(const CXXDestructorDecl *Dtor, unsigned StartIndex,
1746145449b1SDimitry Andric unsigned EndIndex)
1747145449b1SDimitry Andric : Dtor(Dtor), StartIndex(StartIndex), EndIndex(EndIndex) {}
174845b53394SDimitry Andric
174945b53394SDimitry Andric // Generate function call for handling object poisoning.
175045b53394SDimitry Andric // Disables tail call elimination, to prevent the current stack frame
175145b53394SDimitry Andric // from disappearing from the stack trace.
Emit(CodeGenFunction & CGF,Flags flags)175245b53394SDimitry Andric void Emit(CodeGenFunction &CGF, Flags flags) override {
1753145449b1SDimitry Andric const ASTContext &Context = CGF.getContext();
175445b53394SDimitry Andric const ASTRecordLayout &Layout =
175545b53394SDimitry Andric Context.getASTRecordLayout(Dtor->getParent());
175645b53394SDimitry Andric
1757145449b1SDimitry Andric // It's a first trivial field so it should be at the begining of a char,
1758b60736ecSDimitry Andric // still round up start offset just in case.
1759145449b1SDimitry Andric CharUnits PoisonStart = Context.toCharUnitsFromBits(
1760145449b1SDimitry Andric Layout.getFieldOffset(StartIndex) + Context.getCharWidth() - 1);
1761b60736ecSDimitry Andric llvm::ConstantInt *OffsetSizePtr =
1762b60736ecSDimitry Andric llvm::ConstantInt::get(CGF.SizeTy, PoisonStart.getQuantity());
176345b53394SDimitry Andric
1764b1c73532SDimitry Andric llvm::Value *OffsetPtr =
1765b1c73532SDimitry Andric CGF.Builder.CreateGEP(CGF.Int8Ty, CGF.LoadCXXThis(), OffsetSizePtr);
176645b53394SDimitry Andric
1767b60736ecSDimitry Andric CharUnits PoisonEnd;
1768145449b1SDimitry Andric if (EndIndex >= Layout.getFieldCount()) {
1769b60736ecSDimitry Andric PoisonEnd = Layout.getNonVirtualSize();
177045b53394SDimitry Andric } else {
1771b60736ecSDimitry Andric PoisonEnd =
1772145449b1SDimitry Andric Context.toCharUnitsFromBits(Layout.getFieldOffset(EndIndex));
177345b53394SDimitry Andric }
1774b60736ecSDimitry Andric CharUnits PoisonSize = PoisonEnd - PoisonStart;
1775b60736ecSDimitry Andric if (!PoisonSize.isPositive())
177645b53394SDimitry Andric return;
177745b53394SDimitry Andric
1778e3b55780SDimitry Andric // Use the top field declaration location as inline DebugLocation.
1779e3b55780SDimitry Andric DeclAsInlineDebugLocation InlineHere(
1780e3b55780SDimitry Andric CGF, **std::next(Dtor->getParent()->field_begin(), StartIndex));
1781e3b55780SDimitry Andric EmitSanitizerDtorFieldsCallback(CGF, OffsetPtr, PoisonSize.getQuantity());
1782145449b1SDimitry Andric
1783145449b1SDimitry Andric // Prevent the current stack frame from disappearing from the stack trace.
1784145449b1SDimitry Andric CGF.CurFn->addFnAttr("disable-tail-calls", "true");
178545b53394SDimitry Andric }
178645b53394SDimitry Andric };
178745b53394SDimitry Andric
178845b53394SDimitry Andric class SanitizeDtorVTable final : public EHScopeStack::Cleanup {
178945b53394SDimitry Andric const CXXDestructorDecl *Dtor;
179045b53394SDimitry Andric
179145b53394SDimitry Andric public:
SanitizeDtorVTable(const CXXDestructorDecl * Dtor)179245b53394SDimitry Andric SanitizeDtorVTable(const CXXDestructorDecl *Dtor) : Dtor(Dtor) {}
179345b53394SDimitry Andric
179445b53394SDimitry Andric // Generate function call for handling vtable pointer poisoning.
Emit(CodeGenFunction & CGF,Flags flags)179545b53394SDimitry Andric void Emit(CodeGenFunction &CGF, Flags flags) override {
179645b53394SDimitry Andric assert(Dtor->getParent()->isDynamicClass());
179745b53394SDimitry Andric (void)Dtor;
179845b53394SDimitry Andric // Poison vtable and vtable ptr if they exist for this class.
179945b53394SDimitry Andric llvm::Value *VTablePtr = CGF.LoadCXXThis();
180045b53394SDimitry Andric
180145b53394SDimitry Andric // Pass in void pointer and size of region as arguments to runtime
180245b53394SDimitry Andric // function
1803e3b55780SDimitry Andric EmitSanitizerDtorCallback(CGF, "__sanitizer_dtor_callback_vptr",
1804e3b55780SDimitry Andric VTablePtr);
180545b53394SDimitry Andric }
180645b53394SDimitry Andric };
1807145449b1SDimitry Andric
1808145449b1SDimitry Andric class SanitizeDtorCleanupBuilder {
1809145449b1SDimitry Andric ASTContext &Context;
1810145449b1SDimitry Andric EHScopeStack &EHStack;
1811145449b1SDimitry Andric const CXXDestructorDecl *DD;
1812e3b55780SDimitry Andric std::optional<unsigned> StartIndex;
1813145449b1SDimitry Andric
1814145449b1SDimitry Andric public:
SanitizeDtorCleanupBuilder(ASTContext & Context,EHScopeStack & EHStack,const CXXDestructorDecl * DD)1815145449b1SDimitry Andric SanitizeDtorCleanupBuilder(ASTContext &Context, EHScopeStack &EHStack,
1816145449b1SDimitry Andric const CXXDestructorDecl *DD)
1817e3b55780SDimitry Andric : Context(Context), EHStack(EHStack), DD(DD), StartIndex(std::nullopt) {}
PushCleanupForField(const FieldDecl * Field)1818145449b1SDimitry Andric void PushCleanupForField(const FieldDecl *Field) {
1819ac9a064cSDimitry Andric if (isEmptyFieldForLayout(Context, Field))
1820145449b1SDimitry Andric return;
1821145449b1SDimitry Andric unsigned FieldIndex = Field->getFieldIndex();
1822145449b1SDimitry Andric if (FieldHasTrivialDestructorBody(Context, Field)) {
1823145449b1SDimitry Andric if (!StartIndex)
1824145449b1SDimitry Andric StartIndex = FieldIndex;
1825145449b1SDimitry Andric } else if (StartIndex) {
1826e3b55780SDimitry Andric EHStack.pushCleanup<SanitizeDtorFieldRange>(NormalAndEHCleanup, DD,
1827e3b55780SDimitry Andric *StartIndex, FieldIndex);
1828e3b55780SDimitry Andric StartIndex = std::nullopt;
1829145449b1SDimitry Andric }
1830145449b1SDimitry Andric }
End()1831145449b1SDimitry Andric void End() {
1832145449b1SDimitry Andric if (StartIndex)
1833145449b1SDimitry Andric EHStack.pushCleanup<SanitizeDtorFieldRange>(NormalAndEHCleanup, DD,
1834e3b55780SDimitry Andric *StartIndex, -1);
1835145449b1SDimitry Andric }
1836145449b1SDimitry Andric };
183745b53394SDimitry Andric } // end anonymous namespace
183845b53394SDimitry Andric
183948675466SDimitry Andric /// Emit all code that comes at the end of class's
1840abe15e55SRoman Divacky /// destructor. This is to call destructors on members and base classes
1841abe15e55SRoman Divacky /// in reverse order of their construction.
1842461a67faSDimitry Andric ///
1843461a67faSDimitry Andric /// For a deleting destructor, this also handles the case where a destroying
1844461a67faSDimitry Andric /// operator delete completely overrides the definition.
EnterDtorCleanups(const CXXDestructorDecl * DD,CXXDtorType DtorType)18453d1dcd9bSDimitry Andric void CodeGenFunction::EnterDtorCleanups(const CXXDestructorDecl *DD,
1846abe15e55SRoman Divacky CXXDtorType DtorType) {
18479f4dbff6SDimitry Andric assert((!DD->isTrivial() || DD->hasAttr<DLLExportAttr>()) &&
18489f4dbff6SDimitry Andric "Should not emit dtor epilogue for non-exported trivial dtor!");
1849abe15e55SRoman Divacky
18503d1dcd9bSDimitry Andric // The deleting-destructor phase just needs to call the appropriate
18513d1dcd9bSDimitry Andric // operator delete that Sema picked up.
185279ade4e0SRoman Divacky if (DtorType == Dtor_Deleting) {
185379ade4e0SRoman Divacky assert(DD->getOperatorDelete() &&
18549f4dbff6SDimitry Andric "operator delete missing - EnterDtorCleanups");
1855809500fcSDimitry Andric if (CXXStructorImplicitParamValue) {
1856809500fcSDimitry Andric // If there is an implicit param to the deleting dtor, it's a boolean
1857461a67faSDimitry Andric // telling whether this is a deleting destructor.
1858461a67faSDimitry Andric if (DD->getOperatorDelete()->isDestroyingOperatorDelete())
1859461a67faSDimitry Andric EmitConditionalDtorDeleteCall(*this, CXXStructorImplicitParamValue,
1860461a67faSDimitry Andric /*ReturnAfterDelete*/true);
1861461a67faSDimitry Andric else
1862809500fcSDimitry Andric EHStack.pushCleanup<CallDtorDeleteConditional>(
1863809500fcSDimitry Andric NormalAndEHCleanup, CXXStructorImplicitParamValue);
1864809500fcSDimitry Andric } else {
1865461a67faSDimitry Andric if (DD->getOperatorDelete()->isDestroyingOperatorDelete()) {
1866461a67faSDimitry Andric const CXXRecordDecl *ClassDecl = DD->getParent();
1867461a67faSDimitry Andric EmitDeleteCall(DD->getOperatorDelete(),
1868461a67faSDimitry Andric LoadThisForDtorDelete(*this, DD),
1869461a67faSDimitry Andric getContext().getTagDeclType(ClassDecl));
1870461a67faSDimitry Andric EmitBranchThroughCleanup(ReturnBlock);
1871461a67faSDimitry Andric } else {
18723d1dcd9bSDimitry Andric EHStack.pushCleanup<CallDtorDelete>(NormalAndEHCleanup);
1873809500fcSDimitry Andric }
1874461a67faSDimitry Andric }
187579ade4e0SRoman Divacky return;
187679ade4e0SRoman Divacky }
187779ade4e0SRoman Divacky
18783d1dcd9bSDimitry Andric const CXXRecordDecl *ClassDecl = DD->getParent();
18793d1dcd9bSDimitry Andric
188036981b17SDimitry Andric // Unions have no bases and do not call field destructors.
188136981b17SDimitry Andric if (ClassDecl->isUnion())
188236981b17SDimitry Andric return;
188336981b17SDimitry Andric
18843d1dcd9bSDimitry Andric // The complete-destructor phase just destructs all the virtual bases.
188579ade4e0SRoman Divacky if (DtorType == Dtor_Complete) {
188645b53394SDimitry Andric // Poison the vtable pointer such that access after the base
188745b53394SDimitry Andric // and member destructors are invoked is invalid.
188845b53394SDimitry Andric if (CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor &&
188945b53394SDimitry Andric SanOpts.has(SanitizerKind::Memory) && ClassDecl->getNumVBases() &&
189045b53394SDimitry Andric ClassDecl->isPolymorphic())
189145b53394SDimitry Andric EHStack.pushCleanup<SanitizeDtorVTable>(NormalAndEHCleanup, DD);
18923d1dcd9bSDimitry Andric
18933d1dcd9bSDimitry Andric // We push them in the forward order so that they'll be popped in
18943d1dcd9bSDimitry Andric // the reverse order.
18959f4dbff6SDimitry Andric for (const auto &Base : ClassDecl->vbases()) {
1896519fc96cSDimitry Andric auto *BaseClassDecl =
1897519fc96cSDimitry Andric cast<CXXRecordDecl>(Base.getType()->castAs<RecordType>()->getDecl());
189879ade4e0SRoman Divacky
1899145449b1SDimitry Andric if (BaseClassDecl->hasTrivialDestructor()) {
1900145449b1SDimitry Andric // Under SanitizeMemoryUseAfterDtor, poison the trivial base class
1901145449b1SDimitry Andric // memory. For non-trival base classes the same is done in the class
1902145449b1SDimitry Andric // destructor.
1903145449b1SDimitry Andric if (CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor &&
1904145449b1SDimitry Andric SanOpts.has(SanitizerKind::Memory) && !BaseClassDecl->isEmpty())
1905145449b1SDimitry Andric EHStack.pushCleanup<SanitizeDtorTrivialBase>(NormalAndEHCleanup,
19063d1dcd9bSDimitry Andric BaseClassDecl,
19073d1dcd9bSDimitry Andric /*BaseIsVirtual*/ true);
1908145449b1SDimitry Andric } else {
1909145449b1SDimitry Andric EHStack.pushCleanup<CallBaseDtor>(NormalAndEHCleanup, BaseClassDecl,
1910145449b1SDimitry Andric /*BaseIsVirtual*/ true);
1911145449b1SDimitry Andric }
191279ade4e0SRoman Divacky }
19133d1dcd9bSDimitry Andric
191479ade4e0SRoman Divacky return;
191579ade4e0SRoman Divacky }
191679ade4e0SRoman Divacky
191779ade4e0SRoman Divacky assert(DtorType == Dtor_Base);
191845b53394SDimitry Andric // Poison the vtable pointer if it has no virtual bases, but inherits
191945b53394SDimitry Andric // virtual functions.
192045b53394SDimitry Andric if (CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor &&
192145b53394SDimitry Andric SanOpts.has(SanitizerKind::Memory) && !ClassDecl->getNumVBases() &&
192245b53394SDimitry Andric ClassDecl->isPolymorphic())
192345b53394SDimitry Andric EHStack.pushCleanup<SanitizeDtorVTable>(NormalAndEHCleanup, DD);
192479ade4e0SRoman Divacky
19253d1dcd9bSDimitry Andric // Destroy non-virtual bases.
19269f4dbff6SDimitry Andric for (const auto &Base : ClassDecl->bases()) {
19273d1dcd9bSDimitry Andric // Ignore virtual bases.
19283d1dcd9bSDimitry Andric if (Base.isVirtual())
19293d1dcd9bSDimitry Andric continue;
19303d1dcd9bSDimitry Andric
19313d1dcd9bSDimitry Andric CXXRecordDecl *BaseClassDecl = Base.getType()->getAsCXXRecordDecl();
19323d1dcd9bSDimitry Andric
1933145449b1SDimitry Andric if (BaseClassDecl->hasTrivialDestructor()) {
1934145449b1SDimitry Andric if (CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor &&
1935145449b1SDimitry Andric SanOpts.has(SanitizerKind::Memory) && !BaseClassDecl->isEmpty())
1936145449b1SDimitry Andric EHStack.pushCleanup<SanitizeDtorTrivialBase>(NormalAndEHCleanup,
19373d1dcd9bSDimitry Andric BaseClassDecl,
19383d1dcd9bSDimitry Andric /*BaseIsVirtual*/ false);
1939145449b1SDimitry Andric } else {
1940145449b1SDimitry Andric EHStack.pushCleanup<CallBaseDtor>(NormalAndEHCleanup, BaseClassDecl,
1941145449b1SDimitry Andric /*BaseIsVirtual*/ false);
1942145449b1SDimitry Andric }
19433d1dcd9bSDimitry Andric }
19443d1dcd9bSDimitry Andric
194545b53394SDimitry Andric // Poison fields such that access after their destructors are
194645b53394SDimitry Andric // invoked, and before the base class destructor runs, is invalid.
1947145449b1SDimitry Andric bool SanitizeFields = CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor &&
1948145449b1SDimitry Andric SanOpts.has(SanitizerKind::Memory);
1949145449b1SDimitry Andric SanitizeDtorCleanupBuilder SanitizeBuilder(getContext(), EHStack, DD);
195045b53394SDimitry Andric
19513d1dcd9bSDimitry Andric // Destroy direct fields.
19529f4dbff6SDimitry Andric for (const auto *Field : ClassDecl->fields()) {
1953145449b1SDimitry Andric if (SanitizeFields)
1954145449b1SDimitry Andric SanitizeBuilder.PushCleanupForField(Field);
1955145449b1SDimitry Andric
19569f4dbff6SDimitry Andric QualType type = Field->getType();
1957180abc3dSDimitry Andric QualType::DestructionKind dtorKind = type.isDestructedType();
1958145449b1SDimitry Andric if (!dtorKind)
1959145449b1SDimitry Andric continue;
1960abe15e55SRoman Divacky
1961dbe13110SDimitry Andric // Anonymous union members do not have their destructors called.
1962dbe13110SDimitry Andric const RecordType *RT = type->getAsUnionType();
1963145449b1SDimitry Andric if (RT && RT->getDecl()->isAnonymousStructOrUnion())
1964145449b1SDimitry Andric continue;
1965dbe13110SDimitry Andric
1966180abc3dSDimitry Andric CleanupKind cleanupKind = getCleanupKind(dtorKind);
1967145449b1SDimitry Andric EHStack.pushCleanup<DestroyField>(
1968145449b1SDimitry Andric cleanupKind, Field, getDestroyer(dtorKind), cleanupKind & EHCleanup);
1969abe15e55SRoman Divacky }
1970145449b1SDimitry Andric
1971145449b1SDimitry Andric if (SanitizeFields)
1972145449b1SDimitry Andric SanitizeBuilder.End();
1973abe15e55SRoman Divacky }
1974ee791ddeSRoman Divacky
1975180abc3dSDimitry Andric /// EmitCXXAggrConstructorCall - Emit a loop to call a particular
1976180abc3dSDimitry Andric /// constructor for each of several members of an array.
19773d1dcd9bSDimitry Andric ///
1978180abc3dSDimitry Andric /// \param ctor the constructor to call for each element
1979180abc3dSDimitry Andric /// \param arrayType the type of the array to initialize
1980180abc3dSDimitry Andric /// \param arrayBegin an arrayType*
1981180abc3dSDimitry Andric /// \param zeroInitialize true if each element should be
1982180abc3dSDimitry Andric /// zero-initialized before it is constructed
EmitCXXAggrConstructorCall(const CXXConstructorDecl * ctor,const ArrayType * arrayType,Address arrayBegin,const CXXConstructExpr * E,bool NewPointerIsChecked,bool zeroInitialize)198306d4ba38SDimitry Andric void CodeGenFunction::EmitCXXAggrConstructorCall(
19842b6b257fSDimitry Andric const CXXConstructorDecl *ctor, const ArrayType *arrayType,
1985c7e70c43SDimitry Andric Address arrayBegin, const CXXConstructExpr *E, bool NewPointerIsChecked,
1986c7e70c43SDimitry Andric bool zeroInitialize) {
1987180abc3dSDimitry Andric QualType elementType;
1988180abc3dSDimitry Andric llvm::Value *numElements =
1989180abc3dSDimitry Andric emitArrayLength(arrayType, elementType, arrayBegin);
1990ee791ddeSRoman Divacky
1991c7e70c43SDimitry Andric EmitCXXAggrConstructorCall(ctor, numElements, arrayBegin, E,
1992c7e70c43SDimitry Andric NewPointerIsChecked, zeroInitialize);
1993ee791ddeSRoman Divacky }
1994ee791ddeSRoman Divacky
1995180abc3dSDimitry Andric /// EmitCXXAggrConstructorCall - Emit a loop to call a particular
1996180abc3dSDimitry Andric /// constructor for each of several members of an array.
1997180abc3dSDimitry Andric ///
1998180abc3dSDimitry Andric /// \param ctor the constructor to call for each element
1999180abc3dSDimitry Andric /// \param numElements the number of elements in the array;
2000180abc3dSDimitry Andric /// may be zero
200145b53394SDimitry Andric /// \param arrayBase a T*, where T is the type constructed by ctor
2002180abc3dSDimitry Andric /// \param zeroInitialize true if each element should be
2003180abc3dSDimitry Andric /// zero-initialized before it is constructed
EmitCXXAggrConstructorCall(const CXXConstructorDecl * ctor,llvm::Value * numElements,Address arrayBase,const CXXConstructExpr * E,bool NewPointerIsChecked,bool zeroInitialize)200406d4ba38SDimitry Andric void CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor,
2005180abc3dSDimitry Andric llvm::Value *numElements,
200645b53394SDimitry Andric Address arrayBase,
200706d4ba38SDimitry Andric const CXXConstructExpr *E,
2008c7e70c43SDimitry Andric bool NewPointerIsChecked,
2009180abc3dSDimitry Andric bool zeroInitialize) {
2010180abc3dSDimitry Andric // It's legal for numElements to be zero. This can happen both
2011180abc3dSDimitry Andric // dynamically, because x can be zero in 'new A[x]', and statically,
2012180abc3dSDimitry Andric // because of GCC extensions that permit zero-length arrays. There
2013180abc3dSDimitry Andric // are probably legitimate places where we could assume that this
2014180abc3dSDimitry Andric // doesn't happen, but it's not clear that it's worth it.
20159f4dbff6SDimitry Andric llvm::BranchInst *zeroCheckBranch = nullptr;
2016ee791ddeSRoman Divacky
2017180abc3dSDimitry Andric // Optimize for a constant count.
2018180abc3dSDimitry Andric llvm::ConstantInt *constantCount
2019180abc3dSDimitry Andric = dyn_cast<llvm::ConstantInt>(numElements);
2020180abc3dSDimitry Andric if (constantCount) {
2021180abc3dSDimitry Andric // Just skip out if the constant count is zero.
2022180abc3dSDimitry Andric if (constantCount->isZero()) return;
2023ee791ddeSRoman Divacky
2024180abc3dSDimitry Andric // Otherwise, emit the check.
2025180abc3dSDimitry Andric } else {
2026180abc3dSDimitry Andric llvm::BasicBlock *loopBB = createBasicBlock("new.ctorloop");
2027180abc3dSDimitry Andric llvm::Value *iszero = Builder.CreateIsNull(numElements, "isempty");
2028180abc3dSDimitry Andric zeroCheckBranch = Builder.CreateCondBr(iszero, loopBB, loopBB);
2029180abc3dSDimitry Andric EmitBlock(loopBB);
2030180abc3dSDimitry Andric }
2031ee791ddeSRoman Divacky
2032180abc3dSDimitry Andric // Find the end of the array.
2033344a3780SDimitry Andric llvm::Type *elementType = arrayBase.getElementType();
2034ac9a064cSDimitry Andric llvm::Value *arrayBegin = arrayBase.emitRawPointer(*this);
2035344a3780SDimitry Andric llvm::Value *arrayEnd = Builder.CreateInBoundsGEP(
2036344a3780SDimitry Andric elementType, arrayBegin, numElements, "arrayctor.end");
2037ee791ddeSRoman Divacky
2038180abc3dSDimitry Andric // Enter the loop, setting up a phi for the current location to initialize.
2039180abc3dSDimitry Andric llvm::BasicBlock *entryBB = Builder.GetInsertBlock();
2040180abc3dSDimitry Andric llvm::BasicBlock *loopBB = createBasicBlock("arrayctor.loop");
2041180abc3dSDimitry Andric EmitBlock(loopBB);
2042180abc3dSDimitry Andric llvm::PHINode *cur = Builder.CreatePHI(arrayBegin->getType(), 2,
2043180abc3dSDimitry Andric "arrayctor.cur");
2044180abc3dSDimitry Andric cur->addIncoming(arrayBegin, entryBB);
2045ee791ddeSRoman Divacky
2046ee791ddeSRoman Divacky // Inside the loop body, emit the constructor call on the array element.
2047180abc3dSDimitry Andric
204845b53394SDimitry Andric // The alignment of the base, adjusted by the size of a single element,
204945b53394SDimitry Andric // provides a conservative estimate of the alignment of every element.
205045b53394SDimitry Andric // (This assumes we never start tracking offsetted alignments.)
205145b53394SDimitry Andric //
205245b53394SDimitry Andric // Note that these are complete objects and so we don't need to
205345b53394SDimitry Andric // use the non-virtual size or alignment.
2054180abc3dSDimitry Andric QualType type = getContext().getTypeDeclType(ctor->getParent());
205545b53394SDimitry Andric CharUnits eltAlignment =
205645b53394SDimitry Andric arrayBase.getAlignment()
205745b53394SDimitry Andric .alignmentOfArrayElement(getContext().getTypeSizeInChars(type));
20586f8fc217SDimitry Andric Address curAddr = Address(cur, elementType, eltAlignment);
2059ee791ddeSRoman Divacky
20603d1dcd9bSDimitry Andric // Zero initialize the storage, if requested.
2061180abc3dSDimitry Andric if (zeroInitialize)
206245b53394SDimitry Andric EmitNullInitialization(curAddr, type);
20633d1dcd9bSDimitry Andric
2064ee791ddeSRoman Divacky // C++ [class.temporary]p4:
2065ee791ddeSRoman Divacky // There are two contexts in which temporaries are destroyed at a different
2066ee791ddeSRoman Divacky // point than the end of the full-expression. The first context is when a
2067ee791ddeSRoman Divacky // default constructor is called to initialize an element of an array.
2068ee791ddeSRoman Divacky // If the constructor has one or more default arguments, the destruction of
2069ee791ddeSRoman Divacky // every temporary created in a default argument expression is sequenced
2070ee791ddeSRoman Divacky // before the construction of the next array element, if any.
2071ee791ddeSRoman Divacky
207211d2b2d2SRoman Divacky {
20734ba67500SRoman Divacky RunCleanupsScope Scope(*this);
2074ee791ddeSRoman Divacky
2075180abc3dSDimitry Andric // Evaluate the constructor and its arguments in a regular
2076180abc3dSDimitry Andric // partial-destroy cleanup.
2077dbe13110SDimitry Andric if (getLangOpts().Exceptions &&
2078180abc3dSDimitry Andric !ctor->getParent()->hasTrivialDestructor()) {
2079180abc3dSDimitry Andric Destroyer *destroyer = destroyCXXObject;
208045b53394SDimitry Andric pushRegularPartialArrayCleanup(arrayBegin, cur, type, eltAlignment,
208145b53394SDimitry Andric *destroyer);
208211d2b2d2SRoman Divacky }
208322989816SDimitry Andric auto currAVS = AggValueSlot::forAddr(
208422989816SDimitry Andric curAddr, type.getQualifiers(), AggValueSlot::IsDestructed,
208522989816SDimitry Andric AggValueSlot::DoesNotNeedGCBarriers, AggValueSlot::IsNotAliased,
208622989816SDimitry Andric AggValueSlot::DoesNotOverlap, AggValueSlot::IsNotZeroed,
208722989816SDimitry Andric NewPointerIsChecked ? AggValueSlot::IsSanitizerChecked
208822989816SDimitry Andric : AggValueSlot::IsNotSanitizerChecked);
2089180abc3dSDimitry Andric EmitCXXConstructorCall(ctor, Ctor_Complete, /*ForVirtualBase=*/false,
209022989816SDimitry Andric /*Delegating=*/false, currAVS, E);
2091ee791ddeSRoman Divacky }
2092ee791ddeSRoman Divacky
2093180abc3dSDimitry Andric // Go to the next element.
2094344a3780SDimitry Andric llvm::Value *next = Builder.CreateInBoundsGEP(
2095344a3780SDimitry Andric elementType, cur, llvm::ConstantInt::get(SizeTy, 1), "arrayctor.next");
2096180abc3dSDimitry Andric cur->addIncoming(next, Builder.GetInsertBlock());
2097ee791ddeSRoman Divacky
2098180abc3dSDimitry Andric // Check whether that's the end of the loop.
2099180abc3dSDimitry Andric llvm::Value *done = Builder.CreateICmpEQ(next, arrayEnd, "arrayctor.done");
2100180abc3dSDimitry Andric llvm::BasicBlock *contBB = createBasicBlock("arrayctor.cont");
2101180abc3dSDimitry Andric Builder.CreateCondBr(done, contBB, loopBB);
2102180abc3dSDimitry Andric
2103180abc3dSDimitry Andric // Patch the earlier check to skip over the loop.
2104180abc3dSDimitry Andric if (zeroCheckBranch) zeroCheckBranch->setSuccessor(0, contBB);
2105180abc3dSDimitry Andric
2106180abc3dSDimitry Andric EmitBlock(contBB);
2107ee791ddeSRoman Divacky }
2108ee791ddeSRoman Divacky
destroyCXXObject(CodeGenFunction & CGF,Address addr,QualType type)2109180abc3dSDimitry Andric void CodeGenFunction::destroyCXXObject(CodeGenFunction &CGF,
211045b53394SDimitry Andric Address addr,
2111180abc3dSDimitry Andric QualType type) {
2112180abc3dSDimitry Andric const RecordType *rtype = type->castAs<RecordType>();
2113180abc3dSDimitry Andric const CXXRecordDecl *record = cast<CXXRecordDecl>(rtype->getDecl());
2114180abc3dSDimitry Andric const CXXDestructorDecl *dtor = record->getDestructor();
2115180abc3dSDimitry Andric assert(!dtor->isTrivial());
2116180abc3dSDimitry Andric CGF.EmitCXXDestructorCall(dtor, Dtor_Complete, /*for vbase*/ false,
211722989816SDimitry Andric /*Delegating=*/false, addr, type);
2118ee791ddeSRoman Divacky }
2119ee791ddeSRoman Divacky
EmitCXXConstructorCall(const CXXConstructorDecl * D,CXXCtorType Type,bool ForVirtualBase,bool Delegating,AggValueSlot ThisAVS,const CXXConstructExpr * E)212006d4ba38SDimitry Andric void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
212106d4ba38SDimitry Andric CXXCtorType Type,
212206d4ba38SDimitry Andric bool ForVirtualBase,
212322989816SDimitry Andric bool Delegating,
212422989816SDimitry Andric AggValueSlot ThisAVS,
212522989816SDimitry Andric const CXXConstructExpr *E) {
21262b6b257fSDimitry Andric CallArgList Args;
212722989816SDimitry Andric Address This = ThisAVS.getAddress();
212822989816SDimitry Andric LangAS SlotAS = ThisAVS.getQualifiers().getAddressSpace();
2129b1c73532SDimitry Andric LangAS ThisAS = D->getFunctionObjectParameterType().getAddressSpace();
2130ac9a064cSDimitry Andric llvm::Value *ThisPtr =
2131ac9a064cSDimitry Andric getAsNaturalPointerTo(This, D->getThisType()->getPointeeType());
213222989816SDimitry Andric
2133676fbe81SDimitry Andric if (SlotAS != ThisAS) {
2134676fbe81SDimitry Andric unsigned TargetThisAS = getContext().getTargetAddressSpace(ThisAS);
21357fa27ce4SDimitry Andric llvm::Type *NewType =
21367fa27ce4SDimitry Andric llvm::PointerType::get(getLLVMContext(), TargetThisAS);
2137ac9a064cSDimitry Andric ThisPtr = getTargetHooks().performAddrSpaceCast(*this, ThisPtr, ThisAS,
2138ac9a064cSDimitry Andric SlotAS, NewType);
2139676fbe81SDimitry Andric }
214022989816SDimitry Andric
21412b6b257fSDimitry Andric // Push the this ptr.
2142676fbe81SDimitry Andric Args.add(RValue::get(ThisPtr), D->getThisType());
21432b6b257fSDimitry Andric
21442b6b257fSDimitry Andric // If this is a trivial constructor, emit a memcpy now before we lose
21452b6b257fSDimitry Andric // the alignment information on the argument.
21462b6b257fSDimitry Andric // FIXME: It would be better to preserve alignment information into CallArg.
21472b6b257fSDimitry Andric if (isMemcpyEquivalentSpecialMember(D)) {
21482b6b257fSDimitry Andric assert(E->getNumArgs() == 1 && "unexpected argcount for trivial ctor");
21492b6b257fSDimitry Andric
21502b6b257fSDimitry Andric const Expr *Arg = E->getArg(0);
215148675466SDimitry Andric LValue Src = EmitLValue(Arg);
21522b6b257fSDimitry Andric QualType DestTy = getContext().getTypeDeclType(D->getParent());
215348675466SDimitry Andric LValue Dest = MakeAddrLValue(This, DestTy);
215422989816SDimitry Andric EmitAggregateCopyCtor(Dest, Src, ThisAVS.mayOverlap());
21552b6b257fSDimitry Andric return;
21562b6b257fSDimitry Andric }
21572b6b257fSDimitry Andric
21582b6b257fSDimitry Andric // Add the rest of the user-supplied arguments.
21592b6b257fSDimitry Andric const FunctionProtoType *FPT = D->getType()->castAs<FunctionProtoType>();
21607442d6faSDimitry Andric EvaluationOrder Order = E->isListInitialization()
21617442d6faSDimitry Andric ? EvaluationOrder::ForceLeftToRight
21627442d6faSDimitry Andric : EvaluationOrder::Default;
21637442d6faSDimitry Andric EmitCallArgs(Args, FPT, E->arguments(), E->getConstructor(),
21647442d6faSDimitry Andric /*ParamsToSkip*/ 0, Order);
21652b6b257fSDimitry Andric
216648675466SDimitry Andric EmitCXXConstructorCall(D, Type, ForVirtualBase, Delegating, This, Args,
216722989816SDimitry Andric ThisAVS.mayOverlap(), E->getExprLoc(),
216822989816SDimitry Andric ThisAVS.isSanitizerChecked());
21692b6b257fSDimitry Andric }
21702b6b257fSDimitry Andric
canEmitDelegateCallArgs(CodeGenFunction & CGF,const CXXConstructorDecl * Ctor,CXXCtorType Type,CallArgList & Args)21712b6b257fSDimitry Andric static bool canEmitDelegateCallArgs(CodeGenFunction &CGF,
21722b6b257fSDimitry Andric const CXXConstructorDecl *Ctor,
21732b6b257fSDimitry Andric CXXCtorType Type, CallArgList &Args) {
21742b6b257fSDimitry Andric // We can't forward a variadic call.
21752b6b257fSDimitry Andric if (Ctor->isVariadic())
21762b6b257fSDimitry Andric return false;
21772b6b257fSDimitry Andric
21782b6b257fSDimitry Andric if (CGF.getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee()) {
21792b6b257fSDimitry Andric // If the parameters are callee-cleanup, it's not safe to forward.
21802b6b257fSDimitry Andric for (auto *P : Ctor->parameters())
2181519fc96cSDimitry Andric if (P->needsDestruction(CGF.getContext()))
21822b6b257fSDimitry Andric return false;
21832b6b257fSDimitry Andric
21842b6b257fSDimitry Andric // Likewise if they're inalloca.
21852b6b257fSDimitry Andric const CGFunctionInfo &Info =
21867442d6faSDimitry Andric CGF.CGM.getTypes().arrangeCXXConstructorCall(Args, Ctor, Type, 0, 0);
21872b6b257fSDimitry Andric if (Info.usesInAlloca())
21882b6b257fSDimitry Andric return false;
21892b6b257fSDimitry Andric }
21902b6b257fSDimitry Andric
21912b6b257fSDimitry Andric // Anything else should be OK.
21922b6b257fSDimitry Andric return true;
21932b6b257fSDimitry Andric }
21942b6b257fSDimitry Andric
EmitCXXConstructorCall(const CXXConstructorDecl * D,CXXCtorType Type,bool ForVirtualBase,bool Delegating,Address This,CallArgList & Args,AggValueSlot::Overlap_t Overlap,SourceLocation Loc,bool NewPointerIsChecked)21952b6b257fSDimitry Andric void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
21962b6b257fSDimitry Andric CXXCtorType Type,
21972b6b257fSDimitry Andric bool ForVirtualBase,
21982b6b257fSDimitry Andric bool Delegating,
21992b6b257fSDimitry Andric Address This,
220048675466SDimitry Andric CallArgList &Args,
220148675466SDimitry Andric AggValueSlot::Overlap_t Overlap,
2202c7e70c43SDimitry Andric SourceLocation Loc,
2203c7e70c43SDimitry Andric bool NewPointerIsChecked) {
220445b53394SDimitry Andric const CXXRecordDecl *ClassDecl = D->getParent();
220545b53394SDimitry Andric
2206c7e70c43SDimitry Andric if (!NewPointerIsChecked)
2207ac9a064cSDimitry Andric EmitTypeCheck(CodeGenFunction::TCK_ConstructorCall, Loc, This,
2208c7e70c43SDimitry Andric getContext().getRecordType(ClassDecl), CharUnits::Zero());
22099f4dbff6SDimitry Andric
22105e20cdd8SDimitry Andric if (D->isTrivial() && D->isDefaultConstructor()) {
22112b6b257fSDimitry Andric assert(Args.size() == 1 && "trivial default ctor with args");
22125e20cdd8SDimitry Andric return;
22135e20cdd8SDimitry Andric }
22145e20cdd8SDimitry Andric
22155e20cdd8SDimitry Andric // If this is a trivial constructor, just emit what's needed. If this is a
22165e20cdd8SDimitry Andric // union copy constructor, we must emit a memcpy, because the AST does not
22175e20cdd8SDimitry Andric // model that copy.
22185e20cdd8SDimitry Andric if (isMemcpyEquivalentSpecialMember(D)) {
22192b6b257fSDimitry Andric assert(Args.size() == 2 && "unexpected argcount for trivial ctor");
22202b6b257fSDimitry Andric QualType SrcTy = D->getParamDecl(0)->getType().getNonReferenceType();
2221ac9a064cSDimitry Andric Address Src = makeNaturalAddressForPointer(
2222ac9a064cSDimitry Andric Args[1].getRValue(*this).getScalarVal(), SrcTy);
222348675466SDimitry Andric LValue SrcLVal = MakeAddrLValue(Src, SrcTy);
222445b53394SDimitry Andric QualType DestTy = getContext().getTypeDeclType(ClassDecl);
222548675466SDimitry Andric LValue DestLVal = MakeAddrLValue(This, DestTy);
222648675466SDimitry Andric EmitAggregateCopyCtor(DestLVal, SrcLVal, Overlap);
22275e20cdd8SDimitry Andric return;
22285e20cdd8SDimitry Andric }
22295e20cdd8SDimitry Andric
22307442d6faSDimitry Andric bool PassPrototypeArgs = true;
22312b6b257fSDimitry Andric // Check whether we can actually emit the constructor before trying to do so.
22322b6b257fSDimitry Andric if (auto Inherited = D->getInheritedConstructor()) {
22337442d6faSDimitry Andric PassPrototypeArgs = getTypes().inheritingCtorHasParams(Inherited, Type);
22347442d6faSDimitry Andric if (PassPrototypeArgs && !canEmitDelegateCallArgs(*this, D, Type, Args)) {
22352b6b257fSDimitry Andric EmitInlinedInheritingCXXConstructorCall(D, Type, ForVirtualBase,
22362b6b257fSDimitry Andric Delegating, Args);
22372b6b257fSDimitry Andric return;
22382b6b257fSDimitry Andric }
22392b6b257fSDimitry Andric }
22409f4dbff6SDimitry Andric
22419f4dbff6SDimitry Andric // Insert any ABI-specific implicit constructor arguments.
2242cfca06d7SDimitry Andric CGCXXABI::AddedStructorArgCounts ExtraArgs =
22437442d6faSDimitry Andric CGM.getCXXABI().addImplicitConstructorArgs(*this, D, Type, ForVirtualBase,
22447442d6faSDimitry Andric Delegating, Args);
22459f4dbff6SDimitry Andric
22469f4dbff6SDimitry Andric // Emit the call.
224722989816SDimitry Andric llvm::Constant *CalleePtr = CGM.getAddrOfCXXStructor(GlobalDecl(D, Type));
22487442d6faSDimitry Andric const CGFunctionInfo &Info = CGM.getTypes().arrangeCXXConstructorCall(
22497442d6faSDimitry Andric Args, D, Type, ExtraArgs.Prefix, ExtraArgs.Suffix, PassPrototypeArgs);
2250676fbe81SDimitry Andric CGCallee Callee = CGCallee::forDirect(CalleePtr, GlobalDecl(D, Type));
2251344a3780SDimitry Andric EmitCall(Info, Callee, ReturnValueSlot(), Args, nullptr, false, Loc);
225245b53394SDimitry Andric
225345b53394SDimitry Andric // Generate vtable assumptions if we're constructing a complete object
225445b53394SDimitry Andric // with a vtable. We don't do this for base subobjects for two reasons:
225545b53394SDimitry Andric // first, it's incorrect for classes with virtual bases, and second, we're
225645b53394SDimitry Andric // about to overwrite the vptrs anyway.
225745b53394SDimitry Andric // We also have to make sure if we can refer to vtable:
225845b53394SDimitry Andric // - Otherwise we can refer to vtable if it's safe to speculatively emit.
225945b53394SDimitry Andric // FIXME: If vtable is used by ctor/dtor, or if vtable is external and we are
226045b53394SDimitry Andric // sure that definition of vtable is not hidden,
226145b53394SDimitry Andric // then we are always safe to refer to it.
226245b53394SDimitry Andric // FIXME: It looks like InstCombine is very inefficient on dealing with
226345b53394SDimitry Andric // assumes. Make assumption loads require -fstrict-vtable-pointers temporarily.
226445b53394SDimitry Andric if (CGM.getCodeGenOpts().OptimizationLevel > 0 &&
226545b53394SDimitry Andric ClassDecl->isDynamicClass() && Type != Ctor_Base &&
226645b53394SDimitry Andric CGM.getCXXABI().canSpeculativelyEmitVTable(ClassDecl) &&
226745b53394SDimitry Andric CGM.getCodeGenOpts().StrictVTablePointers)
226845b53394SDimitry Andric EmitVTableAssumptionLoads(ClassDecl, This);
226945b53394SDimitry Andric }
227045b53394SDimitry Andric
EmitInheritedCXXConstructorCall(const CXXConstructorDecl * D,bool ForVirtualBase,Address This,bool InheritedFromVBase,const CXXInheritedCtorInitExpr * E)22712b6b257fSDimitry Andric void CodeGenFunction::EmitInheritedCXXConstructorCall(
22722b6b257fSDimitry Andric const CXXConstructorDecl *D, bool ForVirtualBase, Address This,
22732b6b257fSDimitry Andric bool InheritedFromVBase, const CXXInheritedCtorInitExpr *E) {
22742b6b257fSDimitry Andric CallArgList Args;
2275ac9a064cSDimitry Andric CallArg ThisArg(RValue::get(getAsNaturalPointerTo(
2276ac9a064cSDimitry Andric This, D->getThisType()->getPointeeType())),
2277ac9a064cSDimitry Andric D->getThisType());
22782b6b257fSDimitry Andric
22792b6b257fSDimitry Andric // Forward the parameters.
22802b6b257fSDimitry Andric if (InheritedFromVBase &&
22812b6b257fSDimitry Andric CGM.getTarget().getCXXABI().hasConstructorVariants()) {
22822b6b257fSDimitry Andric // Nothing to do; this construction is not responsible for constructing
22832b6b257fSDimitry Andric // the base class containing the inherited constructor.
22842b6b257fSDimitry Andric // FIXME: Can we just pass undef's for the remaining arguments if we don't
22852b6b257fSDimitry Andric // have constructor variants?
22862b6b257fSDimitry Andric Args.push_back(ThisArg);
22872b6b257fSDimitry Andric } else if (!CXXInheritedCtorInitExprArgs.empty()) {
22882b6b257fSDimitry Andric // The inheriting constructor was inlined; just inject its arguments.
22892b6b257fSDimitry Andric assert(CXXInheritedCtorInitExprArgs.size() >= D->getNumParams() &&
22902b6b257fSDimitry Andric "wrong number of parameters for inherited constructor call");
22912b6b257fSDimitry Andric Args = CXXInheritedCtorInitExprArgs;
22922b6b257fSDimitry Andric Args[0] = ThisArg;
22932b6b257fSDimitry Andric } else {
22942b6b257fSDimitry Andric // The inheriting constructor was not inlined. Emit delegating arguments.
22952b6b257fSDimitry Andric Args.push_back(ThisArg);
22962b6b257fSDimitry Andric const auto *OuterCtor = cast<CXXConstructorDecl>(CurCodeDecl);
22972b6b257fSDimitry Andric assert(OuterCtor->getNumParams() == D->getNumParams());
22982b6b257fSDimitry Andric assert(!OuterCtor->isVariadic() && "should have been inlined");
22992b6b257fSDimitry Andric
23002b6b257fSDimitry Andric for (const auto *Param : OuterCtor->parameters()) {
23012b6b257fSDimitry Andric assert(getContext().hasSameUnqualifiedType(
23022b6b257fSDimitry Andric OuterCtor->getParamDecl(Param->getFunctionScopeIndex())->getType(),
23032b6b257fSDimitry Andric Param->getType()));
23042b6b257fSDimitry Andric EmitDelegateCallArg(Args, Param, E->getLocation());
23052b6b257fSDimitry Andric
23062b6b257fSDimitry Andric // Forward __attribute__(pass_object_size).
23072b6b257fSDimitry Andric if (Param->hasAttr<PassObjectSizeAttr>()) {
23082b6b257fSDimitry Andric auto *POSParam = SizeArguments[Param];
23092b6b257fSDimitry Andric assert(POSParam && "missing pass_object_size value for forwarding");
23102b6b257fSDimitry Andric EmitDelegateCallArg(Args, POSParam, E->getLocation());
23112b6b257fSDimitry Andric }
23122b6b257fSDimitry Andric }
23132b6b257fSDimitry Andric }
23142b6b257fSDimitry Andric
23152b6b257fSDimitry Andric EmitCXXConstructorCall(D, Ctor_Base, ForVirtualBase, /*Delegating*/false,
231648675466SDimitry Andric This, Args, AggValueSlot::MayOverlap,
2317c7e70c43SDimitry Andric E->getLocation(), /*NewPointerIsChecked*/true);
23182b6b257fSDimitry Andric }
23192b6b257fSDimitry Andric
EmitInlinedInheritingCXXConstructorCall(const CXXConstructorDecl * Ctor,CXXCtorType CtorType,bool ForVirtualBase,bool Delegating,CallArgList & Args)23202b6b257fSDimitry Andric void CodeGenFunction::EmitInlinedInheritingCXXConstructorCall(
23212b6b257fSDimitry Andric const CXXConstructorDecl *Ctor, CXXCtorType CtorType, bool ForVirtualBase,
23222b6b257fSDimitry Andric bool Delegating, CallArgList &Args) {
23237442d6faSDimitry Andric GlobalDecl GD(Ctor, CtorType);
23247442d6faSDimitry Andric InlinedInheritingConstructorScope Scope(*this, GD);
23257442d6faSDimitry Andric ApplyInlineDebugLocation DebugScope(*this, GD);
2326676fbe81SDimitry Andric RunCleanupsScope RunCleanups(*this);
23272b6b257fSDimitry Andric
23282b6b257fSDimitry Andric // Save the arguments to be passed to the inherited constructor.
23292b6b257fSDimitry Andric CXXInheritedCtorInitExprArgs = Args;
23302b6b257fSDimitry Andric
23312b6b257fSDimitry Andric FunctionArgList Params;
23322b6b257fSDimitry Andric QualType RetType = BuildFunctionArgList(CurGD, Params);
23332b6b257fSDimitry Andric FnRetTy = RetType;
23342b6b257fSDimitry Andric
23352b6b257fSDimitry Andric // Insert any ABI-specific implicit constructor arguments.
23362b6b257fSDimitry Andric CGM.getCXXABI().addImplicitConstructorArgs(*this, Ctor, CtorType,
23372b6b257fSDimitry Andric ForVirtualBase, Delegating, Args);
23382b6b257fSDimitry Andric
23392b6b257fSDimitry Andric // Emit a simplified prolog. We only need to emit the implicit params.
23402b6b257fSDimitry Andric assert(Args.size() >= Params.size() && "too few arguments for call");
23412b6b257fSDimitry Andric for (unsigned I = 0, N = Args.size(); I != N; ++I) {
23422b6b257fSDimitry Andric if (I < Params.size() && isa<ImplicitParamDecl>(Params[I])) {
234348675466SDimitry Andric const RValue &RV = Args[I].getRValue(*this);
23442b6b257fSDimitry Andric assert(!RV.isComplex() && "complex indirect params not supported");
23452b6b257fSDimitry Andric ParamValue Val = RV.isScalar()
23462b6b257fSDimitry Andric ? ParamValue::forDirect(RV.getScalarVal())
23472b6b257fSDimitry Andric : ParamValue::forIndirect(RV.getAggregateAddress());
23482b6b257fSDimitry Andric EmitParmDecl(*Params[I], Val, I + 1);
23492b6b257fSDimitry Andric }
23502b6b257fSDimitry Andric }
23512b6b257fSDimitry Andric
23522b6b257fSDimitry Andric // Create a return value slot if the ABI implementation wants one.
23532b6b257fSDimitry Andric // FIXME: This is dumb, we should ask the ABI not to try to set the return
23542b6b257fSDimitry Andric // value instead.
23552b6b257fSDimitry Andric if (!RetType->isVoidType())
23562b6b257fSDimitry Andric ReturnValue = CreateIRTemp(RetType, "retval.inhctor");
23572b6b257fSDimitry Andric
23582b6b257fSDimitry Andric CGM.getCXXABI().EmitInstanceFunctionProlog(*this);
23592b6b257fSDimitry Andric CXXThisValue = CXXABIThisValue;
23602b6b257fSDimitry Andric
23612b6b257fSDimitry Andric // Directly emit the constructor initializers.
23622b6b257fSDimitry Andric EmitCtorPrologue(Ctor, CtorType, Params);
23632b6b257fSDimitry Andric }
23642b6b257fSDimitry Andric
EmitVTableAssumptionLoad(const VPtr & Vptr,Address This)236545b53394SDimitry Andric void CodeGenFunction::EmitVTableAssumptionLoad(const VPtr &Vptr, Address This) {
236645b53394SDimitry Andric llvm::Value *VTableGlobal =
236745b53394SDimitry Andric CGM.getCXXABI().getVTableAddressPoint(Vptr.Base, Vptr.VTableClass);
236845b53394SDimitry Andric if (!VTableGlobal)
236945b53394SDimitry Andric return;
237045b53394SDimitry Andric
237145b53394SDimitry Andric // We can just use the base offset in the complete class.
237245b53394SDimitry Andric CharUnits NonVirtualOffset = Vptr.Base.getBaseOffset();
237345b53394SDimitry Andric
237445b53394SDimitry Andric if (!NonVirtualOffset.isZero())
237545b53394SDimitry Andric This =
237645b53394SDimitry Andric ApplyNonVirtualAndVirtualOffset(*this, This, NonVirtualOffset, nullptr,
237745b53394SDimitry Andric Vptr.VTableClass, Vptr.NearestVBase);
237845b53394SDimitry Andric
237945b53394SDimitry Andric llvm::Value *VPtrValue =
238045b53394SDimitry Andric GetVTablePtr(This, VTableGlobal->getType(), Vptr.VTableClass);
238145b53394SDimitry Andric llvm::Value *Cmp =
238245b53394SDimitry Andric Builder.CreateICmpEQ(VPtrValue, VTableGlobal, "cmp.vtables");
238345b53394SDimitry Andric Builder.CreateAssumption(Cmp);
238445b53394SDimitry Andric }
238545b53394SDimitry Andric
EmitVTableAssumptionLoads(const CXXRecordDecl * ClassDecl,Address This)238645b53394SDimitry Andric void CodeGenFunction::EmitVTableAssumptionLoads(const CXXRecordDecl *ClassDecl,
238745b53394SDimitry Andric Address This) {
238845b53394SDimitry Andric if (CGM.getCXXABI().doStructorsInitializeVPtrs(ClassDecl))
238945b53394SDimitry Andric for (const VPtr &Vptr : getVTablePointers(ClassDecl))
239045b53394SDimitry Andric EmitVTableAssumptionLoad(Vptr, This);
2391ee791ddeSRoman Divacky }
2392ee791ddeSRoman Divacky
239379ade4e0SRoman Divacky void
EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl * D,Address This,Address Src,const CXXConstructExpr * E)2394bca07a45SDimitry Andric CodeGenFunction::EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D,
239545b53394SDimitry Andric Address This, Address Src,
239606d4ba38SDimitry Andric const CXXConstructExpr *E) {
23979f4dbff6SDimitry Andric const FunctionProtoType *FPT = D->getType()->castAs<FunctionProtoType>();
2398bca07a45SDimitry Andric
2399bca07a45SDimitry Andric CallArgList Args;
2400bca07a45SDimitry Andric
2401bca07a45SDimitry Andric // Push the this ptr.
2402ac9a064cSDimitry Andric Args.add(RValue::get(getAsNaturalPointerTo(This, D->getThisType())),
2403ac9a064cSDimitry Andric D->getThisType());
2404bca07a45SDimitry Andric
2405bca07a45SDimitry Andric // Push the src ptr.
24069f4dbff6SDimitry Andric QualType QT = *(FPT->param_type_begin());
240736981b17SDimitry Andric llvm::Type *t = CGM.getTypes().ConvertType(QT);
2408ac9a064cSDimitry Andric llvm::Value *Val = getAsNaturalPointerTo(Src, D->getThisType());
2409ac9a064cSDimitry Andric llvm::Value *SrcVal = Builder.CreateBitCast(Val, t);
2410145449b1SDimitry Andric Args.add(RValue::get(SrcVal), QT);
2411bca07a45SDimitry Andric
2412bca07a45SDimitry Andric // Skip over first argument (Src).
241345b53394SDimitry Andric EmitCallArgs(Args, FPT, drop_begin(E->arguments(), 1), E->getConstructor(),
241406d4ba38SDimitry Andric /*ParamsToSkip*/ 1);
2415bca07a45SDimitry Andric
2416c7e70c43SDimitry Andric EmitCXXConstructorCall(D, Ctor_Complete, /*ForVirtualBase*/false,
2417c7e70c43SDimitry Andric /*Delegating*/false, This, Args,
2418c7e70c43SDimitry Andric AggValueSlot::MayOverlap, E->getExprLoc(),
2419c7e70c43SDimitry Andric /*NewPointerIsChecked*/false);
2420bca07a45SDimitry Andric }
2421bca07a45SDimitry Andric
2422bca07a45SDimitry Andric void
EmitDelegateCXXConstructorCall(const CXXConstructorDecl * Ctor,CXXCtorType CtorType,const FunctionArgList & Args,SourceLocation Loc)242379ade4e0SRoman Divacky CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor,
242479ade4e0SRoman Divacky CXXCtorType CtorType,
2425bfef3995SDimitry Andric const FunctionArgList &Args,
2426bfef3995SDimitry Andric SourceLocation Loc) {
242779ade4e0SRoman Divacky CallArgList DelegateArgs;
242879ade4e0SRoman Divacky
242979ade4e0SRoman Divacky FunctionArgList::const_iterator I = Args.begin(), E = Args.end();
243079ade4e0SRoman Divacky assert(I != E && "no parameters to constructor");
243179ade4e0SRoman Divacky
243279ade4e0SRoman Divacky // this
24332b6b257fSDimitry Andric Address This = LoadCXXThisAddress();
2434ac9a064cSDimitry Andric DelegateArgs.add(RValue::get(getAsNaturalPointerTo(
2435ac9a064cSDimitry Andric This, (*I)->getType()->getPointeeType())),
2436ac9a064cSDimitry Andric (*I)->getType());
243779ade4e0SRoman Divacky ++I;
243879ade4e0SRoman Divacky
24392b6b257fSDimitry Andric // FIXME: The location of the VTT parameter in the parameter list is
24402b6b257fSDimitry Andric // specific to the Itanium ABI and shouldn't be hardcoded here.
2441bfef3995SDimitry Andric if (CGM.getCXXABI().NeedsVTTParameter(CurGD)) {
244279ade4e0SRoman Divacky assert(I != E && "cannot skip vtt parameter, already done with args");
24432b6b257fSDimitry Andric assert((*I)->getType()->isPointerType() &&
24442b6b257fSDimitry Andric "skipping parameter not of vtt type");
244579ade4e0SRoman Divacky ++I;
244679ade4e0SRoman Divacky }
244779ade4e0SRoman Divacky
244879ade4e0SRoman Divacky // Explicit arguments.
244979ade4e0SRoman Divacky for (; I != E; ++I) {
245001af97d3SDimitry Andric const VarDecl *param = *I;
2451bfef3995SDimitry Andric // FIXME: per-argument source location
2452bfef3995SDimitry Andric EmitDelegateCallArg(DelegateArgs, param, Loc);
245379ade4e0SRoman Divacky }
245479ade4e0SRoman Divacky
24552b6b257fSDimitry Andric EmitCXXConstructorCall(Ctor, CtorType, /*ForVirtualBase=*/false,
245648675466SDimitry Andric /*Delegating=*/true, This, DelegateArgs,
2457c7e70c43SDimitry Andric AggValueSlot::MayOverlap, Loc,
2458c7e70c43SDimitry Andric /*NewPointerIsChecked=*/true);
245979ade4e0SRoman Divacky }
246079ade4e0SRoman Divacky
246129cafa66SDimitry Andric namespace {
246245b53394SDimitry Andric struct CallDelegatingCtorDtor final : EHScopeStack::Cleanup {
246329cafa66SDimitry Andric const CXXDestructorDecl *Dtor;
246445b53394SDimitry Andric Address Addr;
246529cafa66SDimitry Andric CXXDtorType Type;
246629cafa66SDimitry Andric
CallDelegatingCtorDtor__anonf1d54d130511::CallDelegatingCtorDtor246745b53394SDimitry Andric CallDelegatingCtorDtor(const CXXDestructorDecl *D, Address Addr,
246829cafa66SDimitry Andric CXXDtorType Type)
246929cafa66SDimitry Andric : Dtor(D), Addr(Addr), Type(Type) {}
247029cafa66SDimitry Andric
Emit__anonf1d54d130511::CallDelegatingCtorDtor24719f4dbff6SDimitry Andric void Emit(CodeGenFunction &CGF, Flags flags) override {
247222989816SDimitry Andric // We are calling the destructor from within the constructor.
247322989816SDimitry Andric // Therefore, "this" should have the expected type.
2474b1c73532SDimitry Andric QualType ThisTy = Dtor->getFunctionObjectParameterType();
247529cafa66SDimitry Andric CGF.EmitCXXDestructorCall(Dtor, Type, /*ForVirtualBase=*/false,
247622989816SDimitry Andric /*Delegating=*/true, Addr, ThisTy);
247729cafa66SDimitry Andric }
247829cafa66SDimitry Andric };
247945b53394SDimitry Andric } // end anonymous namespace
248029cafa66SDimitry Andric
248101af97d3SDimitry Andric void
EmitDelegatingCXXConstructorCall(const CXXConstructorDecl * Ctor,const FunctionArgList & Args)248201af97d3SDimitry Andric CodeGenFunction::EmitDelegatingCXXConstructorCall(const CXXConstructorDecl *Ctor,
248301af97d3SDimitry Andric const FunctionArgList &Args) {
248401af97d3SDimitry Andric assert(Ctor->isDelegatingConstructor());
248501af97d3SDimitry Andric
248645b53394SDimitry Andric Address ThisPtr = LoadCXXThisAddress();
248701af97d3SDimitry Andric
2488180abc3dSDimitry Andric AggValueSlot AggSlot =
248945b53394SDimitry Andric AggValueSlot::forAddr(ThisPtr, Qualifiers(),
249036981b17SDimitry Andric AggValueSlot::IsDestructed,
249136981b17SDimitry Andric AggValueSlot::DoesNotNeedGCBarriers,
249248675466SDimitry Andric AggValueSlot::IsNotAliased,
2493c7e70c43SDimitry Andric AggValueSlot::MayOverlap,
2494c7e70c43SDimitry Andric AggValueSlot::IsNotZeroed,
2495c7e70c43SDimitry Andric // Checks are made by the code that calls constructor.
2496c7e70c43SDimitry Andric AggValueSlot::IsSanitizerChecked);
249701af97d3SDimitry Andric
249801af97d3SDimitry Andric EmitAggExpr(Ctor->init_begin()[0]->getInit(), AggSlot);
249901af97d3SDimitry Andric
250029cafa66SDimitry Andric const CXXRecordDecl *ClassDecl = Ctor->getParent();
2501dbe13110SDimitry Andric if (CGM.getLangOpts().Exceptions && !ClassDecl->hasTrivialDestructor()) {
250229cafa66SDimitry Andric CXXDtorType Type =
250329cafa66SDimitry Andric CurGD.getCtorType() == Ctor_Complete ? Dtor_Complete : Dtor_Base;
250429cafa66SDimitry Andric
250529cafa66SDimitry Andric EHStack.pushCleanup<CallDelegatingCtorDtor>(EHCleanup,
250629cafa66SDimitry Andric ClassDecl->getDestructor(),
250729cafa66SDimitry Andric ThisPtr, Type);
250829cafa66SDimitry Andric }
250929cafa66SDimitry Andric }
251001af97d3SDimitry Andric
EmitCXXDestructorCall(const CXXDestructorDecl * DD,CXXDtorType Type,bool ForVirtualBase,bool Delegating,Address This,QualType ThisTy)2511ee791ddeSRoman Divacky void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD,
2512ee791ddeSRoman Divacky CXXDtorType Type,
25130883ccd9SRoman Divacky bool ForVirtualBase,
251422989816SDimitry Andric bool Delegating, Address This,
251522989816SDimitry Andric QualType ThisTy) {
25169f4dbff6SDimitry Andric CGM.getCXXABI().EmitDestructorCall(*this, DD, Type, ForVirtualBase,
251722989816SDimitry Andric Delegating, This, ThisTy);
2518ee791ddeSRoman Divacky }
2519ee791ddeSRoman Divacky
25203d1dcd9bSDimitry Andric namespace {
252145b53394SDimitry Andric struct CallLocalDtor final : EHScopeStack::Cleanup {
25223d1dcd9bSDimitry Andric const CXXDestructorDecl *Dtor;
252345b53394SDimitry Andric Address Addr;
252422989816SDimitry Andric QualType Ty;
25253d1dcd9bSDimitry Andric
CallLocalDtor__anonf1d54d130611::CallLocalDtor252622989816SDimitry Andric CallLocalDtor(const CXXDestructorDecl *D, Address Addr, QualType Ty)
252722989816SDimitry Andric : Dtor(D), Addr(Addr), Ty(Ty) {}
25283d1dcd9bSDimitry Andric
Emit__anonf1d54d130611::CallLocalDtor25299f4dbff6SDimitry Andric void Emit(CodeGenFunction &CGF, Flags flags) override {
25303d1dcd9bSDimitry Andric CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete,
2531809500fcSDimitry Andric /*ForVirtualBase=*/false,
253222989816SDimitry Andric /*Delegating=*/false, Addr, Ty);
25333d1dcd9bSDimitry Andric }
25343d1dcd9bSDimitry Andric };
25352b6b257fSDimitry Andric } // end anonymous namespace
25363d1dcd9bSDimitry Andric
PushDestructorCleanup(const CXXDestructorDecl * D,QualType T,Address Addr)25373d1dcd9bSDimitry Andric void CodeGenFunction::PushDestructorCleanup(const CXXDestructorDecl *D,
253822989816SDimitry Andric QualType T, Address Addr) {
253922989816SDimitry Andric EHStack.pushCleanup<CallLocalDtor>(NormalAndEHCleanup, D, Addr, T);
25403d1dcd9bSDimitry Andric }
25413d1dcd9bSDimitry Andric
PushDestructorCleanup(QualType T,Address Addr)254245b53394SDimitry Andric void CodeGenFunction::PushDestructorCleanup(QualType T, Address Addr) {
25434ba67500SRoman Divacky CXXRecordDecl *ClassDecl = T->getAsCXXRecordDecl();
25444ba67500SRoman Divacky if (!ClassDecl) return;
25454ba67500SRoman Divacky if (ClassDecl->hasTrivialDestructor()) return;
25464ba67500SRoman Divacky
25474ba67500SRoman Divacky const CXXDestructorDecl *D = ClassDecl->getDestructor();
254801af97d3SDimitry Andric assert(D && D->isUsed() && "destructor not marked as used!");
254922989816SDimitry Andric PushDestructorCleanup(D, T, Addr);
25504ba67500SRoman Divacky }
25514ba67500SRoman Divacky
InitializeVTablePointer(const VPtr & Vptr)255245b53394SDimitry Andric void CodeGenFunction::InitializeVTablePointer(const VPtr &Vptr) {
255311d2b2d2SRoman Divacky // Compute the address point.
2554bfef3995SDimitry Andric llvm::Value *VTableAddressPoint =
2555bfef3995SDimitry Andric CGM.getCXXABI().getVTableAddressPointInStructor(
255645b53394SDimitry Andric *this, Vptr.VTableClass, Vptr.Base, Vptr.NearestVBase);
255745b53394SDimitry Andric
2558bfef3995SDimitry Andric if (!VTableAddressPoint)
2559bfef3995SDimitry Andric return;
2560ee791ddeSRoman Divacky
256111d2b2d2SRoman Divacky // Compute where to store the address point.
25629f4dbff6SDimitry Andric llvm::Value *VirtualOffset = nullptr;
256301af97d3SDimitry Andric CharUnits NonVirtualOffset = CharUnits::Zero();
2564ee791ddeSRoman Divacky
256545b53394SDimitry Andric if (CGM.getCXXABI().isVirtualOffsetNeededForVTableField(*this, Vptr)) {
256611d2b2d2SRoman Divacky // We need to use the virtual base offset offset because the virtual base
256711d2b2d2SRoman Divacky // might have a different offset in the most derived class.
256845b53394SDimitry Andric
256945b53394SDimitry Andric VirtualOffset = CGM.getCXXABI().GetVirtualBaseClassOffset(
257045b53394SDimitry Andric *this, LoadCXXThisAddress(), Vptr.VTableClass, Vptr.NearestVBase);
257145b53394SDimitry Andric NonVirtualOffset = Vptr.OffsetFromNearestVBase;
257211d2b2d2SRoman Divacky } else {
25730883ccd9SRoman Divacky // We can just use the base offset in the complete class.
257445b53394SDimitry Andric NonVirtualOffset = Vptr.Base.getBaseOffset();
257511d2b2d2SRoman Divacky }
257611d2b2d2SRoman Divacky
25770883ccd9SRoman Divacky // Apply the offsets.
257845b53394SDimitry Andric Address VTableField = LoadCXXThisAddress();
257901af97d3SDimitry Andric if (!NonVirtualOffset.isZero() || VirtualOffset)
258045b53394SDimitry Andric VTableField = ApplyNonVirtualAndVirtualOffset(
258145b53394SDimitry Andric *this, VTableField, NonVirtualOffset, VirtualOffset, Vptr.VTableClass,
258245b53394SDimitry Andric Vptr.NearestVBase);
25830883ccd9SRoman Divacky
258406d4ba38SDimitry Andric // Finally, store the address point. Use the same LLVM types as the field to
258506d4ba38SDimitry Andric // support optimization.
2586b60736ecSDimitry Andric unsigned GlobalsAS = CGM.getDataLayout().getDefaultGlobalsAddressSpace();
25877fa27ce4SDimitry Andric llvm::Type *PtrTy = llvm::PointerType::get(CGM.getLLVMContext(), GlobalsAS);
2588e3b55780SDimitry Andric // vtable field is derived from `this` pointer, therefore they should be in
2589c0981da4SDimitry Andric // the same addr space. Note that this might not be LLVM address space 0.
25907fa27ce4SDimitry Andric VTableField = VTableField.withElementType(PtrTy);
259145b53394SDimitry Andric
2592ac9a064cSDimitry Andric if (auto AuthenticationInfo = CGM.getVTablePointerAuthInfo(
2593ac9a064cSDimitry Andric this, Vptr.Base.getBase(), VTableField.emitRawPointer(*this)))
2594ac9a064cSDimitry Andric VTableAddressPoint =
2595ac9a064cSDimitry Andric EmitPointerAuthSign(*AuthenticationInfo, VTableAddressPoint);
2596ac9a064cSDimitry Andric
2597dbe13110SDimitry Andric llvm::StoreInst *Store = Builder.CreateStore(VTableAddressPoint, VTableField);
25987fa27ce4SDimitry Andric TBAAAccessInfo TBAAInfo = CGM.getTBAAVTablePtrAccessInfo(PtrTy);
2599461a67faSDimitry Andric CGM.DecorateInstructionWithTBAA(Store, TBAAInfo);
260045b53394SDimitry Andric if (CGM.getCodeGenOpts().OptimizationLevel > 0 &&
260145b53394SDimitry Andric CGM.getCodeGenOpts().StrictVTablePointers)
260245b53394SDimitry Andric CGM.DecorateInstructionWithInvariantGroup(Store, Vptr.VTableClass);
260311d2b2d2SRoman Divacky }
260411d2b2d2SRoman Divacky
260545b53394SDimitry Andric CodeGenFunction::VPtrsVector
getVTablePointers(const CXXRecordDecl * VTableClass)260645b53394SDimitry Andric CodeGenFunction::getVTablePointers(const CXXRecordDecl *VTableClass) {
260745b53394SDimitry Andric CodeGenFunction::VPtrsVector VPtrsResult;
260845b53394SDimitry Andric VisitedVirtualBasesSetTy VBases;
260945b53394SDimitry Andric getVTablePointers(BaseSubobject(VTableClass, CharUnits::Zero()),
261045b53394SDimitry Andric /*NearestVBase=*/nullptr,
261145b53394SDimitry Andric /*OffsetFromNearestVBase=*/CharUnits::Zero(),
261245b53394SDimitry Andric /*BaseIsNonVirtualPrimaryBase=*/false, VTableClass, VBases,
261345b53394SDimitry Andric VPtrsResult);
261445b53394SDimitry Andric return VPtrsResult;
261545b53394SDimitry Andric }
261645b53394SDimitry Andric
getVTablePointers(BaseSubobject Base,const CXXRecordDecl * NearestVBase,CharUnits OffsetFromNearestVBase,bool BaseIsNonVirtualPrimaryBase,const CXXRecordDecl * VTableClass,VisitedVirtualBasesSetTy & VBases,VPtrsVector & Vptrs)261745b53394SDimitry Andric void CodeGenFunction::getVTablePointers(BaseSubobject Base,
26180883ccd9SRoman Divacky const CXXRecordDecl *NearestVBase,
261901af97d3SDimitry Andric CharUnits OffsetFromNearestVBase,
262011d2b2d2SRoman Divacky bool BaseIsNonVirtualPrimaryBase,
262111d2b2d2SRoman Divacky const CXXRecordDecl *VTableClass,
262245b53394SDimitry Andric VisitedVirtualBasesSetTy &VBases,
262345b53394SDimitry Andric VPtrsVector &Vptrs) {
262411d2b2d2SRoman Divacky // If this base is a non-virtual primary base the address point has already
262511d2b2d2SRoman Divacky // been set.
262611d2b2d2SRoman Divacky if (!BaseIsNonVirtualPrimaryBase) {
262711d2b2d2SRoman Divacky // Initialize the vtable pointer for this base.
262845b53394SDimitry Andric VPtr Vptr = {Base, NearestVBase, OffsetFromNearestVBase, VTableClass};
262945b53394SDimitry Andric Vptrs.push_back(Vptr);
263011d2b2d2SRoman Divacky }
263111d2b2d2SRoman Divacky
263211d2b2d2SRoman Divacky const CXXRecordDecl *RD = Base.getBase();
263311d2b2d2SRoman Divacky
263411d2b2d2SRoman Divacky // Traverse bases.
26359f4dbff6SDimitry Andric for (const auto &I : RD->bases()) {
2636519fc96cSDimitry Andric auto *BaseDecl =
2637519fc96cSDimitry Andric cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl());
263811d2b2d2SRoman Divacky
263911d2b2d2SRoman Divacky // Ignore classes without a vtable.
264011d2b2d2SRoman Divacky if (!BaseDecl->isDynamicClass())
264111d2b2d2SRoman Divacky continue;
264211d2b2d2SRoman Divacky
264301af97d3SDimitry Andric CharUnits BaseOffset;
264401af97d3SDimitry Andric CharUnits BaseOffsetFromNearestVBase;
264511d2b2d2SRoman Divacky bool BaseDeclIsNonVirtualPrimaryBase;
264611d2b2d2SRoman Divacky
26479f4dbff6SDimitry Andric if (I.isVirtual()) {
264811d2b2d2SRoman Divacky // Check if we've visited this virtual base before.
264906d4ba38SDimitry Andric if (!VBases.insert(BaseDecl).second)
265011d2b2d2SRoman Divacky continue;
265111d2b2d2SRoman Divacky
265211d2b2d2SRoman Divacky const ASTRecordLayout &Layout =
265311d2b2d2SRoman Divacky getContext().getASTRecordLayout(VTableClass);
265411d2b2d2SRoman Divacky
265501af97d3SDimitry Andric BaseOffset = Layout.getVBaseClassOffset(BaseDecl);
265601af97d3SDimitry Andric BaseOffsetFromNearestVBase = CharUnits::Zero();
265711d2b2d2SRoman Divacky BaseDeclIsNonVirtualPrimaryBase = false;
265811d2b2d2SRoman Divacky } else {
265911d2b2d2SRoman Divacky const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
266011d2b2d2SRoman Divacky
266101af97d3SDimitry Andric BaseOffset = Base.getBaseOffset() + Layout.getBaseClassOffset(BaseDecl);
26620883ccd9SRoman Divacky BaseOffsetFromNearestVBase =
266301af97d3SDimitry Andric OffsetFromNearestVBase + Layout.getBaseClassOffset(BaseDecl);
266411d2b2d2SRoman Divacky BaseDeclIsNonVirtualPrimaryBase = Layout.getPrimaryBase() == BaseDecl;
266511d2b2d2SRoman Divacky }
266611d2b2d2SRoman Divacky
266745b53394SDimitry Andric getVTablePointers(
266845b53394SDimitry Andric BaseSubobject(BaseDecl, BaseOffset),
266945b53394SDimitry Andric I.isVirtual() ? BaseDecl : NearestVBase, BaseOffsetFromNearestVBase,
267045b53394SDimitry Andric BaseDeclIsNonVirtualPrimaryBase, VTableClass, VBases, Vptrs);
267111d2b2d2SRoman Divacky }
267211d2b2d2SRoman Divacky }
267311d2b2d2SRoman Divacky
InitializeVTablePointers(const CXXRecordDecl * RD)267411d2b2d2SRoman Divacky void CodeGenFunction::InitializeVTablePointers(const CXXRecordDecl *RD) {
267511d2b2d2SRoman Divacky // Ignore classes without a vtable.
267611d2b2d2SRoman Divacky if (!RD->isDynamicClass())
267711d2b2d2SRoman Divacky return;
267811d2b2d2SRoman Divacky
267911d2b2d2SRoman Divacky // Initialize the vtable pointers for this class and all of its bases.
268045b53394SDimitry Andric if (CGM.getCXXABI().doStructorsInitializeVPtrs(RD))
268145b53394SDimitry Andric for (const VPtr &Vptr : getVTablePointers(RD))
268245b53394SDimitry Andric InitializeVTablePointer(Vptr);
2683bfef3995SDimitry Andric
2684bfef3995SDimitry Andric if (RD->getNumVBases())
2685bfef3995SDimitry Andric CGM.getCXXABI().initializeHiddenVirtualInheritanceMembers(*this, RD);
2686ee791ddeSRoman Divacky }
2687bca07a45SDimitry Andric
GetVTablePtr(Address This,llvm::Type * VTableTy,const CXXRecordDecl * RD,VTableAuthMode AuthMode)268845b53394SDimitry Andric llvm::Value *CodeGenFunction::GetVTablePtr(Address This,
268945b53394SDimitry Andric llvm::Type *VTableTy,
2690ac9a064cSDimitry Andric const CXXRecordDecl *RD,
2691ac9a064cSDimitry Andric VTableAuthMode AuthMode) {
26927fa27ce4SDimitry Andric Address VTablePtrSrc = This.withElementType(VTableTy);
2693dbe13110SDimitry Andric llvm::Instruction *VTable = Builder.CreateLoad(VTablePtrSrc, "vtable");
2694461a67faSDimitry Andric TBAAAccessInfo TBAAInfo = CGM.getTBAAVTablePtrAccessInfo(VTableTy);
2695461a67faSDimitry Andric CGM.DecorateInstructionWithTBAA(VTable, TBAAInfo);
269645b53394SDimitry Andric
2697ac9a064cSDimitry Andric if (auto AuthenticationInfo =
2698ac9a064cSDimitry Andric CGM.getVTablePointerAuthInfo(this, RD, This.emitRawPointer(*this))) {
2699ac9a064cSDimitry Andric if (AuthMode != VTableAuthMode::UnsafeUbsanStrip) {
2700ac9a064cSDimitry Andric VTable = cast<llvm::Instruction>(
2701ac9a064cSDimitry Andric EmitPointerAuthAuth(*AuthenticationInfo, VTable));
2702ac9a064cSDimitry Andric if (AuthMode == VTableAuthMode::MustTrap) {
2703ac9a064cSDimitry Andric // This is clearly suboptimal but until we have an ability
2704ac9a064cSDimitry Andric // to rely on the authentication intrinsic trapping and force
2705ac9a064cSDimitry Andric // an authentication to occur we don't really have a choice.
2706ac9a064cSDimitry Andric VTable =
2707ac9a064cSDimitry Andric cast<llvm::Instruction>(Builder.CreateBitCast(VTable, Int8PtrTy));
2708ac9a064cSDimitry Andric Builder.CreateLoad(RawAddress(VTable, Int8Ty, CGM.getPointerAlign()),
2709ac9a064cSDimitry Andric /* IsVolatile */ true);
2710ac9a064cSDimitry Andric }
2711ac9a064cSDimitry Andric } else {
2712ac9a064cSDimitry Andric VTable = cast<llvm::Instruction>(EmitPointerAuthAuth(
2713ac9a064cSDimitry Andric CGPointerAuthInfo(0, PointerAuthenticationMode::Strip, false, false,
2714ac9a064cSDimitry Andric nullptr),
2715ac9a064cSDimitry Andric VTable));
2716ac9a064cSDimitry Andric }
2717ac9a064cSDimitry Andric }
2718ac9a064cSDimitry Andric
271945b53394SDimitry Andric if (CGM.getCodeGenOpts().OptimizationLevel > 0 &&
272045b53394SDimitry Andric CGM.getCodeGenOpts().StrictVTablePointers)
272145b53394SDimitry Andric CGM.DecorateInstructionWithInvariantGroup(VTable, RD);
272245b53394SDimitry Andric
2723dbe13110SDimitry Andric return VTable;
2724bca07a45SDimitry Andric }
272529cafa66SDimitry Andric
27265e20cdd8SDimitry Andric // If a class has a single non-virtual base and does not introduce or override
27275e20cdd8SDimitry Andric // virtual member functions or fields, it will have the same layout as its base.
27285e20cdd8SDimitry Andric // This function returns the least derived such class.
27295e20cdd8SDimitry Andric //
27305e20cdd8SDimitry Andric // Casting an instance of a base class to such a derived class is technically
27315e20cdd8SDimitry Andric // undefined behavior, but it is a relatively common hack for introducing member
27325e20cdd8SDimitry Andric // functions on class instances with specific properties (e.g. llvm::Operator)
27335e20cdd8SDimitry Andric // that works under most compilers and should not have security implications, so
27345e20cdd8SDimitry Andric // we allow it by default. It can be disabled with -fsanitize=cfi-cast-strict.
27355e20cdd8SDimitry Andric static const CXXRecordDecl *
LeastDerivedClassWithSameLayout(const CXXRecordDecl * RD)27365e20cdd8SDimitry Andric LeastDerivedClassWithSameLayout(const CXXRecordDecl *RD) {
27375e20cdd8SDimitry Andric if (!RD->field_empty())
27385e20cdd8SDimitry Andric return RD;
27395e20cdd8SDimitry Andric
27405e20cdd8SDimitry Andric if (RD->getNumVBases() != 0)
27415e20cdd8SDimitry Andric return RD;
27425e20cdd8SDimitry Andric
27435e20cdd8SDimitry Andric if (RD->getNumBases() != 1)
27445e20cdd8SDimitry Andric return RD;
27455e20cdd8SDimitry Andric
27465e20cdd8SDimitry Andric for (const CXXMethodDecl *MD : RD->methods()) {
27475e20cdd8SDimitry Andric if (MD->isVirtual()) {
27485e20cdd8SDimitry Andric // Virtual member functions are only ok if they are implicit destructors
27495e20cdd8SDimitry Andric // because the implicit destructor will have the same semantics as the
27505e20cdd8SDimitry Andric // base class's destructor if no fields are added.
27515e20cdd8SDimitry Andric if (isa<CXXDestructorDecl>(MD) && MD->isImplicit())
27525e20cdd8SDimitry Andric continue;
27535e20cdd8SDimitry Andric return RD;
27545e20cdd8SDimitry Andric }
27555e20cdd8SDimitry Andric }
27565e20cdd8SDimitry Andric
27575e20cdd8SDimitry Andric return LeastDerivedClassWithSameLayout(
27585e20cdd8SDimitry Andric RD->bases_begin()->getType()->getAsCXXRecordDecl());
27595e20cdd8SDimitry Andric }
27605e20cdd8SDimitry Andric
EmitTypeMetadataCodeForVCall(const CXXRecordDecl * RD,llvm::Value * VTable,SourceLocation Loc)27612b6b257fSDimitry Andric void CodeGenFunction::EmitTypeMetadataCodeForVCall(const CXXRecordDecl *RD,
27622b6b257fSDimitry Andric llvm::Value *VTable,
27632b6b257fSDimitry Andric SourceLocation Loc) {
2764461a67faSDimitry Andric if (SanOpts.has(SanitizerKind::CFIVCall))
2765461a67faSDimitry Andric EmitVTablePtrCheckForCall(RD, VTable, CodeGenFunction::CFITCK_VCall, Loc);
2766461a67faSDimitry Andric else if (CGM.getCodeGenOpts().WholeProgramVTables &&
2767145449b1SDimitry Andric // Don't insert type test assumes if we are forcing public
2768cfca06d7SDimitry Andric // visibility.
2769145449b1SDimitry Andric !CGM.AlwaysHasLTOVisibilityPublic(RD)) {
277008e8dd7bSDimitry Andric QualType Ty = QualType(RD->getTypeForDecl(), 0);
277108e8dd7bSDimitry Andric llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(Ty);
27722b6b257fSDimitry Andric llvm::Value *TypeId =
27732b6b257fSDimitry Andric llvm::MetadataAsValue::get(CGM.getLLVMContext(), MD);
27742b6b257fSDimitry Andric
277508e8dd7bSDimitry Andric // If we already know that the call has hidden LTO visibility, emit
277608e8dd7bSDimitry Andric // @llvm.type.test(). Otherwise emit @llvm.public.type.test(), which WPD
277708e8dd7bSDimitry Andric // will convert to @llvm.type.test() if we assert at link time that we have
277808e8dd7bSDimitry Andric // whole program visibility.
277908e8dd7bSDimitry Andric llvm::Intrinsic::ID IID = CGM.HasHiddenLTOVisibility(RD)
278008e8dd7bSDimitry Andric ? llvm::Intrinsic::type_test
278108e8dd7bSDimitry Andric : llvm::Intrinsic::public_type_test;
27822b6b257fSDimitry Andric llvm::Value *TypeTest =
2783b1c73532SDimitry Andric Builder.CreateCall(CGM.getIntrinsic(IID), {VTable, TypeId});
27842b6b257fSDimitry Andric Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::assume), TypeTest);
27852b6b257fSDimitry Andric }
27862b6b257fSDimitry Andric }
27872b6b257fSDimitry Andric
EmitVTablePtrCheckForCall(const CXXRecordDecl * RD,llvm::Value * VTable,CFITypeCheckKind TCK,SourceLocation Loc)27882b6b257fSDimitry Andric void CodeGenFunction::EmitVTablePtrCheckForCall(const CXXRecordDecl *RD,
27892e645aa5SDimitry Andric llvm::Value *VTable,
27902e645aa5SDimitry Andric CFITypeCheckKind TCK,
27912e645aa5SDimitry Andric SourceLocation Loc) {
27925e20cdd8SDimitry Andric if (!SanOpts.has(SanitizerKind::CFICastStrict))
27932b6b257fSDimitry Andric RD = LeastDerivedClassWithSameLayout(RD);
27945e20cdd8SDimitry Andric
27952b6b257fSDimitry Andric EmitVTablePtrCheck(RD, VTable, TCK, Loc);
27965e20cdd8SDimitry Andric }
27975e20cdd8SDimitry Andric
EmitVTablePtrCheckForCast(QualType T,Address Derived,bool MayBeNull,CFITypeCheckKind TCK,SourceLocation Loc)2798145449b1SDimitry Andric void CodeGenFunction::EmitVTablePtrCheckForCast(QualType T, Address Derived,
27992e645aa5SDimitry Andric bool MayBeNull,
28002e645aa5SDimitry Andric CFITypeCheckKind TCK,
28012e645aa5SDimitry Andric SourceLocation Loc) {
28025e20cdd8SDimitry Andric if (!getLangOpts().CPlusPlus)
28035e20cdd8SDimitry Andric return;
28045e20cdd8SDimitry Andric
28055e20cdd8SDimitry Andric auto *ClassTy = T->getAs<RecordType>();
28065e20cdd8SDimitry Andric if (!ClassTy)
28075e20cdd8SDimitry Andric return;
28085e20cdd8SDimitry Andric
28095e20cdd8SDimitry Andric const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(ClassTy->getDecl());
28105e20cdd8SDimitry Andric
28115e20cdd8SDimitry Andric if (!ClassDecl->isCompleteDefinition() || !ClassDecl->isDynamicClass())
28125e20cdd8SDimitry Andric return;
28135e20cdd8SDimitry Andric
28145e20cdd8SDimitry Andric if (!SanOpts.has(SanitizerKind::CFICastStrict))
28155e20cdd8SDimitry Andric ClassDecl = LeastDerivedClassWithSameLayout(ClassDecl);
28165e20cdd8SDimitry Andric
281745b53394SDimitry Andric llvm::BasicBlock *ContBlock = nullptr;
28185e20cdd8SDimitry Andric
28195e20cdd8SDimitry Andric if (MayBeNull) {
28205e20cdd8SDimitry Andric llvm::Value *DerivedNotNull =
2821ac9a064cSDimitry Andric Builder.CreateIsNotNull(Derived.emitRawPointer(*this), "cast.nonnull");
28225e20cdd8SDimitry Andric
28235e20cdd8SDimitry Andric llvm::BasicBlock *CheckBlock = createBasicBlock("cast.check");
28245e20cdd8SDimitry Andric ContBlock = createBasicBlock("cast.cont");
28255e20cdd8SDimitry Andric
28265e20cdd8SDimitry Andric Builder.CreateCondBr(DerivedNotNull, CheckBlock, ContBlock);
28275e20cdd8SDimitry Andric
28285e20cdd8SDimitry Andric EmitBlock(CheckBlock);
28295e20cdd8SDimitry Andric }
28305e20cdd8SDimitry Andric
2831461a67faSDimitry Andric llvm::Value *VTable;
2832145449b1SDimitry Andric std::tie(VTable, ClassDecl) =
2833145449b1SDimitry Andric CGM.getCXXABI().LoadVTablePtr(*this, Derived, ClassDecl);
283445b53394SDimitry Andric
28352e645aa5SDimitry Andric EmitVTablePtrCheck(ClassDecl, VTable, TCK, Loc);
28365e20cdd8SDimitry Andric
28375e20cdd8SDimitry Andric if (MayBeNull) {
28385e20cdd8SDimitry Andric Builder.CreateBr(ContBlock);
28395e20cdd8SDimitry Andric EmitBlock(ContBlock);
28405e20cdd8SDimitry Andric }
28415e20cdd8SDimitry Andric }
28425e20cdd8SDimitry Andric
EmitVTablePtrCheck(const CXXRecordDecl * RD,llvm::Value * VTable,CFITypeCheckKind TCK,SourceLocation Loc)28435e20cdd8SDimitry Andric void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD,
28442e645aa5SDimitry Andric llvm::Value *VTable,
28452e645aa5SDimitry Andric CFITypeCheckKind TCK,
28462e645aa5SDimitry Andric SourceLocation Loc) {
28472b6b257fSDimitry Andric if (!CGM.getCodeGenOpts().SanitizeCfiCrossDso &&
28482b6b257fSDimitry Andric !CGM.HasHiddenLTOVisibility(RD))
28492b6b257fSDimitry Andric return;
28502b6b257fSDimitry Andric
2851461a67faSDimitry Andric SanitizerMask M;
28522b6b257fSDimitry Andric llvm::SanitizerStatKind SSK;
28532b6b257fSDimitry Andric switch (TCK) {
28542b6b257fSDimitry Andric case CFITCK_VCall:
2855461a67faSDimitry Andric M = SanitizerKind::CFIVCall;
28562b6b257fSDimitry Andric SSK = llvm::SanStat_CFI_VCall;
28572b6b257fSDimitry Andric break;
28582b6b257fSDimitry Andric case CFITCK_NVCall:
2859461a67faSDimitry Andric M = SanitizerKind::CFINVCall;
28602b6b257fSDimitry Andric SSK = llvm::SanStat_CFI_NVCall;
28612b6b257fSDimitry Andric break;
28622b6b257fSDimitry Andric case CFITCK_DerivedCast:
2863461a67faSDimitry Andric M = SanitizerKind::CFIDerivedCast;
28642b6b257fSDimitry Andric SSK = llvm::SanStat_CFI_DerivedCast;
28652b6b257fSDimitry Andric break;
28662b6b257fSDimitry Andric case CFITCK_UnrelatedCast:
2867461a67faSDimitry Andric M = SanitizerKind::CFIUnrelatedCast;
28682b6b257fSDimitry Andric SSK = llvm::SanStat_CFI_UnrelatedCast;
28692b6b257fSDimitry Andric break;
28702b6b257fSDimitry Andric case CFITCK_ICall:
287148675466SDimitry Andric case CFITCK_NVMFCall:
287248675466SDimitry Andric case CFITCK_VMFCall:
287348675466SDimitry Andric llvm_unreachable("unexpected sanitizer kind");
28742b6b257fSDimitry Andric }
2875461a67faSDimitry Andric
2876461a67faSDimitry Andric std::string TypeName = RD->getQualifiedNameAsString();
2877344a3780SDimitry Andric if (getContext().getNoSanitizeList().containsType(M, TypeName))
2878461a67faSDimitry Andric return;
2879461a67faSDimitry Andric
2880461a67faSDimitry Andric SanitizerScope SanScope(this);
28812b6b257fSDimitry Andric EmitSanitizerStatReport(SSK);
28822e645aa5SDimitry Andric
288345b53394SDimitry Andric llvm::Metadata *MD =
288445b53394SDimitry Andric CGM.CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0));
28852b6b257fSDimitry Andric llvm::Value *TypeId = llvm::MetadataAsValue::get(getLLVMContext(), MD);
28865e20cdd8SDimitry Andric
28872b6b257fSDimitry Andric llvm::Value *TypeTest = Builder.CreateCall(
2888b1c73532SDimitry Andric CGM.getIntrinsic(llvm::Intrinsic::type_test), {VTable, TypeId});
288945b53394SDimitry Andric
28902e645aa5SDimitry Andric llvm::Constant *StaticData[] = {
28912b6b257fSDimitry Andric llvm::ConstantInt::get(Int8Ty, TCK),
28922e645aa5SDimitry Andric EmitCheckSourceLocation(Loc),
28932e645aa5SDimitry Andric EmitCheckTypeDescriptor(QualType(RD->getTypeForDecl(), 0)),
28942e645aa5SDimitry Andric };
28952b6b257fSDimitry Andric
28962b6b257fSDimitry Andric auto CrossDsoTypeId = CGM.CreateCrossDsoCfiTypeId(MD);
28972b6b257fSDimitry Andric if (CGM.getCodeGenOpts().SanitizeCfiCrossDso && CrossDsoTypeId) {
2898b1c73532SDimitry Andric EmitCfiSlowPathCheck(M, TypeTest, CrossDsoTypeId, VTable, StaticData);
28992b6b257fSDimitry Andric return;
29002b6b257fSDimitry Andric }
29012b6b257fSDimitry Andric
29022b6b257fSDimitry Andric if (CGM.getCodeGenOpts().SanitizeTrap.has(M)) {
2903b60736ecSDimitry Andric EmitTrapCheck(TypeTest, SanitizerHandler::CFICheckFail);
29042b6b257fSDimitry Andric return;
29052b6b257fSDimitry Andric }
29062b6b257fSDimitry Andric
29072b6b257fSDimitry Andric llvm::Value *AllVtables = llvm::MetadataAsValue::get(
29082b6b257fSDimitry Andric CGM.getLLVMContext(),
29092b6b257fSDimitry Andric llvm::MDString::get(CGM.getLLVMContext(), "all-vtables"));
29102b6b257fSDimitry Andric llvm::Value *ValidVtable = Builder.CreateCall(
2911b1c73532SDimitry Andric CGM.getIntrinsic(llvm::Intrinsic::type_test), {VTable, AllVtables});
2912bab175ecSDimitry Andric EmitCheck(std::make_pair(TypeTest, M), SanitizerHandler::CFICheckFail,
2913b1c73532SDimitry Andric StaticData, {VTable, ValidVtable});
29142b6b257fSDimitry Andric }
29152b6b257fSDimitry Andric
ShouldEmitVTableTypeCheckedLoad(const CXXRecordDecl * RD)29162b6b257fSDimitry Andric bool CodeGenFunction::ShouldEmitVTableTypeCheckedLoad(const CXXRecordDecl *RD) {
29172b6b257fSDimitry Andric if (!CGM.getCodeGenOpts().WholeProgramVTables ||
29182b6b257fSDimitry Andric !CGM.HasHiddenLTOVisibility(RD))
29192b6b257fSDimitry Andric return false;
29202b6b257fSDimitry Andric
2921519fc96cSDimitry Andric if (CGM.getCodeGenOpts().VirtualFunctionElimination)
2922519fc96cSDimitry Andric return true;
2923519fc96cSDimitry Andric
2924519fc96cSDimitry Andric if (!SanOpts.has(SanitizerKind::CFIVCall) ||
2925519fc96cSDimitry Andric !CGM.getCodeGenOpts().SanitizeTrap.has(SanitizerKind::CFIVCall))
2926519fc96cSDimitry Andric return false;
2927519fc96cSDimitry Andric
29282b6b257fSDimitry Andric std::string TypeName = RD->getQualifiedNameAsString();
2929344a3780SDimitry Andric return !getContext().getNoSanitizeList().containsType(SanitizerKind::CFIVCall,
2930344a3780SDimitry Andric TypeName);
29312b6b257fSDimitry Andric }
29322b6b257fSDimitry Andric
EmitVTableTypeCheckedLoad(const CXXRecordDecl * RD,llvm::Value * VTable,llvm::Type * VTableTy,uint64_t VTableByteOffset)29332b6b257fSDimitry Andric llvm::Value *CodeGenFunction::EmitVTableTypeCheckedLoad(
2934145449b1SDimitry Andric const CXXRecordDecl *RD, llvm::Value *VTable, llvm::Type *VTableTy,
2935145449b1SDimitry Andric uint64_t VTableByteOffset) {
29362b6b257fSDimitry Andric SanitizerScope SanScope(this);
29372b6b257fSDimitry Andric
29382b6b257fSDimitry Andric EmitSanitizerStatReport(llvm::SanStat_CFI_VCall);
29392b6b257fSDimitry Andric
29402b6b257fSDimitry Andric llvm::Metadata *MD =
29412b6b257fSDimitry Andric CGM.CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0));
29422b6b257fSDimitry Andric llvm::Value *TypeId = llvm::MetadataAsValue::get(CGM.getLLVMContext(), MD);
29432b6b257fSDimitry Andric
29442b6b257fSDimitry Andric llvm::Value *CheckedLoad = Builder.CreateCall(
29452b6b257fSDimitry Andric CGM.getIntrinsic(llvm::Intrinsic::type_checked_load),
2946b1c73532SDimitry Andric {VTable, llvm::ConstantInt::get(Int32Ty, VTableByteOffset), TypeId});
29472b6b257fSDimitry Andric llvm::Value *CheckResult = Builder.CreateExtractValue(CheckedLoad, 1);
29482b6b257fSDimitry Andric
2949519fc96cSDimitry Andric std::string TypeName = RD->getQualifiedNameAsString();
2950519fc96cSDimitry Andric if (SanOpts.has(SanitizerKind::CFIVCall) &&
2951344a3780SDimitry Andric !getContext().getNoSanitizeList().containsType(SanitizerKind::CFIVCall,
2952344a3780SDimitry Andric TypeName)) {
29532b6b257fSDimitry Andric EmitCheck(std::make_pair(CheckResult, SanitizerKind::CFIVCall),
2954519fc96cSDimitry Andric SanitizerHandler::CFICheckFail, {}, {});
2955519fc96cSDimitry Andric }
29562b6b257fSDimitry Andric
29576f8fc217SDimitry Andric return Builder.CreateBitCast(Builder.CreateExtractValue(CheckedLoad, 0),
2958145449b1SDimitry Andric VTableTy);
29595e20cdd8SDimitry Andric }
296029cafa66SDimitry Andric
EmitForwardingCallToLambda(const CXXMethodDecl * callOperator,CallArgList & callArgs,const CGFunctionInfo * calleeFnInfo,llvm::Constant * calleePtr)2961bfef3995SDimitry Andric void CodeGenFunction::EmitForwardingCallToLambda(
2962b1c73532SDimitry Andric const CXXMethodDecl *callOperator, CallArgList &callArgs,
2963b1c73532SDimitry Andric const CGFunctionInfo *calleeFnInfo, llvm::Constant *calleePtr) {
2964dbe13110SDimitry Andric // Get the address of the call operator.
2965b1c73532SDimitry Andric if (!calleeFnInfo)
2966b1c73532SDimitry Andric calleeFnInfo = &CGM.getTypes().arrangeCXXMethodDeclaration(callOperator);
2967b1c73532SDimitry Andric
2968b1c73532SDimitry Andric if (!calleePtr)
2969b1c73532SDimitry Andric calleePtr =
297056d91b49SDimitry Andric CGM.GetAddrOfFunction(GlobalDecl(callOperator),
2971b1c73532SDimitry Andric CGM.getTypes().GetFunctionType(*calleeFnInfo));
2972dbe13110SDimitry Andric
297356d91b49SDimitry Andric // Prepare the return slot.
297456d91b49SDimitry Andric const FunctionProtoType *FPT =
297556d91b49SDimitry Andric callOperator->getType()->castAs<FunctionProtoType>();
29769f4dbff6SDimitry Andric QualType resultType = FPT->getReturnType();
297756d91b49SDimitry Andric ReturnValueSlot returnSlot;
297856d91b49SDimitry Andric if (!resultType->isVoidType() &&
2979b1c73532SDimitry Andric calleeFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect &&
2980b1c73532SDimitry Andric !hasScalarEvaluationKind(calleeFnInfo->getReturnType()))
2981cfca06d7SDimitry Andric returnSlot =
2982cfca06d7SDimitry Andric ReturnValueSlot(ReturnValue, resultType.isVolatileQualified(),
2983cfca06d7SDimitry Andric /*IsUnused=*/false, /*IsExternallyDestructed=*/true);
298456d91b49SDimitry Andric
298556d91b49SDimitry Andric // We don't need to separately arrange the call arguments because
298656d91b49SDimitry Andric // the call can't be variadic anyway --- it's impossible to forward
298756d91b49SDimitry Andric // variadic arguments.
2988dbe13110SDimitry Andric
2989dbe13110SDimitry Andric // Now emit our call.
2990676fbe81SDimitry Andric auto callee = CGCallee::forDirect(calleePtr, GlobalDecl(callOperator));
2991b1c73532SDimitry Andric RValue RV = EmitCall(*calleeFnInfo, callee, returnSlot, callArgs);
2992dbe13110SDimitry Andric
299356d91b49SDimitry Andric // If necessary, copy the returned value into the slot.
2994461a67faSDimitry Andric if (!resultType->isVoidType() && returnSlot.isNull()) {
2995461a67faSDimitry Andric if (getLangOpts().ObjCAutoRefCount && resultType->isObjCRetainableType()) {
2996461a67faSDimitry Andric RV = RValue::get(EmitARCRetainAutoreleasedReturnValue(RV.getScalarVal()));
2997461a67faSDimitry Andric }
299856d91b49SDimitry Andric EmitReturnOfRValue(RV, resultType);
2999461a67faSDimitry Andric } else
3000809500fcSDimitry Andric EmitBranchThroughCleanup(ReturnBlock);
3001dbe13110SDimitry Andric }
3002dbe13110SDimitry Andric
EmitLambdaBlockInvokeBody()3003dbe13110SDimitry Andric void CodeGenFunction::EmitLambdaBlockInvokeBody() {
3004dbe13110SDimitry Andric const BlockDecl *BD = BlockInfo->getBlockDecl();
3005dbe13110SDimitry Andric const VarDecl *variable = BD->capture_begin()->getVariable();
3006dbe13110SDimitry Andric const CXXRecordDecl *Lambda = variable->getType()->getAsCXXRecordDecl();
3007461a67faSDimitry Andric const CXXMethodDecl *CallOp = Lambda->getLambdaCallOperator();
3008461a67faSDimitry Andric
3009461a67faSDimitry Andric if (CallOp->isVariadic()) {
3010461a67faSDimitry Andric // FIXME: Making this work correctly is nasty because it requires either
3011461a67faSDimitry Andric // cloning the body of the call operator or making the call operator
3012461a67faSDimitry Andric // forward.
3013461a67faSDimitry Andric CGM.ErrorUnsupported(CurCodeDecl, "lambda conversion to variadic function");
3014461a67faSDimitry Andric return;
3015461a67faSDimitry Andric }
3016dbe13110SDimitry Andric
3017dbe13110SDimitry Andric // Start building arguments for forwarding call
3018dbe13110SDimitry Andric CallArgList CallArgs;
3019dbe13110SDimitry Andric
3020dbe13110SDimitry Andric QualType ThisType = getContext().getPointerType(getContext().getRecordType(Lambda));
3021676fbe81SDimitry Andric Address ThisPtr = GetAddrOfBlockDecl(variable);
3022ac9a064cSDimitry Andric CallArgs.add(RValue::get(getAsNaturalPointerTo(ThisPtr, ThisType)), ThisType);
3023dbe13110SDimitry Andric
3024dbe13110SDimitry Andric // Add the rest of the parameters.
3025e3b55780SDimitry Andric for (auto *param : BD->parameters())
3026676fbe81SDimitry Andric EmitDelegateCallArg(CallArgs, param, param->getBeginLoc());
30279f4dbff6SDimitry Andric
3028bfef3995SDimitry Andric assert(!Lambda->isGenericLambda() &&
3029bfef3995SDimitry Andric "generic lambda interconversion to block not implemented");
3030461a67faSDimitry Andric EmitForwardingCallToLambda(CallOp, CallArgs);
3031dbe13110SDimitry Andric }
3032dbe13110SDimitry Andric
EmitLambdaStaticInvokeBody(const CXXMethodDecl * MD)3033b1c73532SDimitry Andric void CodeGenFunction::EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD) {
3034b1c73532SDimitry Andric if (MD->isVariadic()) {
3035b1c73532SDimitry Andric // FIXME: Making this work correctly is nasty because it requires either
3036b1c73532SDimitry Andric // cloning the body of the call operator or making the call operator
3037b1c73532SDimitry Andric // forward.
3038b1c73532SDimitry Andric CGM.ErrorUnsupported(MD, "lambda conversion to variadic function");
3039b1c73532SDimitry Andric return;
3040b1c73532SDimitry Andric }
3041b1c73532SDimitry Andric
3042dbe13110SDimitry Andric const CXXRecordDecl *Lambda = MD->getParent();
3043dbe13110SDimitry Andric
3044dbe13110SDimitry Andric // Start building arguments for forwarding call
3045dbe13110SDimitry Andric CallArgList CallArgs;
3046dbe13110SDimitry Andric
3047e3b55780SDimitry Andric QualType LambdaType = getContext().getRecordType(Lambda);
3048e3b55780SDimitry Andric QualType ThisType = getContext().getPointerType(LambdaType);
3049e3b55780SDimitry Andric Address ThisPtr = CreateMemTemp(LambdaType, "unused.capture");
3050ac9a064cSDimitry Andric CallArgs.add(RValue::get(ThisPtr.emitRawPointer(*this)), ThisType);
3051dbe13110SDimitry Andric
3052b1c73532SDimitry Andric EmitLambdaDelegatingInvokeBody(MD, CallArgs);
3053b1c73532SDimitry Andric }
3054b1c73532SDimitry Andric
EmitLambdaDelegatingInvokeBody(const CXXMethodDecl * MD,CallArgList & CallArgs)3055b1c73532SDimitry Andric void CodeGenFunction::EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD,
3056b1c73532SDimitry Andric CallArgList &CallArgs) {
3057b1c73532SDimitry Andric // Add the rest of the forwarded parameters.
3058e3b55780SDimitry Andric for (auto *Param : MD->parameters())
3059676fbe81SDimitry Andric EmitDelegateCallArg(CallArgs, Param, Param->getBeginLoc());
30609f4dbff6SDimitry Andric
3061b1c73532SDimitry Andric const CXXRecordDecl *Lambda = MD->getParent();
3062bfef3995SDimitry Andric const CXXMethodDecl *CallOp = Lambda->getLambdaCallOperator();
3063bfef3995SDimitry Andric // For a generic lambda, find the corresponding call operator specialization
3064bfef3995SDimitry Andric // to which the call to the static-invoker shall be forwarded.
3065bfef3995SDimitry Andric if (Lambda->isGenericLambda()) {
3066bfef3995SDimitry Andric assert(MD->isFunctionTemplateSpecialization());
3067bfef3995SDimitry Andric const TemplateArgumentList *TAL = MD->getTemplateSpecializationArgs();
3068bfef3995SDimitry Andric FunctionTemplateDecl *CallOpTemplate = CallOp->getDescribedFunctionTemplate();
30699f4dbff6SDimitry Andric void *InsertPos = nullptr;
3070bfef3995SDimitry Andric FunctionDecl *CorrespondingCallOpSpecialization =
30719f4dbff6SDimitry Andric CallOpTemplate->findSpecialization(TAL->asArray(), InsertPos);
3072bfef3995SDimitry Andric assert(CorrespondingCallOpSpecialization);
3073bfef3995SDimitry Andric CallOp = cast<CXXMethodDecl>(CorrespondingCallOpSpecialization);
3074bfef3995SDimitry Andric }
3075b1c73532SDimitry Andric
3076b1c73532SDimitry Andric // Special lambda forwarding when there are inalloca parameters.
3077b1c73532SDimitry Andric if (hasInAllocaArg(MD)) {
3078b1c73532SDimitry Andric const CGFunctionInfo *ImplFnInfo = nullptr;
3079b1c73532SDimitry Andric llvm::Function *ImplFn = nullptr;
3080b1c73532SDimitry Andric EmitLambdaInAllocaImplFn(CallOp, &ImplFnInfo, &ImplFn);
3081b1c73532SDimitry Andric
3082b1c73532SDimitry Andric EmitForwardingCallToLambda(CallOp, CallArgs, ImplFnInfo, ImplFn);
3083b1c73532SDimitry Andric return;
3084b1c73532SDimitry Andric }
3085b1c73532SDimitry Andric
3086bfef3995SDimitry Andric EmitForwardingCallToLambda(CallOp, CallArgs);
3087dbe13110SDimitry Andric }
3088dbe13110SDimitry Andric
EmitLambdaInAllocaCallOpBody(const CXXMethodDecl * MD)3089b1c73532SDimitry Andric void CodeGenFunction::EmitLambdaInAllocaCallOpBody(const CXXMethodDecl *MD) {
3090dbe13110SDimitry Andric if (MD->isVariadic()) {
3091dbe13110SDimitry Andric // FIXME: Making this work correctly is nasty because it requires either
3092dbe13110SDimitry Andric // cloning the body of the call operator or making the call operator forward.
3093dbe13110SDimitry Andric CGM.ErrorUnsupported(MD, "lambda conversion to variadic function");
3094dbe13110SDimitry Andric return;
3095dbe13110SDimitry Andric }
3096dbe13110SDimitry Andric
3097b1c73532SDimitry Andric // Forward %this argument.
3098b1c73532SDimitry Andric CallArgList CallArgs;
3099b1c73532SDimitry Andric QualType LambdaType = getContext().getRecordType(MD->getParent());
3100b1c73532SDimitry Andric QualType ThisType = getContext().getPointerType(LambdaType);
3101b1c73532SDimitry Andric llvm::Value *ThisArg = CurFn->getArg(0);
3102b1c73532SDimitry Andric CallArgs.add(RValue::get(ThisArg), ThisType);
3103b1c73532SDimitry Andric
3104b1c73532SDimitry Andric EmitLambdaDelegatingInvokeBody(MD, CallArgs);
3105b1c73532SDimitry Andric }
3106b1c73532SDimitry Andric
EmitLambdaInAllocaImplFn(const CXXMethodDecl * CallOp,const CGFunctionInfo ** ImplFnInfo,llvm::Function ** ImplFn)3107b1c73532SDimitry Andric void CodeGenFunction::EmitLambdaInAllocaImplFn(
3108b1c73532SDimitry Andric const CXXMethodDecl *CallOp, const CGFunctionInfo **ImplFnInfo,
3109b1c73532SDimitry Andric llvm::Function **ImplFn) {
3110b1c73532SDimitry Andric const CGFunctionInfo &FnInfo =
3111b1c73532SDimitry Andric CGM.getTypes().arrangeCXXMethodDeclaration(CallOp);
3112b1c73532SDimitry Andric llvm::Function *CallOpFn =
3113b1c73532SDimitry Andric cast<llvm::Function>(CGM.GetAddrOfFunction(GlobalDecl(CallOp)));
3114b1c73532SDimitry Andric
3115b1c73532SDimitry Andric // Emit function containing the original call op body. __invoke will delegate
3116b1c73532SDimitry Andric // to this function.
3117b1c73532SDimitry Andric SmallVector<CanQualType, 4> ArgTypes;
3118b1c73532SDimitry Andric for (auto I = FnInfo.arg_begin(); I != FnInfo.arg_end(); ++I)
3119b1c73532SDimitry Andric ArgTypes.push_back(I->type);
3120b1c73532SDimitry Andric *ImplFnInfo = &CGM.getTypes().arrangeLLVMFunctionInfo(
3121b1c73532SDimitry Andric FnInfo.getReturnType(), FnInfoOpts::IsDelegateCall, ArgTypes,
3122b1c73532SDimitry Andric FnInfo.getExtInfo(), {}, FnInfo.getRequiredArgs());
3123b1c73532SDimitry Andric
3124b1c73532SDimitry Andric // Create mangled name as if this was a method named __impl. If for some
3125b1c73532SDimitry Andric // reason the name doesn't look as expected then just tack __impl to the
3126b1c73532SDimitry Andric // front.
3127b1c73532SDimitry Andric // TODO: Use the name mangler to produce the right name instead of using
3128b1c73532SDimitry Andric // string replacement.
3129b1c73532SDimitry Andric StringRef CallOpName = CallOpFn->getName();
3130b1c73532SDimitry Andric std::string ImplName;
3131b1c73532SDimitry Andric if (size_t Pos = CallOpName.find_first_of("<lambda"))
3132b1c73532SDimitry Andric ImplName = ("?__impl@" + CallOpName.drop_front(Pos)).str();
3133b1c73532SDimitry Andric else
3134b1c73532SDimitry Andric ImplName = ("__impl" + CallOpName).str();
3135b1c73532SDimitry Andric
3136b1c73532SDimitry Andric llvm::Function *Fn = CallOpFn->getParent()->getFunction(ImplName);
3137b1c73532SDimitry Andric if (!Fn) {
3138b1c73532SDimitry Andric Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(**ImplFnInfo),
3139b1c73532SDimitry Andric llvm::GlobalValue::InternalLinkage, ImplName,
3140b1c73532SDimitry Andric CGM.getModule());
3141b1c73532SDimitry Andric CGM.SetInternalFunctionAttributes(CallOp, Fn, **ImplFnInfo);
3142b1c73532SDimitry Andric
3143b1c73532SDimitry Andric const GlobalDecl &GD = GlobalDecl(CallOp);
3144b1c73532SDimitry Andric const auto *D = cast<FunctionDecl>(GD.getDecl());
3145b1c73532SDimitry Andric CodeGenFunction(CGM).GenerateCode(GD, Fn, **ImplFnInfo);
3146b1c73532SDimitry Andric CGM.SetLLVMFunctionAttributesForDefinition(D, Fn);
3147b1c73532SDimitry Andric }
3148b1c73532SDimitry Andric *ImplFn = Fn;
314929cafa66SDimitry Andric }
3150