summaryrefslogtreecommitdiff
path: root/src/dynamic_cast.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/dynamic_cast.cc')
-rw-r--r--src/dynamic_cast.cc19
1 files changed, 17 insertions, 2 deletions
diff --git a/src/dynamic_cast.cc b/src/dynamic_cast.cc
index a68248b..043796f 100644
--- a/src/dynamic_cast.cc
+++ b/src/dynamic_cast.cc
@@ -14,6 +14,10 @@ struct vtable_header
const __class_type_info *type;
};
+/**
+ * Simple macro that does pointer arithmetic in bytes but returns a value of
+ * the same type as the original.
+ */
#define ADD_TO_PTR(x, off) (__typeof__(x))(((char*)x) + off)
bool __class_type_info::can_cast_to(const struct __class_type_info *other) const
@@ -104,7 +108,17 @@ void *__vmi_class_type_info::cast_to(void *obj, const struct __class_type_info *
}
/**
- * ABI function used to implement the dynamic_cast<> operator.
+ * ABI function used to implement the dynamic_cast<> operator. Some cases of
+ * this operator are implemented entirely in the compiler (e.g. to void*).
+ * This function implements the dynamic casts of the form dynamic_cast<T>(v).
+ * This will be translated to a call to this function with the value v as the
+ * first argument. The type id of the static type of v is the second argument
+ * and the type id of the destination type (T) is the third argument.
+ *
+ * The third argument is a hint about the compiler's guess at the correct
+ * pointer offset. If this value is negative, then -1 indicates no hint, -2
+ * that src is not a public base of dst, and -3 that src is a multiple public
+ * base type but never a virtual base type
*/
extern "C" void* __dynamic_cast(const void *sub,
const __class_type_info *src,
@@ -112,7 +126,8 @@ extern "C" void* __dynamic_cast(const void *sub,
ptrdiff_t src2dst_offset)
{
char *vtable_location = *(char**)sub;
- const vtable_header *header = (const vtable_header*)(vtable_location - sizeof(vtable_header));
+ const vtable_header *header =
+ (const vtable_header*)(vtable_location - sizeof(vtable_header));
void *leaf = ADD_TO_PTR((void*)sub, header->leaf_offset);
return header->type->cast_to(leaf, dst);
}