PointerUnion.h revision 586ea17be9fbf2fa1f2341900ebf1675a0924edc
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 18df6e5fb77ca864c55735b903eb022fb1e38fa3d2Douglas Gregor#include "llvm/Support/Compiler.h" 192491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner#include "llvm/ADT/PointerIntPair.h" 202491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 212491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattnernamespace llvm { 222491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 23128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis template <typename T> 24128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis struct PointerUnionTypeSelectorReturn { 25128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis typedef T Return; 26128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis }; 27128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis 28128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis /// \brief Get a type based on whether two types are the same or not. For: 29128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis /// @code 30128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis /// typedef typename PointerUnionTypeSelector<T1, T2, EQ, NE>::Return Ret; 31128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis /// @endcode 32128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis /// Ret will be EQ type if T1 is same as T2 or NE type otherwise. 33128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis template <typename T1, typename T2, typename RET_EQ, typename RET_NE> 34128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis struct PointerUnionTypeSelector { 35128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis typedef typename PointerUnionTypeSelectorReturn<RET_NE>::Return Return; 36128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis }; 37128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis 38128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis template <typename T, typename RET_EQ, typename RET_NE> 39128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis struct PointerUnionTypeSelector<T, T, RET_EQ, RET_NE> { 40128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis typedef typename PointerUnionTypeSelectorReturn<RET_EQ>::Return Return; 41128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis }; 42128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis 43128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis template <typename T1, typename T2, typename RET_EQ, typename RET_NE> 44128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis struct PointerUnionTypeSelectorReturn< 45128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE> > { 46128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis typedef typename PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE>::Return 47128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis Return; 48128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis }; 49128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis 502491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// Provide PointerLikeTypeTraits for void* that is used by PointerUnion 512491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// for the two template arguments. 522491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner template <typename PT1, typename PT2> 532491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner class PointerUnionUIntTraits { 542491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner public: 552491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner static inline void *getAsVoidPointer(void *P) { return P; } 562491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner static inline void *getFromVoidPointer(void *P) { return P; } 572491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner enum { 58b76fb96cd66aec709e2a0cfda8c29c53ba5ad98cGalina Kistanova PT1BitsAv = (int)(PointerLikeTypeTraits<PT1>::NumLowBitsAvailable), 59b76fb96cd66aec709e2a0cfda8c29c53ba5ad98cGalina Kistanova PT2BitsAv = (int)(PointerLikeTypeTraits<PT2>::NumLowBitsAvailable), 602491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner NumLowBitsAvailable = PT1BitsAv < PT2BitsAv ? PT1BitsAv : PT2BitsAv 612491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner }; 622491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner }; 632491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 642491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// PointerUnion - This implements a discriminated union of two pointer types, 652491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// and keeps the discriminator bit-mangled into the low bits of the pointer. 662491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// This allows the implementation to be extremely efficient in space, but 672491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// permits a very natural and type-safe API. 682491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// 692491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// Common use patterns would be something like this: 702491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// PointerUnion<int*, float*> P; 712491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// P = (int*)0; 722491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// printf("%d %d", P.is<int*>(), P.is<float*>()); // prints "1 0" 732491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// X = P.get<int*>(); // ok. 742491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// Y = P.get<float*>(); // runtime assertion failure. 75f54229192c22559389b0ef47e731fd628db963c5Chris Lattner /// Z = P.get<double*>(); // runtime assertion failure (regardless of tag) 762491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// P = (float*)0; 772491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// Y = P.get<float*>(); // ok. 782491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner /// X = P.get<int*>(); // runtime assertion failure. 792491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner template <typename PT1, typename PT2> 802491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner class PointerUnion { 812491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner public: 822491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner typedef PointerIntPair<void*, 1, bool, 832491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner PointerUnionUIntTraits<PT1,PT2> > ValTy; 842491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner private: 852491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner ValTy Val; 86a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis 87a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis struct IsPT1 { 88a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis static const int Num = 0; 89a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis }; 90a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis struct IsPT2 { 91a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis static const int Num = 1; 92a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis }; 93a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis template <typename T> 94a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis struct UNION_DOESNT_CONTAIN_TYPE { }; 95a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis 962491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner public: 972491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner PointerUnion() {} 982491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 99acb8d9fbe3853394a2537985349993580309b8cdArgyrios Kyrtzidis PointerUnion(PT1 V) : Val( 100acb8d9fbe3853394a2537985349993580309b8cdArgyrios Kyrtzidis const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(V))) { 1012491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 102acb8d9fbe3853394a2537985349993580309b8cdArgyrios Kyrtzidis PointerUnion(PT2 V) : Val( 103acb8d9fbe3853394a2537985349993580309b8cdArgyrios Kyrtzidis const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(V)), 1) { 1042491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 1052491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 10626ef510d5d20b89c637d13e2d9169c0458de775cDouglas Gregor /// isNull - Return true if the pointer held in the union is null, 1073a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner /// regardless of which type it is. 108823eb1ca11d684530048f1fe85a727aa1ef622d1Chris Lattner bool isNull() const { 109823eb1ca11d684530048f1fe85a727aa1ef622d1Chris Lattner // Convert from the void* to one of the pointer types, to make sure that 110823eb1ca11d684530048f1fe85a727aa1ef622d1Chris Lattner // we recursively strip off low bits if we have a nested PointerUnion. 111823eb1ca11d684530048f1fe85a727aa1ef622d1Chris Lattner return !PointerLikeTypeTraits<PT1>::getFromVoidPointer(Val.getPointer()); 112823eb1ca11d684530048f1fe85a727aa1ef622d1Chris Lattner } 113453f4f01302f00651aae2fc7658f6e23a2beadb0David Blaikie LLVM_EXPLICIT operator bool() const { return !isNull(); } 114e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 1153a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner /// is<T>() return true if the Union currently holds the type matching T. 1162491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner template<typename T> 1172491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner int is() const { 118a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis typedef typename 119a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis ::llvm::PointerUnionTypeSelector<PT1, T, IsPT1, 120a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis ::llvm::PointerUnionTypeSelector<PT2, T, IsPT2, 121a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis UNION_DOESNT_CONTAIN_TYPE<T> > >::Return Ty; 122a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis int TyNo = Ty::Num; 12337c286c18128cce7f52654876a5a104150be4b79Sebastian Redl return static_cast<int>(Val.getInt()) == TyNo; 1242491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 1253a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner 1263a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner /// get<T>() - Return the value of the specified pointer type. If the 1273a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner /// specified pointer type is incorrect, assert. 1282491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner template<typename T> 1292491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner T get() const { 1302491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner assert(is<T>() && "Invalid accessor called"); 131e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner return PointerLikeTypeTraits<T>::getFromVoidPointer(Val.getPointer()); 1322491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 1332491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 1343a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner /// dyn_cast<T>() - If the current value is of the specified pointer type, 1353a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner /// return it, otherwise return null. 1363a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner template<typename T> 1373a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner T dyn_cast() const { 138e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner if (is<T>()) return get<T>(); 1393a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner return T(); 1403a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner } 14138297f5f760de604258aaa9000e5aadb43c78921Argyrios Kyrtzidis 1420db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis /// \brief If the union is set to the first pointer type get an address 1430db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis /// pointing to it. 1440db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis PT1 const *getAddrOfPtr1() const { 1450db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis return const_cast<PointerUnion *>(this)->getAddrOfPtr1(); 1460db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis } 1470db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis 1480db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis /// \brief If the union is set to the first pointer type get an address 1490db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis /// pointing to it. 1500db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis PT1 *getAddrOfPtr1() { 15138297f5f760de604258aaa9000e5aadb43c78921Argyrios Kyrtzidis assert(is<PT1>() && "Val is not the first pointer"); 15238297f5f760de604258aaa9000e5aadb43c78921Argyrios Kyrtzidis assert(get<PT1>() == Val.getPointer() && 15338297f5f760de604258aaa9000e5aadb43c78921Argyrios Kyrtzidis "Can't get the address because PointerLikeTypeTraits changes the ptr"); 1540db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis return (PT1 *)Val.getAddrOfPointer(); 15538297f5f760de604258aaa9000e5aadb43c78921Argyrios Kyrtzidis } 1563a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner 1573a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner /// Assignment operators - Allow assigning into this union from either 1583a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner /// pointer type, setting the discriminator to remember what it came from. 1592491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner const PointerUnion &operator=(const PT1 &RHS) { 160acb8d9fbe3853394a2537985349993580309b8cdArgyrios Kyrtzidis Val.initWithPointer( 16141222823db11107834414a378525bb21493d3a1fDouglas Gregor const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(RHS))); 1622491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner return *this; 1632491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 1642491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner const PointerUnion &operator=(const PT2 &RHS) { 165acb8d9fbe3853394a2537985349993580309b8cdArgyrios Kyrtzidis Val.setPointerAndInt( 166acb8d9fbe3853394a2537985349993580309b8cdArgyrios Kyrtzidis const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(RHS)), 167acb8d9fbe3853394a2537985349993580309b8cdArgyrios Kyrtzidis 1); 1682491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner return *this; 1692491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 1702491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 1712491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner void *getOpaqueValue() const { return Val.getOpaqueValue(); } 1728260ea5c6c15345e00ced1398b03e6886145e45cTed Kremenek static inline PointerUnion getFromOpaqueValue(void *VP) { 1732491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner PointerUnion V; 1742491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner V.Val = ValTy::getFromOpaqueValue(VP); 1752491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner return V; 1762491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 1772491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner }; 178453f4f01302f00651aae2fc7658f6e23a2beadb0David Blaikie 179453f4f01302f00651aae2fc7658f6e23a2beadb0David Blaikie template<typename PT1, typename PT2> 180b2820859240b8b8ad03384207ce896da60702f98Chris Lattner static bool operator==(PointerUnion<PT1, PT2> lhs, 181b2820859240b8b8ad03384207ce896da60702f98Chris Lattner PointerUnion<PT1, PT2> rhs) { 182453f4f01302f00651aae2fc7658f6e23a2beadb0David Blaikie return lhs.getOpaqueValue() == rhs.getOpaqueValue(); 183453f4f01302f00651aae2fc7658f6e23a2beadb0David Blaikie } 184b2820859240b8b8ad03384207ce896da60702f98Chris Lattner 185b2820859240b8b8ad03384207ce896da60702f98Chris Lattner template<typename PT1, typename PT2> 186b2820859240b8b8ad03384207ce896da60702f98Chris Lattner static bool operator!=(PointerUnion<PT1, PT2> lhs, 187b2820859240b8b8ad03384207ce896da60702f98Chris Lattner PointerUnion<PT1, PT2> rhs) { 188586ea17be9fbf2fa1f2341900ebf1675a0924edcChris Lattner return lhs.getOpaqueValue() != rhs.getOpaqueValue(); 189b2820859240b8b8ad03384207ce896da60702f98Chris Lattner } 190b2820859240b8b8ad03384207ce896da60702f98Chris Lattner 191e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner // Teach SmallPtrSet that PointerUnion is "basically a pointer", that has 1922491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner // # low bits available = min(PT1bits,PT2bits)-1. 1932491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner template<typename PT1, typename PT2> 1942491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner class PointerLikeTypeTraits<PointerUnion<PT1, PT2> > { 1952491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner public: 1962491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner static inline void * 1972491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner getAsVoidPointer(const PointerUnion<PT1, PT2> &P) { 1982491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner return P.getOpaqueValue(); 1992491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 2002491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner static inline PointerUnion<PT1, PT2> 2012491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner getFromVoidPointer(void *P) { 2022491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner return PointerUnion<PT1, PT2>::getFromOpaqueValue(P); 2032491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 2042491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 2052491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner // The number of bits available are the min of the two pointer types. 2062491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner enum { 2072491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner NumLowBitsAvailable = 208e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner PointerLikeTypeTraits<typename PointerUnion<PT1,PT2>::ValTy> 209e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner ::NumLowBitsAvailable 210e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner }; 211e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner }; 212e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 213e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 214e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// PointerUnion3 - This is a pointer union of three pointer types. See 215e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// documentation for PointerUnion for usage. 216e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner template <typename PT1, typename PT2, typename PT3> 217e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner class PointerUnion3 { 218e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner public: 219e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner typedef PointerUnion<PT1, PT2> InnerUnion; 220e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner typedef PointerUnion<InnerUnion, PT3> ValTy; 221e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner private: 222e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner ValTy Val; 223128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis 224128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis struct IsInnerUnion { 225128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis ValTy Val; 226128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis IsInnerUnion(ValTy val) : Val(val) { } 227128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis template<typename T> 228128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis int is() const { 229128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis return Val.template is<InnerUnion>() && 230128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis Val.template get<InnerUnion>().template is<T>(); 231128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis } 232128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis template<typename T> 233128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis T get() const { 234128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis return Val.template get<InnerUnion>().template get<T>(); 235128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis } 236128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis }; 237128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis 238128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis struct IsPT3 { 239128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis ValTy Val; 240128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis IsPT3(ValTy val) : Val(val) { } 241128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis template<typename T> 242128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis int is() const { 243128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis return Val.template is<T>(); 244128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis } 245128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis template<typename T> 246128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis T get() const { 247128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis return Val.template get<T>(); 248128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis } 249128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis }; 250128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis 251e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner public: 252e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner PointerUnion3() {} 253e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 254e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner PointerUnion3(PT1 V) { 255e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner Val = InnerUnion(V); 256e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 257e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner PointerUnion3(PT2 V) { 258e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner Val = InnerUnion(V); 259e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 260e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner PointerUnion3(PT3 V) { 261e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner Val = V; 262e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 263e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 26426ef510d5d20b89c637d13e2d9169c0458de775cDouglas Gregor /// isNull - Return true if the pointer held in the union is null, 265e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// regardless of which type it is. 266e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner bool isNull() const { return Val.isNull(); } 267453f4f01302f00651aae2fc7658f6e23a2beadb0David Blaikie LLVM_EXPLICIT operator bool() const { return !isNull(); } 268e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 269e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// is<T>() return true if the Union currently holds the type matching T. 270e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner template<typename T> 271e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner int is() const { 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 is<T>(); 278e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 279e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 280e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// get<T>() - Return the value of the specified pointer type. If the 281e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// specified pointer type is incorrect, assert. 282e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner template<typename T> 283e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner T get() const { 284e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner assert(is<T>() && "Invalid accessor called"); 285128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis // If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3. 286128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis typedef typename 287128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis ::llvm::PointerUnionTypeSelector<PT1, T, IsInnerUnion, 288128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis ::llvm::PointerUnionTypeSelector<PT2, T, IsInnerUnion, IsPT3 > 289128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis >::Return Ty; 29087d8e60505b26960956996550c8b805c81e5b02bDouglas Gregor return Ty(Val).template get<T>(); 291e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 292e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 293e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// dyn_cast<T>() - If the current value is of the specified pointer type, 294e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// return it, otherwise return null. 295e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner template<typename T> 296e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner T dyn_cast() const { 297e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner if (is<T>()) return get<T>(); 298e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner return T(); 299e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 300e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 301e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// Assignment operators - Allow assigning into this union from either 302e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// pointer type, setting the discriminator to remember what it came from. 303e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner const PointerUnion3 &operator=(const PT1 &RHS) { 304e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner Val = InnerUnion(RHS); 305e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner return *this; 306e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 307e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner const PointerUnion3 &operator=(const PT2 &RHS) { 308e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner Val = InnerUnion(RHS); 309e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner return *this; 310e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 311e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner const PointerUnion3 &operator=(const PT3 &RHS) { 312e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner Val = RHS; 313e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner return *this; 314e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 315e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 316e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner void *getOpaqueValue() const { return Val.getOpaqueValue(); } 3178260ea5c6c15345e00ced1398b03e6886145e45cTed Kremenek static inline PointerUnion3 getFromOpaqueValue(void *VP) { 318e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner PointerUnion3 V; 319e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner V.Val = ValTy::getFromOpaqueValue(VP); 320e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner return V; 321e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 322e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner }; 323e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 324e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner // Teach SmallPtrSet that PointerUnion3 is "basically a pointer", that has 325e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner // # low bits available = min(PT1bits,PT2bits,PT2bits)-2. 326e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner template<typename PT1, typename PT2, typename PT3> 327e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner class PointerLikeTypeTraits<PointerUnion3<PT1, PT2, PT3> > { 328e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner public: 329e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner static inline void * 330e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner getAsVoidPointer(const PointerUnion3<PT1, PT2, PT3> &P) { 331e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner return P.getOpaqueValue(); 332e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 333e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner static inline PointerUnion3<PT1, PT2, PT3> 334e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner getFromVoidPointer(void *P) { 335e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner return PointerUnion3<PT1, PT2, PT3>::getFromOpaqueValue(P); 336e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 337e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 338e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner // The number of bits available are the min of the two pointer types. 339e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner enum { 340e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner NumLowBitsAvailable = 341e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner PointerLikeTypeTraits<typename PointerUnion3<PT1, PT2, PT3>::ValTy> 342e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner ::NumLowBitsAvailable 3432491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner }; 3442491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner }; 345e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 346e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// PointerUnion4 - This is a pointer union of four pointer types. See 347e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// documentation for PointerUnion for usage. 348e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor template <typename PT1, typename PT2, typename PT3, typename PT4> 349e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor class PointerUnion4 { 350e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor public: 351e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor typedef PointerUnion<PT1, PT2> InnerUnion1; 352e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor typedef PointerUnion<PT3, PT4> InnerUnion2; 353e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor typedef PointerUnion<InnerUnion1, InnerUnion2> ValTy; 354e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor private: 355e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor ValTy Val; 356e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor public: 357e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor PointerUnion4() {} 358e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 359e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor PointerUnion4(PT1 V) { 360e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor Val = InnerUnion1(V); 361e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 362e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor PointerUnion4(PT2 V) { 363e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor Val = InnerUnion1(V); 364e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 365e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor PointerUnion4(PT3 V) { 366e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor Val = InnerUnion2(V); 367e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 368e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor PointerUnion4(PT4 V) { 369e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor Val = InnerUnion2(V); 370e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 371e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 37226ef510d5d20b89c637d13e2d9169c0458de775cDouglas Gregor /// isNull - Return true if the pointer held in the union is null, 373e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// regardless of which type it is. 374e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor bool isNull() const { return Val.isNull(); } 375453f4f01302f00651aae2fc7658f6e23a2beadb0David Blaikie LLVM_EXPLICIT operator bool() const { return !isNull(); } 376e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 377e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// is<T>() return true if the Union currently holds the type matching T. 378e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor template<typename T> 379e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor int is() const { 380128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis // If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2. 381128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis typedef typename 382128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis ::llvm::PointerUnionTypeSelector<PT1, T, InnerUnion1, 383128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis ::llvm::PointerUnionTypeSelector<PT2, T, InnerUnion1, InnerUnion2 > 384128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis >::Return Ty; 385128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis return Val.template is<Ty>() && 386128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis Val.template get<Ty>().template is<T>(); 387e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 388e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 389e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// get<T>() - Return the value of the specified pointer type. If the 390e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// specified pointer type is incorrect, assert. 391e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor template<typename T> 392e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor T get() const { 393e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor assert(is<T>() && "Invalid accessor called"); 394128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis // If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2. 395128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis typedef typename 396128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis ::llvm::PointerUnionTypeSelector<PT1, T, InnerUnion1, 397128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis ::llvm::PointerUnionTypeSelector<PT2, T, InnerUnion1, InnerUnion2 > 398128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis >::Return Ty; 399128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis return Val.template get<Ty>().template get<T>(); 400e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 401e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 402e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// dyn_cast<T>() - If the current value is of the specified pointer type, 403e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// return it, otherwise return null. 404e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor template<typename T> 405e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor T dyn_cast() const { 406e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor if (is<T>()) return get<T>(); 407e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor return T(); 408e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 409e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 410e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// Assignment operators - Allow assigning into this union from either 411e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// pointer type, setting the discriminator to remember what it came from. 412e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor const PointerUnion4 &operator=(const PT1 &RHS) { 413e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor Val = InnerUnion1(RHS); 414e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor return *this; 415e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 416e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor const PointerUnion4 &operator=(const PT2 &RHS) { 417e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor Val = InnerUnion1(RHS); 418e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor return *this; 419e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 420e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor const PointerUnion4 &operator=(const PT3 &RHS) { 421e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor Val = InnerUnion2(RHS); 422e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor return *this; 423e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 424e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor const PointerUnion4 &operator=(const PT4 &RHS) { 425e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor Val = InnerUnion2(RHS); 426e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor return *this; 427e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 428e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 429e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor void *getOpaqueValue() const { return Val.getOpaqueValue(); } 4308260ea5c6c15345e00ced1398b03e6886145e45cTed Kremenek static inline PointerUnion4 getFromOpaqueValue(void *VP) { 431e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor PointerUnion4 V; 432e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor V.Val = ValTy::getFromOpaqueValue(VP); 433e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor return V; 434e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 435e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor }; 436e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 437e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor // Teach SmallPtrSet that PointerUnion4 is "basically a pointer", that has 438e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor // # low bits available = min(PT1bits,PT2bits,PT2bits)-2. 439e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor template<typename PT1, typename PT2, typename PT3, typename PT4> 440e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor class PointerLikeTypeTraits<PointerUnion4<PT1, PT2, PT3, PT4> > { 441e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor public: 442e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor static inline void * 443e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor getAsVoidPointer(const PointerUnion4<PT1, PT2, PT3, PT4> &P) { 444e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor return P.getOpaqueValue(); 445e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 446e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor static inline PointerUnion4<PT1, PT2, PT3, PT4> 447e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor getFromVoidPointer(void *P) { 448e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor return PointerUnion4<PT1, PT2, PT3, PT4>::getFromOpaqueValue(P); 449e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 450e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 451e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor // The number of bits available are the min of the two pointer types. 452e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor enum { 453e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor NumLowBitsAvailable = 454e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor PointerLikeTypeTraits<typename PointerUnion4<PT1, PT2, PT3, PT4>::ValTy> 455e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor ::NumLowBitsAvailable 456e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor }; 457e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor }; 4582491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner} 4592491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 4602491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner#endif 461