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 @@ -17,6 +17,7 @@ #include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/VariantTraits.h" #include "llvm/Support/PointerLikeTypeTraits.h" #include #include @@ -162,9 +163,12 @@ explicit operator bool() const { return !isNull(); } + /// Get index of pointer type currently held by Union. + size_t index() const { return this->Val.getInt(); } + /// Test if the Union currently holds the type matching T. template bool is() const { - return this->Val.getInt() == FirstIndexOfType{}; + return index() == FirstIndexOfType{}; } /// Returns the value of the specified pointer type. @@ -273,6 +277,18 @@ } }; +template struct VariantTraits> { + static constexpr size_t size() { return sizeof...(PTs); } + static constexpr size_t index(const PointerUnion &Variant) { + return Variant.index(); + } + template > + static constexpr decltype(auto) get(VariantT &&Variant) { + return std::forward(Variant) + .template get>(); + } +}; + } // end namespace llvm #endif // LLVM_ADT_POINTERUNION_H 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,26 @@ EXPECT_TRUE((void *)n.getAddrOfPtr1() == (void *)&n); } +TEST_F(PointerUnionTest, Visitor) { + void *ptr; + + visit(makeVisitor([&](int *intPtr) { ptr = intPtr; }, + [&](float *floatPtr) { ptr = floatPtr; }), + a); + EXPECT_EQ(&f, ptr); + + visit(makeVisitor([&](int *intPtr) { ptr = intPtr; }, + [&](float *floatPtr) { ptr = floatPtr; }, + [&](long long *longPtr) { ptr = longPtr; }), + i3); + EXPECT_EQ(&i, ptr); + + visit(makeVisitor([&](int *intPtr) { ptr = intPtr; }, + [&](float *floatPtr) { ptr = floatPtr; }, + [&](long long *longPtr) { ptr = longPtr; }, + [&](double *doublePtr) { ptr = doublePtr; }), + d4); + EXPECT_EQ(&d, ptr); +} + } // end anonymous namespace