[clang] [Clang][NFC] Refactor operator delete argument handling (PR #160554)
Andy Kaylor via cfe-commits
cfe-commits at lists.llvm.org
Wed Sep 24 09:33:22 PDT 2025
https://github.com/andykaylor created https://github.com/llvm/llvm-project/pull/160554
This change moves the getUsualDeleteParams function into the FunctionDecl class so that it can be shared between LLVM IR and CIR codegen. It also renames the function and associated structure to better reflect its use.
>From 0ad9048d8df08e99b1b150d5c9bea9487763cb68 Mon Sep 17 00:00:00 2001
From: Andy Kaylor <akaylor at nvidia.com>
Date: Tue, 23 Sep 2025 17:09:29 -0700
Subject: [PATCH] [Clang][NFC] Refactor operator delete argument handling
This change moves the getUsualDeleteParams function into the FunctionDecl
class so that it can be shared between LLVM IR and CIR codegen. It also
renames the function and associated structure to better reflect its use.
---
clang/include/clang/AST/Decl.h | 3 ++
clang/include/clang/AST/ExprCXX.h | 8 +++++
clang/lib/AST/Decl.cpp | 47 +++++++++++++++++++++++++
clang/lib/CodeGen/CGExprCXX.cpp | 58 ++-----------------------------
4 files changed, 61 insertions(+), 55 deletions(-)
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index d85d04d2a4d53..6894877ab5adf 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -80,6 +80,7 @@ class TypeAliasTemplateDecl;
class UnresolvedSetImpl;
class VarTemplateDecl;
enum class ImplicitParamKind;
+struct DeleteParamInfo;
// Holds a constraint expression along with a pack expansion index, if
// expanded.
@@ -2646,6 +2647,8 @@ class FunctionDecl : public DeclaratorDecl,
bool isTypeAwareOperatorNewOrDelete() const;
void setIsTypeAwareOperatorNewOrDelete(bool IsTypeAwareOperator = true);
+ DeleteParamInfo getDeleteParamInfo() const;
+
/// Compute the language linkage.
LanguageLinkage getLanguageLinkage() const;
diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h
index 9fedb230ce397..6b3706a7a84b9 100644
--- a/clang/include/clang/AST/ExprCXX.h
+++ b/clang/include/clang/AST/ExprCXX.h
@@ -2342,6 +2342,14 @@ struct ImplicitDeallocationParameters {
SizedDeallocationMode PassSize;
};
+/// The parameters to pass to a usual operator delete.
+struct DeleteParamInfo {
+ TypeAwareAllocationMode TypeAwareDelete = TypeAwareAllocationMode::No;
+ bool DestroyingDelete = false;
+ bool Size = false;
+ AlignedAllocationMode Alignment = AlignedAllocationMode::No;
+};
+
/// Represents a new-expression for memory allocation and constructor
/// calls, e.g: "new CXXNewExpr(foo)".
class CXXNewExpr final
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index cd8e495e82c80..f7b80eb244191 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -3552,6 +3552,53 @@ void FunctionDecl::setIsTypeAwareOperatorNewOrDelete(bool IsTypeAware) {
getASTContext().setIsTypeAwareOperatorNewOrDelete(this, IsTypeAware);
}
+DeleteParamInfo FunctionDecl::getDeleteParamInfo() const {
+ DeleteParamInfo Params;
+
+ // This function should only be called for operator delete declarations.
+ assert(getDeclName().isAnyOperatorDelete());
+ if (!getDeclName().isAnyOperatorDelete())
+ return Params;
+
+ const FunctionProtoType *FPT = getType()->castAs<FunctionProtoType>();
+ auto AI = FPT->param_type_begin(), AE = FPT->param_type_end();
+
+ if (isTypeAwareOperatorNewOrDelete()) {
+ Params.TypeAwareDelete = TypeAwareAllocationMode::Yes;
+ assert(AI != AE);
+ ++AI;
+ }
+
+ // The first argument after the type-identity parameter (if any) is
+ // always a void* (or C* for a destroying operator delete for class
+ // type C).
+ ++AI;
+
+ // The next parameter may be a std::destroying_delete_t.
+ if (isDestroyingOperatorDelete()) {
+ assert(!isTypeAwareAllocation(Params.TypeAwareDelete));
+ Params.DestroyingDelete = true;
+ assert(AI != AE);
+ ++AI;
+ }
+
+ // Figure out what other parameters we should be implicitly passing.
+ if (AI != AE && (*AI)->isIntegerType()) {
+ Params.Size = true;
+ ++AI;
+ } else
+ assert(!isTypeAwareAllocation(Params.TypeAwareDelete));
+
+ if (AI != AE && (*AI)->isAlignValT()) {
+ Params.Alignment = AlignedAllocationMode::Yes;
+ ++AI;
+ } else
+ assert(!isTypeAwareAllocation(Params.TypeAwareDelete));
+
+ assert(AI == AE && "unexpected usual deallocation function parameter");
+ return Params;
+}
+
LanguageLinkage FunctionDecl::getLanguageLinkage() const {
return getDeclLanguageLinkage(*this);
}
diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index a092b718412be..349319a571442 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/lib/CodeGen/CGExprCXX.cpp
@@ -1376,58 +1376,6 @@ RValue CodeGenFunction::EmitBuiltinNewDeleteCall(const FunctionProtoType *Type,
llvm_unreachable("predeclared global operator new/delete is missing");
}
-namespace {
-/// The parameters to pass to a usual operator delete.
-struct UsualDeleteParams {
- TypeAwareAllocationMode TypeAwareDelete = TypeAwareAllocationMode::No;
- bool DestroyingDelete = false;
- bool Size = false;
- AlignedAllocationMode Alignment = AlignedAllocationMode::No;
-};
-}
-
-static UsualDeleteParams getUsualDeleteParams(const FunctionDecl *FD) {
- UsualDeleteParams Params;
-
- const FunctionProtoType *FPT = FD->getType()->castAs<FunctionProtoType>();
- auto AI = FPT->param_type_begin(), AE = FPT->param_type_end();
-
- if (FD->isTypeAwareOperatorNewOrDelete()) {
- Params.TypeAwareDelete = TypeAwareAllocationMode::Yes;
- assert(AI != AE);
- ++AI;
- }
-
- // The first argument after the type-identity parameter (if any) is
- // always a void* (or C* for a destroying operator delete for class
- // type C).
- ++AI;
-
- // The next parameter may be a std::destroying_delete_t.
- if (FD->isDestroyingOperatorDelete()) {
- assert(!isTypeAwareAllocation(Params.TypeAwareDelete));
- Params.DestroyingDelete = true;
- assert(AI != AE);
- ++AI;
- }
-
- // Figure out what other parameters we should be implicitly passing.
- if (AI != AE && (*AI)->isIntegerType()) {
- Params.Size = true;
- ++AI;
- } else
- assert(!isTypeAwareAllocation(Params.TypeAwareDelete));
-
- if (AI != AE && (*AI)->isAlignValT()) {
- Params.Alignment = AlignedAllocationMode::Yes;
- ++AI;
- } else
- assert(!isTypeAwareAllocation(Params.TypeAwareDelete));
-
- assert(AI == AE && "unexpected usual deallocation function parameter");
- return Params;
-}
-
namespace {
/// A cleanup to call the given 'operator delete' function upon abnormal
/// exit from a new expression. Templated on a traits type that deals with
@@ -1494,7 +1442,7 @@ namespace {
DeleteArgs.add(Traits::get(CGF, Ptr), FPT->getParamType(FirstNonTypeArg));
// Figure out what other parameters we should be implicitly passing.
- UsualDeleteParams Params;
+ DeleteParamInfo Params;
if (NumPlacementArgs) {
// A placement deallocation function is implicitly passed an alignment
// if the placement allocation function was, but is never passed a size.
@@ -1505,7 +1453,7 @@ namespace {
} else {
// For a non-placement new-expression, 'operator delete' can take a
// size and/or an alignment if it has the right parameters.
- Params = getUsualDeleteParams(OperatorDelete);
+ Params = OperatorDelete->getDeleteParamInfo();
}
assert(!Params.DestroyingDelete &&
@@ -1838,7 +1786,7 @@ void CodeGenFunction::EmitDeleteCall(const FunctionDecl *DeleteFD,
const auto *DeleteFTy = DeleteFD->getType()->castAs<FunctionProtoType>();
CallArgList DeleteArgs;
- auto Params = getUsualDeleteParams(DeleteFD);
+ auto Params = DeleteFD->getDeleteParamInfo();
auto ParamTypeIt = DeleteFTy->param_type_begin();
std::optional<llvm::AllocaInst *> TagAlloca;
More information about the cfe-commits
mailing list