Skip to content

Commit

Permalink
[clang][Interp] Check inc/dec family of ops for initialization
Browse files Browse the repository at this point in the history
Differential Revision: https://reviews.llvm.org/D149846
  • Loading branch information
tbaederr committed Jun 16, 2023
1 parent dddf66f commit 459f495
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 24 deletions.
23 changes: 12 additions & 11 deletions clang/lib/AST/Interp/Interp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,6 @@ static bool Jf(InterpState &S, CodePtr &PC, int32_t Offset) {
return true;
}

static bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
AccessKinds AK) {
if (Ptr.isInitialized())
return true;
if (!S.checkingPotentialConstantExpression()) {
const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc, diag::note_constexpr_access_uninit) << AK << false;
}
return false;
}

static bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
AccessKinds AK) {
if (Ptr.isActive())
Expand Down Expand Up @@ -243,6 +232,18 @@ bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
return false;
}

bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
AccessKinds AK) {
if (Ptr.isInitialized())
return true;

if (!S.checkingPotentialConstantExpression()) {
const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc, diag::note_constexpr_access_uninit) << AK << false;
}
return false;
}

bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
if (!CheckLive(S, OpPC, Ptr, AK_Read))
return false;
Expand Down
39 changes: 31 additions & 8 deletions clang/lib/AST/Interp/Interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
/// Checks if a value can be loaded from a block.
bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr);

bool CheckInitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
AccessKinds AK);

/// Checks if a value can be stored in a block.
bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr);

Expand Down Expand Up @@ -501,9 +504,11 @@ bool IncDecHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
/// 4) Pushes the original (pre-inc) value on the stack.
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool Inc(InterpState &S, CodePtr OpPC) {
// FIXME: Check initialization of Ptr
const Pointer &Ptr = S.Stk.pop<Pointer>();

if (!CheckInitialized(S, OpPC, Ptr, AK_Increment))
return false;

return IncDecHelper<T, IncDecOp::Inc, PushVal::Yes>(S, OpPC, Ptr);
}

Expand All @@ -512,9 +517,11 @@ bool Inc(InterpState &S, CodePtr OpPC) {
/// 3) Writes the value increased by one back to the pointer
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool IncPop(InterpState &S, CodePtr OpPC) {
// FIXME: Check initialization of Ptr
const Pointer &Ptr = S.Stk.pop<Pointer>();

if (!CheckInitialized(S, OpPC, Ptr, AK_Increment))
return false;

return IncDecHelper<T, IncDecOp::Inc, PushVal::No>(S, OpPC, Ptr);
}

Expand All @@ -524,9 +531,11 @@ bool IncPop(InterpState &S, CodePtr OpPC) {
/// 4) Pushes the original (pre-dec) value on the stack.
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool Dec(InterpState &S, CodePtr OpPC) {
// FIXME: Check initialization of Ptr
const Pointer &Ptr = S.Stk.pop<Pointer>();

if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement))
return false;

return IncDecHelper<T, IncDecOp::Dec, PushVal::Yes>(S, OpPC, Ptr);
}

Expand All @@ -535,9 +544,11 @@ bool Dec(InterpState &S, CodePtr OpPC) {
/// 3) Writes the value decreased by one back to the pointer
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool DecPop(InterpState &S, CodePtr OpPC) {
// FIXME: Check initialization of Ptr
const Pointer &Ptr = S.Stk.pop<Pointer>();

if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement))
return false;

return IncDecHelper<T, IncDecOp::Dec, PushVal::No>(S, OpPC, Ptr);
}

Expand All @@ -562,26 +573,38 @@ bool IncDecFloatHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
}

inline bool Incf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
// FIXME: Check initialization of Ptr
const Pointer &Ptr = S.Stk.pop<Pointer>();

if (!CheckInitialized(S, OpPC, Ptr, AK_Increment))
return false;

return IncDecFloatHelper<IncDecOp::Inc, PushVal::Yes>(S, OpPC, Ptr, RM);
}

inline bool IncfPop(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
// FIXME: Check initialization of Ptr
const Pointer &Ptr = S.Stk.pop<Pointer>();

if (!CheckInitialized(S, OpPC, Ptr, AK_Increment))
return false;

return IncDecFloatHelper<IncDecOp::Inc, PushVal::No>(S, OpPC, Ptr, RM);
}

inline bool Decf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
// FIXME: Check initialization of Ptr
const Pointer &Ptr = S.Stk.pop<Pointer>();

if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement))
return false;

return IncDecFloatHelper<IncDecOp::Dec, PushVal::Yes>(S, OpPC, Ptr, RM);
}

inline bool DecfPop(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
// FIXME: Check initialization of Ptr
const Pointer &Ptr = S.Stk.pop<Pointer>();

if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement))
return false;

return IncDecFloatHelper<IncDecOp::Dec, PushVal::No>(S, OpPC, Ptr, RM);
}

Expand Down
32 changes: 27 additions & 5 deletions clang/test/AST/Interp/literals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -462,14 +462,36 @@ namespace IncDec {
}
static_assert(incBool(), "");

template<typename T, bool Inc>
constexpr int uninit() {
int a;
++a; // ref-note {{increment of uninitialized}} \
// FIXME: Should also be rejected by new interpreter
T a;
if constexpr (Inc)
++a; // ref-note 2{{increment of uninitialized}} \
// expected-note 2{{increment of object outside its lifetime}}
else
--a; // ref-note 2{{decrement of uninitialized}} \
// expected-note 2{{decrement of object outside its lifetime}}
return 1;
}
static_assert(uninit(), ""); // ref-error {{not an integral constant expression}} \
// ref-note {{in call to 'uninit()'}}
static_assert(uninit<int, true>(), ""); // ref-error {{not an integral constant expression}} \
// ref-note {{in call to 'uninit()'}} \
// 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()'}} \
// 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()'}} \
// 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()'}} \
// 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 459f495

Please sign in to comment.