]> granicus.if.org Git - llvm/commitdiff
[MathExtras] Fix undefined behavior (shift by bit width)
authorBenjamin Kramer <benny.kra@googlemail.com>
Wed, 19 Apr 2017 17:46:15 +0000 (17:46 +0000)
committerBenjamin Kramer <benny.kra@googlemail.com>
Wed, 19 Apr 2017 17:46:15 +0000 (17:46 +0000)
While there add some unit tests for uint64_t. Found by ubsan.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@300721 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Support/MathExtras.h
unittests/Support/MathExtrasTest.cpp

index b5b605f18935a2acf5999088464f5c2d7bcd5f0a..994456f9a68192ed11756d43c8fb9d72c271d5f4 100644 (file)
@@ -205,7 +205,7 @@ template <typename T> T maskTrailingOnes(unsigned N) {
   static_assert(std::is_unsigned<T>::value, "Invalid type!");
   const unsigned Bits = CHAR_BIT * sizeof(T);
   assert(N <= Bits && "Invalid bit index");
-  return -T(N != 0) & (T(-1) >> (Bits - N));
+  return N == 0 ? 0 : (T(-1) >> (Bits - N));
 }
 
 /// \brief Create a bitmask with the N left-most bits set to 1, and all other
index de8272170833bb954120ddc330175f165e6344da..f46d94e9e577b444c175215a586e847a18cd44f4 100644 (file)
@@ -84,6 +84,11 @@ TEST(MathExtras, onesMask) {
 
   EXPECT_EQ(0xFFFFFFFFU, maskTrailingOnes<uint32_t>(32U));
   EXPECT_EQ(0xFFFFFFFFU, maskLeadingOnes<uint32_t>(32U));
+  EXPECT_EQ(0xFFFFFFFFFFFFFFFFULL, maskTrailingOnes<uint64_t>(64U));
+  EXPECT_EQ(0xFFFFFFFFFFFFFFFFULL, maskLeadingOnes<uint64_t>(64U));
+
+  EXPECT_EQ(0x0000FFFFFFFFFFFFULL, maskTrailingOnes<uint64_t>(48U));
+  EXPECT_EQ(0xFFFFFFFFFFFF0000ULL, maskLeadingOnes<uint64_t>(48U));
 }
 
 TEST(MathExtras, findFirstSet) {