Author: Timm Baeder Date: 2026-01-05T10:59:38+01:00 New Revision: 24f0c26dd05da17a809b4c48d8ee2e9448ed7af8
URL: https://github.com/llvm/llvm-project/commit/24f0c26dd05da17a809b4c48d8ee2e9448ed7af8 DIFF: https://github.com/llvm/llvm-project/commit/24f0c26dd05da17a809b4c48d8ee2e9448ed7af8.diff LOG: [clang][bytecode] Check inc/dec operations for constness (#174276) Added: Modified: clang/lib/AST/ByteCode/Interp.h clang/test/AST/ByteCode/literals.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index 9accbbc1605a9..155d96fc1652b 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -777,6 +777,8 @@ bool Inc(InterpState &S, CodePtr OpPC, bool CanOverflow) { const Pointer &Ptr = S.Stk.pop<Pointer>(); if (!CheckLoad(S, OpPC, Ptr, AK_Increment)) return false; + if (!CheckConst(S, OpPC, Ptr)) + return false; return IncDecHelper<T, IncDecOp::Inc, PushVal::Yes>(S, OpPC, Ptr, CanOverflow); @@ -788,6 +790,8 @@ bool IncBitfield(InterpState &S, CodePtr OpPC, bool CanOverflow, const Pointer &Ptr = S.Stk.pop<Pointer>(); if (!CheckLoad(S, OpPC, Ptr, AK_Increment)) return false; + if (!CheckConst(S, OpPC, Ptr)) + return false; return IncDecHelper<T, IncDecOp::Inc, PushVal::Yes>(S, OpPC, Ptr, CanOverflow, BitWidth); @@ -801,6 +805,8 @@ bool IncPop(InterpState &S, CodePtr OpPC, bool CanOverflow) { const Pointer &Ptr = S.Stk.pop<Pointer>(); if (!CheckLoad(S, OpPC, Ptr, AK_Increment)) return false; + if (!CheckConst(S, OpPC, Ptr)) + return false; return IncDecHelper<T, IncDecOp::Inc, PushVal::No>(S, OpPC, Ptr, CanOverflow); } @@ -811,6 +817,8 @@ bool IncPopBitfield(InterpState &S, CodePtr OpPC, bool CanOverflow, const Pointer &Ptr = S.Stk.pop<Pointer>(); if (!CheckLoad(S, OpPC, Ptr, AK_Increment)) return false; + if (!CheckConst(S, OpPC, Ptr)) + return false; return IncDecHelper<T, IncDecOp::Inc, PushVal::No>(S, OpPC, Ptr, CanOverflow, BitWidth); @@ -821,6 +829,8 @@ bool PreInc(InterpState &S, CodePtr OpPC, bool CanOverflow) { const Pointer &Ptr = S.Stk.peek<Pointer>(); if (!CheckLoad(S, OpPC, Ptr, AK_Increment)) return false; + if (!CheckConst(S, OpPC, Ptr)) + return false; return IncDecHelper<T, IncDecOp::Inc, PushVal::No>(S, OpPC, Ptr, CanOverflow); } @@ -831,6 +841,8 @@ bool PreIncBitfield(InterpState &S, CodePtr OpPC, bool CanOverflow, const Pointer &Ptr = S.Stk.peek<Pointer>(); if (!CheckLoad(S, OpPC, Ptr, AK_Increment)) return false; + if (!CheckConst(S, OpPC, Ptr)) + return false; return IncDecHelper<T, IncDecOp::Inc, PushVal::No>(S, OpPC, Ptr, CanOverflow, BitWidth); @@ -845,6 +857,8 @@ bool Dec(InterpState &S, CodePtr OpPC, bool CanOverflow) { const Pointer &Ptr = S.Stk.pop<Pointer>(); if (!CheckLoad(S, OpPC, Ptr, AK_Decrement)) return false; + if (!CheckConst(S, OpPC, Ptr)) + return false; return IncDecHelper<T, IncDecOp::Dec, PushVal::Yes>(S, OpPC, Ptr, CanOverflow); @@ -855,6 +869,8 @@ bool DecBitfield(InterpState &S, CodePtr OpPC, bool CanOverflow, const Pointer &Ptr = S.Stk.pop<Pointer>(); if (!CheckLoad(S, OpPC, Ptr, AK_Decrement)) return false; + if (!CheckConst(S, OpPC, Ptr)) + return false; return IncDecHelper<T, IncDecOp::Dec, PushVal::Yes>(S, OpPC, Ptr, CanOverflow, BitWidth); @@ -868,6 +884,8 @@ bool DecPop(InterpState &S, CodePtr OpPC, bool CanOverflow) { const Pointer &Ptr = S.Stk.pop<Pointer>(); if (!CheckLoad(S, OpPC, Ptr, AK_Decrement)) return false; + if (!CheckConst(S, OpPC, Ptr)) + return false; return IncDecHelper<T, IncDecOp::Dec, PushVal::No>(S, OpPC, Ptr, CanOverflow); } @@ -878,6 +896,8 @@ bool DecPopBitfield(InterpState &S, CodePtr OpPC, bool CanOverflow, const Pointer &Ptr = S.Stk.pop<Pointer>(); if (!CheckLoad(S, OpPC, Ptr, AK_Decrement)) return false; + if (!CheckConst(S, OpPC, Ptr)) + return false; return IncDecHelper<T, IncDecOp::Dec, PushVal::No>(S, OpPC, Ptr, CanOverflow, BitWidth); @@ -888,6 +908,8 @@ bool PreDec(InterpState &S, CodePtr OpPC, bool CanOverflow) { const Pointer &Ptr = S.Stk.peek<Pointer>(); if (!CheckLoad(S, OpPC, Ptr, AK_Decrement)) return false; + if (!CheckConst(S, OpPC, Ptr)) + return false; return IncDecHelper<T, IncDecOp::Dec, PushVal::No>(S, OpPC, Ptr, CanOverflow); } @@ -897,6 +919,8 @@ bool PreDecBitfield(InterpState &S, CodePtr OpPC, bool CanOverflow, const Pointer &Ptr = S.Stk.peek<Pointer>(); if (!CheckLoad(S, OpPC, Ptr, AK_Decrement)) return false; + if (!CheckConst(S, OpPC, Ptr)) + return false; return IncDecHelper<T, IncDecOp::Dec, PushVal::No>(S, OpPC, Ptr, CanOverflow, BitWidth); } @@ -926,6 +950,8 @@ inline bool Incf(InterpState &S, CodePtr OpPC, uint32_t FPOI) { const Pointer &Ptr = S.Stk.pop<Pointer>(); if (!CheckLoad(S, OpPC, Ptr, AK_Increment)) return false; + if (!CheckConst(S, OpPC, Ptr)) + return false; return IncDecFloatHelper<IncDecOp::Inc, PushVal::Yes>(S, OpPC, Ptr, FPOI); } @@ -934,6 +960,8 @@ inline bool IncfPop(InterpState &S, CodePtr OpPC, uint32_t FPOI) { const Pointer &Ptr = S.Stk.pop<Pointer>(); if (!CheckLoad(S, OpPC, Ptr, AK_Increment)) return false; + if (!CheckConst(S, OpPC, Ptr)) + return false; return IncDecFloatHelper<IncDecOp::Inc, PushVal::No>(S, OpPC, Ptr, FPOI); } @@ -942,6 +970,8 @@ inline bool Decf(InterpState &S, CodePtr OpPC, uint32_t FPOI) { const Pointer &Ptr = S.Stk.pop<Pointer>(); if (!CheckLoad(S, OpPC, Ptr, AK_Decrement)) return false; + if (!CheckConst(S, OpPC, Ptr)) + return false; return IncDecFloatHelper<IncDecOp::Dec, PushVal::Yes>(S, OpPC, Ptr, FPOI); } @@ -950,6 +980,8 @@ inline bool DecfPop(InterpState &S, CodePtr OpPC, uint32_t FPOI) { const Pointer &Ptr = S.Stk.pop<Pointer>(); if (!CheckLoad(S, OpPC, Ptr, AK_Decrement)) return false; + if (!CheckConst(S, OpPC, Ptr)) + return false; return IncDecFloatHelper<IncDecOp::Dec, PushVal::No>(S, OpPC, Ptr, FPOI); } diff --git a/clang/test/AST/ByteCode/literals.cpp b/clang/test/AST/ByteCode/literals.cpp index c6d79f9c60058..d637eccc448c4 100644 --- a/clang/test/AST/ByteCode/literals.cpp +++ b/clang/test/AST/ByteCode/literals.cpp @@ -866,7 +866,62 @@ namespace IncDec { // both-note {{function parameter 'a' with unknown value cannot be used in a constant expression}} } -}; + namespace Const { + constexpr int test1(const int a) { + ((int&)a)++; // both-note {{modification of object of const-qualified type 'const int'}} + return a; + } + static_assert(test1(12) == 10); // both-error {{not an integral constant expression}} \ + // both-note {{in call to}} + + constexpr int test2(const int a) { + ++((int&)a); // both-note {{modification of object of const-qualified type 'const int'}} + return a; + } + static_assert(test2(12) == 10); // both-error {{not an integral constant expression}} \ + // both-note {{in call to}} + constexpr int test3(const int a) { + ((int&)a)--; // both-note {{modification of object of const-qualified type 'const int'}} + return a; + } + static_assert(test3(12) == 10); // both-error {{not an integral constant expression}} \ + // both-note {{in call to}} + + constexpr int test4(const int a) { + --((int&)a); // both-note {{modification of object of const-qualified type 'const int'}} + return a; + } + static_assert(test4(12) == 10); // both-error {{not an integral constant expression}} \ + // both-note {{in call to}} + + constexpr int test5(const int a) { + int b = ((int&)a)++; // both-note {{modification of object of const-qualified type 'const int'}} + return a; + } + static_assert(test5(12) == 10); // both-error {{not an integral constant expression}} \ + // both-note {{in call to}} + + constexpr int test6(const int a) { + int b = ++((int&)a); // both-note {{modification of object of const-qualified type 'const int'}} + return a; + } + static_assert(test6(12) == 10); // both-error {{not an integral constant expression}} \ + // both-note {{in call to}} + constexpr int test7(const int a) { + int b = ((int&)a)--; // both-note {{modification of object of const-qualified type 'const int'}} + return a; + } + static_assert(test7(12) == 10); // both-error {{not an integral constant expression}} \ + // both-note {{in call to}} + + constexpr int test8(const int a) { + int b = --((int&)a); // both-note {{modification of object of const-qualified type 'const int'}} + return a; + } + static_assert(test8(12) == 10); // both-error {{not an integral constant expression}} \ + // both-note {{in call to}} + } +} #endif namespace CompoundLiterals { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
