[PATCH] D75301: [ADT] Allow K to be incomplete during DenseMap<K*, V> instantiation

Reid Kleckner via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 28 14:27:38 PST 2020


This revision was automatically updated to reflect the committed changes.
Closed by commit rG53f51da09e45: [ADT] Allow K to be incomplete during DenseMap<K*, V> instantiation (authored by rnk).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D75301/new/

https://reviews.llvm.org/D75301

Files:
  llvm/include/llvm/ADT/DenseMapInfo.h
  llvm/unittests/ADT/DenseMapTest.cpp


Index: llvm/unittests/ADT/DenseMapTest.cpp
===================================================================
--- llvm/unittests/ADT/DenseMapTest.cpp
+++ llvm/unittests/ADT/DenseMapTest.cpp
@@ -622,4 +622,28 @@
   EXPECT_NE(Map.find(B), Map.end());
   EXPECT_NE(Map.find(C), Map.end());
 }
+
+struct IncompleteStruct;
+
+TEST(DenseMapCustomTest, OpaquePointerKey) {
+  // Test that we can use a pointer to an incomplete type as a DenseMap key.
+  // This is an important build time optimization, since many classes have
+  // DenseMap members.
+  DenseMap<IncompleteStruct *, int> Map;
+  int Keys[3] = {0, 0, 0};
+  IncompleteStruct *K1 = reinterpret_cast<IncompleteStruct *>(&Keys[0]);
+  IncompleteStruct *K2 = reinterpret_cast<IncompleteStruct *>(&Keys[1]);
+  IncompleteStruct *K3 = reinterpret_cast<IncompleteStruct *>(&Keys[2]);
+  Map.insert({K1, 1});
+  Map.insert({K2, 2});
+  Map.insert({K3, 3});
+  EXPECT_EQ(Map.count(K1), 1u);
+  EXPECT_EQ(Map[K1], 1);
+  EXPECT_EQ(Map[K2], 2);
+  EXPECT_EQ(Map[K3], 3);
+  Map.clear();
+  EXPECT_EQ(Map.find(K1), Map.end());
+  EXPECT_EQ(Map.find(K2), Map.end());
+  EXPECT_EQ(Map.find(K3), Map.end());
+}
 }
Index: llvm/include/llvm/ADT/DenseMapInfo.h
===================================================================
--- llvm/include/llvm/ADT/DenseMapInfo.h
+++ llvm/include/llvm/ADT/DenseMapInfo.h
@@ -16,7 +16,6 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/Hashing.h"
 #include "llvm/ADT/StringRef.h"
-#include "llvm/Support/PointerLikeTypeTraits.h"
 #include <cassert>
 #include <cstddef>
 #include <cstdint>
@@ -32,18 +31,28 @@
   //static bool isEqual(const T &LHS, const T &RHS);
 };
 
-// Provide DenseMapInfo for all pointers.
+// Provide DenseMapInfo for all pointers. Come up with sentinel pointer values
+// that are aligned to alignof(T) bytes, but try to avoid requiring T to be
+// complete. This allows clients to instantiate DenseMap<T*, ...> with forward
+// declared key types. Assume that no pointer key type requires more than 4096
+// bytes of alignment.
 template<typename T>
 struct DenseMapInfo<T*> {
+  // The following should hold, but it would require T to be complete:
+  // static_assert(alignof(T) <= (1 << Log2MaxAlign),
+  //               "DenseMap does not support pointer keys requiring more than "
+  //               "Log2MaxAlign bits of alignment");
+  static constexpr uintptr_t Log2MaxAlign = 12;
+
   static inline T* getEmptyKey() {
     uintptr_t Val = static_cast<uintptr_t>(-1);
-    Val <<= PointerLikeTypeTraits<T*>::NumLowBitsAvailable;
+    Val <<= Log2MaxAlign;
     return reinterpret_cast<T*>(Val);
   }
 
   static inline T* getTombstoneKey() {
     uintptr_t Val = static_cast<uintptr_t>(-2);
-    Val <<= PointerLikeTypeTraits<T*>::NumLowBitsAvailable;
+    Val <<= Log2MaxAlign;
     return reinterpret_cast<T*>(Val);
   }
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D75301.247369.patch
Type: text/x-patch
Size: 2846 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200228/3d9ddb2c/attachment.bin>


More information about the llvm-commits mailing list