dynamic_cast.cc 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /*
  2. * Copyright 2010-2011 PathScale, Inc. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions are met:
  6. *
  7. * 1. Redistributions of source code must retain the above copyright notice,
  8. * this list of conditions and the following disclaimer.
  9. *
  10. * 2. Redistributions in binary form must reproduce the above copyright notice,
  11. * this list of conditions and the following disclaimer in the documentation
  12. * and/or other materials provided with the distribution.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
  15. * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  16. * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  17. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
  18. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  19. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  20. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  21. * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  22. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  23. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  24. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include "typeinfo.h"
  27. #include <stdio.h>
  28. using namespace ABI_NAMESPACE;
  29. /**
  30. * Vtable header.
  31. */
  32. struct vtable_header
  33. {
  34. /** Offset of the leaf object. */
  35. ptrdiff_t leaf_offset;
  36. /** Type of the object. */
  37. const __class_type_info *type;
  38. };
  39. /**
  40. * Simple macro that does pointer arithmetic in bytes but returns a value of
  41. * the same type as the original.
  42. */
  43. #define ADD_TO_PTR(x, off) reinterpret_cast<__typeof__(x)>(reinterpret_cast<char*>(x) + off)
  44. bool std::type_info::__do_catch(std::type_info const *ex_type,
  45. void **exception_object,
  46. unsigned int outer) const
  47. {
  48. const type_info *type = this;
  49. if (type == ex_type)
  50. {
  51. return true;
  52. }
  53. if (const __class_type_info *cti = dynamic_cast<const __class_type_info *>(type))
  54. {
  55. return ex_type->__do_upcast(cti, exception_object);
  56. }
  57. return false;
  58. }
  59. bool __pbase_type_info::__do_catch(std::type_info const *ex_type,
  60. void **exception_object,
  61. unsigned int outer) const
  62. {
  63. if (ex_type == this)
  64. {
  65. return true;
  66. }
  67. if (!ex_type->__is_pointer_p())
  68. {
  69. // Can't catch a non-pointer type in a pointer catch
  70. return false;
  71. }
  72. if (!(outer & 1))
  73. {
  74. // If the low bit is cleared on this means that we've gone
  75. // through a pointer that is not const qualified.
  76. return false;
  77. }
  78. // Clear the low bit on outer if we're not const qualified.
  79. if (!(__flags & __const_mask))
  80. {
  81. outer &= ~1;
  82. }
  83. const __pbase_type_info *ptr_type =
  84. static_cast<const __pbase_type_info*>(ex_type);
  85. if (ptr_type->__flags & ~__flags)
  86. {
  87. // Handler pointer is less qualified
  88. return false;
  89. }
  90. // Special case for void* handler.
  91. if(*__pointee == typeid(void))
  92. {
  93. return true;
  94. }
  95. return __pointee->__do_catch(ptr_type->__pointee, exception_object, outer);
  96. }
  97. void *__class_type_info::cast_to(void *obj, const struct __class_type_info *other) const
  98. {
  99. if (this == other)
  100. {
  101. return obj;
  102. }
  103. return 0;
  104. }
  105. void *__si_class_type_info::cast_to(void *obj, const struct __class_type_info *other) const
  106. {
  107. if (this == other)
  108. {
  109. return obj;
  110. }
  111. return __base_type->cast_to(obj, other);
  112. }
  113. bool __si_class_type_info::__do_upcast(const __class_type_info *target,
  114. void **thrown_object) const
  115. {
  116. if (this == target)
  117. {
  118. return true;
  119. }
  120. return __base_type->__do_upcast(target, thrown_object);
  121. }
  122. void *__vmi_class_type_info::cast_to(void *obj, const struct __class_type_info *other) const
  123. {
  124. if (__do_upcast(other, &obj))
  125. {
  126. return obj;
  127. }
  128. return 0;
  129. }
  130. bool __vmi_class_type_info::__do_upcast(const __class_type_info *target,
  131. void **thrown_object) const
  132. {
  133. if (this == target)
  134. {
  135. return true;
  136. }
  137. for (unsigned int i=0 ; i<__base_count ; i++)
  138. {
  139. const __base_class_type_info *info = &__base_info[i];
  140. ptrdiff_t offset = info->offset();
  141. // If this is a virtual superclass, the offset is stored in the
  142. // object's vtable at the offset requested; 2.9.5.6.c:
  143. //
  144. // 'For a non-virtual base, this is the offset in the object of the
  145. // base subobject. For a virtual base, this is the offset in the
  146. // virtual table of the virtual base offset for the virtual base
  147. // referenced (negative).'
  148. void *obj = *thrown_object;
  149. if (info->isVirtual())
  150. {
  151. // Object's vtable
  152. ptrdiff_t *off = *static_cast<ptrdiff_t**>(obj);
  153. // Offset location in vtable
  154. off = ADD_TO_PTR(off, offset);
  155. offset = *off;
  156. }
  157. void *cast = ADD_TO_PTR(obj, offset);
  158. if (info->__base_type == target ||
  159. (info->__base_type->__do_upcast(target, &cast)))
  160. {
  161. *thrown_object = cast;
  162. return true;
  163. }
  164. }
  165. return 0;
  166. }
  167. /**
  168. * ABI function used to implement the dynamic_cast<> operator. Some cases of
  169. * this operator are implemented entirely in the compiler (e.g. to void*).
  170. * This function implements the dynamic casts of the form dynamic_cast<T>(v).
  171. * This will be translated to a call to this function with the value v as the
  172. * first argument. The type id of the static type of v is the second argument
  173. * and the type id of the destination type (T) is the third argument.
  174. *
  175. * The third argument is a hint about the compiler's guess at the correct
  176. * pointer offset. If this value is negative, then -1 indicates no hint, -2
  177. * that src is not a public base of dst, and -3 that src is a multiple public
  178. * base type but never a virtual base type
  179. */
  180. extern "C" void* __dynamic_cast(const void *sub,
  181. const __class_type_info *src,
  182. const __class_type_info *dst,
  183. ptrdiff_t src2dst_offset)
  184. {
  185. const char *vtable_location = *static_cast<const char * const *>(sub);
  186. const vtable_header *header =
  187. reinterpret_cast<const vtable_header*>(vtable_location - sizeof(vtable_header));
  188. void *leaf = ADD_TO_PTR(const_cast<void *>(sub), header->leaf_offset);
  189. return header->type->cast_to(leaf, dst);
  190. }