diff --git a/dlls/msvcrt/cppexcept.h b/dlls/msvcrt/cppexcept.h index d9ed2faee32..7947a17bb26 100644 --- a/dlls/msvcrt/cppexcept.h +++ b/dlls/msvcrt/cppexcept.h @@ -133,20 +133,21 @@ static inline const char *dbgstr_type_info( const type_info *info ) /* compute the this pointer for a base class of a given type */ static inline void *get_this_pointer( const this_ptr_offsets *off, void *object ) { - void *this_ptr; - int *offset_ptr; - if (!object) return NULL; - this_ptr = (char *)object + off->this_offset; + if (off->vbase_descr >= 0) { + int *offset_ptr; + /* move this ptr to vbase descriptor */ - this_ptr = (char *)this_ptr + off->vbase_descr; + object = (char *)object + off->vbase_descr; /* and fetch additional offset from vbase descriptor */ - offset_ptr = (int *)(*(char **)this_ptr + off->vbase_offset); - this_ptr = (char *)this_ptr + *offset_ptr; + offset_ptr = (int *)(*(char **)object + off->vbase_offset); + object = (char *)object + *offset_ptr; } - return this_ptr; + + object = (char *)object + off->this_offset; + return object; } #ifndef __x86_64__ diff --git a/dlls/msvcrt/tests/cpp.c b/dlls/msvcrt/tests/cpp.c index 8baf9b66d0e..88f82250fbb 100644 --- a/dlls/msvcrt/tests/cpp.c +++ b/dlls/msvcrt/tests/cpp.c @@ -901,6 +901,12 @@ static void test_rtti(void) { {RTTI_REF(child_class_rtti, base_descriptor[0]), RTTI_REF(child_class_rtti, base_descriptor[1])} }, {0, 0, 2, RTTI_REF(child_class_rtti, base_array)}, {1, 0, 0, RTTI_REF(child_class_rtti, type_info[1]), RTTI_REF(child_class_rtti, object_hierarchy), RTTI_REF(child_class_rtti, object_locator)} + }, virtual_base_class_rtti = { + { {NULL, NULL, "simple_class"}, {NULL, NULL, "child_class"} }, + { {RTTI_REF(virtual_base_class_rtti, type_info[1]), 0, {0x10, sizeof(void*), sizeof(int)}, 0}, {RTTI_REF(virtual_base_class_rtti, type_info[0]), 0, {8, -1, 0}, 0} }, + { {RTTI_REF(virtual_base_class_rtti, base_descriptor[0]), RTTI_REF(virtual_base_class_rtti, base_descriptor[1])} }, + {0, 0, 2, RTTI_REF(virtual_base_class_rtti, base_array)}, + {1, 0, 0, RTTI_REF(virtual_base_class_rtti, type_info[1]), RTTI_REF(virtual_base_class_rtti, object_hierarchy), RTTI_REF(virtual_base_class_rtti, object_locator)} }; static struct rtti_data simple_class_sig0_rtti, child_class_sig0_rtti; @@ -912,6 +918,9 @@ static void test_rtti(void) void *simple_class_sig0 = &simple_class_sig0_vtbl[1]; void *child_class_sig0_vtbl[2] = {&child_class_sig0_rtti.object_locator}; void *child_class_sig0 = &child_class_sig0_vtbl[1]; + void *virtual_base_class_vtbl[2] = {&virtual_base_class_rtti.object_locator}; + int virtual_base_class_vbtbl[2] = {0, 0x100}; + void *virtual_base_class[2] = {&virtual_base_class_vtbl[1], virtual_base_class_vbtbl}; static const char* e_name = "name"; type_info *ti,*bti; @@ -1026,6 +1035,9 @@ static void test_rtti(void) casted = p__RTDynamicCast(&child_class, 0, &child_class_rtti.type_info[0], &child_class_rtti.type_info[1], 0); ok(casted == (char*)&child_class+4, "failed cast to child class (%p %p)\n", casted, &child_class); + + casted = p__RTDynamicCast(&virtual_base_class, 0, &virtual_base_class_rtti.type_info[0], &virtual_base_class_rtti.type_info[1], 0); + ok(casted == (char*)&virtual_base_class+0x110+sizeof(void*), "failed cast to child class (%p %p)\n", casted, &virtual_base_class); } struct _demangle {