PointerUnion.h revision 8260ea5c6c15345e00ced1398b03e6886145e45c
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.
57f54229192c22559389b0ef47e731fd628db963c5Chris Lattner  ///    Z = P.get<double*>();  // runtime assertion failure (regardless of tag)
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) {
7241222823db11107834414a378525bb21493d3a1fDouglas Gregor      Val.setPointer(
7341222823db11107834414a378525bb21493d3a1fDouglas Gregor         const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(V)));
742491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      Val.setInt(0);
752491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    }
762491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    PointerUnion(PT2 V) {
7741222823db11107834414a378525bb21493d3a1fDouglas Gregor      Val.setPointer(
7841222823db11107834414a378525bb21493d3a1fDouglas Gregor         const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(V)));
792491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      Val.setInt(1);
802491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    }
812491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
8226ef510d5d20b89c637d13e2d9169c0458de775cDouglas Gregor    /// isNull - Return true if the pointer held in the union is null,
833a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    /// regardless of which type it is.
84ba315c1ee7bef78c6824441fe6c1761596ec9880Chris Lattner    bool isNull() const { return Val.getPointer() == 0; }
85e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    operator bool() const { return !isNull(); }
86e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
873a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    /// is<T>() return true if the Union currently holds the type matching T.
882491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    template<typename T>
892491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    int is() const {
90e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      int TyNo = ::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0);
91e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      assert(TyNo != -1 && "Type query could never succeed on PointerUnion!");
9237c286c18128cce7f52654876a5a104150be4b79Sebastian Redl      return static_cast<int>(Val.getInt()) == TyNo;
932491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    }
943a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner
953a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    /// get<T>() - Return the value of the specified pointer type. If the
963a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    /// specified pointer type is incorrect, assert.
972491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    template<typename T>
982491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    T get() const {
992491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      assert(is<T>() && "Invalid accessor called");
100e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      return PointerLikeTypeTraits<T>::getFromVoidPointer(Val.getPointer());
1012491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    }
1022491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
1033a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    /// dyn_cast<T>() - If the current value is of the specified pointer type,
1043a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    /// return it, otherwise return null.
1053a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    template<typename T>
1063a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    T dyn_cast() const {
107e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      if (is<T>()) return get<T>();
1083a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner      return T();
1093a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    }
1103a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner
1113a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    /// Assignment operators - Allow assigning into this union from either
1123a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    /// pointer type, setting the discriminator to remember what it came from.
1132491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    const PointerUnion &operator=(const PT1 &RHS) {
11441222823db11107834414a378525bb21493d3a1fDouglas Gregor      Val.setPointer(
11541222823db11107834414a378525bb21493d3a1fDouglas Gregor         const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(RHS)));
1162491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      Val.setInt(0);
1172491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      return *this;
1182491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    }
1192491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    const PointerUnion &operator=(const PT2 &RHS) {
12041222823db11107834414a378525bb21493d3a1fDouglas Gregor      Val.setPointer(
12141222823db11107834414a378525bb21493d3a1fDouglas Gregor        const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(RHS)));
1222491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      Val.setInt(1);
1232491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      return *this;
1242491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    }
1252491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
1262491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    void *getOpaqueValue() const { return Val.getOpaqueValue(); }
1278260ea5c6c15345e00ced1398b03e6886145e45cTed Kremenek    static inline PointerUnion getFromOpaqueValue(void *VP) {
1282491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      PointerUnion V;
1292491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      V.Val = ValTy::getFromOpaqueValue(VP);
1302491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      return V;
1312491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    }
1322491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  };
1332491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
134e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  // Teach SmallPtrSet that PointerUnion is "basically a pointer", that has
1352491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  // # low bits available = min(PT1bits,PT2bits)-1.
1362491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  template<typename PT1, typename PT2>
1372491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  class PointerLikeTypeTraits<PointerUnion<PT1, PT2> > {
1382491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  public:
1392491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    static inline void *
1402491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    getAsVoidPointer(const PointerUnion<PT1, PT2> &P) {
1412491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      return P.getOpaqueValue();
1422491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    }
1432491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    static inline PointerUnion<PT1, PT2>
1442491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    getFromVoidPointer(void *P) {
1452491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      return PointerUnion<PT1, PT2>::getFromOpaqueValue(P);
1462491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    }
1472491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
1482491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    // The number of bits available are the min of the two pointer types.
1492491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    enum {
1502491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      NumLowBitsAvailable =
151e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner        PointerLikeTypeTraits<typename PointerUnion<PT1,PT2>::ValTy>
152e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner          ::NumLowBitsAvailable
153e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    };
154e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  };
155e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
156e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
157e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  /// PointerUnion3 - This is a pointer union of three pointer types.  See
158e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  /// documentation for PointerUnion for usage.
159e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  template <typename PT1, typename PT2, typename PT3>
160e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  class PointerUnion3 {
161e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  public:
162e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    typedef PointerUnion<PT1, PT2> InnerUnion;
163e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    typedef PointerUnion<InnerUnion, PT3> ValTy;
164e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  private:
165e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    ValTy Val;
166e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  public:
167e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    PointerUnion3() {}
168e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
169e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    PointerUnion3(PT1 V) {
170e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      Val = InnerUnion(V);
171e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
172e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    PointerUnion3(PT2 V) {
173e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      Val = InnerUnion(V);
174e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
175e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    PointerUnion3(PT3 V) {
176e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      Val = V;
177e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
178e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
17926ef510d5d20b89c637d13e2d9169c0458de775cDouglas Gregor    /// isNull - Return true if the pointer held in the union is null,
180e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    /// regardless of which type it is.
181e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    bool isNull() const { return Val.isNull(); }
182e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    operator bool() const { return !isNull(); }
183e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
184e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    /// is<T>() return true if the Union currently holds the type matching T.
185e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    template<typename T>
186e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    int is() const {
187e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      // Is it PT1/PT2?
188e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      if (::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0) != -1)
1896a66b388469f045c9fcff839595900c9f1512177Douglas Gregor        return Val.template is<InnerUnion>() &&
1906a66b388469f045c9fcff839595900c9f1512177Douglas Gregor               Val.template get<InnerUnion>().template is<T>();
1916a66b388469f045c9fcff839595900c9f1512177Douglas Gregor      return Val.template is<T>();
192e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
193e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
194e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    /// get<T>() - Return the value of the specified pointer type. If the
195e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    /// specified pointer type is incorrect, assert.
196e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    template<typename T>
197e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    T get() const {
198e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      assert(is<T>() && "Invalid accessor called");
1992048cdb08ef6ad04bd1baf52886605d455236eb7Douglas Gregor      // Is it PT1/PT2?
2002048cdb08ef6ad04bd1baf52886605d455236eb7Douglas Gregor      if (::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0) != -1)
2016a66b388469f045c9fcff839595900c9f1512177Douglas Gregor        return Val.template get<InnerUnion>().template get<T>();
2022048cdb08ef6ad04bd1baf52886605d455236eb7Douglas Gregor
2036a66b388469f045c9fcff839595900c9f1512177Douglas Gregor      return Val.template get<T>();
204e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
205e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
206e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    /// dyn_cast<T>() - If the current value is of the specified pointer type,
207e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    /// return it, otherwise return null.
208e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    template<typename T>
209e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    T dyn_cast() const {
210e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      if (is<T>()) return get<T>();
211e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      return T();
212e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
213e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
214e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    /// Assignment operators - Allow assigning into this union from either
215e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    /// pointer type, setting the discriminator to remember what it came from.
216e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    const PointerUnion3 &operator=(const PT1 &RHS) {
217e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      Val = InnerUnion(RHS);
218e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      return *this;
219e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
220e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    const PointerUnion3 &operator=(const PT2 &RHS) {
221e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      Val = InnerUnion(RHS);
222e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      return *this;
223e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
224e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    const PointerUnion3 &operator=(const PT3 &RHS) {
225e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      Val = RHS;
226e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      return *this;
227e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
228e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
229e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    void *getOpaqueValue() const { return Val.getOpaqueValue(); }
2308260ea5c6c15345e00ced1398b03e6886145e45cTed Kremenek    static inline PointerUnion3 getFromOpaqueValue(void *VP) {
231e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      PointerUnion3 V;
232e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      V.Val = ValTy::getFromOpaqueValue(VP);
233e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      return V;
234e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
235e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  };
236e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
237e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  // Teach SmallPtrSet that PointerUnion3 is "basically a pointer", that has
238e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  // # low bits available = min(PT1bits,PT2bits,PT2bits)-2.
239e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  template<typename PT1, typename PT2, typename PT3>
240e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  class PointerLikeTypeTraits<PointerUnion3<PT1, PT2, PT3> > {
241e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  public:
242e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    static inline void *
243e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    getAsVoidPointer(const PointerUnion3<PT1, PT2, PT3> &P) {
244e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      return P.getOpaqueValue();
245e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
246e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    static inline PointerUnion3<PT1, PT2, PT3>
247e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    getFromVoidPointer(void *P) {
248e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      return PointerUnion3<PT1, PT2, PT3>::getFromOpaqueValue(P);
249e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
250e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
251e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    // The number of bits available are the min of the two pointer types.
252e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    enum {
253e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      NumLowBitsAvailable =
254e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner        PointerLikeTypeTraits<typename PointerUnion3<PT1, PT2, PT3>::ValTy>
255e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner          ::NumLowBitsAvailable
2562491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    };
2572491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  };
258e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor
259e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  /// PointerUnion4 - This is a pointer union of four pointer types.  See
260e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  /// documentation for PointerUnion for usage.
261e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  template <typename PT1, typename PT2, typename PT3, typename PT4>
262e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  class PointerUnion4 {
263e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  public:
264e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    typedef PointerUnion<PT1, PT2> InnerUnion1;
265e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    typedef PointerUnion<PT3, PT4> InnerUnion2;
266e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    typedef PointerUnion<InnerUnion1, InnerUnion2> ValTy;
267e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  private:
268e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    ValTy Val;
269e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  public:
270e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    PointerUnion4() {}
271e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor
272e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    PointerUnion4(PT1 V) {
273e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      Val = InnerUnion1(V);
274e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
275e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    PointerUnion4(PT2 V) {
276e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      Val = InnerUnion1(V);
277e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
278e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    PointerUnion4(PT3 V) {
279e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      Val = InnerUnion2(V);
280e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
281e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    PointerUnion4(PT4 V) {
282e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      Val = InnerUnion2(V);
283e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
284e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor
28526ef510d5d20b89c637d13e2d9169c0458de775cDouglas Gregor    /// isNull - Return true if the pointer held in the union is null,
286e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    /// regardless of which type it is.
287e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    bool isNull() const { return Val.isNull(); }
288e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    operator bool() const { return !isNull(); }
289e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor
290e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    /// is<T>() return true if the Union currently holds the type matching T.
291e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    template<typename T>
292e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    int is() const {
293e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      // Is it PT1/PT2?
294e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      if (::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0) != -1)
2956a66b388469f045c9fcff839595900c9f1512177Douglas Gregor        return Val.template is<InnerUnion1>() &&
2966a66b388469f045c9fcff839595900c9f1512177Douglas Gregor               Val.template get<InnerUnion1>().template is<T>();
2976a66b388469f045c9fcff839595900c9f1512177Douglas Gregor      return Val.template is<InnerUnion2>() &&
2986a66b388469f045c9fcff839595900c9f1512177Douglas Gregor             Val.template get<InnerUnion2>().template is<T>();
299e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
300e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor
301e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    /// get<T>() - Return the value of the specified pointer type. If the
302e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    /// specified pointer type is incorrect, assert.
303e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    template<typename T>
304e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    T get() const {
305e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      assert(is<T>() && "Invalid accessor called");
306e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      // Is it PT1/PT2?
307e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      if (::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0) != -1)
3086a66b388469f045c9fcff839595900c9f1512177Douglas Gregor        return Val.template get<InnerUnion1>().template get<T>();
309e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor
3106a66b388469f045c9fcff839595900c9f1512177Douglas Gregor      return Val.template get<InnerUnion2>().template get<T>();
311e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
312e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor
313e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    /// dyn_cast<T>() - If the current value is of the specified pointer type,
314e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    /// return it, otherwise return null.
315e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    template<typename T>
316e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    T dyn_cast() const {
317e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      if (is<T>()) return get<T>();
318e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      return T();
319e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
320e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor
321e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    /// Assignment operators - Allow assigning into this union from either
322e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    /// pointer type, setting the discriminator to remember what it came from.
323e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    const PointerUnion4 &operator=(const PT1 &RHS) {
324e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      Val = InnerUnion1(RHS);
325e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      return *this;
326e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
327e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    const PointerUnion4 &operator=(const PT2 &RHS) {
328e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      Val = InnerUnion1(RHS);
329e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      return *this;
330e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
331e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    const PointerUnion4 &operator=(const PT3 &RHS) {
332e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      Val = InnerUnion2(RHS);
333e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      return *this;
334e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
335e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    const PointerUnion4 &operator=(const PT4 &RHS) {
336e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      Val = InnerUnion2(RHS);
337e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      return *this;
338e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
339e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor
340e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    void *getOpaqueValue() const { return Val.getOpaqueValue(); }
3418260ea5c6c15345e00ced1398b03e6886145e45cTed Kremenek    static inline PointerUnion4 getFromOpaqueValue(void *VP) {
342e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      PointerUnion4 V;
343e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      V.Val = ValTy::getFromOpaqueValue(VP);
344e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      return V;
345e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
346e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  };
347e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor
348e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  // Teach SmallPtrSet that PointerUnion4 is "basically a pointer", that has
349e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  // # low bits available = min(PT1bits,PT2bits,PT2bits)-2.
350e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  template<typename PT1, typename PT2, typename PT3, typename PT4>
351e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  class PointerLikeTypeTraits<PointerUnion4<PT1, PT2, PT3, PT4> > {
352e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  public:
353e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    static inline void *
354e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    getAsVoidPointer(const PointerUnion4<PT1, PT2, PT3, PT4> &P) {
355e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      return P.getOpaqueValue();
356e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
357e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    static inline PointerUnion4<PT1, PT2, PT3, PT4>
358e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    getFromVoidPointer(void *P) {
359e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      return PointerUnion4<PT1, PT2, PT3, PT4>::getFromOpaqueValue(P);
360e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
361e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor
362e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    // The number of bits available are the min of the two pointer types.
363e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    enum {
364e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      NumLowBitsAvailable =
365e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor        PointerLikeTypeTraits<typename PointerUnion4<PT1, PT2, PT3, PT4>::ValTy>
366e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor          ::NumLowBitsAvailable
367e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    };
368e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  };
3692491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner}
3702491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
3712491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner#endif
372