[clang] 56dab2c - [clang][Interp] Fix truncateCast() (#69911)

via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 30 08:27:52 PDT 2023


Author: Timm Baeder
Date: 2023-10-30T16:27:47+01:00
New Revision: 56dab2cb0733f10df4e9cff8c83dd7081154527b

URL: https://github.com/llvm/llvm-project/commit/56dab2cb0733f10df4e9cff8c83dd7081154527b
DIFF: https://github.com/llvm/llvm-project/commit/56dab2cb0733f10df4e9cff8c83dd7081154527b.diff

LOG: [clang][Interp] Fix truncateCast() (#69911)

The added test case used to fail because we converted the LHS to `-1`.

Added: 
    

Modified: 
    clang/lib/AST/Interp/IntegralAP.h
    clang/test/AST/Interp/intap.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/Interp/IntegralAP.h b/clang/lib/AST/Interp/IntegralAP.h
index cfed9ca29336d2e..9aefea6d0c47ed9 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();
@@ -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);

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 {


        


More information about the cfe-commits mailing list