[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 1 08:04:58 PDT 2026
https://github.com/ankit-cybertron created https://github.com/llvm/llvm-project/pull/213455
This PR adds a completeness check in `Sema::ActOnCXXDelete` so type-aware operator delete lookup is skipped when the pointee type is incomplete.
Added a test covering C++17/23 (warn) and C++26 (error).
Fixes #212675
>From 55d423457b4db2c6455e87ba76093fd6ae569b3f 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] [Clang] Skip type-aware delete resolution for incomplete
types + test
---
clang/lib/Sema/SemaExprCXX.cpp | 10 +++++--
.../type-aware-delete-incomplete-type.cpp | 30 +++++++++++++++++++
2 files changed, 37 insertions(+), 3 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..08938291987ef 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -4149,9 +4149,14 @@ 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(),
+ Pointee, PassTypeIdentity,
AlignedAllocationMode::No, SizedDeallocationMode::No};
if (!UseGlobal &&
FindDeallocationFunction(StartLoc, PointeeRD, DeleteName,
@@ -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,7 +4211,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
// Look for a global declaration.
ImplicitDeallocationParameters IDP = {
- Pointee, ShouldUseTypeAwareOperatorNewOrDelete(),
+ Pointee, PassTypeIdentity,
alignedAllocationModeFromBool(Overaligned),
sizedDeallocationModeFromBool(CanProvideSize)};
OperatorDelete = FindUsualDeallocationFunction(StartLoc, IDP, DeleteName);
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
More information about the cfe-commits
mailing list