[llvm] r264906 - Add a copy constructor to StringMap
Justin Bogner via llvm-commits
llvm-commits at lists.llvm.org
Wed Mar 30 17:01:43 PDT 2016
Hal Finkel via llvm-commits <llvm-commits at lists.llvm.org> writes:
> Author: hfinkel
> Date: Wed Mar 30 14:54:56 2016
> New Revision: 264906
>
> URL: http://llvm.org/viewvc/llvm-project?rev=264906&view=rev
> Log:
> Add a copy constructor to StringMap
>
> There is code under review that requires StringMap to have a copy constructor,
> and this makes StringMap more consistent with our other containers (like
> DenseMap) that have copy constructors.
>
> Differential Revision: http://reviews.llvm.org/D18506
>
> Modified:
> llvm/trunk/include/llvm/ADT/StringMap.h
> llvm/trunk/unittests/ADT/StringMapTest.cpp
>
> Modified: llvm/trunk/include/llvm/ADT/StringMap.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/StringMap.h?rev=264906&r1=264905&r2=264906&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/ADT/StringMap.h (original)
> +++ llvm/trunk/include/llvm/ADT/StringMap.h Wed Mar 30 14:54:56 2016
> @@ -89,7 +89,8 @@ protected:
> /// 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,39 @@ public:
> return *this;
> }
>
> - // FIXME: Implement copy operations if/when they're needed.
> + StringMap(const StringMap &RHS) :
> + StringMapImpl(static_cast<unsigned>(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];
UBSan complains here when this is a tombstone:
include/llvm/ADT/StringMap.h:264:22: runtime error: upcast of misaligned address 0xffffffffffffffff for type 'llvm::StringMapEntry<int>', which requires 4 byte alignment
I guess this is fairly unlikely to do the wrong thing in practice, but
maybe we should check for the tombstone value before doing the cast?
> + if (!Bucket || Bucket == getTombstoneVal()) {
> + TheTable[I] = Bucket;
> + continue;
> + }
> +
> + TheTable[I] = MapEntryTy::Create(Bucket->getKey(), Allocator,
> + Bucket->getValue());
> + HashTable[I] = RHSHashTable[I];
> + }
> +
> + // Note that here we've copied everything from the RHS into this object,
> + // tombstones included. We could, instead, have re-probed for each key to
> + // instantiate this new object without any tombstone buckets. The
> + // assumption here is that items are rarely deleted from most StringMaps,
> + // and so tombstones are rare, so the cost of re-probing for all inputs is
> + // not worthwhile.
> + }
>
> AllocatorTy &getAllocator() { return Allocator; }
> const AllocatorTy &getAllocator() const { return Allocator; }
>
> Modified: llvm/trunk/unittests/ADT/StringMapTest.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/StringMapTest.cpp?rev=264906&r1=264905&r2=264906&view=diff
> ==============================================================================
> --- llvm/trunk/unittests/ADT/StringMapTest.cpp (original)
> +++ llvm/trunk/unittests/ADT/StringMapTest.cpp Wed Mar 30 14:54:56 2016
> @@ -157,6 +157,33 @@ TEST_F(StringMapTest, SmallFullMapTest)
> EXPECT_EQ(5, Map.lookup("funf"));
> }
>
> +TEST_F(StringMapTest, CopyCtorTest) {
> + llvm::StringMap<int> 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<int> 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];
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list