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())
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;
/// 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);
/// 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);
}
/// 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);
}
/// 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);
}
/// 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);
}
}
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);
}
}
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}}