+Fri Oct 25 18:59:32 1991 Per Bothner (bothner at cygnus.com)
+
+ Various fixes to improve g++ debugging.
+ * symtab.h: Add is_const and is_volatile flags for each method.
+ These are bit fields - take their space from voffset,
+ which shrinks to 30 bits. Since voffset is now a bitfield,
+ make it unsigned for portability. This changes its interpretation
+ slightly: Static methods now have voffset 1 instead of -1,
+ and virtual offsets start at 2, not 1.
+ * symtab.c: Renamed gdb_mangle_typename to gdb_mangle_name,
+ since it now returns an entire magled method name, not just
+ the type part. This avoids some duplication.
+ It also allows us to correctly mangle const and volatile
+ methods (using the new is_const and is_volatile bit fields
+ mentioned above).
+ * valprint.c (type_print_base), values.c (check_stub_method):
+ Simplify by using new gdb_mangle_name.
+ * values.c (value_headof): Fix to correctly handle single
+ inheritance (actually two fixes, either of which suffices).
+ * dbxread.c (read_struct_type): Handle const and volatile
+ method specifiers.
+ * dbxread.c (read_struct_type): Yet one more place where
+ we must handle '\\' continuations.
+ * valprint.c (vtbl_ptr_name): Add final '\0'.
+
Fri Oct 25 16:06:38 1991 Stu Grossman (grossman at cygnus.com)
* tm-sparc.h, tm-68k.h (EXTRACT_RETURN_VALUE): fix output of
*pp = p + 1;
new_sublist->visibility = *(*pp)++ - '0';
if (**pp == '\\') *pp = next_symbol_text ();
- /* FIXME-tiemann: need to add const/volatile info
- to the methods. For now, just skip the char.
- In future, here's what we need to implement:
-
- A for normal functions.
- B for `const' member functions.
- C for `volatile' member functions.
- D for `const volatile' member functions. */
- if (**pp == 'A' || **pp == 'B' || **pp == 'C' || **pp == 'D')
- (*pp)++;
-
- /* This probably just means we're processing a file compiled
- with g++ version 1. */
- else
- complain(&const_vol_complaint, **pp);
+ switch (**pp)
+ {
+ case 'A': /* Normal functions. */
+ new_sublist->fn_field.is_const = 0;
+ new_sublist->fn_field.is_volatile = 0;
+ (*pp)++;
+ break;
+ case 'B': /* `const' member functions. */
+ new_sublist->fn_field.is_const = 1;
+ new_sublist->fn_field.is_volatile = 0;
+ (*pp)++;
+ break;
+ case 'C': /* `volatile' member function. */
+ new_sublist->fn_field.is_const = 0;
+ new_sublist->fn_field.is_volatile = 1;
+ (*pp)++;
+ break;
+ case 'D': /* `const volatile' member function. */
+ new_sublist->fn_field.is_const = 1;
+ new_sublist->fn_field.is_volatile = 1;
+ (*pp)++;
+ break;
+ default:
+ /* This probably just means we're processing a file compiled
+ with g++ version 1. */
+ complain(&const_vol_complaint, **pp);
+ }
switch (*(*pp)++)
{
the sign bit out, and usable as a valid index into
the array. Remove the sign bit here. */
new_sublist->fn_field.voffset =
- (0x7fffffff & read_number (pp, ';')) + 1;
+ (0x7fffffff & read_number (pp, ';')) + 2;
if (**pp == '\\') *pp = next_symbol_text ();
new_sublist->next = sublist;
sublist = new_sublist;
length++;
+ if (**pp == '\\') *pp = next_symbol_text ();
}
while (**pp != ';' && **pp != '\0');
extern char *getenv ();
extern char *cplus_demangle ();
+extern char *cplus_mangle_opname ();
extern struct value *value_of_this ();
extern void break_command ();
extern void select_source_symtab ();
/* Demangle a GDB method stub type. */
char *
-gdb_mangle_typename (type)
+gdb_mangle_name (type, i, j)
struct type *type;
+ int i, j;
{
- static struct type *last_type;
- static char *mangled_typename;
+ int mangled_name_len;
+ char *mangled_name;
+ struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
+ struct fn_field *method = &f[j];
+ char *field_name = TYPE_FN_FIELDLIST_NAME (type, i);
- if (type != last_type)
+ /* Need a new type prefix. */
+ char *strchr ();
+ char *const_prefix = method->is_const ? "C" : "";
+ char *volatile_prefix = method->is_volatile ? "V" : "";
+ char *newname = type_name_no_tag (type);
+ char buf[20];
+ int len = strlen (newname);
+
+ sprintf (buf, "__%s%s%d", const_prefix, volatile_prefix, len);
+ mangled_name_len = (strlen (field_name)
+ + strlen (buf) + len
+ + strlen (TYPE_FN_FIELD_PHYSNAME (f, j))
+ + 1);
+
+ if (OPNAME_PREFIX_P (field_name))
+ {
+ char *opname = cplus_mangle_opname (field_name + 3);
+ if (opname == NULL)
+ error ("No mangling for \"%s\"", field_name);
+ mangled_name_len += strlen (opname);
+ mangled_name = (char *)xmalloc (mangled_name_len);
+
+ strncpy (mangled_name, field_name, 3);
+ mangled_name[3] = '\0';
+ strcat (mangled_name, opname);
+ }
+ else
{
- /* Need a new type prefix. */
- char *strchr ();
- char *newname = type_name_no_tag (type);
- char buf[20];
- int len;
-
- if (mangled_typename)
- free (mangled_typename);
-
- len = strlen (newname);
- sprintf (buf, "__%d", len);
- mangled_typename = (char *)xmalloc (strlen (buf) + len + 1);
- strcpy (mangled_typename, buf);
- strcat (mangled_typename, newname);
- /* Now we have built "__#newname". */
+ mangled_name = (char *)xmalloc (mangled_name_len);
+ strcpy (mangled_name, TYPE_FN_FIELDLIST_NAME (type, i));
}
- return mangled_typename;
+ strcat (mangled_name, buf);
+ strcat (mangled_name, newname);
+ strcat (mangled_name, TYPE_FN_FIELD_PHYSNAME (f, j));
+
+ return mangled_name;
}
/* Lookup a primitive type named NAME.
/* For virtual functions. */
/* First baseclass that defines this virtual function. */
struct type *fcontext;
+ unsigned int is_const : 1;
+ unsigned int is_volatile : 1;
/* Index into that baseclass's virtual function table,
- minus 1; else if static: VOFFSET_STATIC; else: 0. */
- int voffset;
-# define VOFFSET_STATIC (-1)
+ minus 2; else if static: VOFFSET_STATIC; else: 0. */
+ unsigned long voffset : 30;
+# define VOFFSET_STATIC 1
} *fn_fields;
B_TYPE *private_fn_field_bits;
#define TYPE_FN_FIELD_TYPE(thistype, n) (thistype)[n].type
#define TYPE_FN_FIELD_ARGS(thistype, n) TYPE_ARG_TYPES ((thistype)[n].type)
#define TYPE_FN_FIELD_PHYSNAME(thistype, n) (thistype)[n].physname
-#define TYPE_FN_FIELD_VIRTUAL_P(thistype, n) ((thistype)[n].voffset > 0)
+#define TYPE_FN_FIELD_VIRTUAL_P(thistype, n) ((thistype)[n].voffset > 1)
#define TYPE_FN_FIELD_STATIC_P(thistype, n) ((thistype)[n].voffset == VOFFSET_STATIC)
-#define TYPE_FN_FIELD_VOFFSET(thistype, n) ((thistype)[n].voffset-1)
+#define TYPE_FN_FIELD_VOFFSET(thistype, n) ((thistype)[n].voffset-2)
#define TYPE_FN_FIELD_FCONTEXT(thistype, n) ((thistype)[n].fcontext)
#define TYPE_FN_PRIVATE_BITS(thistype) (thistype).private_fn_field_bits
{
char *typename = TYPE_NAME(type);
static const char vtbl_ptr_name[] =
- { CPLUS_MARKER,'v','t','b','l','_','p','t','r','_','t','y','p','e' };
+ { CPLUS_MARKER,'v','t','b','l','_','p','t','r','_','t','y','p','e', 0 };
return (typename != NULL && !strcmp(typename, vtbl_ptr_name));
}
if (TYPE_FLAGS (TYPE_FN_FIELD_TYPE (f, j)) & TYPE_FLAG_STUB)
{
/* Build something we can demangle. */
- char *strchr (), *gdb_mangle_typename ();
- char *inner_name = gdb_mangle_typename (type);
- char *mangled_name
- = (char *)xmalloc (strlen (TYPE_FN_FIELDLIST_NAME (type, i))
- + strlen (inner_name)
- + strlen (TYPE_FN_FIELD_PHYSNAME (f, j))
- + 1);
- char *demangled_name, *cplus_demangle ();
- strcpy (mangled_name, TYPE_FN_FIELDLIST_NAME (type, i));
- strcat (mangled_name, inner_name);
- strcat (mangled_name, TYPE_FN_FIELD_PHYSNAME (f, j));
- demangled_name = cplus_demangle (mangled_name, 1);
+ char *strchr (), *gdb_mangle_name (), *cplus_demangle ();
+ char *mangled_name = gdb_mangle_name (type, i, j);
+ char *demangled_name = cplus_demangle (mangled_name, 1);
if (demangled_name == 0)
fprintf_filtered (stream, " <badly mangled name %s>",
mangled_name);
#include "gdbcmd.h"
extern char *cplus_demangle ();
-extern char *cplus_mangle_opname ();
/* The value-history records all the values printed
by print commands during this session. Each chunk
struct symbol *sym;
CORE_ADDR pc_for_sym;
char *demangled_name;
-
btype = TYPE_VPTR_BASETYPE (dtype);
check_stub_type (btype);
if (btype != dtype)
/* Check that VTBL looks like it points to a virtual function table. */
i = find_pc_misc_function (VALUE_ADDRESS (vtbl));
- if (i < 0 || ! VTBL_PREFIX_P (misc_function_vector[i].name))
+ if (i < 0 || ! VTBL_PREFIX_P (demangled_name = misc_function_vector[i].name))
{
/* If we expected to find a vtable, but did not, let the user
know that we aren't happy, but don't throw an error.
entry = value_subscript (vtbl, value_from_longest (builtin_type_int,
(LONGEST) i));
offset = longest_to_int (value_as_long (value_field (entry, 0)));
- if (offset < best_offset)
+ /* If we use '<=' we can handle single inheritance
+ * where all offsets are zero - just use the first entry found. */
+ if (offset <= best_offset)
{
best_offset = offset;
best_entry = entry;
}
}
- if (best_entry == 0)
- return arg;
-
/* Move the pointer according to BEST_ENTRY's offset, and figure
out what type we should return as the new pointer. */
- pc_for_sym = value_as_pointer (value_field (best_entry, 2));
- sym = find_pc_function (pc_for_sym);
- demangled_name = cplus_demangle (SYMBOL_NAME (sym), -1);
- *(strchr (demangled_name, ':')) = '\0';
+ if (best_entry == 0)
+ {
+ /* An alternative method (which should no longer be necessary).
+ * But we leave it in for future use, when we will hopefully
+ * have optimizes the vtable to use thunks instead of offsets. */
+ /* Use the name of vtable itself to extract a base type. */
+ demangled_name += 4; /* Skip _vt$ prefix. */
+ }
+ else
+ {
+ pc_for_sym = value_as_pointer (value_field (best_entry, 2));
+ sym = find_pc_function (pc_for_sym);
+ demangled_name = cplus_demangle (SYMBOL_NAME (sym), -1);
+ *(strchr (demangled_name, ':')) = '\0';
+ }
sym = lookup_symbol (demangled_name, 0, VAR_NAMESPACE, 0, 0);
if (sym == 0)
error ("could not find type declaration for `%s'", SYMBOL_NAME (sym));
- free (demangled_name);
- arg = value_add (value_cast (builtin_type_int, arg),
- value_field (best_entry, 0));
+ if (best_entry)
+ {
+ free (demangled_name);
+ arg = value_add (value_cast (builtin_type_int, arg),
+ value_field (best_entry, 0));
+ }
VALUE_TYPE (arg) = lookup_pointer_type (SYMBOL_TYPE (sym));
return arg;
}
struct type *type;
int i, j;
{
- extern char *gdb_mangle_typename (), *strchr ();
+ extern char *gdb_mangle_name (), *strchr ();
struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
- char *field_name = TYPE_FN_FIELDLIST_NAME (type, i);
- char *inner_name = gdb_mangle_typename (type);
- int mangled_name_len = (strlen (field_name)
- + strlen (inner_name)
- + strlen (TYPE_FN_FIELD_PHYSNAME (f, j))
- + 1);
- char *mangled_name;
- char *demangled_name;
+ char *mangled_name = gdb_mangle_name (type, i, j);
+ char *demangled_name = cplus_demangle (mangled_name, 0);
char *argtypetext, *p;
int depth = 0, argcount = 1;
struct type **argtypes;
- if (OPNAME_PREFIX_P (field_name))
- {
- char *opname = cplus_mangle_opname (field_name + 3);
- if (opname == NULL)
- error ("No mangling for \"%s\"", field_name);
- mangled_name_len += strlen (opname);
- mangled_name = (char *)xmalloc (mangled_name_len);
-
- strncpy (mangled_name, field_name, 3);
- mangled_name[3] = '\0';
- strcat (mangled_name, opname);
- }
- else
- {
- mangled_name = (char *)xmalloc (mangled_name_len);
- strcpy (mangled_name, TYPE_FN_FIELDLIST_NAME (type, i));
- }
- strcat (mangled_name, inner_name);
- strcat (mangled_name, TYPE_FN_FIELD_PHYSNAME (f, j));
- demangled_name = cplus_demangle (mangled_name, 0);
-
/* Now, read in the parameters that define this type. */
argtypetext = strchr (demangled_name, '(') + 1;
p = argtypetext;