LLVM API Documentation
00001 //===-- llvm/Support/Casting.h - Allow flexible, checked, casts -*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file was developed by the LLVM research group and is distributed under 00006 // the University of Illinois Open Source License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines the isa<X>(), cast<X>(), dyn_cast<X>(), cast_or_null<X>(), 00011 // and dyn_cast_or_null<X>() templates. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #ifndef LLVM_SUPPORT_CASTING_H 00016 #define LLVM_SUPPORT_CASTING_H 00017 00018 namespace llvm { 00019 00020 //===----------------------------------------------------------------------===// 00021 // isa<x> Support Templates 00022 //===----------------------------------------------------------------------===// 00023 00024 template<typename FromCl> struct isa_impl_cl; 00025 00026 // Define a template that can be specialized by smart pointers to reflect the 00027 // fact that they are automatically dereferenced, and are not involved with the 00028 // template selection process... the default implementation is a noop. 00029 // 00030 template<typename From> struct simplify_type { 00031 typedef From SimpleType; // The real type this represents... 00032 00033 // An accessor to get the real value... 00034 static SimpleType &getSimplifiedValue(From &Val) { return Val; } 00035 }; 00036 00037 template<typename From> struct simplify_type<const From> { 00038 typedef const From SimpleType; 00039 static SimpleType &getSimplifiedValue(const From &Val) { 00040 return simplify_type<From>::getSimplifiedValue(static_cast<From&>(Val)); 00041 } 00042 }; 00043 00044 00045 // isa<X> - Return true if the parameter to the template is an instance of the 00046 // template type argument. Used like this: 00047 // 00048 // if (isa<Type*>(myVal)) { ... } 00049 // 00050 template <typename To, typename From> 00051 inline bool isa_impl(const From &Val) { 00052 return To::classof(&Val); 00053 } 00054 00055 template<typename To, typename From, typename SimpleType> 00056 struct isa_impl_wrap { 00057 // When From != SimplifiedType, we can simplify the type some more by using 00058 // the simplify_type template. 00059 static bool doit(const From &Val) { 00060 return isa_impl_cl<const SimpleType>::template 00061 isa<To>(simplify_type<const From>::getSimplifiedValue(Val)); 00062 } 00063 }; 00064 00065 template<typename To, typename FromTy> 00066 struct isa_impl_wrap<To, const FromTy, const FromTy> { 00067 // When From == SimpleType, we are as simple as we are going to get. 00068 static bool doit(const FromTy &Val) { 00069 return isa_impl<To,FromTy>(Val); 00070 } 00071 }; 00072 00073 // isa_impl_cl - Use class partial specialization to transform types to a single 00074 // canonical form for isa_impl. 00075 // 00076 template<typename FromCl> 00077 struct isa_impl_cl { 00078 template<class ToCl> 00079 static bool isa(const FromCl &Val) { 00080 return isa_impl_wrap<ToCl,const FromCl, 00081 typename simplify_type<const FromCl>::SimpleType>::doit(Val); 00082 } 00083 }; 00084 00085 // Specialization used to strip const qualifiers off of the FromCl type... 00086 template<typename FromCl> 00087 struct isa_impl_cl<const FromCl> { 00088 template<class ToCl> 00089 static bool isa(const FromCl &Val) { 00090 return isa_impl_cl<FromCl>::template isa<ToCl>(Val); 00091 } 00092 }; 00093 00094 // Define pointer traits in terms of base traits... 00095 template<class FromCl> 00096 struct isa_impl_cl<FromCl*> { 00097 template<class ToCl> 00098 static bool isa(FromCl *Val) { 00099 return isa_impl_cl<FromCl>::template isa<ToCl>(*Val); 00100 } 00101 }; 00102 00103 // Define reference traits in terms of base traits... 00104 template<class FromCl> 00105 struct isa_impl_cl<FromCl&> { 00106 template<class ToCl> 00107 static bool isa(FromCl &Val) { 00108 return isa_impl_cl<FromCl>::template isa<ToCl>(&Val); 00109 } 00110 }; 00111 00112 template <class X, class Y> 00113 inline bool isa(const Y &Val) { 00114 return isa_impl_cl<Y>::template isa<X>(Val); 00115 } 00116 00117 //===----------------------------------------------------------------------===// 00118 // cast<x> Support Templates 00119 //===----------------------------------------------------------------------===// 00120 00121 template<class To, class From> struct cast_retty; 00122 00123 00124 // Calculate what type the 'cast' function should return, based on a requested 00125 // type of To and a source type of From. 00126 template<class To, class From> struct cast_retty_impl { 00127 typedef To& ret_type; // Normal case, return Ty& 00128 }; 00129 template<class To, class From> struct cast_retty_impl<To, const From> { 00130 typedef const To &ret_type; // Normal case, return Ty& 00131 }; 00132 00133 template<class To, class From> struct cast_retty_impl<To, From*> { 00134 typedef To* ret_type; // Pointer arg case, return Ty* 00135 }; 00136 00137 template<class To, class From> struct cast_retty_impl<To, const From*> { 00138 typedef const To* ret_type; // Constant pointer arg case, return const Ty* 00139 }; 00140 00141 template<class To, class From> struct cast_retty_impl<To, const From*const> { 00142 typedef const To* ret_type; // Constant pointer arg case, return const Ty* 00143 }; 00144 00145 00146 template<class To, class From, class SimpleFrom> 00147 struct cast_retty_wrap { 00148 // When the simplified type and the from type are not the same, use the type 00149 // simplifier to reduce the type, then reuse cast_retty_impl to get the 00150 // resultant type. 00151 typedef typename cast_retty<To, SimpleFrom>::ret_type ret_type; 00152 }; 00153 00154 template<class To, class FromTy> 00155 struct cast_retty_wrap<To, FromTy, FromTy> { 00156 // When the simplified type is equal to the from type, use it directly. 00157 typedef typename cast_retty_impl<To,FromTy>::ret_type ret_type; 00158 }; 00159 00160 template<class To, class From> 00161 struct cast_retty { 00162 typedef typename cast_retty_wrap<To, From, 00163 typename simplify_type<From>::SimpleType>::ret_type ret_type; 00164 }; 00165 00166 // Ensure the non-simple values are converted using the simplify_type template 00167 // that may be specialized by smart pointers... 00168 // 00169 template<class To, class From, class SimpleFrom> struct cast_convert_val { 00170 // This is not a simple type, use the template to simplify it... 00171 static typename cast_retty<To, From>::ret_type doit(const From &Val) { 00172 return cast_convert_val<To, SimpleFrom, 00173 typename simplify_type<SimpleFrom>::SimpleType>::doit( 00174 simplify_type<From>::getSimplifiedValue(Val)); 00175 } 00176 }; 00177 00178 template<class To, class FromTy> struct cast_convert_val<To,FromTy,FromTy> { 00179 // This _is_ a simple type, just cast it. 00180 static typename cast_retty<To, FromTy>::ret_type doit(const FromTy &Val) { 00181 return reinterpret_cast<typename cast_retty<To, FromTy>::ret_type>( 00182 const_cast<FromTy&>(Val)); 00183 } 00184 }; 00185 00186 00187 00188 // cast<X> - Return the argument parameter cast to the specified type. This 00189 // casting operator asserts that the type is correct, so it does not return null 00190 // on failure. But it will correctly return NULL when the input is NULL. 00191 // Used Like this: 00192 // 00193 // cast<Instruction>(myVal)->getParent() 00194 // 00195 template <class X, class Y> 00196 inline typename cast_retty<X, Y>::ret_type cast(const Y &Val) { 00197 assert(isa<X>(Val) && "cast<Ty>() argument of incompatible type!"); 00198 return cast_convert_val<X, Y, 00199 typename simplify_type<Y>::SimpleType>::doit(Val); 00200 } 00201 00202 // cast_or_null<X> - Functionally identical to cast, except that a null value is 00203 // accepted. 00204 // 00205 template <class X, class Y> 00206 inline typename cast_retty<X, Y*>::ret_type cast_or_null(Y *Val) { 00207 if (Val == 0) return 0; 00208 assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!"); 00209 return cast<X>(Val); 00210 } 00211 00212 00213 // dyn_cast<X> - Return the argument parameter cast to the specified type. This 00214 // casting operator returns null if the argument is of the wrong type, so it can 00215 // be used to test for a type as well as cast if successful. This should be 00216 // used in the context of an if statement like this: 00217 // 00218 // if (const Instruction *I = dyn_cast<Instruction>(myVal)) { ... } 00219 // 00220 00221 template <class X, class Y> 00222 inline typename cast_retty<X, Y>::ret_type dyn_cast(Y Val) { 00223 return isa<X>(Val) ? cast<X, Y>(Val) : 0; 00224 } 00225 00226 // dyn_cast_or_null<X> - Functionally identical to dyn_cast, except that a null 00227 // value is accepted. 00228 // 00229 template <class X, class Y> 00230 inline typename cast_retty<X, Y>::ret_type dyn_cast_or_null(Y Val) { 00231 return (Val && isa<X>(Val)) ? cast<X, Y>(Val) : 0; 00232 } 00233 00234 00235 #ifdef DEBUG_CAST_OPERATORS 00236 #include <iostream> 00237 00238 struct bar { 00239 bar() {} 00240 private: 00241 bar(const bar &); 00242 }; 00243 struct foo { 00244 void ext() const; 00245 /* static bool classof(const bar *X) { 00246 cerr << "Classof: " << X << "\n"; 00247 return true; 00248 }*/ 00249 }; 00250 00251 template <> inline bool isa_impl<foo,bar>(const bar &Val) { 00252 cerr << "Classof: " << &Val << "\n"; 00253 return true; 00254 } 00255 00256 00257 bar *fub(); 00258 void test(bar &B1, const bar *B2) { 00259 // test various configurations of const 00260 const bar &B3 = B1; 00261 const bar *const B4 = B2; 00262 00263 // test isa 00264 if (!isa<foo>(B1)) return; 00265 if (!isa<foo>(B2)) return; 00266 if (!isa<foo>(B3)) return; 00267 if (!isa<foo>(B4)) return; 00268 00269 // test cast 00270 foo &F1 = cast<foo>(B1); 00271 const foo *F3 = cast<foo>(B2); 00272 const foo *F4 = cast<foo>(B2); 00273 const foo &F8 = cast<foo>(B3); 00274 const foo *F9 = cast<foo>(B4); 00275 foo *F10 = cast<foo>(fub()); 00276 00277 // test cast_or_null 00278 const foo *F11 = cast_or_null<foo>(B2); 00279 const foo *F12 = cast_or_null<foo>(B2); 00280 const foo *F13 = cast_or_null<foo>(B4); 00281 const foo *F14 = cast_or_null<foo>(fub()); // Shouldn't print. 00282 00283 // These lines are errors... 00284 //foo *F20 = cast<foo>(B2); // Yields const foo* 00285 //foo &F21 = cast<foo>(B3); // Yields const foo& 00286 //foo *F22 = cast<foo>(B4); // Yields const foo* 00287 //foo &F23 = cast_or_null<foo>(B1); 00288 //const foo &F24 = cast_or_null<foo>(B3); 00289 } 00290 00291 bar *fub() { return 0; } 00292 void main() { 00293 bar B; 00294 test(B, &B); 00295 } 00296 00297 #endif 00298 00299 } // End llvm namespace 00300 00301 #endif