PointerUnion.h revision b76fb96cd66aec709e2a0cfda8c29c53ba5ad98c
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 982491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner PointerUnion(PT1 V) { 9941222823db11107834414a378525bb21493d3a1fDouglas Gregor Val.setPointer( 10041222823db11107834414a378525bb21493d3a1fDouglas Gregor const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(V))); 1012491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner Val.setInt(0); 1022491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 1032491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner PointerUnion(PT2 V) { 10441222823db11107834414a378525bb21493d3a1fDouglas Gregor Val.setPointer( 10541222823db11107834414a378525bb21493d3a1fDouglas Gregor const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(V))); 1062491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner Val.setInt(1); 1072491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 1082491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 10926ef510d5d20b89c637d13e2d9169c0458de775cDouglas Gregor /// isNull - Return true if the pointer held in the union is null, 1103a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner /// regardless of which type it is. 111823eb1ca11d684530048f1fe85a727aa1ef622d1Chris Lattner bool isNull() const { 112823eb1ca11d684530048f1fe85a727aa1ef622d1Chris Lattner // Convert from the void* to one of the pointer types, to make sure that 113823eb1ca11d684530048f1fe85a727aa1ef622d1Chris Lattner // we recursively strip off low bits if we have a nested PointerUnion. 114823eb1ca11d684530048f1fe85a727aa1ef622d1Chris Lattner return !PointerLikeTypeTraits<PT1>::getFromVoidPointer(Val.getPointer()); 115823eb1ca11d684530048f1fe85a727aa1ef622d1Chris Lattner } 116e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner operator bool() const { return !isNull(); } 117e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 1183a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner /// is<T>() return true if the Union currently holds the type matching T. 1192491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner template<typename T> 1202491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner int is() const { 121a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis typedef typename 122a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis ::llvm::PointerUnionTypeSelector<PT1, T, IsPT1, 123a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis ::llvm::PointerUnionTypeSelector<PT2, T, IsPT2, 124a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis UNION_DOESNT_CONTAIN_TYPE<T> > >::Return Ty; 125a36be826643ed1f6a4639f79270276df621853baArgyrios Kyrtzidis int TyNo = Ty::Num; 12637c286c18128cce7f52654876a5a104150be4b79Sebastian Redl return static_cast<int>(Val.getInt()) == TyNo; 1272491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 1283a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner 1293a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner /// get<T>() - Return the value of the specified pointer type. If the 1303a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner /// specified pointer type is incorrect, assert. 1312491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner template<typename T> 1322491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner T get() const { 1332491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner assert(is<T>() && "Invalid accessor called"); 134e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner return PointerLikeTypeTraits<T>::getFromVoidPointer(Val.getPointer()); 1352491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 1362491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 1373a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner /// dyn_cast<T>() - If the current value is of the specified pointer type, 1383a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner /// return it, otherwise return null. 1393a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner template<typename T> 1403a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner T dyn_cast() const { 141e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner if (is<T>()) return get<T>(); 1423a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner return T(); 1433a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner } 14438297f5f760de604258aaa9000e5aadb43c78921Argyrios Kyrtzidis 1450db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis /// \brief If the union is set to the first pointer type get an address 1460db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis /// pointing to it. 1470db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis PT1 const *getAddrOfPtr1() const { 1480db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis return const_cast<PointerUnion *>(this)->getAddrOfPtr1(); 1490db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis } 1500db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis 1510db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis /// \brief If the union is set to the first pointer type get an address 1520db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis /// pointing to it. 1530db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis PT1 *getAddrOfPtr1() { 15438297f5f760de604258aaa9000e5aadb43c78921Argyrios Kyrtzidis assert(is<PT1>() && "Val is not the first pointer"); 15538297f5f760de604258aaa9000e5aadb43c78921Argyrios Kyrtzidis assert(get<PT1>() == Val.getPointer() && 15638297f5f760de604258aaa9000e5aadb43c78921Argyrios Kyrtzidis "Can't get the address because PointerLikeTypeTraits changes the ptr"); 1570db235a2b0ed6ae5c3c870012061906054b6dbc4Argyrios Kyrtzidis return (PT1 *)Val.getAddrOfPointer(); 15838297f5f760de604258aaa9000e5aadb43c78921Argyrios Kyrtzidis } 1593a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner 1603a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner /// Assignment operators - Allow assigning into this union from either 1613a9fe06bfe30da6fb1e0a540f05877c3640c7335Chris Lattner /// pointer type, setting the discriminator to remember what it came from. 1622491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner const PointerUnion &operator=(const PT1 &RHS) { 16341222823db11107834414a378525bb21493d3a1fDouglas Gregor Val.setPointer( 16441222823db11107834414a378525bb21493d3a1fDouglas Gregor const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(RHS))); 1652491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner Val.setInt(0); 1662491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner return *this; 1672491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 1682491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner const PointerUnion &operator=(const PT2 &RHS) { 16941222823db11107834414a378525bb21493d3a1fDouglas Gregor Val.setPointer( 17041222823db11107834414a378525bb21493d3a1fDouglas Gregor const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(RHS))); 1712491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner Val.setInt(1); 1722491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner return *this; 1732491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 1742491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 1752491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner void *getOpaqueValue() const { return Val.getOpaqueValue(); } 1768260ea5c6c15345e00ced1398b03e6886145e45cTed Kremenek static inline PointerUnion getFromOpaqueValue(void *VP) { 1772491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner PointerUnion V; 1782491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner V.Val = ValTy::getFromOpaqueValue(VP); 1792491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner return V; 1802491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 1812491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner }; 1822491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 183e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner // Teach SmallPtrSet that PointerUnion is "basically a pointer", that has 1842491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner // # low bits available = min(PT1bits,PT2bits)-1. 1852491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner template<typename PT1, typename PT2> 1862491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner class PointerLikeTypeTraits<PointerUnion<PT1, PT2> > { 1872491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner public: 1882491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner static inline void * 1892491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner getAsVoidPointer(const PointerUnion<PT1, PT2> &P) { 1902491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner return P.getOpaqueValue(); 1912491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 1922491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner static inline PointerUnion<PT1, PT2> 1932491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner getFromVoidPointer(void *P) { 1942491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner return PointerUnion<PT1, PT2>::getFromOpaqueValue(P); 1952491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner } 1962491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 1972491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner // The number of bits available are the min of the two pointer types. 1982491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner enum { 1992491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner NumLowBitsAvailable = 200e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner PointerLikeTypeTraits<typename PointerUnion<PT1,PT2>::ValTy> 201e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner ::NumLowBitsAvailable 202e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner }; 203e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner }; 204e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 205e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 206e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// PointerUnion3 - This is a pointer union of three pointer types. See 207e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// documentation for PointerUnion for usage. 208e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner template <typename PT1, typename PT2, typename PT3> 209e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner class PointerUnion3 { 210e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner public: 211e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner typedef PointerUnion<PT1, PT2> InnerUnion; 212e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner typedef PointerUnion<InnerUnion, PT3> ValTy; 213e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner private: 214e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner ValTy Val; 215128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis 216128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis struct IsInnerUnion { 217128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis ValTy Val; 218128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis IsInnerUnion(ValTy val) : Val(val) { } 219128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis template<typename T> 220128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis int is() const { 221128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis return Val.template is<InnerUnion>() && 222128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis Val.template get<InnerUnion>().template is<T>(); 223128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis } 224128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis template<typename T> 225128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis T get() const { 226128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis return Val.template get<InnerUnion>().template get<T>(); 227128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis } 228128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis }; 229128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis 230128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis struct IsPT3 { 231128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis ValTy Val; 232128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis IsPT3(ValTy val) : Val(val) { } 233128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis template<typename T> 234128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis int is() const { 235128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis return Val.template is<T>(); 236128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis } 237128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis template<typename T> 238128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis T get() const { 239128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis return Val.template get<T>(); 240128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis } 241128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis }; 242128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis 243e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner public: 244e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner PointerUnion3() {} 245e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 246e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner PointerUnion3(PT1 V) { 247e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner Val = InnerUnion(V); 248e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 249e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner PointerUnion3(PT2 V) { 250e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner Val = InnerUnion(V); 251e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 252e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner PointerUnion3(PT3 V) { 253e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner Val = V; 254e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 255e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 25626ef510d5d20b89c637d13e2d9169c0458de775cDouglas Gregor /// isNull - Return true if the pointer held in the union is null, 257e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// regardless of which type it is. 258e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner bool isNull() const { return Val.isNull(); } 259e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner operator bool() const { return !isNull(); } 260e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 261e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// is<T>() return true if the Union currently holds the type matching T. 262e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner template<typename T> 263e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner int is() const { 264128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis // If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3. 265128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis typedef typename 266128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis ::llvm::PointerUnionTypeSelector<PT1, T, IsInnerUnion, 267128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis ::llvm::PointerUnionTypeSelector<PT2, T, IsInnerUnion, IsPT3 > 268128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis >::Return Ty; 26987d8e60505b26960956996550c8b805c81e5b02bDouglas Gregor return Ty(Val).template is<T>(); 270e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 271e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 272e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// get<T>() - Return the value of the specified pointer type. If the 273e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// specified pointer type is incorrect, assert. 274e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner template<typename T> 275e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner T get() const { 276e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner assert(is<T>() && "Invalid accessor called"); 277128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis // If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3. 278128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis typedef typename 279128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis ::llvm::PointerUnionTypeSelector<PT1, T, IsInnerUnion, 280128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis ::llvm::PointerUnionTypeSelector<PT2, T, IsInnerUnion, IsPT3 > 281128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis >::Return Ty; 28287d8e60505b26960956996550c8b805c81e5b02bDouglas Gregor return Ty(Val).template get<T>(); 283e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 284e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 285e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// dyn_cast<T>() - If the current value is of the specified pointer type, 286e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// return it, otherwise return null. 287e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner template<typename T> 288e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner T dyn_cast() const { 289e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner if (is<T>()) return get<T>(); 290e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner return T(); 291e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 292e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 293e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// Assignment operators - Allow assigning into this union from either 294e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner /// pointer type, setting the discriminator to remember what it came from. 295e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner const PointerUnion3 &operator=(const PT1 &RHS) { 296e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner Val = InnerUnion(RHS); 297e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner return *this; 298e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 299e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner const PointerUnion3 &operator=(const PT2 &RHS) { 300e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner Val = InnerUnion(RHS); 301e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner return *this; 302e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 303e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner const PointerUnion3 &operator=(const PT3 &RHS) { 304e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner Val = RHS; 305e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner return *this; 306e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 307e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 308e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner void *getOpaqueValue() const { return Val.getOpaqueValue(); } 3098260ea5c6c15345e00ced1398b03e6886145e45cTed Kremenek static inline PointerUnion3 getFromOpaqueValue(void *VP) { 310e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner PointerUnion3 V; 311e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner V.Val = ValTy::getFromOpaqueValue(VP); 312e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner return V; 313e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 314e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner }; 315e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 316e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner // Teach SmallPtrSet that PointerUnion3 is "basically a pointer", that has 317e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner // # low bits available = min(PT1bits,PT2bits,PT2bits)-2. 318e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner template<typename PT1, typename PT2, typename PT3> 319e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner class PointerLikeTypeTraits<PointerUnion3<PT1, PT2, PT3> > { 320e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner public: 321e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner static inline void * 322e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner getAsVoidPointer(const PointerUnion3<PT1, PT2, PT3> &P) { 323e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner return P.getOpaqueValue(); 324e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 325e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner static inline PointerUnion3<PT1, PT2, PT3> 326e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner getFromVoidPointer(void *P) { 327e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner return PointerUnion3<PT1, PT2, PT3>::getFromOpaqueValue(P); 328e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner } 329e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner 330e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner // The number of bits available are the min of the two pointer types. 331e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner enum { 332e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner NumLowBitsAvailable = 333e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner PointerLikeTypeTraits<typename PointerUnion3<PT1, PT2, PT3>::ValTy> 334e8bc475668ddd2f31f44dd00b042d15b255e1b9eChris Lattner ::NumLowBitsAvailable 3352491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner }; 3362491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner }; 337e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 338e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// PointerUnion4 - This is a pointer union of four pointer types. See 339e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// documentation for PointerUnion for usage. 340e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor template <typename PT1, typename PT2, typename PT3, typename PT4> 341e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor class PointerUnion4 { 342e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor public: 343e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor typedef PointerUnion<PT1, PT2> InnerUnion1; 344e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor typedef PointerUnion<PT3, PT4> InnerUnion2; 345e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor typedef PointerUnion<InnerUnion1, InnerUnion2> ValTy; 346e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor private: 347e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor ValTy Val; 348e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor public: 349e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor PointerUnion4() {} 350e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 351e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor PointerUnion4(PT1 V) { 352e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor Val = InnerUnion1(V); 353e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 354e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor PointerUnion4(PT2 V) { 355e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor Val = InnerUnion1(V); 356e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 357e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor PointerUnion4(PT3 V) { 358e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor Val = InnerUnion2(V); 359e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 360e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor PointerUnion4(PT4 V) { 361e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor Val = InnerUnion2(V); 362e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 363e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 36426ef510d5d20b89c637d13e2d9169c0458de775cDouglas Gregor /// isNull - Return true if the pointer held in the union is null, 365e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// regardless of which type it is. 366e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor bool isNull() const { return Val.isNull(); } 367e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor operator bool() const { return !isNull(); } 368e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 369e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// is<T>() return true if the Union currently holds the type matching T. 370e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor template<typename T> 371e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor int is() const { 372128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis // If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2. 373128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis typedef typename 374128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis ::llvm::PointerUnionTypeSelector<PT1, T, InnerUnion1, 375128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis ::llvm::PointerUnionTypeSelector<PT2, T, InnerUnion1, InnerUnion2 > 376128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis >::Return Ty; 377128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis return Val.template is<Ty>() && 378128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis Val.template get<Ty>().template is<T>(); 379e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 380e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 381e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// get<T>() - Return the value of the specified pointer type. If the 382e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// specified pointer type is incorrect, assert. 383e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor template<typename T> 384e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor T get() const { 385e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor assert(is<T>() && "Invalid accessor called"); 386128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis // If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2. 387128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis typedef typename 388128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis ::llvm::PointerUnionTypeSelector<PT1, T, InnerUnion1, 389128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis ::llvm::PointerUnionTypeSelector<PT2, T, InnerUnion1, InnerUnion2 > 390128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis >::Return Ty; 391128ccbb8e5e142d4ec6c9afb4160b74f76cb3064Argyrios Kyrtzidis return Val.template get<Ty>().template get<T>(); 392e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 393e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 394e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// dyn_cast<T>() - If the current value is of the specified pointer type, 395e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// return it, otherwise return null. 396e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor template<typename T> 397e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor T dyn_cast() const { 398e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor if (is<T>()) return get<T>(); 399e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor return T(); 400e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 401e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 402e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// Assignment operators - Allow assigning into this union from either 403e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor /// pointer type, setting the discriminator to remember what it came from. 404e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor const PointerUnion4 &operator=(const PT1 &RHS) { 405e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor Val = InnerUnion1(RHS); 406e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor return *this; 407e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 408e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor const PointerUnion4 &operator=(const PT2 &RHS) { 409e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor Val = InnerUnion1(RHS); 410e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor return *this; 411e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 412e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor const PointerUnion4 &operator=(const PT3 &RHS) { 413e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor Val = InnerUnion2(RHS); 414e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor return *this; 415e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 416e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor const PointerUnion4 &operator=(const PT4 &RHS) { 417e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor Val = InnerUnion2(RHS); 418e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor return *this; 419e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 420e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 421e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor void *getOpaqueValue() const { return Val.getOpaqueValue(); } 4228260ea5c6c15345e00ced1398b03e6886145e45cTed Kremenek static inline PointerUnion4 getFromOpaqueValue(void *VP) { 423e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor PointerUnion4 V; 424e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor V.Val = ValTy::getFromOpaqueValue(VP); 425e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor return V; 426e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 427e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor }; 428e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 429e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor // Teach SmallPtrSet that PointerUnion4 is "basically a pointer", that has 430e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor // # low bits available = min(PT1bits,PT2bits,PT2bits)-2. 431e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor template<typename PT1, typename PT2, typename PT3, typename PT4> 432e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor class PointerLikeTypeTraits<PointerUnion4<PT1, PT2, PT3, PT4> > { 433e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor public: 434e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor static inline void * 435e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor getAsVoidPointer(const PointerUnion4<PT1, PT2, PT3, PT4> &P) { 436e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor return P.getOpaqueValue(); 437e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 438e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor static inline PointerUnion4<PT1, PT2, PT3, PT4> 439e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor getFromVoidPointer(void *P) { 440e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor return PointerUnion4<PT1, PT2, PT3, PT4>::getFromOpaqueValue(P); 441e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor } 442e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor 443e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor // The number of bits available are the min of the two pointer types. 444e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor enum { 445e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor NumLowBitsAvailable = 446e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor PointerLikeTypeTraits<typename PointerUnion4<PT1, PT2, PT3, PT4>::ValTy> 447e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor ::NumLowBitsAvailable 448e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor }; 449e657ec6701ee78e70ed7de43a9d98dbd00f330e5Douglas Gregor }; 4502491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner} 4512491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner 4522491e4657d95f7ff61fb2a741ba9996e492df515Chris Lattner#endif 453