- /// Common use patterns would be something like this:
- /// PointerUnion<int*, float*> P;
- /// P = (int*)0;
- /// printf("%d %d", P.is<int*>(), P.is<float*>()); // prints "1 0"
- /// X = P.get<int*>(); // ok.
- /// Y = P.get<float*>(); // runtime assertion failure.
- /// Z = P.get<double*>(); // compile time failure.
- /// P = (float*)0;
- /// Y = P.get<float*>(); // ok.
- /// X = P.get<int*>(); // runtime assertion failure.
- template <typename PT1, typename PT2>
- class PointerUnion {
- public:
- typedef PointerIntPair<void*, 1, bool,
- PointerUnionUIntTraits<PT1,PT2> > ValTy;
- private:
- ValTy Val;
-
- struct IsPT1 {
- static const int Num = 0;
- };
- struct IsPT2 {
- static const int Num = 1;
- };
- template <typename T>
- struct UNION_DOESNT_CONTAIN_TYPE { };
-
- public:
- PointerUnion() {}
-
- PointerUnion(PT1 V) : Val(
- const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(V))) {
- }
- PointerUnion(PT2 V) : Val(
- const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(V)), 1) {
- }
-
- /// isNull - Return true if the pointer held in the union is null,
- /// regardless of which type it is.
- bool isNull() const {
- // Convert from the void* to one of the pointer types, to make sure that
- // we recursively strip off low bits if we have a nested PointerUnion.
- return !PointerLikeTypeTraits<PT1>::getFromVoidPointer(Val.getPointer());
- }
- explicit operator bool() const { return !isNull(); }
-
- /// is<T>() return true if the Union currently holds the type matching T.
- template<typename T>
- int is() const {
- typedef typename
- ::llvm::PointerUnionTypeSelector<PT1, T, IsPT1,
- ::llvm::PointerUnionTypeSelector<PT2, T, IsPT2,
- UNION_DOESNT_CONTAIN_TYPE<T> > >::Return Ty;
- int TyNo = Ty::Num;
- return static_cast<int>(Val.getInt()) == TyNo;
- }
-
- /// get<T>() - Return the value of the specified pointer type. If the
- /// specified pointer type is incorrect, assert.
- template<typename T>
- T get() const {
- assert(is<T>() && "Invalid accessor called");
- return PointerLikeTypeTraits<T>::getFromVoidPointer(Val.getPointer());
- }