struct type *run_time_type;
struct type *base_type;
LONGEST offset_to_top;
+ struct type *values_type_vptr_basetype;
+ int values_type_vptr_fieldno;
/* We only have RTTI for class objects. */
if (TYPE_CODE (values_type) != TYPE_CODE_CLASS)
/* If we can't find the virtual table pointer for values_type, we
can't find the RTTI. */
- fill_in_vptr_fieldno (values_type);
- if (TYPE_VPTR_FIELDNO (values_type) == -1)
+ values_type_vptr_fieldno = get_vptr_fieldno (values_type,
+ &values_type_vptr_basetype);
+ if (values_type_vptr_fieldno == -1)
return NULL;
if (using_enc_p)
/* Fetch VALUE's virtual table pointer, and tweak it to point at
an instance of our imaginary gdb_gnu_v3_abi_vtable structure. */
- base_type = check_typedef (TYPE_VPTR_BASETYPE (values_type));
+ base_type = check_typedef (values_type_vptr_basetype);
if (values_type != base_type)
{
value = value_cast (base_type, value);
*using_enc_p = 1;
}
vtable_address
- = value_as_address (value_field (value, TYPE_VPTR_FIELDNO (values_type)));
+ = value_as_address (value_field (value, values_type_vptr_fieldno));
vtable = value_at_lazy (vtable_type,
vtable_address - vtable_address_point_offset ());
struct value *offset_val, *vbase_array;
CORE_ADDR vtable_address;
long int cur_base_offset, base_offset;
+ int vbasetype_vptr_fieldno;
/* If it isn't a virtual base, this is easy. The offset is in the
type definition. */
we have debugging information for that baseclass. */
vbasetype = TYPE_VPTR_BASETYPE (type);
- if (TYPE_VPTR_FIELDNO (vbasetype) < 0)
- fill_in_vptr_fieldno (vbasetype);
+ vbasetype_vptr_fieldno = get_vptr_fieldno (vbasetype, NULL);
- if (TYPE_VPTR_FIELDNO (vbasetype) >= 0
- && TYPE_FIELD_BITPOS (vbasetype, TYPE_VPTR_FIELDNO (vbasetype)) != 0)
+ if (vbasetype_vptr_fieldno >= 0
+ && TYPE_FIELD_BITPOS (vbasetype, vbasetype_vptr_fieldno) != 0)
error (_("Illegal vptr offset in class %s"),
TYPE_NAME (vbasetype) ? TYPE_NAME (vbasetype) : "<unknown>");
return NULL;
}
+/* Decode GNU v3 method pointer. */
+
+static int
+gnuv3_decode_method_ptr (const gdb_byte *contents,
+ CORE_ADDR *value_p,
+ LONGEST *adjustment_p)
+{
+ struct type *funcptr_type = builtin_type_void_func_ptr;
+ struct type *offset_type = builtin_type_long;
+ CORE_ADDR ptr_value;
+ LONGEST voffset, adjustment;
+ int vbit;
+
+ /* Extract the pointer to member. The first element is either a pointer
+ or a vtable offset. For pointers, we need to use extract_typed_address
+ to allow the back-end to convert the pointer to a GDB address -- but
+ vtable offsets we must handle as integers. At this point, we do not
+ yet know which case we have, so we extract the value under both
+ interpretations and choose the right one later on. */
+ ptr_value = extract_typed_address (contents, funcptr_type);
+ voffset = extract_signed_integer (contents, TYPE_LENGTH (funcptr_type));
+ contents += TYPE_LENGTH (funcptr_type);
+ adjustment = extract_signed_integer (contents, TYPE_LENGTH (offset_type));
+
+ if (!gdbarch_vbit_in_delta (current_gdbarch))
+ {
+ vbit = voffset & 1;
+ voffset = voffset ^ vbit;
+ }
+ else
+ {
+ vbit = adjustment & 1;
+ adjustment = adjustment >> 1;
+ }
+
+ *value_p = vbit? voffset : ptr_value;
+ *adjustment_p = adjustment;
+ return vbit;
+}
+
/* GNU v3 implementation of cplus_print_method_ptr. */
static void
domain = TYPE_DOMAIN_TYPE (type);
/* Extract the pointer to member. */
- ptr_value = extract_typed_address (contents, builtin_type_void_func_ptr);
- contents += TYPE_LENGTH (builtin_type_void_func_ptr);
- adjustment = extract_signed_integer (contents,
- TYPE_LENGTH (builtin_type_long));
-
- if (!gdbarch_vbit_in_delta (current_gdbarch))
- {
- vbit = ptr_value & 1;
- ptr_value = ptr_value ^ vbit;
- }
- else
- {
- vbit = adjustment & 1;
- adjustment = adjustment >> 1;
- }
+ vbit = gnuv3_decode_method_ptr (contents, &ptr_value, &adjustment);
/* Check for NULL. */
if (ptr_value == 0 && vbit == 0)
method_type = TYPE_TARGET_TYPE (check_typedef (value_type (method_ptr)));
- ptr_value = extract_typed_address (contents, builtin_type_void_func_ptr);
- contents += TYPE_LENGTH (builtin_type_void_func_ptr);
- adjustment = extract_signed_integer (contents,
- TYPE_LENGTH (builtin_type_long));
-
- if (!gdbarch_vbit_in_delta (current_gdbarch))
- {
- vbit = ptr_value & 1;
- ptr_value = ptr_value ^ vbit;
- }
- else
- {
- vbit = adjustment & 1;
- adjustment = adjustment >> 1;
- }
+ /* Extract the pointer to member. */
+ vbit = gnuv3_decode_method_ptr (contents, &ptr_value, &adjustment);
/* First convert THIS to match the containing type of the pointer to
member. This cast may adjust the value of THIS. */