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 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
