@@ -1857,8 +1857,23 @@ bool OffsetHelper(InterpState &S, CodePtr OpPC, const T &Offset,
18571857 else
18581858 S.Stk .push <Pointer>(V - O, Ptr.asIntPointer ().Desc );
18591859 return true ;
1860+ } else if (Ptr.isFunctionPointer ()) {
1861+ uint64_t O = static_cast <uint64_t >(Offset);
1862+ uint64_t N;
1863+ if constexpr (Op == ArithOp::Add)
1864+ N = Ptr.getByteOffset () + O;
1865+ else
1866+ N = Ptr.getByteOffset () - O;
1867+
1868+ if (N > 1 )
1869+ S.CCEDiag (S.Current ->getSource (OpPC), diag::note_constexpr_array_index)
1870+ << N << /* non-array*/ true << 0 ;
1871+ S.Stk .push <Pointer>(Ptr.asFunctionPointer ().getFunction (), N);
1872+ return true ;
18601873 }
18611874
1875+ assert (Ptr.isBlockPointer ());
1876+
18621877 uint64_t MaxIndex = static_cast <uint64_t >(Ptr.getNumElems ());
18631878 uint64_t Index;
18641879 if (Ptr.isOnePastEnd ())
@@ -2024,10 +2039,15 @@ inline bool SubPtr(InterpState &S, CodePtr OpPC) {
20242039 return true ;
20252040 }
20262041
2027- T A = LHS.isElementPastEnd () ? T::from (LHS.getNumElems ())
2028- : T::from (LHS.getIndex ());
2029- T B = RHS.isElementPastEnd () ? T::from (RHS.getNumElems ())
2030- : T::from (RHS.getIndex ());
2042+ T A = LHS.isBlockPointer ()
2043+ ? (LHS.isElementPastEnd () ? T::from (LHS.getNumElems ())
2044+ : T::from (LHS.getIndex ()))
2045+ : T::from (LHS.getIntegerRepresentation ());
2046+ T B = RHS.isBlockPointer ()
2047+ ? (RHS.isElementPastEnd () ? T::from (RHS.getNumElems ())
2048+ : T::from (RHS.getIndex ()))
2049+ : T::from (RHS.getIntegerRepresentation ());
2050+
20312051 return AddSubMulHelper<T, T::sub, std::minus>(S, OpPC, A.bitWidth (), A, B);
20322052}
20332053
@@ -2905,8 +2925,15 @@ inline bool DecayPtr(InterpState &S, CodePtr OpPC) {
29052925
29062926 if constexpr (std::is_same_v<FromT, FunctionPointer> &&
29072927 std::is_same_v<ToT, Pointer>) {
2908- S.Stk .push <Pointer>(OldPtr.getFunction ());
2928+ S.Stk .push <Pointer>(OldPtr.getFunction (), OldPtr. getOffset () );
29092929 return true ;
2930+ } else if constexpr (std::is_same_v<FromT, Pointer> &&
2931+ std::is_same_v<ToT, FunctionPointer>) {
2932+ if (OldPtr.isFunctionPointer ()) {
2933+ S.Stk .push <FunctionPointer>(OldPtr.asFunctionPointer ().getFunction (),
2934+ OldPtr.getByteOffset ());
2935+ return true ;
2936+ }
29102937 }
29112938
29122939 S.Stk .push <ToT>(ToT (OldPtr.getIntegerRepresentation (), nullptr ));
0 commit comments