[clang] [clang][Interp] Fix truncateCast() (PR #69911)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Oct 23 03:19:47 PDT 2023
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Timm Baeder (tbaederr)
<details>
<summary>Changes</summary>
The added test case used to fail because we converted the LHS to `-1`.
---
Full diff: https://github.com/llvm/llvm-project/pull/69911.diff
2 Files Affected:
- (modified) clang/lib/AST/Interp/IntegralAP.h (+25-11)
- (modified) clang/test/AST/Interp/intap.cpp (+3)
``````````diff
diff --git a/clang/lib/AST/Interp/IntegralAP.h b/clang/lib/AST/Interp/IntegralAP.h
index 45e5b49546270aa..98d4dae8fa4df0e 100644
--- a/clang/lib/AST/Interp/IntegralAP.h
+++ b/clang/lib/AST/Interp/IntegralAP.h
@@ -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();
@@ -81,14 +89,20 @@ template <bool Signed> class IntegralAP final {
}
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); }
+ explicit operator int8_t() const { return truncateCast<int8_t, Signed>(V); }
+ explicit operator uint8_t() const { return truncateCast<uint8_t, Signed>(V); }
+ explicit operator int16_t() const { return truncateCast<int16_t, Signed>(V); }
+ explicit operator uint16_t() const {
+ return truncateCast<uint16_t, Signed>(V);
+ }
+ explicit operator int32_t() const { return truncateCast<int32_t, Signed>(V); }
+ explicit operator uint32_t() const {
+ return truncateCast<uint32_t, Signed>(V);
+ }
+ explicit operator int64_t() const { return truncateCast<int64_t, Signed>(V); }
+ explicit operator uint64_t() const {
+ return truncateCast<uint64_t, Signed>(V);
+ }
template <typename T> static IntegralAP from(T Value, unsigned NumBits = 0) {
assert(NumBits > 0);
diff --git a/clang/test/AST/Interp/intap.cpp b/clang/test/AST/Interp/intap.cpp
index 27fae1b904351ce..02a860eb0986c15 100644
--- a/clang/test/AST/Interp/intap.cpp
+++ b/clang/test/AST/Interp/intap.cpp
@@ -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 {
``````````
</details>
https://github.com/llvm/llvm-project/pull/69911
More information about the cfe-commits
mailing list