llvm.org GIT mirror llvm / a0c4c21
[ADT] Fix PointerEmbeddedInt when the underlying type is uintptr_t. ...and when you try to store negative values in it. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@261259 91177308-0d34-0410-b5e6-96231b3b80d8 Jordan Rose 4 years ago
2 changed file(s) with 52 addition(s) and 7 deletion(s). Raw diff Collapse all Expand all
1010 #define LLVM_ADT_POINTEREMBEDDEDINT_H
1111
1212 #include "llvm/ADT/DenseMapInfo.h"
13 #include "llvm/Support/MathExtras.h"
1314 #include "llvm/Support/PointerLikeTypeTraits.h"
1415 #include
1516
2930 class PointerEmbeddedInt {
3031 uintptr_t Value;
3132
33 // Note: This '<' is correct; using '<=' would result in some shifts
34 // overflowing their storage types.
3235 static_assert(Bits < sizeof(uintptr_t) * CHAR_BIT,
3336 "Cannot embed more bits than we have in a pointer!");
3437
4144 Mask = static_cast(-1) << Bits
4245 };
4346
47 static constexpr const struct RawValueTag {} RawValue = RawValueTag();
48
4449 friend class PointerLikeTypeTraits;
4550
46 explicit PointerEmbeddedInt(uintptr_t Value) : Value(Value) {}
51 explicit PointerEmbeddedInt(uintptr_t Value, RawValueTag) : Value(Value) {}
4752
4853 public:
4954 PointerEmbeddedInt() : Value(0) {}
5055
51 PointerEmbeddedInt(IntT I) : Value(static_cast(I) << Shift) {
52 assert((I & Mask) == 0 && "Integer has bits outside those preserved!");
56 PointerEmbeddedInt(IntT I) {
57 *this = I;
5358 }
5459
5560 PointerEmbeddedInt &operator=(IntT I) {
56 assert((I & Mask) == 0 && "Integer has bits outside those preserved!");
61 assert((std::is_signed::value ? llvm::isInt(I)
62 : llvm::isUInt(I)) &&
63 "Integer has bits outside those preserved!");
5764 Value = static_cast(I) << Shift;
5865 return *this;
5966 }
6067
6168 // Note that this implicit conversion additionally allows all of the basic
6269 // comparison operators to work transparently, etc.
63 operator IntT() const { return static_cast(Value >> Shift); }
70 operator IntT() const {
71 if (std::is_signed::value)
72 return static_cast(static_cast(Value) >> Shift);
73 return static_cast(Value >> Shift);
74 }
6475 };
6576
6677 // Provide pointer like traits to support use with pointer unions and sum
7485 return reinterpret_cast(P.Value);
7586 }
7687 static inline T getFromVoidPointer(void *P) {
77 return T(reinterpret_cast(P));
88 return T(reinterpret_cast(P), T::RawValue);
7889 }
7990 static inline T getFromVoidPointer(const void *P) {
80 return T(reinterpret_cast(P));
91 return T(reinterpret_cast(P), T::RawValue);
8192 }
8293
8394 enum { NumLowBitsAvailable = T::Shift };
4242 EXPECT_FALSE(42 >= J);
4343 }
4444
45 TEST(PointerEmbeddedIntTest, intptr_t) {
46 PointerEmbeddedInt IPos = 42, INeg = -42;
47 EXPECT_EQ(42, IPos);
48 EXPECT_EQ(-42, INeg);
49
50 PointerEmbeddedInt U = 42, USaturated = 255;
51 EXPECT_EQ(42U, U);
52 EXPECT_EQ(255U, USaturated);
53
54 PointerEmbeddedInt::digits>
55 IMax = std::numeric_limits::max() >> 1,
56 IMin = std::numeric_limits::min() >> 1;
57 EXPECT_EQ(std::numeric_limits::max() >> 1, IMax);
58 EXPECT_EQ(std::numeric_limits::min() >> 1, IMin);
59
60 PointerEmbeddedInt::digits - 1>
61 UMax = std::numeric_limits::max() >> 1,
62 UMin = std::numeric_limits::min() >> 1;
63 EXPECT_EQ(std::numeric_limits::max() >> 1, UMax);
64 EXPECT_EQ(std::numeric_limits::min() >> 1, UMin);
65 }
66
67 TEST(PointerEmbeddedIntTest, PointerLikeTypeTraits) {
68 PointerEmbeddedInt I = 42;
69 using ITraits = PointerLikeTypeTraits;
70 EXPECT_EQ(42, ITraits::getFromVoidPointer(ITraits::getAsVoidPointer(I)));
71
72 PointerEmbeddedInt::digits - 1>
73 Max = std::numeric_limits::max() >> 1;
74 using MaxTraits = PointerLikeTypeTraits;
75 EXPECT_EQ(std::numeric_limits::max() >> 1,
76 MaxTraits::getFromVoidPointer(MaxTraits::getAsVoidPointer(Max)));
77 }
78
4579 } // end anonymous namespace