[clang] [clang][bytecode] Call CheckLocalLoad in GetLocal (PR #152090)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Aug 4 23:01:02 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Timm Baeder (tbaederr)
<details>
<summary>Changes</summary>
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.
---
Full diff: https://github.com/llvm/llvm-project/pull/152090.diff
3 Files Affected:
- (modified) clang/lib/AST/ByteCode/Interp.cpp (+2)
- (modified) clang/lib/AST/ByteCode/Interp.h (+1-1)
- (modified) clang/test/AST/ByteCode/cxx2a.cpp (+38)
``````````diff
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index f2366f674f45b..eb4e4800d44ae 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -752,6 +752,8 @@ bool CheckGlobalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
// Similarly, for local loads.
bool CheckLocalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
+ if (!CheckLifetime(S, OpPC, Ptr, AK_Read))
+ return false;
if (!CheckInitialized(S, OpPC, Ptr, AK_Read))
return false;
if (!CheckVolatile(S, OpPC, Ptr, AK_Read))
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 61e776965a006..8a28106c0583a 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -1352,7 +1352,7 @@ inline bool ConstFloat(InterpState &S, CodePtr OpPC, const Floating &F) {
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool GetLocal(InterpState &S, CodePtr OpPC, uint32_t I) {
const Pointer &Ptr = S.Current->getLocalPointer(I);
- if (!CheckLoad(S, OpPC, Ptr))
+ if (!CheckLocalLoad(S, OpPC, Ptr))
return false;
S.Stk.push<T>(Ptr.deref<T>());
return true;
diff --git a/clang/test/AST/ByteCode/cxx2a.cpp b/clang/test/AST/ByteCode/cxx2a.cpp
index d9541aca225b9..ac2f9883d49b6 100644
--- a/clang/test/AST/ByteCode/cxx2a.cpp
+++ b/clang/test/AST/ByteCode/cxx2a.cpp
@@ -1,6 +1,25 @@
// RUN: %clang_cc1 -std=c++2a -fsyntax-only -fcxx-exceptions -verify=ref,both %s
// RUN: %clang_cc1 -std=c++2a -fsyntax-only -fcxx-exceptions -verify=expected,both %s -fexperimental-new-constant-interpreter
+
+namespace std {
+ struct type_info;
+ struct destroying_delete_t {
+ explicit destroying_delete_t() = default;
+ } inline constexpr destroying_delete{};
+ struct nothrow_t {
+ explicit nothrow_t() = default;
+ } inline constexpr nothrow{};
+ using size_t = decltype(sizeof(0));
+ enum class align_val_t : size_t {};
+};
+
+constexpr void *operator new(std::size_t, void *p) { return p; }
+namespace std {
+ template<typename T> constexpr T *construct(T *p) { return new (p) T; }
+ template<typename T> constexpr void destroy(T *p) { p->~T(); }
+}
+
template <unsigned N>
struct S {
S() requires (N==1) = default;
@@ -187,3 +206,22 @@ namespace PureVirtual {
struct PureVirtualCall : Abstract { void f(); }; // both-note {{in call to 'Abstract}}
constexpr PureVirtualCall pure_virtual_call; // both-error {{constant expression}} both-note {{in call to 'PureVirtualCall}}
}
+
+namespace Dtor {
+ constexpr bool pseudo(bool read, bool recreate) {
+ using T = bool;
+ bool b = false; // both-note {{lifetime has already ended}}
+ // This evaluates the store to 'b'...
+ (b = true).~T();
+ // ... and ends the lifetime of the object.
+ return (read
+ ? b // both-note {{read of object outside its lifetime}}
+ : true) +
+ (recreate
+ ? (std::construct(&b), true)
+ : true);
+ }
+ static_assert(pseudo(false, false)); // both-error {{constant expression}} both-note {{in call}}
+ static_assert(pseudo(true, false)); // both-error {{constant expression}} both-note {{in call}}
+ static_assert(pseudo(false, true));
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/152090
More information about the cfe-commits
mailing list