Skip to content

Commit 6416b2d

Browse files
authored
[clang][Interp] Implement IntegralAP subtraction (#71648)
1 parent ce7fd49 commit 6416b2d

File tree

2 files changed

+27
-20
lines changed

2 files changed

+27
-20
lines changed

clang/lib/AST/Interp/IntegralAP.h

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -191,12 +191,11 @@ template <bool Signed> class IntegralAP final {
191191
}
192192

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

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

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

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

274-
const APSInt &LHS = APSInt(A.V, A.isSigned());
275-
const APSInt &RHS = APSInt(B.V, B.isSigned());
276-
277-
APSInt Value(LHS.extend(BitWidth) + RHS.extend(BitWidth), false);
274+
const APSInt &LHS = A.toAPSInt();
275+
const APSInt &RHS = B.toAPSInt();
276+
APSInt Value = Op<APSInt>{}(LHS.extend(BitWidth), RHS.extend(BitWidth));
278277
APSInt Result = Value.trunc(LHS.getBitWidth());
279-
if (Result.extend(BitWidth) != Value)
280-
return true;
281-
282278
R->V = Result;
283-
return false;
284-
}
285-
static bool CheckSubUB(const IntegralAP &A, const IntegralAP &B,
286-
IntegralAP *R) {
287-
R->V = A.V - B.V;
288-
return false; // Success!
279+
280+
return Result.extend(BitWidth) != Value;
289281
}
290282
};
291283

clang/test/AST/Interp/intap.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,12 @@ constexpr _BitInt(2) B = A + 1;
1111
constexpr _BitInt(2) C = B + 1; // expected-warning {{from 2 to -2}} \
1212
// ref-warning {{from 2 to -2}}
1313
static_assert(C == -2, "");
14+
static_assert(C - B == A, ""); // expected-error {{not an integral constant expression}} \
15+
// expected-note {{value -3 is outside the range of representable values}} \
16+
// ref-error {{not an integral constant expression}} \
17+
// ref-note {{value -3 is outside the range of representable values}}
1418

19+
static_assert(B - 1 == 0, "");
1520

1621
constexpr MaxBitInt A_ = 0;
1722
constexpr MaxBitInt B_ = A_ + 1;
@@ -130,6 +135,16 @@ namespace i128 {
130135
// expected-warning {{implicit conversion of out of range value}} \
131136
// expected-error {{must be initialized by a constant expression}} \
132137
// expected-note {{is outside the range of representable values of type}}
138+
139+
constexpr uint128_t Zero = 0;
140+
static_assert((Zero -1) == -1, "");
141+
constexpr int128_t Five = 5;
142+
static_assert(Five - Zero == Five, "");
143+
144+
constexpr int128_t Sub1 = INT128_MIN - 1; // expected-error {{must be initialized by a constant expression}} \
145+
// expected-note {{-170141183460469231731687303715884105729 is outside the range}} \
146+
// ref-error {{must be initialized by a constant expression}} \
147+
// ref-note {{-170141183460469231731687303715884105729 is outside the range}}
133148
}
134149

135150
namespace AddSubOffset {

0 commit comments

Comments
 (0)