From: Simon Pilgrim Date: Sun, 21 Jul 2019 16:06:26 +0000 (+0000) Subject: [SmallBitVector] Fix bug in find_next_unset for small types with indices >=32 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9b4b52095ce2e446960d1085aee9085aa331ec71;p=llvm [SmallBitVector] Fix bug in find_next_unset for small types with indices >=32 We were creating a bitmask from a shift of unsigned instead of uintptr_t, meaning we couldn't create masks for indices above 31. Noticed due to a MSVC analyzer warning. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@366657 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/ADT/SmallBitVector.h b/include/llvm/ADT/SmallBitVector.h index 742450e6a95..61375c00802 100644 --- a/include/llvm/ADT/SmallBitVector.h +++ b/include/llvm/ADT/SmallBitVector.h @@ -290,7 +290,7 @@ public: ++Prev; uintptr_t Bits = getSmallBits(); // Mask in previous bits. - uintptr_t Mask = (1 << Prev) - 1; + uintptr_t Mask = (uintptr_t(1) << Prev) - 1; Bits |= Mask; if (Bits == ~uintptr_t(0) || Prev + 1 >= getSmallSize()) diff --git a/unittests/ADT/BitVectorTest.cpp b/unittests/ADT/BitVectorTest.cpp index 559dcc579d1..fea58422c5f 100644 --- a/unittests/ADT/BitVectorTest.cpp +++ b/unittests/ADT/BitVectorTest.cpp @@ -228,6 +228,38 @@ TYPED_TEST(BitVectorTest, SimpleFindOpsMultiWord) { EXPECT_EQ(99, A.find_next_unset(98)); } +// Test finding next set and unset bits in a BitVector/SmallBitVector within a +// uintptr_t - check both 32-bit (Multi) and 64-bit (Small) targets. +TYPED_TEST(BitVectorTest, SimpleFindOps64Bit) { + TypeParam A; + + A.resize(57); + A.set(12); + A.set(13); + A.set(47); + + EXPECT_EQ(47, A.find_last()); + EXPECT_EQ(12, A.find_first()); + EXPECT_EQ(13, A.find_next(12)); + EXPECT_EQ(47, A.find_next(13)); + EXPECT_EQ(-1, A.find_next(47)); + + EXPECT_EQ(-1, A.find_prev(12)); + EXPECT_EQ(12, A.find_prev(13)); + EXPECT_EQ(13, A.find_prev(47)); + EXPECT_EQ(47, A.find_prev(56)); + + EXPECT_EQ(0, A.find_first_unset()); + EXPECT_EQ(56, A.find_last_unset()); + EXPECT_EQ(14, A.find_next_unset(11)); + EXPECT_EQ(14, A.find_next_unset(12)); + EXPECT_EQ(14, A.find_next_unset(13)); + EXPECT_EQ(16, A.find_next_unset(15)); + EXPECT_EQ(48, A.find_next_unset(46)); + EXPECT_EQ(48, A.find_next_unset(47)); + EXPECT_EQ(-1, A.find_next_unset(56)); +} + // Check if a SmallBitVector is in small mode. This check is used in tests // that run for both SmallBitVector and BitVector. This check doesn't apply // to BitVector so we provide an overload that returns true to get the tests