https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/125727
See the attached test case. >From c4eb23f06871536c4df8842b5065fa6f470aa2ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbae...@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/lifetimes.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 2d3421e5e61295..e17183eef9eac6 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 89fc7a4515d641..c383b2bc7f95ce 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/lifetimes.cpp b/clang/test/AST/ByteCode/lifetimes.cpp index 43039d0c766e9e..318bc205c76724 100644 --- a/clang/test/AST/ByteCode/lifetimes.cpp +++ b/clang/test/AST/ByteCode/lifetimes.cpp @@ -68,3 +68,26 @@ namespace PrimitiveMoveFn { const float &x = y; } } + +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); +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits