Skip to content

Commit

Permalink
[clang][Interp] Check pointer inc/dec ops for initialization
Browse files Browse the repository at this point in the history
Differential Revision: https://reviews.llvm.org/D158702
  • Loading branch information
tbaederr committed Sep 15, 2023
1 parent 3ebf3dd commit 177f9ab
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 30 deletions.
18 changes: 14 additions & 4 deletions clang/lib/AST/Interp/Interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>());
Expand All @@ -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.
Expand Down
88 changes: 62 additions & 26 deletions clang/test/AST/Interp/literals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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}}
Expand Down

0 comments on commit 177f9ab

Please sign in to comment.