From d36aa2fa3c88efacdbec40dd48f5d3380b60ff7f Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Sun, 21 Jul 2019 16:06:26 +0000 Subject: [PATCH] [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. llvm-svn: 366657 --- include/llvm/ADT/SmallBitVector.h | 2 +- unittests/ADT/BitVectorTest.cpp | 32 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) 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