@@ -2066,34 +2066,32 @@ inline bool CastMemberPtrPtr(InterpState &S, CodePtr OpPC) {
20662066// ===----------------------------------------------------------------------===//
20672067
20682068template <class T , ArithOp Op>
2069- bool OffsetHelper (InterpState &S, CodePtr OpPC, const T &Offset,
2070- const Pointer &Ptr, bool IsPointerArith = false ) {
2069+ std::optional<Pointer> OffsetHelper (InterpState &S, CodePtr OpPC,
2070+ const T &Offset, const Pointer &Ptr,
2071+ bool IsPointerArith = false ) {
20712072 // A zero offset does not change the pointer.
2072- if (Offset.isZero ()) {
2073- S.Stk .push <Pointer>(Ptr);
2074- return true ;
2075- }
2073+ if (Offset.isZero ())
2074+ return Ptr;
20762075
20772076 if (IsPointerArith && !CheckNull (S, OpPC, Ptr, CSK_ArrayIndex)) {
20782077 // The CheckNull will have emitted a note already, but we only
20792078 // abort in C++, since this is fine in C.
20802079 if (S.getLangOpts ().CPlusPlus )
2081- return false ;
2080+ return std:: nullopt ;
20822081 }
20832082
20842083 // Arrays of unknown bounds cannot have pointers into them.
20852084 if (!CheckArray (S, OpPC, Ptr))
2086- return false ;
2085+ return std:: nullopt ;
20872086
20882087 // This is much simpler for integral pointers, so handle them first.
20892088 if (Ptr.isIntegralPointer ()) {
20902089 uint64_t V = Ptr.getIntegerRepresentation ();
20912090 uint64_t O = static_cast <uint64_t >(Offset) * Ptr.elemSize ();
20922091 if constexpr (Op == ArithOp::Add)
2093- S. Stk . push < Pointer> (V + O, Ptr.asIntPointer ().Desc );
2092+ return Pointer (V + O, Ptr.asIntPointer ().Desc );
20942093 else
2095- S.Stk .push <Pointer>(V - O, Ptr.asIntPointer ().Desc );
2096- return true ;
2094+ return Pointer (V - O, Ptr.asIntPointer ().Desc );
20972095 } else if (Ptr.isFunctionPointer ()) {
20982096 uint64_t O = static_cast <uint64_t >(Offset);
20992097 uint64_t N;
@@ -2105,8 +2103,7 @@ bool OffsetHelper(InterpState &S, CodePtr OpPC, const T &Offset,
21052103 if (N > 1 )
21062104 S.CCEDiag (S.Current ->getSource (OpPC), diag::note_constexpr_array_index)
21072105 << N << /* non-array*/ true << 0 ;
2108- S.Stk .push <Pointer>(Ptr.asFunctionPointer ().getFunction (), N);
2109- return true ;
2106+ return Pointer (Ptr.asFunctionPointer ().getFunction (), N);
21102107 }
21112108
21122109 assert (Ptr.isBlockPointer ());
@@ -2156,7 +2153,7 @@ bool OffsetHelper(InterpState &S, CodePtr OpPC, const T &Offset,
21562153 }
21572154
21582155 if (Invalid && S.getLangOpts ().CPlusPlus )
2159- return false ;
2156+ return std:: nullopt ;
21602157
21612158 // Offset is valid - compute it on unsigned.
21622159 int64_t WideIndex = static_cast <int64_t >(Index);
@@ -2172,15 +2169,11 @@ bool OffsetHelper(InterpState &S, CodePtr OpPC, const T &Offset,
21722169 // we don't get here.
21732170 if (Result == 0 && Ptr.isOnePastEnd ()) {
21742171 if (Ptr.getFieldDesc ()->isArray ())
2175- S.Stk .push <Pointer>(Ptr.atIndex (0 ));
2176- else
2177- S.Stk .push <Pointer>(Ptr.asBlockPointer ().Pointee ,
2178- Ptr.asBlockPointer ().Base );
2179- return true ;
2172+ return Ptr.atIndex (0 );
2173+ return Pointer (Ptr.asBlockPointer ().Pointee , Ptr.asBlockPointer ().Base );
21802174 }
21812175
2182- S.Stk .push <Pointer>(Ptr.atIndex (static_cast <uint64_t >(Result)));
2183- return true ;
2176+ return Ptr.atIndex (static_cast <uint64_t >(Result));
21842177}
21852178
21862179template <PrimType Name, class T = typename PrimConv<Name>::T>
@@ -2189,16 +2182,26 @@ bool AddOffset(InterpState &S, CodePtr OpPC) {
21892182 Pointer Ptr = S.Stk .pop <Pointer>();
21902183 if (Ptr.isBlockPointer ())
21912184 Ptr = Ptr.expand ();
2192- return OffsetHelper<T, ArithOp::Add>(S, OpPC, Offset, Ptr,
2193- /* IsPointerArith=*/ true );
2185+
2186+ if (std::optional<Pointer> Result = OffsetHelper<T, ArithOp::Add>(
2187+ S, OpPC, Offset, Ptr, /* IsPointerArith=*/ true )) {
2188+ S.Stk .push <Pointer>(*Result);
2189+ return true ;
2190+ }
2191+ return false ;
21942192}
21952193
21962194template <PrimType Name, class T = typename PrimConv<Name>::T>
21972195bool SubOffset (InterpState &S, CodePtr OpPC) {
21982196 const T &Offset = S.Stk .pop <T>();
21992197 const Pointer &Ptr = S.Stk .pop <Pointer>();
2200- return OffsetHelper<T, ArithOp::Sub>(S, OpPC, Offset, Ptr,
2201- /* IsPointerArith=*/ true );
2198+
2199+ if (std::optional<Pointer> Result = OffsetHelper<T, ArithOp::Sub>(
2200+ S, OpPC, Offset, Ptr, /* IsPointerArith=*/ true )) {
2201+ S.Stk .push <Pointer>(*Result);
2202+ return true ;
2203+ }
2204+ return false ;
22022205}
22032206
22042207template <ArithOp Op>
@@ -2218,12 +2221,13 @@ static inline bool IncDecPtrHelper(InterpState &S, CodePtr OpPC,
22182221
22192222 // Now the current Ptr again and a constant 1.
22202223 OneT One = OneT::from (1 );
2221- if (!OffsetHelper<OneT, Op>(S, OpPC, One, P, /* IsPointerArith=*/ true ))
2222- return false ;
2223-
2224- // Store the new value.
2225- Ptr.deref <Pointer>() = S.Stk .pop <Pointer>();
2226- return true ;
2224+ if (std::optional<Pointer> Result =
2225+ OffsetHelper<OneT, Op>(S, OpPC, One, P, /* IsPointerArith=*/ true )) {
2226+ // Store the new value.
2227+ Ptr.deref <Pointer>() = *Result;
2228+ return true ;
2229+ }
2230+ return false ;
22272231}
22282232
22292233static inline bool IncPtr (InterpState &S, CodePtr OpPC) {
@@ -2925,16 +2929,22 @@ inline bool ArrayElemPtr(InterpState &S, CodePtr OpPC) {
29252929
29262930 if (Offset.isZero ()) {
29272931 if (Ptr.getFieldDesc ()->isArray () && Ptr.getIndex () == 0 ) {
2928- S.Stk .push <Pointer>(Ptr.atIndex (0 ));
2929- } else {
2930- S.Stk .push <Pointer>(Ptr);
2932+ S.Stk .push <Pointer>(Ptr.atIndex (0 ).narrow ());
2933+ return true ;
29312934 }
2932- } else {
2933- if (!OffsetHelper<T, ArithOp::Add>(S, OpPC, Offset, Ptr))
2934- return false ;
2935+ S.Stk .push <Pointer>(Ptr);
2936+ return true ;
2937+ }
2938+
2939+ assert (!Offset.isZero ());
2940+
2941+ if (std::optional<Pointer> Result =
2942+ OffsetHelper<T, ArithOp::Add>(S, OpPC, Offset, Ptr)) {
2943+ S.Stk .push <Pointer>(Result->narrow ());
2944+ return true ;
29352945 }
29362946
2937- return NarrowPtr (S, OpPC) ;
2947+ return false ;
29382948}
29392949
29402950template <PrimType Name, class T = typename PrimConv<Name>::T>
@@ -2949,16 +2959,21 @@ inline bool ArrayElemPtrPop(InterpState &S, CodePtr OpPC) {
29492959
29502960 if (Offset.isZero ()) {
29512961 if (Ptr.getFieldDesc ()->isArray () && Ptr.getIndex () == 0 ) {
2952- S.Stk .push <Pointer>(Ptr.atIndex (0 ));
2953- } else {
2954- S.Stk .push <Pointer>(Ptr);
2962+ S.Stk .push <Pointer>(Ptr.atIndex (0 ).narrow ());
2963+ return true ;
29552964 }
2956- } else {
2957- if (!OffsetHelper<T, ArithOp::Add>(S, OpPC, Offset, Ptr))
2958- return false ;
2965+ S.Stk .push <Pointer>(Ptr);
2966+ return true ;
29592967 }
29602968
2961- return NarrowPtr (S, OpPC);
2969+ assert (!Offset.isZero ());
2970+
2971+ if (std::optional<Pointer> Result =
2972+ OffsetHelper<T, ArithOp::Add>(S, OpPC, Offset, Ptr)) {
2973+ S.Stk .push <Pointer>(Result->narrow ());
2974+ return true ;
2975+ }
2976+ return false ;
29622977}
29632978
29642979template <PrimType Name, class T = typename PrimConv<Name>::T>
0 commit comments