PointerIntPair: Avoid an (academic) case of undefined behavior in the DenseMapInfo...
authorBenjamin Kramer <benny.kra@googlemail.com>
Sat, 15 Mar 2014 18:10:49 +0000 (18:10 +0000)
committerBenjamin Kramer <benny.kra@googlemail.com>
Sat, 15 Mar 2014 18:10:49 +0000 (18:10 +0000)
If we use a pair with an enum type this could create values outside
of the enum range. Avoid it by creating the bit pattern directly.
While there turn a dynamic assert into a static one. No functionality
change.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204010 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/ADT/PointerIntPair.h

index 313abf3a14ba0c1c5db0ad02f7f7393ccc13e801..45a40db85c046fdf20f6b76fc934af6f3d158c90 100644 (file)
@@ -45,6 +45,8 @@ class PointerIntPair {
   static_assert(PtrTraits::NumLowBitsAvailable <
                 std::numeric_limits<uintptr_t>::digits,
                 "cannot use a pointer type that has all bits free");
+  static_assert(IntBits <= PtrTraits::NumLowBitsAvailable,
+                "PointerIntPair with integer size too large for pointer");
   enum : uintptr_t {
     /// PointerBitMask - The bits that come from the pointer.
     PointerBitMask =
@@ -63,8 +65,6 @@ class PointerIntPair {
 public:
   PointerIntPair() : Value(0) {}
   PointerIntPair(PointerTy PtrVal, IntType IntVal) {
-    assert(IntBits <= PtrTraits::NumLowBitsAvailable &&
-           "PointerIntPair formed with integer size too large for pointer");
     setPointerAndInt(PtrVal, IntVal);
   }
   explicit PointerIntPair(PointerTy PtrVal) {
@@ -162,13 +162,13 @@ struct DenseMapInfo<PointerIntPair<PointerTy, IntBits, IntType> > {
   typedef PointerIntPair<PointerTy, IntBits, IntType> Ty;
   static Ty getEmptyKey() {
     uintptr_t Val = static_cast<uintptr_t>(-1);
-    Val <<= PointerLikeTypeTraits<PointerTy>::NumLowBitsAvailable;
-    return Ty(reinterpret_cast<PointerTy>(Val), IntType((1 << IntBits)-1));
+    Val <<= PointerLikeTypeTraits<Ty>::NumLowBitsAvailable;
+    return Ty::getFromOpaqueValue(reinterpret_cast<void *>(Val));
   }
   static Ty getTombstoneKey() {
     uintptr_t Val = static_cast<uintptr_t>(-2);
     Val <<= PointerLikeTypeTraits<PointerTy>::NumLowBitsAvailable;
-    return Ty(reinterpret_cast<PointerTy>(Val), IntType(0));
+    return Ty::getFromOpaqueValue(reinterpret_cast<void *>(Val));
   }
   static unsigned getHashValue(Ty V) {
     uintptr_t IV = reinterpret_cast<uintptr_t>(V.getOpaqueValue());