diff options
author | Jordan Rose <jordan_rose@apple.com> | 2014-03-07 19:19:56 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2014-03-07 19:19:56 +0000 |
commit | bc3b24269eabf6e9e54598c82ede3c741d8a6e61 (patch) | |
tree | 05263dec97561e85f08186e318bd8b84b517f290 /include | |
parent | fac248734708670e898b814f88f5f262da774de3 (diff) | |
download | llvm-bc3b24269eabf6e9e54598c82ede3c741d8a6e61.tar.gz llvm-bc3b24269eabf6e9e54598c82ede3c741d8a6e61.tar.bz2 llvm-bc3b24269eabf6e9e54598c82ede3c741d8a6e61.tar.xz |
[ADT] Update PointerIntPair to handle pointer types with more than 31 bits free.
Previously, the assertions in PointerIntPair would try to calculate the value
(1 << NumLowBitsAvailable); the inferred type here is 'int', so if there were
more than 31 bits available we'd get a shift overflow.
Also, add a rudimentary unit test file for PointerIntPair.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203273 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include')
-rw-r--r-- | include/llvm/ADT/PointerIntPair.h | 14 |
1 files changed, 9 insertions, 5 deletions
diff --git a/include/llvm/ADT/PointerIntPair.h b/include/llvm/ADT/PointerIntPair.h index a5a684744b..313abf3a14 100644 --- a/include/llvm/ADT/PointerIntPair.h +++ b/include/llvm/ADT/PointerIntPair.h @@ -17,6 +17,7 @@ #include "llvm/Support/Compiler.h" #include "llvm/Support/PointerLikeTypeTraits.h" #include <cassert> +#include <limits> namespace llvm { @@ -41,6 +42,9 @@ template <typename PointerTy, unsigned IntBits, typename IntType=unsigned, typename PtrTraits = PointerLikeTypeTraits<PointerTy> > class PointerIntPair { intptr_t Value; + static_assert(PtrTraits::NumLowBitsAvailable < + std::numeric_limits<uintptr_t>::digits, + "cannot use a pointer type that has all bits free"); enum : uintptr_t { /// PointerBitMask - The bits that come from the pointer. PointerBitMask = @@ -79,7 +83,7 @@ public: void setPointer(PointerTy PtrVal) { intptr_t PtrWord = reinterpret_cast<intptr_t>(PtrTraits::getAsVoidPointer(PtrVal)); - assert((PtrWord & ((1 << PtrTraits::NumLowBitsAvailable)-1)) == 0 && + assert((PtrWord & ~PointerBitMask) == 0 && "Pointer is not sufficiently aligned"); // Preserve all low bits, just update the pointer. Value = PtrWord | (Value & ~PointerBitMask); @@ -87,7 +91,7 @@ public: void setInt(IntType IntVal) { intptr_t IntWord = static_cast<intptr_t>(IntVal); - assert(IntWord < (1 << IntBits) && "Integer too large for field"); + assert((IntWord & ~IntMask) == 0 && "Integer too large for field"); // Preserve all bits other than the ones we are updating. Value &= ~ShiftedIntMask; // Remove integer field. @@ -97,7 +101,7 @@ public: void initWithPointer(PointerTy PtrVal) { intptr_t PtrWord = reinterpret_cast<intptr_t>(PtrTraits::getAsVoidPointer(PtrVal)); - assert((PtrWord & ((1 << PtrTraits::NumLowBitsAvailable)-1)) == 0 && + assert((PtrWord & ~PointerBitMask) == 0 && "Pointer is not sufficiently aligned"); Value = PtrWord; } @@ -105,10 +109,10 @@ public: void setPointerAndInt(PointerTy PtrVal, IntType IntVal) { intptr_t PtrWord = reinterpret_cast<intptr_t>(PtrTraits::getAsVoidPointer(PtrVal)); - assert((PtrWord & ((1 << PtrTraits::NumLowBitsAvailable)-1)) == 0 && + assert((PtrWord & ~PointerBitMask) == 0 && "Pointer is not sufficiently aligned"); intptr_t IntWord = static_cast<intptr_t>(IntVal); - assert(IntWord < (1 << IntBits) && "Integer too large for field"); + assert((IntWord & ~IntMask) == 0 && "Integer too large for field"); Value = PtrWord | (IntWord << IntShift); } |