Skip to content

Commit 56dab2c

Browse files
authored
[clang][Interp] Fix truncateCast() (#69911)
The added test case used to fail because we converted the LHS to `-1`.
1 parent 849297c commit 56dab2c

File tree

2 files changed

+18
-12
lines changed

2 files changed

+18
-12
lines changed

clang/lib/AST/Interp/IntegralAP.h

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,18 @@ template <bool Signed> class IntegralAP final {
3535
friend IntegralAP<!Signed>;
3636
APInt V;
3737

38-
template <typename T> static T truncateCast(const APInt &V) {
38+
template <typename T, bool InputSigned>
39+
static T truncateCast(const APInt &V) {
3940
constexpr unsigned BitSize = sizeof(T) * 8;
40-
if (BitSize >= V.getBitWidth())
41-
return std::is_signed_v<T> ? V.getSExtValue() : V.getZExtValue();
41+
if (BitSize >= V.getBitWidth()) {
42+
APInt Extended;
43+
if constexpr (InputSigned)
44+
Extended = V.sext(BitSize);
45+
else
46+
Extended = V.zext(BitSize);
47+
return std::is_signed_v<T> ? Extended.getSExtValue()
48+
: Extended.getZExtValue();
49+
}
4250

4351
return std::is_signed_v<T> ? V.trunc(BitSize).getSExtValue()
4452
: V.trunc(BitSize).getZExtValue();
@@ -80,15 +88,10 @@ template <bool Signed> class IntegralAP final {
8088
return V.ult(RHS.V);
8189
}
8290

83-
explicit operator bool() const { return !V.isZero(); }
84-
explicit operator int8_t() const { return truncateCast<int8_t>(V); }
85-
explicit operator uint8_t() const { return truncateCast<uint8_t>(V); }
86-
explicit operator int16_t() const { return truncateCast<int16_t>(V); }
87-
explicit operator uint16_t() const { return truncateCast<uint16_t>(V); }
88-
explicit operator int32_t() const { return truncateCast<int32_t>(V); }
89-
explicit operator uint32_t() const { return truncateCast<uint32_t>(V); }
90-
explicit operator int64_t() const { return truncateCast<int64_t>(V); }
91-
explicit operator uint64_t() const { return truncateCast<uint64_t>(V); }
91+
template <typename Ty, typename = std::enable_if_t<std::is_integral_v<Ty>>>
92+
explicit operator Ty() const {
93+
return truncateCast<Ty, Signed>(V);
94+
}
9295

9396
template <typename T> static IntegralAP from(T Value, unsigned NumBits = 0) {
9497
assert(NumBits > 0);

clang/test/AST/Interp/intap.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ static_assert(BitIntZero2 == 0, "");
2727
constexpr unsigned _BitInt(1) UBitIntZero1{};
2828
static_assert(UBitIntZero1 == 0, "");
2929

30+
constexpr unsigned _BitInt(2) BI1 = 3u;
31+
static_assert(BI1 == 3, "");
32+
3033

3134
#ifdef __SIZEOF_INT128__
3235
namespace i128 {

0 commit comments

Comments
 (0)