From 851b79dc4d96c6331093d273fdc51eb3c65cb72b Mon Sep 17 00:00:00 2001 From: Jonathan Roelofs Date: Wed, 10 Aug 2016 19:50:14 +0000 Subject: [PATCH] Fix UB in APInt::ashr i64 -1, whose sign bit is the 0th one, can't be left shifted without invoking UB. https://reviews.llvm.org/D23362 llvm-svn: 278280 --- llvm/lib/Support/APInt.cpp | 6 +----- llvm/unittests/ADT/APIntTest.cpp | 5 +++++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Support/APInt.cpp b/llvm/lib/Support/APInt.cpp index 8c921ce..31ffffc 100644 --- a/llvm/lib/Support/APInt.cpp +++ b/llvm/lib/Support/APInt.cpp @@ -1042,11 +1042,7 @@ APInt APInt::ashr(unsigned shiftAmt) const { if (isSingleWord()) { 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)); - } + return APInt(BitWidth, SignExtend64(VAL, BitWidth) >> shiftAmt); } // If all the bits were shifted out, the result is, technically, undefined. diff --git a/llvm/unittests/ADT/APIntTest.cpp b/llvm/unittests/ADT/APIntTest.cpp index 3a7c2d7..cbffdc0 100644 --- a/llvm/unittests/ADT/APIntTest.cpp +++ b/llvm/unittests/ADT/APIntTest.cpp @@ -32,6 +32,11 @@ TEST(APIntTest, ShiftLeftByZero) { EXPECT_FALSE(Shl[1]); } +TEST(APIntTest, i64_ArithmeticRightShiftNegative) { + const APInt neg_one(64, static_cast(-1), true); + EXPECT_EQ(neg_one, neg_one.ashr(7)); +} + TEST(APIntTest, i128_NegativeCount) { APInt Minus3(128, static_cast(-3), true); EXPECT_EQ(126u, Minus3.countLeadingOnes()); -- 2.7.4