Index: include/llvm/ADT/StringMap.h =================================================================== --- include/llvm/ADT/StringMap.h +++ include/llvm/ADT/StringMap.h @@ -89,7 +89,8 @@ /// table, returning it. If the key is not in the table, this returns null. StringMapEntryBase *RemoveKey(StringRef Key); -private: + /// Allocate the table with the specified number of buckets and otherwise + /// setup the map as empty. void init(unsigned Size); public: @@ -244,7 +245,32 @@ return *this; } - // FIXME: Implement copy operations if/when they're needed. + StringMap(const StringMap &RHS) : + StringMapImpl(static_cast(sizeof(MapEntryTy))), + Allocator(RHS.Allocator) { + if (RHS.empty()) + return; + + // Allocate TheTable of the same size as RHS's TheTable, and set the + // sentinel appropriately (and NumBuckets). + init(RHS.NumBuckets); + unsigned *HashTable = (unsigned *)(TheTable + NumBuckets + 1), + *RHSHashTable = (unsigned *)(RHS.TheTable + NumBuckets + 1); + + NumItems = RHS.NumItems; + NumTombstones = RHS.NumTombstones; + for (unsigned I = 0, E = NumBuckets; I != E; ++I) { + MapEntryTy *Bucket = ((MapEntryTy**) RHS.TheTable)[I]; + if (!Bucket || Bucket == getTombstoneVal()) { + TheTable[I] = Bucket; + continue; + } + + TheTable[I] = MapEntryTy::Create(Bucket->getKey(), Allocator, + Bucket->getValue()); + HashTable[I] = RHSHashTable[I]; + } + } AllocatorTy &getAllocator() { return Allocator; } const AllocatorTy &getAllocator() const { return Allocator; } Index: unittests/ADT/StringMapTest.cpp =================================================================== --- unittests/ADT/StringMapTest.cpp +++ unittests/ADT/StringMapTest.cpp @@ -157,6 +157,33 @@ EXPECT_EQ(5, Map.lookup("funf")); } +TEST_F(StringMapTest, CopyCtorTest) { + llvm::StringMap Map; + + Map["eins"] = 1; + Map["zwei"] = 2; + Map["drei"] = 3; + Map.erase("drei"); + Map.erase("eins"); + Map["veir"] = 4; + Map["funf"] = 5; + + EXPECT_EQ(3u, Map.size()); + EXPECT_EQ(0, Map.lookup("eins")); + EXPECT_EQ(2, Map.lookup("zwei")); + EXPECT_EQ(0, Map.lookup("drei")); + EXPECT_EQ(4, Map.lookup("veir")); + EXPECT_EQ(5, Map.lookup("funf")); + + llvm::StringMap Map2(Map); + EXPECT_EQ(3u, Map2.size()); + EXPECT_EQ(0, Map2.lookup("eins")); + EXPECT_EQ(2, Map2.lookup("zwei")); + EXPECT_EQ(0, Map2.lookup("drei")); + EXPECT_EQ(4, Map2.lookup("veir")); + EXPECT_EQ(5, Map2.lookup("funf")); +} + // A more complex iteration test. TEST_F(StringMapTest, IterationTest) { bool visited[100];