Skip to content

Commit b22adf0

Browse files
committed
[clang][Interp] Clear pointers pointing to dead blocks
before free()ing the dead blocks. Otherwise, we might end up with dangling Pointers to those dead blocks.
1 parent 80e61e3 commit b22adf0

File tree

3 files changed

+23
-1
lines changed

3 files changed

+23
-1
lines changed

clang/lib/AST/Interp/InterpState.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,15 @@ InterpState::~InterpState() {
3333
}
3434
}
3535

36-
void InterpState::cleanup() {}
36+
void InterpState::cleanup() {
37+
// As a last resort, make sure all pointers still pointing to a dead block
38+
// don't point to it anymore.
39+
for (DeadBlock *DB = DeadBlocks; DB; DB = DB->Next) {
40+
for (Pointer *P = DB->B.Pointers; P; P = P->Next) {
41+
P->PointeeStorage.BS.Pointee = nullptr;
42+
}
43+
}
44+
}
3745

3846
Frame *InterpState::getCurrentFrame() {
3947
if (Current && Current->Caller)

clang/lib/AST/Interp/Pointer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,7 @@ class Pointer {
635635
friend class Block;
636636
friend class DeadBlock;
637637
friend class MemberPointer;
638+
friend class InterpState;
638639
friend struct InitMap;
639640

640641
Pointer(Block *Pointee, unsigned Base, uint64_t Offset);

clang/test/AST/Interp/lifetimes.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=expected,both %s
22
// RUN: %clang_cc1 -verify=ref,both %s
33

4+
/// FIXME: Slight difference in diagnostic output here.
5+
46
struct Foo {
57
int a;
68
};
@@ -20,3 +22,14 @@ static_assert(dead1() == 1, ""); // both-error {{not an integral constant expres
2022
// both-note {{in call to}}
2123

2224

25+
struct S {
26+
int &&r; // both-note {{reference member declared here}}
27+
int t;
28+
constexpr S() : r(0), t(r) {} // both-error {{reference member 'r' binds to a temporary object whose lifetime would be shorter than the lifetime of the constructed object}} \
29+
// ref-note {{read of object outside its lifetime is not allowed in a constant expression}} \
30+
// expected-note {{temporary created here}} \
31+
// expected-note {{read of temporary whose lifetime has ended}}
32+
};
33+
constexpr int k1 = S().t; // both-error {{must be initialized by a constant expression}} \
34+
// ref-note {{in call to}} \
35+
// expected-note {{in call to}}

0 commit comments

Comments
 (0)