[llvm-branch-commits] [clang] e50b687 - Revert "[clang][win] Define vector deleting dtor body for declared-only dtor …"

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Mar 24 03:23:32 PDT 2026


Author: Mariya Podchishchaeva
Date: 2026-03-24T11:23:27+01:00
New Revision: e50b687b1517acbe07cca12e5a330a7e978f4afb

URL: https://github.com/llvm/llvm-project/commit/e50b687b1517acbe07cca12e5a330a7e978f4afb
DIFF: https://github.com/llvm/llvm-project/commit/e50b687b1517acbe07cca12e5a330a7e978f4afb.diff

LOG: Revert "[clang][win] Define vector deleting dtor body for declared-only dtor …"

This reverts commit 9b5084f894cb941d76b4638c1305bf3f869c78d4.

Added: 
    

Modified: 
    clang/include/clang/AST/ASTContext.h
    clang/lib/AST/ASTContext.cpp
    clang/lib/CodeGen/CGExprCXX.cpp
    clang/lib/CodeGen/CodeGenModule.cpp
    clang/lib/CodeGen/CodeGenModule.h
    clang/lib/CodeGen/MicrosoftCXXABI.cpp
    clang/lib/Sema/SemaDeclCXX.cpp
    clang/lib/Sema/SemaExprCXX.cpp
    clang/test/SemaCXX/gh134265.cpp

Removed: 
    clang/test/CodeGenCXX/microsoft-vector-deleting-dtors-new-array.cpp


################################################################################
diff  --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 40091acd878fd..560248ea2224e 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -389,9 +389,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
   mutable llvm::DenseMap<const CXXDestructorDecl *, FunctionDecl *>
       GlobalArrayOperatorDeletesForVirtualDtor;
 
-  /// To remember for which types we met new[] call, these potentially require a
-  /// vector deleting dtor.
-  llvm::DenseSet<const CXXRecordDecl *> MaybeRequireVectorDeletingDtor;
+  /// To remember which types did require a vector deleting dtor.
+  llvm::DenseSet<const CXXRecordDecl *> RequireVectorDeletingDtor;
 
   /// The next string literal "version" to allocate during constant evaluation.
   /// This is used to distinguish between repeated evaluations of the same
@@ -3549,8 +3548,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
                                           OperatorDeleteKind K) const;
   bool dtorHasOperatorDelete(const CXXDestructorDecl *Dtor,
                              OperatorDeleteKind K) const;
-  void setClassMaybeNeedsVectorDeletingDestructor(const CXXRecordDecl *RD);
-  bool classMaybeNeedsVectorDeletingDestructor(const CXXRecordDecl *RD);
+  void setClassNeedsVectorDeletingDestructor(const CXXRecordDecl *RD);
+  bool classNeedsVectorDeletingDestructor(const CXXRecordDecl *RD);
 
   /// Retrieve the context for computing mangling numbers in the given
   /// DeclContext.

diff  --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index a8cfdca1cb96d..1e79ee4bc5bcb 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -13626,20 +13626,24 @@ ASTContext::getOperatorDeleteForVDtor(const CXXDestructorDecl *Dtor,
   return nullptr;
 }
 
-bool ASTContext::classMaybeNeedsVectorDeletingDestructor(
-    const CXXRecordDecl *RD) {
+bool ASTContext::classNeedsVectorDeletingDestructor(const CXXRecordDecl *RD) {
   if (!getTargetInfo().emitVectorDeletingDtors(getLangOpts()))
     return false;
+  CXXDestructorDecl *Dtor = RD->getDestructor();
+  // The compiler can't know if new[]/delete[] will be used outside of the DLL,
+  // so just force vector deleting destructor emission if dllexport is present.
+  // This matches MSVC behavior.
+  if (Dtor && Dtor->isVirtual() && Dtor->hasAttr<DLLExportAttr>())
+    return true;
 
-  return MaybeRequireVectorDeletingDtor.count(RD);
+  return RequireVectorDeletingDtor.count(RD);
 }
 
-void ASTContext::setClassMaybeNeedsVectorDeletingDestructor(
+void ASTContext::setClassNeedsVectorDeletingDestructor(
     const CXXRecordDecl *RD) {
   if (!getTargetInfo().emitVectorDeletingDtors(getLangOpts()))
     return;
-
-  MaybeRequireVectorDeletingDtor.insert(RD);
+  RequireVectorDeletingDtor.insert(RD);
 }
 
 MangleNumberingContext &

diff  --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index 82300c3ede183..93ac0305df38f 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/lib/CodeGen/CGExprCXX.cpp
@@ -1201,12 +1201,6 @@ void CodeGenFunction::EmitNewArrayInitializer(
     EmitCXXAggrConstructorCall(Ctor, NumElements, CurPtr, CCE,
                                /*NewPointerIsChecked*/ true,
                                CCE->requiresZeroInitialization());
-    if (getContext().getTargetInfo().emitVectorDeletingDtors(
-            getContext().getLangOpts())) {
-      CXXDestructorDecl *Dtor = Ctor->getParent()->getDestructor();
-      if (Dtor && Dtor->isVirtual())
-        CGM.requireVectorDestructorDefinition(Ctor->getParent());
-    }
     return;
   }
 

diff  --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index daaa846bf42bc..3658d84f55256 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -8561,55 +8561,3 @@ std::string CodeGenModule::getPFPFieldName(const FieldDecl *FD) {
   Out << "." << FD->getName();
   return OutName;
 }
-
-bool CodeGenModule::classNeedsVectorDestructor(const CXXRecordDecl *RD) {
-  if (!Context.getTargetInfo().emitVectorDeletingDtors(Context.getLangOpts()))
-    return false;
-  CXXDestructorDecl *Dtor = RD->getDestructor();
-  // The compiler can't know if new[]/delete[] will be used outside of the DLL,
-  // so just force vector deleting destructor emission if dllexport is present.
-  // This matches MSVC behavior.
-  if (Dtor && Dtor->isVirtual() && Dtor->hasAttr<DLLExportAttr>())
-    return true;
-
-  return RequireVectorDeletingDtor.count(RD);
-}
-
-void CodeGenModule::requireVectorDestructorDefinition(const CXXRecordDecl *RD) {
-  if (!Context.getTargetInfo().emitVectorDeletingDtors(Context.getLangOpts()))
-    return;
-  RequireVectorDeletingDtor.insert(RD);
-
-  // To reduce code size in general case we lazily emit scalar deleting
-  // destructor definition and an alias from vector deleting destructor to
-  // scalar deleting destructor. It may happen that we first emitted the scalar
-  // deleting destructor definition and the alias and then discovered that the
-  // definition of the vector deleting destructor is required. Then we need to
-  // remove the alias and the scalar deleting destructor and queue vector
-  // deleting destructor body for emission. Check if that is the case.
-  CXXDestructorDecl *DtorD = RD->getDestructor();
-  GlobalDecl ScalarDtorGD(DtorD, Dtor_Deleting);
-  StringRef MangledName = getMangledName(ScalarDtorGD);
-  llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
-  GlobalDecl VectorDtorGD(DtorD, Dtor_VectorDeleting);
-  if (Entry && !Entry->isDeclaration()) {
-    StringRef VDName = getMangledName(VectorDtorGD);
-    llvm::GlobalValue *VDEntry = GetGlobalValue(VDName);
-    // It exists and it should be an alias.
-    assert(VDEntry && isa<llvm::GlobalAlias>(VDEntry));
-    auto *NewFn = llvm::Function::Create(
-        cast<llvm::FunctionType>(VDEntry->getValueType()),
-        llvm::Function::ExternalLinkage, VDName, &getModule());
-    SetFunctionAttributes(VectorDtorGD, NewFn, /*IsIncompleteFunction*/ false,
-                          /*IsThunk*/ false);
-    NewFn->takeName(VDEntry);
-    VDEntry->replaceAllUsesWith(NewFn);
-    VDEntry->eraseFromParent();
-    Entry->replaceAllUsesWith(NewFn);
-    Entry->eraseFromParent();
-  }
-  // Always add a deferred decl to emit once we confirmed that vector deleting
-  // destructor definition is required. That helps to enforse its generation
-  // even if destructor is only declared.
-  addDeferredDeclToEmit(VectorDtorGD);
-}

diff  --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index 0a697c84b66a7..0081bf5c4cf5f 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -529,11 +529,6 @@ class CodeGenModule : public CodeGenTypeCache {
   /// that we don't re-emit the initializer.
   llvm::DenseMap<const Decl*, unsigned> DelayedCXXInitPosition;
 
-  /// To remember which types did require a vector deleting destructor body.
-  /// This set basically contains classes that have virtual destructor and new[]
-  /// was emitted for the class.
-  llvm::SmallPtrSet<const CXXRecordDecl *, 16> RequireVectorDeletingDtor;
-
   typedef std::pair<OrderGlobalInitsOrStermFinalizers, llvm::Function *>
       GlobalInitData;
 
@@ -1583,13 +1578,6 @@ class CodeGenModule : public CodeGenTypeCache {
   /// are emitted lazily.
   void EmitGlobal(GlobalDecl D);
 
-  /// Record that new[] was called for the class, transform vector deleting
-  /// destructor definition in a form of alias to the actual definition.
-  void requireVectorDestructorDefinition(const CXXRecordDecl *RD);
-
-  /// Check that class need vector deleting destructor body.
-  bool classNeedsVectorDestructor(const CXXRecordDecl *RD);
-
   bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D);
   void EmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target);
 

diff  --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index d959b89f860e4..06fce6171eb28 100644
--- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -4107,7 +4107,7 @@ void MicrosoftCXXABI::emitCXXStructor(GlobalDecl GD) {
     return;
 
   if (GD.getDtorType() == Dtor_VectorDeleting &&
-      !CGM.classNeedsVectorDestructor(dtor->getParent())) {
+      !getContext().classNeedsVectorDeletingDestructor(dtor->getParent())) {
     // Create GlobalDecl object with the correct type for the scalar
     // deleting destructor.
     GlobalDecl ScalarDtorGD(dtor, Dtor_Deleting);

diff  --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 441df43d3d184..0591d05d361c0 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -11268,7 +11268,6 @@ bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) {
 
       if (Context.getTargetInfo().emitVectorDeletingDtors(
               Context.getLangOpts())) {
-        bool DestructorIsExported = Destructor->hasAttr<DLLExportAttr>();
         // Lookup delete[] too in case we have to emit a vector deleting dtor.
         DeclarationName VDeleteName =
             Context.DeclarationNames.getCXXOperatorName(OO_Array_Delete);
@@ -11282,8 +11281,7 @@ bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) {
                                                     VDeleteName);
           Destructor->setGlobalOperatorArrayDelete(GlobalArrOperatorDelete);
           if (GlobalArrOperatorDelete &&
-              (Context.classMaybeNeedsVectorDeletingDestructor(RD) ||
-               DestructorIsExported))
+              Context.classNeedsVectorDeletingDestructor(RD))
             MarkFunctionReferenced(Loc, GlobalArrOperatorDelete);
         } else if (!ArrOperatorDelete) {
           ArrOperatorDelete = FindDeallocationFunctionForDestructor(
@@ -11291,9 +11289,7 @@ bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) {
               /*LookForGlobal*/ true, VDeleteName);
         }
         Destructor->setOperatorArrayDelete(ArrOperatorDelete);
-        if (ArrOperatorDelete &&
-            (Context.classMaybeNeedsVectorDeletingDestructor(RD) ||
-             DestructorIsExported))
+        if (ArrOperatorDelete && Context.classNeedsVectorDeletingDestructor(RD))
           MarkFunctionReferenced(Loc, ArrOperatorDelete);
       }
     }
@@ -19132,8 +19128,6 @@ void Sema::MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class,
           // delete().
           ContextRAII SavedContext(*this, DD);
           CheckDestructor(DD);
-          if (!DD->getOperatorDelete())
-            DD->setInvalidDecl();
         } else {
           MarkFunctionReferenced(Loc, Class->getDestructor());
         }

diff  --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 08bc6aa483844..8a095b2a89cb7 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -2636,31 +2636,17 @@ ExprResult Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
     MarkFunctionReferenced(StartLoc, OperatorDelete);
   }
 
-  // new[] will trigger vector deleting destructor emission if the class has
-  // virtual destructor for MSVC compatibility. Perform necessary checks.
-  if (Context.getTargetInfo().emitVectorDeletingDtors(Context.getLangOpts())) {
-    if (const CXXConstructExpr *CCE =
-            dyn_cast_or_null<CXXConstructExpr>(Initializer);
-        CCE && ArraySize) {
-      CXXRecordDecl *ClassDecl = CCE->getConstructor()->getParent();
-      // We probably already did this for another new[] with this class so don't
-      // do it twice.
-      if (!Context.classMaybeNeedsVectorDeletingDestructor(ClassDecl)) {
-        auto *Dtor = ClassDecl->getDestructor();
-        if (Dtor && Dtor->isVirtual() && !Dtor->isDeleted()) {
-          Context.setClassMaybeNeedsVectorDeletingDestructor(ClassDecl);
-          if (!Dtor->isDefined() && !Dtor->isInvalidDecl()) {
-            // Call CheckDestructor if destructor is not defined. This is
-            // needed to find operators delete and delete[] for vector deleting
-            // destructor body because new[] will trigger emission of vector
-            // deleting destructor body even if destructor is defined in another
-            // translation unit.
-            ContextRAII SavedContext(*this, Dtor);
-            CheckDestructor(Dtor);
-          }
-        }
-      }
-    }
+  // For MSVC vector deleting destructors support we record that for the class
+  // new[] was called. We try to optimize the code size and only emit vector
+  // deleting destructors when they are required. Vector deleting destructors
+  // are required for delete[] call but MSVC triggers emission of them
+  // whenever new[] is called for an object of the class and we do the same
+  // for compatibility.
+  if (const CXXConstructExpr *CCE =
+          dyn_cast_or_null<CXXConstructExpr>(Initializer);
+      CCE && ArraySize) {
+    Context.setClassNeedsVectorDeletingDestructor(
+        CCE->getConstructor()->getParent());
   }
 
   return CXXNewExpr::Create(Context, UseGlobal, OperatorNew, OperatorDelete,

diff  --git a/clang/test/CodeGenCXX/microsoft-vector-deleting-dtors-new-array.cpp b/clang/test/CodeGenCXX/microsoft-vector-deleting-dtors-new-array.cpp
deleted file mode 100644
index b8b6e44b6b2f8..0000000000000
--- a/clang/test/CodeGenCXX/microsoft-vector-deleting-dtors-new-array.cpp
+++ /dev/null
@@ -1,122 +0,0 @@
-// RUN: %clang_cc1 -emit-llvm -fms-extensions %s -triple=x86_64-pc-windows-msvc -o - | FileCheck %s
-
-// Test that vector deleting destructors are emitted when new[] is used,
-// even when the destructor definition is in another translation unit.
-
-struct ForwardDeclared {
-  ForwardDeclared();
-  virtual ~ForwardDeclared();
-};
-
-struct DefinedInTU {
-  virtual ~DefinedInTU();
-};
-
-struct NonVirtualDtor {
-  ~NonVirtualDtor();
-};
-
-struct NoDtor {
-  virtual void foo();
-  int x;
-};
-
-struct DeclDerived : ForwardDeclared {
-  ~DeclDerived() override;
-};
-
-struct InlineDefaulted {
-  virtual ~InlineDefaulted() = default;
-};
-
-struct OutOfLineDefaulted {
-  virtual ~OutOfLineDefaulted();
-};
-
-OutOfLineDefaulted::~OutOfLineDefaulted() = default;
-
-template<typename T>
-struct Container {
-  T data;
-  virtual ~Container();
-};
-
-extern template class Container<int>;
-Container<int> *arr = new Container<int>[5];
-
-struct ImplicitVDtorDerived : ForwardDeclared{
-  int data;
-};
-
-struct __declspec(dllimport) DllImported {
-  virtual ~DllImported();
-};
-
-struct VirtualDerived : virtual ForwardDeclared {
-  ~VirtualDerived() override;
-};
-
-struct DeclaredCtorDefinedDtor {
-  DeclaredCtorDefinedDtor();
-  virtual ~DeclaredCtorDefinedDtor() {}
-};
-
-struct TemplateNotAllocated {
-  TemplateNotAllocated();
-  virtual ~TemplateNotAllocated();
-};
-
-struct TemplateAllocated {
-  TemplateAllocated();
-  virtual ~TemplateAllocated();
-};
-
-template <int T>
-void allocate() {
-  TemplateNotAllocated *arr = new TemplateNotAllocated[T];
-}
-
-template <typename T>
-void actuallyAllocate() {
-  T *arr = new T[10];
-  delete[] arr;
-}
-
-void cases() {
-  ForwardDeclared *arr = new ForwardDeclared[5];
-  DefinedInTU *arr1 = new DefinedInTU[5];
-  NonVirtualDtor *arr2 = new NonVirtualDtor[5];
-  NoDtor *arr3 = new NoDtor[5];
-  ForwardDeclared *arr4 = new DeclDerived[5];
-  InlineDefaulted *arr5 = new InlineDefaulted[5];
-  OutOfLineDefaulted *arr6 = new OutOfLineDefaulted[5];
-  ImplicitVDtorDerived *arr7 = new ImplicitVDtorDerived[5];
-  DllImported *arr8 = new DllImported[5];
-  VirtualDerived *arr9 = new VirtualDerived[3];
-  DeclaredCtorDefinedDtor *arr10 = new DeclaredCtorDefinedDtor[5];
-  actuallyAllocate<TemplateAllocated>();
-}
-
-
-// CHECK-DAG: declare dso_local void @"??1ForwardDeclared@@UEAA at XZ"(
-// CHECK-DAG: define weak dso_local noundef ptr @"??_EForwardDeclared@@UEAAPEAXI at Z"(
-// CHECK-DAG: define dso_local void @"??1DefinedInTU@@UEAA at XZ"(
-// CHECK-DAG: define weak dso_local noundef ptr @"??_EDefinedInTU@@UEAAPEAXI at Z"(
-// CHECK-DAG: define weak dso_local noundef ptr @"??_EDeclDerived@@UEAAPEAXI at Z"(
-// CHECK-DAG: declare dso_local void @"??1DeclDerived@@UEAA at XZ"(
-// CHECK-DAG: define weak dso_local noundef ptr @"??_EInlineDefaulted@@UEAAPEAXI at Z"(
-// CHECK-DAG: define weak dso_local noundef ptr @"??_EOutOfLineDefaulted@@UEAAPEAXI at Z"(
-// CHECK-DAG: declare dso_local void @"??1?$Container at H@@UEAA at XZ"(
-// CHECK-DAG: define weak dso_local noundef ptr @"??_E?$Container at H@@UEAAPEAXI at Z"(
-// CHECK-DAG: define weak dso_local noundef ptr @"??_EImplicitVDtorDerived@@UEAAPEAXI at Z"(
-// CHECK-DAG: declare dllimport void @"??1DllImported@@UEAA at XZ"(
-// CHECK-DAG: define weak dso_local noundef ptr @"??_EDllImported@@UEAAPEAXI at Z"(
-// CHECK-DAG: define weak dso_local noundef ptr @"??_EVirtualDerived@@UEAAPEAXI at Z"(
-// CHECK-DAG: define weak dso_local noundef ptr @"??_EDeclaredCtorDefinedDtor@@UEAAPEAXI at Z"(
-// CHECK-DAG: declare dso_local void @"??1TemplateAllocated@@UEAA at XZ"(
-// CHECK-DAG: define weak dso_local noundef ptr @"??_ETemplateAllocated@@UEAAPEAXI at Z"(
-// CHECK-NOT: @"??_ETemplateNotAllocated@@
-// CHECK-NOT: @"??_ENonVirtualDtor@@
-// CHECK-NOT: @"??_ENoDtor@@
-
-DefinedInTU::~DefinedInTU() {}

diff  --git a/clang/test/SemaCXX/gh134265.cpp b/clang/test/SemaCXX/gh134265.cpp
index 421197cf3d7f7..790165411c938 100644
--- a/clang/test/SemaCXX/gh134265.cpp
+++ b/clang/test/SemaCXX/gh134265.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 %s -verify=expected,noms -fsyntax-only -triple=x86_64-unknown-linux-gnu
-// RUN: %clang_cc1 %s -verify=expected,noms -fsyntax-only -triple=x86_64-unknown-linux-gnu -std=c++20
+// RUN: %clang_cc1 %s -verify=expected -fsyntax-only -triple=x86_64-unknown-linux-gnu
+// RUN: %clang_cc1 %s -verify=expected -fsyntax-only -triple=x86_64-unknown-linux-gnu -std=c++20
 // RUN: %clang_cc1 %s -verify=expected,ms -fms-extensions -fms-compatibility -triple=x86_64-pc-windows-msvc -DMS
 
 // Verify that clang doesn't emit additional errors when searching for
@@ -56,34 +56,7 @@ struct Final1 : BaseDelete1, BaseDelete2, BaseDestructor {
 };
 #endif // MS
 
-// Make sure there is no double diagnosing for declared-only destructors and
-// new[].
-struct DeclaredOnly {
-  virtual ~DeclaredOnly(); // ms-error {{attempt to use a deleted function}}
-  static void operator delete(void* ptr) = delete; // ms-note {{explicitly marked deleted here}}
-};
-
-struct DeclaredOnlyArr {
-  virtual ~DeclaredOnlyArr();
-  static void operator delete[](void* ptr) = delete;
-};
-
 void foo() {
     Final* a = new Final[10]();
     FinalExplicit* b = new FinalExplicit[10]();
-    DeclaredOnly *d = new DeclaredOnly[5]();
-    DeclaredOnlyArr *e = new DeclaredOnlyArr[5]();
 }
-
-// Make sure there is no double diagnosing for forward declared destructors
-// and new[].
-namespace std { struct destroying_delete_t {}; }
-struct A {
-  void operator delete(
-      A*, //expected-error {{cannot cast 'D' to its private base class 'A'}}
-      std::destroying_delete_t);
-};
-struct B : private A { using A::operator delete; }; //expected-note {{declared private here}}
-struct D : B { virtual ~D(); }; //ms-note {{while checking implicit 'delete this' for virtual destructor}}
-void f() { new D[5]; }
-D::~D() {} // noms-note {{while checking implicit 'delete this' for virtual destructor}}


        


More information about the llvm-branch-commits mailing list