Casting.h revision b2109ce97881269a610fa4afbcbca350e975174d
148486893f46d2e12e926682a3ecb908716bc66c4Chris Lattner//===-- Support/Casting.h - Allow flexible, checked, casts ------*- C++ -*-===//
2b2109ce97881269a610fa4afbcbca350e975174dJohn Criswell//
3b2109ce97881269a610fa4afbcbca350e975174dJohn Criswell//                     The LLVM Compiler Infrastructure
4b2109ce97881269a610fa4afbcbca350e975174dJohn Criswell//
5b2109ce97881269a610fa4afbcbca350e975174dJohn Criswell// This file was developed by the LLVM research group and is distributed under
6b2109ce97881269a610fa4afbcbca350e975174dJohn Criswell// the University of Illinois Open Source License. See LICENSE.TXT for details.
7b2109ce97881269a610fa4afbcbca350e975174dJohn Criswell//
8b2109ce97881269a610fa4afbcbca350e975174dJohn Criswell//===----------------------------------------------------------------------===//
9589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner//
10589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner// This file defines the isa<X>(), cast<X>(), dyn_cast<X>(), cast_or_null<X>(),
11589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner// and dyn_cast_or_null<X>() templates.
12589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner//
13589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner//===----------------------------------------------------------------------===//
14589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner
15589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner#ifndef SUPPORT_CASTING_H
16589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner#define SUPPORT_CASTING_H
17589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner
18589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner//===----------------------------------------------------------------------===//
197e70829632f82de15db187845666aaca6e04b792Chris Lattner//                          isa<x> Support Templates
20589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner//===----------------------------------------------------------------------===//
21589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner
227e70829632f82de15db187845666aaca6e04b792Chris Lattnertemplate<typename FromCl> struct isa_impl_cl;
237e70829632f82de15db187845666aaca6e04b792Chris Lattner
247e70829632f82de15db187845666aaca6e04b792Chris Lattner// Define a template that can be specialized by smart pointers to reflect the
257e70829632f82de15db187845666aaca6e04b792Chris Lattner// fact that they are automatically dereferenced, and are not involved with the
267e70829632f82de15db187845666aaca6e04b792Chris Lattner// template selection process...  the default implementation is a noop.
277e70829632f82de15db187845666aaca6e04b792Chris Lattner//
287e70829632f82de15db187845666aaca6e04b792Chris Lattnertemplate<typename From> struct simplify_type {
297e70829632f82de15db187845666aaca6e04b792Chris Lattner  typedef       From SimpleType;        // The real type this represents...
307e70829632f82de15db187845666aaca6e04b792Chris Lattner
317e70829632f82de15db187845666aaca6e04b792Chris Lattner  // An accessor to get the real value...
327e70829632f82de15db187845666aaca6e04b792Chris Lattner  static SimpleType &getSimplifiedValue(From &Val) { return Val; }
337e70829632f82de15db187845666aaca6e04b792Chris Lattner};
347e70829632f82de15db187845666aaca6e04b792Chris Lattner
357e70829632f82de15db187845666aaca6e04b792Chris Lattnertemplate<typename From> struct simplify_type<const From> {
367e70829632f82de15db187845666aaca6e04b792Chris Lattner  typedef const From SimpleType;
377e70829632f82de15db187845666aaca6e04b792Chris Lattner  static SimpleType &getSimplifiedValue(const From &Val) {
387e70829632f82de15db187845666aaca6e04b792Chris Lattner    return simplify_type<From>::getSimplifiedValue((From&)Val);
397e70829632f82de15db187845666aaca6e04b792Chris Lattner  }
407e70829632f82de15db187845666aaca6e04b792Chris Lattner};
417e70829632f82de15db187845666aaca6e04b792Chris Lattner
427e70829632f82de15db187845666aaca6e04b792Chris Lattner
43589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner// isa<X> - Return true if the parameter to the template is an instance of the
44589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner// template type argument.  Used like this:
45589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner//
467e70829632f82de15db187845666aaca6e04b792Chris Lattner//  if (isa<Type*>(myVal)) { ... }
477e70829632f82de15db187845666aaca6e04b792Chris Lattner//
487e70829632f82de15db187845666aaca6e04b792Chris Lattnertemplate <typename To, typename From>
497e70829632f82de15db187845666aaca6e04b792Chris Lattnerinline bool isa_impl(const From &Val) {
507e70829632f82de15db187845666aaca6e04b792Chris Lattner  return To::classof(&Val);
517e70829632f82de15db187845666aaca6e04b792Chris Lattner}
527e70829632f82de15db187845666aaca6e04b792Chris Lattner
537e70829632f82de15db187845666aaca6e04b792Chris Lattnertemplate<typename To, typename From, typename SimpleType>
547e70829632f82de15db187845666aaca6e04b792Chris Lattnerstruct isa_impl_wrap {
557e70829632f82de15db187845666aaca6e04b792Chris Lattner  // When From != SimplifiedType, we can simplify the type some more by using
567e70829632f82de15db187845666aaca6e04b792Chris Lattner  // the simplify_type template.
577e70829632f82de15db187845666aaca6e04b792Chris Lattner  static bool doit(const From &Val) {
587e70829632f82de15db187845666aaca6e04b792Chris Lattner    return isa_impl_cl<const SimpleType>::template
597e70829632f82de15db187845666aaca6e04b792Chris Lattner                    isa<To>(simplify_type<const From>::getSimplifiedValue(Val));
607e70829632f82de15db187845666aaca6e04b792Chris Lattner  }
617e70829632f82de15db187845666aaca6e04b792Chris Lattner};
627e70829632f82de15db187845666aaca6e04b792Chris Lattner
637e70829632f82de15db187845666aaca6e04b792Chris Lattnertemplate<typename To, typename FromTy>
647e70829632f82de15db187845666aaca6e04b792Chris Lattnerstruct isa_impl_wrap<To, const FromTy, const FromTy> {
657e70829632f82de15db187845666aaca6e04b792Chris Lattner  // When From == SimpleType, we are as simple as we are going to get.
667e70829632f82de15db187845666aaca6e04b792Chris Lattner  static bool doit(const FromTy &Val) {
677e70829632f82de15db187845666aaca6e04b792Chris Lattner    return isa_impl<To,FromTy>(Val);
687e70829632f82de15db187845666aaca6e04b792Chris Lattner  }
697e70829632f82de15db187845666aaca6e04b792Chris Lattner};
707e70829632f82de15db187845666aaca6e04b792Chris Lattner
717e70829632f82de15db187845666aaca6e04b792Chris Lattner// isa_impl_cl - Use class partial specialization to transform types to a single
72776f776838d6e2f83d899bc99452dc83779c341bChris Lattner// canonical form for isa_impl.
73589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner//
747e70829632f82de15db187845666aaca6e04b792Chris Lattnertemplate<typename FromCl>
757e70829632f82de15db187845666aaca6e04b792Chris Lattnerstruct isa_impl_cl {
767e70829632f82de15db187845666aaca6e04b792Chris Lattner  template<class ToCl>
777e70829632f82de15db187845666aaca6e04b792Chris Lattner  static bool isa(const FromCl &Val) {
787e70829632f82de15db187845666aaca6e04b792Chris Lattner    return isa_impl_wrap<ToCl,const FromCl,
795a6d63ae29512d654c8c697f42f32f97b9dc010bChris Lattner                   typename simplify_type<const FromCl>::SimpleType>::doit(Val);
807e70829632f82de15db187845666aaca6e04b792Chris Lattner  }
817e70829632f82de15db187845666aaca6e04b792Chris Lattner};
827e70829632f82de15db187845666aaca6e04b792Chris Lattner
837e70829632f82de15db187845666aaca6e04b792Chris Lattner// Specialization used to strip const qualifiers off of the FromCl type...
847e70829632f82de15db187845666aaca6e04b792Chris Lattnertemplate<typename FromCl>
857e70829632f82de15db187845666aaca6e04b792Chris Lattnerstruct isa_impl_cl<const FromCl> {
867e70829632f82de15db187845666aaca6e04b792Chris Lattner  template<class ToCl>
877e70829632f82de15db187845666aaca6e04b792Chris Lattner  static bool isa(const FromCl &Val) {
887e70829632f82de15db187845666aaca6e04b792Chris Lattner    return isa_impl_cl<FromCl>::template isa<ToCl>(Val);
897e70829632f82de15db187845666aaca6e04b792Chris Lattner  }
907e70829632f82de15db187845666aaca6e04b792Chris Lattner};
917e70829632f82de15db187845666aaca6e04b792Chris Lattner
927e70829632f82de15db187845666aaca6e04b792Chris Lattner// Define pointer traits in terms of base traits...
937e70829632f82de15db187845666aaca6e04b792Chris Lattnertemplate<class FromCl>
947e70829632f82de15db187845666aaca6e04b792Chris Lattnerstruct isa_impl_cl<FromCl*> {
957e70829632f82de15db187845666aaca6e04b792Chris Lattner  template<class ToCl>
967e70829632f82de15db187845666aaca6e04b792Chris Lattner  static bool isa(FromCl *Val) {
977e70829632f82de15db187845666aaca6e04b792Chris Lattner    return isa_impl_cl<FromCl>::template isa<ToCl>(*Val);
987e70829632f82de15db187845666aaca6e04b792Chris Lattner  }
997e70829632f82de15db187845666aaca6e04b792Chris Lattner};
1007e70829632f82de15db187845666aaca6e04b792Chris Lattner
1017e70829632f82de15db187845666aaca6e04b792Chris Lattner// Define reference traits in terms of base traits...
1027e70829632f82de15db187845666aaca6e04b792Chris Lattnertemplate<class FromCl>
1037e70829632f82de15db187845666aaca6e04b792Chris Lattnerstruct isa_impl_cl<FromCl&> {
1047e70829632f82de15db187845666aaca6e04b792Chris Lattner  template<class ToCl>
1057e70829632f82de15db187845666aaca6e04b792Chris Lattner  static bool isa(FromCl &Val) {
1067e70829632f82de15db187845666aaca6e04b792Chris Lattner    return isa_impl_cl<FromCl>::template isa<ToCl>(&Val);
1077e70829632f82de15db187845666aaca6e04b792Chris Lattner  }
1087e70829632f82de15db187845666aaca6e04b792Chris Lattner};
1097e70829632f82de15db187845666aaca6e04b792Chris Lattner
110589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattnertemplate <class X, class Y>
1117e70829632f82de15db187845666aaca6e04b792Chris Lattnerinline bool isa(const Y &Val) {
1127e70829632f82de15db187845666aaca6e04b792Chris Lattner  return isa_impl_cl<Y>::template isa<X>(Val);
113589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner}
114589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner
1157e70829632f82de15db187845666aaca6e04b792Chris Lattner//===----------------------------------------------------------------------===//
1167e70829632f82de15db187845666aaca6e04b792Chris Lattner//                          cast<x> Support Templates
1177e70829632f82de15db187845666aaca6e04b792Chris Lattner//===----------------------------------------------------------------------===//
1187e70829632f82de15db187845666aaca6e04b792Chris Lattner
1197e70829632f82de15db187845666aaca6e04b792Chris Lattnertemplate<class To, class From> struct cast_retty;
1207e70829632f82de15db187845666aaca6e04b792Chris Lattner
1217e70829632f82de15db187845666aaca6e04b792Chris Lattner
1227e70829632f82de15db187845666aaca6e04b792Chris Lattner// Calculate what type the 'cast' function should return, based on a requested
1237e70829632f82de15db187845666aaca6e04b792Chris Lattner// type of To and a source type of From.
1247e70829632f82de15db187845666aaca6e04b792Chris Lattnertemplate<class To, class From> struct cast_retty_impl {
1257e70829632f82de15db187845666aaca6e04b792Chris Lattner  typedef To& ret_type;         // Normal case, return Ty&
1267e70829632f82de15db187845666aaca6e04b792Chris Lattner};
1277e70829632f82de15db187845666aaca6e04b792Chris Lattnertemplate<class To, class From> struct cast_retty_impl<To, const From> {
1287e70829632f82de15db187845666aaca6e04b792Chris Lattner  typedef const To &ret_type;   // Normal case, return Ty&
1297e70829632f82de15db187845666aaca6e04b792Chris Lattner};
1307e70829632f82de15db187845666aaca6e04b792Chris Lattner
1317e70829632f82de15db187845666aaca6e04b792Chris Lattnertemplate<class To, class From> struct cast_retty_impl<To, From*> {
1327e70829632f82de15db187845666aaca6e04b792Chris Lattner  typedef To* ret_type;         // Pointer arg case, return Ty*
1337e70829632f82de15db187845666aaca6e04b792Chris Lattner};
1347e70829632f82de15db187845666aaca6e04b792Chris Lattner
1357e70829632f82de15db187845666aaca6e04b792Chris Lattnertemplate<class To, class From> struct cast_retty_impl<To, const From*> {
1367e70829632f82de15db187845666aaca6e04b792Chris Lattner  typedef const To* ret_type;   // Constant pointer arg case, return const Ty*
1377e70829632f82de15db187845666aaca6e04b792Chris Lattner};
1387e70829632f82de15db187845666aaca6e04b792Chris Lattner
1397e70829632f82de15db187845666aaca6e04b792Chris Lattnertemplate<class To, class From> struct cast_retty_impl<To, const From*const> {
1407e70829632f82de15db187845666aaca6e04b792Chris Lattner  typedef const To* ret_type;   // Constant pointer arg case, return const Ty*
1417e70829632f82de15db187845666aaca6e04b792Chris Lattner};
1427e70829632f82de15db187845666aaca6e04b792Chris Lattner
1437e70829632f82de15db187845666aaca6e04b792Chris Lattner
1447e70829632f82de15db187845666aaca6e04b792Chris Lattnertemplate<class To, class From, class SimpleFrom>
1457e70829632f82de15db187845666aaca6e04b792Chris Lattnerstruct cast_retty_wrap {
1467e70829632f82de15db187845666aaca6e04b792Chris Lattner  // When the simplified type and the from type are not the same, use the type
1477e70829632f82de15db187845666aaca6e04b792Chris Lattner  // simplifier to reduce the type, then reuse cast_retty_impl to get the
1487e70829632f82de15db187845666aaca6e04b792Chris Lattner  // resultant type.
1497e70829632f82de15db187845666aaca6e04b792Chris Lattner  typedef typename cast_retty<To, SimpleFrom>::ret_type ret_type;
1507e70829632f82de15db187845666aaca6e04b792Chris Lattner};
1517e70829632f82de15db187845666aaca6e04b792Chris Lattner
1527e70829632f82de15db187845666aaca6e04b792Chris Lattnertemplate<class To, class FromTy>
1537e70829632f82de15db187845666aaca6e04b792Chris Lattnerstruct cast_retty_wrap<To, FromTy, FromTy> {
1547e70829632f82de15db187845666aaca6e04b792Chris Lattner  // When the simplified type is equal to the from type, use it directly.
1557e70829632f82de15db187845666aaca6e04b792Chris Lattner  typedef typename cast_retty_impl<To,FromTy>::ret_type ret_type;
1567e70829632f82de15db187845666aaca6e04b792Chris Lattner};
1577e70829632f82de15db187845666aaca6e04b792Chris Lattner
1587e70829632f82de15db187845666aaca6e04b792Chris Lattnertemplate<class To, class From>
1597e70829632f82de15db187845666aaca6e04b792Chris Lattnerstruct cast_retty {
1607e70829632f82de15db187845666aaca6e04b792Chris Lattner  typedef typename cast_retty_wrap<To, From,
1615a6d63ae29512d654c8c697f42f32f97b9dc010bChris Lattner                   typename simplify_type<From>::SimpleType>::ret_type ret_type;
1627e70829632f82de15db187845666aaca6e04b792Chris Lattner};
1637e70829632f82de15db187845666aaca6e04b792Chris Lattner
1647e70829632f82de15db187845666aaca6e04b792Chris Lattner// Ensure the non-simple values are converted using the simplify_type template
1657e70829632f82de15db187845666aaca6e04b792Chris Lattner// that may be specialized by smart pointers...
1667e70829632f82de15db187845666aaca6e04b792Chris Lattner//
1677e70829632f82de15db187845666aaca6e04b792Chris Lattnertemplate<class To, class From, class SimpleFrom> struct cast_convert_val {
1687e70829632f82de15db187845666aaca6e04b792Chris Lattner  // This is not a simple type, use the template to simplify it...
1695a6d63ae29512d654c8c697f42f32f97b9dc010bChris Lattner  static typename cast_retty<To, From>::ret_type doit(const From &Val) {
1707e70829632f82de15db187845666aaca6e04b792Chris Lattner    return cast_convert_val<To, SimpleFrom,
1715a6d63ae29512d654c8c697f42f32f97b9dc010bChris Lattner      typename simplify_type<SimpleFrom>::SimpleType>::doit(
1727e70829632f82de15db187845666aaca6e04b792Chris Lattner                          simplify_type<From>::getSimplifiedValue(Val));
1737e70829632f82de15db187845666aaca6e04b792Chris Lattner  }
1747e70829632f82de15db187845666aaca6e04b792Chris Lattner};
1757e70829632f82de15db187845666aaca6e04b792Chris Lattner
1767e70829632f82de15db187845666aaca6e04b792Chris Lattnertemplate<class To, class FromTy> struct cast_convert_val<To,FromTy,FromTy> {
1777e70829632f82de15db187845666aaca6e04b792Chris Lattner  // This _is_ a simple type, just cast it.
1785a6d63ae29512d654c8c697f42f32f97b9dc010bChris Lattner  static typename cast_retty<To, FromTy>::ret_type doit(const FromTy &Val) {
1795a6d63ae29512d654c8c697f42f32f97b9dc010bChris Lattner    return (typename cast_retty<To, FromTy>::ret_type)Val;
1807e70829632f82de15db187845666aaca6e04b792Chris Lattner  }
1817e70829632f82de15db187845666aaca6e04b792Chris Lattner};
1827e70829632f82de15db187845666aaca6e04b792Chris Lattner
1837e70829632f82de15db187845666aaca6e04b792Chris Lattner
184589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner
185589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner// cast<X> - Return the argument parameter cast to the specified type.  This
186589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner// casting operator asserts that the type is correct, so it does not return null
187589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner// on failure.  But it will correctly return NULL when the input is NULL.
188589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner// Used Like this:
189589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner//
1907e70829632f82de15db187845666aaca6e04b792Chris Lattner//  cast<Instruction>(myVal)->getParent()
191589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner//
192589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattnertemplate <class X, class Y>
1935a6d63ae29512d654c8c697f42f32f97b9dc010bChris Lattnerinline typename cast_retty<X, Y>::ret_type cast(const Y &Val) {
19488d942d8983aadecae477fee523c23312d194515Misha Brukman  assert(isa<X>(Val) && "cast<Ty>() argument of incompatible type!");
1955a6d63ae29512d654c8c697f42f32f97b9dc010bChris Lattner  return cast_convert_val<X, Y,
1965a6d63ae29512d654c8c697f42f32f97b9dc010bChris Lattner                          typename simplify_type<Y>::SimpleType>::doit(Val);
197589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner}
198589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner
199589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner// cast_or_null<X> - Functionally identical to cast, except that a null value is
200589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner// accepted.
201589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner//
202589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattnertemplate <class X, class Y>
2035a6d63ae29512d654c8c697f42f32f97b9dc010bChris Lattnerinline typename cast_retty<X, Y*>::ret_type cast_or_null(Y *Val) {
2047e70829632f82de15db187845666aaca6e04b792Chris Lattner  if (Val == 0) return 0;
20588d942d8983aadecae477fee523c23312d194515Misha Brukman  assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!");
2067e70829632f82de15db187845666aaca6e04b792Chris Lattner  return cast<X>(Val);
207589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner}
208589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner
209589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner
210589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner// dyn_cast<X> - Return the argument parameter cast to the specified type.  This
211589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner// casting operator returns null if the argument is of the wrong type, so it can
212589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner// be used to test for a type as well as cast if successful.  This should be
213589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner// used in the context of an if statement like this:
214589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner//
2151ff1da7ac9bff43ba24445ff30ba2fd79bd95cd7Chris Lattner//  if (const Instruction *I = dyn_cast<Instruction>(myVal)) { ... }
216589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner//
217589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner
218589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattnertemplate <class X, class Y>
219ea0f49e52436272c65b52fe1e83f5009aa191a21Chris Lattnerinline typename cast_retty<X, Y>::ret_type dyn_cast(Y Val) {
220ea0f49e52436272c65b52fe1e83f5009aa191a21Chris Lattner  return isa<X>(Val) ? cast<X, Y>(Val) : 0;
221589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner}
222589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner
223589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner// dyn_cast_or_null<X> - Functionally identical to dyn_cast, except that a null
224589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner// value is accepted.
225589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner//
226589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattnertemplate <class X, class Y>
2271ff1da7ac9bff43ba24445ff30ba2fd79bd95cd7Chris Lattnerinline typename cast_retty<X, Y>::ret_type dyn_cast_or_null(Y Val) {
2281ff1da7ac9bff43ba24445ff30ba2fd79bd95cd7Chris Lattner  return (Val && isa<X>(Val)) ? cast<X, Y>(Val) : 0;
2297e70829632f82de15db187845666aaca6e04b792Chris Lattner}
2307e70829632f82de15db187845666aaca6e04b792Chris Lattner
2317e70829632f82de15db187845666aaca6e04b792Chris Lattner
2327e70829632f82de15db187845666aaca6e04b792Chris Lattner#ifdef DEBUG_CAST_OPERATORS
2337e70829632f82de15db187845666aaca6e04b792Chris Lattner#include <iostream>
2347e70829632f82de15db187845666aaca6e04b792Chris Lattner
2357e70829632f82de15db187845666aaca6e04b792Chris Lattnerstruct bar {
2367e70829632f82de15db187845666aaca6e04b792Chris Lattner  bar() {}
2377e70829632f82de15db187845666aaca6e04b792Chris Lattnerprivate:
2387e70829632f82de15db187845666aaca6e04b792Chris Lattner  bar(const bar &);
2397e70829632f82de15db187845666aaca6e04b792Chris Lattner};
2407e70829632f82de15db187845666aaca6e04b792Chris Lattnerstruct foo {
2417e70829632f82de15db187845666aaca6e04b792Chris Lattner  void ext() const;
2427e70829632f82de15db187845666aaca6e04b792Chris Lattner  /*  static bool classof(const bar *X) {
2437e70829632f82de15db187845666aaca6e04b792Chris Lattner    cerr << "Classof: " << X << "\n";
2447e70829632f82de15db187845666aaca6e04b792Chris Lattner    return true;
2457e70829632f82de15db187845666aaca6e04b792Chris Lattner    }*/
2467e70829632f82de15db187845666aaca6e04b792Chris Lattner};
2477e70829632f82de15db187845666aaca6e04b792Chris Lattner
2487e70829632f82de15db187845666aaca6e04b792Chris Lattnertemplate <> inline bool isa_impl<foo,bar>(const bar &Val) {
2497e70829632f82de15db187845666aaca6e04b792Chris Lattner  cerr << "Classof: " << &Val << "\n";
2507e70829632f82de15db187845666aaca6e04b792Chris Lattner  return true;
2517e70829632f82de15db187845666aaca6e04b792Chris Lattner}
2527e70829632f82de15db187845666aaca6e04b792Chris Lattner
2537e70829632f82de15db187845666aaca6e04b792Chris Lattner
2547e70829632f82de15db187845666aaca6e04b792Chris Lattnerbar *fub();
2557e70829632f82de15db187845666aaca6e04b792Chris Lattnervoid test(bar &B1, const bar *B2) {
2567e70829632f82de15db187845666aaca6e04b792Chris Lattner  // test various configurations of const
2577e70829632f82de15db187845666aaca6e04b792Chris Lattner  const bar &B3 = B1;
2587e70829632f82de15db187845666aaca6e04b792Chris Lattner  const bar *const B4 = B2;
2597e70829632f82de15db187845666aaca6e04b792Chris Lattner
2607e70829632f82de15db187845666aaca6e04b792Chris Lattner  // test isa
2617e70829632f82de15db187845666aaca6e04b792Chris Lattner  if (!isa<foo>(B1)) return;
2627e70829632f82de15db187845666aaca6e04b792Chris Lattner  if (!isa<foo>(B2)) return;
2637e70829632f82de15db187845666aaca6e04b792Chris Lattner  if (!isa<foo>(B3)) return;
2647e70829632f82de15db187845666aaca6e04b792Chris Lattner  if (!isa<foo>(B4)) return;
2657e70829632f82de15db187845666aaca6e04b792Chris Lattner
2667e70829632f82de15db187845666aaca6e04b792Chris Lattner  // test cast
2677e70829632f82de15db187845666aaca6e04b792Chris Lattner  foo &F1 = cast<foo>(B1);
2687e70829632f82de15db187845666aaca6e04b792Chris Lattner  const foo *F3 = cast<foo>(B2);
2697e70829632f82de15db187845666aaca6e04b792Chris Lattner  const foo *F4 = cast<foo>(B2);
2707e70829632f82de15db187845666aaca6e04b792Chris Lattner  const foo &F8 = cast<foo>(B3);
2717e70829632f82de15db187845666aaca6e04b792Chris Lattner  const foo *F9 = cast<foo>(B4);
2727e70829632f82de15db187845666aaca6e04b792Chris Lattner  foo *F10 = cast<foo>(fub());
2737e70829632f82de15db187845666aaca6e04b792Chris Lattner
2747e70829632f82de15db187845666aaca6e04b792Chris Lattner  // test cast_or_null
2757e70829632f82de15db187845666aaca6e04b792Chris Lattner  const foo *F11 = cast_or_null<foo>(B2);
2767e70829632f82de15db187845666aaca6e04b792Chris Lattner  const foo *F12 = cast_or_null<foo>(B2);
2777e70829632f82de15db187845666aaca6e04b792Chris Lattner  const foo *F13 = cast_or_null<foo>(B4);
2787e70829632f82de15db187845666aaca6e04b792Chris Lattner  const foo *F14 = cast_or_null<foo>(fub());  // Shouldn't print.
2797e70829632f82de15db187845666aaca6e04b792Chris Lattner
2807e70829632f82de15db187845666aaca6e04b792Chris Lattner  // These lines are errors...
2817e70829632f82de15db187845666aaca6e04b792Chris Lattner  //foo *F20 = cast<foo>(B2);  // Yields const foo*
2827e70829632f82de15db187845666aaca6e04b792Chris Lattner  //foo &F21 = cast<foo>(B3);  // Yields const foo&
2837e70829632f82de15db187845666aaca6e04b792Chris Lattner  //foo *F22 = cast<foo>(B4);  // Yields const foo*
2847e70829632f82de15db187845666aaca6e04b792Chris Lattner  //foo &F23 = cast_or_null<foo>(B1);
2857e70829632f82de15db187845666aaca6e04b792Chris Lattner  //const foo &F24 = cast_or_null<foo>(B3);
2867e70829632f82de15db187845666aaca6e04b792Chris Lattner}
2877e70829632f82de15db187845666aaca6e04b792Chris Lattner
2887e70829632f82de15db187845666aaca6e04b792Chris Lattnerbar *fub() { return 0; }
2897e70829632f82de15db187845666aaca6e04b792Chris Lattnervoid main() {
2907e70829632f82de15db187845666aaca6e04b792Chris Lattner  bar B;
2917e70829632f82de15db187845666aaca6e04b792Chris Lattner  test(B, &B);
292589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner}
293589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner
294589df88ba03a81b2b3dc9d084c191a3a74724ecdChris Lattner#endif
2957e70829632f82de15db187845666aaca6e04b792Chris Lattner
2967e70829632f82de15db187845666aaca6e04b792Chris Lattner#endif
297