PointerUnion.h revision e8bc475668ddd2f31f44dd00b042d15b255e1b9e
12491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner//===- llvm/ADT/PointerUnion.h - Discriminated Union of 2 Ptrs --*- C++ -*-===//
22491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner//
32491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner//                     The LLVM Compiler Infrastructure
42491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner//
52491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner// This file is distributed under the University of Illinois Open Source
62491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner// License. See LICENSE.TXT for details.
72491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner//
82491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner//===----------------------------------------------------------------------===//
92491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner//
102491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner// This file defines the PointerUnion class, which is a discriminated union of
112491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner// pointer types.
122491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner//
132491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner//===----------------------------------------------------------------------===//
142491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
152491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner#ifndef LLVM_ADT_POINTERUNION_H
162491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner#define LLVM_ADT_POINTERUNION_H
172491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
182491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner#include "llvm/ADT/PointerIntPair.h"
192491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
202491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattnernamespace llvm {
212491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
222491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  /// getPointerUnionTypeNum - If the argument has type PT1* or PT2* return
232491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  /// false or true respectively.
242491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  template <typename PT1, typename PT2>
25e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  static inline int getPointerUnionTypeNum(PT1 *P) { return 0; }
262491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  template <typename PT1, typename PT2>
27e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  static inline int getPointerUnionTypeNum(PT2 *P) { return 1; }
28e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  template <typename PT1, typename PT2>
29e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  static inline int getPointerUnionTypeNum(...) { return -1; }
302491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
312491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
322491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  /// Provide PointerLikeTypeTraits for void* that is used by PointerUnion
332491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  /// for the two template arguments.
342491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  template <typename PT1, typename PT2>
352491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  class PointerUnionUIntTraits {
362491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  public:
372491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    static inline void *getAsVoidPointer(void *P) { return P; }
382491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    static inline void *getFromVoidPointer(void *P) { return P; }
392491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    enum {
402491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      PT1BitsAv = PointerLikeTypeTraits<PT1>::NumLowBitsAvailable,
412491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      PT2BitsAv = PointerLikeTypeTraits<PT2>::NumLowBitsAvailable,
422491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      NumLowBitsAvailable = PT1BitsAv < PT2BitsAv ? PT1BitsAv : PT2BitsAv
432491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    };
442491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  };
452491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
462491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  /// PointerUnion - This implements a discriminated union of two pointer types,
472491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  /// and keeps the discriminator bit-mangled into the low bits of the pointer.
482491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  /// This allows the implementation to be extremely efficient in space, but
492491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  /// permits a very natural and type-safe API.
502491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  ///
512491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  /// Common use patterns would be something like this:
522491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  ///    PointerUnion<int*, float*> P;
532491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  ///    P = (int*)0;
542491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  ///    printf("%d %d", P.is<int*>(), P.is<float*>());  // prints "1 0"
552491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  ///    X = P.get<int*>();     // ok.
562491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  ///    Y = P.get<float*>();   // runtime assertion failure.
572491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  ///    Z = P.get<double*>();  // does not compile.
582491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  ///    P = (float*)0;
592491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  ///    Y = P.get<float*>();   // ok.
602491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  ///    X = P.get<int*>();     // runtime assertion failure.
612491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  template <typename PT1, typename PT2>
622491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  class PointerUnion {
632491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  public:
642491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    typedef PointerIntPair<void*, 1, bool,
652491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner                           PointerUnionUIntTraits<PT1,PT2> > ValTy;
662491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  private:
672491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    ValTy Val;
682491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  public:
692491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    PointerUnion() {}
702491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
712491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    PointerUnion(PT1 V) {
72e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      Val.setPointer(PointerLikeTypeTraits<PT1>::getAsVoidPointer(V));
732491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      Val.setInt(0);
742491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    }
752491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    PointerUnion(PT2 V) {
76e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      Val.setPointer(PointerLikeTypeTraits<PT2>::getAsVoidPointer(V));
772491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      Val.setInt(1);
782491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    }
792491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
803a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    /// isNull - Return true if the pointer help in the union is null,
813a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    /// regardless of which type it is.
82ba315c1ee7bef78c6824441fe6c1761596ec9880Chris Lattner    bool isNull() const { return Val.getPointer() == 0; }
83e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    operator bool() const { return !isNull(); }
84e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
853a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    /// is<T>() return true if the Union currently holds the type matching T.
862491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    template<typename T>
872491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    int is() const {
88e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      int TyNo = ::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0);
89e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      assert(TyNo != -1 && "Type query could never succeed on PointerUnion!");
90e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      return Val.getInt() == TyNo;
912491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    }
923a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner
933a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    /// get<T>() - Return the value of the specified pointer type. If the
943a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    /// specified pointer type is incorrect, assert.
952491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    template<typename T>
962491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    T get() const {
972491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      assert(is<T>() && "Invalid accessor called");
98e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      return PointerLikeTypeTraits<T>::getFromVoidPointer(Val.getPointer());
992491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    }
1002491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
1013a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    /// dyn_cast<T>() - If the current value is of the specified pointer type,
1023a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    /// return it, otherwise return null.
1033a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    template<typename T>
1043a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    T dyn_cast() const {
105e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      if (is<T>()) return get<T>();
1063a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner      return T();
1073a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    }
1083a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner
1093a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    /// Assignment operators - Allow assigning into this union from either
1103a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    /// pointer type, setting the discriminator to remember what it came from.
1112491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    const PointerUnion &operator=(const PT1 &RHS) {
112e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      Val.setPointer(PointerLikeTypeTraits<PT1>::getAsVoidPointer(RHS));
1132491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      Val.setInt(0);
1142491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      return *this;
1152491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    }
1162491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    const PointerUnion &operator=(const PT2 &RHS) {
117e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      Val.setPointer(PointerLikeTypeTraits<PT2>::getAsVoidPointer(RHS));
1182491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      Val.setInt(1);
1192491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      return *this;
1202491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    }
1212491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
1222491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    void *getOpaqueValue() const { return Val.getOpaqueValue(); }
1232491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    static PointerUnion getFromOpaqueValue(void *VP) {
1242491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      PointerUnion V;
1252491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      V.Val = ValTy::getFromOpaqueValue(VP);
1262491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      return V;
1272491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    }
1282491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  };
1292491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
130e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  // Teach SmallPtrSet that PointerUnion is "basically a pointer", that has
1312491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  // # low bits available = min(PT1bits,PT2bits)-1.
1322491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  template<typename PT1, typename PT2>
1332491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  class PointerLikeTypeTraits<PointerUnion<PT1, PT2> > {
1342491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  public:
1352491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    static inline void *
1362491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    getAsVoidPointer(const PointerUnion<PT1, PT2> &P) {
1372491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      return P.getOpaqueValue();
1382491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    }
1392491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    static inline PointerUnion<PT1, PT2>
1402491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    getFromVoidPointer(void *P) {
1412491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      return PointerUnion<PT1, PT2>::getFromOpaqueValue(P);
1422491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    }
1432491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
1442491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    // The number of bits available are the min of the two pointer types.
1452491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    enum {
1462491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      NumLowBitsAvailable =
147e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner        PointerLikeTypeTraits<typename PointerUnion<PT1,PT2>::ValTy>
148e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner          ::NumLowBitsAvailable
149e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    };
150e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  };
151e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
152e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
153e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  /// PointerUnion3 - This is a pointer union of three pointer types.  See
154e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  /// documentation for PointerUnion for usage.
155e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  template <typename PT1, typename PT2, typename PT3>
156e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  class PointerUnion3 {
157e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  public:
158e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    typedef PointerUnion<PT1, PT2> InnerUnion;
159e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    typedef PointerUnion<InnerUnion, PT3> ValTy;
160e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  private:
161e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    ValTy Val;
162e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  public:
163e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    PointerUnion3() {}
164e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
165e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    PointerUnion3(PT1 V) {
166e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      Val = InnerUnion(V);
167e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
168e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    PointerUnion3(PT2 V) {
169e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      Val = InnerUnion(V);
170e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
171e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    PointerUnion3(PT3 V) {
172e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      Val = V;
173e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
174e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
175e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    /// isNull - Return true if the pointer help in the union is null,
176e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    /// regardless of which type it is.
177e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    bool isNull() const { return Val.isNull(); }
178e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    operator bool() const { return !isNull(); }
179e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
180e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    /// is<T>() return true if the Union currently holds the type matching T.
181e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    template<typename T>
182e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    int is() const {
183e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      // Is it PT1/PT2?
184e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      if (::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0) != -1)
185e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner        return Val.get<InnerUnion>().is<T>();
186e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      // Must be PT3 or statically invalid.
187e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      assert(Val.is<T>());
188e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      return true;
189e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
190e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
191e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    /// get<T>() - Return the value of the specified pointer type. If the
192e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    /// specified pointer type is incorrect, assert.
193e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    template<typename T>
194e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    T get() const {
195e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      assert(is<T>() && "Invalid accessor called");
196e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      if (Val.is<T>())
197e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner        return Val.get<T>();
198e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      return Val.get<InnerUnion>().get<T>();
199e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
200e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
201e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    /// dyn_cast<T>() - If the current value is of the specified pointer type,
202e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    /// return it, otherwise return null.
203e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    template<typename T>
204e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    T dyn_cast() const {
205e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      if (is<T>()) return get<T>();
206e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      return T();
207e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
208e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
209e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    /// Assignment operators - Allow assigning into this union from either
210e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    /// pointer type, setting the discriminator to remember what it came from.
211e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    const PointerUnion3 &operator=(const PT1 &RHS) {
212e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      Val = InnerUnion(RHS);
213e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      return *this;
214e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
215e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    const PointerUnion3 &operator=(const PT2 &RHS) {
216e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      Val = InnerUnion(RHS);
217e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      return *this;
218e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
219e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    const PointerUnion3 &operator=(const PT3 &RHS) {
220e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      Val = RHS;
221e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      return *this;
222e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
223e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
224e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    void *getOpaqueValue() const { return Val.getOpaqueValue(); }
225e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    static PointerUnion3 getFromOpaqueValue(void *VP) {
226e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      PointerUnion3 V;
227e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      V.Val = ValTy::getFromOpaqueValue(VP);
228e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      return V;
229e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
230e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  };
231e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
232e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  // Teach SmallPtrSet that PointerUnion3 is "basically a pointer", that has
233e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  // # low bits available = min(PT1bits,PT2bits,PT2bits)-2.
234e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  template<typename PT1, typename PT2, typename PT3>
235e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  class PointerLikeTypeTraits<PointerUnion3<PT1, PT2, PT3> > {
236e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  public:
237e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    static inline void *
238e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    getAsVoidPointer(const PointerUnion3<PT1, PT2, PT3> &P) {
239e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      return P.getOpaqueValue();
240e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
241e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    static inline PointerUnion3<PT1, PT2, PT3>
242e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    getFromVoidPointer(void *P) {
243e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      return PointerUnion3<PT1, PT2, PT3>::getFromOpaqueValue(P);
244e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
245e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
246e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    // The number of bits available are the min of the two pointer types.
247e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    enum {
248e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      NumLowBitsAvailable =
249e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner        PointerLikeTypeTraits<typename PointerUnion3<PT1, PT2, PT3>::ValTy>
250e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner          ::NumLowBitsAvailable
2512491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    };
2522491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  };
2532491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner}
2542491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
2552491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner#endif
256