#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>
//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);
}
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());
+}
}