[PATCH] D23362: FIx UB in APInt::ashr

Jonathan Roelofs via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 10 11:08:38 PDT 2016


jroelofs created this revision.
jroelofs added reviewers: majnemer, hfinkel.
jroelofs added a subscriber: llvm-commits.

i64 -1, whose sign bit is the 0th one, can't be left shifted without invoking UB.

https://reviews.llvm.org/D23362

Files:
  lib/Support/APInt.cpp
  unittests/ADT/APIntTest.cpp

Index: unittests/ADT/APIntTest.cpp
===================================================================
--- unittests/ADT/APIntTest.cpp
+++ unittests/ADT/APIntTest.cpp
@@ -32,6 +32,11 @@
   EXPECT_FALSE(Shl[1]);
 }
 
+TEST(APIntTest, i64_ArithmeticRightShiftNegative) {
+  const APInt neg_one(64, static_cast<uint64_t>(-1), true);
+  EXPECT_EQ(neg_one, neg_one.ashr(7));
+}
+
 TEST(APIntTest, i128_NegativeCount) {
   APInt Minus3(128, static_cast<uint64_t>(-3), true);
   EXPECT_EQ(126u, Minus3.countLeadingOnes());
Index: lib/Support/APInt.cpp
===================================================================
--- lib/Support/APInt.cpp
+++ lib/Support/APInt.cpp
@@ -1043,9 +1043,11 @@
     if (shiftAmt == BitWidth)
       return APInt(BitWidth, 0); // undefined
     else {
-      unsigned SignBit = APINT_BITS_PER_WORD - BitWidth;
-      return APInt(BitWidth,
-        (((int64_t(VAL) << SignBit) >> SignBit) >> shiftAmt));
+      if (unsigned SignBit = APINT_BITS_PER_WORD - BitWidth)
+        return APInt(BitWidth,
+          (((int64_t(VAL) << SignBit) >> SignBit) >> shiftAmt));
+      else
+        return APInt(BitWidth, int64_t(VAL) >> shiftAmt);
     }
   }
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D23362.67556.patch
Type: text/x-patch
Size: 1175 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160810/ea37d76e/attachment.bin>


More information about the llvm-commits mailing list