[clang] 24f0c26 - [clang][bytecode] Check inc/dec operations for constness (#174276)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Jan 5 01:59:41 PST 2026
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 {
More information about the cfe-commits
mailing list