[ADT] Make StringMap's tombstone aligned.
authorBenjamin Kramer <benny.kra@googlemail.com>
Fri, 1 Apr 2016 15:51:51 +0000 (15:51 +0000)
committerBenjamin Kramer <benny.kra@googlemail.com>
Fri, 1 Apr 2016 15:51:51 +0000 (15:51 +0000)
This avoids undefined behavior when casting pointers to it. Also make
sure that we don't cast to a derived StringMapEntry before checking for
tombstone, as that may have different alignment requirements.

llvm-svn: 265145

llvm/include/llvm/ADT/StringMap.h

index ce80484..e593e51 100644 (file)
@@ -17,6 +17,7 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/Support/Allocator.h"
+#include "llvm/Support/PointerLikeTypeTraits.h"
 #include <cstring>
 #include <utility>
 
@@ -95,7 +96,9 @@ protected:
 
 public:
   static StringMapEntryBase *getTombstoneVal() {
-    return (StringMapEntryBase*)-1;
+    uintptr_t Val = static_cast<uintptr_t>(-1);
+    Val <<= PointerLikeTypeTraits<StringMapEntryBase *>::NumLowBitsAvailable;
+    return reinterpret_cast<StringMapEntryBase *>(Val);
   }
 
   unsigned getNumBuckets() const { return NumBuckets; }
@@ -260,14 +263,15 @@ public:
     NumItems = RHS.NumItems;
     NumTombstones = RHS.NumTombstones;
     for (unsigned I = 0, E = NumBuckets; I != E; ++I) {
-      MapEntryTy *Bucket = ((MapEntryTy**) RHS.TheTable)[I];
+      StringMapEntryBase *Bucket = RHS.TheTable[I];
       if (!Bucket || Bucket == getTombstoneVal()) {
         TheTable[I] = Bucket;
         continue;
       }
 
-      TheTable[I] = MapEntryTy::Create(Bucket->getKey(), Allocator,
-                                       Bucket->getValue());
+      TheTable[I] = MapEntryTy::Create(
+          static_cast<MapEntryTy *>(Bucket)->getKey(), Allocator,
+          static_cast<MapEntryTy *>(Bucket)->getValue());
       HashTable[I] = RHSHashTable[I];
     }