[clang] [MS][clang] Error about ambiguous operator delete[] only when required (PR #135041)
Mariya Podchishchaeva via cfe-commits
cfe-commits at lists.llvm.org
Thu Apr 10 04:03:27 PDT 2025
https://github.com/Fznamznon updated https://github.com/llvm/llvm-project/pull/135041
>From 9e923b1fe683dea499f7557a48d97aa6d2469c07 Mon Sep 17 00:00:00 2001
From: "Podchishchaeva, Mariya" <mariya.podchishchaeva at intel.com>
Date: Wed, 9 Apr 2025 09:02:17 -0700
Subject: [PATCH 1/4] [MS][clang] Error about ambigous operator delete[] only
when required
And issue was reported in
https://github.com/llvm/llvm-project/pull/133950 . Since we don't always
emit vector deleting dtors, only error out about ambigous operator
delete[] when it will be required for vector delering dtor emission.
---
clang/lib/Sema/SemaDeclCXX.cpp | 21 ++++++++++--------
clang/lib/Sema/SemaExprCXX.cpp | 18 +++++++++++++--
clang/test/SemaCXX/gh134265.cpp | 39 ++++++++++++++++++++++++++++++---
3 files changed, 64 insertions(+), 14 deletions(-)
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index b86f7118e0b34..6732062965aef 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -11045,15 +11045,18 @@ bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) {
DiagnoseUseOfDecl(OperatorDelete, Loc);
MarkFunctionReferenced(Loc, OperatorDelete);
Destructor->setOperatorDelete(OperatorDelete, ThisArg);
- // Lookup delete[] too in case we have to emit a vector deleting dtor;
- DeclarationName VDeleteName =
- Context.DeclarationNames.getCXXOperatorName(OO_Array_Delete);
- FunctionDecl *ArrOperatorDelete = FindDeallocationFunctionForDestructor(
- Loc, RD, VDeleteName, /*Diagnose=*/false);
- // delete[] in the TU will make sure the operator is referenced and its
- // uses diagnosed, otherwise vector deleting dtor won't be called anyway,
- // so just record it in the destructor.
- Destructor->setOperatorArrayDelete(ArrOperatorDelete);
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+ // Lookup delete[] too in case we have to emit a vector deleting dtor;
+ DeclarationName VDeleteName =
+ Context.DeclarationNames.getCXXOperatorName(OO_Array_Delete);
+ FunctionDecl *ArrOperatorDelete = FindDeallocationFunctionForDestructor(
+ Loc, RD, VDeleteName,
+ Destructor->hasAttr<DLLExportAttr>() && Destructor->isDefined());
+ // delete[] in the TU will make sure the operator is referenced and its
+ // uses diagnosed, otherwise vector deleting dtor won't be called
+ // anyway, so just record it in the destructor.
+ Destructor->setOperatorArrayDelete(ArrOperatorDelete);
+ }
}
}
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 42bc4db20e818..247cd02b23522 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -2789,8 +2789,19 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
return true;
}
+ // new[] will force emission of vector deleting dtor which needs delete[].
+ bool MaybeVectorDeletingDtor = false;
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+ if (AllocElemType->isRecordType() && IsArray) {
+ auto *RD =
+ cast<CXXRecordDecl>(AllocElemType->castAs<RecordType>()->getDecl());
+ CXXDestructorDecl *DD = RD->getDestructor();
+ MaybeVectorDeletingDtor = DD && DD->isVirtual() && !DD->isDeleted();
+ }
+ }
+
// We don't need an operator delete if we're running under -fno-exceptions.
- if (!getLangOpts().Exceptions) {
+ if (!getLangOpts().Exceptions && !MaybeVectorDeletingDtor) {
OperatorDelete = nullptr;
return false;
}
@@ -3290,8 +3301,11 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
// Try to find operator delete/operator delete[] in class scope.
LookupQualifiedName(Found, RD);
- if (Found.isAmbiguous())
+ if (Found.isAmbiguous()) {
+ if (!Diagnose)
+ Found.suppressDiagnostics();
return true;
+ }
Found.suppressDiagnostics();
diff --git a/clang/test/SemaCXX/gh134265.cpp b/clang/test/SemaCXX/gh134265.cpp
index c7bdeb2add0cc..a2d360d7ba02a 100644
--- a/clang/test/SemaCXX/gh134265.cpp
+++ b/clang/test/SemaCXX/gh134265.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 %s -verify -fsyntax-only
+// RUN: %clang_cc1 %s -verify=expected -fsyntax-only
+// RUN: %clang_cc1 %s -verify=expected -fsyntax-only -std=c++20
+// RUN: %clang_cc1 %s -verify=expected,ms -fms-extensions -fms-compatibility -triple=x86_64-pc-windows-msvc -DMS
struct Foo {
virtual ~Foo() {} // expected-error {{attempt to use a deleted function}}
@@ -13,10 +15,41 @@ struct Bar {
struct Baz {
virtual ~Baz() {}
- static void operator delete[](void* ptr) = delete; // expected-note {{explicitly marked deleted here}}
+ static void operator delete[](void* ptr) = delete; // expected-note {{explicitly marked deleted here}}\
+ ms-note{{explicitly marked deleted here}}}
+};
+
+struct BarBaz {
+ ~BarBaz() {}
+ static void operator delete[](void* ptr) = delete;
};
void foobar() {
- Baz *B = new Baz[10]();
+ Baz *B = new Baz[10](); // ms-error {{attempt to use a deleted function}}
delete [] B; // expected-error {{attempt to use a deleted function}}
+ BarBaz *BB = new BarBaz[10]();
+}
+
+struct BaseDelete1 {
+ void operator delete[](void *); //ms-note 2{{member found by ambiguous name lookup}}
+};
+struct BaseDelete2 {
+ void operator delete[](void *); //ms-note 2{{member found by ambiguous name lookup}}
+};
+struct BaseDestructor {
+ BaseDestructor() {}
+ virtual ~BaseDestructor() = default;
+};
+struct Final : BaseDelete1, BaseDelete2, BaseDestructor {
+ Final() {}
+};
+
+#ifdef MS
+struct Final1 : BaseDelete1, BaseDelete2, BaseDestructor {
+ __declspec(dllexport) ~Final1() {} // ms-error {{member 'operator delete[]' found in multiple base classes of different types}}
+};
+#endif // MS
+
+void foo() {
+ Final* a = new Final[10](); // ms-error {{member 'operator delete[]' found in multiple base classes of different types}}
}
>From a66bc6c0c4934a95d233e82b3e5a0705dde74467 Mon Sep 17 00:00:00 2001
From: "Podchishchaeva, Mariya" <mariya.podchishchaeva at intel.com>
Date: Thu, 10 Apr 2025 01:06:28 -0700
Subject: [PATCH 2/4] Correct the test
---
clang/test/SemaCXX/gh134265.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/clang/test/SemaCXX/gh134265.cpp b/clang/test/SemaCXX/gh134265.cpp
index a2d360d7ba02a..d5673ece97eba 100644
--- a/clang/test/SemaCXX/gh134265.cpp
+++ b/clang/test/SemaCXX/gh134265.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 %s -verify=expected -fsyntax-only
-// RUN: %clang_cc1 %s -verify=expected -fsyntax-only -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
struct Foo {
>From d0478334528ce6769faf2329ebce02b69c68f355 Mon Sep 17 00:00:00 2001
From: "Podchishchaeva, Mariya" <mariya.podchishchaeva at intel.com>
Date: Thu, 10 Apr 2025 03:39:42 -0700
Subject: [PATCH 3/4] Add a test with explicit dtor
---
clang/test/SemaCXX/gh134265.cpp | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/clang/test/SemaCXX/gh134265.cpp b/clang/test/SemaCXX/gh134265.cpp
index d5673ece97eba..baef10bec8bff 100644
--- a/clang/test/SemaCXX/gh134265.cpp
+++ b/clang/test/SemaCXX/gh134265.cpp
@@ -31,10 +31,10 @@ void foobar() {
}
struct BaseDelete1 {
- void operator delete[](void *); //ms-note 2{{member found by ambiguous name lookup}}
+ void operator delete[](void *); //ms-note 3{{member found by ambiguous name lookup}}
};
struct BaseDelete2 {
- void operator delete[](void *); //ms-note 2{{member found by ambiguous name lookup}}
+ void operator delete[](void *); //ms-note 3{{member found by ambiguous name lookup}}
};
struct BaseDestructor {
BaseDestructor() {}
@@ -43,6 +43,10 @@ struct BaseDestructor {
struct Final : BaseDelete1, BaseDelete2, BaseDestructor {
Final() {}
};
+struct FinalExplicit : BaseDelete1, BaseDelete2, BaseDestructor {
+ FinalExplicit() {}
+ inline ~FinalExplicit() {}
+};
#ifdef MS
struct Final1 : BaseDelete1, BaseDelete2, BaseDestructor {
@@ -52,4 +56,5 @@ struct Final1 : BaseDelete1, BaseDelete2, BaseDestructor {
void foo() {
Final* a = new Final[10](); // ms-error {{member 'operator delete[]' found in multiple base classes of different types}}
+ FinalExplicit* b = new FinalExplicit[10](); // ms-error {{member 'operator delete[]' found in multiple base classes of different types}}
}
>From d441be3fa84d1f48a9981670bcd202131c729a56 Mon Sep 17 00:00:00 2001
From: "Podchishchaeva, Mariya" <mariya.podchishchaeva at intel.com>
Date: Thu, 10 Apr 2025 04:02:55 -0700
Subject: [PATCH 4/4] Clarify why we diagnose for dllexpr
---
clang/lib/Sema/SemaDeclCXX.cpp | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 6732062965aef..0ee58fbfd9067 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -11049,12 +11049,16 @@ bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) {
// Lookup delete[] too in case we have to emit a vector deleting dtor;
DeclarationName VDeleteName =
Context.DeclarationNames.getCXXOperatorName(OO_Array_Delete);
+ // Diagnose if there is no available operator delete[] found and the
+ // destructor is exported. Vector deleting dtor body emission requires
+ // operator delete[] to be present. Whenever the destructor is exported,
+ // we just always emit vector deleting dtor body, because we don't know
+ // if new[] will be used with the type outside of the library. Otherwise
+ // when the dtor is not exported then new[]/delete[] in the TU will make
+ // sure the operator is referenced and its uses diagnosed.
+ bool Diagnose = Destructor->hasAttr<DLLExportAttr>() && Destructor->isDefined();
FunctionDecl *ArrOperatorDelete = FindDeallocationFunctionForDestructor(
- Loc, RD, VDeleteName,
- Destructor->hasAttr<DLLExportAttr>() && Destructor->isDefined());
- // delete[] in the TU will make sure the operator is referenced and its
- // uses diagnosed, otherwise vector deleting dtor won't be called
- // anyway, so just record it in the destructor.
+ Loc, RD, VDeleteName, Diagnose);
Destructor->setOperatorArrayDelete(ArrOperatorDelete);
}
}
More information about the cfe-commits
mailing list