[clang] [clang][bytecode] Destroy local variables in reverse order (PR #125727)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Tue Feb 4 10:06:43 PST 2025
https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/125727
>From 58faf5d42f02fc570a72c9af2d90282bae9fe834 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Tue, 4 Feb 2025 18:08:00 +0100
Subject: [PATCH] [clang][bytecode] Destroy local variables in reverse order
See the attached test case.
---
clang/lib/AST/ByteCode/Function.h | 5 +++++
clang/lib/AST/ByteCode/InterpFrame.cpp | 2 +-
clang/test/AST/ByteCode/cxx20.cpp | 23 +++++++++++++++++++++++
3 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/clang/lib/AST/ByteCode/Function.h b/clang/lib/AST/ByteCode/Function.h
index 2d3421e5e612950..e17183eef9eac64 100644
--- a/clang/lib/AST/ByteCode/Function.h
+++ b/clang/lib/AST/ByteCode/Function.h
@@ -51,6 +51,11 @@ class Scope final {
return llvm::make_range(Descriptors.begin(), Descriptors.end());
}
+ llvm::iterator_range<LocalVectorTy::const_reverse_iterator>
+ locals_reverse() const {
+ return llvm::reverse(Descriptors);
+ }
+
private:
/// Object descriptors in this block.
LocalVectorTy Descriptors;
diff --git a/clang/lib/AST/ByteCode/InterpFrame.cpp b/clang/lib/AST/ByteCode/InterpFrame.cpp
index 89fc7a4515d6416..c383b2bc7f95ce1 100644
--- a/clang/lib/AST/ByteCode/InterpFrame.cpp
+++ b/clang/lib/AST/ByteCode/InterpFrame.cpp
@@ -99,7 +99,7 @@ void InterpFrame::initScope(unsigned Idx) {
}
void InterpFrame::destroy(unsigned Idx) {
- for (auto &Local : Func->getScope(Idx).locals()) {
+ for (auto &Local : Func->getScope(Idx).locals_reverse()) {
S.deallocate(localBlock(Local.Offset));
}
}
diff --git a/clang/test/AST/ByteCode/cxx20.cpp b/clang/test/AST/ByteCode/cxx20.cpp
index 268226a7c143ed8..a63aea1ea5548bc 100644
--- a/clang/test/AST/ByteCode/cxx20.cpp
+++ b/clang/test/AST/ByteCode/cxx20.cpp
@@ -908,3 +908,26 @@ namespace TemporaryInNTTP {
// expected-note {{created here}}
B<2> j2; /// Ok.
}
+
+namespace LocalDestroy {
+ /// This is reduced from a libc++ test case.
+ /// The local f.TI.copied points to the local variable Copied, and we used to
+ /// destroy Copied before f, causing problems later on when a DeadBlock had a
+ /// pointer pointing to it that was already destroyed.
+ struct TrackInitialization {
+ bool *copied_;
+ };
+ struct TrackingPred : TrackInitialization {
+ constexpr TrackingPred(bool *copied) : TrackInitialization(copied) {}
+ };
+ struct F {
+ const TrackingPred &TI;
+ };
+ constexpr int f() {
+ bool Copied = false;
+ TrackingPred TI(&Copied);
+ F f{TI};
+ return 1;
+ }
+ static_assert(f() == 1);
+}
More information about the cfe-commits
mailing list