Skip to content

[MS][clang] Revert vector deleting destructors support #135611

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,6 @@ Windows Support
- Clang now can process the `i128` and `ui128` integeral suffixes when MSVC
extensions are enabled. This allows for properly processing ``intsafe.h`` in
the Windows SDK.
- Clang now supports MSVC vector deleting destructors (GH19772).

LoongArch Support
^^^^^^^^^^^^^^^^^
Expand Down
6 changes: 0 additions & 6 deletions clang/include/clang/AST/DeclCXX.h
Original file line number Diff line number Diff line change
Expand Up @@ -2852,7 +2852,6 @@ class CXXDestructorDecl : public CXXMethodDecl {
// FIXME: Don't allocate storage for these except in the first declaration
// of a virtual destructor.
FunctionDecl *OperatorDelete = nullptr;
FunctionDecl *OperatorArrayDelete = nullptr;
Expr *OperatorDeleteThisArg = nullptr;

CXXDestructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
Expand All @@ -2878,16 +2877,11 @@ class CXXDestructorDecl : public CXXMethodDecl {
static CXXDestructorDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);

void setOperatorDelete(FunctionDecl *OD, Expr *ThisArg);
void setOperatorArrayDelete(FunctionDecl *OD);

const FunctionDecl *getOperatorDelete() const {
return getCanonicalDecl()->OperatorDelete;
}

const FunctionDecl *getArrayOperatorDelete() const {
return getCanonicalDecl()->OperatorArrayDelete;
}

Expr *getOperatorDeleteThisArg() const {
return getCanonicalDecl()->OperatorDeleteThisArg;
}
Expand Down
6 changes: 2 additions & 4 deletions clang/include/clang/AST/VTableBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ class VTableComponent {

bool isRTTIKind() const { return isRTTIKind(getKind()); }

GlobalDecl getGlobalDecl(bool HasVectorDeletingDtors) const {
GlobalDecl getGlobalDecl() const {
assert(isUsedFunctionPointerKind() &&
"GlobalDecl can be created only from virtual function");

Expand All @@ -161,9 +161,7 @@ class VTableComponent {
case CK_CompleteDtorPointer:
return GlobalDecl(DtorDecl, CXXDtorType::Dtor_Complete);
case CK_DeletingDtorPointer:
return GlobalDecl(DtorDecl, (HasVectorDeletingDtors)
? CXXDtorType::Dtor_VectorDeleting
: CXXDtorType::Dtor_Deleting);
return GlobalDecl(DtorDecl, CXXDtorType::Dtor_Deleting);
case CK_VCallOffset:
case CK_VBaseOffset:
case CK_OffsetToTop:
Expand Down
9 changes: 4 additions & 5 deletions clang/include/clang/Basic/ABI.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,10 @@ 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_VectorDeleting ///< Vector deleting dtor
Dtor_Deleting, ///< Deleting dtor
Dtor_Complete, ///< Complete object dtor
Dtor_Base, ///< Base object dtor
Dtor_Comdat ///< The COMDAT used for dtors
};

} // end namespace clang
Expand Down
1 change: 0 additions & 1 deletion clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -8366,7 +8366,6 @@ class Sema final : public SemaBase {
DeclarationName Name);
FunctionDecl *FindDeallocationFunctionForDestructor(SourceLocation StartLoc,
CXXRecordDecl *RD,
DeclarationName Name,
bool Diagnose = true);

/// ActOnCXXDelete - Parsed a C++ 'delete' expression (C++ 5.3.5), as in:
Expand Down
6 changes: 0 additions & 6 deletions clang/lib/AST/DeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3064,12 +3064,6 @@ void CXXDestructorDecl::setOperatorDelete(FunctionDecl *OD, Expr *ThisArg) {
}
}

void CXXDestructorDecl::setOperatorArrayDelete(FunctionDecl *OD) {
auto *First = cast<CXXDestructorDecl>(getFirstDecl());
if (OD && !First->OperatorArrayDelete)
First->OperatorArrayDelete = OD;
}

bool CXXDestructorDecl::isCalledByDelete(const FunctionDecl *OpDel) const {
// C++20 [expr.delete]p6: If the value of the operand of the delete-
// expression is not a null pointer value and the selected deallocation
Expand Down
3 changes: 0 additions & 3 deletions clang/lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,6 @@ const CXXRecordDecl *Expr::getBestDynamicClassType() const {
if (const PointerType *PTy = DerivedType->getAs<PointerType>())
DerivedType = PTy->getPointeeType();

while (const ArrayType *ATy = DerivedType->getAsArrayTypeUnsafe())
DerivedType = ATy->getElementType();

if (DerivedType->isDependentType())
return nullptr;

Expand Down
2 changes: 0 additions & 2 deletions clang/lib/AST/ItaniumMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6047,8 +6047,6 @@ void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
case Dtor_Comdat:
Out << "D5";
break;
case Dtor_VectorDeleting:
llvm_unreachable("Itanium ABI does not use vector deleting dtors");
}
}

Expand Down
22 changes: 9 additions & 13 deletions clang/lib/AST/MicrosoftMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1490,9 +1490,8 @@ void MicrosoftCXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
// <operator-name> ::= ?_G # scalar deleting destructor
case Dtor_Deleting: Out << "?_G"; return;
// <operator-name> ::= ?_E # vector deleting destructor
case Dtor_VectorDeleting:
Out << "?_E";
return;
// FIXME: Add a vector deleting dtor type. It goes in the vtable, so we need
// it.
case Dtor_Comdat:
llvm_unreachable("not expecting a COMDAT");
}
Expand Down Expand Up @@ -2893,12 +2892,9 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
// ::= @ # structors (they have no declared return type)
if (IsStructor) {
if (isa<CXXDestructorDecl>(D) && isStructorDecl(D)) {
// 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 ||
StructorType == Dtor_VectorDeleting) {
// The scalar deleting destructor takes an extra int argument which is not
// reflected in the AST.
if (StructorType == Dtor_Deleting) {
Out << (PointersAre64Bit ? "PEAXI@Z" : "PAXI@Z");
return;
}
Expand Down Expand Up @@ -3871,10 +3867,10 @@ void MicrosoftMangleContextImpl::mangleCXXDtorThunk(const CXXDestructorDecl *DD,
const ThunkInfo &Thunk,
bool /*ElideOverrideInfo*/,
raw_ostream &Out) {
// The dtor thunk should use vector deleting dtor mangling, however as an
// optimization we may end up emitting only scalar deleting dtor body, so just
// use the vector deleting dtor mangling manually.
assert(Type == Dtor_Deleting || Type == Dtor_VectorDeleting);
// FIXME: Actually, the dtor thunk should be emitted for vector deleting
// dtors rather than scalar deleting dtors. Just use the vector deleting dtor
// mangling manually until we support both deleting dtor types.
assert(Type == Dtor_Deleting);
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO, DD, Type);
Mangler.getStream() << "??_E";
Expand Down
19 changes: 6 additions & 13 deletions clang/lib/AST/VTableBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1735,8 +1735,8 @@ 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)] =
MI.VTableIndex - AddressPoint;
MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)]
= MI.VTableIndex - AddressPoint;
MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)]
= MI.VTableIndex + 1 - AddressPoint;
} else {
Expand Down Expand Up @@ -2657,11 +2657,7 @@ class VFTableBuilder {
MethodVFTableLocation Loc(MI.VBTableIndex, WhichVFPtr.getVBaseWithVPtr(),
WhichVFPtr.NonVirtualOffset, MI.VFTableIndex);
if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
// In Microsoft ABI vftable always references vector deleting dtor.
CXXDtorType DtorTy = Context.getTargetInfo().getCXXABI().isMicrosoft()
? Dtor_VectorDeleting
: Dtor_Deleting;
MethodVFTableLocations[GlobalDecl(DD, DtorTy)] = Loc;
MethodVFTableLocations[GlobalDecl(DD, Dtor_Deleting)] = Loc;
} else {
MethodVFTableLocations[MD] = Loc;
}
Expand Down Expand Up @@ -3291,10 +3287,7 @@ void VFTableBuilder::dumpLayout(raw_ostream &Out) {
const CXXDestructorDecl *DD = Component.getDestructorDecl();

DD->printQualifiedName(Out);
if (Context.getTargetInfo().getCXXABI().isMicrosoft())
Out << "() [vector deleting]";
else
Out << "() [scalar deleting]";
Out << "() [scalar deleting]";

if (DD->isPureVirtual())
Out << " [pure]";
Expand Down Expand Up @@ -3764,7 +3757,7 @@ void MicrosoftVTableContext::dumpMethodLocations(
PredefinedIdentKind::PrettyFunctionNoVirtual, MD);

if (isa<CXXDestructorDecl>(MD)) {
IndicesMap[I.second] = MethodName + " [vector deleting]";
IndicesMap[I.second] = MethodName + " [scalar deleting]";
} else {
IndicesMap[I.second] = MethodName;
}
Expand Down Expand Up @@ -3880,7 +3873,7 @@ 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_VectorDeleting);
assert(GD.getDtorType() == Dtor_Deleting);

GD = GD.getCanonicalDecl();

Expand Down
37 changes: 1 addition & 36 deletions clang/lib/CodeGen/CGCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ 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());
Expand All @@ -200,42 +201,6 @@ bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) {
return false;
}

/// Emit a definition as a global alias for another definition, unconditionally.
void CodeGenModule::EmitDefinitionAsAlias(GlobalDecl AliasDecl,
GlobalDecl TargetDecl) {

llvm::Type *AliasValueType = getTypes().GetFunctionType(AliasDecl);

StringRef MangledName = getMangledName(AliasDecl);
llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
if (Entry && !Entry->isDeclaration())
return;
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);

if (Entry) {
assert(Entry->getValueType() == AliasValueType &&
Entry->getAddressSpace() == Alias->getAddressSpace() &&
"declaration exists with different type");
Alias->takeName(Entry);
Entry->replaceAllUsesWith(Alias);
Entry->eraseFromParent();
} else {
Alias->setName(MangledName);
}

// Set any additional necessary attributes for the alias.
SetCommonAttributes(AliasDecl, Alias);
}

llvm::Function *CodeGenModule::codegenCXXStructor(GlobalDecl GD) {
const CGFunctionInfo &FnInfo = getTypes().arrangeCXXStructorDeclaration(GD);
auto *Fn = cast<llvm::Function>(
Expand Down
14 changes: 0 additions & 14 deletions clang/lib/CodeGen/CGCXXABI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -271,20 +271,6 @@ 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) {
assert(eltTy.isDestructedType());

// 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) {
Expand Down
7 changes: 0 additions & 7 deletions clang/lib/CodeGen/CGCXXABI.h
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,6 @@ class CGCXXABI {
virtual CatchTypeInfo getCatchAllTypeInfo();

virtual bool shouldTypeidBeNullChecked(QualType SrcRecordTy) = 0;
virtual bool hasVectorDeletingDtors() = 0;
virtual void EmitBadTypeidCall(CodeGenFunction &CGF) = 0;
virtual llvm::Value *EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy,
Address ThisPtr,
Expand Down Expand Up @@ -576,12 +575,6 @@ 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.
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);

Expand Down
Loading
Loading