From b22adf02a2d2cc290d618fe47bec5aeec47ab992 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Sat, 13 Jul 2024 15:14:58 +0200 Subject: [PATCH] [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. --- clang/lib/AST/Interp/InterpState.cpp | 10 +++++++++- clang/lib/AST/Interp/Pointer.h | 1 + clang/test/AST/Interp/lifetimes.cpp | 13 +++++++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/clang/lib/AST/Interp/InterpState.cpp b/clang/lib/AST/Interp/InterpState.cpp index 550bc9f1a84b97..a8538541f49150 100644 --- a/clang/lib/AST/Interp/InterpState.cpp +++ b/clang/lib/AST/Interp/InterpState.cpp @@ -33,7 +33,15 @@ InterpState::~InterpState() { } } -void InterpState::cleanup() {} +void InterpState::cleanup() { + // As a last resort, make sure all pointers still pointing to a dead block + // don't point to it anymore. + for (DeadBlock *DB = DeadBlocks; DB; DB = DB->Next) { + for (Pointer *P = DB->B.Pointers; P; P = P->Next) { + P->PointeeStorage.BS.Pointee = nullptr; + } + } +} Frame *InterpState::getCurrentFrame() { if (Current && Current->Caller) diff --git a/clang/lib/AST/Interp/Pointer.h b/clang/lib/AST/Interp/Pointer.h index 3515f525a22fea..6e9e8675306ef1 100644 --- a/clang/lib/AST/Interp/Pointer.h +++ b/clang/lib/AST/Interp/Pointer.h @@ -635,6 +635,7 @@ class Pointer { friend class Block; friend class DeadBlock; friend class MemberPointer; + friend class InterpState; friend struct InitMap; Pointer(Block *Pointee, unsigned Base, uint64_t Offset); diff --git a/clang/test/AST/Interp/lifetimes.cpp b/clang/test/AST/Interp/lifetimes.cpp index c544baba6178cb..d47533ab547b36 100644 --- a/clang/test/AST/Interp/lifetimes.cpp +++ b/clang/test/AST/Interp/lifetimes.cpp @@ -1,6 +1,8 @@ // RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=expected,both %s // RUN: %clang_cc1 -verify=ref,both %s +/// FIXME: Slight difference in diagnostic output here. + struct Foo { int a; }; @@ -20,3 +22,14 @@ static_assert(dead1() == 1, ""); // both-error {{not an integral constant expres // both-note {{in call to}} +struct S { + int &&r; // both-note {{reference member declared here}} + int t; + 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}} \ + // ref-note {{read of object outside its lifetime is not allowed in a constant expression}} \ + // expected-note {{temporary created here}} \ + // expected-note {{read of temporary whose lifetime has ended}} +}; +constexpr int k1 = S().t; // both-error {{must be initialized by a constant expression}} \ + // ref-note {{in call to}} \ + // expected-note {{in call to}}