Skip to content

Commit

Permalink
[clang][Interp] Fix truncateCast() (#69911)
Browse files Browse the repository at this point in the history
The added test case used to fail because we converted the LHS to `-1`.
  • Loading branch information
tbaederr committed Oct 30, 2023
1 parent 849297c commit 56dab2c
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 12 deletions.
27 changes: 15 additions & 12 deletions clang/lib/AST/Interp/IntegralAP.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,18 @@ template <bool Signed> class IntegralAP final {
friend IntegralAP<!Signed>;
APInt V;

template <typename T> static T truncateCast(const APInt &V) {
template <typename T, bool InputSigned>
static T truncateCast(const APInt &V) {
constexpr unsigned BitSize = sizeof(T) * 8;
if (BitSize >= V.getBitWidth())
return std::is_signed_v<T> ? V.getSExtValue() : V.getZExtValue();
if (BitSize >= V.getBitWidth()) {
APInt Extended;
if constexpr (InputSigned)
Extended = V.sext(BitSize);
else
Extended = V.zext(BitSize);
return std::is_signed_v<T> ? Extended.getSExtValue()
: Extended.getZExtValue();
}

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

explicit operator bool() const { return !V.isZero(); }
explicit operator int8_t() const { return truncateCast<int8_t>(V); }
explicit operator uint8_t() const { return truncateCast<uint8_t>(V); }
explicit operator int16_t() const { return truncateCast<int16_t>(V); }
explicit operator uint16_t() const { return truncateCast<uint16_t>(V); }
explicit operator int32_t() const { return truncateCast<int32_t>(V); }
explicit operator uint32_t() const { return truncateCast<uint32_t>(V); }
explicit operator int64_t() const { return truncateCast<int64_t>(V); }
explicit operator uint64_t() const { return truncateCast<uint64_t>(V); }
template <typename Ty, typename = std::enable_if_t<std::is_integral_v<Ty>>>
explicit operator Ty() const {
return truncateCast<Ty, Signed>(V);
}

template <typename T> static IntegralAP from(T Value, unsigned NumBits = 0) {
assert(NumBits > 0);
Expand Down
3 changes: 3 additions & 0 deletions clang/test/AST/Interp/intap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ static_assert(BitIntZero2 == 0, "");
constexpr unsigned _BitInt(1) UBitIntZero1{};
static_assert(UBitIntZero1 == 0, "");

constexpr unsigned _BitInt(2) BI1 = 3u;
static_assert(BI1 == 3, "");


#ifdef __SIZEOF_INT128__
namespace i128 {
Expand Down

0 comments on commit 56dab2c

Please sign in to comment.