[llvm] r329523 - [ADT] Fix MapVector when 'Map::mapped_type != unsigned'.

Eric Fiselier via llvm-commits llvm-commits at lists.llvm.org
Sun Apr 8 01:48:59 PDT 2018


Author: ericwf
Date: Sun Apr  8 01:48:58 2018
New Revision: 329523

URL: http://llvm.org/viewvc/llvm-project?rev=329523&view=rev
Log:
[ADT] Fix MapVector when 'Map::mapped_type != unsigned'.

Previously MapVector assumed `Map::mapped_type` was `unsigned`.
This caused problems when using MapVector with a user-specified
map where this didn't hold (For example StringMap<unsigned>).

This patch adjusts MapVector to use the same type as the underlying
map, avoiding reference binding errors in functions like `insert`.

Modified:
    llvm/trunk/include/llvm/ADT/MapVector.h
    llvm/trunk/unittests/ADT/MapVectorTest.cpp

Modified: llvm/trunk/include/llvm/ADT/MapVector.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/MapVector.h?rev=329523&r1=329522&r2=329523&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ADT/MapVector.h (original)
+++ llvm/trunk/include/llvm/ADT/MapVector.h Sun Apr  8 01:48:58 2018
@@ -39,6 +39,10 @@ class MapVector {
   MapType Map;
   VectorType Vector;
 
+  static_assert(
+      std::is_integral<typename MapType::mapped_type>::value,
+      "The mapped_type of the specified Map must be an integral type");
+
 public:
   using value_type = typename VectorType::value_type;
   using size_type = typename VectorType::size_type;
@@ -93,9 +97,9 @@ public:
   }
 
   ValueT &operator[](const KeyT &Key) {
-    std::pair<KeyT, unsigned> Pair = std::make_pair(Key, 0);
+    std::pair<KeyT, typename MapType::mapped_type> Pair = std::make_pair(Key, 0);
     std::pair<typename MapType::iterator, bool> Result = Map.insert(Pair);
-    unsigned &I = Result.first->second;
+    auto &I = Result.first->second;
     if (Result.second) {
       Vector.push_back(std::make_pair(Key, ValueT()));
       I = Vector.size() - 1;
@@ -112,9 +116,9 @@ public:
   }
 
   std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) {
-    std::pair<KeyT, unsigned> Pair = std::make_pair(KV.first, 0);
+    std::pair<KeyT, typename MapType::mapped_type> Pair = std::make_pair(KV.first, 0);
     std::pair<typename MapType::iterator, bool> Result = Map.insert(Pair);
-    unsigned &I = Result.first->second;
+    auto &I = Result.first->second;
     if (Result.second) {
       Vector.push_back(std::make_pair(KV.first, KV.second));
       I = Vector.size() - 1;
@@ -125,9 +129,9 @@ public:
 
   std::pair<iterator, bool> insert(std::pair<KeyT, ValueT> &&KV) {
     // Copy KV.first into the map, then move it into the vector.
-    std::pair<KeyT, unsigned> Pair = std::make_pair(KV.first, 0);
+    std::pair<KeyT, typename MapType::mapped_type> Pair = std::make_pair(KV.first, 0);
     std::pair<typename MapType::iterator, bool> Result = Map.insert(Pair);
-    unsigned &I = Result.first->second;
+    auto &I = Result.first->second;
     if (Result.second) {
       Vector.push_back(std::move(KV));
       I = Vector.size() - 1;

Modified: llvm/trunk/unittests/ADT/MapVectorTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/MapVectorTest.cpp?rev=329523&r1=329522&r2=329523&view=diff
==============================================================================
--- llvm/trunk/unittests/ADT/MapVectorTest.cpp (original)
+++ llvm/trunk/unittests/ADT/MapVectorTest.cpp Sun Apr  8 01:48:58 2018
@@ -157,6 +157,45 @@ TEST(MapVectorTest, NonCopyable) {
   ASSERT_EQ(*MV.find(2)->second, 2);
 }
 
+template <class IntType> struct MapVectorMappedTypeTest : ::testing::Test {
+  using int_type = IntType;
+};
+
+using MapIntTypes = ::testing::Types<int, long, long long, unsigned,
+                                     unsigned long, unsigned long long>;
+TYPED_TEST_CASE(MapVectorMappedTypeTest, MapIntTypes);
+
+TYPED_TEST(MapVectorMappedTypeTest, DifferentDenseMap) {
+  // Test that using a map with a mapped type other than 'unsigned' compiles
+  // and works.
+  using IntType = typename TestFixture::int_type;
+  using MapVectorType = MapVector<int, int, DenseMap<int, IntType>>;
+
+  MapVectorType MV;
+  std::pair<typename MapVectorType::iterator, bool> R;
+
+  R = MV.insert(std::make_pair(1, 2));
+  ASSERT_EQ(R.first, MV.begin());
+  EXPECT_EQ(R.first->first, 1);
+  EXPECT_EQ(R.first->second, 2);
+  EXPECT_TRUE(R.second);
+
+  const std::pair<int, int> Elem(1, 3);
+  R = MV.insert(Elem);
+  ASSERT_EQ(R.first, MV.begin());
+  EXPECT_EQ(R.first->first, 1);
+  EXPECT_EQ(R.first->second, 2);
+  EXPECT_FALSE(R.second);
+
+  int& value = MV[4];
+  EXPECT_EQ(value, 0);
+  value = 5;
+
+  EXPECT_EQ(MV.size(), 2u);
+  EXPECT_EQ(MV[1], 2);
+  EXPECT_EQ(MV[4], 5);
+}
+
 TEST(SmallMapVectorSmallTest, insert_pop) {
   SmallMapVector<int, int, 32> MV;
   std::pair<SmallMapVector<int, int, 32>::iterator, bool> R;




More information about the llvm-commits mailing list