PointerUnion.h revision acb8d9fbe3853394a2537985349993580309b8cd
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
22128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis  template <typename T>
23128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis  struct PointerUnionTypeSelectorReturn {
24128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis    typedef T Return;
25128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis  };
26128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis
27128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis  /// \brief Get a type based on whether two types are the same or not. For:
28128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis  /// @code
29128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis  /// typedef typename PointerUnionTypeSelector<T1, T2, EQ, NE>::Return Ret;
30128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis  /// @endcode
31128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis  /// Ret will be EQ type if T1 is same as T2 or NE type otherwise.
32128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis  template <typename T1, typename T2, typename RET_EQ, typename RET_NE>
33128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis  struct PointerUnionTypeSelector {
34128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis    typedef typename PointerUnionTypeSelectorReturn<RET_NE>::Return Return;
35128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis  };
36128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis
37128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis  template <typename T, typename RET_EQ, typename RET_NE>
38128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis  struct PointerUnionTypeSelector<T, T, RET_EQ, RET_NE> {
39128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis    typedef typename PointerUnionTypeSelectorReturn<RET_EQ>::Return Return;
40128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis  };
41128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis
42128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis  template <typename T1, typename T2, typename RET_EQ, typename RET_NE>
43128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis  struct PointerUnionTypeSelectorReturn<
44128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis                            PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE> > {
45128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis    typedef typename PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE>::Return
46128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis        Return;
47128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis  };
48128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis
492491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  /// Provide PointerLikeTypeTraits for void* that is used by PointerUnion
502491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  /// for the two template arguments.
512491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  template <typename PT1, typename PT2>
522491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  class PointerUnionUIntTraits {
532491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  public:
542491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    static inline void *getAsVoidPointer(void *P) { return P; }
552491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    static inline void *getFromVoidPointer(void *P) { return P; }
562491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    enum {
57b76fb96cd66aec709e2a0cfda8c29c53ba5ad98cGalina Kistanova      PT1BitsAv = (int)(PointerLikeTypeTraits<PT1>::NumLowBitsAvailable),
58b76fb96cd66aec709e2a0cfda8c29c53ba5ad98cGalina Kistanova      PT2BitsAv = (int)(PointerLikeTypeTraits<PT2>::NumLowBitsAvailable),
592491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      NumLowBitsAvailable = PT1BitsAv < PT2BitsAv ? PT1BitsAv : PT2BitsAv
602491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    };
612491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  };
622491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
632491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  /// PointerUnion - This implements a discriminated union of two pointer types,
642491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  /// and keeps the discriminator bit-mangled into the low bits of the pointer.
652491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  /// This allows the implementation to be extremely efficient in space, but
662491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  /// permits a very natural and type-safe API.
672491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  ///
682491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  /// Common use patterns would be something like this:
692491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  ///    PointerUnion<int*, float*> P;
702491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  ///    P = (int*)0;
712491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  ///    printf("%d %d", P.is<int*>(), P.is<float*>());  // prints "1 0"
722491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  ///    X = P.get<int*>();     // ok.
732491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  ///    Y = P.get<float*>();   // runtime assertion failure.
74f54229192c22559389b0ef47e731fd628db963c5Chris Lattner  ///    Z = P.get<double*>();  // runtime assertion failure (regardless of tag)
752491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  ///    P = (float*)0;
762491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  ///    Y = P.get<float*>();   // ok.
772491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  ///    X = P.get<int*>();     // runtime assertion failure.
782491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  template <typename PT1, typename PT2>
792491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  class PointerUnion {
802491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  public:
812491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    typedef PointerIntPair<void*, 1, bool,
822491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner                           PointerUnionUIntTraits<PT1,PT2> > ValTy;
832491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  private:
842491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    ValTy Val;
85a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis
86a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis    struct IsPT1 {
87a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis      static const int Num = 0;
88a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis    };
89a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis    struct IsPT2 {
90a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis      static const int Num = 1;
91a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis    };
92a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis    template <typename T>
93a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis    struct UNION_DOESNT_CONTAIN_TYPE { };
94a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis
952491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  public:
962491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    PointerUnion() {}
972491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
98acb8d9fbe3853394a2537985349993580309b8cdArgyrios Kyrtzidis    PointerUnion(PT1 V) : Val(
99acb8d9fbe3853394a2537985349993580309b8cdArgyrios Kyrtzidis      const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(V))) {
1002491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    }
101acb8d9fbe3853394a2537985349993580309b8cdArgyrios Kyrtzidis    PointerUnion(PT2 V) : Val(
102acb8d9fbe3853394a2537985349993580309b8cdArgyrios Kyrtzidis      const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(V)), 1) {
1032491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    }
1042491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
10526ef510d5d20b89c637d13e2d9169c0458de775cDouglas Gregor    /// isNull - Return true if the pointer held in the union is null,
1063a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    /// regardless of which type it is.
107823eb1ca11d684530048f1fe85a727aa1ef622d1Chris Lattner    bool isNull() const {
108823eb1ca11d684530048f1fe85a727aa1ef622d1Chris Lattner      // Convert from the void* to one of the pointer types, to make sure that
109823eb1ca11d684530048f1fe85a727aa1ef622d1Chris Lattner      // we recursively strip off low bits if we have a nested PointerUnion.
110823eb1ca11d684530048f1fe85a727aa1ef622d1Chris Lattner      return !PointerLikeTypeTraits<PT1>::getFromVoidPointer(Val.getPointer());
111823eb1ca11d684530048f1fe85a727aa1ef622d1Chris Lattner    }
112e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    operator bool() const { return !isNull(); }
113e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
1143a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    /// is<T>() return true if the Union currently holds the type matching T.
1152491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    template<typename T>
1162491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    int is() const {
117a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis      typedef typename
118a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis        ::llvm::PointerUnionTypeSelector<PT1, T, IsPT1,
119a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis          ::llvm::PointerUnionTypeSelector<PT2, T, IsPT2,
120a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis                                    UNION_DOESNT_CONTAIN_TYPE<T> > >::Return Ty;
121a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis      int TyNo = Ty::Num;
12237c286c18128cce7f52654876a5a104150be4b79Sebastian Redl      return static_cast<int>(Val.getInt()) == TyNo;
1232491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    }
1243a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner
1253a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    /// get<T>() - Return the value of the specified pointer type. If the
1263a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    /// specified pointer type is incorrect, assert.
1272491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    template<typename T>
1282491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    T get() const {
1292491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      assert(is<T>() && "Invalid accessor called");
130e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      return PointerLikeTypeTraits<T>::getFromVoidPointer(Val.getPointer());
1312491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    }
1322491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
1333a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    /// dyn_cast<T>() - If the current value is of the specified pointer type,
1343a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    /// return it, otherwise return null.
1353a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    template<typename T>
1363a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    T dyn_cast() const {
137e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      if (is<T>()) return get<T>();
1383a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner      return T();
1393a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    }
14038297f5f760de604258aaa9000e5aadb43c78921Argyrios Kyrtzidis
1410db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis    /// \brief If the union is set to the first pointer type get an address
1420db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis    /// pointing to it.
1430db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis    PT1 const *getAddrOfPtr1() const {
1440db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis      return const_cast<PointerUnion *>(this)->getAddrOfPtr1();
1450db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis    }
1460db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis
1470db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis    /// \brief If the union is set to the first pointer type get an address
1480db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis    /// pointing to it.
1490db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis    PT1 *getAddrOfPtr1() {
15038297f5f760de604258aaa9000e5aadb43c78921Argyrios Kyrtzidis      assert(is<PT1>() && "Val is not the first pointer");
15138297f5f760de604258aaa9000e5aadb43c78921Argyrios Kyrtzidis      assert(get<PT1>() == Val.getPointer() &&
15238297f5f760de604258aaa9000e5aadb43c78921Argyrios Kyrtzidis         "Can't get the address because PointerLikeTypeTraits changes the ptr");
1530db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis      return (PT1 *)Val.getAddrOfPointer();
15438297f5f760de604258aaa9000e5aadb43c78921Argyrios Kyrtzidis    }
1553a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner
1563a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    /// Assignment operators - Allow assigning into this union from either
1573a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    /// pointer type, setting the discriminator to remember what it came from.
1582491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    const PointerUnion &operator=(const PT1 &RHS) {
159acb8d9fbe3853394a2537985349993580309b8cdArgyrios Kyrtzidis      Val.initWithPointer(
16041222823db11107834414a378525bb21493d3a1fDouglas Gregor         const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(RHS)));
1612491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      return *this;
1622491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    }
1632491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    const PointerUnion &operator=(const PT2 &RHS) {
164acb8d9fbe3853394a2537985349993580309b8cdArgyrios Kyrtzidis      Val.setPointerAndInt(
165acb8d9fbe3853394a2537985349993580309b8cdArgyrios Kyrtzidis        const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(RHS)),
166acb8d9fbe3853394a2537985349993580309b8cdArgyrios Kyrtzidis        1);
1672491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      return *this;
1682491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    }
1692491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
1702491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    void *getOpaqueValue() const { return Val.getOpaqueValue(); }
1718260ea5c6c15345e00ced1398b03e6886145e45cTed Kremenek    static inline PointerUnion getFromOpaqueValue(void *VP) {
1722491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      PointerUnion V;
1732491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      V.Val = ValTy::getFromOpaqueValue(VP);
1742491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      return V;
1752491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    }
1762491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  };
1772491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
178e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  // Teach SmallPtrSet that PointerUnion is "basically a pointer", that has
1792491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  // # low bits available = min(PT1bits,PT2bits)-1.
1802491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  template<typename PT1, typename PT2>
1812491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  class PointerLikeTypeTraits<PointerUnion<PT1, PT2> > {
1822491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  public:
1832491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    static inline void *
1842491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    getAsVoidPointer(const PointerUnion<PT1, PT2> &P) {
1852491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      return P.getOpaqueValue();
1862491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    }
1872491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    static inline PointerUnion<PT1, PT2>
1882491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    getFromVoidPointer(void *P) {
1892491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      return PointerUnion<PT1, PT2>::getFromOpaqueValue(P);
1902491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    }
1912491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
1922491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    // The number of bits available are the min of the two pointer types.
1932491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    enum {
1942491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      NumLowBitsAvailable =
195e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner        PointerLikeTypeTraits<typename PointerUnion<PT1,PT2>::ValTy>
196e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner          ::NumLowBitsAvailable
197e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    };
198e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  };
199e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
200e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
201e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  /// PointerUnion3 - This is a pointer union of three pointer types.  See
202e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  /// documentation for PointerUnion for usage.
203e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  template <typename PT1, typename PT2, typename PT3>
204e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  class PointerUnion3 {
205e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  public:
206e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    typedef PointerUnion<PT1, PT2> InnerUnion;
207e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    typedef PointerUnion<InnerUnion, PT3> ValTy;
208e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  private:
209e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    ValTy Val;
210128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis
211128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis    struct IsInnerUnion {
212128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      ValTy Val;
213128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      IsInnerUnion(ValTy val) : Val(val) { }
214128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      template<typename T>
215128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      int is() const {
216128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis        return Val.template is<InnerUnion>() &&
217128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis               Val.template get<InnerUnion>().template is<T>();
218128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      }
219128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      template<typename T>
220128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      T get() const {
221128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis        return Val.template get<InnerUnion>().template get<T>();
222128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      }
223128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis    };
224128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis
225128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis    struct IsPT3 {
226128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      ValTy Val;
227128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      IsPT3(ValTy val) : Val(val) { }
228128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      template<typename T>
229128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      int is() const {
230128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis        return Val.template is<T>();
231128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      }
232128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      template<typename T>
233128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      T get() const {
234128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis        return Val.template get<T>();
235128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      }
236128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis    };
237128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis
238e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  public:
239e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    PointerUnion3() {}
240e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
241e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    PointerUnion3(PT1 V) {
242e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      Val = InnerUnion(V);
243e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
244e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    PointerUnion3(PT2 V) {
245e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      Val = InnerUnion(V);
246e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
247e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    PointerUnion3(PT3 V) {
248e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      Val = V;
249e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
250e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
25126ef510d5d20b89c637d13e2d9169c0458de775cDouglas Gregor    /// isNull - Return true if the pointer held in the union is null,
252e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    /// regardless of which type it is.
253e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    bool isNull() const { return Val.isNull(); }
254e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    operator bool() const { return !isNull(); }
255e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
256e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    /// is<T>() return true if the Union currently holds the type matching T.
257e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    template<typename T>
258e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    int is() const {
259128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      // If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3.
260128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      typedef typename
261128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis        ::llvm::PointerUnionTypeSelector<PT1, T, IsInnerUnion,
262128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis          ::llvm::PointerUnionTypeSelector<PT2, T, IsInnerUnion, IsPT3 >
263128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis                                                                   >::Return Ty;
26487d8e60505b26960956996550c8b805c81e5b02bDouglas Gregor      return Ty(Val).template is<T>();
265e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
266e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
267e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    /// get<T>() - Return the value of the specified pointer type. If the
268e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    /// specified pointer type is incorrect, assert.
269e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    template<typename T>
270e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    T get() const {
271e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      assert(is<T>() && "Invalid accessor called");
272128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      // If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3.
273128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      typedef typename
274128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis        ::llvm::PointerUnionTypeSelector<PT1, T, IsInnerUnion,
275128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis          ::llvm::PointerUnionTypeSelector<PT2, T, IsInnerUnion, IsPT3 >
276128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis                                                                   >::Return Ty;
27787d8e60505b26960956996550c8b805c81e5b02bDouglas Gregor      return Ty(Val).template get<T>();
278e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
279e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
280e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    /// dyn_cast<T>() - If the current value is of the specified pointer type,
281e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    /// return it, otherwise return null.
282e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    template<typename T>
283e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    T dyn_cast() const {
284e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      if (is<T>()) return get<T>();
285e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      return T();
286e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
287e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
288e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    /// Assignment operators - Allow assigning into this union from either
289e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    /// pointer type, setting the discriminator to remember what it came from.
290e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    const PointerUnion3 &operator=(const PT1 &RHS) {
291e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      Val = InnerUnion(RHS);
292e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      return *this;
293e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
294e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    const PointerUnion3 &operator=(const PT2 &RHS) {
295e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      Val = InnerUnion(RHS);
296e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      return *this;
297e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
298e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    const PointerUnion3 &operator=(const PT3 &RHS) {
299e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      Val = RHS;
300e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      return *this;
301e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
302e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
303e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    void *getOpaqueValue() const { return Val.getOpaqueValue(); }
3048260ea5c6c15345e00ced1398b03e6886145e45cTed Kremenek    static inline PointerUnion3 getFromOpaqueValue(void *VP) {
305e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      PointerUnion3 V;
306e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      V.Val = ValTy::getFromOpaqueValue(VP);
307e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      return V;
308e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
309e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  };
310e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
311e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  // Teach SmallPtrSet that PointerUnion3 is "basically a pointer", that has
312e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  // # low bits available = min(PT1bits,PT2bits,PT2bits)-2.
313e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  template<typename PT1, typename PT2, typename PT3>
314e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  class PointerLikeTypeTraits<PointerUnion3<PT1, PT2, PT3> > {
315e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  public:
316e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    static inline void *
317e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    getAsVoidPointer(const PointerUnion3<PT1, PT2, PT3> &P) {
318e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      return P.getOpaqueValue();
319e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
320e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    static inline PointerUnion3<PT1, PT2, PT3>
321e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    getFromVoidPointer(void *P) {
322e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      return PointerUnion3<PT1, PT2, PT3>::getFromOpaqueValue(P);
323e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
324e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
325e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    // The number of bits available are the min of the two pointer types.
326e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    enum {
327e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      NumLowBitsAvailable =
328e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner        PointerLikeTypeTraits<typename PointerUnion3<PT1, PT2, PT3>::ValTy>
329e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner          ::NumLowBitsAvailable
3302491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    };
3312491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  };
332e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor
333e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  /// PointerUnion4 - This is a pointer union of four pointer types.  See
334e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  /// documentation for PointerUnion for usage.
335e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  template <typename PT1, typename PT2, typename PT3, typename PT4>
336e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  class PointerUnion4 {
337e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  public:
338e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    typedef PointerUnion<PT1, PT2> InnerUnion1;
339e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    typedef PointerUnion<PT3, PT4> InnerUnion2;
340e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    typedef PointerUnion<InnerUnion1, InnerUnion2> ValTy;
341e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  private:
342e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    ValTy Val;
343e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  public:
344e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    PointerUnion4() {}
345e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor
346e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    PointerUnion4(PT1 V) {
347e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      Val = InnerUnion1(V);
348e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
349e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    PointerUnion4(PT2 V) {
350e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      Val = InnerUnion1(V);
351e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
352e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    PointerUnion4(PT3 V) {
353e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      Val = InnerUnion2(V);
354e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
355e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    PointerUnion4(PT4 V) {
356e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      Val = InnerUnion2(V);
357e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
358e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor
35926ef510d5d20b89c637d13e2d9169c0458de775cDouglas Gregor    /// isNull - Return true if the pointer held in the union is null,
360e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    /// regardless of which type it is.
361e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    bool isNull() const { return Val.isNull(); }
362e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    operator bool() const { return !isNull(); }
363e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor
364e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    /// is<T>() return true if the Union currently holds the type matching T.
365e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    template<typename T>
366e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    int is() const {
367128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      // If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2.
368128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      typedef typename
369128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis        ::llvm::PointerUnionTypeSelector<PT1, T, InnerUnion1,
370128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis          ::llvm::PointerUnionTypeSelector<PT2, T, InnerUnion1, InnerUnion2 >
371128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis                                                                   >::Return Ty;
372128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      return Val.template is<Ty>() &&
373128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis             Val.template get<Ty>().template is<T>();
374e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
375e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor
376e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    /// get<T>() - Return the value of the specified pointer type. If the
377e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    /// specified pointer type is incorrect, assert.
378e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    template<typename T>
379e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    T get() const {
380e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      assert(is<T>() && "Invalid accessor called");
381128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      // If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2.
382128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      typedef typename
383128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis        ::llvm::PointerUnionTypeSelector<PT1, T, InnerUnion1,
384128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis          ::llvm::PointerUnionTypeSelector<PT2, T, InnerUnion1, InnerUnion2 >
385128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis                                                                   >::Return Ty;
386128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      return Val.template get<Ty>().template get<T>();
387e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
388e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor
389e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    /// dyn_cast<T>() - If the current value is of the specified pointer type,
390e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    /// return it, otherwise return null.
391e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    template<typename T>
392e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    T dyn_cast() const {
393e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      if (is<T>()) return get<T>();
394e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      return T();
395e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
396e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor
397e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    /// Assignment operators - Allow assigning into this union from either
398e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    /// pointer type, setting the discriminator to remember what it came from.
399e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    const PointerUnion4 &operator=(const PT1 &RHS) {
400e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      Val = InnerUnion1(RHS);
401e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      return *this;
402e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
403e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    const PointerUnion4 &operator=(const PT2 &RHS) {
404e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      Val = InnerUnion1(RHS);
405e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      return *this;
406e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
407e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    const PointerUnion4 &operator=(const PT3 &RHS) {
408e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      Val = InnerUnion2(RHS);
409e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      return *this;
410e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
411e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    const PointerUnion4 &operator=(const PT4 &RHS) {
412e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      Val = InnerUnion2(RHS);
413e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      return *this;
414e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
415e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor
416e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    void *getOpaqueValue() const { return Val.getOpaqueValue(); }
4178260ea5c6c15345e00ced1398b03e6886145e45cTed Kremenek    static inline PointerUnion4 getFromOpaqueValue(void *VP) {
418e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      PointerUnion4 V;
419e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      V.Val = ValTy::getFromOpaqueValue(VP);
420e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      return V;
421e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
422e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  };
423e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor
424e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  // Teach SmallPtrSet that PointerUnion4 is "basically a pointer", that has
425e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  // # low bits available = min(PT1bits,PT2bits,PT2bits)-2.
426e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  template<typename PT1, typename PT2, typename PT3, typename PT4>
427e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  class PointerLikeTypeTraits<PointerUnion4<PT1, PT2, PT3, PT4> > {
428e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  public:
429e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    static inline void *
430e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    getAsVoidPointer(const PointerUnion4<PT1, PT2, PT3, PT4> &P) {
431e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      return P.getOpaqueValue();
432e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
433e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    static inline PointerUnion4<PT1, PT2, PT3, PT4>
434e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    getFromVoidPointer(void *P) {
435e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      return PointerUnion4<PT1, PT2, PT3, PT4>::getFromOpaqueValue(P);
436e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
437e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor
438e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    // The number of bits available are the min of the two pointer types.
439e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    enum {
440e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      NumLowBitsAvailable =
441e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor        PointerLikeTypeTraits<typename PointerUnion4<PT1, PT2, PT3, PT4>::ValTy>
442e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor          ::NumLowBitsAvailable
443e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    };
444e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  };
4452491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner}
4462491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
4472491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner#endif
448