Index: llvm/include/llvm/ADT/PointerIntPair.h =================================================================== --- llvm/include/llvm/ADT/PointerIntPair.h +++ llvm/include/llvm/ADT/PointerIntPair.h @@ -19,10 +19,38 @@ #include "llvm/Support/type_traits.h" #include #include +#include #include namespace llvm { +namespace detail { +template struct PunnedPointer { + static_assert(sizeof(Ptr) == sizeof(intptr_t), ""); + + explicit constexpr PunnedPointer(intptr_t i = 0) { *this = i; } + + constexpr intptr_t asInt() const { + intptr_t R = 0; + std::memcpy(&R, &Data, sizeof(R)); + return R; + } + + constexpr operator intptr_t() const { return asInt(); } + + constexpr PunnedPointer &operator=(intptr_t V) { + std::memcpy(&Data, &V, sizeof(Data)); + return *this; + } + + Ptr *getPointerAddress() { return &Data; } + const Ptr *getPointerAddress() const { return &Data; } + +private: + Ptr Data; +}; +} // namespace detail + template struct DenseMapInfo; template struct PointerIntPairInfo; @@ -46,7 +74,7 @@ class PointerIntPair { // Used by MSVC visualizer and generally helpful for debugging/visualizing. using InfoTy = Info; - intptr_t Value = 0; + detail::PunnedPointer Value; public: constexpr PointerIntPair() = default; @@ -86,10 +114,12 @@ assert(Value == reinterpret_cast(getPointer()) && "Can only return the address if IntBits is cleared and " "PtrTraits doesn't change the pointer"); - return reinterpret_cast(&Value); + return Value.getPointerAddress(); } - void *getOpaqueValue() const { return reinterpret_cast(Value); } + void *getOpaqueValue() const { + return reinterpret_cast(Value.asInt()); + } void setFromOpaqueValue(void *Val) & { Value = reinterpret_cast(Val); Index: llvm/unittests/ADT/PointerIntPairTest.cpp =================================================================== --- llvm/unittests/ADT/PointerIntPairTest.cpp +++ llvm/unittests/ADT/PointerIntPairTest.cpp @@ -106,4 +106,22 @@ "trivially copyable"); } +TEST(PointerIntPairTest, TypePunning) { + int I = 0; + int *IntPtr = &I; + + int **IntPtrBegin = &IntPtr; + int **IntPtrEnd = IntPtrBegin + 1; + + PointerIntPair Pair; + int **PairAddr = Pair.getAddrOfPointer(); + + while (IntPtrBegin != IntPtrEnd) { + *PairAddr = *IntPtrBegin; + ++PairAddr; + ++IntPtrBegin; + } + EXPECT_EQ(Pair.getPointer(), IntPtr); +} + } // end anonymous namespace