Skip to content

Commit 8f7dfc6

Browse files
authored
[clang][bytecode] Call CheckLocalLoad in GetLocal (#152090)
I forgot to call this here as well. It was only used in the EvalEmitter implementation of the function. Also fix a problem where we didn't diagnose out-of-lifetime reads here.
1 parent 95d9e8a commit 8f7dfc6

File tree

3 files changed

+41
-1
lines changed

3 files changed

+41
-1
lines changed

clang/lib/AST/ByteCode/Interp.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,8 @@ bool CheckGlobalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
752752

753753
// Similarly, for local loads.
754754
bool CheckLocalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
755+
if (!CheckLifetime(S, OpPC, Ptr, AK_Read))
756+
return false;
755757
if (!CheckInitialized(S, OpPC, Ptr, AK_Read))
756758
return false;
757759
if (!CheckVolatile(S, OpPC, Ptr, AK_Read))

clang/lib/AST/ByteCode/Interp.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1352,7 +1352,7 @@ inline bool ConstFloat(InterpState &S, CodePtr OpPC, const Floating &F) {
13521352
template <PrimType Name, class T = typename PrimConv<Name>::T>
13531353
bool GetLocal(InterpState &S, CodePtr OpPC, uint32_t I) {
13541354
const Pointer &Ptr = S.Current->getLocalPointer(I);
1355-
if (!CheckLoad(S, OpPC, Ptr))
1355+
if (!CheckLocalLoad(S, OpPC, Ptr))
13561356
return false;
13571357
S.Stk.push<T>(Ptr.deref<T>());
13581358
return true;

clang/test/AST/ByteCode/cxx2a.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,25 @@
11
// RUN: %clang_cc1 -std=c++2a -fsyntax-only -fcxx-exceptions -verify=ref,both %s
22
// RUN: %clang_cc1 -std=c++2a -fsyntax-only -fcxx-exceptions -verify=expected,both %s -fexperimental-new-constant-interpreter
33

4+
5+
namespace std {
6+
struct type_info;
7+
struct destroying_delete_t {
8+
explicit destroying_delete_t() = default;
9+
} inline constexpr destroying_delete{};
10+
struct nothrow_t {
11+
explicit nothrow_t() = default;
12+
} inline constexpr nothrow{};
13+
using size_t = decltype(sizeof(0));
14+
enum class align_val_t : size_t {};
15+
};
16+
17+
constexpr void *operator new(std::size_t, void *p) { return p; }
18+
namespace std {
19+
template<typename T> constexpr T *construct(T *p) { return new (p) T; }
20+
template<typename T> constexpr void destroy(T *p) { p->~T(); }
21+
}
22+
423
template <unsigned N>
524
struct S {
625
S() requires (N==1) = default;
@@ -187,3 +206,22 @@ namespace PureVirtual {
187206
struct PureVirtualCall : Abstract { void f(); }; // both-note {{in call to 'Abstract}}
188207
constexpr PureVirtualCall pure_virtual_call; // both-error {{constant expression}} both-note {{in call to 'PureVirtualCall}}
189208
}
209+
210+
namespace Dtor {
211+
constexpr bool pseudo(bool read, bool recreate) {
212+
using T = bool;
213+
bool b = false; // both-note {{lifetime has already ended}}
214+
// This evaluates the store to 'b'...
215+
(b = true).~T();
216+
// ... and ends the lifetime of the object.
217+
return (read
218+
? b // both-note {{read of object outside its lifetime}}
219+
: true) +
220+
(recreate
221+
? (std::construct(&b), true)
222+
: true);
223+
}
224+
static_assert(pseudo(false, false)); // both-error {{constant expression}} both-note {{in call}}
225+
static_assert(pseudo(true, false)); // both-error {{constant expression}} both-note {{in call}}
226+
static_assert(pseudo(false, true));
227+
}

0 commit comments

Comments
 (0)