| Chris Lattner | 98728f7 | 2002-04-08 21:43:56 +0000 | [diff] [blame] | 1 | //===-- Support/Casting.h - Allow flexible, checked, casts -------*- C++ -*--=// | 
|  | 2 | // | 
|  | 3 | // This file defines the isa<X>(), cast<X>(), dyn_cast<X>(), cast_or_null<X>(), | 
|  | 4 | // and dyn_cast_or_null<X>() templates. | 
|  | 5 | // | 
|  | 6 | //===----------------------------------------------------------------------===// | 
|  | 7 |  | 
|  | 8 | #ifndef SUPPORT_CASTING_H | 
|  | 9 | #define SUPPORT_CASTING_H | 
|  | 10 |  | 
| Chris Lattner | 98728f7 | 2002-04-08 21:43:56 +0000 | [diff] [blame] | 11 | //===----------------------------------------------------------------------===// | 
| Chris Lattner | 113f4f4 | 2002-06-25 16:13:24 +0000 | [diff] [blame] | 12 | //                          isa<x> Support Templates | 
| Chris Lattner | 98728f7 | 2002-04-08 21:43:56 +0000 | [diff] [blame] | 13 | //===----------------------------------------------------------------------===// | 
|  | 14 |  | 
| Chris Lattner | 113f4f4 | 2002-06-25 16:13:24 +0000 | [diff] [blame] | 15 | template<typename FromCl> struct isa_impl_cl; | 
|  | 16 |  | 
|  | 17 | // Define a template that can be specialized by smart pointers to reflect the | 
|  | 18 | // fact that they are automatically dereferenced, and are not involved with the | 
|  | 19 | // template selection process...  the default implementation is a noop. | 
|  | 20 | // | 
|  | 21 | template<typename From> struct simplify_type { | 
|  | 22 | typedef       From SimpleType;        // The real type this represents... | 
|  | 23 |  | 
|  | 24 | // An accessor to get the real value... | 
|  | 25 | static SimpleType &getSimplifiedValue(From &Val) { return Val; } | 
|  | 26 | }; | 
|  | 27 |  | 
|  | 28 | template<typename From> struct simplify_type<const From> { | 
|  | 29 | typedef const From SimpleType; | 
|  | 30 | static SimpleType &getSimplifiedValue(const From &Val) { | 
|  | 31 | return simplify_type<From>::getSimplifiedValue((From&)Val); | 
|  | 32 | } | 
|  | 33 | }; | 
|  | 34 |  | 
|  | 35 |  | 
| Chris Lattner | 98728f7 | 2002-04-08 21:43:56 +0000 | [diff] [blame] | 36 | // isa<X> - Return true if the parameter to the template is an instance of the | 
|  | 37 | // template type argument.  Used like this: | 
|  | 38 | // | 
| Chris Lattner | 113f4f4 | 2002-06-25 16:13:24 +0000 | [diff] [blame] | 39 | //  if (isa<Type*>(myVal)) { ... } | 
| Chris Lattner | 98728f7 | 2002-04-08 21:43:56 +0000 | [diff] [blame] | 40 | // | 
| Chris Lattner | 113f4f4 | 2002-06-25 16:13:24 +0000 | [diff] [blame] | 41 | template <typename To, typename From> | 
|  | 42 | inline bool isa_impl(const From &Val) { | 
|  | 43 | return To::classof(&Val); | 
| Chris Lattner | 98728f7 | 2002-04-08 21:43:56 +0000 | [diff] [blame] | 44 | } | 
|  | 45 |  | 
| Chris Lattner | 113f4f4 | 2002-06-25 16:13:24 +0000 | [diff] [blame] | 46 | template<typename To, typename From, typename SimpleType> | 
|  | 47 | struct isa_impl_wrap { | 
|  | 48 | // When From != SimplifiedType, we can simplify the type some more by using | 
|  | 49 | // the simplify_type template. | 
|  | 50 | static bool doit(const From &Val) { | 
|  | 51 | return isa_impl_cl<const SimpleType>::template | 
|  | 52 | isa<To>(simplify_type<const From>::getSimplifiedValue(Val)); | 
|  | 53 | } | 
|  | 54 | }; | 
|  | 55 |  | 
|  | 56 | template<typename To, typename FromTy> | 
|  | 57 | struct isa_impl_wrap<To, const FromTy, const FromTy> { | 
|  | 58 | // When From == SimpleType, we are as simple as we are going to get. | 
|  | 59 | static bool doit(const FromTy &Val) { | 
|  | 60 | return isa_impl<To,FromTy>(Val); | 
|  | 61 | } | 
|  | 62 | }; | 
|  | 63 |  | 
|  | 64 | // isa_impl_cl - Use class partial specialization to transform types to a single | 
|  | 65 | // cannonical form for isa_impl. | 
|  | 66 | // | 
|  | 67 | template<typename FromCl> | 
|  | 68 | struct isa_impl_cl { | 
|  | 69 | template<class ToCl> | 
|  | 70 | static bool isa(const FromCl &Val) { | 
|  | 71 | return isa_impl_wrap<ToCl,const FromCl, | 
| Chris Lattner | 2182c33 | 2002-07-24 20:22:09 +0000 | [diff] [blame] | 72 | typename simplify_type<const FromCl>::SimpleType>::doit(Val); | 
| Chris Lattner | 113f4f4 | 2002-06-25 16:13:24 +0000 | [diff] [blame] | 73 | } | 
|  | 74 | }; | 
|  | 75 |  | 
|  | 76 | // Specialization used to strip const qualifiers off of the FromCl type... | 
|  | 77 | template<typename FromCl> | 
|  | 78 | struct isa_impl_cl<const FromCl> { | 
|  | 79 | template<class ToCl> | 
|  | 80 | static bool isa(const FromCl &Val) { | 
|  | 81 | return isa_impl_cl<FromCl>::template isa<ToCl>(Val); | 
|  | 82 | } | 
|  | 83 | }; | 
|  | 84 |  | 
|  | 85 | // Define pointer traits in terms of base traits... | 
|  | 86 | template<class FromCl> | 
|  | 87 | struct isa_impl_cl<FromCl*> { | 
|  | 88 | template<class ToCl> | 
|  | 89 | static bool isa(FromCl *Val) { | 
|  | 90 | return isa_impl_cl<FromCl>::template isa<ToCl>(*Val); | 
|  | 91 | } | 
|  | 92 | }; | 
|  | 93 |  | 
|  | 94 | // Define reference traits in terms of base traits... | 
|  | 95 | template<class FromCl> | 
|  | 96 | struct isa_impl_cl<FromCl&> { | 
|  | 97 | template<class ToCl> | 
|  | 98 | static bool isa(FromCl &Val) { | 
|  | 99 | return isa_impl_cl<FromCl>::template isa<ToCl>(&Val); | 
|  | 100 | } | 
|  | 101 | }; | 
|  | 102 |  | 
|  | 103 | template <class X, class Y> | 
|  | 104 | inline bool isa(const Y &Val) { | 
|  | 105 | return isa_impl_cl<Y>::template isa<X>(Val); | 
|  | 106 | } | 
|  | 107 |  | 
|  | 108 | //===----------------------------------------------------------------------===// | 
|  | 109 | //                          cast<x> Support Templates | 
|  | 110 | //===----------------------------------------------------------------------===// | 
|  | 111 |  | 
|  | 112 | template<class To, class From> struct cast_retty; | 
|  | 113 |  | 
|  | 114 |  | 
|  | 115 | // Calculate what type the 'cast' function should return, based on a requested | 
|  | 116 | // type of To and a source type of From. | 
|  | 117 | template<class To, class From> struct cast_retty_impl { | 
|  | 118 | typedef To& ret_type;         // Normal case, return Ty& | 
|  | 119 | }; | 
|  | 120 | template<class To, class From> struct cast_retty_impl<To, const From> { | 
|  | 121 | typedef const To &ret_type;   // Normal case, return Ty& | 
|  | 122 | }; | 
|  | 123 |  | 
|  | 124 | template<class To, class From> struct cast_retty_impl<To, From*> { | 
|  | 125 | typedef To* ret_type;         // Pointer arg case, return Ty* | 
|  | 126 | }; | 
|  | 127 |  | 
|  | 128 | template<class To, class From> struct cast_retty_impl<To, const From*> { | 
|  | 129 | typedef const To* ret_type;   // Constant pointer arg case, return const Ty* | 
|  | 130 | }; | 
|  | 131 |  | 
|  | 132 | template<class To, class From> struct cast_retty_impl<To, const From*const> { | 
|  | 133 | typedef const To* ret_type;   // Constant pointer arg case, return const Ty* | 
|  | 134 | }; | 
|  | 135 |  | 
|  | 136 |  | 
|  | 137 | template<class To, class From, class SimpleFrom> | 
|  | 138 | struct cast_retty_wrap { | 
|  | 139 | // When the simplified type and the from type are not the same, use the type | 
|  | 140 | // simplifier to reduce the type, then reuse cast_retty_impl to get the | 
|  | 141 | // resultant type. | 
|  | 142 | typedef typename cast_retty<To, SimpleFrom>::ret_type ret_type; | 
|  | 143 | }; | 
|  | 144 |  | 
|  | 145 | template<class To, class FromTy> | 
|  | 146 | struct cast_retty_wrap<To, FromTy, FromTy> { | 
|  | 147 | // When the simplified type is equal to the from type, use it directly. | 
|  | 148 | typedef typename cast_retty_impl<To,FromTy>::ret_type ret_type; | 
|  | 149 | }; | 
|  | 150 |  | 
|  | 151 | template<class To, class From> | 
|  | 152 | struct cast_retty { | 
|  | 153 | typedef typename cast_retty_wrap<To, From, | 
| Chris Lattner | 2182c33 | 2002-07-24 20:22:09 +0000 | [diff] [blame] | 154 | typename simplify_type<From>::SimpleType>::ret_type ret_type; | 
| Chris Lattner | 113f4f4 | 2002-06-25 16:13:24 +0000 | [diff] [blame] | 155 | }; | 
|  | 156 |  | 
|  | 157 | // Ensure the non-simple values are converted using the simplify_type template | 
|  | 158 | // that may be specialized by smart pointers... | 
|  | 159 | // | 
|  | 160 | template<class To, class From, class SimpleFrom> struct cast_convert_val { | 
|  | 161 | // This is not a simple type, use the template to simplify it... | 
| Chris Lattner | 2182c33 | 2002-07-24 20:22:09 +0000 | [diff] [blame] | 162 | static typename cast_retty<To, From>::ret_type doit(const From &Val) { | 
| Chris Lattner | 113f4f4 | 2002-06-25 16:13:24 +0000 | [diff] [blame] | 163 | return cast_convert_val<To, SimpleFrom, | 
| Chris Lattner | 2182c33 | 2002-07-24 20:22:09 +0000 | [diff] [blame] | 164 | typename simplify_type<SimpleFrom>::SimpleType>::doit( | 
| Chris Lattner | 113f4f4 | 2002-06-25 16:13:24 +0000 | [diff] [blame] | 165 | simplify_type<From>::getSimplifiedValue(Val)); | 
|  | 166 | } | 
|  | 167 | }; | 
|  | 168 |  | 
|  | 169 | template<class To, class FromTy> struct cast_convert_val<To,FromTy,FromTy> { | 
|  | 170 | // This _is_ a simple type, just cast it. | 
| Chris Lattner | 2182c33 | 2002-07-24 20:22:09 +0000 | [diff] [blame] | 171 | static typename cast_retty<To, FromTy>::ret_type doit(const FromTy &Val) { | 
|  | 172 | return (typename cast_retty<To, FromTy>::ret_type)Val; | 
| Chris Lattner | 113f4f4 | 2002-06-25 16:13:24 +0000 | [diff] [blame] | 173 | } | 
|  | 174 | }; | 
|  | 175 |  | 
|  | 176 |  | 
| Chris Lattner | 98728f7 | 2002-04-08 21:43:56 +0000 | [diff] [blame] | 177 |  | 
|  | 178 | // cast<X> - Return the argument parameter cast to the specified type.  This | 
|  | 179 | // casting operator asserts that the type is correct, so it does not return null | 
|  | 180 | // on failure.  But it will correctly return NULL when the input is NULL. | 
|  | 181 | // Used Like this: | 
|  | 182 | // | 
| Chris Lattner | 113f4f4 | 2002-06-25 16:13:24 +0000 | [diff] [blame] | 183 | //  cast<Instruction>(myVal)->getParent() | 
| Chris Lattner | 98728f7 | 2002-04-08 21:43:56 +0000 | [diff] [blame] | 184 | // | 
|  | 185 | template <class X, class Y> | 
| Chris Lattner | 2182c33 | 2002-07-24 20:22:09 +0000 | [diff] [blame] | 186 | inline typename cast_retty<X, Y>::ret_type cast(const Y &Val) { | 
| Misha Brukman | a26dd3b | 2003-08-27 18:26:28 +0000 | [diff] [blame] | 187 | assert(isa<X>(Val) && "cast<Ty>() argument of incompatible type!"); | 
| Chris Lattner | 2182c33 | 2002-07-24 20:22:09 +0000 | [diff] [blame] | 188 | return cast_convert_val<X, Y, | 
|  | 189 | typename simplify_type<Y>::SimpleType>::doit(Val); | 
| Chris Lattner | 98728f7 | 2002-04-08 21:43:56 +0000 | [diff] [blame] | 190 | } | 
|  | 191 |  | 
|  | 192 | // cast_or_null<X> - Functionally identical to cast, except that a null value is | 
|  | 193 | // accepted. | 
|  | 194 | // | 
|  | 195 | template <class X, class Y> | 
| Chris Lattner | 2182c33 | 2002-07-24 20:22:09 +0000 | [diff] [blame] | 196 | inline typename cast_retty<X, Y*>::ret_type cast_or_null(Y *Val) { | 
| Chris Lattner | 113f4f4 | 2002-06-25 16:13:24 +0000 | [diff] [blame] | 197 | if (Val == 0) return 0; | 
| Misha Brukman | a26dd3b | 2003-08-27 18:26:28 +0000 | [diff] [blame] | 198 | assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!"); | 
| Chris Lattner | 113f4f4 | 2002-06-25 16:13:24 +0000 | [diff] [blame] | 199 | return cast<X>(Val); | 
| Chris Lattner | 98728f7 | 2002-04-08 21:43:56 +0000 | [diff] [blame] | 200 | } | 
|  | 201 |  | 
|  | 202 |  | 
|  | 203 | // dyn_cast<X> - Return the argument parameter cast to the specified type.  This | 
|  | 204 | // casting operator returns null if the argument is of the wrong type, so it can | 
|  | 205 | // be used to test for a type as well as cast if successful.  This should be | 
|  | 206 | // used in the context of an if statement like this: | 
|  | 207 | // | 
| Chris Lattner | d670b08 | 2003-05-29 15:07:48 +0000 | [diff] [blame] | 208 | //  if (const Instruction *I = dyn_cast<Instruction>(myVal)) { ... } | 
| Chris Lattner | 98728f7 | 2002-04-08 21:43:56 +0000 | [diff] [blame] | 209 | // | 
|  | 210 |  | 
|  | 211 | template <class X, class Y> | 
| Chris Lattner | 215b005 | 2003-04-23 16:17:28 +0000 | [diff] [blame] | 212 | inline typename cast_retty<X, Y>::ret_type dyn_cast(Y Val) { | 
|  | 213 | return isa<X>(Val) ? cast<X, Y>(Val) : 0; | 
| Chris Lattner | 98728f7 | 2002-04-08 21:43:56 +0000 | [diff] [blame] | 214 | } | 
|  | 215 |  | 
|  | 216 | // dyn_cast_or_null<X> - Functionally identical to dyn_cast, except that a null | 
|  | 217 | // value is accepted. | 
|  | 218 | // | 
|  | 219 | template <class X, class Y> | 
| Chris Lattner | d670b08 | 2003-05-29 15:07:48 +0000 | [diff] [blame] | 220 | inline typename cast_retty<X, Y>::ret_type dyn_cast_or_null(Y Val) { | 
|  | 221 | return (Val && isa<X>(Val)) ? cast<X, Y>(Val) : 0; | 
| Chris Lattner | 98728f7 | 2002-04-08 21:43:56 +0000 | [diff] [blame] | 222 | } | 
|  | 223 |  | 
| Chris Lattner | 113f4f4 | 2002-06-25 16:13:24 +0000 | [diff] [blame] | 224 |  | 
|  | 225 | #ifdef DEBUG_CAST_OPERATORS | 
|  | 226 | #include <iostream> | 
|  | 227 |  | 
|  | 228 | struct bar { | 
|  | 229 | bar() {} | 
|  | 230 | private: | 
|  | 231 | bar(const bar &); | 
|  | 232 | }; | 
|  | 233 | struct foo { | 
|  | 234 | void ext() const; | 
|  | 235 | /*  static bool classof(const bar *X) { | 
|  | 236 | cerr << "Classof: " << X << "\n"; | 
|  | 237 | return true; | 
|  | 238 | }*/ | 
|  | 239 | }; | 
|  | 240 |  | 
|  | 241 | template <> inline bool isa_impl<foo,bar>(const bar &Val) { | 
|  | 242 | cerr << "Classof: " << &Val << "\n"; | 
|  | 243 | return true; | 
|  | 244 | } | 
|  | 245 |  | 
|  | 246 |  | 
|  | 247 | bar *fub(); | 
|  | 248 | void test(bar &B1, const bar *B2) { | 
|  | 249 | // test various configurations of const | 
|  | 250 | const bar &B3 = B1; | 
|  | 251 | const bar *const B4 = B2; | 
|  | 252 |  | 
|  | 253 | // test isa | 
|  | 254 | if (!isa<foo>(B1)) return; | 
|  | 255 | if (!isa<foo>(B2)) return; | 
|  | 256 | if (!isa<foo>(B3)) return; | 
|  | 257 | if (!isa<foo>(B4)) return; | 
|  | 258 |  | 
|  | 259 | // test cast | 
|  | 260 | foo &F1 = cast<foo>(B1); | 
|  | 261 | const foo *F3 = cast<foo>(B2); | 
|  | 262 | const foo *F4 = cast<foo>(B2); | 
|  | 263 | const foo &F8 = cast<foo>(B3); | 
|  | 264 | const foo *F9 = cast<foo>(B4); | 
|  | 265 | foo *F10 = cast<foo>(fub()); | 
|  | 266 |  | 
|  | 267 | // test cast_or_null | 
|  | 268 | const foo *F11 = cast_or_null<foo>(B2); | 
|  | 269 | const foo *F12 = cast_or_null<foo>(B2); | 
|  | 270 | const foo *F13 = cast_or_null<foo>(B4); | 
|  | 271 | const foo *F14 = cast_or_null<foo>(fub());  // Shouldn't print. | 
|  | 272 |  | 
|  | 273 | // These lines are errors... | 
|  | 274 | //foo *F20 = cast<foo>(B2);  // Yields const foo* | 
|  | 275 | //foo &F21 = cast<foo>(B3);  // Yields const foo& | 
|  | 276 | //foo *F22 = cast<foo>(B4);  // Yields const foo* | 
|  | 277 | //foo &F23 = cast_or_null<foo>(B1); | 
|  | 278 | //const foo &F24 = cast_or_null<foo>(B3); | 
|  | 279 | } | 
|  | 280 |  | 
|  | 281 | bar *fub() { return 0; } | 
|  | 282 | void main() { | 
|  | 283 | bar B; | 
|  | 284 | test(B, &B); | 
|  | 285 | } | 
|  | 286 |  | 
|  | 287 | #endif | 
|  | 288 |  | 
| Chris Lattner | 98728f7 | 2002-04-08 21:43:56 +0000 | [diff] [blame] | 289 | #endif |