@@ -765,7 +765,8 @@ enum class IncDecOp {
765765};
766766
767767template <typename T, IncDecOp Op, PushVal DoPush>
768- bool IncDecHelper (InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
768+ bool IncDecHelper (InterpState &S, CodePtr OpPC, const Pointer &Ptr,
769+ bool CanOverflow) {
769770 assert (!Ptr.isDummy ());
770771
771772 if constexpr (std::is_same_v<T, Boolean>) {
@@ -780,16 +781,17 @@ bool IncDecHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
780781 S.Stk .push <T>(Value);
781782
782783 if constexpr (Op == IncDecOp::Inc) {
783- if (!T::increment (Value, &Result)) {
784+ if (!T::increment (Value, &Result) || !CanOverflow ) {
784785 Ptr.deref <T>() = Result;
785786 return true ;
786787 }
787788 } else {
788- if (!T::decrement (Value, &Result)) {
789+ if (!T::decrement (Value, &Result) || !CanOverflow ) {
789790 Ptr.deref <T>() = Result;
790791 return true ;
791792 }
792793 }
794+ assert (CanOverflow);
793795
794796 // Something went wrong with the previous operation. Compute the
795797 // result with another bit of precision.
@@ -812,7 +814,6 @@ bool IncDecHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
812814 << Trunc << Type << E->getSourceRange ();
813815 return true ;
814816 }
815-
816817 return handleOverflow (S, OpPC, APResult);
817818}
818819
@@ -821,49 +822,69 @@ bool IncDecHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr) {
821822// / 3) Writes the value increased by one back to the pointer
822823// / 4) Pushes the original (pre-inc) value on the stack.
823824template <PrimType Name, class T = typename PrimConv<Name>::T>
824- bool Inc (InterpState &S, CodePtr OpPC) {
825+ bool Inc (InterpState &S, CodePtr OpPC, bool CanOverflow ) {
825826 const Pointer &Ptr = S.Stk .pop <Pointer>();
826827 if (!CheckLoad (S, OpPC, Ptr, AK_Increment))
827828 return false ;
828829
829- return IncDecHelper<T, IncDecOp::Inc, PushVal::Yes>(S, OpPC, Ptr);
830+ return IncDecHelper<T, IncDecOp::Inc, PushVal::Yes>(S, OpPC, Ptr,
831+ CanOverflow);
830832}
831833
832834// / 1) Pops a pointer from the stack
833835// / 2) Load the value from the pointer
834836// / 3) Writes the value increased by one back to the pointer
835837template <PrimType Name, class T = typename PrimConv<Name>::T>
836- bool IncPop (InterpState &S, CodePtr OpPC) {
838+ bool IncPop (InterpState &S, CodePtr OpPC, bool CanOverflow ) {
837839 const Pointer &Ptr = S.Stk .pop <Pointer>();
838840 if (!CheckLoad (S, OpPC, Ptr, AK_Increment))
839841 return false ;
840842
841- return IncDecHelper<T, IncDecOp::Inc, PushVal::No>(S, OpPC, Ptr);
843+ return IncDecHelper<T, IncDecOp::Inc, PushVal::No>(S, OpPC, Ptr, CanOverflow);
844+ }
845+
846+ template <PrimType Name, class T = typename PrimConv<Name>::T>
847+ bool PreInc (InterpState &S, CodePtr OpPC, bool CanOverflow) {
848+ const Pointer &Ptr = S.Stk .peek <Pointer>();
849+ if (!CheckLoad (S, OpPC, Ptr, AK_Increment))
850+ return false ;
851+
852+ return IncDecHelper<T, IncDecOp::Inc, PushVal::No>(S, OpPC, Ptr, CanOverflow);
842853}
843854
844855// / 1) Pops a pointer from the stack
845856// / 2) Load the value from the pointer
846857// / 3) Writes the value decreased by one back to the pointer
847858// / 4) Pushes the original (pre-dec) value on the stack.
848859template <PrimType Name, class T = typename PrimConv<Name>::T>
849- bool Dec (InterpState &S, CodePtr OpPC) {
860+ bool Dec (InterpState &S, CodePtr OpPC, bool CanOverflow ) {
850861 const Pointer &Ptr = S.Stk .pop <Pointer>();
851862 if (!CheckLoad (S, OpPC, Ptr, AK_Decrement))
852863 return false ;
853864
854- return IncDecHelper<T, IncDecOp::Dec, PushVal::Yes>(S, OpPC, Ptr);
865+ return IncDecHelper<T, IncDecOp::Dec, PushVal::Yes>(S, OpPC, Ptr,
866+ CanOverflow);
855867}
856868
857869// / 1) Pops a pointer from the stack
858870// / 2) Load the value from the pointer
859871// / 3) Writes the value decreased by one back to the pointer
860872template <PrimType Name, class T = typename PrimConv<Name>::T>
861- bool DecPop (InterpState &S, CodePtr OpPC) {
873+ bool DecPop (InterpState &S, CodePtr OpPC, bool CanOverflow ) {
862874 const Pointer &Ptr = S.Stk .pop <Pointer>();
863875 if (!CheckLoad (S, OpPC, Ptr, AK_Decrement))
864876 return false ;
865877
866- return IncDecHelper<T, IncDecOp::Dec, PushVal::No>(S, OpPC, Ptr);
878+ return IncDecHelper<T, IncDecOp::Dec, PushVal::No>(S, OpPC, Ptr, CanOverflow);
879+ }
880+
881+ template <PrimType Name, class T = typename PrimConv<Name>::T>
882+ bool PreDec (InterpState &S, CodePtr OpPC, bool CanOverflow) {
883+ const Pointer &Ptr = S.Stk .peek <Pointer>();
884+ if (!CheckLoad (S, OpPC, Ptr, AK_Decrement))
885+ return false ;
886+
887+ return IncDecHelper<T, IncDecOp::Dec, PushVal::No>(S, OpPC, Ptr, CanOverflow);
867888}
868889
869890template <IncDecOp Op, PushVal DoPush>
0 commit comments