[clang] [clang][bytecode] Call CheckStore() before activating pointers (PR #165235)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Oct 27 03:55:09 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Timm Baeder (tbaederr)
<details>
<summary>Changes</summary>
We used to do this the other way around to work around an awkwardness with CheckStore, namely that we shouldn't check pointers for being activated when activating them.
Add a parameter to CheckStore instead and call CheckStore() _before_ activating and initializing the pointers in the respective opcode implementations.
Fixes https://github.com/llvm/llvm-project/issues/164975
---
Full diff: https://github.com/llvm/llvm-project/pull/165235.diff
3 Files Affected:
- (modified) clang/lib/AST/ByteCode/Interp.cpp (+3-2)
- (modified) clang/lib/AST/ByteCode/Interp.h (+13-11)
- (modified) clang/test/AST/ByteCode/unions.cpp (+9)
``````````diff
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index 910868b27f48e..0e2ba3c5e82d2 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -870,7 +870,8 @@ bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
return true;
}
-bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
+bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
+ bool WillBeActivated) {
if (!Ptr.isBlockPointer() || Ptr.isZero())
return false;
@@ -885,7 +886,7 @@ bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
return false;
if (!CheckRange(S, OpPC, Ptr, AK_Assign))
return false;
- if (!CheckActive(S, OpPC, Ptr, AK_Assign))
+ if (!WillBeActivated && !CheckActive(S, OpPC, Ptr, AK_Assign))
return false;
if (!CheckGlobal(S, OpPC, Ptr))
return false;
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 89f6fbefb1907..43c3ab76b15f9 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -75,7 +75,8 @@ bool CheckGlobalLoad(InterpState &S, CodePtr OpPC, const Block *B);
bool CheckLocalLoad(InterpState &S, CodePtr OpPC, const Block *B);
/// Checks if a value can be stored in a block.
-bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
+bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
+ bool WillBeActivated = false);
/// Checks if a value can be initialized.
bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
@@ -1977,13 +1978,12 @@ bool StoreActivate(InterpState &S, CodePtr OpPC) {
const T &Value = S.Stk.pop<T>();
const Pointer &Ptr = S.Stk.peek<Pointer>();
+ if (!CheckStore(S, OpPC, Ptr, /*WilLBeActivated=*/true))
+ return false;
if (Ptr.canBeInitialized()) {
Ptr.initialize();
Ptr.activate();
}
-
- if (!CheckStore(S, OpPC, Ptr))
- return false;
Ptr.deref<T>() = Value;
return true;
}
@@ -1993,12 +1993,12 @@ bool StoreActivatePop(InterpState &S, CodePtr OpPC) {
const T &Value = S.Stk.pop<T>();
const Pointer &Ptr = S.Stk.pop<Pointer>();
+ if (!CheckStore(S, OpPC, Ptr, /*WilLBeActivated=*/true))
+ return false;
if (Ptr.canBeInitialized()) {
Ptr.initialize();
Ptr.activate();
}
- if (!CheckStore(S, OpPC, Ptr))
- return false;
Ptr.deref<T>() = Value;
return true;
}
@@ -2007,7 +2007,8 @@ template <PrimType Name, class T = typename PrimConv<Name>::T>
bool StoreBitField(InterpState &S, CodePtr OpPC) {
const T &Value = S.Stk.pop<T>();
const Pointer &Ptr = S.Stk.peek<Pointer>();
- if (!CheckStore(S, OpPC, Ptr))
+
+ if (!CheckStore(S, OpPC, Ptr, /*WilLBeActivated=*/true))
return false;
if (Ptr.canBeInitialized())
Ptr.initialize();
@@ -2037,12 +2038,13 @@ template <PrimType Name, class T = typename PrimConv<Name>::T>
bool StoreBitFieldActivate(InterpState &S, CodePtr OpPC) {
const T &Value = S.Stk.pop<T>();
const Pointer &Ptr = S.Stk.peek<Pointer>();
+
+ if (!CheckStore(S, OpPC, Ptr, /*WilLBeActivated=*/true))
+ return false;
if (Ptr.canBeInitialized()) {
Ptr.initialize();
Ptr.activate();
}
- if (!CheckStore(S, OpPC, Ptr))
- return false;
if (const auto *FD = Ptr.getField())
Ptr.deref<T>() = Value.truncate(FD->getBitWidthValue());
else
@@ -2055,12 +2057,12 @@ bool StoreBitFieldActivatePop(InterpState &S, CodePtr OpPC) {
const T &Value = S.Stk.pop<T>();
const Pointer &Ptr = S.Stk.pop<Pointer>();
+ if (!CheckStore(S, OpPC, Ptr, /*WillBeActivated=*/true))
+ return false;
if (Ptr.canBeInitialized()) {
Ptr.initialize();
Ptr.activate();
}
- if (!CheckStore(S, OpPC, Ptr))
- return false;
if (const auto *FD = Ptr.getField())
Ptr.deref<T>() = Value.truncate(FD->getBitWidthValue());
else
diff --git a/clang/test/AST/ByteCode/unions.cpp b/clang/test/AST/ByteCode/unions.cpp
index 6bccbda23f468..414070417a02a 100644
--- a/clang/test/AST/ByteCode/unions.cpp
+++ b/clang/test/AST/ByteCode/unions.cpp
@@ -977,4 +977,13 @@ namespace UnionMemberOnePastEnd {
}
static_assert(!b());
}
+
+namespace ActicvateInvalidPtr {
+ constexpr void bar() { // both-error {{never produces a constant expression}}
+ union {
+ int a[1];
+ } foo;
+ foo.a[1] = 0; // both-note {{assignment to dereferenced one-past-the-end pointer}}
+ }
+}
#endif
``````````
</details>
https://github.com/llvm/llvm-project/pull/165235
More information about the cfe-commits
mailing list