Index: llvm/include/llvm/ADT/PointerIntPair.h =================================================================== --- llvm/include/llvm/ADT/PointerIntPair.h +++ llvm/include/llvm/ADT/PointerIntPair.h @@ -19,10 +19,37 @@ #include "llvm/Support/type_traits.h" #include #include +#include #include namespace llvm { +namespace detail { +template struct PunnedPointer { + explicit constexpr PunnedPointer(intptr_t i = 0) { *this = i; } + + 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 reinterpret_cast(Data); } + const Ptr *getPointerAddress() const { + return const_cast(this)->getPointerAddress(); + } + + alignas(Ptr) char Data[sizeof(Ptr)]; +}; +} // namespace detail + template struct DenseMapInfo; template struct PointerIntPairInfo; @@ -46,7 +73,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 +113,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