diff --git a/gdb/ChangeLog b/gdb/ChangeLog index ac98789094..177d7a134c 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,12 @@ +Wed Mar 18 15:51:15 1992 Per Bothner (bothner@cygnus.com) + + Some improvements to g++ debugging. + * symtab.c (list_symbols): demangle before pattern matching. + * symtab.c: Other fixes to improve handing of operators. + * valprint.c (type_print_base): Fix test for constructor. + * values.c (value_static_field): Allow evaluation of + CLASS::METHOD, returning a function pointer. + Wed Mar 18 08:39:52 1992 Fred Fish (fnf@cygnus.com) * Makefile.in (VERSION): Roll 4.4.6. diff --git a/gdb/symtab.c b/gdb/symtab.c index 55f3899d95..9814774b11 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -37,10 +37,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include +#include /* Prototypes for local functions */ -static int +extern int find_methods PARAMS ((struct type *, char *, char **, struct symbol **)); static void @@ -1260,14 +1261,24 @@ operator_chars (p, end) /* Don't get faked out by `operator' being part of a longer identifier. */ - if ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') - || *p == '_' || *p == '$' || *p == '\0') + if (isalpha(*p) || *p == '_' || *p == '$' || *p == '\0') return *end; /* Allow some whitespace between `operator' and the operator symbol. */ while (*p == ' ' || *p == '\t') p++; + /* Recognize 'operator TYPENAME'. */ + + if (isalpha(*p) || *p == '_' || *p == '$') + { + register char *q = p+1; + while (isalnum(*q) || *q == '_' || *q == '$') + q++; + *end = q; + return p; + } + switch (*p) { case '!': @@ -1328,7 +1339,7 @@ operator_chars (p, end) * physnames = (char **) alloca (TYPE_NFN_FIELDS_TOTAL (t) * sizeof(char*)); */ -static int +int find_methods (t, name, physnames, sym_arr) struct type *t; char *name; @@ -1392,6 +1403,12 @@ find_methods (t, name, physnames, sym_arr) (int *) NULL, (struct symtab **) NULL); if (sym_arr[i1]) i1++; + else + { + fputs_filtered("(Cannot find method ", stdout); + fputs_demangled(phys_name, stdout, 0); + fputs_filtered(" - possibly inlined.)\n", stdout); + } } } } @@ -1525,18 +1542,22 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line) while (*p && *p != ' ' && *p != '\t' && *p != ',' && *p !=':') p++; q = operator_chars (*argptr, &q1); - copy = (char *) alloca (p - *argptr + 1 + (q1 - q)); if (q1 - q) { - copy[0] = 'o'; - copy[1] = 'p'; - copy[2] = CPLUS_MARKER; - bcopy (q, copy + 3, q1 - q); - copy[3 + (q1 - q)] = '\0'; + char *opname; + char *tmp = alloca (q1 - q + 1); + memcpy (tmp, q, q1 - q); + tmp[q1 - q] = '\0'; + opname = cplus_mangle_opname (tmp, 1); + if (opname == NULL) + error ("No mangling for \"%s\"", tmp); + copy = (char*) alloca (3 + strlen(opname)); + sprintf (copy, "__%s", opname); p = q1; } else { + copy = (char *) alloca (p - *argptr + 1 + (q1 - q)); bcopy (*argptr, copy, p - *argptr); copy[p - *argptr] = '\0'; } @@ -1709,6 +1730,7 @@ decode_line_1 (argptr, funfirstline, default_symtab, default_line) /* Arg token is not digits => try it as a variable name Find the next token (everything up to end or next whitespace). */ + p = *argptr; while (*p && *p != ' ' && *p != '\t' && *p != ',') p++; copy = (char *) alloca (p - *argptr + 1); @@ -2027,6 +2049,21 @@ sources_info () printf_filtered ("\n"); } +static int +name_match(name) + char *name; +{ + char *demangled = cplus_demangle(name, -1); + if (demangled != NULL) + { + int cond = re_exec (demangled); + free (demangled); + return cond; + } + return re_exec(name); +} +#define NAME_MATCH(NAME) name_match(NAME) + /* List all symbols (if REGEXP is 0) or all symbols matching REGEXP. If CLASS is zero, list all symbols except functions and type names. If CLASS is 1, list only functions. @@ -2052,7 +2089,8 @@ list_symbols (regexp, class, bpt) struct partial_symbol *psym; struct objfile *objfile; struct minimal_symbol *msymbol; - char *val; + char *val, *q2; +/* char *mangled;*/ static char *classnames[] = {"variable", "function", "type", "method"}; int found_in_file = 0; @@ -2064,9 +2102,42 @@ list_symbols (regexp, class, bpt) enum minimal_symbol_type ourtype = types[class]; enum minimal_symbol_type ourtype2 = types2[class]; + if (regexp) - if (0 != (val = re_comp (regexp))) - error ("Invalid regexp (%s): %s", val, regexp); + { + /* Make sure spacing is right for C++ operators. + This is just a courtesy to make the matching less sensitive + to how many spaces the user leaves between 'operator' + and or . */ + char *opend; + char *opname = operator_chars (regexp, &opend); + if (*opname) + { + int fix = -1; /* -1 means ok; otherwise number of spaces needed. */ + if (isalpha(*opname) || *opname == '_' || *opname == '$') + { + /* There should 1 space between 'operator' and 'TYPENAME'. */ + if (opname[-1] != ' ' || opname[-2] == ' ') + fix = 1; + } + else + { + /* There should 0 spaces between 'operator' and 'OPERATOR'. */ + if (opname[-1] == ' ') + fix = 0; + } + /* If wrong number of spaces, fix it. */ + if (fix >= 0) + { + char *tmp = (char*) alloca(opend-opname+10); + sprintf(tmp, "operator%.*s%s", fix, " ", opname); + regexp = tmp; + } + } + + if (0 != (val = re_comp (regexp))) + error ("Invalid regexp (%s): %s", val, regexp); + } /* Search through the partial symtabs *first* for all symbols matching the regexp. That way we don't have to reproduce all of @@ -2104,10 +2175,10 @@ list_symbols (regexp, class, bpt) else { QUIT; - + /* If it would match (logic taken from loop below) load the file and go on to the next one */ - if ((regexp == 0 || re_exec (SYMBOL_NAME (psym))) + if ((regexp == 0 || NAME_MATCH (SYMBOL_NAME (psym))) && ((class == 0 && SYMBOL_CLASS (psym) != LOC_TYPEDEF && SYMBOL_CLASS (psym) != LOC_BLOCK) || (class == 1 && SYMBOL_CLASS (psym) == LOC_BLOCK) @@ -2138,7 +2209,7 @@ list_symbols (regexp, class, bpt) { if (msymbol -> type == ourtype || msymbol -> type == ourtype2) { - if (regexp == 0 || re_exec (msymbol -> name)) + if (regexp == 0 || NAME_MATCH (msymbol -> name)) { if (0 == find_pc_symtab (msymbol -> address)) { @@ -2181,7 +2252,7 @@ list_symbols (regexp, class, bpt) { QUIT; sym = BLOCK_SYM (b, j); - if ((regexp == 0 || re_exec (SYMBOL_NAME (sym))) + if ((regexp == 0 || NAME_MATCH (SYMBOL_NAME (sym))) && ((class == 0 && SYMBOL_CLASS (sym) != LOC_TYPEDEF && SYMBOL_CLASS (sym) != LOC_BLOCK) || (class == 1 && SYMBOL_CLASS (sym) == LOC_BLOCK) @@ -2251,7 +2322,7 @@ list_symbols (regexp, class, bpt) { if (msymbol -> type == ourtype || msymbol -> type == ourtype2) { - if (regexp == 0 || re_exec (msymbol -> name)) + if (regexp == 0 || NAME_MATCH (msymbol -> name)) { /* Functions: Look up by address. */ if (class != 1 && diff --git a/gdb/valprint.c b/gdb/valprint.c index b031e16e9c..8b8c40523b 100644 --- a/gdb/valprint.c +++ b/gdb/valprint.c @@ -17,10 +17,10 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include -#include #include "defs.h" +#include #include "symtab.h" +#include "gdbtypes.h" #include "value.h" #include "gdbcore.h" #include "gdbcmd.h" @@ -29,11 +29,59 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "language.h" #include + +/* Prototypes for local functions */ + +static void +print_string PARAMS ((FILE *, char *, unsigned int, int)); + +static void +show_print PARAMS ((char *, int)); + +static void +set_print PARAMS ((char *, int)); + +static void +set_radix PARAMS ((char *, int, struct cmd_list_element *)); + +static void +set_output_radix PARAMS ((char *, int, struct cmd_list_element *)); + +static void +type_print_base PARAMS ((struct type *, FILE *, int, int)); + +static void +type_print_varspec_suffix PARAMS ((struct type *, FILE *, int, int)); + +static void +type_print_varspec_prefix PARAMS ((struct type *, FILE *, int, int)); + +static void +type_print_derivation_info PARAMS ((FILE *, struct type *)); + +static void +type_print_method_args PARAMS ((struct type **, char *, char *, int, FILE *)); + +static void +cplus_val_print PARAMS ((struct type *, char *, FILE *, int, int, + enum val_prettyprint, struct type **)); + +static void +val_print_fields PARAMS ((struct type *, char *, FILE *, int, int, + enum val_prettyprint, struct type **)); + +static int +is_vtbl_member PARAMS ((struct type *)); + +static int +is_vtbl_ptr_type PARAMS ((struct type *)); + +static void +print_hex_chars PARAMS ((FILE *, unsigned char *, unsigned)); + extern int sys_nerr; extern char *sys_errlist[]; -extern void print_scalar_formatted(); /* printcmd.c */ -extern void print_address_demangle(); /* printcmd.c */ extern int demangle; /* whether to print C++ syms raw or source-form */ /* Maximum number of chars to print for a string pointer value @@ -41,11 +89,6 @@ extern int demangle; /* whether to print C++ syms raw or source-form */ static unsigned int print_max; -static void type_print_varspec_suffix (); -static void type_print_varspec_prefix (); -static void type_print_base (); -static void type_print_method_args (); - /* Default input and output radixes, and output format letter. */ unsigned input_radix = 10; @@ -74,14 +117,13 @@ int objectprint; /* Controls looking up an object's derived type struct obstack dont_print_obstack; -static void cplus_val_print (); /* Print the character string STRING, printing at most LENGTH characters. Printing stops early if the number hits print_max; repeat counts are printed as appropriate. Print ellipses at the end if we had to stop before printing LENGTH characters, or if FORCE_ELLIPSES. */ -void +static void print_string (stream, string, length, force_ellipses) FILE *stream; char *string; @@ -286,7 +328,7 @@ int value_print (val, stream, format, pretty) value val; FILE *stream; - char format; + int format; enum val_prettyprint pretty; { register unsigned int i, n, typelen; @@ -439,12 +481,13 @@ is_vtbl_member(type) DONT_PRINT is an array of baseclass types that we should not print, or zero if called from top level. */ + static void val_print_fields (type, valaddr, stream, format, recurse, pretty, dont_print) struct type *type; char *valaddr; FILE *stream; - char format; + int format; int recurse; enum val_prettyprint pretty; struct type **dont_print; @@ -547,7 +590,7 @@ cplus_val_print (type, valaddr, stream, format, recurse, pretty, dont_print) struct type *type; char *valaddr; FILE *stream; - char format; + int format; int recurse; enum val_prettyprint pretty; struct type **dont_print; @@ -634,13 +677,12 @@ cplus_val_print (type, valaddr, stream, format, recurse, pretty, dont_print) The PRETTY parameter controls prettyprinting. */ int -val_print (type, valaddr, address, stream, format, - deref_ref, recurse, pretty) +val_print (type, valaddr, address, stream, format, deref_ref, recurse, pretty) struct type *type; char *valaddr; CORE_ADDR address; FILE *stream; - char format; + int format; int deref_ref; int recurse; enum val_prettyprint pretty; @@ -927,10 +969,17 @@ val_print (type, valaddr, address, stream, format, slower if print_max is set high, e.g. if you set print_max to 1000, not only will it take a long time to fetch short strings, but if you are near - the end of the address space, it might not work. - FIXME. */ + the end of the address space, it might not work. */ QUIT; errcode = target_read_memory (addr, string, print_max); + if (errcode != 0) + { + /* Try reading just one character. If that succeeds, + assume we hit the end of the address space, but + the initial part of the string is probably safe. */ + char x[1]; + errcode = target_read_memory (addr, x, 1); + } if (errcode != 0) force_ellipses = 0; else @@ -974,13 +1023,12 @@ val_print (type, valaddr, address, stream, format, { CORE_ADDR vt_address = unpack_pointer (type, valaddr); - int vt_index = find_pc_misc_function (vt_address); - if (vt_index >= 0 - && vt_address == misc_function_vector[vt_index].address) + struct minimal_symbol *msymbol = + lookup_minimal_symbol_by_pc (vt_address); + if ((msymbol != NULL) && (vt_address == msymbol -> address)) { fputs_filtered (" <", stream); - fputs_demangled (misc_function_vector[vt_index].name, - stream, 1); + fputs_demangled (msymbol -> name, stream, 1); fputs_filtered (">", stream); } if (vtblprint) @@ -1698,7 +1746,7 @@ type_print_base (type, stream, show, level) struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i); int j, len2 = TYPE_FN_FIELDLIST_LENGTH (type, i); char *method_name = TYPE_FN_FIELDLIST_NAME (type, i); - int is_constructor = strcmp(method_name, TYPE_NAME (type)) == 0; + int is_constructor = name && strcmp(method_name, name) == 0; for (j = 0; j < len2; j++) { QUIT; @@ -1723,7 +1771,6 @@ type_print_base (type, stream, show, level) if (TYPE_FN_FIELD_STUB (f, j)) { /* Build something we can demangle. */ - 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) @@ -2011,7 +2058,7 @@ _initialize_valprint () "Set default input and output number radix.", &setlist); add_show_from_set (c, &showlist); - c->function = set_radix; + c->function.sfunc = set_radix; /* Give people the defaults which they are used to. */ prettyprint = 0; diff --git a/gdb/values.c b/gdb/values.c index 34875ca0f2..bb5fa68c29 100644 --- a/gdb/values.c +++ b/gdb/values.c @@ -1124,6 +1124,8 @@ value_static_field (type, fieldname, fieldno) if (fieldno < 0) { + char **physnames; + struct symbol **sym_arr; /* Look for static field. */ int i; for (i = TYPE_NFIELDS (type) - 1; i >= TYPE_N_BASECLASSES (type); i--) @@ -1144,14 +1146,24 @@ value_static_field (type, fieldname, fieldno) return v; } - if (destructor_name_p (fieldname, type)) - error ("Cannot get value of destructor"); - - for (i = TYPE_NFN_FIELDS (type) - 1; i >= 0; i--) + sym_arr = (struct symbol **) + alloca(TYPE_NFN_FIELDS_TOTAL (type) * sizeof(struct symbol*)); + physnames = (char **) + alloca (TYPE_NFN_FIELDS_TOTAL (type) * sizeof(char*)); + /* Note: This does duplicate work, since find_methods does a + recursive search *and* so does value_static_field. FIXME */ + i = find_methods (type, fieldname, physnames, sym_arr); + if (i > 1) + error ("Cannot get value of overloaded method \"%s\"", fieldname); + else if (i) { - if (! strcmp (TYPE_FN_FIELDLIST_NAME (type, i), fieldname)) - error ("Cannot get value of method \"%s\"", fieldname); - } + struct symbol *sym = sym_arr[0]; + value val = read_var_value (sym, (FRAME) 0); + if (val == 0) + error ("Address of method \"%s\" is unknown (possibly inlined).", + fieldname); + return val; + } error("there is no field named %s", fieldname); } @@ -1161,8 +1173,7 @@ value_static_field (type, fieldname, fieldno) if (! sym) error ("Internal error: could not find physical static variable named %s", phys_name); type = TYPE_FIELD_TYPE (type, fieldno); - v = value_at (type, (CORE_ADDR)SYMBOL_BLOCK_VALUE (sym)); - return v; + return value_at (type, (CORE_ADDR)SYMBOL_BLOCK_VALUE (sym)); } /* Compute the address of the baseclass which is