Skip to content

Commit 16c721f

Browse files
authored
[clang][bytecode] Destroy local variables in reverse order (#125727)
See the attached test case.
1 parent e90f9b4 commit 16c721f

File tree

3 files changed

+29
-1
lines changed

3 files changed

+29
-1
lines changed

clang/lib/AST/ByteCode/Function.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ class Scope final {
5151
return llvm::make_range(Descriptors.begin(), Descriptors.end());
5252
}
5353

54+
llvm::iterator_range<LocalVectorTy::const_reverse_iterator>
55+
locals_reverse() const {
56+
return llvm::reverse(Descriptors);
57+
}
58+
5459
private:
5560
/// Object descriptors in this block.
5661
LocalVectorTy Descriptors;

clang/lib/AST/ByteCode/InterpFrame.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ void InterpFrame::initScope(unsigned Idx) {
9999
}
100100

101101
void InterpFrame::destroy(unsigned Idx) {
102-
for (auto &Local : Func->getScope(Idx).locals()) {
102+
for (auto &Local : Func->getScope(Idx).locals_reverse()) {
103103
S.deallocate(localBlock(Local.Offset));
104104
}
105105
}

clang/test/AST/ByteCode/cxx20.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -908,3 +908,26 @@ namespace TemporaryInNTTP {
908908
// expected-note {{created here}}
909909
B<2> j2; /// Ok.
910910
}
911+
912+
namespace LocalDestroy {
913+
/// This is reduced from a libc++ test case.
914+
/// The local f.TI.copied points to the local variable Copied, and we used to
915+
/// destroy Copied before f, causing problems later on when a DeadBlock had a
916+
/// pointer pointing to it that was already destroyed.
917+
struct TrackInitialization {
918+
bool *copied_;
919+
};
920+
struct TrackingPred : TrackInitialization {
921+
constexpr TrackingPred(bool *copied) : TrackInitialization(copied) {}
922+
};
923+
struct F {
924+
const TrackingPred &TI;
925+
};
926+
constexpr int f() {
927+
bool Copied = false;
928+
TrackingPred TI(&Copied);
929+
F f{TI};
930+
return 1;
931+
}
932+
static_assert(f() == 1);
933+
}

0 commit comments

Comments
 (0)