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