Skip to content

Commit

Permalink
[clang][Interp] Implement IntegralAP subtraction (#71648)
Browse files Browse the repository at this point in the history
  • Loading branch information
tbaederr committed Nov 16, 2023
1 parent ce7fd49 commit 6416b2d
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 20 deletions.
32 changes: 12 additions & 20 deletions clang/lib/AST/Interp/IntegralAP.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,12 +191,11 @@ template <bool Signed> class IntegralAP final {
}

static bool add(IntegralAP A, IntegralAP B, unsigned OpBits, IntegralAP *R) {
return CheckAddUB(A, B, OpBits, R);
return CheckAddSubUB<std::plus>(A, B, OpBits, R);
}

static bool sub(IntegralAP A, IntegralAP B, unsigned OpBits, IntegralAP *R) {
/// FIXME: Gotta check if the result fits into OpBits bits.
return CheckSubUB(A, B, R);
return CheckAddSubUB<std::minus>(A, B, OpBits, R);
}

static bool mul(IntegralAP A, IntegralAP B, unsigned OpBits, IntegralAP *R) {
Expand Down Expand Up @@ -264,28 +263,21 @@ template <bool Signed> class IntegralAP final {
}

private:
static bool CheckAddUB(const IntegralAP &A, const IntegralAP &B,
unsigned BitWidth, IntegralAP *R) {
if (!A.isSigned()) {
R->V = A.V + B.V;
template <template <typename T> class Op>
static bool CheckAddSubUB(const IntegralAP &A, const IntegralAP &B,
unsigned BitWidth, IntegralAP *R) {
if constexpr (!Signed) {
R->V = Op<APInt>{}(A.V, B.V);
return false;
}

const APSInt &LHS = APSInt(A.V, A.isSigned());
const APSInt &RHS = APSInt(B.V, B.isSigned());

APSInt Value(LHS.extend(BitWidth) + RHS.extend(BitWidth), false);
const APSInt &LHS = A.toAPSInt();
const APSInt &RHS = B.toAPSInt();
APSInt Value = Op<APSInt>{}(LHS.extend(BitWidth), RHS.extend(BitWidth));
APSInt Result = Value.trunc(LHS.getBitWidth());
if (Result.extend(BitWidth) != Value)
return true;

R->V = Result;
return false;
}
static bool CheckSubUB(const IntegralAP &A, const IntegralAP &B,
IntegralAP *R) {
R->V = A.V - B.V;
return false; // Success!

return Result.extend(BitWidth) != Value;
}
};

Expand Down
15 changes: 15 additions & 0 deletions clang/test/AST/Interp/intap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ constexpr _BitInt(2) B = A + 1;
constexpr _BitInt(2) C = B + 1; // expected-warning {{from 2 to -2}} \
// ref-warning {{from 2 to -2}}
static_assert(C == -2, "");
static_assert(C - B == A, ""); // expected-error {{not an integral constant expression}} \
// expected-note {{value -3 is outside the range of representable values}} \
// ref-error {{not an integral constant expression}} \
// ref-note {{value -3 is outside the range of representable values}}

static_assert(B - 1 == 0, "");

constexpr MaxBitInt A_ = 0;
constexpr MaxBitInt B_ = A_ + 1;
Expand Down Expand Up @@ -130,6 +135,16 @@ namespace i128 {
// expected-warning {{implicit conversion of out of range value}} \
// expected-error {{must be initialized by a constant expression}} \
// expected-note {{is outside the range of representable values of type}}

constexpr uint128_t Zero = 0;
static_assert((Zero -1) == -1, "");
constexpr int128_t Five = 5;
static_assert(Five - Zero == Five, "");

constexpr int128_t Sub1 = INT128_MIN - 1; // expected-error {{must be initialized by a constant expression}} \
// expected-note {{-170141183460469231731687303715884105729 is outside the range}} \
// ref-error {{must be initialized by a constant expression}} \
// ref-note {{-170141183460469231731687303715884105729 is outside the range}}
}

namespace AddSubOffset {
Expand Down

0 comments on commit 6416b2d

Please sign in to comment.