Skip to content

Commit 3dc8666

Browse files
committed
Revert "Revert "Reland [MS][clang] Add support for vector deleting destructors" (llvm#169116)"
This reverts commit 54a4da9.
1 parent 8ec2112 commit 3dc8666

File tree

60 files changed

+1274
-166
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+1274
-166
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@ Potentially Breaking Changes
8686
options-related code has been moved out of the Driver into a separate library.
8787
- The ``clangFrontend`` library no longer depends on ``clangDriver``, which may
8888
break downstream projects that relied on this transitive dependency.
89+
- Clang now supports MSVC vector deleting destructors when targeting Windows.
90+
This means that vtables of classes with virtual destructors will contain a
91+
pointer to vector deleting destructor (instead of scalar deleting destructor)
92+
which in fact is a different symbol with different name and linkage. This
93+
may cause runtime failures if two binaries using the same class defining a
94+
virtual destructor are compiled with different versions of clang.
8995

9096
C/C++ Language Potentially Breaking Changes
9197
-------------------------------------------
@@ -625,6 +631,8 @@ Windows Support
625631
- clang-cl now supports /arch:AVX10.1 and /arch:AVX10.2.
626632
- clang-cl now supports /vlen, /vlen=256 and /vlen=512.
627633

634+
- Clang now supports MSVC vector deleting destructors (GH19772).
635+
628636
LoongArch Support
629637
^^^^^^^^^^^^^^^^^
630638
- Enable linker relaxation by default for loongarch64.

clang/include/clang/AST/ASTContext.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,18 @@ class ASTContext : public RefCountedBase<ASTContext> {
370370
mutable llvm::DenseSet<const FunctionDecl *> DestroyingOperatorDeletes;
371371
mutable llvm::DenseSet<const FunctionDecl *> TypeAwareOperatorNewAndDeletes;
372372

373+
/// Global and array operators delete are only required for MSVC deleting
374+
/// destructors support. Store them here to avoid keeping 4 pointers that are
375+
/// not always used in each redeclaration of the destructor.
376+
mutable llvm::DenseMap<const CXXDestructorDecl *, FunctionDecl *>
377+
OperatorDeletesForVirtualDtor;
378+
mutable llvm::DenseMap<const CXXDestructorDecl *, FunctionDecl *>
379+
GlobalOperatorDeletesForVirtualDtor;
380+
mutable llvm::DenseMap<const CXXDestructorDecl *, FunctionDecl *>
381+
ArrayOperatorDeletesForVirtualDtor;
382+
mutable llvm::DenseMap<const CXXDestructorDecl *, FunctionDecl *>
383+
GlobalArrayOperatorDeletesForVirtualDtor;
384+
373385
/// The next string literal "version" to allocate during constant evaluation.
374386
/// This is used to distinguish between repeated evaluations of the same
375387
/// string literal.
@@ -3473,6 +3485,16 @@ class ASTContext : public RefCountedBase<ASTContext> {
34733485
bool IsTypeAware);
34743486
bool isTypeAwareOperatorNewOrDelete(const FunctionDecl *FD) const;
34753487

3488+
enum OperatorDeleteKind { Regular, GlobalRegular, Array, ArrayGlobal };
3489+
3490+
void addOperatorDeleteForVDtor(const CXXDestructorDecl *Dtor,
3491+
FunctionDecl *OperatorDelete,
3492+
OperatorDeleteKind K) const;
3493+
FunctionDecl *getOperatorDeleteForVDtor(const CXXDestructorDecl *Dtor,
3494+
OperatorDeleteKind K) const;
3495+
bool dtorHasOperatorDelete(const CXXDestructorDecl *Dtor,
3496+
OperatorDeleteKind K) const;
3497+
34763498
/// Retrieve the context for computing mangling numbers in the given
34773499
/// DeclContext.
34783500
MangleNumberingContext &getManglingNumberContext(const DeclContext *DC);

clang/include/clang/AST/ASTMutationListener.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,15 @@ class ASTMutationListener {
9090
virtual void ResolvedOperatorGlobDelete(const CXXDestructorDecl *DD,
9191
const FunctionDecl *GlobDelete) {}
9292

93+
/// A virtual destructor's operator array delete has been resolved.
94+
virtual void ResolvedOperatorArrayDelete(const CXXDestructorDecl *DD,
95+
const FunctionDecl *ArrayDelete) {}
96+
97+
/// A virtual destructor's operator global array delete has been resolved.
98+
virtual void
99+
ResolvedOperatorGlobArrayDelete(const CXXDestructorDecl *DD,
100+
const FunctionDecl *GlobArrayDelete) {}
101+
93102
/// An implicit member got a definition.
94103
virtual void CompletedImplicitDefinition(const FunctionDecl *D) {}
95104

clang/include/clang/AST/DeclCXX.h

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2872,8 +2872,6 @@ class CXXDestructorDecl : public CXXMethodDecl {
28722872

28732873
// FIXME: Don't allocate storage for these except in the first declaration
28742874
// of a virtual destructor.
2875-
FunctionDecl *OperatorDelete = nullptr;
2876-
FunctionDecl *OperatorGlobalDelete = nullptr;
28772875
Expr *OperatorDeleteThisArg = nullptr;
28782876

28792877
CXXDestructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
@@ -2900,14 +2898,12 @@ class CXXDestructorDecl : public CXXMethodDecl {
29002898

29012899
void setOperatorDelete(FunctionDecl *OD, Expr *ThisArg);
29022900
void setOperatorGlobalDelete(FunctionDecl *OD);
2903-
2904-
const FunctionDecl *getOperatorDelete() const {
2905-
return getCanonicalDecl()->OperatorDelete;
2906-
}
2907-
2908-
const FunctionDecl *getOperatorGlobalDelete() const {
2909-
return getCanonicalDecl()->OperatorGlobalDelete;
2910-
}
2901+
void setOperatorArrayDelete(FunctionDecl *OD);
2902+
void setGlobalOperatorArrayDelete(FunctionDecl *OD);
2903+
const FunctionDecl *getOperatorDelete() const;
2904+
const FunctionDecl *getOperatorGlobalDelete() const;
2905+
const FunctionDecl *getArrayOperatorDelete() const;
2906+
const FunctionDecl *getGlobalArrayOperatorDelete() const;
29112907

29122908
Expr *getOperatorDeleteThisArg() const {
29132909
return getCanonicalDecl()->OperatorDeleteThisArg;

clang/include/clang/AST/VTableBuilder.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ class VTableComponent {
150150

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

153-
GlobalDecl getGlobalDecl() const {
153+
GlobalDecl getGlobalDecl(bool HasVectorDeletingDtors) const {
154154
assert(isUsedFunctionPointerKind() &&
155155
"GlobalDecl can be created only from virtual function");
156156

@@ -161,7 +161,9 @@ class VTableComponent {
161161
case CK_CompleteDtorPointer:
162162
return GlobalDecl(DtorDecl, CXXDtorType::Dtor_Complete);
163163
case CK_DeletingDtorPointer:
164-
return GlobalDecl(DtorDecl, CXXDtorType::Dtor_Deleting);
164+
return GlobalDecl(DtorDecl, (HasVectorDeletingDtors)
165+
? CXXDtorType::Dtor_VectorDeleting
166+
: CXXDtorType::Dtor_Deleting);
165167
case CK_VCallOffset:
166168
case CK_VBaseOffset:
167169
case CK_OffsetToTop:

clang/include/clang/Basic/ABI.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,12 @@ enum CXXCtorType {
3232

3333
/// C++ destructor types.
3434
enum CXXDtorType {
35-
Dtor_Deleting, ///< Deleting dtor
36-
Dtor_Complete, ///< Complete object dtor
37-
Dtor_Base, ///< Base object dtor
38-
Dtor_Comdat, ///< The COMDAT used for dtors
39-
Dtor_Unified, ///< GCC-style unified dtor
35+
Dtor_Deleting, ///< Deleting dtor
36+
Dtor_Complete, ///< Complete object dtor
37+
Dtor_Base, ///< Base object dtor
38+
Dtor_Comdat, ///< The COMDAT used for dtors
39+
Dtor_Unified, ///< GCC-style unified dtor
40+
Dtor_VectorDeleting, ///< Vector deleting dtor
4041
};
4142

4243
} // end namespace clang

clang/include/clang/Basic/TargetInfo.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1796,6 +1796,11 @@ class TargetInfo : public TransferrableTargetInfo,
17961796
/// destructor body.
17971797
virtual bool callGlobalDeleteInDeletingDtor(const LangOptions &) const;
17981798

1799+
/// Controls whether to emit MSVC vector deleting destructors. The support for
1800+
/// vector deleting affects vtable layout and therefore is an ABI breaking
1801+
/// change. The support was only implemented at Clang 22 timeframe.
1802+
virtual bool emitVectorDeletingDtors(const LangOptions &) const;
1803+
17991804
/// Controls if __builtin_longjmp / __builtin_setjmp can be lowered to
18001805
/// llvm.eh.sjlj.longjmp / llvm.eh.sjlj.setjmp.
18011806
virtual bool hasSjLjLowering() const {

clang/include/clang/Sema/Sema.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8581,7 +8581,8 @@ class Sema final : public SemaBase {
85818581
FunctionDecl *FindDeallocationFunctionForDestructor(SourceLocation StartLoc,
85828582
CXXRecordDecl *RD,
85838583
bool Diagnose,
8584-
bool LookForGlobal);
8584+
bool LookForGlobal,
8585+
DeclarationName Name);
85858586

85868587
/// ActOnCXXDelete - Parsed a C++ 'delete' expression (C++ 5.3.5), as in:
85878588
/// @code ::delete ptr; @endcode

clang/include/clang/Serialization/ASTWriter.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -955,6 +955,10 @@ class ASTWriter : public ASTDeserializationListener,
955955
Expr *ThisArg) override;
956956
void ResolvedOperatorGlobDelete(const CXXDestructorDecl *DD,
957957
const FunctionDecl *Delete) override;
958+
void ResolvedOperatorArrayDelete(const CXXDestructorDecl *DD,
959+
const FunctionDecl *Delete) override;
960+
void ResolvedOperatorGlobArrayDelete(const CXXDestructorDecl *DD,
961+
const FunctionDecl *Delete) override;
958962
void CompletedImplicitDefinition(const FunctionDecl *D) override;
959963
void InstantiationRequested(const ValueDecl *D) override;
960964
void VariableDefinitionInstantiated(const VarDecl *D) override;

clang/lib/AST/ASTContext.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13337,6 +13337,71 @@ bool ASTContext::isTypeAwareOperatorNewOrDelete(const FunctionDecl *FD) const {
1333713337
return TypeAwareOperatorNewAndDeletes.contains(FD->getCanonicalDecl());
1333813338
}
1333913339

13340+
void ASTContext::addOperatorDeleteForVDtor(const CXXDestructorDecl *Dtor,
13341+
FunctionDecl *OperatorDelete,
13342+
OperatorDeleteKind K) const {
13343+
switch (K) {
13344+
case OperatorDeleteKind::Regular:
13345+
OperatorDeletesForVirtualDtor[Dtor->getCanonicalDecl()] = OperatorDelete;
13346+
break;
13347+
case OperatorDeleteKind::GlobalRegular:
13348+
GlobalOperatorDeletesForVirtualDtor[Dtor->getCanonicalDecl()] =
13349+
OperatorDelete;
13350+
break;
13351+
case OperatorDeleteKind::Array:
13352+
ArrayOperatorDeletesForVirtualDtor[Dtor->getCanonicalDecl()] =
13353+
OperatorDelete;
13354+
break;
13355+
case OperatorDeleteKind::ArrayGlobal:
13356+
GlobalArrayOperatorDeletesForVirtualDtor[Dtor->getCanonicalDecl()] =
13357+
OperatorDelete;
13358+
break;
13359+
}
13360+
}
13361+
13362+
bool ASTContext::dtorHasOperatorDelete(const CXXDestructorDecl *Dtor,
13363+
OperatorDeleteKind K) const {
13364+
switch (K) {
13365+
case OperatorDeleteKind::Regular:
13366+
return OperatorDeletesForVirtualDtor.contains(Dtor->getCanonicalDecl());
13367+
case OperatorDeleteKind::GlobalRegular:
13368+
return GlobalOperatorDeletesForVirtualDtor.contains(
13369+
Dtor->getCanonicalDecl());
13370+
case OperatorDeleteKind::Array:
13371+
return ArrayOperatorDeletesForVirtualDtor.contains(
13372+
Dtor->getCanonicalDecl());
13373+
case OperatorDeleteKind::ArrayGlobal:
13374+
return GlobalArrayOperatorDeletesForVirtualDtor.contains(
13375+
Dtor->getCanonicalDecl());
13376+
}
13377+
return false;
13378+
}
13379+
13380+
FunctionDecl *
13381+
ASTContext::getOperatorDeleteForVDtor(const CXXDestructorDecl *Dtor,
13382+
OperatorDeleteKind K) const {
13383+
const CXXDestructorDecl *Canon = Dtor->getCanonicalDecl();
13384+
switch (K) {
13385+
case OperatorDeleteKind::Regular:
13386+
if (OperatorDeletesForVirtualDtor.contains(Canon))
13387+
return OperatorDeletesForVirtualDtor[Canon];
13388+
return nullptr;
13389+
case OperatorDeleteKind::GlobalRegular:
13390+
if (GlobalOperatorDeletesForVirtualDtor.contains(Canon))
13391+
return GlobalOperatorDeletesForVirtualDtor[Canon];
13392+
return nullptr;
13393+
case OperatorDeleteKind::Array:
13394+
if (ArrayOperatorDeletesForVirtualDtor.contains(Canon))
13395+
return ArrayOperatorDeletesForVirtualDtor[Canon];
13396+
return nullptr;
13397+
case OperatorDeleteKind::ArrayGlobal:
13398+
if (GlobalArrayOperatorDeletesForVirtualDtor.contains(Canon))
13399+
return GlobalArrayOperatorDeletesForVirtualDtor[Canon];
13400+
return nullptr;
13401+
}
13402+
return nullptr;
13403+
}
13404+
1334013405
MangleNumberingContext &
1334113406
ASTContext::getManglingNumberContext(const DeclContext *DC) {
1334213407
assert(LangOpts.CPlusPlus); // We don't need mangling numbers for plain C.

0 commit comments

Comments
 (0)