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
18dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#include "llvm/ADT/DenseMapInfo.h"
192491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner#include "llvm/ADT/PointerIntPair.h"
2036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/Support/Compiler.h"
212491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
222491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattnernamespace llvm {
232491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
24128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis  template <typename T>
25128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis  struct PointerUnionTypeSelectorReturn {
26128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis    typedef T Return;
27128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis  };
28128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis
29128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis  /// \brief Get a type based on whether two types are the same or not. For:
30128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis  /// @code
31128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis  /// typedef typename PointerUnionTypeSelector<T1, T2, EQ, NE>::Return Ret;
32128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis  /// @endcode
33128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis  /// Ret will be EQ type if T1 is same as T2 or NE type otherwise.
34128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis  template <typename T1, typename T2, typename RET_EQ, typename RET_NE>
35128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis  struct PointerUnionTypeSelector {
36128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis    typedef typename PointerUnionTypeSelectorReturn<RET_NE>::Return Return;
37128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis  };
38128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis
39128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis  template <typename T, typename RET_EQ, typename RET_NE>
40128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis  struct PointerUnionTypeSelector<T, T, RET_EQ, RET_NE> {
41128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis    typedef typename PointerUnionTypeSelectorReturn<RET_EQ>::Return Return;
42128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis  };
43128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis
44128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis  template <typename T1, typename T2, typename RET_EQ, typename RET_NE>
45128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis  struct PointerUnionTypeSelectorReturn<
46128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis                            PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE> > {
47128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis    typedef typename PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE>::Return
48128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis        Return;
49128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis  };
50128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis
512491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  /// Provide PointerLikeTypeTraits for void* that is used by PointerUnion
522491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  /// for the two template arguments.
532491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  template <typename PT1, typename PT2>
542491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  class PointerUnionUIntTraits {
552491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  public:
562491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    static inline void *getAsVoidPointer(void *P) { return P; }
572491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    static inline void *getFromVoidPointer(void *P) { return P; }
582491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    enum {
59b76fb96cd66aec709e2a0cfda8c29c53ba5ad98cGalina Kistanova      PT1BitsAv = (int)(PointerLikeTypeTraits<PT1>::NumLowBitsAvailable),
60b76fb96cd66aec709e2a0cfda8c29c53ba5ad98cGalina Kistanova      PT2BitsAv = (int)(PointerLikeTypeTraits<PT2>::NumLowBitsAvailable),
612491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      NumLowBitsAvailable = PT1BitsAv < PT2BitsAv ? PT1BitsAv : PT2BitsAv
622491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    };
632491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  };
642491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
652491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  /// PointerUnion - This implements a discriminated union of two pointer types,
662491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  /// and keeps the discriminator bit-mangled into the low bits of the pointer.
672491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  /// This allows the implementation to be extremely efficient in space, but
682491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  /// permits a very natural and type-safe API.
692491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  ///
702491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  /// Common use patterns would be something like this:
712491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  ///    PointerUnion<int*, float*> P;
722491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  ///    P = (int*)0;
732491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  ///    printf("%d %d", P.is<int*>(), P.is<float*>());  // prints "1 0"
742491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  ///    X = P.get<int*>();     // ok.
752491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  ///    Y = P.get<float*>();   // runtime assertion failure.
76296ca41b2d305f4aaf1d0562c7da90dc20cd9e14David Blaikie  ///    Z = P.get<double*>();  // compile time failure.
772491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  ///    P = (float*)0;
782491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  ///    Y = P.get<float*>();   // ok.
792491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  ///    X = P.get<int*>();     // runtime assertion failure.
802491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  template <typename PT1, typename PT2>
812491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  class PointerUnion {
822491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  public:
832491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    typedef PointerIntPair<void*, 1, bool,
842491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner                           PointerUnionUIntTraits<PT1,PT2> > ValTy;
852491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  private:
862491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    ValTy Val;
87a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis
88a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis    struct IsPT1 {
89a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis      static const int Num = 0;
90a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis    };
91a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis    struct IsPT2 {
92a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis      static const int Num = 1;
93a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis    };
94a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis    template <typename T>
95a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis    struct UNION_DOESNT_CONTAIN_TYPE { };
96a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis
972491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  public:
982491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    PointerUnion() {}
992491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
100acb8d9fbe3853394a2537985349993580309b8cdArgyrios Kyrtzidis    PointerUnion(PT1 V) : Val(
101acb8d9fbe3853394a2537985349993580309b8cdArgyrios Kyrtzidis      const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(V))) {
1022491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    }
103acb8d9fbe3853394a2537985349993580309b8cdArgyrios Kyrtzidis    PointerUnion(PT2 V) : Val(
104acb8d9fbe3853394a2537985349993580309b8cdArgyrios Kyrtzidis      const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(V)), 1) {
1052491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    }
1062491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
10726ef510d5d20b89c637d13e2d9169c0458de775cDouglas Gregor    /// isNull - Return true if the pointer held in the union is null,
1083a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    /// regardless of which type it is.
109823eb1ca11d684530048f1fe85a727aa1ef622d1Chris Lattner    bool isNull() const {
110823eb1ca11d684530048f1fe85a727aa1ef622d1Chris Lattner      // Convert from the void* to one of the pointer types, to make sure that
111823eb1ca11d684530048f1fe85a727aa1ef622d1Chris Lattner      // we recursively strip off low bits if we have a nested PointerUnion.
112823eb1ca11d684530048f1fe85a727aa1ef622d1Chris Lattner      return !PointerLikeTypeTraits<PT1>::getFromVoidPointer(Val.getPointer());
113823eb1ca11d684530048f1fe85a727aa1ef622d1Chris Lattner    }
114453f4f01302f00651aae2fc7658f6e23a2beadb0David Blaikie    LLVM_EXPLICIT operator bool() const { return !isNull(); }
115e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
1163a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    /// is<T>() return true if the Union currently holds the type matching T.
1172491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    template<typename T>
1182491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    int is() const {
119a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis      typedef typename
120a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis        ::llvm::PointerUnionTypeSelector<PT1, T, IsPT1,
121a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis          ::llvm::PointerUnionTypeSelector<PT2, T, IsPT2,
122a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis                                    UNION_DOESNT_CONTAIN_TYPE<T> > >::Return Ty;
123a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis      int TyNo = Ty::Num;
12437c286c18128cce7f52654876a5a104150be4b79Sebastian Redl      return static_cast<int>(Val.getInt()) == TyNo;
1252491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    }
1263a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner
1273a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    /// get<T>() - Return the value of the specified pointer type. If the
1283a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    /// specified pointer type is incorrect, assert.
1292491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    template<typename T>
1302491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    T get() const {
1312491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      assert(is<T>() && "Invalid accessor called");
132e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      return PointerLikeTypeTraits<T>::getFromVoidPointer(Val.getPointer());
1332491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    }
1342491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
1353a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    /// dyn_cast<T>() - If the current value is of the specified pointer type,
1363a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    /// return it, otherwise return null.
1373a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    template<typename T>
1383a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    T dyn_cast() const {
139e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      if (is<T>()) return get<T>();
1403a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner      return T();
1413a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    }
14238297f5f760de604258aaa9000e5aadb43c78921Argyrios Kyrtzidis
1430db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis    /// \brief If the union is set to the first pointer type get an address
1440db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis    /// pointing to it.
1450db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis    PT1 const *getAddrOfPtr1() const {
1460db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis      return const_cast<PointerUnion *>(this)->getAddrOfPtr1();
1470db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis    }
1480db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis
1490db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis    /// \brief If the union is set to the first pointer type get an address
1500db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis    /// pointing to it.
1510db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis    PT1 *getAddrOfPtr1() {
15238297f5f760de604258aaa9000e5aadb43c78921Argyrios Kyrtzidis      assert(is<PT1>() && "Val is not the first pointer");
15338297f5f760de604258aaa9000e5aadb43c78921Argyrios Kyrtzidis      assert(get<PT1>() == Val.getPointer() &&
15438297f5f760de604258aaa9000e5aadb43c78921Argyrios Kyrtzidis         "Can't get the address because PointerLikeTypeTraits changes the ptr");
1550db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis      return (PT1 *)Val.getAddrOfPointer();
15638297f5f760de604258aaa9000e5aadb43c78921Argyrios Kyrtzidis    }
157dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
158dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    /// \brief Assignment from nullptr which just clears the union.
159dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    const PointerUnion &operator=(std::nullptr_t) {
160dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      Val.initWithPointer(nullptr);
161dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      return *this;
162dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    }
1633a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner
1643a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    /// Assignment operators - Allow assigning into this union from either
1653a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner    /// pointer type, setting the discriminator to remember what it came from.
1662491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    const PointerUnion &operator=(const PT1 &RHS) {
167acb8d9fbe3853394a2537985349993580309b8cdArgyrios Kyrtzidis      Val.initWithPointer(
16841222823db11107834414a378525bb21493d3a1fDouglas Gregor         const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(RHS)));
1692491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      return *this;
1702491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    }
1712491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    const PointerUnion &operator=(const PT2 &RHS) {
172acb8d9fbe3853394a2537985349993580309b8cdArgyrios Kyrtzidis      Val.setPointerAndInt(
173acb8d9fbe3853394a2537985349993580309b8cdArgyrios Kyrtzidis        const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(RHS)),
174acb8d9fbe3853394a2537985349993580309b8cdArgyrios Kyrtzidis        1);
1752491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      return *this;
1762491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    }
1772491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
1782491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    void *getOpaqueValue() const { return Val.getOpaqueValue(); }
1798260ea5c6c15345e00ced1398b03e6886145e45cTed Kremenek    static inline PointerUnion getFromOpaqueValue(void *VP) {
1802491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      PointerUnion V;
1812491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      V.Val = ValTy::getFromOpaqueValue(VP);
1822491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      return V;
1832491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    }
1842491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  };
185453f4f01302f00651aae2fc7658f6e23a2beadb0David Blaikie
186453f4f01302f00651aae2fc7658f6e23a2beadb0David Blaikie  template<typename PT1, typename PT2>
187b2820859240b8b8ad03384207ce896da60702f98Chris Lattner  static bool operator==(PointerUnion<PT1, PT2> lhs,
188b2820859240b8b8ad03384207ce896da60702f98Chris Lattner                         PointerUnion<PT1, PT2> rhs) {
189453f4f01302f00651aae2fc7658f6e23a2beadb0David Blaikie    return lhs.getOpaqueValue() == rhs.getOpaqueValue();
190453f4f01302f00651aae2fc7658f6e23a2beadb0David Blaikie  }
191b2820859240b8b8ad03384207ce896da60702f98Chris Lattner
192b2820859240b8b8ad03384207ce896da60702f98Chris Lattner  template<typename PT1, typename PT2>
193b2820859240b8b8ad03384207ce896da60702f98Chris Lattner  static bool operator!=(PointerUnion<PT1, PT2> lhs,
194b2820859240b8b8ad03384207ce896da60702f98Chris Lattner                         PointerUnion<PT1, PT2> rhs) {
195586ea17be9fbf2fa1f2341900ebf1675a0924edcChris Lattner    return lhs.getOpaqueValue() != rhs.getOpaqueValue();
196b2820859240b8b8ad03384207ce896da60702f98Chris Lattner  }
197b2820859240b8b8ad03384207ce896da60702f98Chris Lattner
198e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  // Teach SmallPtrSet that PointerUnion is "basically a pointer", that has
1992491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  // # low bits available = min(PT1bits,PT2bits)-1.
2002491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  template<typename PT1, typename PT2>
2012491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  class PointerLikeTypeTraits<PointerUnion<PT1, PT2> > {
2022491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  public:
2032491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    static inline void *
2042491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    getAsVoidPointer(const PointerUnion<PT1, PT2> &P) {
2052491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      return P.getOpaqueValue();
2062491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    }
2072491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    static inline PointerUnion<PT1, PT2>
2082491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    getFromVoidPointer(void *P) {
2092491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      return PointerUnion<PT1, PT2>::getFromOpaqueValue(P);
2102491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    }
2112491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
2122491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    // The number of bits available are the min of the two pointer types.
2132491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    enum {
2142491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner      NumLowBitsAvailable =
215e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner        PointerLikeTypeTraits<typename PointerUnion<PT1,PT2>::ValTy>
216e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner          ::NumLowBitsAvailable
217e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    };
218e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  };
219e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
220e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
221e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  /// PointerUnion3 - This is a pointer union of three pointer types.  See
222e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  /// documentation for PointerUnion for usage.
223e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  template <typename PT1, typename PT2, typename PT3>
224e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  class PointerUnion3 {
225e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  public:
226e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    typedef PointerUnion<PT1, PT2> InnerUnion;
227e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    typedef PointerUnion<InnerUnion, PT3> ValTy;
228e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  private:
229e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    ValTy Val;
230128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis
231128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis    struct IsInnerUnion {
232128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      ValTy Val;
233128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      IsInnerUnion(ValTy val) : Val(val) { }
234128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      template<typename T>
235128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      int is() const {
236128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis        return Val.template is<InnerUnion>() &&
237128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis               Val.template get<InnerUnion>().template is<T>();
238128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      }
239128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      template<typename T>
240128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      T get() const {
241128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis        return Val.template get<InnerUnion>().template get<T>();
242128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      }
243128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis    };
244128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis
245128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis    struct IsPT3 {
246128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      ValTy Val;
247128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      IsPT3(ValTy val) : Val(val) { }
248128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      template<typename T>
249128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      int is() const {
250128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis        return Val.template is<T>();
251128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      }
252128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      template<typename T>
253128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      T get() const {
254128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis        return Val.template get<T>();
255128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      }
256128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis    };
257128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis
258e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  public:
259e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    PointerUnion3() {}
260e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
261e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    PointerUnion3(PT1 V) {
262e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      Val = InnerUnion(V);
263e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
264e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    PointerUnion3(PT2 V) {
265e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      Val = InnerUnion(V);
266e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
267e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    PointerUnion3(PT3 V) {
268e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      Val = V;
269e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
270e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
27126ef510d5d20b89c637d13e2d9169c0458de775cDouglas Gregor    /// isNull - Return true if the pointer held in the union is null,
272e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    /// regardless of which type it is.
273e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    bool isNull() const { return Val.isNull(); }
274453f4f01302f00651aae2fc7658f6e23a2beadb0David Blaikie    LLVM_EXPLICIT operator bool() const { return !isNull(); }
275e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
276e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    /// is<T>() return true if the Union currently holds the type matching T.
277e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    template<typename T>
278e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    int is() const {
279128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      // If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3.
280128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      typedef typename
281128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis        ::llvm::PointerUnionTypeSelector<PT1, T, IsInnerUnion,
282128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis          ::llvm::PointerUnionTypeSelector<PT2, T, IsInnerUnion, IsPT3 >
283128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis                                                                   >::Return Ty;
28487d8e60505b26960956996550c8b805c81e5b02bDouglas Gregor      return Ty(Val).template is<T>();
285e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
286e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
287e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    /// get<T>() - Return the value of the specified pointer type. If the
288e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    /// specified pointer type is incorrect, assert.
289e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    template<typename T>
290e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    T get() const {
291e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      assert(is<T>() && "Invalid accessor called");
292128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      // If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3.
293128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      typedef typename
294128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis        ::llvm::PointerUnionTypeSelector<PT1, T, IsInnerUnion,
295128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis          ::llvm::PointerUnionTypeSelector<PT2, T, IsInnerUnion, IsPT3 >
296128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis                                                                   >::Return Ty;
29787d8e60505b26960956996550c8b805c81e5b02bDouglas Gregor      return Ty(Val).template get<T>();
298e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
299e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
300e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    /// dyn_cast<T>() - If the current value is of the specified pointer type,
301e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    /// return it, otherwise return null.
302e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    template<typename T>
303e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    T dyn_cast() const {
304e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      if (is<T>()) return get<T>();
305e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      return T();
306e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
307dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
308dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    /// \brief Assignment from nullptr which just clears the union.
309dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    const PointerUnion3 &operator=(std::nullptr_t) {
310dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      Val = nullptr;
311dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      return *this;
312dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    }
313e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
314e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    /// Assignment operators - Allow assigning into this union from either
315e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    /// pointer type, setting the discriminator to remember what it came from.
316e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    const PointerUnion3 &operator=(const PT1 &RHS) {
317e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      Val = InnerUnion(RHS);
318e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      return *this;
319e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
320e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    const PointerUnion3 &operator=(const PT2 &RHS) {
321e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      Val = InnerUnion(RHS);
322e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      return *this;
323e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
324e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    const PointerUnion3 &operator=(const PT3 &RHS) {
325e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      Val = RHS;
326e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      return *this;
327e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
328e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
329e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    void *getOpaqueValue() const { return Val.getOpaqueValue(); }
3308260ea5c6c15345e00ced1398b03e6886145e45cTed Kremenek    static inline PointerUnion3 getFromOpaqueValue(void *VP) {
331e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      PointerUnion3 V;
332e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      V.Val = ValTy::getFromOpaqueValue(VP);
333e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      return V;
334e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
335e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  };
336e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
337e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  // Teach SmallPtrSet that PointerUnion3 is "basically a pointer", that has
338e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  // # low bits available = min(PT1bits,PT2bits,PT2bits)-2.
339e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  template<typename PT1, typename PT2, typename PT3>
340e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  class PointerLikeTypeTraits<PointerUnion3<PT1, PT2, PT3> > {
341e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner  public:
342e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    static inline void *
343e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    getAsVoidPointer(const PointerUnion3<PT1, PT2, PT3> &P) {
344e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      return P.getOpaqueValue();
345e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
346e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    static inline PointerUnion3<PT1, PT2, PT3>
347e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    getFromVoidPointer(void *P) {
348e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      return PointerUnion3<PT1, PT2, PT3>::getFromOpaqueValue(P);
349e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    }
350e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner
351e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    // The number of bits available are the min of the two pointer types.
352e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner    enum {
353e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner      NumLowBitsAvailable =
354e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner        PointerLikeTypeTraits<typename PointerUnion3<PT1, PT2, PT3>::ValTy>
355e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner          ::NumLowBitsAvailable
3562491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner    };
3572491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner  };
358e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor
359e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  /// PointerUnion4 - This is a pointer union of four pointer types.  See
360e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  /// documentation for PointerUnion for usage.
361e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  template <typename PT1, typename PT2, typename PT3, typename PT4>
362e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  class PointerUnion4 {
363e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  public:
364e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    typedef PointerUnion<PT1, PT2> InnerUnion1;
365e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    typedef PointerUnion<PT3, PT4> InnerUnion2;
366e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    typedef PointerUnion<InnerUnion1, InnerUnion2> ValTy;
367e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  private:
368e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    ValTy Val;
369e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  public:
370e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    PointerUnion4() {}
371e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor
372e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    PointerUnion4(PT1 V) {
373e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      Val = InnerUnion1(V);
374e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
375e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    PointerUnion4(PT2 V) {
376e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      Val = InnerUnion1(V);
377e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
378e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    PointerUnion4(PT3 V) {
379e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      Val = InnerUnion2(V);
380e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
381e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    PointerUnion4(PT4 V) {
382e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      Val = InnerUnion2(V);
383e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
384e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor
38526ef510d5d20b89c637d13e2d9169c0458de775cDouglas Gregor    /// isNull - Return true if the pointer held in the union is null,
386e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    /// regardless of which type it is.
387e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    bool isNull() const { return Val.isNull(); }
388453f4f01302f00651aae2fc7658f6e23a2beadb0David Blaikie    LLVM_EXPLICIT operator bool() const { return !isNull(); }
389e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor
390e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    /// is<T>() return true if the Union currently holds the type matching T.
391e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    template<typename T>
392e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    int is() const {
393128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      // If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2.
394128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      typedef typename
395128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis        ::llvm::PointerUnionTypeSelector<PT1, T, InnerUnion1,
396128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis          ::llvm::PointerUnionTypeSelector<PT2, T, InnerUnion1, InnerUnion2 >
397128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis                                                                   >::Return Ty;
398128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      return Val.template is<Ty>() &&
399128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis             Val.template get<Ty>().template is<T>();
400e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
401e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor
402e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    /// get<T>() - Return the value of the specified pointer type. If the
403e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    /// specified pointer type is incorrect, assert.
404e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    template<typename T>
405e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    T get() const {
406e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      assert(is<T>() && "Invalid accessor called");
407128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      // If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2.
408128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      typedef typename
409128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis        ::llvm::PointerUnionTypeSelector<PT1, T, InnerUnion1,
410128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis          ::llvm::PointerUnionTypeSelector<PT2, T, InnerUnion1, InnerUnion2 >
411128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis                                                                   >::Return Ty;
412128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis      return Val.template get<Ty>().template get<T>();
413e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
414e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor
415e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    /// dyn_cast<T>() - If the current value is of the specified pointer type,
416e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    /// return it, otherwise return null.
417e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    template<typename T>
418e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    T dyn_cast() const {
419e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      if (is<T>()) return get<T>();
420e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      return T();
421e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
422dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
423dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    /// \brief Assignment from nullptr which just clears the union.
424dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    const PointerUnion4 &operator=(std::nullptr_t) {
425dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      Val = nullptr;
426dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      return *this;
427dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    }
428e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor
429e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    /// Assignment operators - Allow assigning into this union from either
430e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    /// pointer type, setting the discriminator to remember what it came from.
431e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    const PointerUnion4 &operator=(const PT1 &RHS) {
432e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      Val = InnerUnion1(RHS);
433e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      return *this;
434e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
435e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    const PointerUnion4 &operator=(const PT2 &RHS) {
436e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      Val = InnerUnion1(RHS);
437e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      return *this;
438e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
439e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    const PointerUnion4 &operator=(const PT3 &RHS) {
440e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      Val = InnerUnion2(RHS);
441e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      return *this;
442e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
443e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    const PointerUnion4 &operator=(const PT4 &RHS) {
444e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      Val = InnerUnion2(RHS);
445e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      return *this;
446e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
447e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor
448e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    void *getOpaqueValue() const { return Val.getOpaqueValue(); }
4498260ea5c6c15345e00ced1398b03e6886145e45cTed Kremenek    static inline PointerUnion4 getFromOpaqueValue(void *VP) {
450e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      PointerUnion4 V;
451e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      V.Val = ValTy::getFromOpaqueValue(VP);
452e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      return V;
453e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
454e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  };
455e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor
456e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  // Teach SmallPtrSet that PointerUnion4 is "basically a pointer", that has
457e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  // # low bits available = min(PT1bits,PT2bits,PT2bits)-2.
458e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  template<typename PT1, typename PT2, typename PT3, typename PT4>
459e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  class PointerLikeTypeTraits<PointerUnion4<PT1, PT2, PT3, PT4> > {
460e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  public:
461e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    static inline void *
462e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    getAsVoidPointer(const PointerUnion4<PT1, PT2, PT3, PT4> &P) {
463e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      return P.getOpaqueValue();
464e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
465e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    static inline PointerUnion4<PT1, PT2, PT3, PT4>
466e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    getFromVoidPointer(void *P) {
467e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      return PointerUnion4<PT1, PT2, PT3, PT4>::getFromOpaqueValue(P);
468e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    }
469e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor
470e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    // The number of bits available are the min of the two pointer types.
471e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    enum {
472e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor      NumLowBitsAvailable =
473e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor        PointerLikeTypeTraits<typename PointerUnion4<PT1, PT2, PT3, PT4>::ValTy>
474e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor          ::NumLowBitsAvailable
475e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor    };
476e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor  };
477dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
478dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  // Teach DenseMap how to use PointerUnions as keys.
479dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  template<typename T, typename U>
480dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  struct DenseMapInfo<PointerUnion<T, U> > {
481dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    typedef PointerUnion<T, U> Pair;
482dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    typedef DenseMapInfo<T> FirstInfo;
483dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    typedef DenseMapInfo<U> SecondInfo;
484dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
485dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    static inline Pair getEmptyKey() {
486dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      return Pair(FirstInfo::getEmptyKey());
487dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    }
488dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    static inline Pair getTombstoneKey() {
489dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      return Pair(FirstInfo::getTombstoneKey());
490dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    }
491dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    static unsigned getHashValue(const Pair &PairVal) {
492dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      intptr_t key = (intptr_t)PairVal.getOpaqueValue();
493dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      return DenseMapInfo<intptr_t>::getHashValue(key);
494dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    }
495dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    static bool isEqual(const Pair &LHS, const Pair &RHS) {
496dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      return LHS.template is<T>() == RHS.template is<T>() &&
497dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines             (LHS.template is<T>() ?
498dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines              FirstInfo::isEqual(LHS.template get<T>(),
499dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                 RHS.template get<T>()) :
500dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines              SecondInfo::isEqual(LHS.template get<U>(),
501dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                  RHS.template get<U>()));
502dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    }
503dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  };
5042491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner}
5052491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner
5062491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner#endif
507