[clang] [clang][bytecode] Only collect dynamic blocks if we have any dynamic allocations (PR #224887)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Sun Sep 20 00:14:00 PDT 2026
https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/224887
If we don't have any (live) dynamic allocations, we can save ourselves the work of checking all the pointers in the returned value.
Also move the `getAllocator()` call in `Free()` further down so we don' unnecessarily create a dynamic allocator.
>From 6d0727140e45b548c1811d05e60d938ecdbf9cb0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Sun, 20 Sep 2026 07:13:10 +0200
Subject: [PATCH] hasDynamicAllocator
---
clang/lib/AST/ByteCode/EvaluationResult.cpp | 3 +++
clang/lib/AST/ByteCode/Interp.cpp | 5 ++---
clang/lib/AST/ByteCode/InterpState.h | 4 +++-
3 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/clang/lib/AST/ByteCode/EvaluationResult.cpp b/clang/lib/AST/ByteCode/EvaluationResult.cpp
index 09b1eb822b13e2..905cd8cf93c645 100644
--- a/clang/lib/AST/ByteCode/EvaluationResult.cpp
+++ b/clang/lib/AST/ByteCode/EvaluationResult.cpp
@@ -246,6 +246,9 @@ static void collectBlocks(PtrView Ptr,
bool EvaluationResult::checkDynamicAllocations(InterpState &S,
const Pointer &Ptr,
SourceInfo Info) {
+ if (!S.hasDynamicAllocations())
+ return true;
+
if (!Ptr.isBlockPointer())
return true;
// Collect all blocks that this pointer (transitively) points to and
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index 49ebcc789b7dd2..da192d254919a8 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -1474,8 +1474,6 @@ bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm,
if (!CheckDynamicMemoryAllocation(S, OpPC))
return false;
- DynamicAllocator &Allocator = S.getAllocator();
-
const Expr *Source = nullptr;
const Block *BlockToDelete = nullptr;
{
@@ -1500,7 +1498,7 @@ bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm,
// Check that new[]/delete[] or new/delete were used, not a mixture.
const Descriptor *BlockDesc = BlockToDelete->getDescriptor();
if (std::optional<DynamicAllocator::Form> AllocForm =
- Allocator.getAllocationForm(Source)) {
+ S.getAllocator().getAllocationForm(Source)) {
DynamicAllocator::Form DeleteForm =
DeleteIsArrayForm ? DynamicAllocator::Form::Array
: DynamicAllocator::Form::NonArray;
@@ -1560,6 +1558,7 @@ bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm,
if (!RunDestructors(S, OpPC, BlockToDelete))
return false;
+ DynamicAllocator &Allocator = S.getAllocator();
if (!Allocator.deallocate(Source, BlockToDelete)) {
// Nothing has been deallocated, this must be a double-delete.
const SourceInfo &Loc = S.Current->getSource(OpPC);
diff --git a/clang/lib/AST/ByteCode/InterpState.h b/clang/lib/AST/ByteCode/InterpState.h
index 920197d8021c06..b03679ace8eb5a 100644
--- a/clang/lib/AST/ByteCode/InterpState.h
+++ b/clang/lib/AST/ByteCode/InterpState.h
@@ -82,9 +82,11 @@ class InterpState final : public State {
if (!Alloc) {
Alloc = std::make_unique<DynamicAllocator>();
}
-
return *Alloc;
}
+ bool hasDynamicAllocations() const {
+ return Alloc && Alloc->hasAllocations();
+ }
/// Diagnose any dynamic allocations that haven't been freed yet.
/// Will return \c false if there were any allocations to diagnose,
More information about the cfe-commits
mailing list