Skip to content

Conversation

@Fznamznon
Copy link
Contributor

This reverts 4d10c11 and e6b9805 because it broke Chromium builds with /Zc:DllexportInlines- .

@llvmbot llvmbot added lldb clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:modules C++20 modules and Clang Header Modules clang:codegen IR generation bugs: mangling, exceptions, etc. debuginfo ClangIR Anything related to the ClangIR project labels Nov 21, 2025
@llvmbot
Copy link
Member

llvmbot commented Nov 21, 2025

@llvm/pr-subscribers-debuginfo

@llvm/pr-subscribers-clang-modules

Author: Mariya Podchishchaeva (Fznamznon)

Changes

This reverts 4d10c11 and e6b9805 because it broke Chromium builds with /Zc:DllexportInlines- .


Patch is 122.64 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/169063.diff

59 Files Affected:

  • (modified) clang/docs/ReleaseNotes.rst (-8)
  • (modified) clang/include/clang/AST/ASTContext.h (-22)
  • (modified) clang/include/clang/AST/ASTMutationListener.h (-9)
  • (modified) clang/include/clang/AST/DeclCXX.h (+10-6)
  • (modified) clang/include/clang/AST/VTableBuilder.h (+2-4)
  • (modified) clang/include/clang/Basic/ABI.h (+5-6)
  • (modified) clang/include/clang/Basic/TargetInfo.h (-5)
  • (modified) clang/include/clang/Sema/Sema.h (+1-2)
  • (modified) clang/include/clang/Serialization/ASTWriter.h (-4)
  • (modified) clang/lib/AST/ASTContext.cpp (-65)
  • (modified) clang/lib/AST/DeclCXX.cpp (+10-63)
  • (modified) clang/lib/AST/Expr.cpp (-3)
  • (modified) clang/lib/AST/ItaniumMangle.cpp (-2)
  • (modified) clang/lib/AST/MicrosoftMangle.cpp (+9-13)
  • (modified) clang/lib/AST/VTableBuilder.cpp (+4-14)
  • (modified) clang/lib/Basic/TargetInfo.cpp (-7)
  • (modified) clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp (-7)
  • (modified) clang/lib/CIR/CodeGen/CIRGenFunction.cpp (+1-4)
  • (modified) clang/lib/CodeGen/CGCXX.cpp (+1-36)
  • (modified) clang/lib/CodeGen/CGCXXABI.cpp (-14)
  • (modified) clang/lib/CodeGen/CGCXXABI.h (-6)
  • (modified) clang/lib/CodeGen/CGClass.cpp (+1-94)
  • (modified) clang/lib/CodeGen/CGDebugInfo.cpp (+1-7)
  • (modified) clang/lib/CodeGen/CGExprCXX.cpp (+4-48)
  • (modified) clang/lib/CodeGen/CGVTables.cpp (+1-3)
  • (modified) clang/lib/CodeGen/CodeGenModule.cpp (-50)
  • (modified) clang/lib/CodeGen/CodeGenModule.h (-6)
  • (modified) clang/lib/CodeGen/ItaniumCXXABI.cpp (+1-4)
  • (modified) clang/lib/CodeGen/MicrosoftCXXABI.cpp (+14-56)
  • (modified) clang/lib/Sema/SemaDeclCXX.cpp (+2-28)
  • (modified) clang/lib/Sema/SemaExprCXX.cpp (+6-7)
  • (modified) clang/lib/Serialization/ASTCommon.h (+1-3)
  • (modified) clang/lib/Serialization/ASTReaderDecl.cpp (+13-53)
  • (modified) clang/lib/Serialization/ASTWriter.cpp (-36)
  • (modified) clang/lib/Serialization/ASTWriterDecl.cpp (-2)
  • (modified) clang/test/CodeGenCXX/dllexport.cpp (+2-3)
  • (modified) clang/test/CodeGenCXX/microsoft-abi-extern-template.cpp (+1-1)
  • (modified) clang/test/CodeGenCXX/microsoft-abi-structors.cpp (+1-1)
  • (modified) clang/test/CodeGenCXX/microsoft-abi-thunks.cpp (+2-1)
  • (modified) clang/test/CodeGenCXX/microsoft-abi-vftables.cpp (+10-10)
  • (modified) clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp (+8-9)
  • (modified) clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-vdtors.cpp (+9-9)
  • (modified) clang/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp (+1-1)
  • (modified) clang/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp (+10-10)
  • (modified) clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp (+15-15)
  • (modified) clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp (+9-9)
  • (modified) clang/test/CodeGenCXX/microsoft-no-rtti-data.cpp (+1-1)
  • (removed) clang/test/CodeGenCXX/microsoft-vector-deleting-dtors.cpp (-336)
  • (modified) clang/test/CodeGenCXX/vtable-consteval.cpp (+2-2)
  • (modified) clang/test/DebugInfo/CXX/windows-dtor.cpp (+1-1)
  • (removed) clang/test/Modules/Inputs/msvc-vector-deleting-dtors/module.modulemap (-1)
  • (removed) clang/test/Modules/Inputs/msvc-vector-deleting-dtors/msvc-vector-deleting-dtors.h (-16)
  • (removed) clang/test/Modules/msvc-vector-deleting-destructors.cpp (-30)
  • (modified) clang/test/Modules/vtable-windows.cppm (+1-1)
  • (removed) clang/test/PCH/Inputs/msvc-vector-deleting-dtors.h (-16)
  • (removed) clang/test/PCH/msvc-vector-deleting-destructors.cpp (-34)
  • (modified) clang/test/Profile/cxx-abc-deleting-dtor.cpp (+5-4)
  • (removed) clang/test/SemaCXX/gh134265.cpp (-62)
  • (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (-1)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7e440c35a5b98..e8bd591a44d18 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -84,12 +84,6 @@ Potentially Breaking Changes
 - Downstream projects that previously linked only against ``clangDriver`` may
   now (also) need to link against the new ``clangOptions`` library, since
   options-related code has been moved out of the Driver into a separate library.
-- Clang now supports MSVC vector deleting destructors when targeting Windows.
-  This means that vtables of classes with virtual destructors will contain a
-  pointer to vector deleting destructor (instead of scalar deleting destructor)
-  which in fact is a different symbol with different name and linkage. This
-  may cause runtime failures if two binaries using the same class defining a
-  virtual destructor are compiled with different versions of clang.
 
 C/C++ Language Potentially Breaking Changes
 -------------------------------------------
@@ -621,8 +615,6 @@ Windows Support
 - clang-cl now supports /arch:AVX10.1 and /arch:AVX10.2.
 - clang-cl now supports /vlen, /vlen=256 and /vlen=512.
 
-- Clang now supports MSVC vector deleting destructors (GH19772).
-
 LoongArch Support
 ^^^^^^^^^^^^^^^^^
 - Enable linker relaxation by default for loongarch64.
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 6e9e737dcae4f..33aa2d343aa7a 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -370,18 +370,6 @@ class ASTContext : public RefCountedBase<ASTContext> {
   mutable llvm::DenseSet<const FunctionDecl *> DestroyingOperatorDeletes;
   mutable llvm::DenseSet<const FunctionDecl *> TypeAwareOperatorNewAndDeletes;
 
-  /// Global and array operators delete are only required for MSVC deleting
-  /// destructors support. Store them here to avoid keeping 4 pointers that are
-  /// not always used in each redeclaration of the destructor.
-  mutable llvm::DenseMap<const CXXDestructorDecl *, FunctionDecl *>
-      OperatorDeletesForVirtualDtor;
-  mutable llvm::DenseMap<const CXXDestructorDecl *, FunctionDecl *>
-      GlobalOperatorDeletesForVirtualDtor;
-  mutable llvm::DenseMap<const CXXDestructorDecl *, FunctionDecl *>
-      ArrayOperatorDeletesForVirtualDtor;
-  mutable llvm::DenseMap<const CXXDestructorDecl *, FunctionDecl *>
-      GlobalArrayOperatorDeletesForVirtualDtor;
-
   /// The next string literal "version" to allocate during constant evaluation.
   /// This is used to distinguish between repeated evaluations of the same
   /// string literal.
@@ -3485,16 +3473,6 @@ class ASTContext : public RefCountedBase<ASTContext> {
                                          bool IsTypeAware);
   bool isTypeAwareOperatorNewOrDelete(const FunctionDecl *FD) const;
 
-  enum OperatorDeleteKind { Regular, GlobalRegular, Array, ArrayGlobal };
-
-  void addOperatorDeleteForVDtor(const CXXDestructorDecl *Dtor,
-                                 FunctionDecl *OperatorDelete,
-                                 OperatorDeleteKind K) const;
-  FunctionDecl *getOperatorDeleteForVDtor(const CXXDestructorDecl *Dtor,
-                                          OperatorDeleteKind K) const;
-  bool dtorHasOperatorDelete(const CXXDestructorDecl *Dtor,
-                             OperatorDeleteKind K) const;
-
   /// Retrieve the context for computing mangling numbers in the given
   /// DeclContext.
   MangleNumberingContext &getManglingNumberContext(const DeclContext *DC);
diff --git a/clang/include/clang/AST/ASTMutationListener.h b/clang/include/clang/AST/ASTMutationListener.h
index c8448a25c23a4..352af42391782 100644
--- a/clang/include/clang/AST/ASTMutationListener.h
+++ b/clang/include/clang/AST/ASTMutationListener.h
@@ -90,15 +90,6 @@ class ASTMutationListener {
   virtual void ResolvedOperatorGlobDelete(const CXXDestructorDecl *DD,
                                           const FunctionDecl *GlobDelete) {}
 
-  /// A virtual destructor's operator array delete has been resolved.
-  virtual void ResolvedOperatorArrayDelete(const CXXDestructorDecl *DD,
-                                           const FunctionDecl *ArrayDelete) {}
-
-  /// A virtual destructor's operator global array delete has been resolved.
-  virtual void
-  ResolvedOperatorGlobArrayDelete(const CXXDestructorDecl *DD,
-                                  const FunctionDecl *GlobArrayDelete) {}
-
   /// An implicit member got a definition.
   virtual void CompletedImplicitDefinition(const FunctionDecl *D) {}
 
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h
index 5c4ad3c45da19..dfa3befb27dd0 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -2872,6 +2872,8 @@ class CXXDestructorDecl : public CXXMethodDecl {
 
   // FIXME: Don't allocate storage for these except in the first declaration
   // of a virtual destructor.
+  FunctionDecl *OperatorDelete = nullptr;
+  FunctionDecl *OperatorGlobalDelete = nullptr;
   Expr *OperatorDeleteThisArg = nullptr;
 
   CXXDestructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
@@ -2898,12 +2900,14 @@ class CXXDestructorDecl : public CXXMethodDecl {
 
   void setOperatorDelete(FunctionDecl *OD, Expr *ThisArg);
   void setOperatorGlobalDelete(FunctionDecl *OD);
-  void setOperatorArrayDelete(FunctionDecl *OD);
-  void setGlobalOperatorArrayDelete(FunctionDecl *OD);
-  const FunctionDecl *getOperatorDelete() const;
-  const FunctionDecl *getOperatorGlobalDelete() const;
-  const FunctionDecl *getArrayOperatorDelete() const;
-  const FunctionDecl *getGlobalArrayOperatorDelete() const;
+
+  const FunctionDecl *getOperatorDelete() const {
+    return getCanonicalDecl()->OperatorDelete;
+  }
+
+  const FunctionDecl *getOperatorGlobalDelete() const {
+    return getCanonicalDecl()->OperatorGlobalDelete;
+  }
 
   Expr *getOperatorDeleteThisArg() const {
     return getCanonicalDecl()->OperatorDeleteThisArg;
diff --git a/clang/include/clang/AST/VTableBuilder.h b/clang/include/clang/AST/VTableBuilder.h
index e1efe8cddcc5e..a5de41dbc22f1 100644
--- a/clang/include/clang/AST/VTableBuilder.h
+++ b/clang/include/clang/AST/VTableBuilder.h
@@ -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");
 
@@ -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:
diff --git a/clang/include/clang/Basic/ABI.h b/clang/include/clang/Basic/ABI.h
index be3edccbf50b2..8279529c316cf 100644
--- a/clang/include/clang/Basic/ABI.h
+++ b/clang/include/clang/Basic/ABI.h
@@ -32,12 +32,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_Unified,        ///< GCC-style unified dtor
-  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
+  Dtor_Unified,  ///< GCC-style unified dtor
 };
 
 } // end namespace clang
diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h
index 1c16f9f79ae68..39af84c8d0872 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -1796,11 +1796,6 @@ class TargetInfo : public TransferrableTargetInfo,
   /// destructor body.
   virtual bool callGlobalDeleteInDeletingDtor(const LangOptions &) const;
 
-  /// Controls whether to emit MSVC vector deleting destructors. The support for
-  /// vector deleting affects vtable layout and therefore is an ABI breaking
-  /// change. The support was only implemented at Clang 22 timeframe.
-  virtual bool emitVectorDeletingDtors(const LangOptions &) const;
-
   /// Controls if __builtin_longjmp / __builtin_setjmp can be lowered to
   /// llvm.eh.sjlj.longjmp / llvm.eh.sjlj.setjmp.
   virtual bool hasSjLjLowering() const {
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index cbfcc9bc0ea99..ae500139ee6f7 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -8581,8 +8581,7 @@ class Sema final : public SemaBase {
   FunctionDecl *FindDeallocationFunctionForDestructor(SourceLocation StartLoc,
                                                       CXXRecordDecl *RD,
                                                       bool Diagnose,
-                                                      bool LookForGlobal,
-                                                      DeclarationName Name);
+                                                      bool LookForGlobal);
 
   /// ActOnCXXDelete - Parsed a C++ 'delete' expression (C++ 5.3.5), as in:
   /// @code ::delete ptr; @endcode
diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h
index dbbfc29058f43..c77c98dffc39f 100644
--- a/clang/include/clang/Serialization/ASTWriter.h
+++ b/clang/include/clang/Serialization/ASTWriter.h
@@ -955,10 +955,6 @@ class ASTWriter : public ASTDeserializationListener,
                               Expr *ThisArg) override;
   void ResolvedOperatorGlobDelete(const CXXDestructorDecl *DD,
                                   const FunctionDecl *Delete) override;
-  void ResolvedOperatorArrayDelete(const CXXDestructorDecl *DD,
-                                   const FunctionDecl *Delete) override;
-  void ResolvedOperatorGlobArrayDelete(const CXXDestructorDecl *DD,
-                                       const FunctionDecl *Delete) override;
   void CompletedImplicitDefinition(const FunctionDecl *D) override;
   void InstantiationRequested(const ValueDecl *D) override;
   void VariableDefinitionInstantiated(const VarDecl *D) override;
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index b929b0fc1aa8e..b359fc8350375 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -13337,71 +13337,6 @@ bool ASTContext::isTypeAwareOperatorNewOrDelete(const FunctionDecl *FD) const {
   return TypeAwareOperatorNewAndDeletes.contains(FD->getCanonicalDecl());
 }
 
-void ASTContext::addOperatorDeleteForVDtor(const CXXDestructorDecl *Dtor,
-                                           FunctionDecl *OperatorDelete,
-                                           OperatorDeleteKind K) const {
-  switch (K) {
-  case OperatorDeleteKind::Regular:
-    OperatorDeletesForVirtualDtor[Dtor->getCanonicalDecl()] = OperatorDelete;
-    break;
-  case OperatorDeleteKind::GlobalRegular:
-    GlobalOperatorDeletesForVirtualDtor[Dtor->getCanonicalDecl()] =
-        OperatorDelete;
-    break;
-  case OperatorDeleteKind::Array:
-    ArrayOperatorDeletesForVirtualDtor[Dtor->getCanonicalDecl()] =
-        OperatorDelete;
-    break;
-  case OperatorDeleteKind::ArrayGlobal:
-    GlobalArrayOperatorDeletesForVirtualDtor[Dtor->getCanonicalDecl()] =
-        OperatorDelete;
-    break;
-  }
-}
-
-bool ASTContext::dtorHasOperatorDelete(const CXXDestructorDecl *Dtor,
-                                       OperatorDeleteKind K) const {
-  switch (K) {
-  case OperatorDeleteKind::Regular:
-    return OperatorDeletesForVirtualDtor.contains(Dtor->getCanonicalDecl());
-  case OperatorDeleteKind::GlobalRegular:
-    return GlobalOperatorDeletesForVirtualDtor.contains(
-        Dtor->getCanonicalDecl());
-  case OperatorDeleteKind::Array:
-    return ArrayOperatorDeletesForVirtualDtor.contains(
-        Dtor->getCanonicalDecl());
-  case OperatorDeleteKind::ArrayGlobal:
-    return GlobalArrayOperatorDeletesForVirtualDtor.contains(
-        Dtor->getCanonicalDecl());
-  }
-  return false;
-}
-
-FunctionDecl *
-ASTContext::getOperatorDeleteForVDtor(const CXXDestructorDecl *Dtor,
-                                      OperatorDeleteKind K) const {
-  const CXXDestructorDecl *Canon = Dtor->getCanonicalDecl();
-  switch (K) {
-  case OperatorDeleteKind::Regular:
-    if (OperatorDeletesForVirtualDtor.contains(Canon))
-      return OperatorDeletesForVirtualDtor[Canon];
-    return nullptr;
-  case OperatorDeleteKind::GlobalRegular:
-    if (GlobalOperatorDeletesForVirtualDtor.contains(Canon))
-      return GlobalOperatorDeletesForVirtualDtor[Canon];
-    return nullptr;
-  case OperatorDeleteKind::Array:
-    if (ArrayOperatorDeletesForVirtualDtor.contains(Canon))
-      return ArrayOperatorDeletesForVirtualDtor[Canon];
-    return nullptr;
-  case OperatorDeleteKind::ArrayGlobal:
-    if (GlobalArrayOperatorDeletesForVirtualDtor.contains(Canon))
-      return GlobalArrayOperatorDeletesForVirtualDtor[Canon];
-    return nullptr;
-  }
-  return nullptr;
-}
-
 MangleNumberingContext &
 ASTContext::getManglingNumberContext(const DeclContext *DC) {
   assert(LangOpts.CPlusPlus);  // We don't need mangling numbers for plain C.
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index c16b1bb7a3453..24e4f189cbe4a 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -3110,15 +3110,12 @@ CXXDestructorDecl *CXXDestructorDecl::Create(
 }
 
 void CXXDestructorDecl::setOperatorDelete(FunctionDecl *OD, Expr *ThisArg) {
-  assert(!OD || (OD->getDeclName().getCXXOverloadedOperator() == OO_Delete));
-  if (OD && !getASTContext().dtorHasOperatorDelete(
-                this, ASTContext::OperatorDeleteKind::Regular)) {
-    getASTContext().addOperatorDeleteForVDtor(
-        this, OD, ASTContext::OperatorDeleteKind::Regular);
-    getCanonicalDecl()->OperatorDeleteThisArg = ThisArg;
+  auto *First = cast<CXXDestructorDecl>(getFirstDecl());
+  if (OD && !First->OperatorDelete) {
+    First->OperatorDelete = OD;
+    First->OperatorDeleteThisArg = ThisArg;
     if (auto *L = getASTMutationListener())
-      L->ResolvedOperatorDelete(cast<CXXDestructorDecl>(getCanonicalDecl()), OD,
-                                ThisArg);
+      L->ResolvedOperatorDelete(First, OD, ThisArg);
   }
 }
 
@@ -3130,63 +3127,14 @@ void CXXDestructorDecl::setOperatorGlobalDelete(FunctionDecl *OD) {
   assert(!OD ||
          (OD->getDeclName().getCXXOverloadedOperator() == OO_Delete &&
           OD->getDeclContext()->getRedeclContext()->isTranslationUnit()));
-  if (OD && !getASTContext().dtorHasOperatorDelete(
-                this, ASTContext::OperatorDeleteKind::GlobalRegular)) {
-    getASTContext().addOperatorDeleteForVDtor(
-        this, OD, ASTContext::OperatorDeleteKind::GlobalRegular);
+  auto *Canonical = cast<CXXDestructorDecl>(getCanonicalDecl());
+  if (!Canonical->OperatorGlobalDelete) {
+    Canonical->OperatorGlobalDelete = OD;
     if (auto *L = getASTMutationListener())
-      L->ResolvedOperatorGlobDelete(cast<CXXDestructorDecl>(getCanonicalDecl()),
-                                    OD);
+      L->ResolvedOperatorGlobDelete(Canonical, OD);
   }
 }
 
-void CXXDestructorDecl::setOperatorArrayDelete(FunctionDecl *OD) {
-  assert(!OD ||
-         (OD->getDeclName().getCXXOverloadedOperator() == OO_Array_Delete));
-  if (OD && !getASTContext().dtorHasOperatorDelete(
-                this, ASTContext::OperatorDeleteKind::Array)) {
-    getASTContext().addOperatorDeleteForVDtor(
-        this, OD, ASTContext::OperatorDeleteKind::Array);
-    if (auto *L = getASTMutationListener())
-      L->ResolvedOperatorArrayDelete(
-          cast<CXXDestructorDecl>(getCanonicalDecl()), OD);
-  }
-}
-
-void CXXDestructorDecl::setGlobalOperatorArrayDelete(FunctionDecl *OD) {
-  assert(!OD ||
-         (OD->getDeclName().getCXXOverloadedOperator() == OO_Array_Delete &&
-          OD->getDeclContext()->getRedeclContext()->isTranslationUnit()));
-  if (OD && !getASTContext().dtorHasOperatorDelete(
-                this, ASTContext::OperatorDeleteKind::ArrayGlobal)) {
-    getASTContext().addOperatorDeleteForVDtor(
-        this, OD, ASTContext::OperatorDeleteKind::ArrayGlobal);
-    if (auto *L = getASTMutationListener())
-      L->ResolvedOperatorGlobArrayDelete(
-          cast<CXXDestructorDecl>(getCanonicalDecl()), OD);
-  }
-}
-
-const FunctionDecl *CXXDestructorDecl::getOperatorDelete() const {
-  return getASTContext().getOperatorDeleteForVDtor(
-      this, ASTContext::OperatorDeleteKind::Regular);
-}
-
-const FunctionDecl *CXXDestructorDecl::getOperatorGlobalDelete() const {
-  return getASTContext().getOperatorDeleteForVDtor(
-      this, ASTContext::OperatorDeleteKind::GlobalRegular);
-}
-
-const FunctionDecl *CXXDestructorDecl::getArrayOperatorDelete() const {
-  return getASTContext().getOperatorDeleteForVDtor(
-      this, ASTContext::OperatorDeleteKind::Array);
-}
-
-const FunctionDecl *CXXDestructorDecl::getGlobalArrayOperatorDelete() const {
-  return getASTContext().getOperatorDeleteForVDtor(
-      this, ASTContext::OperatorDeleteKind::ArrayGlobal);
-}
-
 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
@@ -3198,8 +3146,7 @@ bool CXXDestructorDecl::isCalledByDelete(const FunctionDecl *OpDel) const {
   // delete operator, as that destructor is never called, unless the
   // destructor is virtual (see [expr.delete]p8.1) because then the
   // selected operator depends on the dynamic type of the pointer.
-  const FunctionDecl *SelectedOperatorDelete =
-      OpDel ? OpDel : getOperatorDelete();
+  const FunctionDecl *SelectedOperatorDelete = OpDel ? OpDel : OperatorDelete;
   if (!SelectedOperatorDelete)
     return true;
 
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 1d914fa876759..340bb4b2ed6a3 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -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;
 
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index a5bcf5c97e837..5572e0a7ae59c 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -6040,8 +6040,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");
   }
 }
 
diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp
index 551aa7bf3321c..f1baf9f49384b 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -1492,9 +1492,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");
   case Dtor_Unified:
@@ -2914,12 +2913,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. ...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Nov 21, 2025

@llvm/pr-subscribers-clangir

Author: Mariya Podchishchaeva (Fznamznon)

Changes

This reverts 4d10c11 and e6b9805 because it broke Chromium builds with /Zc:DllexportInlines- .


Patch is 122.64 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/169063.diff

59 Files Affected:

  • (modified) clang/docs/ReleaseNotes.rst (-8)
  • (modified) clang/include/clang/AST/ASTContext.h (-22)
  • (modified) clang/include/clang/AST/ASTMutationListener.h (-9)
  • (modified) clang/include/clang/AST/DeclCXX.h (+10-6)
  • (modified) clang/include/clang/AST/VTableBuilder.h (+2-4)
  • (modified) clang/include/clang/Basic/ABI.h (+5-6)
  • (modified) clang/include/clang/Basic/TargetInfo.h (-5)
  • (modified) clang/include/clang/Sema/Sema.h (+1-2)
  • (modified) clang/include/clang/Serialization/ASTWriter.h (-4)
  • (modified) clang/lib/AST/ASTContext.cpp (-65)
  • (modified) clang/lib/AST/DeclCXX.cpp (+10-63)
  • (modified) clang/lib/AST/Expr.cpp (-3)
  • (modified) clang/lib/AST/ItaniumMangle.cpp (-2)
  • (modified) clang/lib/AST/MicrosoftMangle.cpp (+9-13)
  • (modified) clang/lib/AST/VTableBuilder.cpp (+4-14)
  • (modified) clang/lib/Basic/TargetInfo.cpp (-7)
  • (modified) clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp (-7)
  • (modified) clang/lib/CIR/CodeGen/CIRGenFunction.cpp (+1-4)
  • (modified) clang/lib/CodeGen/CGCXX.cpp (+1-36)
  • (modified) clang/lib/CodeGen/CGCXXABI.cpp (-14)
  • (modified) clang/lib/CodeGen/CGCXXABI.h (-6)
  • (modified) clang/lib/CodeGen/CGClass.cpp (+1-94)
  • (modified) clang/lib/CodeGen/CGDebugInfo.cpp (+1-7)
  • (modified) clang/lib/CodeGen/CGExprCXX.cpp (+4-48)
  • (modified) clang/lib/CodeGen/CGVTables.cpp (+1-3)
  • (modified) clang/lib/CodeGen/CodeGenModule.cpp (-50)
  • (modified) clang/lib/CodeGen/CodeGenModule.h (-6)
  • (modified) clang/lib/CodeGen/ItaniumCXXABI.cpp (+1-4)
  • (modified) clang/lib/CodeGen/MicrosoftCXXABI.cpp (+14-56)
  • (modified) clang/lib/Sema/SemaDeclCXX.cpp (+2-28)
  • (modified) clang/lib/Sema/SemaExprCXX.cpp (+6-7)
  • (modified) clang/lib/Serialization/ASTCommon.h (+1-3)
  • (modified) clang/lib/Serialization/ASTReaderDecl.cpp (+13-53)
  • (modified) clang/lib/Serialization/ASTWriter.cpp (-36)
  • (modified) clang/lib/Serialization/ASTWriterDecl.cpp (-2)
  • (modified) clang/test/CodeGenCXX/dllexport.cpp (+2-3)
  • (modified) clang/test/CodeGenCXX/microsoft-abi-extern-template.cpp (+1-1)
  • (modified) clang/test/CodeGenCXX/microsoft-abi-structors.cpp (+1-1)
  • (modified) clang/test/CodeGenCXX/microsoft-abi-thunks.cpp (+2-1)
  • (modified) clang/test/CodeGenCXX/microsoft-abi-vftables.cpp (+10-10)
  • (modified) clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp (+8-9)
  • (modified) clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-vdtors.cpp (+9-9)
  • (modified) clang/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp (+1-1)
  • (modified) clang/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp (+10-10)
  • (modified) clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp (+15-15)
  • (modified) clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp (+9-9)
  • (modified) clang/test/CodeGenCXX/microsoft-no-rtti-data.cpp (+1-1)
  • (removed) clang/test/CodeGenCXX/microsoft-vector-deleting-dtors.cpp (-336)
  • (modified) clang/test/CodeGenCXX/vtable-consteval.cpp (+2-2)
  • (modified) clang/test/DebugInfo/CXX/windows-dtor.cpp (+1-1)
  • (removed) clang/test/Modules/Inputs/msvc-vector-deleting-dtors/module.modulemap (-1)
  • (removed) clang/test/Modules/Inputs/msvc-vector-deleting-dtors/msvc-vector-deleting-dtors.h (-16)
  • (removed) clang/test/Modules/msvc-vector-deleting-destructors.cpp (-30)
  • (modified) clang/test/Modules/vtable-windows.cppm (+1-1)
  • (removed) clang/test/PCH/Inputs/msvc-vector-deleting-dtors.h (-16)
  • (removed) clang/test/PCH/msvc-vector-deleting-destructors.cpp (-34)
  • (modified) clang/test/Profile/cxx-abc-deleting-dtor.cpp (+5-4)
  • (removed) clang/test/SemaCXX/gh134265.cpp (-62)
  • (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (-1)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7e440c35a5b98..e8bd591a44d18 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -84,12 +84,6 @@ Potentially Breaking Changes
 - Downstream projects that previously linked only against ``clangDriver`` may
   now (also) need to link against the new ``clangOptions`` library, since
   options-related code has been moved out of the Driver into a separate library.
-- Clang now supports MSVC vector deleting destructors when targeting Windows.
-  This means that vtables of classes with virtual destructors will contain a
-  pointer to vector deleting destructor (instead of scalar deleting destructor)
-  which in fact is a different symbol with different name and linkage. This
-  may cause runtime failures if two binaries using the same class defining a
-  virtual destructor are compiled with different versions of clang.
 
 C/C++ Language Potentially Breaking Changes
 -------------------------------------------
@@ -621,8 +615,6 @@ Windows Support
 - clang-cl now supports /arch:AVX10.1 and /arch:AVX10.2.
 - clang-cl now supports /vlen, /vlen=256 and /vlen=512.
 
-- Clang now supports MSVC vector deleting destructors (GH19772).
-
 LoongArch Support
 ^^^^^^^^^^^^^^^^^
 - Enable linker relaxation by default for loongarch64.
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 6e9e737dcae4f..33aa2d343aa7a 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -370,18 +370,6 @@ class ASTContext : public RefCountedBase<ASTContext> {
   mutable llvm::DenseSet<const FunctionDecl *> DestroyingOperatorDeletes;
   mutable llvm::DenseSet<const FunctionDecl *> TypeAwareOperatorNewAndDeletes;
 
-  /// Global and array operators delete are only required for MSVC deleting
-  /// destructors support. Store them here to avoid keeping 4 pointers that are
-  /// not always used in each redeclaration of the destructor.
-  mutable llvm::DenseMap<const CXXDestructorDecl *, FunctionDecl *>
-      OperatorDeletesForVirtualDtor;
-  mutable llvm::DenseMap<const CXXDestructorDecl *, FunctionDecl *>
-      GlobalOperatorDeletesForVirtualDtor;
-  mutable llvm::DenseMap<const CXXDestructorDecl *, FunctionDecl *>
-      ArrayOperatorDeletesForVirtualDtor;
-  mutable llvm::DenseMap<const CXXDestructorDecl *, FunctionDecl *>
-      GlobalArrayOperatorDeletesForVirtualDtor;
-
   /// The next string literal "version" to allocate during constant evaluation.
   /// This is used to distinguish between repeated evaluations of the same
   /// string literal.
@@ -3485,16 +3473,6 @@ class ASTContext : public RefCountedBase<ASTContext> {
                                          bool IsTypeAware);
   bool isTypeAwareOperatorNewOrDelete(const FunctionDecl *FD) const;
 
-  enum OperatorDeleteKind { Regular, GlobalRegular, Array, ArrayGlobal };
-
-  void addOperatorDeleteForVDtor(const CXXDestructorDecl *Dtor,
-                                 FunctionDecl *OperatorDelete,
-                                 OperatorDeleteKind K) const;
-  FunctionDecl *getOperatorDeleteForVDtor(const CXXDestructorDecl *Dtor,
-                                          OperatorDeleteKind K) const;
-  bool dtorHasOperatorDelete(const CXXDestructorDecl *Dtor,
-                             OperatorDeleteKind K) const;
-
   /// Retrieve the context for computing mangling numbers in the given
   /// DeclContext.
   MangleNumberingContext &getManglingNumberContext(const DeclContext *DC);
diff --git a/clang/include/clang/AST/ASTMutationListener.h b/clang/include/clang/AST/ASTMutationListener.h
index c8448a25c23a4..352af42391782 100644
--- a/clang/include/clang/AST/ASTMutationListener.h
+++ b/clang/include/clang/AST/ASTMutationListener.h
@@ -90,15 +90,6 @@ class ASTMutationListener {
   virtual void ResolvedOperatorGlobDelete(const CXXDestructorDecl *DD,
                                           const FunctionDecl *GlobDelete) {}
 
-  /// A virtual destructor's operator array delete has been resolved.
-  virtual void ResolvedOperatorArrayDelete(const CXXDestructorDecl *DD,
-                                           const FunctionDecl *ArrayDelete) {}
-
-  /// A virtual destructor's operator global array delete has been resolved.
-  virtual void
-  ResolvedOperatorGlobArrayDelete(const CXXDestructorDecl *DD,
-                                  const FunctionDecl *GlobArrayDelete) {}
-
   /// An implicit member got a definition.
   virtual void CompletedImplicitDefinition(const FunctionDecl *D) {}
 
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h
index 5c4ad3c45da19..dfa3befb27dd0 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -2872,6 +2872,8 @@ class CXXDestructorDecl : public CXXMethodDecl {
 
   // FIXME: Don't allocate storage for these except in the first declaration
   // of a virtual destructor.
+  FunctionDecl *OperatorDelete = nullptr;
+  FunctionDecl *OperatorGlobalDelete = nullptr;
   Expr *OperatorDeleteThisArg = nullptr;
 
   CXXDestructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
@@ -2898,12 +2900,14 @@ class CXXDestructorDecl : public CXXMethodDecl {
 
   void setOperatorDelete(FunctionDecl *OD, Expr *ThisArg);
   void setOperatorGlobalDelete(FunctionDecl *OD);
-  void setOperatorArrayDelete(FunctionDecl *OD);
-  void setGlobalOperatorArrayDelete(FunctionDecl *OD);
-  const FunctionDecl *getOperatorDelete() const;
-  const FunctionDecl *getOperatorGlobalDelete() const;
-  const FunctionDecl *getArrayOperatorDelete() const;
-  const FunctionDecl *getGlobalArrayOperatorDelete() const;
+
+  const FunctionDecl *getOperatorDelete() const {
+    return getCanonicalDecl()->OperatorDelete;
+  }
+
+  const FunctionDecl *getOperatorGlobalDelete() const {
+    return getCanonicalDecl()->OperatorGlobalDelete;
+  }
 
   Expr *getOperatorDeleteThisArg() const {
     return getCanonicalDecl()->OperatorDeleteThisArg;
diff --git a/clang/include/clang/AST/VTableBuilder.h b/clang/include/clang/AST/VTableBuilder.h
index e1efe8cddcc5e..a5de41dbc22f1 100644
--- a/clang/include/clang/AST/VTableBuilder.h
+++ b/clang/include/clang/AST/VTableBuilder.h
@@ -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");
 
@@ -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:
diff --git a/clang/include/clang/Basic/ABI.h b/clang/include/clang/Basic/ABI.h
index be3edccbf50b2..8279529c316cf 100644
--- a/clang/include/clang/Basic/ABI.h
+++ b/clang/include/clang/Basic/ABI.h
@@ -32,12 +32,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_Unified,        ///< GCC-style unified dtor
-  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
+  Dtor_Unified,  ///< GCC-style unified dtor
 };
 
 } // end namespace clang
diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h
index 1c16f9f79ae68..39af84c8d0872 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -1796,11 +1796,6 @@ class TargetInfo : public TransferrableTargetInfo,
   /// destructor body.
   virtual bool callGlobalDeleteInDeletingDtor(const LangOptions &) const;
 
-  /// Controls whether to emit MSVC vector deleting destructors. The support for
-  /// vector deleting affects vtable layout and therefore is an ABI breaking
-  /// change. The support was only implemented at Clang 22 timeframe.
-  virtual bool emitVectorDeletingDtors(const LangOptions &) const;
-
   /// Controls if __builtin_longjmp / __builtin_setjmp can be lowered to
   /// llvm.eh.sjlj.longjmp / llvm.eh.sjlj.setjmp.
   virtual bool hasSjLjLowering() const {
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index cbfcc9bc0ea99..ae500139ee6f7 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -8581,8 +8581,7 @@ class Sema final : public SemaBase {
   FunctionDecl *FindDeallocationFunctionForDestructor(SourceLocation StartLoc,
                                                       CXXRecordDecl *RD,
                                                       bool Diagnose,
-                                                      bool LookForGlobal,
-                                                      DeclarationName Name);
+                                                      bool LookForGlobal);
 
   /// ActOnCXXDelete - Parsed a C++ 'delete' expression (C++ 5.3.5), as in:
   /// @code ::delete ptr; @endcode
diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h
index dbbfc29058f43..c77c98dffc39f 100644
--- a/clang/include/clang/Serialization/ASTWriter.h
+++ b/clang/include/clang/Serialization/ASTWriter.h
@@ -955,10 +955,6 @@ class ASTWriter : public ASTDeserializationListener,
                               Expr *ThisArg) override;
   void ResolvedOperatorGlobDelete(const CXXDestructorDecl *DD,
                                   const FunctionDecl *Delete) override;
-  void ResolvedOperatorArrayDelete(const CXXDestructorDecl *DD,
-                                   const FunctionDecl *Delete) override;
-  void ResolvedOperatorGlobArrayDelete(const CXXDestructorDecl *DD,
-                                       const FunctionDecl *Delete) override;
   void CompletedImplicitDefinition(const FunctionDecl *D) override;
   void InstantiationRequested(const ValueDecl *D) override;
   void VariableDefinitionInstantiated(const VarDecl *D) override;
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index b929b0fc1aa8e..b359fc8350375 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -13337,71 +13337,6 @@ bool ASTContext::isTypeAwareOperatorNewOrDelete(const FunctionDecl *FD) const {
   return TypeAwareOperatorNewAndDeletes.contains(FD->getCanonicalDecl());
 }
 
-void ASTContext::addOperatorDeleteForVDtor(const CXXDestructorDecl *Dtor,
-                                           FunctionDecl *OperatorDelete,
-                                           OperatorDeleteKind K) const {
-  switch (K) {
-  case OperatorDeleteKind::Regular:
-    OperatorDeletesForVirtualDtor[Dtor->getCanonicalDecl()] = OperatorDelete;
-    break;
-  case OperatorDeleteKind::GlobalRegular:
-    GlobalOperatorDeletesForVirtualDtor[Dtor->getCanonicalDecl()] =
-        OperatorDelete;
-    break;
-  case OperatorDeleteKind::Array:
-    ArrayOperatorDeletesForVirtualDtor[Dtor->getCanonicalDecl()] =
-        OperatorDelete;
-    break;
-  case OperatorDeleteKind::ArrayGlobal:
-    GlobalArrayOperatorDeletesForVirtualDtor[Dtor->getCanonicalDecl()] =
-        OperatorDelete;
-    break;
-  }
-}
-
-bool ASTContext::dtorHasOperatorDelete(const CXXDestructorDecl *Dtor,
-                                       OperatorDeleteKind K) const {
-  switch (K) {
-  case OperatorDeleteKind::Regular:
-    return OperatorDeletesForVirtualDtor.contains(Dtor->getCanonicalDecl());
-  case OperatorDeleteKind::GlobalRegular:
-    return GlobalOperatorDeletesForVirtualDtor.contains(
-        Dtor->getCanonicalDecl());
-  case OperatorDeleteKind::Array:
-    return ArrayOperatorDeletesForVirtualDtor.contains(
-        Dtor->getCanonicalDecl());
-  case OperatorDeleteKind::ArrayGlobal:
-    return GlobalArrayOperatorDeletesForVirtualDtor.contains(
-        Dtor->getCanonicalDecl());
-  }
-  return false;
-}
-
-FunctionDecl *
-ASTContext::getOperatorDeleteForVDtor(const CXXDestructorDecl *Dtor,
-                                      OperatorDeleteKind K) const {
-  const CXXDestructorDecl *Canon = Dtor->getCanonicalDecl();
-  switch (K) {
-  case OperatorDeleteKind::Regular:
-    if (OperatorDeletesForVirtualDtor.contains(Canon))
-      return OperatorDeletesForVirtualDtor[Canon];
-    return nullptr;
-  case OperatorDeleteKind::GlobalRegular:
-    if (GlobalOperatorDeletesForVirtualDtor.contains(Canon))
-      return GlobalOperatorDeletesForVirtualDtor[Canon];
-    return nullptr;
-  case OperatorDeleteKind::Array:
-    if (ArrayOperatorDeletesForVirtualDtor.contains(Canon))
-      return ArrayOperatorDeletesForVirtualDtor[Canon];
-    return nullptr;
-  case OperatorDeleteKind::ArrayGlobal:
-    if (GlobalArrayOperatorDeletesForVirtualDtor.contains(Canon))
-      return GlobalArrayOperatorDeletesForVirtualDtor[Canon];
-    return nullptr;
-  }
-  return nullptr;
-}
-
 MangleNumberingContext &
 ASTContext::getManglingNumberContext(const DeclContext *DC) {
   assert(LangOpts.CPlusPlus);  // We don't need mangling numbers for plain C.
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index c16b1bb7a3453..24e4f189cbe4a 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -3110,15 +3110,12 @@ CXXDestructorDecl *CXXDestructorDecl::Create(
 }
 
 void CXXDestructorDecl::setOperatorDelete(FunctionDecl *OD, Expr *ThisArg) {
-  assert(!OD || (OD->getDeclName().getCXXOverloadedOperator() == OO_Delete));
-  if (OD && !getASTContext().dtorHasOperatorDelete(
-                this, ASTContext::OperatorDeleteKind::Regular)) {
-    getASTContext().addOperatorDeleteForVDtor(
-        this, OD, ASTContext::OperatorDeleteKind::Regular);
-    getCanonicalDecl()->OperatorDeleteThisArg = ThisArg;
+  auto *First = cast<CXXDestructorDecl>(getFirstDecl());
+  if (OD && !First->OperatorDelete) {
+    First->OperatorDelete = OD;
+    First->OperatorDeleteThisArg = ThisArg;
     if (auto *L = getASTMutationListener())
-      L->ResolvedOperatorDelete(cast<CXXDestructorDecl>(getCanonicalDecl()), OD,
-                                ThisArg);
+      L->ResolvedOperatorDelete(First, OD, ThisArg);
   }
 }
 
@@ -3130,63 +3127,14 @@ void CXXDestructorDecl::setOperatorGlobalDelete(FunctionDecl *OD) {
   assert(!OD ||
          (OD->getDeclName().getCXXOverloadedOperator() == OO_Delete &&
           OD->getDeclContext()->getRedeclContext()->isTranslationUnit()));
-  if (OD && !getASTContext().dtorHasOperatorDelete(
-                this, ASTContext::OperatorDeleteKind::GlobalRegular)) {
-    getASTContext().addOperatorDeleteForVDtor(
-        this, OD, ASTContext::OperatorDeleteKind::GlobalRegular);
+  auto *Canonical = cast<CXXDestructorDecl>(getCanonicalDecl());
+  if (!Canonical->OperatorGlobalDelete) {
+    Canonical->OperatorGlobalDelete = OD;
     if (auto *L = getASTMutationListener())
-      L->ResolvedOperatorGlobDelete(cast<CXXDestructorDecl>(getCanonicalDecl()),
-                                    OD);
+      L->ResolvedOperatorGlobDelete(Canonical, OD);
   }
 }
 
-void CXXDestructorDecl::setOperatorArrayDelete(FunctionDecl *OD) {
-  assert(!OD ||
-         (OD->getDeclName().getCXXOverloadedOperator() == OO_Array_Delete));
-  if (OD && !getASTContext().dtorHasOperatorDelete(
-                this, ASTContext::OperatorDeleteKind::Array)) {
-    getASTContext().addOperatorDeleteForVDtor(
-        this, OD, ASTContext::OperatorDeleteKind::Array);
-    if (auto *L = getASTMutationListener())
-      L->ResolvedOperatorArrayDelete(
-          cast<CXXDestructorDecl>(getCanonicalDecl()), OD);
-  }
-}
-
-void CXXDestructorDecl::setGlobalOperatorArrayDelete(FunctionDecl *OD) {
-  assert(!OD ||
-         (OD->getDeclName().getCXXOverloadedOperator() == OO_Array_Delete &&
-          OD->getDeclContext()->getRedeclContext()->isTranslationUnit()));
-  if (OD && !getASTContext().dtorHasOperatorDelete(
-                this, ASTContext::OperatorDeleteKind::ArrayGlobal)) {
-    getASTContext().addOperatorDeleteForVDtor(
-        this, OD, ASTContext::OperatorDeleteKind::ArrayGlobal);
-    if (auto *L = getASTMutationListener())
-      L->ResolvedOperatorGlobArrayDelete(
-          cast<CXXDestructorDecl>(getCanonicalDecl()), OD);
-  }
-}
-
-const FunctionDecl *CXXDestructorDecl::getOperatorDelete() const {
-  return getASTContext().getOperatorDeleteForVDtor(
-      this, ASTContext::OperatorDeleteKind::Regular);
-}
-
-const FunctionDecl *CXXDestructorDecl::getOperatorGlobalDelete() const {
-  return getASTContext().getOperatorDeleteForVDtor(
-      this, ASTContext::OperatorDeleteKind::GlobalRegular);
-}
-
-const FunctionDecl *CXXDestructorDecl::getArrayOperatorDelete() const {
-  return getASTContext().getOperatorDeleteForVDtor(
-      this, ASTContext::OperatorDeleteKind::Array);
-}
-
-const FunctionDecl *CXXDestructorDecl::getGlobalArrayOperatorDelete() const {
-  return getASTContext().getOperatorDeleteForVDtor(
-      this, ASTContext::OperatorDeleteKind::ArrayGlobal);
-}
-
 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
@@ -3198,8 +3146,7 @@ bool CXXDestructorDecl::isCalledByDelete(const FunctionDecl *OpDel) const {
   // delete operator, as that destructor is never called, unless the
   // destructor is virtual (see [expr.delete]p8.1) because then the
   // selected operator depends on the dynamic type of the pointer.
-  const FunctionDecl *SelectedOperatorDelete =
-      OpDel ? OpDel : getOperatorDelete();
+  const FunctionDecl *SelectedOperatorDelete = OpDel ? OpDel : OperatorDelete;
   if (!SelectedOperatorDelete)
     return true;
 
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 1d914fa876759..340bb4b2ed6a3 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -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;
 
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index a5bcf5c97e837..5572e0a7ae59c 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -6040,8 +6040,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");
   }
 }
 
diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp
index 551aa7bf3321c..f1baf9f49384b 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -1492,9 +1492,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");
   case Dtor_Unified:
@@ -2914,12 +2913,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. ...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Nov 21, 2025

@llvm/pr-subscribers-lldb

Author: Mariya Podchishchaeva (Fznamznon)

Changes

This reverts 4d10c11 and e6b9805 because it broke Chromium builds with /Zc:DllexportInlines- .


Patch is 122.64 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/169063.diff

59 Files Affected:

  • (modified) clang/docs/ReleaseNotes.rst (-8)
  • (modified) clang/include/clang/AST/ASTContext.h (-22)
  • (modified) clang/include/clang/AST/ASTMutationListener.h (-9)
  • (modified) clang/include/clang/AST/DeclCXX.h (+10-6)
  • (modified) clang/include/clang/AST/VTableBuilder.h (+2-4)
  • (modified) clang/include/clang/Basic/ABI.h (+5-6)
  • (modified) clang/include/clang/Basic/TargetInfo.h (-5)
  • (modified) clang/include/clang/Sema/Sema.h (+1-2)
  • (modified) clang/include/clang/Serialization/ASTWriter.h (-4)
  • (modified) clang/lib/AST/ASTContext.cpp (-65)
  • (modified) clang/lib/AST/DeclCXX.cpp (+10-63)
  • (modified) clang/lib/AST/Expr.cpp (-3)
  • (modified) clang/lib/AST/ItaniumMangle.cpp (-2)
  • (modified) clang/lib/AST/MicrosoftMangle.cpp (+9-13)
  • (modified) clang/lib/AST/VTableBuilder.cpp (+4-14)
  • (modified) clang/lib/Basic/TargetInfo.cpp (-7)
  • (modified) clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp (-7)
  • (modified) clang/lib/CIR/CodeGen/CIRGenFunction.cpp (+1-4)
  • (modified) clang/lib/CodeGen/CGCXX.cpp (+1-36)
  • (modified) clang/lib/CodeGen/CGCXXABI.cpp (-14)
  • (modified) clang/lib/CodeGen/CGCXXABI.h (-6)
  • (modified) clang/lib/CodeGen/CGClass.cpp (+1-94)
  • (modified) clang/lib/CodeGen/CGDebugInfo.cpp (+1-7)
  • (modified) clang/lib/CodeGen/CGExprCXX.cpp (+4-48)
  • (modified) clang/lib/CodeGen/CGVTables.cpp (+1-3)
  • (modified) clang/lib/CodeGen/CodeGenModule.cpp (-50)
  • (modified) clang/lib/CodeGen/CodeGenModule.h (-6)
  • (modified) clang/lib/CodeGen/ItaniumCXXABI.cpp (+1-4)
  • (modified) clang/lib/CodeGen/MicrosoftCXXABI.cpp (+14-56)
  • (modified) clang/lib/Sema/SemaDeclCXX.cpp (+2-28)
  • (modified) clang/lib/Sema/SemaExprCXX.cpp (+6-7)
  • (modified) clang/lib/Serialization/ASTCommon.h (+1-3)
  • (modified) clang/lib/Serialization/ASTReaderDecl.cpp (+13-53)
  • (modified) clang/lib/Serialization/ASTWriter.cpp (-36)
  • (modified) clang/lib/Serialization/ASTWriterDecl.cpp (-2)
  • (modified) clang/test/CodeGenCXX/dllexport.cpp (+2-3)
  • (modified) clang/test/CodeGenCXX/microsoft-abi-extern-template.cpp (+1-1)
  • (modified) clang/test/CodeGenCXX/microsoft-abi-structors.cpp (+1-1)
  • (modified) clang/test/CodeGenCXX/microsoft-abi-thunks.cpp (+2-1)
  • (modified) clang/test/CodeGenCXX/microsoft-abi-vftables.cpp (+10-10)
  • (modified) clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp (+8-9)
  • (modified) clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-vdtors.cpp (+9-9)
  • (modified) clang/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp (+1-1)
  • (modified) clang/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp (+10-10)
  • (modified) clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp (+15-15)
  • (modified) clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp (+9-9)
  • (modified) clang/test/CodeGenCXX/microsoft-no-rtti-data.cpp (+1-1)
  • (removed) clang/test/CodeGenCXX/microsoft-vector-deleting-dtors.cpp (-336)
  • (modified) clang/test/CodeGenCXX/vtable-consteval.cpp (+2-2)
  • (modified) clang/test/DebugInfo/CXX/windows-dtor.cpp (+1-1)
  • (removed) clang/test/Modules/Inputs/msvc-vector-deleting-dtors/module.modulemap (-1)
  • (removed) clang/test/Modules/Inputs/msvc-vector-deleting-dtors/msvc-vector-deleting-dtors.h (-16)
  • (removed) clang/test/Modules/msvc-vector-deleting-destructors.cpp (-30)
  • (modified) clang/test/Modules/vtable-windows.cppm (+1-1)
  • (removed) clang/test/PCH/Inputs/msvc-vector-deleting-dtors.h (-16)
  • (removed) clang/test/PCH/msvc-vector-deleting-destructors.cpp (-34)
  • (modified) clang/test/Profile/cxx-abc-deleting-dtor.cpp (+5-4)
  • (removed) clang/test/SemaCXX/gh134265.cpp (-62)
  • (modified) lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (-1)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7e440c35a5b98..e8bd591a44d18 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -84,12 +84,6 @@ Potentially Breaking Changes
 - Downstream projects that previously linked only against ``clangDriver`` may
   now (also) need to link against the new ``clangOptions`` library, since
   options-related code has been moved out of the Driver into a separate library.
-- Clang now supports MSVC vector deleting destructors when targeting Windows.
-  This means that vtables of classes with virtual destructors will contain a
-  pointer to vector deleting destructor (instead of scalar deleting destructor)
-  which in fact is a different symbol with different name and linkage. This
-  may cause runtime failures if two binaries using the same class defining a
-  virtual destructor are compiled with different versions of clang.
 
 C/C++ Language Potentially Breaking Changes
 -------------------------------------------
@@ -621,8 +615,6 @@ Windows Support
 - clang-cl now supports /arch:AVX10.1 and /arch:AVX10.2.
 - clang-cl now supports /vlen, /vlen=256 and /vlen=512.
 
-- Clang now supports MSVC vector deleting destructors (GH19772).
-
 LoongArch Support
 ^^^^^^^^^^^^^^^^^
 - Enable linker relaxation by default for loongarch64.
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 6e9e737dcae4f..33aa2d343aa7a 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -370,18 +370,6 @@ class ASTContext : public RefCountedBase<ASTContext> {
   mutable llvm::DenseSet<const FunctionDecl *> DestroyingOperatorDeletes;
   mutable llvm::DenseSet<const FunctionDecl *> TypeAwareOperatorNewAndDeletes;
 
-  /// Global and array operators delete are only required for MSVC deleting
-  /// destructors support. Store them here to avoid keeping 4 pointers that are
-  /// not always used in each redeclaration of the destructor.
-  mutable llvm::DenseMap<const CXXDestructorDecl *, FunctionDecl *>
-      OperatorDeletesForVirtualDtor;
-  mutable llvm::DenseMap<const CXXDestructorDecl *, FunctionDecl *>
-      GlobalOperatorDeletesForVirtualDtor;
-  mutable llvm::DenseMap<const CXXDestructorDecl *, FunctionDecl *>
-      ArrayOperatorDeletesForVirtualDtor;
-  mutable llvm::DenseMap<const CXXDestructorDecl *, FunctionDecl *>
-      GlobalArrayOperatorDeletesForVirtualDtor;
-
   /// The next string literal "version" to allocate during constant evaluation.
   /// This is used to distinguish between repeated evaluations of the same
   /// string literal.
@@ -3485,16 +3473,6 @@ class ASTContext : public RefCountedBase<ASTContext> {
                                          bool IsTypeAware);
   bool isTypeAwareOperatorNewOrDelete(const FunctionDecl *FD) const;
 
-  enum OperatorDeleteKind { Regular, GlobalRegular, Array, ArrayGlobal };
-
-  void addOperatorDeleteForVDtor(const CXXDestructorDecl *Dtor,
-                                 FunctionDecl *OperatorDelete,
-                                 OperatorDeleteKind K) const;
-  FunctionDecl *getOperatorDeleteForVDtor(const CXXDestructorDecl *Dtor,
-                                          OperatorDeleteKind K) const;
-  bool dtorHasOperatorDelete(const CXXDestructorDecl *Dtor,
-                             OperatorDeleteKind K) const;
-
   /// Retrieve the context for computing mangling numbers in the given
   /// DeclContext.
   MangleNumberingContext &getManglingNumberContext(const DeclContext *DC);
diff --git a/clang/include/clang/AST/ASTMutationListener.h b/clang/include/clang/AST/ASTMutationListener.h
index c8448a25c23a4..352af42391782 100644
--- a/clang/include/clang/AST/ASTMutationListener.h
+++ b/clang/include/clang/AST/ASTMutationListener.h
@@ -90,15 +90,6 @@ class ASTMutationListener {
   virtual void ResolvedOperatorGlobDelete(const CXXDestructorDecl *DD,
                                           const FunctionDecl *GlobDelete) {}
 
-  /// A virtual destructor's operator array delete has been resolved.
-  virtual void ResolvedOperatorArrayDelete(const CXXDestructorDecl *DD,
-                                           const FunctionDecl *ArrayDelete) {}
-
-  /// A virtual destructor's operator global array delete has been resolved.
-  virtual void
-  ResolvedOperatorGlobArrayDelete(const CXXDestructorDecl *DD,
-                                  const FunctionDecl *GlobArrayDelete) {}
-
   /// An implicit member got a definition.
   virtual void CompletedImplicitDefinition(const FunctionDecl *D) {}
 
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h
index 5c4ad3c45da19..dfa3befb27dd0 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -2872,6 +2872,8 @@ class CXXDestructorDecl : public CXXMethodDecl {
 
   // FIXME: Don't allocate storage for these except in the first declaration
   // of a virtual destructor.
+  FunctionDecl *OperatorDelete = nullptr;
+  FunctionDecl *OperatorGlobalDelete = nullptr;
   Expr *OperatorDeleteThisArg = nullptr;
 
   CXXDestructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc,
@@ -2898,12 +2900,14 @@ class CXXDestructorDecl : public CXXMethodDecl {
 
   void setOperatorDelete(FunctionDecl *OD, Expr *ThisArg);
   void setOperatorGlobalDelete(FunctionDecl *OD);
-  void setOperatorArrayDelete(FunctionDecl *OD);
-  void setGlobalOperatorArrayDelete(FunctionDecl *OD);
-  const FunctionDecl *getOperatorDelete() const;
-  const FunctionDecl *getOperatorGlobalDelete() const;
-  const FunctionDecl *getArrayOperatorDelete() const;
-  const FunctionDecl *getGlobalArrayOperatorDelete() const;
+
+  const FunctionDecl *getOperatorDelete() const {
+    return getCanonicalDecl()->OperatorDelete;
+  }
+
+  const FunctionDecl *getOperatorGlobalDelete() const {
+    return getCanonicalDecl()->OperatorGlobalDelete;
+  }
 
   Expr *getOperatorDeleteThisArg() const {
     return getCanonicalDecl()->OperatorDeleteThisArg;
diff --git a/clang/include/clang/AST/VTableBuilder.h b/clang/include/clang/AST/VTableBuilder.h
index e1efe8cddcc5e..a5de41dbc22f1 100644
--- a/clang/include/clang/AST/VTableBuilder.h
+++ b/clang/include/clang/AST/VTableBuilder.h
@@ -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");
 
@@ -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:
diff --git a/clang/include/clang/Basic/ABI.h b/clang/include/clang/Basic/ABI.h
index be3edccbf50b2..8279529c316cf 100644
--- a/clang/include/clang/Basic/ABI.h
+++ b/clang/include/clang/Basic/ABI.h
@@ -32,12 +32,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_Unified,        ///< GCC-style unified dtor
-  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
+  Dtor_Unified,  ///< GCC-style unified dtor
 };
 
 } // end namespace clang
diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h
index 1c16f9f79ae68..39af84c8d0872 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -1796,11 +1796,6 @@ class TargetInfo : public TransferrableTargetInfo,
   /// destructor body.
   virtual bool callGlobalDeleteInDeletingDtor(const LangOptions &) const;
 
-  /// Controls whether to emit MSVC vector deleting destructors. The support for
-  /// vector deleting affects vtable layout and therefore is an ABI breaking
-  /// change. The support was only implemented at Clang 22 timeframe.
-  virtual bool emitVectorDeletingDtors(const LangOptions &) const;
-
   /// Controls if __builtin_longjmp / __builtin_setjmp can be lowered to
   /// llvm.eh.sjlj.longjmp / llvm.eh.sjlj.setjmp.
   virtual bool hasSjLjLowering() const {
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index cbfcc9bc0ea99..ae500139ee6f7 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -8581,8 +8581,7 @@ class Sema final : public SemaBase {
   FunctionDecl *FindDeallocationFunctionForDestructor(SourceLocation StartLoc,
                                                       CXXRecordDecl *RD,
                                                       bool Diagnose,
-                                                      bool LookForGlobal,
-                                                      DeclarationName Name);
+                                                      bool LookForGlobal);
 
   /// ActOnCXXDelete - Parsed a C++ 'delete' expression (C++ 5.3.5), as in:
   /// @code ::delete ptr; @endcode
diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h
index dbbfc29058f43..c77c98dffc39f 100644
--- a/clang/include/clang/Serialization/ASTWriter.h
+++ b/clang/include/clang/Serialization/ASTWriter.h
@@ -955,10 +955,6 @@ class ASTWriter : public ASTDeserializationListener,
                               Expr *ThisArg) override;
   void ResolvedOperatorGlobDelete(const CXXDestructorDecl *DD,
                                   const FunctionDecl *Delete) override;
-  void ResolvedOperatorArrayDelete(const CXXDestructorDecl *DD,
-                                   const FunctionDecl *Delete) override;
-  void ResolvedOperatorGlobArrayDelete(const CXXDestructorDecl *DD,
-                                       const FunctionDecl *Delete) override;
   void CompletedImplicitDefinition(const FunctionDecl *D) override;
   void InstantiationRequested(const ValueDecl *D) override;
   void VariableDefinitionInstantiated(const VarDecl *D) override;
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index b929b0fc1aa8e..b359fc8350375 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -13337,71 +13337,6 @@ bool ASTContext::isTypeAwareOperatorNewOrDelete(const FunctionDecl *FD) const {
   return TypeAwareOperatorNewAndDeletes.contains(FD->getCanonicalDecl());
 }
 
-void ASTContext::addOperatorDeleteForVDtor(const CXXDestructorDecl *Dtor,
-                                           FunctionDecl *OperatorDelete,
-                                           OperatorDeleteKind K) const {
-  switch (K) {
-  case OperatorDeleteKind::Regular:
-    OperatorDeletesForVirtualDtor[Dtor->getCanonicalDecl()] = OperatorDelete;
-    break;
-  case OperatorDeleteKind::GlobalRegular:
-    GlobalOperatorDeletesForVirtualDtor[Dtor->getCanonicalDecl()] =
-        OperatorDelete;
-    break;
-  case OperatorDeleteKind::Array:
-    ArrayOperatorDeletesForVirtualDtor[Dtor->getCanonicalDecl()] =
-        OperatorDelete;
-    break;
-  case OperatorDeleteKind::ArrayGlobal:
-    GlobalArrayOperatorDeletesForVirtualDtor[Dtor->getCanonicalDecl()] =
-        OperatorDelete;
-    break;
-  }
-}
-
-bool ASTContext::dtorHasOperatorDelete(const CXXDestructorDecl *Dtor,
-                                       OperatorDeleteKind K) const {
-  switch (K) {
-  case OperatorDeleteKind::Regular:
-    return OperatorDeletesForVirtualDtor.contains(Dtor->getCanonicalDecl());
-  case OperatorDeleteKind::GlobalRegular:
-    return GlobalOperatorDeletesForVirtualDtor.contains(
-        Dtor->getCanonicalDecl());
-  case OperatorDeleteKind::Array:
-    return ArrayOperatorDeletesForVirtualDtor.contains(
-        Dtor->getCanonicalDecl());
-  case OperatorDeleteKind::ArrayGlobal:
-    return GlobalArrayOperatorDeletesForVirtualDtor.contains(
-        Dtor->getCanonicalDecl());
-  }
-  return false;
-}
-
-FunctionDecl *
-ASTContext::getOperatorDeleteForVDtor(const CXXDestructorDecl *Dtor,
-                                      OperatorDeleteKind K) const {
-  const CXXDestructorDecl *Canon = Dtor->getCanonicalDecl();
-  switch (K) {
-  case OperatorDeleteKind::Regular:
-    if (OperatorDeletesForVirtualDtor.contains(Canon))
-      return OperatorDeletesForVirtualDtor[Canon];
-    return nullptr;
-  case OperatorDeleteKind::GlobalRegular:
-    if (GlobalOperatorDeletesForVirtualDtor.contains(Canon))
-      return GlobalOperatorDeletesForVirtualDtor[Canon];
-    return nullptr;
-  case OperatorDeleteKind::Array:
-    if (ArrayOperatorDeletesForVirtualDtor.contains(Canon))
-      return ArrayOperatorDeletesForVirtualDtor[Canon];
-    return nullptr;
-  case OperatorDeleteKind::ArrayGlobal:
-    if (GlobalArrayOperatorDeletesForVirtualDtor.contains(Canon))
-      return GlobalArrayOperatorDeletesForVirtualDtor[Canon];
-    return nullptr;
-  }
-  return nullptr;
-}
-
 MangleNumberingContext &
 ASTContext::getManglingNumberContext(const DeclContext *DC) {
   assert(LangOpts.CPlusPlus);  // We don't need mangling numbers for plain C.
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index c16b1bb7a3453..24e4f189cbe4a 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -3110,15 +3110,12 @@ CXXDestructorDecl *CXXDestructorDecl::Create(
 }
 
 void CXXDestructorDecl::setOperatorDelete(FunctionDecl *OD, Expr *ThisArg) {
-  assert(!OD || (OD->getDeclName().getCXXOverloadedOperator() == OO_Delete));
-  if (OD && !getASTContext().dtorHasOperatorDelete(
-                this, ASTContext::OperatorDeleteKind::Regular)) {
-    getASTContext().addOperatorDeleteForVDtor(
-        this, OD, ASTContext::OperatorDeleteKind::Regular);
-    getCanonicalDecl()->OperatorDeleteThisArg = ThisArg;
+  auto *First = cast<CXXDestructorDecl>(getFirstDecl());
+  if (OD && !First->OperatorDelete) {
+    First->OperatorDelete = OD;
+    First->OperatorDeleteThisArg = ThisArg;
     if (auto *L = getASTMutationListener())
-      L->ResolvedOperatorDelete(cast<CXXDestructorDecl>(getCanonicalDecl()), OD,
-                                ThisArg);
+      L->ResolvedOperatorDelete(First, OD, ThisArg);
   }
 }
 
@@ -3130,63 +3127,14 @@ void CXXDestructorDecl::setOperatorGlobalDelete(FunctionDecl *OD) {
   assert(!OD ||
          (OD->getDeclName().getCXXOverloadedOperator() == OO_Delete &&
           OD->getDeclContext()->getRedeclContext()->isTranslationUnit()));
-  if (OD && !getASTContext().dtorHasOperatorDelete(
-                this, ASTContext::OperatorDeleteKind::GlobalRegular)) {
-    getASTContext().addOperatorDeleteForVDtor(
-        this, OD, ASTContext::OperatorDeleteKind::GlobalRegular);
+  auto *Canonical = cast<CXXDestructorDecl>(getCanonicalDecl());
+  if (!Canonical->OperatorGlobalDelete) {
+    Canonical->OperatorGlobalDelete = OD;
     if (auto *L = getASTMutationListener())
-      L->ResolvedOperatorGlobDelete(cast<CXXDestructorDecl>(getCanonicalDecl()),
-                                    OD);
+      L->ResolvedOperatorGlobDelete(Canonical, OD);
   }
 }
 
-void CXXDestructorDecl::setOperatorArrayDelete(FunctionDecl *OD) {
-  assert(!OD ||
-         (OD->getDeclName().getCXXOverloadedOperator() == OO_Array_Delete));
-  if (OD && !getASTContext().dtorHasOperatorDelete(
-                this, ASTContext::OperatorDeleteKind::Array)) {
-    getASTContext().addOperatorDeleteForVDtor(
-        this, OD, ASTContext::OperatorDeleteKind::Array);
-    if (auto *L = getASTMutationListener())
-      L->ResolvedOperatorArrayDelete(
-          cast<CXXDestructorDecl>(getCanonicalDecl()), OD);
-  }
-}
-
-void CXXDestructorDecl::setGlobalOperatorArrayDelete(FunctionDecl *OD) {
-  assert(!OD ||
-         (OD->getDeclName().getCXXOverloadedOperator() == OO_Array_Delete &&
-          OD->getDeclContext()->getRedeclContext()->isTranslationUnit()));
-  if (OD && !getASTContext().dtorHasOperatorDelete(
-                this, ASTContext::OperatorDeleteKind::ArrayGlobal)) {
-    getASTContext().addOperatorDeleteForVDtor(
-        this, OD, ASTContext::OperatorDeleteKind::ArrayGlobal);
-    if (auto *L = getASTMutationListener())
-      L->ResolvedOperatorGlobArrayDelete(
-          cast<CXXDestructorDecl>(getCanonicalDecl()), OD);
-  }
-}
-
-const FunctionDecl *CXXDestructorDecl::getOperatorDelete() const {
-  return getASTContext().getOperatorDeleteForVDtor(
-      this, ASTContext::OperatorDeleteKind::Regular);
-}
-
-const FunctionDecl *CXXDestructorDecl::getOperatorGlobalDelete() const {
-  return getASTContext().getOperatorDeleteForVDtor(
-      this, ASTContext::OperatorDeleteKind::GlobalRegular);
-}
-
-const FunctionDecl *CXXDestructorDecl::getArrayOperatorDelete() const {
-  return getASTContext().getOperatorDeleteForVDtor(
-      this, ASTContext::OperatorDeleteKind::Array);
-}
-
-const FunctionDecl *CXXDestructorDecl::getGlobalArrayOperatorDelete() const {
-  return getASTContext().getOperatorDeleteForVDtor(
-      this, ASTContext::OperatorDeleteKind::ArrayGlobal);
-}
-
 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
@@ -3198,8 +3146,7 @@ bool CXXDestructorDecl::isCalledByDelete(const FunctionDecl *OpDel) const {
   // delete operator, as that destructor is never called, unless the
   // destructor is virtual (see [expr.delete]p8.1) because then the
   // selected operator depends on the dynamic type of the pointer.
-  const FunctionDecl *SelectedOperatorDelete =
-      OpDel ? OpDel : getOperatorDelete();
+  const FunctionDecl *SelectedOperatorDelete = OpDel ? OpDel : OperatorDelete;
   if (!SelectedOperatorDelete)
     return true;
 
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 1d914fa876759..340bb4b2ed6a3 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -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;
 
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index a5bcf5c97e837..5572e0a7ae59c 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -6040,8 +6040,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");
   }
 }
 
diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp
index 551aa7bf3321c..f1baf9f49384b 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -1492,9 +1492,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");
   case Dtor_Unified:
@@ -2914,12 +2913,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. ...
[truncated]

@github-actions
Copy link

github-actions bot commented Nov 21, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@github-actions
Copy link

github-actions bot commented Nov 21, 2025

🐧 Linux x64 Test Results

  • 91849 tests passed
  • 2067 tests skipped
  • 2 tests failed

Failed Tests

(click on a test name to see its output)

ORC-x86_64-linux

ORC-x86_64-linux.TestCases/Linux/x86-64/lljit-ehframe.cpp (Likely Already Failing) This test is already failing at the base commit.
Exit Code: -9
Timeout: Reached timeout of 1200 seconds

Command Output (stderr):
--
/home/gha/actions-runner/_work/llvm-project/llvm-project/build/./bin/clang  --driver-mode=g++  -m64  -fPIC -emit-llvm -c -o /home/gha/actions-runner/_work/llvm-project/llvm-project/build/runtimes/runtimes-bins/compiler-rt/test/orc/X86_64LinuxConfig/TestCases/Linux/x86-64/Output/lljit-ehframe.cpp.tmp /home/gha/actions-runner/_work/llvm-project/llvm-project/compiler-rt/test/orc/TestCases/Linux/x86-64/lljit-ehframe.cpp # RUN: at line 1
+ /home/gha/actions-runner/_work/llvm-project/llvm-project/build/./bin/clang --driver-mode=g++ -m64 -fPIC -emit-llvm -c -o /home/gha/actions-runner/_work/llvm-project/llvm-project/build/runtimes/runtimes-bins/compiler-rt/test/orc/X86_64LinuxConfig/TestCases/Linux/x86-64/Output/lljit-ehframe.cpp.tmp /home/gha/actions-runner/_work/llvm-project/llvm-project/compiler-rt/test/orc/TestCases/Linux/x86-64/lljit-ehframe.cpp
/home/gha/actions-runner/_work/llvm-project/llvm-project/build/./bin/lli -jit-kind=orc -jit-linker=jitlink -orc-runtime=/home/gha/actions-runner/_work/llvm-project/llvm-project/build/./lib/../lib/clang/22/lib/x86_64-unknown-linux-gnu/liborc_rt.a -relocation-model=pic /home/gha/actions-runner/_work/llvm-project/llvm-project/build/runtimes/runtimes-bins/compiler-rt/test/orc/X86_64LinuxConfig/TestCases/Linux/x86-64/Output/lljit-ehframe.cpp.tmp | FileCheck /home/gha/actions-runner/_work/llvm-project/llvm-project/compiler-rt/test/orc/TestCases/Linux/x86-64/lljit-ehframe.cpp # RUN: at line 2
+ /home/gha/actions-runner/_work/llvm-project/llvm-project/build/./bin/lli -jit-kind=orc -jit-linker=jitlink -orc-runtime=/home/gha/actions-runner/_work/llvm-project/llvm-project/build/./lib/../lib/clang/22/lib/x86_64-unknown-linux-gnu/liborc_rt.a -relocation-model=pic /home/gha/actions-runner/_work/llvm-project/llvm-project/build/runtimes/runtimes-bins/compiler-rt/test/orc/X86_64LinuxConfig/TestCases/Linux/x86-64/Output/lljit-ehframe.cpp.tmp
+ FileCheck /home/gha/actions-runner/_work/llvm-project/llvm-project/compiler-rt/test/orc/TestCases/Linux/x86-64/lljit-ehframe.cpp
JIT session error: Invalid arch in ELF object file: 0

--

ORC-x86_64-linux.TestCases/Linux/x86-64/lljit-initialize-deinitialize.ll (Likely Already Failing) This test is already failing at the base commit.
Exit Code: -9
Timeout: Reached timeout of 1200 seconds

Command Output (stderr):
--
/home/gha/actions-runner/_work/llvm-project/llvm-project/build/./bin/lli -jit-kind=orc -jit-linker=jitlink -orc-runtime=/home/gha/actions-runner/_work/llvm-project/llvm-project/build/./lib/../lib/clang/22/lib/x86_64-unknown-linux-gnu/liborc_rt.a /home/gha/actions-runner/_work/llvm-project/llvm-project/compiler-rt/test/orc/TestCases/Linux/x86-64/lljit-initialize-deinitialize.ll | FileCheck /home/gha/actions-runner/_work/llvm-project/llvm-project/compiler-rt/test/orc/TestCases/Linux/x86-64/lljit-initialize-deinitialize.ll # RUN: at line 1
+ /home/gha/actions-runner/_work/llvm-project/llvm-project/build/./bin/lli -jit-kind=orc -jit-linker=jitlink -orc-runtime=/home/gha/actions-runner/_work/llvm-project/llvm-project/build/./lib/../lib/clang/22/lib/x86_64-unknown-linux-gnu/liborc_rt.a /home/gha/actions-runner/_work/llvm-project/llvm-project/compiler-rt/test/orc/TestCases/Linux/x86-64/lljit-initialize-deinitialize.ll
+ FileCheck /home/gha/actions-runner/_work/llvm-project/llvm-project/compiler-rt/test/orc/TestCases/Linux/x86-64/lljit-initialize-deinitialize.ll
JIT session error: Invalid arch in ELF object file: 0

--

If these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the infrastructure label.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang:codegen IR generation bugs: mangling, exceptions, etc. clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:modules C++20 modules and Clang Header Modules ClangIR Anything related to the ClangIR project debuginfo lldb

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants