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