Skip to content

Commit 58d60a4

Browse files
authored
[clang][bytecode] Diagnose destroying already dead locals (#137357)
1 parent 9bf7023 commit 58d60a4

File tree

2 files changed

+31
-2
lines changed

2 files changed

+31
-2
lines changed

clang/lib/AST/ByteCode/Interp.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2197,6 +2197,21 @@ inline bool SubPtr(InterpState &S, CodePtr OpPC) {
21972197
//===----------------------------------------------------------------------===//
21982198

21992199
inline bool Destroy(InterpState &S, CodePtr OpPC, uint32_t I) {
2200+
assert(S.Current->getFunction());
2201+
2202+
// FIXME: We iterate the scope once here and then again in the destroy() call
2203+
// below.
2204+
for (auto &Local : S.Current->getFunction()->getScope(I).locals_reverse()) {
2205+
const Pointer &Ptr = S.Current->getLocalPointer(Local.Offset);
2206+
2207+
if (Ptr.getLifetime() == Lifetime::Ended) {
2208+
auto *D = cast<NamedDecl>(Ptr.getFieldDesc()->asDecl());
2209+
S.FFDiag(D->getLocation(), diag::note_constexpr_destroy_out_of_lifetime)
2210+
<< D->getNameAsString();
2211+
return false;
2212+
}
2213+
}
2214+
22002215
S.Current->destroy(I);
22012216
return true;
22022217
}

clang/test/AST/ByteCode/lifetimes.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=expected,both %s
2-
// RUN: %clang_cc1 -verify=ref,both %s
1+
// RUN: %clang_cc1 -verify=expected,both -std=c++20 %s -fexperimental-new-constant-interpreter
2+
// RUN: %clang_cc1 -verify=ref,both -std=c++20 %s
33

44
/// FIXME: Slight difference in diagnostic output here.
55

@@ -68,3 +68,17 @@ namespace PrimitiveMoveFn {
6868
const float &x = y;
6969
}
7070
}
71+
72+
/// FIXME:
73+
/// 1) This doesn't work for parameters
74+
/// 2) We need to do this for all fields in composite scenarios
75+
namespace PseudoDtor {
76+
typedef int I;
77+
constexpr bool foo() { // both-error {{never produces a constant expression}}
78+
{
79+
int a; // both-note {{destroying object 'a' whose lifetime has already ended}}
80+
a.~I();
81+
}
82+
return true;
83+
}
84+
}

0 commit comments

Comments
 (0)