[clang] 6efff59 - [UBSAN] [NFC] resolve clang-format errors (#175716)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Jan 18 21:39:14 PST 2026
Author: VASU SHARMA
Date: 2026-01-19T11:09:09+05:30
New Revision: 6efff59302332e9534c0c060e5e5c046dee5f8ca
URL: https://github.com/llvm/llvm-project/commit/6efff59302332e9534c0c060e5e5c046dee5f8ca
DIFF: https://github.com/llvm/llvm-project/commit/6efff59302332e9534c0c060e5e5c046dee5f8ca.diff
LOG: [UBSAN] [NFC] resolve clang-format errors (#175716)
PR to resolve clang-format errors in the files:
- `clang/lib/CodeGen/CGExprAgg.cpp`
- `clang/lib/CodeGen/CGExprCXX.cpp`
- `clang/lib/CodeGen/CGClass.cpp`
Co-authored-by: vasu-ibm <Vasu.Sharma2 at ibm.com>
Added:
Modified:
clang/lib/CodeGen/CGClass.cpp
clang/lib/CodeGen/CGExprAgg.cpp
clang/lib/CodeGen/CGExprCXX.cpp
Removed:
################################################################################
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index a5096506f0ab1..e91dde147a889 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -190,10 +190,9 @@ CharUnits CodeGenModule::computeNonVirtualBaseClassOffset(
return Offset;
}
-llvm::Constant *
-CodeGenModule::GetNonVirtualBaseClassOffset(const CXXRecordDecl *ClassDecl,
- CastExpr::path_const_iterator PathBegin,
- CastExpr::path_const_iterator PathEnd) {
+llvm::Constant *CodeGenModule::GetNonVirtualBaseClassOffset(
+ const CXXRecordDecl *ClassDecl, CastExpr::path_const_iterator PathBegin,
+ CastExpr::path_const_iterator PathEnd) {
assert(PathBegin != PathEnd && "Base path should not be empty!");
CharUnits Offset =
@@ -212,11 +211,9 @@ CodeGenModule::GetNonVirtualBaseClassOffset(const CXXRecordDecl *ClassDecl,
/// when the type is known to be complete (e.g. in complete destructors).
///
/// The object pointed to by 'This' is assumed to be non-null.
-Address
-CodeGenFunction::GetAddressOfDirectBaseInCompleteClass(Address This,
- const CXXRecordDecl *Derived,
- const CXXRecordDecl *Base,
- bool BaseIsVirtual) {
+Address CodeGenFunction::GetAddressOfDirectBaseInCompleteClass(
+ Address This, const CXXRecordDecl *Derived, const CXXRecordDecl *Base,
+ bool BaseIsVirtual) {
// 'this' must be a pointer (in some address space) to Derived.
assert(This.getElementType() == ConvertType(Derived));
@@ -238,12 +235,10 @@ CodeGenFunction::GetAddressOfDirectBaseInCompleteClass(Address This,
return V.withElementType(ConvertType(Base));
}
-static Address
-ApplyNonVirtualAndVirtualOffset(CodeGenFunction &CGF, Address addr,
- CharUnits nonVirtualOffset,
- llvm::Value *virtualOffset,
- const CXXRecordDecl *derivedClass,
- const CXXRecordDecl *nearestVBase) {
+static Address ApplyNonVirtualAndVirtualOffset(
+ CodeGenFunction &CGF, Address addr, CharUnits nonVirtualOffset,
+ llvm::Value *virtualOffset, const CXXRecordDecl *derivedClass,
+ const CXXRecordDecl *nearestVBase) {
// Assert that we have something to do.
assert(!nonVirtualOffset.isZero() || virtualOffset != nullptr);
@@ -273,8 +268,8 @@ ApplyNonVirtualAndVirtualOffset(CodeGenFunction &CGF, Address addr,
CharUnits alignment;
if (virtualOffset) {
assert(nearestVBase && "virtual offset without vbase?");
- alignment = CGF.CGM.getVBaseAlignment(addr.getAlignment(),
- derivedClass, nearestVBase);
+ alignment = CGF.CGM.getVBaseAlignment(addr.getAlignment(), derivedClass,
+ nearestVBase);
} else {
alignment = addr.getAlignment();
}
@@ -390,19 +385,17 @@ Address CodeGenFunction::GetAddressOfBaseClass(
return Value;
}
-Address
-CodeGenFunction::GetAddressOfDerivedClass(Address BaseAddr,
- const CXXRecordDecl *Derived,
- CastExpr::path_const_iterator PathBegin,
- CastExpr::path_const_iterator PathEnd,
- bool NullCheckValue) {
+Address CodeGenFunction::GetAddressOfDerivedClass(
+ Address BaseAddr, const CXXRecordDecl *Derived,
+ CastExpr::path_const_iterator PathBegin,
+ CastExpr::path_const_iterator PathEnd, bool NullCheckValue) {
assert(PathBegin != PathEnd && "Base path should not be empty!");
CanQualType DerivedTy = getContext().getCanonicalTagType(Derived);
llvm::Type *DerivedValueTy = ConvertType(DerivedTy);
llvm::Value *NonVirtualOffset =
- CGM.GetNonVirtualBaseClassOffset(Derived, PathBegin, PathEnd);
+ CGM.GetNonVirtualBaseClassOffset(Derived, PathBegin, PathEnd);
if (!NonVirtualOffset) {
// No offset, we can just cast back.
@@ -475,12 +468,11 @@ llvm::Value *CodeGenFunction::GetVTTParameter(GlobalDecl GD,
SubVTTIndex = 0;
} else {
const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
- CharUnits BaseOffset = ForVirtualBase ?
- Layout.getVBaseClassOffset(Base) :
- Layout.getBaseClassOffset(Base);
+ CharUnits BaseOffset = ForVirtualBase ? Layout.getVBaseClassOffset(Base)
+ : Layout.getBaseClassOffset(Base);
SubVTTIndex =
- CGM.getVTables().getSubVTTIndex(RD, BaseSubobject(Base, BaseOffset));
+ CGM.getVTables().getSubVTTIndex(RD, BaseSubobject(Base, BaseOffset));
assert(SubVTTIndex != 0 && "Sub-VTT index must be greater than zero!");
}
@@ -491,52 +483,51 @@ llvm::Value *CodeGenFunction::GetVTTParameter(GlobalDecl GD,
} else {
// We're the complete constructor, so get the VTT by name.
llvm::GlobalValue *VTT = CGM.getVTables().GetAddrOfVTT(RD);
- return Builder.CreateConstInBoundsGEP2_64(
- VTT->getValueType(), VTT, 0, SubVTTIndex);
+ return Builder.CreateConstInBoundsGEP2_64(VTT->getValueType(), VTT, 0,
+ SubVTTIndex);
}
}
namespace {
- /// Call the destructor for a direct base class.
- struct CallBaseDtor final : EHScopeStack::Cleanup {
- const CXXRecordDecl *BaseClass;
- bool BaseIsVirtual;
- CallBaseDtor(const CXXRecordDecl *Base, bool BaseIsVirtual)
+/// Call the destructor for a direct base class.
+struct CallBaseDtor final : EHScopeStack::Cleanup {
+ const CXXRecordDecl *BaseClass;
+ bool BaseIsVirtual;
+ CallBaseDtor(const CXXRecordDecl *Base, bool BaseIsVirtual)
: BaseClass(Base), BaseIsVirtual(BaseIsVirtual) {}
- void Emit(CodeGenFunction &CGF, Flags flags) override {
- const CXXRecordDecl *DerivedClass =
+ void Emit(CodeGenFunction &CGF, Flags flags) override {
+ const CXXRecordDecl *DerivedClass =
cast<CXXMethodDecl>(CGF.CurCodeDecl)->getParent();
- const CXXDestructorDecl *D = BaseClass->getDestructor();
- // We are already inside a destructor, so presumably the object being
- // destroyed should have the expected type.
- QualType ThisTy = D->getFunctionObjectParameterType();
- Address Addr =
- CGF.GetAddressOfDirectBaseInCompleteClass(CGF.LoadCXXThisAddress(),
- DerivedClass, BaseClass,
- BaseIsVirtual);
- CGF.EmitCXXDestructorCall(D, Dtor_Base, BaseIsVirtual,
- /*Delegating=*/false, Addr, ThisTy);
- }
- };
+ const CXXDestructorDecl *D = BaseClass->getDestructor();
+ // We are already inside a destructor, so presumably the object being
+ // destroyed should have the expected type.
+ QualType ThisTy = D->getFunctionObjectParameterType();
+ Address Addr = CGF.GetAddressOfDirectBaseInCompleteClass(
+ CGF.LoadCXXThisAddress(), DerivedClass, BaseClass, BaseIsVirtual);
+ CGF.EmitCXXDestructorCall(D, Dtor_Base, BaseIsVirtual,
+ /*Delegating=*/false, Addr, ThisTy);
+ }
+};
- /// A visitor which checks whether an initializer uses 'this' in a
- /// way which requires the vtable to be properly set.
- struct DynamicThisUseChecker : ConstEvaluatedExprVisitor<DynamicThisUseChecker> {
- typedef ConstEvaluatedExprVisitor<DynamicThisUseChecker> super;
+/// A visitor which checks whether an initializer uses 'this' in a
+/// way which requires the vtable to be properly set.
+struct DynamicThisUseChecker
+ : ConstEvaluatedExprVisitor<DynamicThisUseChecker> {
+ typedef ConstEvaluatedExprVisitor<DynamicThisUseChecker> super;
- bool UsesThis;
+ bool UsesThis;
- DynamicThisUseChecker(const ASTContext &C) : super(C), UsesThis(false) {}
+ DynamicThisUseChecker(const ASTContext &C) : super(C), UsesThis(false) {}
- // Black-list all explicit and implicit references to 'this'.
- //
- // Do we need to worry about external references to 'this' derived
- // from arbitrary code? If so, then anything which runs arbitrary
- // external code might potentially access the vtable.
- void VisitCXXThisExpr(const CXXThisExpr *E) { UsesThis = true; }
- };
+ // Black-list all explicit and implicit references to 'this'.
+ //
+ // Do we need to worry about external references to 'this' derived
+ // from arbitrary code? If so, then anything which runs arbitrary
+ // external code might potentially access the vtable.
+ void VisitCXXThisExpr(const CXXThisExpr *E) { UsesThis = true; }
+};
} // end anonymous namespace
static bool BaseInitializerUsesThis(ASTContext &C, const Expr *Init) {
@@ -548,8 +539,7 @@ static bool BaseInitializerUsesThis(ASTContext &C, const Expr *Init) {
static void EmitBaseInitializer(CodeGenFunction &CGF,
const CXXRecordDecl *ClassDecl,
CXXCtorInitializer *BaseInit) {
- assert(BaseInit->isBaseInitializer() &&
- "Must have base initializer!");
+ assert(BaseInit->isBaseInitializer() && "Must have base initializer!");
Address ThisPtr = CGF.LoadCXXThisAddress();
@@ -565,17 +555,12 @@ static void EmitBaseInitializer(CodeGenFunction &CGF,
// We can pretend to be a complete class because it only matters for
// virtual bases, and we only do virtual bases for complete ctors.
- Address V =
- CGF.GetAddressOfDirectBaseInCompleteClass(ThisPtr, ClassDecl,
- BaseClassDecl,
- isBaseVirtual);
- AggValueSlot AggSlot =
- AggValueSlot::forAddr(
- V, Qualifiers(),
- AggValueSlot::IsDestructed,
- AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsNotAliased,
- CGF.getOverlapForBaseInit(ClassDecl, BaseClassDecl, isBaseVirtual));
+ Address V = CGF.GetAddressOfDirectBaseInCompleteClass(
+ ThisPtr, ClassDecl, BaseClassDecl, isBaseVirtual);
+ AggValueSlot AggSlot = AggValueSlot::forAddr(
+ V, Qualifiers(), AggValueSlot::IsDestructed,
+ AggValueSlot::DoesNotNeedGCBarriers, AggValueSlot::IsNotAliased,
+ CGF.getOverlapForBaseInit(ClassDecl, BaseClassDecl, isBaseVirtual));
CGF.EmitAggExpr(BaseInit->getInit(), AggSlot);
@@ -649,8 +634,8 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
// AST and perform the copy we know is equivalent.
// FIXME: This is hacky at best... if we had a bit more explicit information
// in the AST, we could generalize it more easily.
- const ConstantArrayType *Array
- = CGF.getContext().getAsConstantArrayType(FieldType);
+ const ConstantArrayType *Array =
+ CGF.getContext().getAsConstantArrayType(FieldType);
if (Array && Constructor->isDefaulted() &&
Constructor->isCopyOrMoveConstructor()) {
QualType BaseElementTy = CGF.getContext().getBaseElementType(Array);
@@ -659,13 +644,14 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
(CE && isMemcpyEquivalentSpecialMember(CE->getConstructor()))) {
unsigned SrcArgIndex =
CGF.CGM.getCXXABI().getSrcArgforCopyCtor(Constructor, Args);
- llvm::Value *SrcPtr
- = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(Args[SrcArgIndex]));
+ llvm::Value *SrcPtr =
+ CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(Args[SrcArgIndex]));
LValue ThisRHSLV = CGF.MakeNaturalAlignAddrLValue(SrcPtr, RecordTy);
LValue Src = CGF.EmitLValueForFieldInitialization(ThisRHSLV, Field);
// Copy the aggregate.
- CGF.EmitAggregateCopy(LHS, Src, FieldType, CGF.getOverlapForFieldInit(Field),
+ CGF.EmitAggregateCopy(LHS, Src, FieldType,
+ CGF.getOverlapForFieldInit(Field),
LHS.isVolatileQualified());
// Ensure that we destroy the objects if an exception is thrown later in
// the constructor.
@@ -770,7 +756,8 @@ void CodeGenFunction::EmitAsanPrologueOrEpilogue(bool Prologue) {
const CXXRecordDecl *ClassDecl =
Prologue ? cast<CXXConstructorDecl>(CurGD.getDecl())->getParent()
: cast<CXXDestructorDecl>(CurGD.getDecl())->getParent();
- if (!ClassDecl->mayInsertExtraPadding()) return;
+ if (!ClassDecl->mayInsertExtraPadding())
+ return;
struct SizeAndOffset {
uint64_t Size;
@@ -796,13 +783,13 @@ void CodeGenFunction::EmitAsanPrologueOrEpilogue(bool Prologue) {
NumFields++;
}
assert(NumFields == SSV.size());
- if (SSV.size() <= 1) return;
+ if (SSV.size() <= 1)
+ return;
// We will insert calls to __asan_* run-time functions.
// LLVM AddressSanitizer pass may decide to inline them later.
llvm::Type *Args[2] = {IntPtrTy, IntPtrTy};
- llvm::FunctionType *FTy =
- llvm::FunctionType::get(CGM.VoidTy, Args, false);
+ llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, Args, false);
llvm::FunctionCallee F = CGM.CreateRuntimeFunction(
FTy, Prologue ? "__asan_poison_intra_object_redzone"
: "__asan_unpoison_intra_object_redzone");
@@ -883,377 +870,370 @@ void CodeGenFunction::EmitConstructorBody(FunctionArgList &Args) {
}
namespace {
- /// RAII object to indicate that codegen is copying the value representation
- /// instead of the object representation. Useful when copying a struct or
- /// class which has uninitialized members and we're only performing
- /// lvalue-to-rvalue conversion on the object but not its members.
- class CopyingValueRepresentation {
- public:
- explicit CopyingValueRepresentation(CodeGenFunction &CGF)
- : CGF(CGF), OldSanOpts(CGF.SanOpts) {
- CGF.SanOpts.set(SanitizerKind::Bool, false);
- CGF.SanOpts.set(SanitizerKind::Enum, false);
- }
- ~CopyingValueRepresentation() {
- CGF.SanOpts = OldSanOpts;
- }
- private:
- CodeGenFunction &CGF;
- SanitizerSet OldSanOpts;
- };
+/// RAII object to indicate that codegen is copying the value representation
+/// instead of the object representation. Useful when copying a struct or
+/// class which has uninitialized members and we're only performing
+/// lvalue-to-rvalue conversion on the object but not its members.
+class CopyingValueRepresentation {
+public:
+ explicit CopyingValueRepresentation(CodeGenFunction &CGF)
+ : CGF(CGF), OldSanOpts(CGF.SanOpts) {
+ CGF.SanOpts.set(SanitizerKind::Bool, false);
+ CGF.SanOpts.set(SanitizerKind::Enum, false);
+ }
+ ~CopyingValueRepresentation() { CGF.SanOpts = OldSanOpts; }
+
+private:
+ CodeGenFunction &CGF;
+ SanitizerSet OldSanOpts;
+};
} // end anonymous namespace
namespace {
- class FieldMemcpyizer {
- public:
- FieldMemcpyizer(CodeGenFunction &CGF, const CXXRecordDecl *ClassDecl,
- const VarDecl *SrcRec)
+class FieldMemcpyizer {
+public:
+ FieldMemcpyizer(CodeGenFunction &CGF, const CXXRecordDecl *ClassDecl,
+ const VarDecl *SrcRec)
: CGF(CGF), ClassDecl(ClassDecl), SrcRec(SrcRec),
RecLayout(CGF.getContext().getASTRecordLayout(ClassDecl)),
FirstField(nullptr), LastField(nullptr), FirstFieldOffset(0),
LastFieldOffset(0), LastAddedFieldIndex(0) {}
- bool isMemcpyableField(FieldDecl *F) const {
- // Never memcpy fields when we are adding poisoned paddings.
- if (CGF.getContext().getLangOpts().SanitizeAddressFieldPadding)
- return false;
- Qualifiers Qual = F->getType().getQualifiers();
- if (Qual.hasVolatile() || Qual.hasObjCLifetime())
- return false;
- if (PointerAuthQualifier Q = F->getType().getPointerAuth();
- Q && Q.isAddressDiscriminated())
- return false;
- return true;
- }
-
- void addMemcpyableField(FieldDecl *F) {
- if (isEmptyFieldForLayout(CGF.getContext(), F))
- return;
- if (!FirstField)
- addInitialField(F);
- else
- addNextField(F);
- }
+ bool isMemcpyableField(FieldDecl *F) const {
+ // Never memcpy fields when we are adding poisoned paddings.
+ if (CGF.getContext().getLangOpts().SanitizeAddressFieldPadding)
+ return false;
+ Qualifiers Qual = F->getType().getQualifiers();
+ if (Qual.hasVolatile() || Qual.hasObjCLifetime())
+ return false;
+ if (PointerAuthQualifier Q = F->getType().getPointerAuth();
+ Q && Q.isAddressDiscriminated())
+ return false;
+ return true;
+ }
- CharUnits getMemcpySize(uint64_t FirstByteOffset) const {
- ASTContext &Ctx = CGF.getContext();
- unsigned LastFieldSize =
- LastField->isBitField()
- ? LastField->getBitWidthValue()
- : Ctx.toBits(
- Ctx.getTypeInfoDataSizeInChars(LastField->getType()).Width);
- uint64_t MemcpySizeBits = LastFieldOffset + LastFieldSize -
- FirstByteOffset + Ctx.getCharWidth() - 1;
- CharUnits MemcpySize = Ctx.toCharUnitsFromBits(MemcpySizeBits);
- return MemcpySize;
+ void addMemcpyableField(FieldDecl *F) {
+ if (isEmptyFieldForLayout(CGF.getContext(), F))
+ return;
+ if (!FirstField)
+ addInitialField(F);
+ else
+ addNextField(F);
+ }
+
+ CharUnits getMemcpySize(uint64_t FirstByteOffset) const {
+ ASTContext &Ctx = CGF.getContext();
+ unsigned LastFieldSize =
+ LastField->isBitField()
+ ? LastField->getBitWidthValue()
+ : Ctx.toBits(
+ Ctx.getTypeInfoDataSizeInChars(LastField->getType()).Width);
+ uint64_t MemcpySizeBits = LastFieldOffset + LastFieldSize -
+ FirstByteOffset + Ctx.getCharWidth() - 1;
+ CharUnits MemcpySize = Ctx.toCharUnitsFromBits(MemcpySizeBits);
+ return MemcpySize;
+ }
+
+ void emitMemcpy() {
+ // Give the subclass a chance to bail out if it feels the memcpy isn't
+ // worth it (e.g. Hasn't aggregated enough data).
+ if (!FirstField) {
+ return;
}
- void emitMemcpy() {
- // Give the subclass a chance to bail out if it feels the memcpy isn't
- // worth it (e.g. Hasn't aggregated enough data).
- if (!FirstField) {
- return;
- }
-
- uint64_t FirstByteOffset;
- if (FirstField->isBitField()) {
- const CGRecordLayout &RL =
+ uint64_t FirstByteOffset;
+ if (FirstField->isBitField()) {
+ const CGRecordLayout &RL =
CGF.getTypes().getCGRecordLayout(FirstField->getParent());
- const CGBitFieldInfo &BFInfo = RL.getBitFieldInfo(FirstField);
- // FirstFieldOffset is not appropriate for bitfields,
- // we need to use the storage offset instead.
- FirstByteOffset = CGF.getContext().toBits(BFInfo.StorageOffset);
- } else {
- FirstByteOffset = FirstFieldOffset;
- }
-
- CharUnits MemcpySize = getMemcpySize(FirstByteOffset);
- CanQualType RecordTy = CGF.getContext().getCanonicalTagType(ClassDecl);
- Address ThisPtr = CGF.LoadCXXThisAddress();
- LValue DestLV = CGF.MakeAddrLValue(ThisPtr, RecordTy);
- LValue Dest = CGF.EmitLValueForFieldInitialization(DestLV, FirstField);
- llvm::Value *SrcPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(SrcRec));
- LValue SrcLV = CGF.MakeNaturalAlignAddrLValue(SrcPtr, RecordTy);
- LValue Src = CGF.EmitLValueForFieldInitialization(SrcLV, FirstField);
-
- emitMemcpyIR(
- Dest.isBitField() ? Dest.getBitFieldAddress() : Dest.getAddress(),
- Src.isBitField() ? Src.getBitFieldAddress() : Src.getAddress(),
- MemcpySize);
- reset();
- }
-
- void reset() {
- FirstField = nullptr;
- }
-
- protected:
- CodeGenFunction &CGF;
- const CXXRecordDecl *ClassDecl;
-
- private:
- void emitMemcpyIR(Address DestPtr, Address SrcPtr, CharUnits Size) {
- DestPtr = DestPtr.withElementType(CGF.Int8Ty);
- SrcPtr = SrcPtr.withElementType(CGF.Int8Ty);
- auto *I = CGF.Builder.CreateMemCpy(DestPtr, SrcPtr, Size.getQuantity());
- CGF.addInstToCurrentSourceAtom(I, nullptr);
+ const CGBitFieldInfo &BFInfo = RL.getBitFieldInfo(FirstField);
+ // FirstFieldOffset is not appropriate for bitfields,
+ // we need to use the storage offset instead.
+ FirstByteOffset = CGF.getContext().toBits(BFInfo.StorageOffset);
+ } else {
+ FirstByteOffset = FirstFieldOffset;
}
- void addInitialField(FieldDecl *F) {
+ CharUnits MemcpySize = getMemcpySize(FirstByteOffset);
+ CanQualType RecordTy = CGF.getContext().getCanonicalTagType(ClassDecl);
+ Address ThisPtr = CGF.LoadCXXThisAddress();
+ LValue DestLV = CGF.MakeAddrLValue(ThisPtr, RecordTy);
+ LValue Dest = CGF.EmitLValueForFieldInitialization(DestLV, FirstField);
+ llvm::Value *SrcPtr = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(SrcRec));
+ LValue SrcLV = CGF.MakeNaturalAlignAddrLValue(SrcPtr, RecordTy);
+ LValue Src = CGF.EmitLValueForFieldInitialization(SrcLV, FirstField);
+
+ emitMemcpyIR(Dest.isBitField() ? Dest.getBitFieldAddress()
+ : Dest.getAddress(),
+ Src.isBitField() ? Src.getBitFieldAddress() : Src.getAddress(),
+ MemcpySize);
+ reset();
+ }
+
+ void reset() { FirstField = nullptr; }
+
+protected:
+ CodeGenFunction &CGF;
+ const CXXRecordDecl *ClassDecl;
+
+private:
+ void emitMemcpyIR(Address DestPtr, Address SrcPtr, CharUnits Size) {
+ DestPtr = DestPtr.withElementType(CGF.Int8Ty);
+ SrcPtr = SrcPtr.withElementType(CGF.Int8Ty);
+ auto *I = CGF.Builder.CreateMemCpy(DestPtr, SrcPtr, Size.getQuantity());
+ CGF.addInstToCurrentSourceAtom(I, nullptr);
+ }
+
+ void addInitialField(FieldDecl *F) {
+ FirstField = F;
+ LastField = F;
+ FirstFieldOffset = RecLayout.getFieldOffset(F->getFieldIndex());
+ LastFieldOffset = FirstFieldOffset;
+ LastAddedFieldIndex = F->getFieldIndex();
+ }
+
+ void addNextField(FieldDecl *F) {
+ // For the most part, the following invariant will hold:
+ // F->getFieldIndex() == LastAddedFieldIndex + 1
+ // The one exception is that Sema won't add a copy-initializer for an
+ // unnamed bitfield, which will show up here as a gap in the sequence.
+ assert(F->getFieldIndex() >= LastAddedFieldIndex + 1 &&
+ "Cannot aggregate fields out of order.");
+ LastAddedFieldIndex = F->getFieldIndex();
+
+ // The 'first' and 'last' fields are chosen by offset, rather than field
+ // index. This allows the code to support bitfields, as well as regular
+ // fields.
+ uint64_t FOffset = RecLayout.getFieldOffset(F->getFieldIndex());
+ if (FOffset < FirstFieldOffset) {
FirstField = F;
+ FirstFieldOffset = FOffset;
+ } else if (FOffset >= LastFieldOffset) {
LastField = F;
- FirstFieldOffset = RecLayout.getFieldOffset(F->getFieldIndex());
- LastFieldOffset = FirstFieldOffset;
- LastAddedFieldIndex = F->getFieldIndex();
- }
-
- void addNextField(FieldDecl *F) {
- // For the most part, the following invariant will hold:
- // F->getFieldIndex() == LastAddedFieldIndex + 1
- // The one exception is that Sema won't add a copy-initializer for an
- // unnamed bitfield, which will show up here as a gap in the sequence.
- assert(F->getFieldIndex() >= LastAddedFieldIndex + 1 &&
- "Cannot aggregate fields out of order.");
- LastAddedFieldIndex = F->getFieldIndex();
-
- // The 'first' and 'last' fields are chosen by offset, rather than field
- // index. This allows the code to support bitfields, as well as regular
- // fields.
- uint64_t FOffset = RecLayout.getFieldOffset(F->getFieldIndex());
- if (FOffset < FirstFieldOffset) {
- FirstField = F;
- FirstFieldOffset = FOffset;
- } else if (FOffset >= LastFieldOffset) {
- LastField = F;
- LastFieldOffset = FOffset;
- }
+ LastFieldOffset = FOffset;
}
+ }
- const VarDecl *SrcRec;
- const ASTRecordLayout &RecLayout;
- FieldDecl *FirstField;
- FieldDecl *LastField;
- uint64_t FirstFieldOffset, LastFieldOffset;
- unsigned LastAddedFieldIndex;
- };
+ const VarDecl *SrcRec;
+ const ASTRecordLayout &RecLayout;
+ FieldDecl *FirstField;
+ FieldDecl *LastField;
+ uint64_t FirstFieldOffset, LastFieldOffset;
+ unsigned LastAddedFieldIndex;
+};
+
+class ConstructorMemcpyizer : public FieldMemcpyizer {
+private:
+ /// Get source argument for copy constructor. Returns null if not a copy
+ /// constructor.
+ static const VarDecl *getTrivialCopySource(CodeGenFunction &CGF,
+ const CXXConstructorDecl *CD,
+ FunctionArgList &Args) {
+ if (CD->isCopyOrMoveConstructor() && CD->isDefaulted())
+ return Args[CGF.CGM.getCXXABI().getSrcArgforCopyCtor(CD, Args)];
+ return nullptr;
+ }
- class ConstructorMemcpyizer : public FieldMemcpyizer {
- private:
- /// Get source argument for copy constructor. Returns null if not a copy
- /// constructor.
- static const VarDecl *getTrivialCopySource(CodeGenFunction &CGF,
- const CXXConstructorDecl *CD,
- FunctionArgList &Args) {
- if (CD->isCopyOrMoveConstructor() && CD->isDefaulted())
- return Args[CGF.CGM.getCXXABI().getSrcArgforCopyCtor(CD, Args)];
- return nullptr;
- }
+ // Returns true if a CXXCtorInitializer represents a member initialization
+ // that can be rolled into a memcpy.
+ bool isMemberInitMemcpyable(CXXCtorInitializer *MemberInit) const {
+ if (!MemcpyableCtor)
+ return false;
+ FieldDecl *Field = MemberInit->getMember();
+ assert(Field && "No field for member init.");
+ QualType FieldType = Field->getType();
+ CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(MemberInit->getInit());
- // Returns true if a CXXCtorInitializer represents a member initialization
- // that can be rolled into a memcpy.
- bool isMemberInitMemcpyable(CXXCtorInitializer *MemberInit) const {
- if (!MemcpyableCtor)
- return false;
- FieldDecl *Field = MemberInit->getMember();
- assert(Field && "No field for member init.");
- QualType FieldType = Field->getType();
- CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(MemberInit->getInit());
-
- // Bail out on non-memcpyable, not-trivially-copyable members.
- if (!(CE && isMemcpyEquivalentSpecialMember(CE->getConstructor())) &&
- !(FieldType.isTriviallyCopyableType(CGF.getContext()) ||
- FieldType->isReferenceType()))
- return false;
+ // Bail out on non-memcpyable, not-trivially-copyable members.
+ if (!(CE && isMemcpyEquivalentSpecialMember(CE->getConstructor())) &&
+ !(FieldType.isTriviallyCopyableType(CGF.getContext()) ||
+ FieldType->isReferenceType()))
+ return false;
- // Bail out on volatile fields.
- if (!isMemcpyableField(Field))
- return false;
+ // Bail out on volatile fields.
+ if (!isMemcpyableField(Field))
+ return false;
- // Otherwise we're good.
- return true;
- }
+ // Otherwise we're good.
+ return true;
+ }
- public:
- ConstructorMemcpyizer(CodeGenFunction &CGF, const CXXConstructorDecl *CD,
- FunctionArgList &Args)
- : FieldMemcpyizer(CGF, CD->getParent(), getTrivialCopySource(CGF, CD, Args)),
+public:
+ ConstructorMemcpyizer(CodeGenFunction &CGF, const CXXConstructorDecl *CD,
+ FunctionArgList &Args)
+ : FieldMemcpyizer(CGF, CD->getParent(),
+ getTrivialCopySource(CGF, CD, Args)),
ConstructorDecl(CD),
- MemcpyableCtor(CD->isDefaulted() &&
- CD->isCopyOrMoveConstructor() &&
+ MemcpyableCtor(CD->isDefaulted() && CD->isCopyOrMoveConstructor() &&
CGF.getLangOpts().getGC() == LangOptions::NonGC),
- Args(Args) { }
+ Args(Args) {}
- void addMemberInitializer(CXXCtorInitializer *MemberInit) {
- if (isMemberInitMemcpyable(MemberInit)) {
- AggregatedInits.push_back(MemberInit);
- addMemcpyableField(MemberInit->getMember());
- } else {
- emitAggregatedInits();
- EmitMemberInitializer(CGF, ConstructorDecl->getParent(), MemberInit,
- ConstructorDecl, Args);
- }
+ void addMemberInitializer(CXXCtorInitializer *MemberInit) {
+ if (isMemberInitMemcpyable(MemberInit)) {
+ AggregatedInits.push_back(MemberInit);
+ addMemcpyableField(MemberInit->getMember());
+ } else {
+ emitAggregatedInits();
+ EmitMemberInitializer(CGF, ConstructorDecl->getParent(), MemberInit,
+ ConstructorDecl, Args);
}
+ }
- void emitAggregatedInits() {
- if (AggregatedInits.size() <= 1) {
- // This memcpy is too small to be worthwhile. Fall back on default
- // codegen.
- if (!AggregatedInits.empty()) {
- CopyingValueRepresentation CVR(CGF);
- EmitMemberInitializer(CGF, ConstructorDecl->getParent(),
- AggregatedInits[0], ConstructorDecl, Args);
- AggregatedInits.clear();
- }
- reset();
- return;
+ void emitAggregatedInits() {
+ if (AggregatedInits.size() <= 1) {
+ // This memcpy is too small to be worthwhile. Fall back on default
+ // codegen.
+ if (!AggregatedInits.empty()) {
+ CopyingValueRepresentation CVR(CGF);
+ EmitMemberInitializer(CGF, ConstructorDecl->getParent(),
+ AggregatedInits[0], ConstructorDecl, Args);
+ AggregatedInits.clear();
}
-
- pushEHDestructors();
- ApplyAtomGroup Grp(CGF.getDebugInfo());
- emitMemcpy();
- AggregatedInits.clear();
+ reset();
+ return;
}
- void pushEHDestructors() {
- Address ThisPtr = CGF.LoadCXXThisAddress();
- CanQualType RecordTy = CGF.getContext().getCanonicalTagType(ClassDecl);
- LValue LHS = CGF.MakeAddrLValue(ThisPtr, RecordTy);
-
- for (unsigned i = 0; i < AggregatedInits.size(); ++i) {
- CXXCtorInitializer *MemberInit = AggregatedInits[i];
- QualType FieldType = MemberInit->getAnyMember()->getType();
- QualType::DestructionKind dtorKind = FieldType.isDestructedType();
- if (!CGF.needsEHCleanup(dtorKind))
- continue;
- LValue FieldLHS = LHS;
- EmitLValueForAnyFieldInitialization(CGF, MemberInit, FieldLHS);
- CGF.pushEHDestroy(dtorKind, FieldLHS.getAddress(), FieldType);
- }
- }
+ pushEHDestructors();
+ ApplyAtomGroup Grp(CGF.getDebugInfo());
+ emitMemcpy();
+ AggregatedInits.clear();
+ }
- void finish() {
- emitAggregatedInits();
+ void pushEHDestructors() {
+ Address ThisPtr = CGF.LoadCXXThisAddress();
+ CanQualType RecordTy = CGF.getContext().getCanonicalTagType(ClassDecl);
+ LValue LHS = CGF.MakeAddrLValue(ThisPtr, RecordTy);
+
+ for (unsigned i = 0; i < AggregatedInits.size(); ++i) {
+ CXXCtorInitializer *MemberInit = AggregatedInits[i];
+ QualType FieldType = MemberInit->getAnyMember()->getType();
+ QualType::DestructionKind dtorKind = FieldType.isDestructedType();
+ if (!CGF.needsEHCleanup(dtorKind))
+ continue;
+ LValue FieldLHS = LHS;
+ EmitLValueForAnyFieldInitialization(CGF, MemberInit, FieldLHS);
+ CGF.pushEHDestroy(dtorKind, FieldLHS.getAddress(), FieldType);
}
+ }
- private:
- const CXXConstructorDecl *ConstructorDecl;
- bool MemcpyableCtor;
- FunctionArgList &Args;
- SmallVector<CXXCtorInitializer*, 16> AggregatedInits;
- };
+ void finish() { emitAggregatedInits(); }
+
+private:
+ const CXXConstructorDecl *ConstructorDecl;
+ bool MemcpyableCtor;
+ FunctionArgList &Args;
+ SmallVector<CXXCtorInitializer *, 16> AggregatedInits;
+};
- class AssignmentMemcpyizer : public FieldMemcpyizer {
- private:
- // Returns the memcpyable field copied by the given statement, if one
- // exists. Otherwise returns null.
- FieldDecl *getMemcpyableField(Stmt *S) {
- if (!AssignmentsMemcpyable)
+class AssignmentMemcpyizer : public FieldMemcpyizer {
+private:
+ // Returns the memcpyable field copied by the given statement, if one
+ // exists. Otherwise returns null.
+ FieldDecl *getMemcpyableField(Stmt *S) {
+ if (!AssignmentsMemcpyable)
+ return nullptr;
+ if (BinaryOperator *BO = dyn_cast<BinaryOperator>(S)) {
+ // Recognise trivial assignments.
+ if (BO->getOpcode() != BO_Assign)
+ return nullptr;
+ MemberExpr *ME = dyn_cast<MemberExpr>(BO->getLHS());
+ if (!ME)
+ return nullptr;
+ FieldDecl *Field = dyn_cast<FieldDecl>(ME->getMemberDecl());
+ if (!Field || !isMemcpyableField(Field))
return nullptr;
- if (BinaryOperator *BO = dyn_cast<BinaryOperator>(S)) {
- // Recognise trivial assignments.
- if (BO->getOpcode() != BO_Assign)
- return nullptr;
- MemberExpr *ME = dyn_cast<MemberExpr>(BO->getLHS());
- if (!ME)
- return nullptr;
- FieldDecl *Field = dyn_cast<FieldDecl>(ME->getMemberDecl());
- if (!Field || !isMemcpyableField(Field))
- return nullptr;
- Stmt *RHS = BO->getRHS();
- if (ImplicitCastExpr *EC = dyn_cast<ImplicitCastExpr>(RHS))
- RHS = EC->getSubExpr();
- if (!RHS)
- return nullptr;
- if (MemberExpr *ME2 = dyn_cast<MemberExpr>(RHS)) {
- if (ME2->getMemberDecl() == Field)
- return Field;
- }
+ Stmt *RHS = BO->getRHS();
+ if (ImplicitCastExpr *EC = dyn_cast<ImplicitCastExpr>(RHS))
+ RHS = EC->getSubExpr();
+ if (!RHS)
return nullptr;
- } else if (CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(S)) {
- CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MCE->getCalleeDecl());
- if (!(MD && isMemcpyEquivalentSpecialMember(MD)))
- return nullptr;
- MemberExpr *IOA = dyn_cast<MemberExpr>(MCE->getImplicitObjectArgument());
- if (!IOA)
- return nullptr;
- FieldDecl *Field = dyn_cast<FieldDecl>(IOA->getMemberDecl());
- if (!Field || !isMemcpyableField(Field))
- return nullptr;
- MemberExpr *Arg0 = dyn_cast<MemberExpr>(MCE->getArg(0));
- if (!Arg0 || Field != dyn_cast<FieldDecl>(Arg0->getMemberDecl()))
- return nullptr;
- return Field;
- } else if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
- FunctionDecl *FD = dyn_cast<FunctionDecl>(CE->getCalleeDecl());
- if (!FD || FD->getBuiltinID() != Builtin::BI__builtin_memcpy)
- return nullptr;
- Expr *DstPtr = CE->getArg(0);
- if (ImplicitCastExpr *DC = dyn_cast<ImplicitCastExpr>(DstPtr))
- DstPtr = DC->getSubExpr();
- UnaryOperator *DUO = dyn_cast<UnaryOperator>(DstPtr);
- if (!DUO || DUO->getOpcode() != UO_AddrOf)
- return nullptr;
- MemberExpr *ME = dyn_cast<MemberExpr>(DUO->getSubExpr());
- if (!ME)
- return nullptr;
- FieldDecl *Field = dyn_cast<FieldDecl>(ME->getMemberDecl());
- if (!Field || !isMemcpyableField(Field))
- return nullptr;
- Expr *SrcPtr = CE->getArg(1);
- if (ImplicitCastExpr *SC = dyn_cast<ImplicitCastExpr>(SrcPtr))
- SrcPtr = SC->getSubExpr();
- UnaryOperator *SUO = dyn_cast<UnaryOperator>(SrcPtr);
- if (!SUO || SUO->getOpcode() != UO_AddrOf)
- return nullptr;
- MemberExpr *ME2 = dyn_cast<MemberExpr>(SUO->getSubExpr());
- if (!ME2 || Field != dyn_cast<FieldDecl>(ME2->getMemberDecl()))
- return nullptr;
- return Field;
+ if (MemberExpr *ME2 = dyn_cast<MemberExpr>(RHS)) {
+ if (ME2->getMemberDecl() == Field)
+ return Field;
}
-
return nullptr;
+ } else if (CXXMemberCallExpr *MCE = dyn_cast<CXXMemberCallExpr>(S)) {
+ CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MCE->getCalleeDecl());
+ if (!(MD && isMemcpyEquivalentSpecialMember(MD)))
+ return nullptr;
+ MemberExpr *IOA = dyn_cast<MemberExpr>(MCE->getImplicitObjectArgument());
+ if (!IOA)
+ return nullptr;
+ FieldDecl *Field = dyn_cast<FieldDecl>(IOA->getMemberDecl());
+ if (!Field || !isMemcpyableField(Field))
+ return nullptr;
+ MemberExpr *Arg0 = dyn_cast<MemberExpr>(MCE->getArg(0));
+ if (!Arg0 || Field != dyn_cast<FieldDecl>(Arg0->getMemberDecl()))
+ return nullptr;
+ return Field;
+ } else if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
+ FunctionDecl *FD = dyn_cast<FunctionDecl>(CE->getCalleeDecl());
+ if (!FD || FD->getBuiltinID() != Builtin::BI__builtin_memcpy)
+ return nullptr;
+ Expr *DstPtr = CE->getArg(0);
+ if (ImplicitCastExpr *DC = dyn_cast<ImplicitCastExpr>(DstPtr))
+ DstPtr = DC->getSubExpr();
+ UnaryOperator *DUO = dyn_cast<UnaryOperator>(DstPtr);
+ if (!DUO || DUO->getOpcode() != UO_AddrOf)
+ return nullptr;
+ MemberExpr *ME = dyn_cast<MemberExpr>(DUO->getSubExpr());
+ if (!ME)
+ return nullptr;
+ FieldDecl *Field = dyn_cast<FieldDecl>(ME->getMemberDecl());
+ if (!Field || !isMemcpyableField(Field))
+ return nullptr;
+ Expr *SrcPtr = CE->getArg(1);
+ if (ImplicitCastExpr *SC = dyn_cast<ImplicitCastExpr>(SrcPtr))
+ SrcPtr = SC->getSubExpr();
+ UnaryOperator *SUO = dyn_cast<UnaryOperator>(SrcPtr);
+ if (!SUO || SUO->getOpcode() != UO_AddrOf)
+ return nullptr;
+ MemberExpr *ME2 = dyn_cast<MemberExpr>(SUO->getSubExpr());
+ if (!ME2 || Field != dyn_cast<FieldDecl>(ME2->getMemberDecl()))
+ return nullptr;
+ return Field;
}
- bool AssignmentsMemcpyable;
- SmallVector<Stmt*, 16> AggregatedStmts;
+ return nullptr;
+ }
- public:
- AssignmentMemcpyizer(CodeGenFunction &CGF, const CXXMethodDecl *AD,
- FunctionArgList &Args)
+ bool AssignmentsMemcpyable;
+ SmallVector<Stmt *, 16> AggregatedStmts;
+
+public:
+ AssignmentMemcpyizer(CodeGenFunction &CGF, const CXXMethodDecl *AD,
+ FunctionArgList &Args)
: FieldMemcpyizer(CGF, AD->getParent(), Args[Args.size() - 1]),
AssignmentsMemcpyable(CGF.getLangOpts().getGC() == LangOptions::NonGC) {
- assert(Args.size() == 2);
- }
+ assert(Args.size() == 2);
+ }
- void emitAssignment(Stmt *S) {
- FieldDecl *F = getMemcpyableField(S);
- if (F) {
- addMemcpyableField(F);
- AggregatedStmts.push_back(S);
- } else {
- emitAggregatedStmts();
- CGF.EmitStmt(S);
- }
+ void emitAssignment(Stmt *S) {
+ FieldDecl *F = getMemcpyableField(S);
+ if (F) {
+ addMemcpyableField(F);
+ AggregatedStmts.push_back(S);
+ } else {
+ emitAggregatedStmts();
+ CGF.EmitStmt(S);
}
+ }
- void emitAggregatedStmts() {
- if (AggregatedStmts.size() <= 1) {
- if (!AggregatedStmts.empty()) {
- CopyingValueRepresentation CVR(CGF);
- CGF.EmitStmt(AggregatedStmts[0]);
- }
- reset();
+ void emitAggregatedStmts() {
+ if (AggregatedStmts.size() <= 1) {
+ if (!AggregatedStmts.empty()) {
+ CopyingValueRepresentation CVR(CGF);
+ CGF.EmitStmt(AggregatedStmts[0]);
}
-
- ApplyAtomGroup Grp(CGF.getDebugInfo());
- emitMemcpy();
- AggregatedStmts.clear();
+ reset();
}
- void finish() {
- emitAggregatedStmts();
- }
- };
+ ApplyAtomGroup Grp(CGF.getDebugInfo());
+ emitMemcpy();
+ AggregatedStmts.clear();
+ }
+
+ void finish() { emitAggregatedStmts(); }
+};
} // end anonymous namespace
static bool isInitializerOfDynamicClass(const CXXCtorInitializer *BaseInit) {
@@ -1357,14 +1337,13 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
CM.finish();
}
-static bool
-FieldHasTrivialDestructorBody(ASTContext &Context, const FieldDecl *Field);
+static bool FieldHasTrivialDestructorBody(ASTContext &Context,
+ const FieldDecl *Field);
static bool
HasTrivialDestructorBody(ASTContext &Context,
const CXXRecordDecl *BaseClassDecl,
- const CXXRecordDecl *MostDerivedClassDecl)
-{
+ const CXXRecordDecl *MostDerivedClassDecl) {
// If the destructor is trivial we don't have to check anything else.
if (BaseClassDecl->hasTrivialDestructor())
return true;
@@ -1392,8 +1371,7 @@ HasTrivialDestructorBody(ASTContext &Context,
// Check virtual bases.
for (const auto &I : BaseClassDecl->vbases()) {
const auto *VirtualBase = I.getType()->castAsCXXRecordDecl();
- if (!HasTrivialDestructorBody(Context, VirtualBase,
- MostDerivedClassDecl))
+ if (!HasTrivialDestructorBody(Context, VirtualBase, MostDerivedClassDecl))
return false;
}
}
@@ -1401,10 +1379,8 @@ HasTrivialDestructorBody(ASTContext &Context,
return true;
}
-static bool
-FieldHasTrivialDestructorBody(ASTContext &Context,
- const FieldDecl *Field)
-{
+static bool FieldHasTrivialDestructorBody(ASTContext &Context,
+ const FieldDecl *Field) {
QualType FieldBaseElementType = Context.getBaseElementType(Field->getType());
auto *FieldClassDecl = FieldBaseElementType->getAsCXXRecordDecl();
@@ -1602,8 +1578,10 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
switch (DtorType) {
case Dtor_Unified:
llvm_unreachable("not expecting a unified dtor");
- case Dtor_Comdat: llvm_unreachable("not expecting a COMDAT");
- case Dtor_Deleting: llvm_unreachable("already handled deleting case");
+ case Dtor_Comdat:
+ llvm_unreachable("not expecting a COMDAT");
+ case Dtor_Deleting:
+ llvm_unreachable("already handled deleting case");
case Dtor_VectorDeleting:
llvm_unreachable("already handled vector deleting case");
@@ -1664,7 +1642,8 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
ExitCXXTryStmt(*cast<CXXTryStmt>(Body), true);
}
-void CodeGenFunction::emitImplicitAssignmentOperatorBody(FunctionArgList &Args) {
+void CodeGenFunction::emitImplicitAssignmentOperatorBody(
+ FunctionArgList &Args) {
const CXXMethodDecl *AssignOp = cast<CXXMethodDecl>(CurGD.getDecl());
const Stmt *RootS = AssignOp->getBody();
assert(isa<CompoundStmt>(RootS) &&
@@ -1683,329 +1662,326 @@ void CodeGenFunction::emitImplicitAssignmentOperatorBody(FunctionArgList &Args)
}
namespace {
- llvm::Value *LoadThisForDtorDelete(CodeGenFunction &CGF,
- const CXXDestructorDecl *DD) {
- if (Expr *ThisArg = DD->getOperatorDeleteThisArg())
- return CGF.EmitScalarExpr(ThisArg);
- return CGF.LoadCXXThis();
- }
-
- /// Call the operator delete associated with the current destructor.
- struct CallDtorDelete final : EHScopeStack::Cleanup {
- CallDtorDelete() {}
-
- void Emit(CodeGenFunction &CGF, Flags flags) override {
- const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CGF.CurCodeDecl);
- const CXXRecordDecl *ClassDecl = Dtor->getParent();
- CGF.EmitDeleteCall(Dtor->getOperatorDelete(),
- LoadThisForDtorDelete(CGF, Dtor),
- CGF.getContext().getCanonicalTagType(ClassDecl));
- }
- };
+llvm::Value *LoadThisForDtorDelete(CodeGenFunction &CGF,
+ const CXXDestructorDecl *DD) {
+ if (Expr *ThisArg = DD->getOperatorDeleteThisArg())
+ return CGF.EmitScalarExpr(ThisArg);
+ return CGF.LoadCXXThis();
+}
+
+/// Call the operator delete associated with the current destructor.
+struct CallDtorDelete final : EHScopeStack::Cleanup {
+ CallDtorDelete() {}
- // This function implements generation of scalar deleting destructor body for
- // the case when the destructor also accepts an implicit flag. Right now only
- // Microsoft ABI requires deleting destructors to accept implicit flags.
- // The flag indicates whether an operator delete should be called and whether
- // it should be a class-specific operator delete or a global one.
- void EmitConditionalDtorDeleteCall(CodeGenFunction &CGF,
- llvm::Value *ShouldDeleteCondition,
- bool ReturnAfterDelete) {
+ void Emit(CodeGenFunction &CGF, Flags flags) override {
const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CGF.CurCodeDecl);
const CXXRecordDecl *ClassDecl = Dtor->getParent();
- const FunctionDecl *OD = Dtor->getOperatorDelete();
- assert(OD->isDestroyingOperatorDelete() == ReturnAfterDelete &&
- "unexpected value for ReturnAfterDelete");
- auto *CondTy = cast<llvm::IntegerType>(ShouldDeleteCondition->getType());
- // MSVC calls global operator delete inside of the dtor body, but clang
- // aligned with this behavior only after a particular version. This is not
- // ABI-compatible with previous versions.
- ASTContext &Context = CGF.getContext();
- bool CallGlobDelete =
- Context.getTargetInfo().callGlobalDeleteInDeletingDtor(
- Context.getLangOpts());
- if (CallGlobDelete && OD->isDestroyingOperatorDelete()) {
- llvm::BasicBlock *CallDtor = CGF.createBasicBlock("dtor.call_dtor");
- llvm::BasicBlock *DontCallDtor = CGF.createBasicBlock("dtor.entry_cont");
- // Third bit set signals that global operator delete is called. That means
- // despite class having destroying operator delete which is responsible
- // for calling dtor, we need to call dtor because global operator delete
- // won't do that.
- llvm::Value *Check3rdBit = CGF.Builder.CreateAnd(
- ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 4));
- llvm::Value *ShouldCallDtor = CGF.Builder.CreateIsNull(Check3rdBit);
- CGF.Builder.CreateCondBr(ShouldCallDtor, DontCallDtor, CallDtor);
- CGF.EmitBlock(CallDtor);
- QualType ThisTy = Dtor->getFunctionObjectParameterType();
- CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false,
- /*Delegating=*/false, CGF.LoadCXXThisAddress(),
- ThisTy);
- CGF.Builder.CreateBr(DontCallDtor);
- CGF.EmitBlock(DontCallDtor);
- }
- llvm::BasicBlock *callDeleteBB = CGF.createBasicBlock("dtor.call_delete");
- llvm::BasicBlock *continueBB = CGF.createBasicBlock("dtor.continue");
- // First bit set signals that operator delete must be called.
- llvm::Value *Check1stBit = CGF.Builder.CreateAnd(
- ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 1));
- llvm::Value *ShouldCallDelete = CGF.Builder.CreateIsNull(Check1stBit);
- CGF.Builder.CreateCondBr(ShouldCallDelete, continueBB, callDeleteBB);
-
- CGF.EmitBlock(callDeleteBB);
- auto EmitDeleteAndGoToEnd = [&](const FunctionDecl *DeleteOp) {
- CGF.EmitDeleteCall(DeleteOp, LoadThisForDtorDelete(CGF, Dtor),
- Context.getCanonicalTagType(ClassDecl));
- if (ReturnAfterDelete)
- CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
- else
- CGF.Builder.CreateBr(continueBB);
- };
- // If Sema only found a global operator delete previously, the dtor can
- // always call it. Otherwise we need to check the third bit and call the
- // appropriate operator delete, i.e. global or class-specific.
- if (const FunctionDecl *GlobOD = Dtor->getOperatorGlobalDelete();
- isa<CXXMethodDecl>(OD) && GlobOD && CallGlobDelete) {
- // Third bit set signals that global operator delete is called, i.e.
- // ::delete appears on the callsite.
- llvm::Value *CheckTheBitForGlobDeleteCall = CGF.Builder.CreateAnd(
- ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 4));
- llvm::Value *ShouldCallGlobDelete =
- CGF.Builder.CreateIsNull(CheckTheBitForGlobDeleteCall);
- llvm::BasicBlock *GlobDelete =
- CGF.createBasicBlock("dtor.call_glob_delete");
- llvm::BasicBlock *ClassDelete =
- CGF.createBasicBlock("dtor.call_class_delete");
- CGF.Builder.CreateCondBr(ShouldCallGlobDelete, ClassDelete, GlobDelete);
- CGF.EmitBlock(GlobDelete);
-
- EmitDeleteAndGoToEnd(GlobOD);
- CGF.EmitBlock(ClassDelete);
- }
- EmitDeleteAndGoToEnd(OD);
- CGF.EmitBlock(continueBB);
- }
-
- struct CallDtorDeleteConditional final : EHScopeStack::Cleanup {
- llvm::Value *ShouldDeleteCondition;
-
- public:
- CallDtorDeleteConditional(llvm::Value *ShouldDeleteCondition)
- : ShouldDeleteCondition(ShouldDeleteCondition) {
- assert(ShouldDeleteCondition != nullptr);
- }
-
- void Emit(CodeGenFunction &CGF, Flags flags) override {
- EmitConditionalDtorDeleteCall(CGF, ShouldDeleteCondition,
- /*ReturnAfterDelete*/false);
- }
- };
-
- class DestroyField final : public EHScopeStack::Cleanup {
- const FieldDecl *field;
- CodeGenFunction::Destroyer *destroyer;
- bool useEHCleanupForArray;
-
- public:
- DestroyField(const FieldDecl *field, CodeGenFunction::Destroyer *destroyer,
- bool useEHCleanupForArray)
- : field(field), destroyer(destroyer),
- useEHCleanupForArray(useEHCleanupForArray) {}
-
- void Emit(CodeGenFunction &CGF, Flags flags) override {
- // Find the address of the field.
- Address thisValue = CGF.LoadCXXThisAddress();
- CanQualType RecordTy =
- CGF.getContext().getCanonicalTagType(field->getParent());
- LValue ThisLV = CGF.MakeAddrLValue(thisValue, RecordTy);
- LValue LV = CGF.EmitLValueForField(ThisLV, field);
- assert(LV.isSimple());
-
- CGF.emitDestroy(LV.getAddress(), field->getType(), destroyer,
- flags.isForNormalCleanup() && useEHCleanupForArray);
- }
- };
-
- class DeclAsInlineDebugLocation {
- CGDebugInfo *DI;
- llvm::MDNode *InlinedAt;
- std::optional<ApplyDebugLocation> Location;
-
- public:
- DeclAsInlineDebugLocation(CodeGenFunction &CGF, const NamedDecl &Decl)
- : DI(CGF.getDebugInfo()) {
- if (!DI)
- return;
- InlinedAt = DI->getInlinedAt();
- DI->setInlinedAt(CGF.Builder.getCurrentDebugLocation());
- Location.emplace(CGF, Decl.getLocation());
- }
+ CGF.EmitDeleteCall(Dtor->getOperatorDelete(),
+ LoadThisForDtorDelete(CGF, Dtor),
+ CGF.getContext().getCanonicalTagType(ClassDecl));
+ }
+};
+
+// This function implements generation of scalar deleting destructor body for
+// the case when the destructor also accepts an implicit flag. Right now only
+// Microsoft ABI requires deleting destructors to accept implicit flags.
+// The flag indicates whether an operator delete should be called and whether
+// it should be a class-specific operator delete or a global one.
+void EmitConditionalDtorDeleteCall(CodeGenFunction &CGF,
+ llvm::Value *ShouldDeleteCondition,
+ bool ReturnAfterDelete) {
+ const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CGF.CurCodeDecl);
+ const CXXRecordDecl *ClassDecl = Dtor->getParent();
+ const FunctionDecl *OD = Dtor->getOperatorDelete();
+ assert(OD->isDestroyingOperatorDelete() == ReturnAfterDelete &&
+ "unexpected value for ReturnAfterDelete");
+ auto *CondTy = cast<llvm::IntegerType>(ShouldDeleteCondition->getType());
+ // MSVC calls global operator delete inside of the dtor body, but clang
+ // aligned with this behavior only after a particular version. This is not
+ // ABI-compatible with previous versions.
+ ASTContext &Context = CGF.getContext();
+ bool CallGlobDelete = Context.getTargetInfo().callGlobalDeleteInDeletingDtor(
+ Context.getLangOpts());
+ if (CallGlobDelete && OD->isDestroyingOperatorDelete()) {
+ llvm::BasicBlock *CallDtor = CGF.createBasicBlock("dtor.call_dtor");
+ llvm::BasicBlock *DontCallDtor = CGF.createBasicBlock("dtor.entry_cont");
+ // Third bit set signals that global operator delete is called. That means
+ // despite class having destroying operator delete which is responsible
+ // for calling dtor, we need to call dtor because global operator delete
+ // won't do that.
+ llvm::Value *Check3rdBit = CGF.Builder.CreateAnd(
+ ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 4));
+ llvm::Value *ShouldCallDtor = CGF.Builder.CreateIsNull(Check3rdBit);
+ CGF.Builder.CreateCondBr(ShouldCallDtor, DontCallDtor, CallDtor);
+ CGF.EmitBlock(CallDtor);
+ QualType ThisTy = Dtor->getFunctionObjectParameterType();
+ CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false,
+ /*Delegating=*/false, CGF.LoadCXXThisAddress(),
+ ThisTy);
+ CGF.Builder.CreateBr(DontCallDtor);
+ CGF.EmitBlock(DontCallDtor);
+ }
+ llvm::BasicBlock *callDeleteBB = CGF.createBasicBlock("dtor.call_delete");
+ llvm::BasicBlock *continueBB = CGF.createBasicBlock("dtor.continue");
+ // First bit set signals that operator delete must be called.
+ llvm::Value *Check1stBit = CGF.Builder.CreateAnd(
+ ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 1));
+ llvm::Value *ShouldCallDelete = CGF.Builder.CreateIsNull(Check1stBit);
+ CGF.Builder.CreateCondBr(ShouldCallDelete, continueBB, callDeleteBB);
- ~DeclAsInlineDebugLocation() {
- if (!DI)
- return;
- Location.reset();
- DI->setInlinedAt(InlinedAt);
- }
+ CGF.EmitBlock(callDeleteBB);
+ auto EmitDeleteAndGoToEnd = [&](const FunctionDecl *DeleteOp) {
+ CGF.EmitDeleteCall(DeleteOp, LoadThisForDtorDelete(CGF, Dtor),
+ Context.getCanonicalTagType(ClassDecl));
+ if (ReturnAfterDelete)
+ CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
+ else
+ CGF.Builder.CreateBr(continueBB);
};
-
- static void EmitSanitizerDtorCallback(
- CodeGenFunction &CGF, StringRef Name, llvm::Value *Ptr,
- std::optional<CharUnits::QuantityType> PoisonSize = {}) {
- CodeGenFunction::SanitizerScope SanScope(&CGF);
- // Pass in void pointer and size of region as arguments to runtime
- // function
- SmallVector<llvm::Value *, 2> Args = {Ptr};
- SmallVector<llvm::Type *, 2> ArgTypes = {CGF.VoidPtrTy};
-
- if (PoisonSize.has_value()) {
- Args.emplace_back(llvm::ConstantInt::get(CGF.SizeTy, *PoisonSize));
- ArgTypes.emplace_back(CGF.SizeTy);
- }
-
- llvm::FunctionType *FnType =
- llvm::FunctionType::get(CGF.VoidTy, ArgTypes, false);
- llvm::FunctionCallee Fn = CGF.CGM.CreateRuntimeFunction(FnType, Name);
-
- CGF.EmitNounwindRuntimeCall(Fn, Args);
+ // If Sema only found a global operator delete previously, the dtor can
+ // always call it. Otherwise we need to check the third bit and call the
+ // appropriate operator delete, i.e. global or class-specific.
+ if (const FunctionDecl *GlobOD = Dtor->getOperatorGlobalDelete();
+ isa<CXXMethodDecl>(OD) && GlobOD && CallGlobDelete) {
+ // Third bit set signals that global operator delete is called, i.e.
+ // ::delete appears on the callsite.
+ llvm::Value *CheckTheBitForGlobDeleteCall = CGF.Builder.CreateAnd(
+ ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 4));
+ llvm::Value *ShouldCallGlobDelete =
+ CGF.Builder.CreateIsNull(CheckTheBitForGlobDeleteCall);
+ llvm::BasicBlock *GlobDelete =
+ CGF.createBasicBlock("dtor.call_glob_delete");
+ llvm::BasicBlock *ClassDelete =
+ CGF.createBasicBlock("dtor.call_class_delete");
+ CGF.Builder.CreateCondBr(ShouldCallGlobDelete, ClassDelete, GlobDelete);
+ CGF.EmitBlock(GlobDelete);
+
+ EmitDeleteAndGoToEnd(GlobOD);
+ CGF.EmitBlock(ClassDelete);
+ }
+ EmitDeleteAndGoToEnd(OD);
+ CGF.EmitBlock(continueBB);
+}
+
+struct CallDtorDeleteConditional final : EHScopeStack::Cleanup {
+ llvm::Value *ShouldDeleteCondition;
+
+public:
+ CallDtorDeleteConditional(llvm::Value *ShouldDeleteCondition)
+ : ShouldDeleteCondition(ShouldDeleteCondition) {
+ assert(ShouldDeleteCondition != nullptr);
+ }
+
+ void Emit(CodeGenFunction &CGF, Flags flags) override {
+ EmitConditionalDtorDeleteCall(CGF, ShouldDeleteCondition,
+ /*ReturnAfterDelete*/ false);
+ }
+};
+
+class DestroyField final : public EHScopeStack::Cleanup {
+ const FieldDecl *field;
+ CodeGenFunction::Destroyer *destroyer;
+ bool useEHCleanupForArray;
+
+public:
+ DestroyField(const FieldDecl *field, CodeGenFunction::Destroyer *destroyer,
+ bool useEHCleanupForArray)
+ : field(field), destroyer(destroyer),
+ useEHCleanupForArray(useEHCleanupForArray) {}
+
+ void Emit(CodeGenFunction &CGF, Flags flags) override {
+ // Find the address of the field.
+ Address thisValue = CGF.LoadCXXThisAddress();
+ CanQualType RecordTy =
+ CGF.getContext().getCanonicalTagType(field->getParent());
+ LValue ThisLV = CGF.MakeAddrLValue(thisValue, RecordTy);
+ LValue LV = CGF.EmitLValueForField(ThisLV, field);
+ assert(LV.isSimple());
+
+ CGF.emitDestroy(LV.getAddress(), field->getType(), destroyer,
+ flags.isForNormalCleanup() && useEHCleanupForArray);
+ }
+};
+
+class DeclAsInlineDebugLocation {
+ CGDebugInfo *DI;
+ llvm::MDNode *InlinedAt;
+ std::optional<ApplyDebugLocation> Location;
+
+public:
+ DeclAsInlineDebugLocation(CodeGenFunction &CGF, const NamedDecl &Decl)
+ : DI(CGF.getDebugInfo()) {
+ if (!DI)
+ return;
+ InlinedAt = DI->getInlinedAt();
+ DI->setInlinedAt(CGF.Builder.getCurrentDebugLocation());
+ Location.emplace(CGF, Decl.getLocation());
}
- static void
- EmitSanitizerDtorFieldsCallback(CodeGenFunction &CGF, llvm::Value *Ptr,
- CharUnits::QuantityType PoisonSize) {
- EmitSanitizerDtorCallback(CGF, "__sanitizer_dtor_callback_fields", Ptr,
- PoisonSize);
+ ~DeclAsInlineDebugLocation() {
+ if (!DI)
+ return;
+ Location.reset();
+ DI->setInlinedAt(InlinedAt);
}
+};
- /// Poison base class with a trivial destructor.
- struct SanitizeDtorTrivialBase final : EHScopeStack::Cleanup {
- const CXXRecordDecl *BaseClass;
- bool BaseIsVirtual;
- SanitizeDtorTrivialBase(const CXXRecordDecl *Base, bool BaseIsVirtual)
- : BaseClass(Base), BaseIsVirtual(BaseIsVirtual) {}
+static void EmitSanitizerDtorCallback(
+ CodeGenFunction &CGF, StringRef Name, llvm::Value *Ptr,
+ std::optional<CharUnits::QuantityType> PoisonSize = {}) {
+ CodeGenFunction::SanitizerScope SanScope(&CGF);
+ // Pass in void pointer and size of region as arguments to runtime
+ // function
+ SmallVector<llvm::Value *, 2> Args = {Ptr};
+ SmallVector<llvm::Type *, 2> ArgTypes = {CGF.VoidPtrTy};
- void Emit(CodeGenFunction &CGF, Flags flags) override {
- const CXXRecordDecl *DerivedClass =
- cast<CXXMethodDecl>(CGF.CurCodeDecl)->getParent();
+ if (PoisonSize.has_value()) {
+ Args.emplace_back(llvm::ConstantInt::get(CGF.SizeTy, *PoisonSize));
+ ArgTypes.emplace_back(CGF.SizeTy);
+ }
- Address Addr = CGF.GetAddressOfDirectBaseInCompleteClass(
- CGF.LoadCXXThisAddress(), DerivedClass, BaseClass, BaseIsVirtual);
+ llvm::FunctionType *FnType =
+ llvm::FunctionType::get(CGF.VoidTy, ArgTypes, false);
+ llvm::FunctionCallee Fn = CGF.CGM.CreateRuntimeFunction(FnType, Name);
- const ASTRecordLayout &BaseLayout =
- CGF.getContext().getASTRecordLayout(BaseClass);
- CharUnits BaseSize = BaseLayout.getSize();
+ CGF.EmitNounwindRuntimeCall(Fn, Args);
+}
- if (!BaseSize.isPositive())
- return;
+static void
+EmitSanitizerDtorFieldsCallback(CodeGenFunction &CGF, llvm::Value *Ptr,
+ CharUnits::QuantityType PoisonSize) {
+ EmitSanitizerDtorCallback(CGF, "__sanitizer_dtor_callback_fields", Ptr,
+ PoisonSize);
+}
- // Use the base class declaration location as inline DebugLocation. All
- // fields of the class are destroyed.
- DeclAsInlineDebugLocation InlineHere(CGF, *BaseClass);
- EmitSanitizerDtorFieldsCallback(CGF, Addr.emitRawPointer(CGF),
- BaseSize.getQuantity());
+/// Poison base class with a trivial destructor.
+struct SanitizeDtorTrivialBase final : EHScopeStack::Cleanup {
+ const CXXRecordDecl *BaseClass;
+ bool BaseIsVirtual;
+ SanitizeDtorTrivialBase(const CXXRecordDecl *Base, bool BaseIsVirtual)
+ : BaseClass(Base), BaseIsVirtual(BaseIsVirtual) {}
- // Prevent the current stack frame from disappearing from the stack trace.
- CGF.CurFn->addFnAttr("disable-tail-calls", "true");
- }
- };
+ void Emit(CodeGenFunction &CGF, Flags flags) override {
+ const CXXRecordDecl *DerivedClass =
+ cast<CXXMethodDecl>(CGF.CurCodeDecl)->getParent();
- class SanitizeDtorFieldRange final : public EHScopeStack::Cleanup {
- const CXXDestructorDecl *Dtor;
- unsigned StartIndex;
- unsigned EndIndex;
-
- public:
- SanitizeDtorFieldRange(const CXXDestructorDecl *Dtor, unsigned StartIndex,
- unsigned EndIndex)
- : Dtor(Dtor), StartIndex(StartIndex), EndIndex(EndIndex) {}
-
- // Generate function call for handling object poisoning.
- // Disables tail call elimination, to prevent the current stack frame
- // from disappearing from the stack trace.
- void Emit(CodeGenFunction &CGF, Flags flags) override {
- const ASTContext &Context = CGF.getContext();
- const ASTRecordLayout &Layout =
- Context.getASTRecordLayout(Dtor->getParent());
+ Address Addr = CGF.GetAddressOfDirectBaseInCompleteClass(
+ CGF.LoadCXXThisAddress(), DerivedClass, BaseClass, BaseIsVirtual);
- // It's a first trivial field so it should be at the begining of a char,
- // still round up start offset just in case.
- CharUnits PoisonStart = Context.toCharUnitsFromBits(
- Layout.getFieldOffset(StartIndex) + Context.getCharWidth() - 1);
- llvm::ConstantInt *OffsetSizePtr =
- llvm::ConstantInt::get(CGF.SizeTy, PoisonStart.getQuantity());
+ const ASTRecordLayout &BaseLayout =
+ CGF.getContext().getASTRecordLayout(BaseClass);
+ CharUnits BaseSize = BaseLayout.getSize();
- llvm::Value *OffsetPtr =
- CGF.Builder.CreateGEP(CGF.Int8Ty, CGF.LoadCXXThis(), OffsetSizePtr);
+ if (!BaseSize.isPositive())
+ return;
- CharUnits PoisonEnd;
- if (EndIndex >= Layout.getFieldCount()) {
- PoisonEnd = Layout.getNonVirtualSize();
- } else {
- PoisonEnd =
- Context.toCharUnitsFromBits(Layout.getFieldOffset(EndIndex));
- }
- CharUnits PoisonSize = PoisonEnd - PoisonStart;
- if (!PoisonSize.isPositive())
- return;
+ // Use the base class declaration location as inline DebugLocation. All
+ // fields of the class are destroyed.
+ DeclAsInlineDebugLocation InlineHere(CGF, *BaseClass);
+ EmitSanitizerDtorFieldsCallback(CGF, Addr.emitRawPointer(CGF),
+ BaseSize.getQuantity());
+
+ // Prevent the current stack frame from disappearing from the stack trace.
+ CGF.CurFn->addFnAttr("disable-tail-calls", "true");
+ }
+};
+
+class SanitizeDtorFieldRange final : public EHScopeStack::Cleanup {
+ const CXXDestructorDecl *Dtor;
+ unsigned StartIndex;
+ unsigned EndIndex;
+
+public:
+ SanitizeDtorFieldRange(const CXXDestructorDecl *Dtor, unsigned StartIndex,
+ unsigned EndIndex)
+ : Dtor(Dtor), StartIndex(StartIndex), EndIndex(EndIndex) {}
+
+ // Generate function call for handling object poisoning.
+ // Disables tail call elimination, to prevent the current stack frame
+ // from disappearing from the stack trace.
+ void Emit(CodeGenFunction &CGF, Flags flags) override {
+ const ASTContext &Context = CGF.getContext();
+ const ASTRecordLayout &Layout =
+ Context.getASTRecordLayout(Dtor->getParent());
+
+ // It's a first trivial field so it should be at the begining of a char,
+ // still round up start offset just in case.
+ CharUnits PoisonStart = Context.toCharUnitsFromBits(
+ Layout.getFieldOffset(StartIndex) + Context.getCharWidth() - 1);
+ llvm::ConstantInt *OffsetSizePtr =
+ llvm::ConstantInt::get(CGF.SizeTy, PoisonStart.getQuantity());
+
+ llvm::Value *OffsetPtr =
+ CGF.Builder.CreateGEP(CGF.Int8Ty, CGF.LoadCXXThis(), OffsetSizePtr);
+
+ CharUnits PoisonEnd;
+ if (EndIndex >= Layout.getFieldCount()) {
+ PoisonEnd = Layout.getNonVirtualSize();
+ } else {
+ PoisonEnd = Context.toCharUnitsFromBits(Layout.getFieldOffset(EndIndex));
+ }
+ CharUnits PoisonSize = PoisonEnd - PoisonStart;
+ if (!PoisonSize.isPositive())
+ return;
- // Use the top field declaration location as inline DebugLocation.
- DeclAsInlineDebugLocation InlineHere(
- CGF, **std::next(Dtor->getParent()->field_begin(), StartIndex));
- EmitSanitizerDtorFieldsCallback(CGF, OffsetPtr, PoisonSize.getQuantity());
+ // Use the top field declaration location as inline DebugLocation.
+ DeclAsInlineDebugLocation InlineHere(
+ CGF, **std::next(Dtor->getParent()->field_begin(), StartIndex));
+ EmitSanitizerDtorFieldsCallback(CGF, OffsetPtr, PoisonSize.getQuantity());
- // Prevent the current stack frame from disappearing from the stack trace.
- CGF.CurFn->addFnAttr("disable-tail-calls", "true");
- }
- };
+ // Prevent the current stack frame from disappearing from the stack trace.
+ CGF.CurFn->addFnAttr("disable-tail-calls", "true");
+ }
+};
- class SanitizeDtorVTable final : public EHScopeStack::Cleanup {
- const CXXDestructorDecl *Dtor;
+class SanitizeDtorVTable final : public EHScopeStack::Cleanup {
+ const CXXDestructorDecl *Dtor;
- public:
- SanitizeDtorVTable(const CXXDestructorDecl *Dtor) : Dtor(Dtor) {}
+public:
+ SanitizeDtorVTable(const CXXDestructorDecl *Dtor) : Dtor(Dtor) {}
- // Generate function call for handling vtable pointer poisoning.
- void Emit(CodeGenFunction &CGF, Flags flags) override {
- assert(Dtor->getParent()->isDynamicClass());
- (void)Dtor;
- // Poison vtable and vtable ptr if they exist for this class.
- llvm::Value *VTablePtr = CGF.LoadCXXThis();
+ // Generate function call for handling vtable pointer poisoning.
+ void Emit(CodeGenFunction &CGF, Flags flags) override {
+ assert(Dtor->getParent()->isDynamicClass());
+ (void)Dtor;
+ // Poison vtable and vtable ptr if they exist for this class.
+ llvm::Value *VTablePtr = CGF.LoadCXXThis();
- // Pass in void pointer and size of region as arguments to runtime
- // function
- EmitSanitizerDtorCallback(CGF, "__sanitizer_dtor_callback_vptr",
- VTablePtr);
+ // Pass in void pointer and size of region as arguments to runtime
+ // function
+ EmitSanitizerDtorCallback(CGF, "__sanitizer_dtor_callback_vptr", VTablePtr);
+ }
+};
+
+class SanitizeDtorCleanupBuilder {
+ ASTContext &Context;
+ EHScopeStack &EHStack;
+ const CXXDestructorDecl *DD;
+ std::optional<unsigned> StartIndex;
+
+public:
+ SanitizeDtorCleanupBuilder(ASTContext &Context, EHScopeStack &EHStack,
+ const CXXDestructorDecl *DD)
+ : Context(Context), EHStack(EHStack), DD(DD), StartIndex(std::nullopt) {}
+ void PushCleanupForField(const FieldDecl *Field) {
+ if (isEmptyFieldForLayout(Context, Field))
+ return;
+ unsigned FieldIndex = Field->getFieldIndex();
+ if (FieldHasTrivialDestructorBody(Context, Field)) {
+ if (!StartIndex)
+ StartIndex = FieldIndex;
+ } else if (StartIndex) {
+ EHStack.pushCleanup<SanitizeDtorFieldRange>(NormalAndEHCleanup, DD,
+ *StartIndex, FieldIndex);
+ StartIndex = std::nullopt;
}
- };
-
- class SanitizeDtorCleanupBuilder {
- ASTContext &Context;
- EHScopeStack &EHStack;
- const CXXDestructorDecl *DD;
- std::optional<unsigned> StartIndex;
-
- public:
- SanitizeDtorCleanupBuilder(ASTContext &Context, EHScopeStack &EHStack,
- const CXXDestructorDecl *DD)
- : Context(Context), EHStack(EHStack), DD(DD), StartIndex(std::nullopt) {}
- void PushCleanupForField(const FieldDecl *Field) {
- if (isEmptyFieldForLayout(Context, Field))
- return;
- unsigned FieldIndex = Field->getFieldIndex();
- if (FieldHasTrivialDestructorBody(Context, Field)) {
- if (!StartIndex)
- StartIndex = FieldIndex;
- } else if (StartIndex) {
- EHStack.pushCleanup<SanitizeDtorFieldRange>(NormalAndEHCleanup, DD,
- *StartIndex, FieldIndex);
- StartIndex = std::nullopt;
- }
- }
- void End() {
- if (StartIndex)
- EHStack.pushCleanup<SanitizeDtorFieldRange>(NormalAndEHCleanup, DD,
- *StartIndex, -1);
- }
- };
+ }
+ void End() {
+ if (StartIndex)
+ EHStack.pushCleanup<SanitizeDtorFieldRange>(NormalAndEHCleanup, DD,
+ *StartIndex, -1);
+ }
+};
} // end anonymous namespace
/// Emit all code that comes at the end of class's
@@ -2029,7 +2005,7 @@ void CodeGenFunction::EnterDtorCleanups(const CXXDestructorDecl *DD,
// telling whether this is a deleting destructor.
if (DD->getOperatorDelete()->isDestroyingOperatorDelete())
EmitConditionalDtorDeleteCall(*this, CXXStructorImplicitParamValue,
- /*ReturnAfterDelete*/true);
+ /*ReturnAfterDelete*/ true);
else
EHStack.pushCleanup<CallDtorDeleteConditional>(
NormalAndEHCleanup, CXXStructorImplicitParamValue);
@@ -2150,13 +2126,15 @@ void CodeGenFunction::EnterDtorCleanups(const CXXDestructorDecl *DD,
/// \param arrayBegin an arrayType*
/// \param zeroInitialize true if each element should be
/// zero-initialized before it is constructed
-void CodeGenFunction::EmitCXXAggrConstructorCall(
- const CXXConstructorDecl *ctor, const ArrayType *arrayType,
- Address arrayBegin, const CXXConstructExpr *E, bool NewPointerIsChecked,
- bool zeroInitialize) {
+void CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor,
+ const ArrayType *arrayType,
+ Address arrayBegin,
+ const CXXConstructExpr *E,
+ bool NewPointerIsChecked,
+ bool zeroInitialize) {
QualType elementType;
llvm::Value *numElements =
- emitArrayLength(arrayType, elementType, arrayBegin);
+ emitArrayLength(arrayType, elementType, arrayBegin);
EmitCXXAggrConstructorCall(ctor, numElements, arrayBegin, E,
NewPointerIsChecked, zeroInitialize);
@@ -2171,12 +2149,9 @@ void CodeGenFunction::EmitCXXAggrConstructorCall(
/// \param arrayBase a T*, where T is the type constructed by ctor
/// \param zeroInitialize true if each element should be
/// zero-initialized before it is constructed
-void CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor,
- llvm::Value *numElements,
- Address arrayBase,
- const CXXConstructExpr *E,
- bool NewPointerIsChecked,
- bool zeroInitialize) {
+void CodeGenFunction::EmitCXXAggrConstructorCall(
+ const CXXConstructorDecl *ctor, llvm::Value *numElements, Address arrayBase,
+ const CXXConstructExpr *E, bool NewPointerIsChecked, bool zeroInitialize) {
// It's legal for numElements to be zero. This can happen both
// dynamically, because x can be zero in 'new A[x]', and statically,
// because of GCC extensions that permit zero-length arrays. There
@@ -2185,13 +2160,13 @@ void CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor,
llvm::BranchInst *zeroCheckBranch = nullptr;
// Optimize for a constant count.
- llvm::ConstantInt *constantCount
- = dyn_cast<llvm::ConstantInt>(numElements);
+ llvm::ConstantInt *constantCount = dyn_cast<llvm::ConstantInt>(numElements);
if (constantCount) {
// Just skip out if the constant count is zero.
- if (constantCount->isZero()) return;
+ if (constantCount->isZero())
+ return;
- // Otherwise, emit the check.
+ // Otherwise, emit the check.
} else {
llvm::BasicBlock *loopBB = createBasicBlock("new.ctorloop");
llvm::Value *iszero = Builder.CreateIsNull(numElements, "isempty");
@@ -2209,8 +2184,8 @@ void CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor,
llvm::BasicBlock *entryBB = Builder.GetInsertBlock();
llvm::BasicBlock *loopBB = createBasicBlock("arrayctor.loop");
EmitBlock(loopBB);
- llvm::PHINode *cur = Builder.CreatePHI(arrayBegin->getType(), 2,
- "arrayctor.cur");
+ llvm::PHINode *cur =
+ Builder.CreatePHI(arrayBegin->getType(), 2, "arrayctor.cur");
cur->addIncoming(arrayBegin, entryBB);
// Inside the loop body, emit the constructor call on the array element.
@@ -2224,9 +2199,8 @@ void CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor,
// Note that these are complete objects and so we don't need to
// use the non-virtual size or alignment.
CanQualType type = getContext().getCanonicalTagType(ctor->getParent());
- CharUnits eltAlignment =
- arrayBase.getAlignment()
- .alignmentOfArrayElement(getContext().getTypeSizeInChars(type));
+ CharUnits eltAlignment = arrayBase.getAlignment().alignmentOfArrayElement(
+ getContext().getTypeSizeInChars(type));
Address curAddr = Address(cur, elementType, eltAlignment);
// Zero initialize the storage, if requested.
@@ -2273,7 +2247,8 @@ void CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor,
Builder.CreateCondBr(done, contBB, loopBB);
// Patch the earlier check to skip over the loop.
- if (zeroCheckBranch) zeroCheckBranch->setSuccessor(0, contBB);
+ if (zeroCheckBranch)
+ zeroCheckBranch->setSuccessor(0, contBB);
if (CGM.shouldEmitConvergenceTokens())
ConvergenceTokenStack.pop_back();
@@ -2281,8 +2256,7 @@ void CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor,
EmitBlock(contBB);
}
-void CodeGenFunction::destroyCXXObject(CodeGenFunction &CGF,
- Address addr,
+void CodeGenFunction::destroyCXXObject(CodeGenFunction &CGF, Address addr,
QualType type) {
const CXXDestructorDecl *dtor = type->castAsCXXRecordDecl()->getDestructor();
assert(!dtor->isTrivial());
@@ -2290,12 +2264,9 @@ void CodeGenFunction::destroyCXXObject(CodeGenFunction &CGF,
/*Delegating=*/false, addr, type);
}
-void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
- CXXCtorType Type,
- bool ForVirtualBase,
- bool Delegating,
- AggValueSlot ThisAVS,
- const CXXConstructExpr *E) {
+void CodeGenFunction::EmitCXXConstructorCall(
+ const CXXConstructorDecl *D, CXXCtorType Type, bool ForVirtualBase,
+ bool Delegating, AggValueSlot ThisAVS, const CXXConstructExpr *E) {
CallArgList Args;
Address This = ThisAVS.getAddress();
LangAS SlotAS = ThisAVS.getQualifiers().getAddressSpace();
@@ -2430,7 +2401,8 @@ void CodeGenFunction::EmitCXXConstructorCall(
// sure that definition of vtable is not hidden,
// then we are always safe to refer to it.
// FIXME: It looks like InstCombine is very inefficient on dealing with
- // assumes. Make assumption loads require -fstrict-vtable-pointers temporarily.
+ // assumes. Make assumption loads require -fstrict-vtable-pointers
+ // temporarily.
if (CGM.getCodeGenOpts().OptimizationLevel > 0 &&
ClassDecl->isDynamicClass() && Type != Ctor_Base &&
CGM.getCXXABI().canSpeculativelyEmitVTable(ClassDecl) &&
@@ -2482,9 +2454,9 @@ void CodeGenFunction::EmitInheritedCXXConstructorCall(
}
}
- EmitCXXConstructorCall(D, Ctor_Base, ForVirtualBase, /*Delegating*/false,
- This, Args, AggValueSlot::MayOverlap,
- E->getLocation(), /*NewPointerIsChecked*/true);
+ EmitCXXConstructorCall(D, Ctor_Base, ForVirtualBase, /*Delegating*/ false,
+ This, Args, AggValueSlot::MayOverlap, E->getLocation(),
+ /*NewPointerIsChecked*/ true);
}
void CodeGenFunction::EmitInlinedInheritingCXXConstructorCall(
@@ -2560,10 +2532,9 @@ void CodeGenFunction::EmitVTableAssumptionLoads(const CXXRecordDecl *ClassDecl,
EmitVTableAssumptionLoad(Vptr, This);
}
-void
-CodeGenFunction::EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D,
- Address This, Address Src,
- const CXXConstructExpr *E) {
+void CodeGenFunction::EmitSynthesizedCXXCopyCtorCall(
+ const CXXConstructorDecl *D, Address This, Address Src,
+ const CXXConstructExpr *E) {
const FunctionProtoType *FPT = D->getType()->castAs<FunctionProtoType>();
CallArgList Args;
@@ -2583,17 +2554,15 @@ CodeGenFunction::EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D,
EmitCallArgs(Args, FPT, drop_begin(E->arguments(), 1), E->getConstructor(),
/*ParamsToSkip*/ 1);
- EmitCXXConstructorCall(D, Ctor_Complete, /*ForVirtualBase*/false,
- /*Delegating*/false, This, Args,
+ EmitCXXConstructorCall(D, Ctor_Complete, /*ForVirtualBase*/ false,
+ /*Delegating*/ false, This, Args,
AggValueSlot::MayOverlap, E->getExprLoc(),
- /*NewPointerIsChecked*/false);
+ /*NewPointerIsChecked*/ false);
}
-void
-CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor,
- CXXCtorType CtorType,
- const FunctionArgList &Args,
- SourceLocation Loc) {
+void CodeGenFunction::EmitDelegateCXXConstructorCall(
+ const CXXConstructorDecl *Ctor, CXXCtorType CtorType,
+ const FunctionArgList &Args, SourceLocation Loc) {
CallArgList DelegateArgs;
FunctionArgList::const_iterator I = Args.begin(), E = Args.end();
@@ -2629,52 +2598,47 @@ CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor,
}
namespace {
- struct CallDelegatingCtorDtor final : EHScopeStack::Cleanup {
- const CXXDestructorDecl *Dtor;
- Address Addr;
- CXXDtorType Type;
+struct CallDelegatingCtorDtor final : EHScopeStack::Cleanup {
+ const CXXDestructorDecl *Dtor;
+ Address Addr;
+ CXXDtorType Type;
- CallDelegatingCtorDtor(const CXXDestructorDecl *D, Address Addr,
- CXXDtorType Type)
+ CallDelegatingCtorDtor(const CXXDestructorDecl *D, Address Addr,
+ CXXDtorType Type)
: Dtor(D), Addr(Addr), Type(Type) {}
- void Emit(CodeGenFunction &CGF, Flags flags) override {
- // We are calling the destructor from within the constructor.
- // Therefore, "this" should have the expected type.
- QualType ThisTy = Dtor->getFunctionObjectParameterType();
- CGF.EmitCXXDestructorCall(Dtor, Type, /*ForVirtualBase=*/false,
- /*Delegating=*/true, Addr, ThisTy);
- }
- };
+ void Emit(CodeGenFunction &CGF, Flags flags) override {
+ // We are calling the destructor from within the constructor.
+ // Therefore, "this" should have the expected type.
+ QualType ThisTy = Dtor->getFunctionObjectParameterType();
+ CGF.EmitCXXDestructorCall(Dtor, Type, /*ForVirtualBase=*/false,
+ /*Delegating=*/true, Addr, ThisTy);
+ }
+};
} // end anonymous namespace
-void
-CodeGenFunction::EmitDelegatingCXXConstructorCall(const CXXConstructorDecl *Ctor,
- const FunctionArgList &Args) {
+void CodeGenFunction::EmitDelegatingCXXConstructorCall(
+ const CXXConstructorDecl *Ctor, const FunctionArgList &Args) {
assert(Ctor->isDelegatingConstructor());
Address ThisPtr = LoadCXXThisAddress();
- AggValueSlot AggSlot =
- AggValueSlot::forAddr(ThisPtr, Qualifiers(),
- AggValueSlot::IsDestructed,
- AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsNotAliased,
- AggValueSlot::MayOverlap,
- AggValueSlot::IsNotZeroed,
- // Checks are made by the code that calls constructor.
- AggValueSlot::IsSanitizerChecked);
+ AggValueSlot AggSlot = AggValueSlot::forAddr(
+ ThisPtr, Qualifiers(), AggValueSlot::IsDestructed,
+ AggValueSlot::DoesNotNeedGCBarriers, AggValueSlot::IsNotAliased,
+ AggValueSlot::MayOverlap, AggValueSlot::IsNotZeroed,
+ // Checks are made by the code that calls constructor.
+ AggValueSlot::IsSanitizerChecked);
EmitAggExpr(Ctor->init_begin()[0]->getInit(), AggSlot);
const CXXRecordDecl *ClassDecl = Ctor->getParent();
if (CGM.getLangOpts().Exceptions && !ClassDecl->hasTrivialDestructor()) {
CXXDtorType Type =
- CurGD.getCtorType() == Ctor_Complete ? Dtor_Complete : Dtor_Base;
+ CurGD.getCtorType() == Ctor_Complete ? Dtor_Complete : Dtor_Base;
- EHStack.pushCleanup<CallDelegatingCtorDtor>(EHCleanup,
- ClassDecl->getDestructor(),
- ThisPtr, Type);
+ EHStack.pushCleanup<CallDelegatingCtorDtor>(
+ EHCleanup, ClassDecl->getDestructor(), ThisPtr, Type);
}
}
@@ -2688,20 +2652,20 @@ void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD,
}
namespace {
- struct CallLocalDtor final : EHScopeStack::Cleanup {
- const CXXDestructorDecl *Dtor;
- Address Addr;
- QualType Ty;
-
- CallLocalDtor(const CXXDestructorDecl *D, Address Addr, QualType Ty)
- : Dtor(D), Addr(Addr), Ty(Ty) {}
-
- void Emit(CodeGenFunction &CGF, Flags flags) override {
- CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete,
- /*ForVirtualBase=*/false,
- /*Delegating=*/false, Addr, Ty);
- }
- };
+struct CallLocalDtor final : EHScopeStack::Cleanup {
+ const CXXDestructorDecl *Dtor;
+ Address Addr;
+ QualType Ty;
+
+ CallLocalDtor(const CXXDestructorDecl *D, Address Addr, QualType Ty)
+ : Dtor(D), Addr(Addr), Ty(Ty) {}
+
+ void Emit(CodeGenFunction &CGF, Flags flags) override {
+ CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete,
+ /*ForVirtualBase=*/false,
+ /*Delegating=*/false, Addr, Ty);
+ }
+};
} // end anonymous namespace
void CodeGenFunction::PushDestructorCleanup(const CXXDestructorDecl *D,
@@ -2711,8 +2675,10 @@ void CodeGenFunction::PushDestructorCleanup(const CXXDestructorDecl *D,
void CodeGenFunction::PushDestructorCleanup(QualType T, Address Addr) {
CXXRecordDecl *ClassDecl = T->getAsCXXRecordDecl();
- if (!ClassDecl) return;
- if (ClassDecl->hasTrivialDestructor()) return;
+ if (!ClassDecl)
+ return;
+ if (ClassDecl->hasTrivialDestructor())
+ return;
const CXXDestructorDecl *D = ClassDecl->getDestructor();
assert(D && D->isUsed() && "destructor not marked as used!");
@@ -2818,7 +2784,7 @@ void CodeGenFunction::getVTablePointers(BaseSubobject Base,
continue;
const ASTRecordLayout &Layout =
- getContext().getASTRecordLayout(VTableClass);
+ getContext().getASTRecordLayout(VTableClass);
BaseOffset = Layout.getVBaseClassOffset(BaseDecl);
BaseOffsetFromNearestVBase = CharUnits::Zero();
@@ -2828,7 +2794,7 @@ void CodeGenFunction::getVTablePointers(BaseSubobject Base,
BaseOffset = Base.getBaseOffset() + Layout.getBaseClassOffset(BaseDecl);
BaseOffsetFromNearestVBase =
- OffsetFromNearestVBase + Layout.getBaseClassOffset(BaseDecl);
+ OffsetFromNearestVBase + Layout.getBaseClassOffset(BaseDecl);
BaseDeclIsNonVirtualPrimaryBase = Layout.getPrimaryBase() == BaseDecl;
}
@@ -2853,8 +2819,7 @@ void CodeGenFunction::InitializeVTablePointers(const CXXRecordDecl *RD) {
CGM.getCXXABI().initializeHiddenVirtualInheritanceMembers(*this, RD);
}
-llvm::Value *CodeGenFunction::GetVTablePtr(Address This,
- llvm::Type *VTableTy,
+llvm::Value *CodeGenFunction::GetVTablePtr(Address This, llvm::Type *VTableTy,
const CXXRecordDecl *RD,
VTableAuthMode AuthMode) {
Address VTablePtrSrc = This.withElementType(VTableTy);
@@ -2942,8 +2907,7 @@ void CodeGenFunction::EmitTypeMetadataCodeForVCall(const CXXRecordDecl *RD,
CGM.getCodeGenOpts().DevirtualizeSpeculatively) {
CanQualType Ty = CGM.getContext().getCanonicalTagType(RD);
llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(Ty);
- llvm::Value *TypeId =
- llvm::MetadataAsValue::get(CGM.getLLVMContext(), MD);
+ llvm::Value *TypeId = llvm::MetadataAsValue::get(CGM.getLLVMContext(), MD);
// If we already know that the call has hidden LTO visibility, emit
// @llvm.type.test(). Otherwise emit @llvm.public.type.test(), which WPD
@@ -3161,7 +3125,7 @@ void CodeGenFunction::EmitForwardingCallToLambda(
// Prepare the return slot.
const FunctionProtoType *FPT =
- callOperator->getType()->castAs<FunctionProtoType>();
+ callOperator->getType()->castAs<FunctionProtoType>();
QualType resultType = FPT->getReturnType();
ReturnValueSlot returnSlot;
if (!resultType->isVoidType() &&
@@ -3216,7 +3180,7 @@ void CodeGenFunction::EmitLambdaBlockInvokeBody() {
EmitDelegateCallArg(CallArgs, param, param->getBeginLoc());
assert(!Lambda->isGenericLambda() &&
- "generic lambda interconversion to block not implemented");
+ "generic lambda interconversion to block not implemented");
EmitForwardingCallToLambda(CallOp, CallArgs);
}
@@ -3255,7 +3219,8 @@ void CodeGenFunction::EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD,
if (Lambda->isGenericLambda()) {
assert(MD->isFunctionTemplateSpecialization());
const TemplateArgumentList *TAL = MD->getTemplateSpecializationArgs();
- FunctionTemplateDecl *CallOpTemplate = CallOp->getDescribedFunctionTemplate();
+ FunctionTemplateDecl *CallOpTemplate =
+ CallOp->getDescribedFunctionTemplate();
void *InsertPos = nullptr;
FunctionDecl *CorrespondingCallOpSpecialization =
CallOpTemplate->findSpecialization(TAL->asArray(), InsertPos);
@@ -3279,7 +3244,8 @@ void CodeGenFunction::EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD,
void CodeGenFunction::EmitLambdaInAllocaCallOpBody(const CXXMethodDecl *MD) {
if (MD->isVariadic()) {
// FIXME: Making this work correctly is nasty because it requires either
- // cloning the body of the call operator or making the call operator forward.
+ // cloning the body of the call operator or making the call operator
+ // forward.
CGM.ErrorUnsupported(MD, "lambda conversion to variadic function");
return;
}
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index 7cc4d6c8f06f6..28136313a0ca4 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -50,11 +50,13 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
bool IsResultUnused;
AggValueSlot EnsureSlot(QualType T) {
- if (!Dest.isIgnored()) return Dest;
+ if (!Dest.isIgnored())
+ return Dest;
return CGF.CreateAggTemp(T, "agg.tmp.ensured");
}
void EnsureDest(QualType T) {
- if (!Dest.isIgnored()) return;
+ if (!Dest.isIgnored())
+ return;
Dest = CGF.CreateAggTemp(T, "agg.tmp.ensured");
}
@@ -72,8 +74,8 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
public:
AggExprEmitter(CodeGenFunction &cgf, AggValueSlot Dest, bool IsResultUnused)
- : CGF(cgf), Builder(CGF.Builder), Dest(Dest),
- IsResultUnused(IsResultUnused) { }
+ : CGF(cgf), Builder(CGF.Builder), Dest(Dest),
+ IsResultUnused(IsResultUnused) {}
//===--------------------------------------------------------------------===//
// Utilities
@@ -114,9 +116,7 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
StmtVisitor<AggExprEmitter>::Visit(E);
}
- void VisitStmt(Stmt *S) {
- CGF.ErrorUnsupported(S, "aggregate expression");
- }
+ void VisitStmt(Stmt *S) { CGF.ErrorUnsupported(S, "aggregate expression"); }
void VisitParenExpr(ParenExpr *PE) { Visit(PE->getSubExpr()); }
void VisitGenericSelectionExpr(GenericSelectionExpr *GE) {
Visit(GE->getResultExpr());
@@ -157,9 +157,7 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
void VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
EmitAggLoadOfLValue(E);
}
- void VisitPredefinedExpr(const PredefinedExpr *E) {
- EmitAggLoadOfLValue(E);
- }
+ void VisitPredefinedExpr(const PredefinedExpr *E) { EmitAggLoadOfLValue(E); }
// Operators.
void VisitCastExpr(CastExpr *E);
@@ -175,9 +173,7 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
}
void VisitObjCMessageExpr(ObjCMessageExpr *E);
- void VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
- EmitAggLoadOfLValue(E);
- }
+ void VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { EmitAggLoadOfLValue(E); }
void VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *E);
void VisitAbstractConditionalOperator(const AbstractConditionalOperator *CO);
@@ -189,7 +185,7 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
void VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E,
llvm::Value *outerBegin = nullptr);
void VisitImplicitValueInitExpr(ImplicitValueInitExpr *E);
- void VisitNoInitExpr(NoInitExpr *E) { } // Do nothing.
+ void VisitNoInitExpr(NoInitExpr *E) {} // Do nothing.
void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) {
CodeGenFunction::CXXDefaultArgExprScope Scope(CGF, DAE);
Visit(DAE->getExpr());
@@ -244,7 +240,7 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
Visit(E->getSelectedExpr());
}
};
-} // end anonymous namespace.
+} // end anonymous namespace.
//===----------------------------------------------------------------------===//
// Utilities
@@ -393,10 +389,8 @@ void AggExprEmitter::EmitCopy(QualType type, const AggValueSlot &dest,
if (dest.requiresGCollection()) {
CharUnits sz = dest.getPreferredSize(CGF.getContext(), type);
llvm::Value *size = llvm::ConstantInt::get(CGF.SizeTy, sz.getQuantity());
- CGF.CGM.getObjCRuntime().EmitGCMemmoveCollectable(CGF,
- dest.getAddress(),
- src.getAddress(),
- size);
+ CGF.CGM.getObjCRuntime().EmitGCMemmoveCollectable(CGF, dest.getAddress(),
+ src.getAddress(), size);
return;
}
@@ -411,8 +405,8 @@ void AggExprEmitter::EmitCopy(QualType type, const AggValueSlot &dest,
/// Emit the initializer for a std::initializer_list initialized with a
/// real initializer list.
-void
-AggExprEmitter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) {
+void AggExprEmitter::VisitCXXStdInitializerListExpr(
+ CXXStdInitializerListExpr *E) {
// Emit an array containing the elements. The array is externally destructed
// if the std::initializer_list object is.
ASTContext &Ctx = CGF.getContext();
@@ -454,7 +448,7 @@ AggExprEmitter::VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E) {
ArrayType->getElementType()) &&
"Expected std::initializer_list second field to be const E *");
llvm::Value *Zero = llvm::ConstantInt::get(CGF.PtrDiffTy, 0);
- llvm::Value *IdxEnd[] = { Zero, Size };
+ llvm::Value *IdxEnd[] = {Zero, Size};
llvm::Value *ArrayEnd = Builder.CreateInBoundsGEP(
ArrayPtr.getElementType(), ArrayPtr.emitRawPointer(CGF), IdxEnd,
"arrayend");
@@ -571,7 +565,7 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType,
CGF.getContext().getAsArrayType(ArrayQTy)->getElementType();
CharUnits elementSize = CGF.getContext().getTypeSizeInChars(elementType);
CharUnits elementAlign =
- DestPtr.getAlignment().alignmentOfArrayElement(elementSize);
+ DestPtr.getAlignment().alignmentOfArrayElement(elementSize);
llvm::Type *llvmElementType = CGF.ConvertTypeForMem(elementType);
// Consider initializing the array by copying from a global. For this to be
@@ -686,7 +680,8 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType,
llvmElementType, element,
llvm::ConstantInt::get(CGF.SizeTy, NumInitElements),
"arrayinit.start");
- if (endOfInit.isValid()) Builder.CreateStore(element, endOfInit);
+ if (endOfInit.isValid())
+ Builder.CreateStore(element, endOfInit);
}
// Compute the end of the array.
@@ -700,7 +695,7 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType,
// Jump into the body.
CGF.EmitBlock(bodyBB);
llvm::PHINode *currentElement =
- Builder.CreatePHI(element->getType(), 2, "arrayinit.cur");
+ Builder.CreatePHI(element->getType(), 2, "arrayinit.cur");
currentElement->addIncoming(element, entryBB);
// Emit the actual filler expression.
@@ -724,11 +719,12 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType,
llvmElementType, currentElement, one, "arrayinit.next");
// Tell the EH cleanup that we finished with the last element.
- if (endOfInit.isValid()) Builder.CreateStore(nextElement, endOfInit);
+ if (endOfInit.isValid())
+ Builder.CreateStore(nextElement, endOfInit);
// Leave the loop if we're done.
- llvm::Value *done = Builder.CreateICmpEQ(nextElement, end,
- "arrayinit.done");
+ llvm::Value *done =
+ Builder.CreateICmpEQ(nextElement, end, "arrayinit.done");
llvm::BasicBlock *endBB = CGF.createBasicBlock("arrayinit.end");
Builder.CreateCondBr(done, endBB, bodyBB);
currentElement->addIncoming(nextElement, Builder.GetInsertBlock());
@@ -741,7 +737,8 @@ void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType,
// Visitor Methods
//===----------------------------------------------------------------------===//
-void AggExprEmitter::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E){
+void AggExprEmitter::VisitMaterializeTemporaryExpr(
+ MaterializeTemporaryExpr *E) {
Visit(E->getSubExpr());
}
@@ -753,8 +750,7 @@ void AggExprEmitter::VisitOpaqueValueExpr(OpaqueValueExpr *e) {
EmitFinalDestCopy(e->getType(), CGF.getOrCreateOpaqueLValueMapping(e));
}
-void
-AggExprEmitter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
+void AggExprEmitter::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
if (Dest.isPotentiallyAliased()) {
// Just emit a load of the lvalue + a copy, because our compound literal
// might alias the destination.
@@ -798,8 +794,8 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
case CK_Dynamic: {
// FIXME: Can this actually happen? We have no test coverage for it.
assert(isa<CXXDynamicCastExpr>(E) && "CK_Dynamic without a dynamic_cast?");
- LValue LV = CGF.EmitCheckedLValue(E->getSubExpr(),
- CodeGenFunction::TCK_Load);
+ LValue LV =
+ CGF.EmitCheckedLValue(E->getSubExpr(), CodeGenFunction::TCK_Load);
// FIXME: Do we also need to handle property references here?
if (LV.isSimple())
CGF.EmitDynamicCast(LV.getAddress(), cast<CXXDynamicCastExpr>(E));
@@ -848,7 +844,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
case CK_BaseToDerived:
case CK_UncheckedDerivedToBase: {
llvm_unreachable("cannot perform hierarchy conversion in EmitAggExpr: "
- "should have been unpacked before we got here");
+ "should have been unpacked before we got here");
}
case CK_NonAtomicToAtomic:
@@ -858,11 +854,12 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
// Determine the atomic and value types.
QualType atomicType = E->getSubExpr()->getType();
QualType valueType = E->getType();
- if (isToAtomic) std::swap(atomicType, valueType);
+ if (isToAtomic)
+ std::swap(atomicType, valueType);
assert(atomicType->isAtomicType());
- assert(CGF.getContext().hasSameUnqualifiedType(valueType,
- atomicType->castAs<AtomicType>()->getValueType()));
+ assert(CGF.getContext().hasSameUnqualifiedType(
+ valueType, atomicType->castAs<AtomicType>()->getValueType()));
// Just recurse normally if we're ignoring the result or the
// atomic type doesn't change representation.
@@ -871,14 +868,14 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
}
CastKind peepholeTarget =
- (isToAtomic ? CK_AtomicToNonAtomic : CK_NonAtomicToAtomic);
+ (isToAtomic ? CK_AtomicToNonAtomic : CK_NonAtomicToAtomic);
// These two cases are reverses of each other; try to peephole them.
if (Expr *op =
findPeephole(E->getSubExpr(), peepholeTarget, CGF.getContext())) {
assert(CGF.getContext().hasSameUnqualifiedType(op->getType(),
E->getType()) &&
- "peephole significantly changed types?");
+ "peephole significantly changed types?");
return Visit(op);
}
@@ -895,13 +892,11 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
// Build a GEP to refer to the subobject.
Address valueAddr =
CGF.Builder.CreateStructGEP(valueDest.getAddress(), 0);
- valueDest = AggValueSlot::forAddr(valueAddr,
- valueDest.getQualifiers(),
- valueDest.isExternallyDestructed(),
- valueDest.requiresGCollection(),
- valueDest.isPotentiallyAliased(),
- AggValueSlot::DoesNotOverlap,
- AggValueSlot::IsZeroed);
+ valueDest = AggValueSlot::forAddr(
+ valueAddr, valueDest.getQualifiers(),
+ valueDest.isExternallyDestructed(), valueDest.requiresGCollection(),
+ valueDest.isPotentiallyAliased(), AggValueSlot::DoesNotOverlap,
+ AggValueSlot::IsZeroed);
}
CGF.EmitAggExpr(E->getSubExpr(), valueDest);
@@ -911,7 +906,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
// Otherwise, we're converting an atomic type to a non-atomic type.
// Make an atomic temporary, emit into that, and then copy the value out.
AggValueSlot atomicSlot =
- CGF.CreateAggTemp(atomicType, "atomic-to-nonatomic.temp");
+ CGF.CreateAggTemp(atomicType, "atomic-to-nonatomic.temp");
CGF.EmitAggExpr(E->getSubExpr(), atomicSlot);
Address valueAddr = Builder.CreateStructGEP(atomicSlot.getAddress(), 0);
@@ -919,7 +914,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
return EmitFinalDestCopy(valueType, rvalue);
}
case CK_AddressSpaceConversion:
- return Visit(E->getSubExpr());
+ return Visit(E->getSubExpr());
case CK_LValueToRValue:
// If we're loading from a volatile type, force the destination
@@ -1054,9 +1049,8 @@ void AggExprEmitter::VisitCallExpr(const CallExpr *E) {
return;
}
- withReturnValueSlot(E, [&](ReturnValueSlot Slot) {
- return CGF.EmitCallExpr(E, Slot);
- });
+ withReturnValueSlot(
+ E, [&](ReturnValueSlot Slot) { return CGF.EmitCallExpr(E, Slot); });
}
void AggExprEmitter::VisitObjCMessageExpr(ObjCMessageExpr *E) {
@@ -1219,7 +1213,7 @@ void AggExprEmitter::VisitBinaryOperator(const BinaryOperator *E) {
}
void AggExprEmitter::VisitPointerToDataMemberBinaryOperator(
- const BinaryOperator *E) {
+ const BinaryOperator *E) {
LValue LV = CGF.EmitPointerToDataMemberBinaryExpr(E);
EmitFinalDestCopy(E->getType(), LV);
}
@@ -1252,37 +1246,36 @@ static bool isBlockVarRef(const Expr *E) {
// FIXME: pointer arithmetic?
return false;
- // Check both sides of a conditional operator.
- } else if (const AbstractConditionalOperator *op
- = dyn_cast<AbstractConditionalOperator>(E)) {
- return isBlockVarRef(op->getTrueExpr())
- || isBlockVarRef(op->getFalseExpr());
+ // Check both sides of a conditional operator.
+ } else if (const AbstractConditionalOperator *op =
+ dyn_cast<AbstractConditionalOperator>(E)) {
+ return isBlockVarRef(op->getTrueExpr()) ||
+ isBlockVarRef(op->getFalseExpr());
- // OVEs are required to support BinaryConditionalOperators.
- } else if (const OpaqueValueExpr *op
- = dyn_cast<OpaqueValueExpr>(E)) {
+ // OVEs are required to support BinaryConditionalOperators.
+ } else if (const OpaqueValueExpr *op = dyn_cast<OpaqueValueExpr>(E)) {
if (const Expr *src = op->getSourceExpr())
return isBlockVarRef(src);
- // Casts are necessary to get things like (*(int*)&var) = foo().
- // We don't really care about the kind of cast here, except
- // we don't want to look through l2r casts, because it's okay
- // to get the *value* in a __block variable.
+ // Casts are necessary to get things like (*(int*)&var) = foo().
+ // We don't really care about the kind of cast here, except
+ // we don't want to look through l2r casts, because it's okay
+ // to get the *value* in a __block variable.
} else if (const CastExpr *cast = dyn_cast<CastExpr>(E)) {
if (cast->getCastKind() == CK_LValueToRValue)
return false;
return isBlockVarRef(cast->getSubExpr());
- // Handle unary operators. Again, just aggressively look through
- // it, ignoring the operation.
+ // Handle unary operators. Again, just aggressively look through
+ // it, ignoring the operation.
} else if (const UnaryOperator *uop = dyn_cast<UnaryOperator>(E)) {
return isBlockVarRef(uop->getSubExpr());
- // Look into the base of a field access.
+ // Look into the base of a field access.
} else if (const MemberExpr *mem = dyn_cast<MemberExpr>(E)) {
return isBlockVarRef(mem->getBase());
- // Look into the base of a subscript.
+ // Look into the base of a subscript.
} else if (const ArraySubscriptExpr *sub = dyn_cast<ArraySubscriptExpr>(E)) {
return isBlockVarRef(sub->getBase());
}
@@ -1295,8 +1288,8 @@ void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) {
// For an assignment to work, the value on the right has
// to be compatible with the value on the left.
assert(CGF.getContext().hasSameUnqualifiedType(E->getLHS()->getType(),
- E->getRHS()->getType())
- && "Invalid assignment");
+ E->getRHS()->getType()) &&
+ "Invalid assignment");
// If the LHS might be a __block variable, and the RHS can
// potentially cause a block copy, we need to evaluate the RHS first
@@ -1344,8 +1337,7 @@ void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) {
LHS, AggValueSlot::IsDestructed, needsGC(E->getLHS()->getType()),
AggValueSlot::IsAliased, AggValueSlot::MayOverlap);
// A non-volatile aggregate destination might have volatile member.
- if (!LHSSlot.isVolatile() &&
- CGF.hasVolatileMember(E->getLHS()->getType()))
+ if (!LHSSlot.isVolatile() && CGF.hasVolatileMember(E->getLHS()->getType()))
LHSSlot.setVolatile(true);
CGF.EmitAggExpr(E->getRHS(), LHSSlot);
@@ -1359,8 +1351,8 @@ void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) {
E->getType());
}
-void AggExprEmitter::
-VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
+void AggExprEmitter::VisitAbstractConditionalOperator(
+ const AbstractConditionalOperator *E) {
llvm::BasicBlock *LHSBlock = CGF.createBasicBlock("cond.true");
llvm::BasicBlock *RHSBlock = CGF.createBasicBlock("cond.false");
llvm::BasicBlock *ContBlock = CGF.createBasicBlock("cond.end");
@@ -1445,8 +1437,7 @@ void AggExprEmitter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) {
CGF.EmitCXXTemporary(E->getTemporary(), E->getType(), Dest.getAddress());
}
-void
-AggExprEmitter::VisitCXXConstructExpr(const CXXConstructExpr *E) {
+void AggExprEmitter::VisitCXXConstructExpr(const CXXConstructExpr *E) {
AggValueSlot Slot = EnsureSlot(E->getType());
CGF.EmitCXXConstructExpr(E, Slot);
}
@@ -1454,13 +1445,12 @@ AggExprEmitter::VisitCXXConstructExpr(const CXXConstructExpr *E) {
void AggExprEmitter::VisitCXXInheritedCtorInitExpr(
const CXXInheritedCtorInitExpr *E) {
AggValueSlot Slot = EnsureSlot(E->getType());
- CGF.EmitInheritedCXXConstructorCall(
- E->getConstructor(), E->constructsVBase(), Slot.getAddress(),
- E->inheritedFromVBase(), E);
+ CGF.EmitInheritedCXXConstructorCall(E->getConstructor(), E->constructsVBase(),
+ Slot.getAddress(),
+ E->inheritedFromVBase(), E);
}
-void
-AggExprEmitter::VisitLambdaExpr(LambdaExpr *E) {
+void AggExprEmitter::VisitLambdaExpr(LambdaExpr *E) {
AggValueSlot Slot = EnsureSlot(E->getType());
LValue SlotLV = CGF.MakeAddrLValue(Slot.getAddress(), E->getType());
@@ -1644,9 +1634,7 @@ static bool isSimpleZero(const Expr *E, CodeGenFunction &CGF) {
return false;
}
-
-void
-AggExprEmitter::EmitInitializationToLValue(Expr *E, LValue LV) {
+void AggExprEmitter::EmitInitializationToLValue(Expr *E, LValue LV) {
QualType type = LV.getType();
// FIXME: Ignore result?
// FIXME: Are initializers affected by volatile?
@@ -1789,10 +1777,8 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr(
Dest.getAddress(), CXXRD, BaseRD,
/*isBaseVirtual*/ false);
AggValueSlot AggSlot = AggValueSlot::forAddr(
- V, Qualifiers(),
- AggValueSlot::IsDestructed,
- AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsNotAliased,
+ V, Qualifiers(), AggValueSlot::IsDestructed,
+ AggValueSlot::DoesNotNeedGCBarriers, AggValueSlot::IsNotAliased,
CGF.getOverlapForBaseInit(CXXRD, BaseRD, Base.isVirtual()));
CGF.EmitAggExpr(InitExprs[curInitIndex++], AggSlot);
@@ -1888,8 +1874,8 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr(
// Push a destructor if necessary.
// FIXME: if we have an array of structures, all explicitly
// initialized, we can end up pushing a linear number of cleanups.
- if (QualType::DestructionKind dtorKind
- = field->getType().isDestructedType()) {
+ if (QualType::DestructionKind dtorKind =
+ field->getType().isDestructedType()) {
assert(LV.isSimple());
if (dtorKind) {
CGF.pushDestroyAndDeferDeactivation(NormalAndEHCleanup, LV.getAddress(),
@@ -2044,7 +2030,8 @@ void AggExprEmitter::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E,
CGF.DeactivateCleanupBlock(cleanup, index);
}
-void AggExprEmitter::VisitDesignatedInitUpdateExpr(DesignatedInitUpdateExpr *E) {
+void AggExprEmitter::VisitDesignatedInitUpdateExpr(
+ DesignatedInitUpdateExpr *E) {
AggValueSlot Dest = EnsureSlot(E->getType());
LValue DestLV = CGF.MakeAddrLValue(Dest.getAddress(), E->getType());
@@ -2065,7 +2052,8 @@ static CharUnits GetNumNonZeroBytesInInit(const Expr *E, CodeGenFunction &CGF) {
E = E->IgnoreParenNoopCasts(CGF.getContext());
// 0 and 0.0 won't require any non-zero stores!
- if (isSimpleZero(E, CGF)) return CharUnits::Zero();
+ if (isSimpleZero(E, CGF))
+ return CharUnits::Zero();
// If this is an initlist expr, sum up the size of sizes of the (present)
// elements. If this is something weird, assume the whole thing is non-zero.
@@ -2146,7 +2134,7 @@ static void CheckAggExprForMemSetUse(AggValueSlot &Slot, const Expr *E,
// Check to see if over 3/4 of the initializer are known to be zero. If so,
// we prefer to emit memset + individual stores for the rest.
CharUnits NumNonZeroBytes = GetNumNonZeroBytesInInit(E, CGF);
- if (NumNonZeroBytes*4 > Size)
+ if (NumNonZeroBytes * 4 > Size)
return;
// Okay, it seems like a good idea to use an initial memset, emit the call.
@@ -2159,9 +2147,6 @@ static void CheckAggExprForMemSetUse(AggValueSlot &Slot, const Expr *E,
Slot.setZeroed();
}
-
-
-
/// EmitAggExpr - Emit the computation of the specified expression of aggregate
/// type. The result is computed into DestPtr. Note that if DestPtr is null,
/// the value of the aggregate expression is not needed. If VolatileDest is
@@ -2175,7 +2160,7 @@ void CodeGenFunction::EmitAggExpr(const Expr *E, AggValueSlot Slot) {
// Optimize the slot if possible.
CheckAggExprForMemSetUse(Slot, E, *this);
- AggExprEmitter(*this, Slot, Slot.isIgnored()).Visit(const_cast<Expr*>(E));
+ AggExprEmitter(*this, Slot, Slot.isIgnored()).Visit(const_cast<Expr *>(E));
}
LValue CodeGenFunction::EmitAggExprToLValue(const Expr *E) {
diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index 074c124dbf01b..78c10ec757bca 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/lib/CodeGen/CGExprCXX.cpp
@@ -30,7 +30,7 @@ struct MemberCallInfo {
// Number of prefix arguments for the call. Ignores the `this` pointer.
unsigned PrefixSize;
};
-}
+} // namespace
static MemberCallInfo
commonEmitCXXMemberOrOperatorCall(CodeGenFunction &CGF, GlobalDecl GD,
@@ -125,8 +125,8 @@ RValue CodeGenFunction::EmitCXXDestructorCall(
CE ? CE->getExprLoc() : SourceLocation{});
}
-RValue CodeGenFunction::EmitCXXPseudoDestructorExpr(
- const CXXPseudoDestructorExpr *E) {
+RValue
+CodeGenFunction::EmitCXXPseudoDestructorExpr(const CXXPseudoDestructorExpr *E) {
QualType DestroyedType = E->getDestroyedType();
if (DestroyedType.hasStrongOrWeakObjCLifetime()) {
// Automatic Reference Counting:
@@ -155,9 +155,9 @@ RValue CodeGenFunction::EmitCXXPseudoDestructorExpr(
break;
case Qualifiers::OCL_Strong:
- EmitARCRelease(Builder.CreateLoad(BaseValue,
- DestroyedType.isVolatileQualified()),
- ARCPreciseLifetime);
+ EmitARCRelease(
+ Builder.CreateLoad(BaseValue, DestroyedType.isVolatileQualified()),
+ ARCPreciseLifetime);
break;
case Qualifiers::OCL_Weak:
@@ -272,7 +272,7 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
RtlArgs = &RtlArgStorage;
EmitCallArgs(*RtlArgs, MD->getType()->castAs<FunctionProtoType>(),
drop_begin(CE->arguments(), 1), CE->getDirectCallee(),
- /*ParamsToSkip*/0, EvaluationOrder::ForceRightToLeft);
+ /*ParamsToSkip*/ 0, EvaluationOrder::ForceRightToLeft);
}
}
}
@@ -316,9 +316,8 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
// It's important that we use the result of EmitLValue here rather than
// emitting call arguments, in order to preserve TBAA information from
// the RHS.
- LValue RHS = isa<CXXOperatorCallExpr>(CE)
- ? TrivialAssignmentRHS
- : EmitLValue(*CE->arg_begin());
+ LValue RHS = isa<CXXOperatorCallExpr>(CE) ? TrivialAssignmentRHS
+ : EmitLValue(*CE->arg_begin());
EmitAggregateAssign(This, RHS, CE->getType());
return RValue::get(This.getPointer(*this));
}
@@ -469,9 +468,8 @@ CodeGenFunction::EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E,
// Ask the ABI to load the callee. Note that This is modified.
llvm::Value *ThisPtrForCall = nullptr;
- CGCallee Callee =
- CGM.getCXXABI().EmitLoadOfMemberFunctionPointer(*this, BO, This,
- ThisPtrForCall, MemFnPtr, MPT);
+ CGCallee Callee = CGM.getCXXABI().EmitLoadOfMemberFunctionPointer(
+ *this, BO, This, ThisPtrForCall, MemFnPtr, MPT);
CallArgList Args;
@@ -584,9 +582,9 @@ static void EmitNullBaseClassInitialization(CodeGenFunction &CGF,
StoreSizeVal);
}
- // Otherwise, just memset the whole thing to zero. This is legal
- // because in LLVM, all default initializers (other than the ones we just
- // handled above) are guaranteed to have a bit pattern of all zeros.
+ // Otherwise, just memset the whole thing to zero. This is legal
+ // because in LLVM, all default initializers (other than the ones we just
+ // handled above) are guaranteed to have a bit pattern of all zeros.
} else {
for (std::pair<CharUnits, CharUnits> Store : Stores) {
CharUnits StoreOffset = Store.first;
@@ -599,9 +597,8 @@ static void EmitNullBaseClassInitialization(CodeGenFunction &CGF,
}
}
-void
-CodeGenFunction::EmitCXXConstructExpr(const CXXConstructExpr *E,
- AggValueSlot Dest) {
+void CodeGenFunction::EmitCXXConstructExpr(const CXXConstructExpr *E,
+ AggValueSlot Dest) {
assert(!Dest.isIgnored() && "Must have a destination!");
const CXXConstructorDecl *CD = E->getConstructor();
@@ -642,8 +639,7 @@ CodeGenFunction::EmitCXXConstructExpr(const CXXConstructExpr *E,
return;
}
- if (const ArrayType *arrayType
- = getContext().getAsArrayType(E->getType())) {
+ if (const ArrayType *arrayType = getContext().getAsArrayType(E->getType())) {
EmitCXXAggrConstructorCall(CD, arrayType, Dest.getAddress(), E,
Dest.isSanitizerChecked());
} else {
@@ -668,10 +664,10 @@ CodeGenFunction::EmitCXXConstructExpr(const CXXConstructExpr *E,
case CXXConstructionKind::NonVirtualBase:
Type = Ctor_Base;
- }
+ }
- // Call the constructor.
- EmitCXXConstructorCall(CD, Type, ForVirtualBase, Delegating, Dest, E);
+ // Call the constructor.
+ EmitCXXConstructorCall(CD, Type, ForVirtualBase, Delegating, Dest, E);
}
}
@@ -681,7 +677,7 @@ void CodeGenFunction::EmitSynthesizedCXXCopyCtor(Address Dest, Address Src,
Exp = E->getSubExpr();
assert(isa<CXXConstructExpr>(Exp) &&
"EmitSynthesizedCXXCopyCtor - unknown copy ctor expr");
- const CXXConstructExpr* E = cast<CXXConstructExpr>(Exp);
+ const CXXConstructExpr *E = cast<CXXConstructExpr>(Exp);
const CXXConstructorDecl *CD = E->getConstructor();
RunCleanupsScope Scope(*this);
@@ -692,8 +688,8 @@ void CodeGenFunction::EmitSynthesizedCXXCopyCtor(Address Dest, Address Src,
if (E->requiresZeroInitialization())
EmitNullInitialization(Dest, E->getType());
- assert(!getContext().getAsConstantArrayType(E->getType())
- && "EmitSynthesizedCXXCopyCtor - Copied-in Array");
+ assert(!getContext().getAsConstantArrayType(E->getType()) &&
+ "EmitSynthesizedCXXCopyCtor - Copied-in Array");
EmitSynthesizedCXXCopyCtorCall(CD, Dest, Src, E);
}
@@ -719,8 +715,8 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
if (!e->isArray()) {
CharUnits typeSize = CGF.getContext().getTypeSizeInChars(type);
- sizeWithoutCookie
- = llvm::ConstantInt::get(CGF.SizeTy, typeSize.getQuantity());
+ sizeWithoutCookie =
+ llvm::ConstantInt::get(CGF.SizeTy, typeSize.getQuantity());
return sizeWithoutCookie;
}
@@ -746,16 +742,16 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
// size_t. That's just a gloss, though, and it's wrong in one
// important way: if the count is negative, it's an error even if
// the cookie size would bring the total size >= 0.
- bool isSigned
- = (*e->getArraySize())->getType()->isSignedIntegerOrEnumerationType();
- llvm::IntegerType *numElementsType
- = cast<llvm::IntegerType>(numElements->getType());
+ bool isSigned =
+ (*e->getArraySize())->getType()->isSignedIntegerOrEnumerationType();
+ llvm::IntegerType *numElementsType =
+ cast<llvm::IntegerType>(numElements->getType());
unsigned numElementsWidth = numElementsType->getBitWidth();
// Compute the constant factor.
llvm::APInt arraySizeMultiplier(sizeWidth, 1);
- while (const ConstantArrayType *CAT
- = CGF.getContext().getAsConstantArrayType(type)) {
+ while (const ConstantArrayType *CAT =
+ CGF.getContext().getAsConstantArrayType(type)) {
type = CAT->getElementType();
arraySizeMultiplier *= CAT->getSize();
}
@@ -770,7 +766,7 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
// If someone is doing 'new int[42]' there is no need to do a dynamic check.
// Don't bloat the -O0 code.
if (llvm::ConstantInt *numElementsC =
- dyn_cast<llvm::ConstantInt>(numElements)) {
+ dyn_cast<llvm::ConstantInt>(numElements)) {
const llvm::APInt &count = numElementsC->getValue();
bool hasAnyOverflow = false;
@@ -797,13 +793,13 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
// Scale numElements by that. This might overflow, but we don't
// care because it only overflows if allocationSize does, too, and
// if that overflows then we shouldn't use this.
- numElements = llvm::ConstantInt::get(CGF.SizeTy,
- adjustedCount * arraySizeMultiplier);
+ numElements =
+ llvm::ConstantInt::get(CGF.SizeTy, adjustedCount * arraySizeMultiplier);
// Compute the size before cookie, and track whether it overflowed.
bool overflow;
- llvm::APInt allocationSize
- = adjustedCount.umul_ov(typeSizeMultiplier, overflow);
+ llvm::APInt allocationSize =
+ adjustedCount.umul_ov(typeSizeMultiplier, overflow);
hasAnyOverflow |= overflow;
// Add in the cookie, and check whether it's overflowed.
@@ -823,7 +819,7 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
size = llvm::ConstantInt::get(CGF.SizeTy, allocationSize);
}
- // Otherwise, we might need to use the overflow intrinsics.
+ // Otherwise, we might need to use the overflow intrinsics.
} else {
// There are up to five conditions we need to test for:
// 1) if isSigned, we need to check whether numElements is negative;
@@ -847,13 +843,13 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
llvm::APInt threshold =
llvm::APInt::getOneBitSet(numElementsWidth, sizeWidth);
- llvm::Value *thresholdV
- = llvm::ConstantInt::get(numElementsType, threshold);
+ llvm::Value *thresholdV =
+ llvm::ConstantInt::get(numElementsType, threshold);
hasOverflow = CGF.Builder.CreateICmpUGE(numElements, thresholdV);
numElements = CGF.Builder.CreateTrunc(numElements, CGF.SizeTy);
- // Otherwise, if we're signed, we want to sext up to size_t.
+ // Otherwise, if we're signed, we want to sext up to size_t.
} else if (isSigned) {
if (numElementsWidth < sizeWidth)
numElements = CGF.Builder.CreateSExt(numElements, CGF.SizeTy);
@@ -864,10 +860,10 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
// unsigned overflow. Otherwise, we have to do it here. But at least
// in this case, we can subsume the >= minElements check.
if (typeSizeMultiplier == 1)
- hasOverflow = CGF.Builder.CreateICmpSLT(numElements,
- llvm::ConstantInt::get(CGF.SizeTy, minElements));
+ hasOverflow = CGF.Builder.CreateICmpSLT(
+ numElements, llvm::ConstantInt::get(CGF.SizeTy, minElements));
- // Otherwise, zext up to size_t if necessary.
+ // Otherwise, zext up to size_t if necessary.
} else if (numElementsWidth < sizeWidth) {
numElements = CGF.Builder.CreateZExt(numElements, CGF.SizeTy);
}
@@ -877,15 +873,16 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
if (minElements) {
// Don't allow allocation of fewer elements than we have initializers.
if (!hasOverflow) {
- hasOverflow = CGF.Builder.CreateICmpULT(numElements,
- llvm::ConstantInt::get(CGF.SizeTy, minElements));
+ hasOverflow = CGF.Builder.CreateICmpULT(
+ numElements, llvm::ConstantInt::get(CGF.SizeTy, minElements));
} else if (numElementsWidth > sizeWidth) {
// The other existing overflow subsumes this check.
// We do an unsigned comparison, since any signed value < -1 is
// taken care of either above or below.
- hasOverflow = CGF.Builder.CreateOr(hasOverflow,
- CGF.Builder.CreateICmpULT(numElements,
- llvm::ConstantInt::get(CGF.SizeTy, minElements)));
+ hasOverflow = CGF.Builder.CreateOr(
+ hasOverflow,
+ CGF.Builder.CreateICmpULT(
+ numElements, llvm::ConstantInt::get(CGF.SizeTy, minElements)));
}
}
@@ -899,11 +896,11 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
// can be ignored because the result shouldn't be used if
// allocation fails.
if (typeSizeMultiplier != 1) {
- llvm::Function *umul_with_overflow
- = CGF.CGM.getIntrinsic(llvm::Intrinsic::umul_with_overflow, CGF.SizeTy);
+ llvm::Function *umul_with_overflow =
+ CGF.CGM.getIntrinsic(llvm::Intrinsic::umul_with_overflow, CGF.SizeTy);
llvm::Value *tsmV =
- llvm::ConstantInt::get(CGF.SizeTy, typeSizeMultiplier);
+ llvm::ConstantInt::get(CGF.SizeTy, typeSizeMultiplier);
llvm::Value *result =
CGF.Builder.CreateCall(umul_with_overflow, {size, tsmV});
@@ -923,10 +920,10 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
assert(arraySizeMultiplier == typeSizeMultiplier);
numElements = size;
- // Otherwise we need a separate multiply.
+ // Otherwise we need a separate multiply.
} else {
llvm::Value *asmV =
- llvm::ConstantInt::get(CGF.SizeTy, arraySizeMultiplier);
+ llvm::ConstantInt::get(CGF.SizeTy, arraySizeMultiplier);
numElements = CGF.Builder.CreateMul(numElements, asmV);
}
}
@@ -939,8 +936,8 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
if (cookieSize != 0) {
sizeWithoutCookie = size;
- llvm::Function *uadd_with_overflow
- = CGF.CGM.getIntrinsic(llvm::Intrinsic::uadd_with_overflow, CGF.SizeTy);
+ llvm::Function *uadd_with_overflow =
+ CGF.CGM.getIntrinsic(llvm::Intrinsic::uadd_with_overflow, CGF.SizeTy);
llvm::Value *cookieSizeV = llvm::ConstantInt::get(CGF.SizeTy, cookieSize);
llvm::Value *result =
@@ -959,9 +956,8 @@ static llvm::Value *EmitCXXNewAllocSize(CodeGenFunction &CGF,
// overwrite 'size' with an all-ones value, which should cause
// operator new to throw.
if (hasOverflow)
- size = CGF.Builder.CreateSelect(hasOverflow,
- llvm::Constant::getAllOnesValue(CGF.SizeTy),
- size);
+ size = CGF.Builder.CreateSelect(
+ hasOverflow, llvm::Constant::getAllOnesValue(CGF.SizeTy), size);
}
if (cookieSize == 0)
@@ -978,21 +974,19 @@ static void StoreAnyExprIntoOneUnit(CodeGenFunction &CGF, const Expr *Init,
// FIXME: Refactor with EmitExprAsInit.
switch (CGF.getEvaluationKind(AllocType)) {
case TEK_Scalar:
- CGF.EmitScalarInit(Init, nullptr,
- CGF.MakeAddrLValue(NewPtr, AllocType), false);
+ CGF.EmitScalarInit(Init, nullptr, CGF.MakeAddrLValue(NewPtr, AllocType),
+ false);
return;
case TEK_Complex:
CGF.EmitComplexExprIntoLValue(Init, CGF.MakeAddrLValue(NewPtr, AllocType),
/*isInit*/ true);
return;
case TEK_Aggregate: {
- AggValueSlot Slot
- = AggValueSlot::forAddr(NewPtr, AllocType.getQualifiers(),
- AggValueSlot::IsDestructed,
- AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsNotAliased,
- MayOverlap, AggValueSlot::IsNotZeroed,
- AggValueSlot::IsSanitizerChecked);
+ AggValueSlot Slot = AggValueSlot::forAddr(
+ NewPtr, AllocType.getQualifiers(), AggValueSlot::IsDestructed,
+ AggValueSlot::DoesNotNeedGCBarriers, AggValueSlot::IsNotAliased,
+ MayOverlap, AggValueSlot::IsNotZeroed,
+ AggValueSlot::IsSanitizerChecked);
CGF.EmitAggExpr(Init, Slot);
return;
}
@@ -1021,7 +1015,7 @@ void CodeGenFunction::EmitNewArrayInitializer(
CharUnits ElementSize = getContext().getTypeSizeInChars(ElementType);
CharUnits ElementAlign =
- BeginPtr.getAlignment().alignmentOfArrayElement(ElementSize);
+ BeginPtr.getAlignment().alignmentOfArrayElement(ElementSize);
// Attempt to perform zero-initialization using memset.
auto TryMemsetInitialization = [&]() -> bool {
@@ -1071,22 +1065,19 @@ void CodeGenFunction::EmitNewArrayInitializer(
// Initialize the initial portion of length equal to that of the string
// literal. The allocation must be for at least this much; we emitted a
// check for that earlier.
- AggValueSlot Slot =
- AggValueSlot::forAddr(CurPtr, ElementType.getQualifiers(),
- AggValueSlot::IsDestructed,
- AggValueSlot::DoesNotNeedGCBarriers,
- AggValueSlot::IsNotAliased,
- AggValueSlot::DoesNotOverlap,
- AggValueSlot::IsNotZeroed,
- AggValueSlot::IsSanitizerChecked);
+ AggValueSlot Slot = AggValueSlot::forAddr(
+ CurPtr, ElementType.getQualifiers(), AggValueSlot::IsDestructed,
+ AggValueSlot::DoesNotNeedGCBarriers, AggValueSlot::IsNotAliased,
+ AggValueSlot::DoesNotOverlap, AggValueSlot::IsNotZeroed,
+ AggValueSlot::IsSanitizerChecked);
EmitAggExpr(ILE ? ILE->getInit(0) : Init, Slot);
// Move past these elements.
InitListElements =
cast<ConstantArrayType>(Init->getType()->getAsArrayTypeUnsafe())
->getZExtSize();
- CurPtr = Builder.CreateConstInBoundsGEP(
- CurPtr, InitListElements, "string.init.end");
+ CurPtr = Builder.CreateConstInBoundsGEP(CurPtr, InitListElements,
+ "string.init.end");
// Zero out the rest, if any remain.
llvm::ConstantInt *ConstNum = dyn_cast<llvm::ConstantInt>(NumElements);
@@ -1209,7 +1200,7 @@ void CodeGenFunction::EmitNewArrayInitializer(
NumElements,
llvm::ConstantInt::get(NumElements->getType(), InitListElements));
EmitCXXAggrConstructorCall(Ctor, NumElements, CurPtr, CCE,
- /*NewPointerIsChecked*/true,
+ /*NewPointerIsChecked*/ true,
CCE->requiresZeroInitialization());
return;
}
@@ -1345,10 +1336,9 @@ static RValue EmitNewDeleteCall(CodeGenFunction &CGF,
llvm::CallBase *CallOrInvoke;
llvm::Constant *CalleePtr = CGF.CGM.GetAddrOfFunction(CalleeDecl);
CGCallee Callee = CGCallee::forDirect(CalleePtr, GlobalDecl(CalleeDecl));
- RValue RV =
- CGF.EmitCall(CGF.CGM.getTypes().arrangeFreeFunctionCall(
- Args, CalleeType, /*ChainCall=*/false),
- Callee, ReturnValueSlot(), Args, &CallOrInvoke);
+ RValue RV = CGF.EmitCall(CGF.CGM.getTypes().arrangeFreeFunctionCall(
+ Args, CalleeType, /*ChainCall=*/false),
+ Callee, ReturnValueSlot(), Args, &CallOrInvoke);
/// C++1y [expr.new]p10:
/// [In a new-expression,] an implementation is allowed to omit a call
@@ -1356,8 +1346,8 @@ static RValue EmitNewDeleteCall(CodeGenFunction &CGF,
///
/// We model such elidable calls with the 'builtin' attribute.
llvm::Function *Fn = dyn_cast<llvm::Function>(CalleePtr);
- if (CalleeDecl->isReplaceableGlobalAllocationFunction() &&
- Fn && Fn->hasFnAttribute(llvm::Attribute::NoBuiltin)) {
+ if (CalleeDecl->isReplaceableGlobalAllocationFunction() && Fn &&
+ Fn->hasFnAttribute(llvm::Attribute::NoBuiltin)) {
CallOrInvoke->addFnAttr(llvm::Attribute::Builtin);
}
@@ -1371,8 +1361,8 @@ RValue CodeGenFunction::EmitBuiltinNewDeleteCall(const FunctionProtoType *Type,
EmitCallArgs(Args, Type, TheCall->arguments());
// Find the allocation or deallocation function that we're calling.
ASTContext &Ctx = getContext();
- DeclarationName Name = Ctx.DeclarationNames
- .getCXXOperatorName(IsDelete ? OO_Delete : OO_New);
+ DeclarationName Name =
+ Ctx.DeclarationNames.getCXXOperatorName(IsDelete ? OO_Delete : OO_New);
for (auto *Decl : Ctx.getTranslationUnitDecl()->lookup(Name))
if (auto *FD = dyn_cast<FunctionDecl>(Decl))
@@ -1390,113 +1380,111 @@ RValue CodeGenFunction::EmitBuiltinNewDeleteCall(const FunctionProtoType *Type,
}
namespace {
- /// A cleanup to call the given 'operator delete' function upon abnormal
- /// exit from a new expression. Templated on a traits type that deals with
- /// ensuring that the arguments dominate the cleanup if necessary.
- template<typename Traits>
- class CallDeleteDuringNew final : public EHScopeStack::Cleanup {
- /// Type used to hold llvm::Value*s.
- typedef typename Traits::ValueTy ValueTy;
- /// Type used to hold RValues.
- typedef typename Traits::RValueTy RValueTy;
- struct PlacementArg {
- RValueTy ArgValue;
- QualType ArgType;
- };
-
- unsigned NumPlacementArgs : 30;
- LLVM_PREFERRED_TYPE(AlignedAllocationMode)
- unsigned PassAlignmentToPlacementDelete : 1;
- const FunctionDecl *OperatorDelete;
- RValueTy TypeIdentity;
- ValueTy Ptr;
- ValueTy AllocSize;
- CharUnits AllocAlign;
-
- PlacementArg *getPlacementArgs() {
- return reinterpret_cast<PlacementArg *>(this + 1);
- }
+/// A cleanup to call the given 'operator delete' function upon abnormal
+/// exit from a new expression. Templated on a traits type that deals with
+/// ensuring that the arguments dominate the cleanup if necessary.
+template <typename Traits>
+class CallDeleteDuringNew final : public EHScopeStack::Cleanup {
+ /// Type used to hold llvm::Value*s.
+ typedef typename Traits::ValueTy ValueTy;
+ /// Type used to hold RValues.
+ typedef typename Traits::RValueTy RValueTy;
+ struct PlacementArg {
+ RValueTy ArgValue;
+ QualType ArgType;
+ };
- public:
- static size_t getExtraSize(size_t NumPlacementArgs) {
- return NumPlacementArgs * sizeof(PlacementArg);
- }
+ unsigned NumPlacementArgs : 30;
+ LLVM_PREFERRED_TYPE(AlignedAllocationMode)
+ unsigned PassAlignmentToPlacementDelete : 1;
+ const FunctionDecl *OperatorDelete;
+ RValueTy TypeIdentity;
+ ValueTy Ptr;
+ ValueTy AllocSize;
+ CharUnits AllocAlign;
+
+ PlacementArg *getPlacementArgs() {
+ return reinterpret_cast<PlacementArg *>(this + 1);
+ }
- CallDeleteDuringNew(size_t NumPlacementArgs,
- const FunctionDecl *OperatorDelete,
- RValueTy TypeIdentity, ValueTy Ptr, ValueTy AllocSize,
- const ImplicitAllocationParameters &IAP,
- CharUnits AllocAlign)
- : NumPlacementArgs(NumPlacementArgs),
- PassAlignmentToPlacementDelete(
- isAlignedAllocation(IAP.PassAlignment)),
- OperatorDelete(OperatorDelete), TypeIdentity(TypeIdentity), Ptr(Ptr),
- AllocSize(AllocSize), AllocAlign(AllocAlign) {}
-
- void setPlacementArg(unsigned I, RValueTy Arg, QualType Type) {
- assert(I < NumPlacementArgs && "index out of range");
- getPlacementArgs()[I] = {Arg, Type};
- }
+public:
+ static size_t getExtraSize(size_t NumPlacementArgs) {
+ return NumPlacementArgs * sizeof(PlacementArg);
+ }
- void Emit(CodeGenFunction &CGF, Flags flags) override {
- const auto *FPT = OperatorDelete->getType()->castAs<FunctionProtoType>();
- CallArgList DeleteArgs;
- unsigned FirstNonTypeArg = 0;
- TypeAwareAllocationMode TypeAwareDeallocation =
- TypeAwareAllocationMode::No;
- if (OperatorDelete->isTypeAwareOperatorNewOrDelete()) {
- TypeAwareDeallocation = TypeAwareAllocationMode::Yes;
- QualType SpecializedTypeIdentity = FPT->getParamType(0);
- ++FirstNonTypeArg;
- DeleteArgs.add(Traits::get(CGF, TypeIdentity), SpecializedTypeIdentity);
- }
- // The first argument after type-identity parameter (if any) is always
- // a void* (or C* for a destroying operator delete for class type C).
- DeleteArgs.add(Traits::get(CGF, Ptr), FPT->getParamType(FirstNonTypeArg));
-
- // Figure out what other parameters we should be implicitly passing.
- UsualDeleteParams Params;
- if (NumPlacementArgs) {
- // A placement deallocation function is implicitly passed an alignment
- // if the placement allocation function was, but is never passed a size.
- Params.Alignment =
- alignedAllocationModeFromBool(PassAlignmentToPlacementDelete);
- Params.TypeAwareDelete = TypeAwareDeallocation;
- Params.Size = isTypeAwareAllocation(Params.TypeAwareDelete);
- } else {
- // For a non-placement new-expression, 'operator delete' can take a
- // size and/or an alignment if it has the right parameters.
- Params = OperatorDelete->getUsualDeleteParams();
- }
+ CallDeleteDuringNew(size_t NumPlacementArgs,
+ const FunctionDecl *OperatorDelete, RValueTy TypeIdentity,
+ ValueTy Ptr, ValueTy AllocSize,
+ const ImplicitAllocationParameters &IAP,
+ CharUnits AllocAlign)
+ : NumPlacementArgs(NumPlacementArgs),
+ PassAlignmentToPlacementDelete(isAlignedAllocation(IAP.PassAlignment)),
+ OperatorDelete(OperatorDelete), TypeIdentity(TypeIdentity), Ptr(Ptr),
+ AllocSize(AllocSize), AllocAlign(AllocAlign) {}
+
+ void setPlacementArg(unsigned I, RValueTy Arg, QualType Type) {
+ assert(I < NumPlacementArgs && "index out of range");
+ getPlacementArgs()[I] = {Arg, Type};
+ }
- assert(!Params.DestroyingDelete &&
- "should not call destroying delete in a new-expression");
-
- // The second argument can be a std::size_t (for non-placement delete).
- if (Params.Size)
- DeleteArgs.add(Traits::get(CGF, AllocSize),
- CGF.getContext().getSizeType());
-
- // The next (second or third) argument can be a std::align_val_t, which
- // is an enum whose underlying type is std::size_t.
- // FIXME: Use the right type as the parameter type. Note that in a call
- // to operator delete(size_t, ...), we may not have it available.
- if (isAlignedAllocation(Params.Alignment))
- DeleteArgs.add(RValue::get(llvm::ConstantInt::get(
- CGF.SizeTy, AllocAlign.getQuantity())),
- CGF.getContext().getSizeType());
-
- // Pass the rest of the arguments, which must match exactly.
- for (unsigned I = 0; I != NumPlacementArgs; ++I) {
- auto Arg = getPlacementArgs()[I];
- DeleteArgs.add(Traits::get(CGF, Arg.ArgValue), Arg.ArgType);
- }
+ void Emit(CodeGenFunction &CGF, Flags flags) override {
+ const auto *FPT = OperatorDelete->getType()->castAs<FunctionProtoType>();
+ CallArgList DeleteArgs;
+ unsigned FirstNonTypeArg = 0;
+ TypeAwareAllocationMode TypeAwareDeallocation = TypeAwareAllocationMode::No;
+ if (OperatorDelete->isTypeAwareOperatorNewOrDelete()) {
+ TypeAwareDeallocation = TypeAwareAllocationMode::Yes;
+ QualType SpecializedTypeIdentity = FPT->getParamType(0);
+ ++FirstNonTypeArg;
+ DeleteArgs.add(Traits::get(CGF, TypeIdentity), SpecializedTypeIdentity);
+ }
+ // The first argument after type-identity parameter (if any) is always
+ // a void* (or C* for a destroying operator delete for class type C).
+ DeleteArgs.add(Traits::get(CGF, Ptr), FPT->getParamType(FirstNonTypeArg));
+
+ // Figure out what other parameters we should be implicitly passing.
+ UsualDeleteParams Params;
+ if (NumPlacementArgs) {
+ // A placement deallocation function is implicitly passed an alignment
+ // if the placement allocation function was, but is never passed a size.
+ Params.Alignment =
+ alignedAllocationModeFromBool(PassAlignmentToPlacementDelete);
+ Params.TypeAwareDelete = TypeAwareDeallocation;
+ Params.Size = isTypeAwareAllocation(Params.TypeAwareDelete);
+ } else {
+ // For a non-placement new-expression, 'operator delete' can take a
+ // size and/or an alignment if it has the right parameters.
+ Params = OperatorDelete->getUsualDeleteParams();
+ }
- // Call 'operator delete'.
- EmitNewDeleteCall(CGF, OperatorDelete, FPT, DeleteArgs);
+ assert(!Params.DestroyingDelete &&
+ "should not call destroying delete in a new-expression");
+
+ // The second argument can be a std::size_t (for non-placement delete).
+ if (Params.Size)
+ DeleteArgs.add(Traits::get(CGF, AllocSize),
+ CGF.getContext().getSizeType());
+
+ // The next (second or third) argument can be a std::align_val_t, which
+ // is an enum whose underlying type is std::size_t.
+ // FIXME: Use the right type as the parameter type. Note that in a call
+ // to operator delete(size_t, ...), we may not have it available.
+ if (isAlignedAllocation(Params.Alignment))
+ DeleteArgs.add(RValue::get(llvm::ConstantInt::get(
+ CGF.SizeTy, AllocAlign.getQuantity())),
+ CGF.getContext().getSizeType());
+
+ // Pass the rest of the arguments, which must match exactly.
+ for (unsigned I = 0; I != NumPlacementArgs; ++I) {
+ auto Arg = getPlacementArgs()[I];
+ DeleteArgs.add(Traits::get(CGF, Arg.ArgValue), Arg.ArgType);
}
- };
-}
+
+ // Call 'operator delete'.
+ EmitNewDeleteCall(CGF, OperatorDelete, FPT, DeleteArgs);
+ }
+};
+} // namespace
/// Enter a cleanup to call 'operator delete' if the initializer in a
/// new-expression throws.
@@ -1534,7 +1522,7 @@ static void EnterNewDeleteCleanup(CodeGenFunction &CGF, const CXXNewExpr *E,
DominatingValue<RValue>::saved_type SavedNewPtr =
DominatingValue<RValue>::save(CGF, RValue::get(NewPtr, CGF));
DominatingValue<RValue>::saved_type SavedAllocSize =
- DominatingValue<RValue>::save(CGF, RValue::get(AllocSize));
+ DominatingValue<RValue>::save(CGF, RValue::get(AllocSize));
DominatingValue<RValue>::saved_type SavedTypeIdentity =
DominatingValue<RValue>::save(CGF, TypeIdentity);
struct ConditionalCleanupTraits {
@@ -1588,9 +1576,8 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
llvm::Value *numElements = nullptr;
llvm::Value *allocSizeWithoutCookie = nullptr;
- llvm::Value *allocSize =
- EmitCXXNewAllocSize(*this, E, minElements, numElements,
- allocSizeWithoutCookie);
+ llvm::Value *allocSize = EmitCXXNewAllocSize(
+ *this, E, minElements, numElements, allocSizeWithoutCookie);
CharUnits allocAlign = getContext().getTypeAlignInChars(allocType);
// Emit the allocation call. If the allocator is a global placement
@@ -1621,7 +1608,7 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
} else {
const FunctionProtoType *allocatorType =
- allocator->getType()->castAs<FunctionProtoType>();
+ allocator->getType()->castAs<FunctionProtoType>();
ImplicitAllocationParameters IAP = E->implicitAllocationParameters();
unsigned ParamsToSkip = 0;
if (isTypeAwareAllocation(IAP.PassTypeIdentity)) {
@@ -1663,10 +1650,10 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
// FIXME: Why do we not pass a CalleeDecl here?
EmitCallArgs(allocatorArgs, allocatorType, E->placement_arguments(),
- /*AC*/AbstractCallee(), /*ParamsToSkip*/ParamsToSkip);
+ /*AC*/ AbstractCallee(), /*ParamsToSkip*/ ParamsToSkip);
RValue RV =
- EmitNewDeleteCall(*this, allocator, allocatorType, allocatorArgs);
+ EmitNewDeleteCall(*this, allocator, allocatorType, allocatorArgs);
if (auto *newCall = dyn_cast<llvm::CallBase>(RV.getScalarVal())) {
if (auto *CGDI = getDebugInfo()) {
@@ -1738,9 +1725,8 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
CalculateCookiePadding(*this, E).isZero());
if (allocSize != allocSizeWithoutCookie) {
assert(E->isArray());
- allocation = CGM.getCXXABI().InitializeArrayCookie(*this, allocation,
- numElements,
- E, allocType);
+ allocation = CGM.getCXXABI().InitializeArrayCookie(
+ *this, allocation, numElements, E, allocType);
}
llvm::Type *elementTy = ConvertTypeForMem(allocType);
@@ -1873,27 +1859,25 @@ void CodeGenFunction::EmitDeleteCall(const FunctionDecl *DeleteFD,
(*TagAlloca)->eraseFromParent();
}
namespace {
- /// Calls the given 'operator delete' on a single object.
- struct CallObjectDelete final : EHScopeStack::Cleanup {
- llvm::Value *Ptr;
- const FunctionDecl *OperatorDelete;
- QualType ElementType;
-
- CallObjectDelete(llvm::Value *Ptr,
- const FunctionDecl *OperatorDelete,
- QualType ElementType)
+/// Calls the given 'operator delete' on a single object.
+struct CallObjectDelete final : EHScopeStack::Cleanup {
+ llvm::Value *Ptr;
+ const FunctionDecl *OperatorDelete;
+ QualType ElementType;
+
+ CallObjectDelete(llvm::Value *Ptr, const FunctionDecl *OperatorDelete,
+ QualType ElementType)
: Ptr(Ptr), OperatorDelete(OperatorDelete), ElementType(ElementType) {}
- void Emit(CodeGenFunction &CGF, Flags flags) override {
- CGF.EmitDeleteCall(OperatorDelete, Ptr, ElementType);
- }
- };
-}
+ void Emit(CodeGenFunction &CGF, Flags flags) override {
+ CGF.EmitDeleteCall(OperatorDelete, Ptr, ElementType);
+ }
+};
+} // namespace
-void
-CodeGenFunction::pushCallObjectDeleteCleanup(const FunctionDecl *OperatorDelete,
- llvm::Value *CompletePtr,
- QualType ElementType) {
+void CodeGenFunction::pushCallObjectDeleteCleanup(
+ const FunctionDecl *OperatorDelete, llvm::Value *CompletePtr,
+ QualType ElementType) {
EHStack.pushCleanup<CallObjectDelete>(NormalAndEHCleanup, CompletePtr,
OperatorDelete, ElementType);
}
@@ -1941,10 +1925,9 @@ static bool EmitObjectDelete(CodeGenFunction &CGF, const CXXDeleteExpr *DE,
if (Dtor->isVirtual()) {
bool UseVirtualCall = true;
const Expr *Base = DE->getArgument();
- if (auto *DevirtualizedDtor =
- dyn_cast_or_null<const CXXDestructorDecl>(
- Dtor->getDevirtualizedMethod(
- Base, CGF.CGM.getLangOpts().AppleKext))) {
+ if (auto *DevirtualizedDtor = dyn_cast_or_null<const CXXDestructorDecl>(
+ Dtor->getDevirtualizedMethod(
+ Base, CGF.CGM.getLangOpts().AppleKext))) {
UseVirtualCall = false;
const CXXRecordDecl *DevirtualizedClass =
DevirtualizedDtor->getParent();
@@ -1979,8 +1962,7 @@ static bool EmitObjectDelete(CodeGenFunction &CGF, const CXXDeleteExpr *DE,
if (Dtor)
CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete,
/*ForVirtualBase=*/false,
- /*Delegating=*/false,
- Ptr, ElementType);
+ /*Delegating=*/false, Ptr, ElementType);
else if (auto Lifetime = ElementType.getObjCLifetime()) {
switch (Lifetime) {
case Qualifiers::OCL_None:
@@ -2010,34 +1992,30 @@ static bool EmitObjectDelete(CodeGenFunction &CGF, const CXXDeleteExpr *DE,
}
namespace {
- /// Calls the given 'operator delete' on an array of objects.
- struct CallArrayDelete final : EHScopeStack::Cleanup {
- llvm::Value *Ptr;
- const FunctionDecl *OperatorDelete;
- llvm::Value *NumElements;
- QualType ElementType;
- CharUnits CookieSize;
-
- CallArrayDelete(llvm::Value *Ptr,
- const FunctionDecl *OperatorDelete,
- llvm::Value *NumElements,
- QualType ElementType,
- CharUnits CookieSize)
+/// Calls the given 'operator delete' on an array of objects.
+struct CallArrayDelete final : EHScopeStack::Cleanup {
+ llvm::Value *Ptr;
+ const FunctionDecl *OperatorDelete;
+ llvm::Value *NumElements;
+ QualType ElementType;
+ CharUnits CookieSize;
+
+ CallArrayDelete(llvm::Value *Ptr, const FunctionDecl *OperatorDelete,
+ llvm::Value *NumElements, QualType ElementType,
+ CharUnits CookieSize)
: Ptr(Ptr), OperatorDelete(OperatorDelete), NumElements(NumElements),
ElementType(ElementType), CookieSize(CookieSize) {}
- void Emit(CodeGenFunction &CGF, Flags flags) override {
- CGF.EmitDeleteCall(OperatorDelete, Ptr, ElementType, NumElements,
- CookieSize);
- }
- };
-}
+ void Emit(CodeGenFunction &CGF, Flags flags) override {
+ CGF.EmitDeleteCall(OperatorDelete, Ptr, ElementType, NumElements,
+ CookieSize);
+ }
+};
+} // namespace
/// Emit the code for deleting an array of objects.
-static void EmitArrayDelete(CodeGenFunction &CGF,
- const CXXDeleteExpr *E,
- Address deletedPtr,
- QualType elementType) {
+static void EmitArrayDelete(CodeGenFunction &CGF, const CXXDeleteExpr *E,
+ Address deletedPtr, QualType elementType) {
llvm::Value *numElements = nullptr;
llvm::Value *allocatedPtr = nullptr;
CharUnits cookieSize;
@@ -2048,10 +2026,9 @@ static void EmitArrayDelete(CodeGenFunction &CGF,
// Make sure that we call delete even if one of the dtors throws.
const FunctionDecl *operatorDelete = E->getOperatorDelete();
- CGF.EHStack.pushCleanup<CallArrayDelete>(NormalAndEHCleanup,
- allocatedPtr, operatorDelete,
- numElements, elementType,
- cookieSize);
+ CGF.EHStack.pushCleanup<CallArrayDelete>(NormalAndEHCleanup, allocatedPtr,
+ operatorDelete, numElements,
+ elementType, cookieSize);
// Destroy the elements.
if (QualType::DestructionKind dtorKind = elementType.isDestructedType()) {
@@ -2059,11 +2036,11 @@ static void EmitArrayDelete(CodeGenFunction &CGF,
CharUnits elementSize = CGF.getContext().getTypeSizeInChars(elementType);
CharUnits elementAlign =
- deletedPtr.getAlignment().alignmentOfArrayElement(elementSize);
+ deletedPtr.getAlignment().alignmentOfArrayElement(elementSize);
llvm::Value *arrayBegin = deletedPtr.emitRawPointer(CGF);
llvm::Value *arrayEnd = CGF.Builder.CreateInBoundsGEP(
- deletedPtr.getElementType(), arrayBegin, numElements, "delete.end");
+ deletedPtr.getElementType(), arrayBegin, numElements, "delete.end");
// Note that it is legal to allocate a zero-length array, and we
// can never fold the check away because the length should always
More information about the cfe-commits
mailing list