[clang] [Clang] Skip type-aware operator delete resolution for incomplete pointee types (PR #213455)
Ankit Kumar Tiwari via cfe-commits
cfe-commits at lists.llvm.org
Sat Aug 8 14:10:59 PDT 2026
https://github.com/ankit-cybertron updated https://github.com/llvm/llvm-project/pull/213455
>From b09136141651917ef6f3531a15929aa8a44cb25c Mon Sep 17 00:00:00 2001
From: Ankit Kumar Tiwari <ankit.cybertron at gmail.com>
Date: Sat, 1 Aug 2026 20:24:16 +0530
Subject: [PATCH 1/4] [Clang] Skip type-aware delete resolution for incomplete
types + test
---
clang/lib/Sema/SemaExprCXX.cpp | 15 ++++++----
.../type-aware-delete-incomplete-type.cpp | 30 +++++++++++++++++++
2 files changed, 39 insertions(+), 6 deletions(-)
create mode 100644 clang/test/SemaCXX/type-aware-delete-incomplete-type.cpp
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 538604aa2e64b..e8e109d40ced8 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -4149,10 +4149,15 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
DeclarationName DeleteName = Context.DeclarationNames.getCXXOperatorName(
ArrayForm ? OO_Array_Delete : OO_Delete);
+ bool IsComplete = isCompleteType(StartLoc, Pointee);
+ TypeAwareAllocationMode PassTypeIdentity =
+ IsComplete ? ShouldUseTypeAwareOperatorNewOrDelete()
+ : TypeAwareAllocationMode::No;
+
if (PointeeRD) {
- ImplicitDeallocationParameters IDP = {
- Pointee, ShouldUseTypeAwareOperatorNewOrDelete(),
- AlignedAllocationMode::No, SizedDeallocationMode::No};
+ ImplicitDeallocationParameters IDP = {Pointee, PassTypeIdentity,
+ AlignedAllocationMode::No,
+ SizedDeallocationMode::No};
if (!UseGlobal &&
FindDeallocationFunction(StartLoc, PointeeRD, DeleteName,
OperatorDelete, IDP))
@@ -4199,7 +4204,6 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
return ExprError();
}
- bool IsComplete = isCompleteType(StartLoc, Pointee);
bool CanProvideSize =
IsComplete && (!ArrayForm || UsualArrayDeleteWantsSize ||
Pointee.isDestructedType());
@@ -4207,8 +4211,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
// Look for a global declaration.
ImplicitDeallocationParameters IDP = {
- Pointee, ShouldUseTypeAwareOperatorNewOrDelete(),
- alignedAllocationModeFromBool(Overaligned),
+ Pointee, PassTypeIdentity, alignedAllocationModeFromBool(Overaligned),
sizedDeallocationModeFromBool(CanProvideSize)};
OperatorDelete = FindUsualDeallocationFunction(StartLoc, IDP, DeleteName);
if (!OperatorDelete)
diff --git a/clang/test/SemaCXX/type-aware-delete-incomplete-type.cpp b/clang/test/SemaCXX/type-aware-delete-incomplete-type.cpp
new file mode 100644
index 0000000000000..2eb74beaec8d0
--- /dev/null
+++ b/clang/test/SemaCXX/type-aware-delete-incomplete-type.cpp
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify=warn %s
+// RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify=warn %s
+// RUN: %clang_cc1 -std=c++26 -fsyntax-only -verify=err %s
+// RUN: %clang_cc1 -std=c++17 -emit-llvm -o - %s | FileCheck %s
+
+class Foo; // warn-note {{forward declaration of 'Foo'}} \
+ // err-note {{forward declaration of 'Foo'}}
+
+typedef __SIZE_TYPE__ size_t;
+
+namespace std {
+ enum class align_val_t : size_t {};
+ template <class T> struct type_identity {
+ typedef T type;
+ };
+}
+
+template <class T>
+void operator delete(std::type_identity<T>, void *, size_t, std::align_val_t); // warn-warning {{type aware allocators are a Clang extension}} \
+ // err-warning {{type aware allocators are a Clang extension}}
+
+void f(Foo *o) {
+ delete o;
+ // warn-warning at -1 {{deleting pointer to incomplete type 'Foo' is incompatible with C++2c and may cause undefined behavior}}
+ // err-error at -2 {{cannot delete pointer to incomplete type 'Foo'}}
+}
+
+// CHECK-LABEL: define {{.*}} @_Z1fP3Foo
+// CHECK-NOT: call {{.*}} @{{.*}}operator delete{{.*}}type_identity
+// CHECK: call void @_ZdlPv
\ No newline at end of file
>From 8895993e2023881aee12f91e2336e3a9a04b7218 Mon Sep 17 00:00:00 2001
From: Ankit Kumar Tiwari <ankit.cybertron at gmail.com>
Date: Mon, 3 Aug 2026 00:33:16 +0530
Subject: [PATCH 2/4] Add warning when dropping type-aware delete for
incomplete types
---
clang/include/clang/Basic/DiagnosticSemaKinds.td | 4 ++++
clang/lib/Sema/SemaExprCXX.cpp | 7 +++++--
clang/test/SemaCXX/type-aware-delete-incomplete-type.cpp | 8 +++++---
3 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index cce6f70a58893..e45a5e4c4cb08 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10444,6 +10444,10 @@ def err_destroying_operator_delete_not_usual : Error<
def err_type_aware_destroying_operator_delete : Error<
"destroying delete is not permitted to be type aware">;
+def warn_type_aware_delete_incomplete : Warning<
+ "type-aware deallocation is not used for deletion of "
+ "pointer to incomplete type %0">,
+ InGroup<DeleteIncomplete>;
def warn_ext_type_aware_allocators : ExtWarn<
"type aware allocators are a Clang extension">, InGroup<DiagGroup<"ext-cxx-type-aware-allocators">>;
def err_type_aware_allocator_missing_matching_operator : Error<
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index e8e109d40ced8..54bd27ff853d1 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -4151,8 +4151,11 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
bool IsComplete = isCompleteType(StartLoc, Pointee);
TypeAwareAllocationMode PassTypeIdentity =
- IsComplete ? ShouldUseTypeAwareOperatorNewOrDelete()
- : TypeAwareAllocationMode::No;
+ ShouldUseTypeAwareOperatorNewOrDelete();
+ if (!IsComplete && isTypeAwareAllocation(PassTypeIdentity)) {
+ Diag(StartLoc, diag::warn_type_aware_delete_incomplete) << Pointee;
+ PassTypeIdentity = TypeAwareAllocationMode::No;
+ }
if (PointeeRD) {
ImplicitDeallocationParameters IDP = {Pointee, PassTypeIdentity,
diff --git a/clang/test/SemaCXX/type-aware-delete-incomplete-type.cpp b/clang/test/SemaCXX/type-aware-delete-incomplete-type.cpp
index 2eb74beaec8d0..610fd8a81a74b 100644
--- a/clang/test/SemaCXX/type-aware-delete-incomplete-type.cpp
+++ b/clang/test/SemaCXX/type-aware-delete-incomplete-type.cpp
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify=warn %s
// RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify=warn %s
// RUN: %clang_cc1 -std=c++26 -fsyntax-only -verify=err %s
-// RUN: %clang_cc1 -std=c++17 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s
class Foo; // warn-note {{forward declaration of 'Foo'}} \
// err-note {{forward declaration of 'Foo'}}
@@ -21,8 +21,10 @@ void operator delete(std::type_identity<T>, void *, size_t, std::align_val_t); /
void f(Foo *o) {
delete o;
- // warn-warning at -1 {{deleting pointer to incomplete type 'Foo' is incompatible with C++2c and may cause undefined behavior}}
- // err-error at -2 {{cannot delete pointer to incomplete type 'Foo'}}
+ // warn-warning at -1 {{type-aware deallocation is not used for deletion of pointer to incomplete type 'Foo'}}
+ // warn-warning at -2 {{deleting pointer to incomplete type 'Foo' is incompatible with C++2c and may cause undefined behavior}}
+ // err-warning at -3 {{type-aware deallocation is not used for deletion of pointer to incomplete type 'Foo'}}
+ // err-error at -4 {{cannot delete pointer to incomplete type 'Foo'}}
}
// CHECK-LABEL: define {{.*}} @_Z1fP3Foo
>From 58ff52629ea67fd553ea82a1717af64451ec18bd Mon Sep 17 00:00:00 2001
From: Ankit Kumar Tiwari <ankit.cybertron at gmail.com>
Date: Sun, 9 Aug 2026 02:36:38 +0530
Subject: [PATCH 3/4] Add error for type-aware binding to incomplete types
---
.../clang/Basic/DiagnosticSemaKinds.td | 3 ++
clang/lib/Sema/SemaExprCXX.cpp | 13 ++++----
.../type-aware-delete-incomplete-type.cpp | 30 +++++++++++++------
3 files changed, 31 insertions(+), 15 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index e45a5e4c4cb08..8d959bd907eb7 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10448,6 +10448,9 @@ def warn_type_aware_delete_incomplete : Warning<
"type-aware deallocation is not used for deletion of "
"pointer to incomplete type %0">,
InGroup<DeleteIncomplete>;
+def err_type_aware_delete_incomplete : Error<
+ "type-aware deallocation function matches incomplete type %0; "
+ "the type must be complete to use type-aware deallocation">;
def warn_ext_type_aware_allocators : ExtWarn<
"type aware allocators are a Clang extension">, InGroup<DiagGroup<"ext-cxx-type-aware-allocators">>;
def err_type_aware_allocator_missing_matching_operator : Error<
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 54bd27ff853d1..e9917a08a6f89 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -4152,10 +4152,6 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
bool IsComplete = isCompleteType(StartLoc, Pointee);
TypeAwareAllocationMode PassTypeIdentity =
ShouldUseTypeAwareOperatorNewOrDelete();
- if (!IsComplete && isTypeAwareAllocation(PassTypeIdentity)) {
- Diag(StartLoc, diag::warn_type_aware_delete_incomplete) << Pointee;
- PassTypeIdentity = TypeAwareAllocationMode::No;
- }
if (PointeeRD) {
ImplicitDeallocationParameters IDP = {Pointee, PassTypeIdentity,
@@ -4242,11 +4238,16 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
unsigned AddressParamIdx = 0;
if (OperatorDelete->isTypeAwareOperatorNewOrDelete()) {
+ if (!IsComplete) {
+ Diag(StartLoc, diag::err_type_aware_delete_incomplete) << Pointee;
+ return ExprError();
+ }
QualType TypeIdentity = OperatorDelete->getParamDecl(0)->getType();
- if (RequireCompleteType(StartLoc, TypeIdentity,
- diag::err_incomplete_type))
+ if (RequireCompleteType(StartLoc, TypeIdentity, diag::err_incomplete_type))
return ExprError();
AddressParamIdx = 1;
+ } else if (!IsComplete && isTypeAwareAllocation(PassTypeIdentity)) {
+ Diag(StartLoc, diag::warn_type_aware_delete_incomplete) << Pointee;
}
// Convert the operand to the type of the first parameter of operator
diff --git a/clang/test/SemaCXX/type-aware-delete-incomplete-type.cpp b/clang/test/SemaCXX/type-aware-delete-incomplete-type.cpp
index 610fd8a81a74b..7fb2698997b7b 100644
--- a/clang/test/SemaCXX/type-aware-delete-incomplete-type.cpp
+++ b/clang/test/SemaCXX/type-aware-delete-incomplete-type.cpp
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify=warn %s
// RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify=warn %s
// RUN: %clang_cc1 -std=c++26 -fsyntax-only -verify=err %s
-// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -DCODEGEN -emit-llvm -o - %s | FileCheck %s
class Foo; // warn-note {{forward declaration of 'Foo'}} \
// err-note {{forward declaration of 'Foo'}}
@@ -15,18 +15,30 @@ namespace std {
};
}
-template <class T>
-void operator delete(std::type_identity<T>, void *, size_t, std::align_val_t); // warn-warning {{type aware allocators are a Clang extension}} \
+void operator delete(std::type_identity<Foo>, void *, size_t, std::align_val_t); // warn-warning {{type aware allocators are a Clang extension}} \
// err-warning {{type aware allocators are a Clang extension}}
+#ifndef CODEGEN
void f(Foo *o) {
delete o;
- // warn-warning at -1 {{type-aware deallocation is not used for deletion of pointer to incomplete type 'Foo'}}
- // warn-warning at -2 {{deleting pointer to incomplete type 'Foo' is incompatible with C++2c and may cause undefined behavior}}
- // err-warning at -3 {{type-aware deallocation is not used for deletion of pointer to incomplete type 'Foo'}}
- // err-error at -4 {{cannot delete pointer to incomplete type 'Foo'}}
+ // warn-warning at -1 {{deleting pointer to incomplete type 'Foo' is incompatible with C++2c and may cause undefined behavior}}
+ // warn-error at -2 {{type-aware deallocation function matches incomplete type 'Foo'; the type must be complete to use type-aware deallocation}}
+ // err-error at -3 {{cannot delete pointer to incomplete type 'Foo'}}
+ // err-error at -4 {{type-aware deallocation function matches incomplete type 'Foo'; the type must be complete to use type-aware deallocation}}
}
+#endif
-// CHECK-LABEL: define {{.*}} @_Z1fP3Foo
+class Bar; // warn-note {{forward declaration of 'Bar'}} \
+ // err-note {{forward declaration of 'Bar'}}
+
+void g(Bar *b) {
+ delete b;
+ // warn-warning at -1 {{type-aware deallocation is not used for deletion of pointer to incomplete type 'Bar'}}
+ // warn-warning at -2 {{deleting pointer to incomplete type 'Bar' is incompatible with C++2c and may cause undefined behavior}}
+ // err-warning at -3 {{type-aware deallocation is not used for deletion of pointer to incomplete type 'Bar'}}
+ // err-error at -4 {{cannot delete pointer to incomplete type 'Bar'}}
+}
+
+// CHECK-LABEL: define {{.*}} @_Z1gP3Bar
// CHECK-NOT: call {{.*}} @{{.*}}operator delete{{.*}}type_identity
-// CHECK: call void @_ZdlPv
\ No newline at end of file
+// CHECK: call void @_ZdlPv
>From 4d5b6a4e83b2e7a62e09149eb26f1963d722ea4c Mon Sep 17 00:00:00 2001
From: Ankit Kumar Tiwari <ankit.cybertron at gmail.com>
Date: Sun, 9 Aug 2026 02:40:45 +0530
Subject: [PATCH 4/4] Fix formatting
---
clang/lib/Sema/SemaExprCXX.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index e9917a08a6f89..07a32e98ccd9e 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -4243,7 +4243,8 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
return ExprError();
}
QualType TypeIdentity = OperatorDelete->getParamDecl(0)->getType();
- if (RequireCompleteType(StartLoc, TypeIdentity, diag::err_incomplete_type))
+ if (RequireCompleteType(StartLoc, TypeIdentity,
+ diag::err_incomplete_type))
return ExprError();
AddressParamIdx = 1;
} else if (!IsComplete && isTypeAwareAllocation(PassTypeIdentity)) {
More information about the cfe-commits
mailing list