diff --git a/clang/lib/AST/Interp/Boolean.h b/clang/lib/AST/Interp/Boolean.h index c3ed3d61f76ca..336f7941dfc47 100644 --- a/clang/lib/AST/Interp/Boolean.h +++ b/clang/lib/AST/Interp/Boolean.h @@ -42,6 +42,7 @@ class Boolean final { bool operator>(unsigned RHS) const { return static_cast(V) > RHS; } Boolean operator-() const { return Boolean(V); } + Boolean operator-(const Boolean &Other) const { return Boolean(V - Other.V); } Boolean operator~() const { return Boolean(true); } explicit operator int8_t() const { return V; } diff --git a/clang/lib/AST/Interp/Integral.h b/clang/lib/AST/Interp/Integral.h index 4dbe9c9bcb14b..cc1cab8f39fb1 100644 --- a/clang/lib/AST/Interp/Integral.h +++ b/clang/lib/AST/Interp/Integral.h @@ -88,6 +88,9 @@ template class Integral final { } Integral operator-() const { return Integral(-V); } + Integral operator-(const Integral &Other) const { + return Integral(V - Other.V); + } Integral operator~() const { return Integral(~V); } template diff --git a/clang/lib/AST/Interp/IntegralAP.h b/clang/lib/AST/Interp/IntegralAP.h index f9a33bbcd7bd7..f17fb8e484415 100644 --- a/clang/lib/AST/Interp/IntegralAP.h +++ b/clang/lib/AST/Interp/IntegralAP.h @@ -59,6 +59,9 @@ template class IntegralAP final { IntegralAP() : V(APSInt::getMaxValue(1024, Signed)) {} IntegralAP operator-() const { return IntegralAP(-V); } + IntegralAP operator-(const IntegralAP &Other) const { + return IntegralAP(V - Other.V); + } bool operator>(IntegralAP RHS) const { return V > RHS.V; } bool operator>=(IntegralAP RHS) const { return V >= RHS.V; } bool operator<(IntegralAP RHS) const { return V < RHS.V; } diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index 1ad3b8bfc7711..e3e6a4cec63b1 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -1421,7 +1421,7 @@ bool OffsetHelper(InterpState &S, CodePtr OpPC, const T &Offset, // Get a version of the index comparable to the type. T Index = T::from(Ptr.getIndex(), Offset.bitWidth()); // Compute the largest index into the array. - unsigned MaxIndex = Ptr.getNumElems(); + T MaxIndex = T::from(Ptr.getNumElems(), Offset.bitWidth()); // Helper to report an invalid offset, computed as APSInt. auto InvalidOffset = [&]() { @@ -1437,7 +1437,7 @@ bool OffsetHelper(InterpState &S, CodePtr OpPC, const T &Offset, return false; }; - unsigned MaxOffset = MaxIndex - Ptr.getIndex(); + T MaxOffset = T::from(MaxIndex - Index, Offset.bitWidth()); if constexpr (Op == ArithOp::Add) { // If the new offset would be negative, bail out. if (Offset.isNegative() && (Offset.isMin() || -Offset > Index)) diff --git a/clang/test/AST/Interp/intap.cpp b/clang/test/AST/Interp/intap.cpp index 8fe65a69a4fee..f9cbc698a3290 100644 --- a/clang/test/AST/Interp/intap.cpp +++ b/clang/test/AST/Interp/intap.cpp @@ -90,4 +90,14 @@ namespace i128 { // expected-error {{must be initialized by a constant expression}} \ // expected-note {{is outside the range of representable values of type}} } + +namespace AddSubOffset { + constexpr __int128 A = 1; + constexpr int arr[] = {1,2,3}; + constexpr const int *P = arr + A; + static_assert(*P == 2, ""); + constexpr const int *P2 = P - A; + static_assert(*P2 == 1,""); +} + #endif