[clang] WIP on vector deleting destructors (PR #121490)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Jan 2 07:57:29 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Mariya Podchishchaeva (Fznamznon)
<details>
<summary>Changes</summary>
---
Patch is 22.88 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/121490.diff
11 Files Affected:
- (modified) clang/include/clang/AST/VTableBuilder.h (+1-1)
- (modified) clang/include/clang/Basic/ABI.h (+5-4)
- (modified) clang/lib/AST/ItaniumMangle.cpp (+2)
- (modified) clang/lib/AST/MicrosoftMangle.cpp (+6-4)
- (modified) clang/lib/AST/VTableBuilder.cpp (+15-7)
- (modified) clang/lib/CodeGen/CGCXX.cpp (+41-1)
- (modified) clang/lib/CodeGen/CGCXXABI.cpp (+15)
- (modified) clang/lib/CodeGen/CGCXXABI.h (+6)
- (modified) clang/lib/CodeGen/CGClass.cpp (+102-10)
- (modified) clang/lib/CodeGen/CodeGenModule.h (+1)
- (modified) clang/lib/CodeGen/MicrosoftCXXABI.cpp (+15-8)
``````````diff
diff --git a/clang/include/clang/AST/VTableBuilder.h b/clang/include/clang/AST/VTableBuilder.h
index a5de41dbc22f14..07217677d2b021 100644
--- a/clang/include/clang/AST/VTableBuilder.h
+++ b/clang/include/clang/AST/VTableBuilder.h
@@ -161,7 +161,7 @@ class VTableComponent {
case CK_CompleteDtorPointer:
return GlobalDecl(DtorDecl, CXXDtorType::Dtor_Complete);
case CK_DeletingDtorPointer:
- return GlobalDecl(DtorDecl, CXXDtorType::Dtor_Deleting);
+ return GlobalDecl(DtorDecl, CXXDtorType::Dtor_VectorDeleting);
case CK_VCallOffset:
case CK_VBaseOffset:
case CK_OffsetToTop:
diff --git a/clang/include/clang/Basic/ABI.h b/clang/include/clang/Basic/ABI.h
index 231bad799a42cb..48969e4f295c36 100644
--- a/clang/include/clang/Basic/ABI.h
+++ b/clang/include/clang/Basic/ABI.h
@@ -31,10 +31,11 @@ enum CXXCtorType {
/// C++ destructor types.
enum CXXDtorType {
- Dtor_Deleting, ///< Deleting dtor
- Dtor_Complete, ///< Complete object dtor
- Dtor_Base, ///< Base object dtor
- Dtor_Comdat ///< The COMDAT used for dtors
+ Dtor_Deleting, ///< Deleting dtor
+ Dtor_Complete, ///< Complete object dtor
+ Dtor_Base, ///< Base object dtor
+ Dtor_Comdat, ///< The COMDAT used for dtors
+ Dtor_VectorDeleting ///< Vector deleting dtor
};
} // end namespace clang
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 47aa9b40dab845..827e22724fa55a 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -5994,6 +5994,8 @@ void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
case Dtor_Comdat:
Out << "D5";
break;
+ case Dtor_VectorDeleting:
+ llvm_unreachable("Itanium ABI does not use vector deleting dtors");
}
}
diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp
index edeeaeaa9ae17c..0f878c2de653bf 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -1484,8 +1484,7 @@ void MicrosoftCXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
// <operator-name> ::= ?_G # scalar deleting destructor
case Dtor_Deleting: Out << "?_G"; return;
// <operator-name> ::= ?_E # vector deleting destructor
- // FIXME: Add a vector deleting dtor type. It goes in the vtable, so we need
- // it.
+ case Dtor_VectorDeleting: Out << "?_E"; return;
case Dtor_Comdat:
llvm_unreachable("not expecting a COMDAT");
}
@@ -2917,9 +2916,12 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
// ::= @ # structors (they have no declared return type)
if (IsStructor) {
if (isa<CXXDestructorDecl>(D) && isStructorDecl(D)) {
- // The scalar deleting destructor takes an extra int argument which is not
+ // The deleting destructors take an extra argument of type int that indicates
+ // whether the storage for the object should be deleted and whether a single
+ // object or an array of objects is being destroyed. This extra argument is not
// reflected in the AST.
- if (StructorType == Dtor_Deleting) {
+ if (StructorType == Dtor_Deleting ||
+ StructorType == Dtor_VectorDeleting) {
Out << (PointersAre64Bit ? "PEAXI at Z" : "PAXI at Z");
return;
}
diff --git a/clang/lib/AST/VTableBuilder.cpp b/clang/lib/AST/VTableBuilder.cpp
index e941c3bedb0a7e..d2a3128c28d7f5 100644
--- a/clang/lib/AST/VTableBuilder.cpp
+++ b/clang/lib/AST/VTableBuilder.cpp
@@ -1341,7 +1341,6 @@ void ItaniumVTableBuilder::AddMethod(const CXXMethodDecl *MD,
if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
assert(ReturnAdjustment.isEmpty() &&
"Destructor can't have return adjustment!");
-
// Add both the complete destructor and the deleting destructor.
Components.push_back(VTableComponent::MakeCompleteDtor(DD));
Components.push_back(VTableComponent::MakeDeletingDtor(DD));
@@ -1733,7 +1732,7 @@ void ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables(
const CXXMethodDecl *MD = I.first;
const MethodInfo &MI = I.second;
if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
- MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)]
+ MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)]
= MI.VTableIndex - AddressPoint;
MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)]
= MI.VTableIndex + 1 - AddressPoint;
@@ -2655,7 +2654,11 @@ class VFTableBuilder {
MethodVFTableLocation Loc(MI.VBTableIndex, WhichVFPtr.getVBaseWithVPtr(),
WhichVFPtr.NonVirtualOffset, MI.VFTableIndex);
if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
- MethodVFTableLocations[GlobalDecl(DD, Dtor_Deleting)] = Loc;
+ if (!Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+ MethodVFTableLocations[GlobalDecl(DD, Dtor_Deleting)] = Loc;
+ } else {
+ MethodVFTableLocations[GlobalDecl(DD, Dtor_VectorDeleting)] = Loc;
+ }
} else {
MethodVFTableLocations[MD] = Loc;
}
@@ -3285,7 +3288,10 @@ void VFTableBuilder::dumpLayout(raw_ostream &Out) {
const CXXDestructorDecl *DD = Component.getDestructorDecl();
DD->printQualifiedName(Out);
- Out << "() [scalar deleting]";
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft())
+ Out << "() [vector deleting]";
+ else
+ Out << "() [deleting]";
if (DD->isPureVirtual())
Out << " [pure]";
@@ -3756,7 +3762,7 @@ void MicrosoftVTableContext::dumpMethodLocations(
PredefinedIdentKind::PrettyFunctionNoVirtual, MD);
if (isa<CXXDestructorDecl>(MD)) {
- IndicesMap[I.second] = MethodName + " [scalar deleting]";
+ IndicesMap[I.second] = MethodName + " [deleting]";
} else {
IndicesMap[I.second] = MethodName;
}
@@ -3872,8 +3878,10 @@ MethodVFTableLocation
MicrosoftVTableContext::getMethodVFTableLocation(GlobalDecl GD) {
assert(hasVtableSlot(cast<CXXMethodDecl>(GD.getDecl())) &&
"Only use this method for virtual methods or dtors");
- if (isa<CXXDestructorDecl>(GD.getDecl()))
- assert(GD.getDtorType() == Dtor_Deleting);
+ if (isa<CXXDestructorDecl>(GD.getDecl())) {
+ assert(GD.getDtorType() == Dtor_Deleting ||
+ GD.getDtorType() == Dtor_VectorDeleting);
+ }
GD = GD.getCanonicalDecl();
diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp
index 78a7b021855b7e..2c83a87897f1ac 100644
--- a/clang/lib/CodeGen/CGCXX.cpp
+++ b/clang/lib/CodeGen/CGCXX.cpp
@@ -175,7 +175,6 @@ bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) {
// requires explicit comdat support in the IL.
if (llvm::GlobalValue::isWeakForLinker(TargetLinkage))
return true;
-
// Create the alias with no name.
auto *Alias = llvm::GlobalAlias::create(AliasValueType, 0, Linkage, "",
Aliasee, &getModule());
@@ -201,7 +200,48 @@ bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) {
return false;
}
+/// Emit a definition as a global alias for another definition, unconditionally.
+/// Use this function with care as it can produce invalid aliases. Generally
+/// this function should be used only where there is an ABI requirement to emit
+/// an alias.
+void CodeGenModule::EmitDefinitionAsAlias(GlobalDecl AliasDecl, GlobalDecl TargetDecl) {
+
+ // Derive the type for the alias.
+ llvm::PointerType *AliasValueType =
+ getTypes().GetFunctionType(AliasDecl)->getPointerTo();
+ auto *Aliasee = cast<llvm::GlobalValue>(GetAddrOfGlobal(TargetDecl));
+
+ // Determine the linkage type for the alias.
+ llvm::GlobalValue::LinkageTypes Linkage = getFunctionLinkage(AliasDecl);
+
+ // Create the alias with no name.
+ auto *Alias = llvm::GlobalAlias::create(AliasValueType, 0, Linkage, "",
+ Aliasee, &getModule());
+ // Destructors are always unnamed_addr.
+ Alias->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
+
+ // Set any additional necessary attributes for the alias.
+ SetCommonAttributes(AliasDecl, Alias);
+}
+
llvm::Function *CodeGenModule::codegenCXXStructor(GlobalDecl GD) {
+ // The Microsoft ABI requires that the vector deleting destructor
+ // be weak aliased to the scalar deleting destructor.
+ auto Dtor = dyn_cast<CXXDestructorDecl>(GD.getDecl());
+ if (Dtor && getTarget().getCXXABI().isMicrosoft() &&
+ GD.getDtorType() == Dtor_VectorDeleting) {
+ const CXXDestructorDecl *DtorDecl = cast<CXXDestructorDecl>(GD.getDecl());
+
+ // Create GlobalDecl objects with the correct type for the vector and scalar
+ // deleting destructors.
+ GlobalDecl VectorDtorGD(DtorDecl, Dtor_VectorDeleting);
+ GlobalDecl ScalarDtorGD(DtorDecl, Dtor_Deleting);
+
+ // Emit an alias from the vector deleting destructor to the scalar deleting
+ // destructor.
+ EmitDefinitionAsAlias(VectorDtorGD, ScalarDtorGD);
+
+ }
const CGFunctionInfo &FnInfo = getTypes().arrangeCXXStructorDeclaration(GD);
auto *Fn = cast<llvm::Function>(
getAddrOfCXXStructor(GD, &FnInfo, /*FnType=*/nullptr,
diff --git a/clang/lib/CodeGen/CGCXXABI.cpp b/clang/lib/CodeGen/CGCXXABI.cpp
index 7c6dfc3e59d8c0..e562e263abaa5f 100644
--- a/clang/lib/CodeGen/CGCXXABI.cpp
+++ b/clang/lib/CodeGen/CGCXXABI.cpp
@@ -273,6 +273,21 @@ void CGCXXABI::ReadArrayCookie(CodeGenFunction &CGF, Address ptr,
numElements = readArrayCookieImpl(CGF, allocAddr, cookieSize);
}
+void CGCXXABI::ReadArrayCookie(CodeGenFunction &CGF, Address ptr,
+ QualType eltTy, llvm::Value *&numElements,
+ llvm::Value *&allocPtr, CharUnits &cookieSize) {
+ // FIXME
+ // Assert that we have a cookie.
+
+ // Derive a char* in the same address space as the pointer.
+ ptr = ptr.withElementType(CGF.Int8Ty);
+
+ cookieSize = getArrayCookieSizeImpl(eltTy);
+ Address allocAddr = CGF.Builder.CreateConstInBoundsByteGEP(ptr, -cookieSize);
+ allocPtr = allocAddr.emitRawPointer(CGF);
+ numElements = readArrayCookieImpl(CGF, allocAddr, cookieSize);
+}
+
llvm::Value *CGCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
Address ptr,
CharUnits cookieSize) {
diff --git a/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h
index 687ff7fb844445..382ad11f504b81 100644
--- a/clang/lib/CodeGen/CGCXXABI.h
+++ b/clang/lib/CodeGen/CGCXXABI.h
@@ -575,6 +575,12 @@ class CGCXXABI {
QualType ElementType, llvm::Value *&NumElements,
llvm::Value *&AllocPtr, CharUnits &CookieSize);
+ /// Reads the array cookie associated with the given pointer,
+ /// that should have one.
+ virtual void ReadArrayCookie(CodeGenFunction &CGF, Address Ptr,
+ QualType ElementType, llvm::Value *&NumElements,
+ llvm::Value *&AllocPtr, CharUnits &CookieSize);
+
/// Return whether the given global decl needs a VTT parameter.
virtual bool NeedsVTTParameter(GlobalDecl GD);
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index c45688bd1ed3ce..8b9cdf91111c94 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -1433,6 +1433,88 @@ static bool CanSkipVTablePointerInitialization(CodeGenFunction &CGF,
return true;
}
+namespace {
+llvm::Value *LoadThisForDtorDelete(CodeGenFunction &CGF,
+ const CXXDestructorDecl *DD) {
+ if (Expr *ThisArg = DD->getOperatorDeleteThisArg())
+ return CGF.EmitScalarExpr(ThisArg);
+ return CGF.LoadCXXThis();
+}
+}
+
+void EmitConditionalArrayDtorCall(const CXXDestructorDecl *DD,
+ CodeGenFunction &CGF,
+ llvm::Value *ShouldDeleteCondition,
+ bool ReturnAfterDelete) {
+ Address ThisPtr = CGF.LoadCXXThisAddress();
+ // llvm::Value *ThisPtr = LoadThisForDtorDelete(CGF, DD);
+ // llvm::BasicBlock *End = CGF.createBasicBlock("dtor.end");
+ llvm::BasicBlock *ScalarBB = CGF.createBasicBlock("dtor.scalar");
+ llvm::BasicBlock *callDeleteBB =
+ CGF.createBasicBlock("dtor.call_delete_after_array_destroy");
+ llvm::BasicBlock *VectorBB = CGF.createBasicBlock("dtor.vector");
+ auto *CondTy = cast<llvm::IntegerType>(ShouldDeleteCondition->getType());
+ llvm::Value *CheckTheBitForArrayDestroy = CGF.Builder.CreateAnd(
+ ShouldDeleteCondition,
+ llvm::Constant::getIntegerValue(CondTy, llvm::APInt(CondTy->getBitWidth(),
+ /*val=*/2)));
+ llvm::Value *ShouldDestroyArray =
+ CGF.Builder.CreateIsNull(CheckTheBitForArrayDestroy);
+ CGF.Builder.CreateCondBr(ShouldDestroyArray, ScalarBB, VectorBB);
+
+ CGF.EmitBlock(VectorBB);
+
+ llvm::Value *numElements = nullptr;
+ llvm::Value *allocatedPtr = nullptr;
+ CharUnits cookieSize;
+ QualType EltTy = DD->getThisType()->getPointeeType();
+ CGF.CGM.getCXXABI().ReadArrayCookie(CGF, ThisPtr, EltTy, numElements,
+ allocatedPtr, cookieSize);
+
+ // Destroy the elements.
+ QualType::DestructionKind dtorKind = EltTy.isDestructedType();
+
+ assert(dtorKind);
+ assert(numElements && "no element count for a type with a destructor!");
+
+ CharUnits elementSize = CGF.getContext().getTypeSizeInChars(EltTy);
+ CharUnits elementAlign =
+ ThisPtr.getAlignment().alignmentOfArrayElement(elementSize);
+
+ llvm::Value *arrayBegin = ThisPtr.emitRawPointer(CGF);
+ llvm::Value *arrayEnd = CGF.Builder.CreateInBoundsGEP(
+ ThisPtr.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
+ // come from a cookie.
+ CGF.emitArrayDestroy(arrayBegin, arrayEnd, EltTy, elementAlign,
+ CGF.getDestroyer(dtorKind),
+ /*checkZeroLength*/ true, CGF.needsEHCleanup(dtorKind));
+
+ llvm::BasicBlock *VectorBBCont = CGF.createBasicBlock("dtor.vector.cont");
+ CGF.EmitBlock(VectorBBCont);
+
+ llvm::Value *CheckTheBitForDeleteCall = CGF.Builder.CreateAnd(
+ ShouldDeleteCondition,
+ llvm::Constant::getIntegerValue(CondTy, llvm::APInt(CondTy->getBitWidth(),
+ /*val=*/1)));
+
+ llvm::Value *ShouldCallDelete =
+ CGF.Builder.CreateIsNull(CheckTheBitForDeleteCall);
+ CGF.Builder.CreateCondBr(ShouldCallDelete, CGF.ReturnBlock.getBlock(),
+ callDeleteBB);
+ CGF.EmitBlock(callDeleteBB);
+ const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CGF.CurCodeDecl);
+ const CXXRecordDecl *ClassDecl = Dtor->getParent();
+ CGF.EmitDeleteCall(Dtor->getOperatorDelete(), allocatedPtr,
+ CGF.getContext().getTagDeclType(ClassDecl));
+
+ // FIXME figure how to go to the end properly
+ CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
+ CGF.EmitBlock(ScalarBB);
+}
+
/// EmitDestructorBody - Emits the body of the current destructor.
void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CurGD.getDecl());
@@ -1462,7 +1544,11 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
// outside of the function-try-block, which means it's always
// possible to delegate the destructor body to the complete
// destructor. Do so.
- if (DtorType == Dtor_Deleting) {
+ if (DtorType == Dtor_Deleting || DtorType == Dtor_VectorDeleting) {
+ if (CXXStructorImplicitParamValue && DtorType == Dtor_VectorDeleting) {
+ EmitConditionalArrayDtorCall(Dtor, *this, CXXStructorImplicitParamValue,
+ false);
+ }
RunCleanupsScope DtorEpilogue(*this);
EnterDtorCleanups(Dtor, Dtor_Deleting);
if (HaveInsertPoint()) {
@@ -1491,6 +1577,7 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
switch (DtorType) {
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");
case Dtor_Complete:
assert((Body || getTarget().getCXXABI().isMicrosoft()) &&
@@ -1567,12 +1654,12 @@ 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();
- }
+ // 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 {
@@ -1592,8 +1679,12 @@ namespace {
bool ReturnAfterDelete) {
llvm::BasicBlock *callDeleteBB = CGF.createBasicBlock("dtor.call_delete");
llvm::BasicBlock *continueBB = CGF.createBasicBlock("dtor.continue");
- llvm::Value *ShouldCallDelete
- = CGF.Builder.CreateIsNull(ShouldDeleteCondition);
+ auto *CondTy = cast<llvm::IntegerType>(ShouldDeleteCondition->getType());
+ llvm::Value *CheckTheBit = CGF.Builder.CreateAnd(
+ ShouldDeleteCondition, llvm::Constant::getIntegerValue(
+ CondTy, llvm::APInt(CondTy->getBitWidth(),
+ /*val=*/1)));
+ llvm::Value *ShouldCallDelete = CGF.Builder.CreateIsNull(CheckTheBit);
CGF.Builder.CreateCondBr(ShouldCallDelete, continueBB, callDeleteBB);
CGF.EmitBlock(callDeleteBB);
@@ -1857,9 +1948,10 @@ void CodeGenFunction::EnterDtorCleanups(const CXXDestructorDecl *DD,
if (DD->getOperatorDelete()->isDestroyingOperatorDelete())
EmitConditionalDtorDeleteCall(*this, CXXStructorImplicitParamValue,
/*ReturnAfterDelete*/true);
- else
+ else {
EHStack.pushCleanup<CallDtorDeleteConditional>(
NormalAndEHCleanup, CXXStructorImplicitParamValue);
+ }
} else {
if (DD->getOperatorDelete()->isDestroyingOperatorDelete()) {
const CXXRecordDecl *ClassDecl = DD->getParent();
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index 741b0f17da6584..ac285a63d69c25 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -1485,6 +1485,7 @@ class CodeGenModule : public CodeGenTypeCache {
void EmitGlobal(GlobalDecl D);
bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D);
+ void EmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target);
llvm::GlobalValue *GetGlobalValue(StringRef Ref);
diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index 90651c3bafe26e..2e1fea535454b1 100644
--- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -70,8 +70,8 @@ class MicrosoftCXXABI : public CGCXXABI {
switch (GD.getDtorType()) {
case Dtor_Complete:
case Dtor_Deleting:
+ case Dtor_VectorDeleting:
return true;
-
case Dtor_Base:
return false;
@@ -260,7 +260,7 @@ class MicrosoftCXXABI : public CGCXXABI {
// There's only Dtor_Deleting in vftable but it shares the this
// adjustment with the base one, so look up the deleting one instead.
- LookupGD = GlobalDecl(DD, Dtor_Deleting);
+ LookupGD = GlobalDecl(DD, Dtor_VectorDeleting);
}
MethodVFTableLocation ML =
CGM.getMicrosoftVTableContext().getMethodVFTableLocation(LookupGD);
@@ -894,7 +894,8 @@ void MicrosoftCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF,
// FIXME: Provide a source location here even though there's no
// CXXMemberCallExpr for dtor call.
bool...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/121490
More information about the cfe-commits
mailing list