[clang] d7e40f3 - [clang][bytecode] Call CheckStore() before activating pointers (#165235)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Oct 27 06:41:25 PDT 2025
Author: Timm Baeder
Date: 2025-10-27T14:41:21+01:00
New Revision: d7e40f3e71654658e249ee481e28aeae0e0410b1
URL: https://github.com/llvm/llvm-project/commit/d7e40f3e71654658e249ee481e28aeae0e0410b1
DIFF: https://github.com/llvm/llvm-project/commit/d7e40f3e71654658e249ee481e28aeae0e0410b1.diff
LOG: [clang][bytecode] Call CheckStore() before activating pointers (#165235)
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
Added:
Modified:
clang/lib/AST/ByteCode/Interp.cpp
clang/lib/AST/ByteCode/Interp.h
clang/test/AST/ByteCode/unions.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index df74d80495783..d640be032b4f6 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
More information about the cfe-commits
mailing list