- in the vcall_and_vbase_offsets array. */
-
- orig_object = value_at_lazy (type, address, NULL);
- vbasetype = TYPE_VPTR_BASETYPE (VALUE_TYPE (orig_object));
- vbase_object = value_cast (vbasetype, orig_object);
-
- vtable_address
- = value_as_address (value_field (vbase_object,
- TYPE_VPTR_FIELDNO (vbasetype)));
+ in the vcall_and_vbase_offsets array. We used to cast the object to
+ its TYPE_VPTR_BASETYPE, and reference the vtable as TYPE_VPTR_FIELDNO;
+ however, that cast can not be done without calling baseclass_offset again
+ if the TYPE_VPTR_BASETYPE is a virtual base class, as described in the
+ v3 C++ ABI Section 2.4.I.2.b. Fortunately the ABI guarantees that the
+ vtable pointer will be located at the beginning of the object, so we can
+ bypass the casting. Verify that the TYPE_VPTR_FIELDNO is in fact at the
+ start of whichever baseclass it resides in, as a sanity measure. */
+
+ vbasetype = TYPE_VPTR_BASETYPE (type);
+ if (TYPE_FIELD_BITPOS (vbasetype, TYPE_VPTR_FIELDNO (vbasetype)) != 0)
+ error ("Illegal vptr offset in class %s",
+ TYPE_NAME (vbasetype) ? TYPE_NAME (vbasetype) : "<unknown>");
+
+ vtable_address = value_as_address (value_at_lazy (builtin_type_void_data_ptr,
+ address, NULL));