diff --git a/llvm/include/llvm/ADT/PointerUnion.h b/llvm/include/llvm/ADT/PointerUnion.h --- a/llvm/include/llvm/ADT/PointerUnion.h +++ b/llvm/include/llvm/ADT/PointerUnion.h @@ -18,6 +18,7 @@ #include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/PointerLikeTypeTraits.h" #include #include @@ -205,6 +206,35 @@ return lhs.getOpaqueValue() < rhs.getOpaqueValue(); } +// Specialization of CastInfo for PointerUnion +template +struct CastInfo> + : CastIsPossible> { + using From = PointerUnion; + + static inline bool isPossible(From &f) { return f.template is(); } + + static To doCast(From &f) { + assert(f.template is() && + "cast to incompatible pointer type from PointerUnion !"); + return f.template get(); + } + + static To castFailed() { return nullptr; } + + static To doCastIfPossible(From &f) { + if (isPossible(f)) + return doCast(f); + + return castFailed(); + } +}; + +template +struct CastInfo> + : ConstStrippingForwardingCast, + CastInfo>> {}; + // Teach SmallPtrSet that PointerUnion is "basically a pointer", that has // # low bits available = min(PT1bits,PT2bits)-1. template diff --git a/llvm/unittests/ADT/PointerUnionTest.cpp b/llvm/unittests/ADT/PointerUnionTest.cpp --- a/llvm/unittests/ADT/PointerUnionTest.cpp +++ b/llvm/unittests/ADT/PointerUnionTest.cpp @@ -156,4 +156,120 @@ EXPECT_TRUE((void *)n.getAddrOfPtr1() == (void *)&n); } +TEST_F(PointerUnionTest, NewCastInfra) { + // test isa<> + EXPECT_TRUE(isa(a)); + EXPECT_TRUE(isa(b)); + EXPECT_TRUE(isa(c)); + EXPECT_TRUE(isa(n)); + EXPECT_TRUE(isa(i3)); + EXPECT_TRUE(isa(f3)); + EXPECT_TRUE(isa(l3)); + EXPECT_TRUE(isa(i4)); + EXPECT_TRUE(isa(f4)); + EXPECT_TRUE(isa(l4)); + EXPECT_TRUE(isa(d4)); + EXPECT_TRUE(isa(i4null)); + EXPECT_TRUE(isa(f4null)); + EXPECT_TRUE(isa(l4null)); + EXPECT_TRUE(isa(d4null)); + EXPECT_FALSE(isa(a)); + EXPECT_FALSE(isa(b)); + EXPECT_FALSE(isa(c)); + EXPECT_FALSE(isa(n)); + EXPECT_FALSE(isa(i3)); + EXPECT_FALSE(isa(i3)); + EXPECT_FALSE(isa(f3)); + EXPECT_FALSE(isa(f3)); + EXPECT_FALSE(isa(l3)); + EXPECT_FALSE(isa(l3)); + EXPECT_FALSE(isa(i4)); + EXPECT_FALSE(isa(i4)); + EXPECT_FALSE(isa(i4)); + EXPECT_FALSE(isa(f4)); + EXPECT_FALSE(isa(f4)); + EXPECT_FALSE(isa(f4)); + EXPECT_FALSE(isa(l4)); + EXPECT_FALSE(isa(l4)); + EXPECT_FALSE(isa(l4)); + EXPECT_FALSE(isa(d4)); + EXPECT_FALSE(isa(d4)); + EXPECT_FALSE(isa(d4)); + EXPECT_FALSE(isa(i4null)); + EXPECT_FALSE(isa(i4null)); + EXPECT_FALSE(isa(i4null)); + EXPECT_FALSE(isa(f4null)); + EXPECT_FALSE(isa(f4null)); + EXPECT_FALSE(isa(f4null)); + EXPECT_FALSE(isa(l4null)); + EXPECT_FALSE(isa(l4null)); + EXPECT_FALSE(isa(l4null)); + EXPECT_FALSE(isa(d4null)); + EXPECT_FALSE(isa(d4null)); + EXPECT_FALSE(isa(d4null)); + + // test cast<> + EXPECT_EQ(cast(a), &f); + EXPECT_EQ(cast(b), &i); + EXPECT_EQ(cast(c), &i); + EXPECT_EQ(cast(i3), &i); + EXPECT_EQ(cast(f3), &f); + EXPECT_EQ(cast(l3), &l); + EXPECT_EQ(cast(i4), &i); + EXPECT_EQ(cast(f4), &f); + EXPECT_EQ(cast(l4), &l); + EXPECT_EQ(cast(d4), &d); + + // test dyn_cast + EXPECT_EQ(dyn_cast(a), nullptr); + EXPECT_EQ(dyn_cast(a), &f); + EXPECT_EQ(dyn_cast(b), &i); + EXPECT_EQ(dyn_cast(b), nullptr); + EXPECT_EQ(dyn_cast(c), &i); + EXPECT_EQ(dyn_cast(c), nullptr); + EXPECT_EQ(dyn_cast(n), nullptr); + EXPECT_EQ(dyn_cast(n), nullptr); + EXPECT_EQ(dyn_cast(i3), &i); + EXPECT_EQ(dyn_cast(i3), nullptr); + EXPECT_EQ(dyn_cast(i3), nullptr); + EXPECT_EQ(dyn_cast(f3), nullptr); + EXPECT_EQ(dyn_cast(f3), &f); + EXPECT_EQ(dyn_cast(f3), nullptr); + EXPECT_EQ(dyn_cast(l3), nullptr); + EXPECT_EQ(dyn_cast(l3), nullptr); + EXPECT_EQ(dyn_cast(l3), &l); + EXPECT_EQ(dyn_cast(i4), &i); + EXPECT_EQ(dyn_cast(i4), nullptr); + EXPECT_EQ(dyn_cast(i4), nullptr); + EXPECT_EQ(dyn_cast(i4), nullptr); + EXPECT_EQ(dyn_cast(f4), nullptr); + EXPECT_EQ(dyn_cast(f4), &f); + EXPECT_EQ(dyn_cast(f4), nullptr); + EXPECT_EQ(dyn_cast(f4), nullptr); + EXPECT_EQ(dyn_cast(l4), nullptr); + EXPECT_EQ(dyn_cast(l4), nullptr); + EXPECT_EQ(dyn_cast(l4), &l); + EXPECT_EQ(dyn_cast(l4), nullptr); + EXPECT_EQ(dyn_cast(d4), nullptr); + EXPECT_EQ(dyn_cast(d4), nullptr); + EXPECT_EQ(dyn_cast(d4), nullptr); + EXPECT_EQ(dyn_cast(d4), &d); + EXPECT_EQ(dyn_cast(i4null), nullptr); + EXPECT_EQ(dyn_cast(i4null), nullptr); + EXPECT_EQ(dyn_cast(i4null), nullptr); + EXPECT_EQ(dyn_cast(i4null), nullptr); + EXPECT_EQ(dyn_cast(f4null), nullptr); + EXPECT_EQ(dyn_cast(f4null), nullptr); + EXPECT_EQ(dyn_cast(f4null), nullptr); + EXPECT_EQ(dyn_cast(f4null), nullptr); + EXPECT_EQ(dyn_cast(l4null), nullptr); + EXPECT_EQ(dyn_cast(l4null), nullptr); + EXPECT_EQ(dyn_cast(l4null), nullptr); + EXPECT_EQ(dyn_cast(l4null), nullptr); + EXPECT_EQ(dyn_cast(d4null), nullptr); + EXPECT_EQ(dyn_cast(d4null), nullptr); + EXPECT_EQ(dyn_cast(d4null), nullptr); + EXPECT_EQ(dyn_cast(d4null), nullptr); +} + } // end anonymous namespace