[clang] 177f9ab - [clang][Interp] Check pointer inc/dec ops for initialization
Timm Bäder via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 15 04:04:42 PDT 2023
Author: Timm Bäder
Date: 2023-09-15T13:04:04+02:00
New Revision: 177f9ab2fbd868fb9cc7d5504e56a241e8e79329
URL: https://github.com/llvm/llvm-project/commit/177f9ab2fbd868fb9cc7d5504e56a241e8e79329
DIFF: https://github.com/llvm/llvm-project/commit/177f9ab2fbd868fb9cc7d5504e56a241e8e79329.diff
LOG: [clang][Interp] Check pointer inc/dec ops for initialization
Differential Revision: https://reviews.llvm.org/D158702
Added:
Modified:
clang/lib/AST/Interp/Interp.h
clang/test/AST/Interp/literals.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index b109f2bda17bfb1..37d3dd0da6568af 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -1441,9 +1441,9 @@ bool SubOffset(InterpState &S, CodePtr OpPC) {
}
template <ArithOp Op>
-static inline bool IncDecPtrHelper(InterpState &S, CodePtr OpPC) {
+static inline bool IncDecPtrHelper(InterpState &S, CodePtr OpPC,
+ const Pointer &Ptr) {
using OneT = Integral<8, false>;
- const Pointer &Ptr = S.Stk.pop<Pointer>();
// Get the current value on the stack.
S.Stk.push<Pointer>(Ptr.deref<Pointer>());
@@ -1460,11 +1460,21 @@ static inline bool IncDecPtrHelper(InterpState &S, CodePtr OpPC) {
}
static inline bool IncPtr(InterpState &S, CodePtr OpPC) {
- return IncDecPtrHelper<ArithOp::Add>(S, OpPC);
+ const Pointer &Ptr = S.Stk.pop<Pointer>();
+
+ if (!CheckInitialized(S, OpPC, Ptr, AK_Increment))
+ return false;
+
+ return IncDecPtrHelper<ArithOp::Add>(S, OpPC, Ptr);
}
static inline bool DecPtr(InterpState &S, CodePtr OpPC) {
- return IncDecPtrHelper<ArithOp::Sub>(S, OpPC);
+ const Pointer &Ptr = S.Stk.pop<Pointer>();
+
+ if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement))
+ return false;
+
+ return IncDecPtrHelper<ArithOp::Sub>(S, OpPC, Ptr);
}
/// 1) Pops a Pointer from the stack.
diff --git a/clang/test/AST/Interp/literals.cpp b/clang/test/AST/Interp/literals.cpp
index dae1d5af6f7ae38..1a12413f3f0fa8e 100644
--- a/clang/test/AST/Interp/literals.cpp
+++ b/clang/test/AST/Interp/literals.cpp
@@ -509,36 +509,72 @@ namespace IncDec {
}
static_assert(incBool(), "");
- template<typename T, bool Inc>
+ /// FIXME: The diagnostics for pre-inc/dec of pointers doesn't match the
+ /// current interpreter. But they are stil OK.
+ template<typename T, bool Inc, bool Pre>
constexpr int uninit() {
T a;
- if constexpr (Inc)
- ++a; // ref-note 2{{increment of uninitialized}} \
- // expected-note 2{{increment of uninitialized}}
- else
- --a; // ref-note 2{{decrement of uninitialized}} \
- // expected-note 2{{decrement of uninitialized}}
+ if constexpr (Inc) {
+ if (Pre)
+ ++a; // ref-note 3{{increment of uninitialized}} \
+ // expected-note 2{{increment of uninitialized}} \
+ // expected-note {{read of uninitialized}}
+ else
+ a++; // ref-note 2{{increment of uninitialized}} \
+ // expected-note 2{{increment of uninitialized}}
+ } else {
+ if (Pre)
+ --a; // ref-note 3{{decrement of uninitialized}} \
+ // expected-note 2{{decrement of uninitialized}} \
+ // expected-note {{read of uninitialized}}
+ else
+ a--; // ref-note 2{{decrement of uninitialized}} \
+ // expected-note 2{{decrement of uninitialized}}
+ }
return 1;
}
- static_assert(uninit<int, true>(), ""); // ref-error {{not an integral constant expression}} \
- // ref-note {{in call to 'uninit<int, true>()'}} \
- // expected-error {{not an integral constant expression}} \
- // expected-note {{in call to 'uninit()'}}
-
- static_assert(uninit<int, false>(), ""); // ref-error {{not an integral constant expression}} \
- // ref-note {{in call to 'uninit<int, false>()'}} \
- // expected-error {{not an integral constant expression}} \
- // expected-note {{in call to 'uninit()'}}
-
- static_assert(uninit<float, true>(), ""); // ref-error {{not an integral constant expression}} \
- // ref-note {{in call to 'uninit<float, true>()'}} \
- // expected-error {{not an integral constant expression}} \
- // expected-note {{in call to 'uninit()'}}
-
- static_assert(uninit<float, false>(), ""); // ref-error {{not an integral constant expression}} \
- // ref-note {{in call to 'uninit<float, false>()'}} \
- // expected-error {{not an integral constant expression}} \
- // expected-note {{in call to 'uninit()'}}
+ static_assert(uninit<int, true, true>(), ""); // ref-error {{not an integral constant expression}} \
+ // ref-note {{in call to 'uninit<int, true, true>()'}} \
+ // expected-error {{not an integral constant expression}} \
+ // expected-note {{in call to 'uninit()'}}
+ static_assert(uninit<int, false, true>(), ""); // ref-error {{not an integral constant expression}} \
+ // ref-note {{in call to 'uninit<int, false, true>()'}} \
+ // expected-error {{not an integral constant expression}} \
+ // expected-note {{in call to 'uninit()'}}
+
+ static_assert(uninit<float, true, true>(), ""); // ref-error {{not an integral constant expression}} \
+ // ref-note {{in call to 'uninit<float, true, true>()'}} \
+ // expected-error {{not an integral constant expression}} \
+ // expected-note {{in call to 'uninit()'}}
+ static_assert(uninit<float, false, true>(), ""); // ref-error {{not an integral constant expression}} \
+ // ref-note {{in call to 'uninit<float, false, true>()'}} \
+ // expected-error {{not an integral constant expression}} \
+ // expected-note {{in call to 'uninit()'}}
+ static_assert(uninit<float, true, false>(), ""); // ref-error {{not an integral constant expression}} \
+ // ref-note {{in call to 'uninit<float, true, false>()'}} \
+ // expected-error {{not an integral constant expression}} \
+ // expected-note {{in call to 'uninit()'}}
+ static_assert(uninit<float, false, false>(), ""); // ref-error {{not an integral constant expression}} \
+ // ref-note {{in call to 'uninit<float, false, false>()'}} \
+ // expected-error {{not an integral constant expression}} \
+ // expected-note {{in call to 'uninit()'}}
+
+ static_assert(uninit<int*, true, true>(), ""); // ref-error {{not an integral constant expression}} \
+ // ref-note {{in call to 'uninit<int *, true, true>()'}} \
+ // expected-error {{not an integral constant expression}} \
+ // expected-note {{in call to 'uninit()'}}
+ static_assert(uninit<int*, false, true>(), ""); // ref-error {{not an integral constant expression}} \
+ // ref-note {{in call to 'uninit<int *, false, true>()'}} \
+ // expected-error {{not an integral constant expression}} \
+ // expected-note {{in call to 'uninit()'}}
+ static_assert(uninit<int*, true, false>(), ""); // ref-error {{not an integral constant expression}} \
+ // ref-note {{in call to 'uninit<int *, true, false>()'}} \
+ // expected-error {{not an integral constant expression}} \
+ // expected-note {{in call to 'uninit()'}}
+ static_assert(uninit<int*, false, false>(), ""); // ref-error {{not an integral constant expression}} \
+ // ref-note {{in call to 'uninit<int *, false, false>()'}} \
+ // expected-error {{not an integral constant expression}} \
+ // expected-note {{in call to 'uninit()'}}
constexpr int OverFlow() { // ref-error {{never produces a constant expression}} \
// expected-error {{never produces a constant expression}}
More information about the cfe-commits
mailing list