X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fc-typeprint.c;h=c9a644229bb5defa4ee0eddcf0b03ba206359a44;hb=fb603883409b7c56d89b9a8a7a344d18f861bbc5;hp=566e68f1327919250c4a1eb98e4226c403f77cd9;hpb=b8c9b27d1e133d46199734ca1f047af8bb2d3314;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/c-typeprint.c b/gdb/c-typeprint.c index 566e68f132..c9a644229b 100644 --- a/gdb/c-typeprint.c +++ b/gdb/c-typeprint.c @@ -1,5 +1,6 @@ /* Support for printing C and C++ types for GDB, the GNU debugger. - Copyright 1986, 1988, 1989, 1991, 1993-1996, 1998-2000 + Copyright 1986, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1998, + 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. This file is part of GDB. @@ -20,7 +21,7 @@ Boston, MA 02111-1307, USA. */ #include "defs.h" -#include "obstack.h" +#include "gdb_obstack.h" #include "bfd.h" /* Binary File Description */ #include "symtab.h" #include "gdbtypes.h" @@ -28,21 +29,16 @@ #include "value.h" #include "gdbcore.h" #include "target.h" -#include "command.h" -#include "gdbcmd.h" #include "language.h" #include "demangle.h" #include "c-lang.h" #include "typeprint.h" +#include "cp-abi.h" #include "gdb_string.h" #include -#include -/* Flag indicating target was compiled by HP compiler */ -extern int hp_som_som_object_present; - -static void cp_type_print_method_args (struct type ** args, char *prefix, +static void cp_type_print_method_args (struct type *mtype, char *prefix, char *varstring, int staticp, struct ui_file *stream); @@ -50,11 +46,12 @@ static void c_type_print_args (struct type *, struct ui_file *); static void cp_type_print_derivation_info (struct ui_file *, struct type *); -void c_type_print_varspec_prefix (struct type *, struct ui_file *, int, - int); +static void c_type_print_varspec_prefix (struct type *, struct ui_file *, int, + int, int); -static void c_type_print_cv_qualifier (struct type *, struct ui_file *, - int, int); +/* Print "const", "volatile", or address space modifiers. */ +static void c_type_print_modifier (struct type *, struct ui_file *, + int, int); @@ -65,8 +62,9 @@ void c_print_type (struct type *type, char *varstring, struct ui_file *stream, int show, int level) { - register enum type_code code; + enum type_code code; int demangled_args; + int need_post_space; if (show > 0) CHECK_TYPEDEF (type); @@ -85,7 +83,8 @@ c_print_type (struct type *type, char *varstring, struct ui_file *stream, || code == TYPE_CODE_MEMBER || code == TYPE_CODE_REF))) fputs_filtered (" ", stream); - c_type_print_varspec_prefix (type, stream, show, 0); + need_post_space = (varstring != NULL && strcmp (varstring, "") != 0); + c_type_print_varspec_prefix (type, stream, show, 0, need_post_space); if (varstring != NULL) { @@ -147,40 +146,40 @@ cp_type_print_derivation_info (struct ui_file *stream, struct type *type) fputs_filtered (" ", stream); } } + /* Print the C++ method arguments ARGS to the file STREAM. */ static void -cp_type_print_method_args (struct type **args, char *prefix, char *varstring, +cp_type_print_method_args (struct type *mtype, char *prefix, char *varstring, int staticp, struct ui_file *stream) { + struct field *args = TYPE_FIELDS (mtype); + int nargs = TYPE_NFIELDS (mtype); + int varargs = TYPE_VARARGS (mtype); int i; fprintf_symbol_filtered (stream, prefix, language_cplus, DMGL_ANSI); fprintf_symbol_filtered (stream, varstring, language_cplus, DMGL_ANSI); fputs_filtered ("(", stream); - if (args && args[!staticp] && args[!staticp]->code != TYPE_CODE_VOID) + + /* Skip the class variable. */ + i = staticp ? 0 : 1; + if (nargs > i) { - i = !staticp; /* skip the class variable */ - while (1) + while (i < nargs) { - type_print (args[i++], "", stream, 0); - if (!args[i]) - { - fprintf_filtered (stream, " ..."); - break; - } - else if (args[i]->code != TYPE_CODE_VOID) - { - fprintf_filtered (stream, ", "); - } - else - break; + type_print (args[i++].type, "", stream, 0); + + if (i == nargs && varargs) + fprintf_filtered (stream, ", ..."); + else if (i < nargs) + fprintf_filtered (stream, ", "); } } + else if (varargs) + fprintf_filtered (stream, "..."); else if (current_language->la_language == language_cplus) - { - fprintf_filtered (stream, "void"); - } + fprintf_filtered (stream, "void"); fprintf_filtered (stream, ")"); } @@ -192,11 +191,15 @@ cp_type_print_method_args (struct type **args, char *prefix, char *varstring, On outermost call, pass 0 for PASSED_A_PTR. On outermost call, SHOW > 0 means should ignore any typename for TYPE and show its details. - SHOW is always zero on recursive calls. */ + SHOW is always zero on recursive calls. + + NEED_POST_SPACE is non-zero when a space will be be needed + between a trailing qualifier and a field, variable, or function + name. */ void c_type_print_varspec_prefix (struct type *type, struct ui_file *stream, - int show, int passed_a_ptr) + int show, int passed_a_ptr, int need_post_space) { char *name; if (type == 0) @@ -210,15 +213,15 @@ c_type_print_varspec_prefix (struct type *type, struct ui_file *stream, switch (TYPE_CODE (type)) { case TYPE_CODE_PTR: - c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1); + c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, show, 1, 1); fprintf_filtered (stream, "*"); - c_type_print_cv_qualifier (type, stream, 1, 0); + c_type_print_modifier (type, stream, 1, need_post_space); break; case TYPE_CODE_MEMBER: if (passed_a_ptr) fprintf_filtered (stream, "("); - c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0); + c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, show, 0, 0); fprintf_filtered (stream, " "); name = type_name_no_tag (TYPE_DOMAIN_TYPE (type)); if (name) @@ -231,7 +234,7 @@ c_type_print_varspec_prefix (struct type *type, struct ui_file *stream, case TYPE_CODE_METHOD: if (passed_a_ptr) fprintf_filtered (stream, "("); - c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0); + c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, show, 0, 0); if (passed_a_ptr) { fprintf_filtered (stream, " "); @@ -241,23 +244,27 @@ c_type_print_varspec_prefix (struct type *type, struct ui_file *stream, break; case TYPE_CODE_REF: - c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 1); + c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, show, 1, 0); fprintf_filtered (stream, "&"); - c_type_print_cv_qualifier (type, stream, 1, 0); + c_type_print_modifier (type, stream, 1, need_post_space); break; case TYPE_CODE_FUNC: - c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0); + c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, show, 0, 0); if (passed_a_ptr) fprintf_filtered (stream, "("); break; case TYPE_CODE_ARRAY: - c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, 0, 0); + c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, show, 0, 0); if (passed_a_ptr) fprintf_filtered (stream, "("); break; + case TYPE_CODE_TYPEDEF: + c_type_print_varspec_prefix (TYPE_TARGET_TYPE (type), stream, show, 0, 0); + break; + case TYPE_CODE_UNDEF: case TYPE_CODE_STRUCT: case TYPE_CODE_UNION: @@ -273,8 +280,8 @@ c_type_print_varspec_prefix (struct type *type, struct ui_file *stream, case TYPE_CODE_STRING: case TYPE_CODE_BITSTRING: case TYPE_CODE_COMPLEX: - case TYPE_CODE_TYPEDEF: case TYPE_CODE_TEMPLATE: + case TYPE_CODE_NAMESPACE: /* These types need no prefix. They are listed here so that gcc -Wall will reveal any types that haven't been handled. */ break; @@ -290,28 +297,42 @@ c_type_print_varspec_prefix (struct type *type, struct ui_file *stream, NEED_SPACE = 1 indicates an initial white space is needed */ static void -c_type_print_cv_qualifier (struct type *type, struct ui_file *stream, - int need_pre_space, int need_post_space) +c_type_print_modifier (struct type *type, struct ui_file *stream, + int need_pre_space, int need_post_space) { - int flag = 0; - - if (TYPE_CONST (type)) + int did_print_modifier = 0; + const char *address_space_id; + + /* We don't print `const' qualifiers for references --- since all + operators affect the thing referenced, not the reference itself, + every reference is `const'. */ + if (TYPE_CONST (type) + && TYPE_CODE (type) != TYPE_CODE_REF) { if (need_pre_space) fprintf_filtered (stream, " "); fprintf_filtered (stream, "const"); - flag = 1; + did_print_modifier = 1; } if (TYPE_VOLATILE (type)) { - if (flag || need_pre_space) + if (did_print_modifier || need_pre_space) fprintf_filtered (stream, " "); fprintf_filtered (stream, "volatile"); - flag = 1; + did_print_modifier = 1; + } + + address_space_id = address_space_int_to_name (TYPE_INSTANCE_FLAGS (type)); + if (address_space_id) + { + if (did_print_modifier || need_pre_space) + fprintf_filtered (stream, " "); + fprintf_filtered (stream, "@%s", address_space_id); + did_print_modifier = 1; } - if (flag && need_post_space) + if (did_print_modifier && need_post_space) fprintf_filtered (stream, " "); } @@ -322,39 +343,31 @@ static void c_type_print_args (struct type *type, struct ui_file *stream) { int i; - struct type **args; + struct field *args; fprintf_filtered (stream, "("); - args = TYPE_ARG_TYPES (type); + args = TYPE_FIELDS (type); if (args != NULL) { - if (args[1] == NULL) - { - fprintf_filtered (stream, "..."); - } - else if ((args[1]->code == TYPE_CODE_VOID) && - (current_language->la_language == language_cplus)) - { - fprintf_filtered (stream, "void"); - } - else + int i; + + /* FIXME drow/2002-05-31: Always skips the first argument, + should we be checking for static members? */ + + for (i = 1; i < TYPE_NFIELDS (type); i++) { - for (i = 1; - args[i] != NULL && args[i]->code != TYPE_CODE_VOID; - i++) + c_print_type (args[i].type, "", stream, -1, 0); + if (i != TYPE_NFIELDS (type)) { - c_print_type (args[i], "", stream, -1, 0); - if (args[i + 1] == NULL) - { - fprintf_filtered (stream, "..."); - } - else if (args[i + 1]->code != TYPE_CODE_VOID) - { - fprintf_filtered (stream, ","); - wrap_here (" "); - } + fprintf_filtered (stream, ","); + wrap_here (" "); } } + if (TYPE_VARARGS (type)) + fprintf_filtered (stream, "..."); + else if (i == 1 + && (current_language->la_language == language_cplus)) + fprintf_filtered (stream, "void"); } else if (current_language->la_language == language_cplus) { @@ -388,12 +401,20 @@ is_type_conversion_operator (struct type *type, int i, int j) while (strchr (" \t\f\n\r", *name)) name++; - if (strncmp (name, "new", 3) == 0) + if (!('a' <= *name && *name <= 'z') + && !('A' <= *name && *name <= 'Z') + && *name != '_') + /* If this doesn't look like the start of an identifier, then it + isn't a type conversion operator. */ + return 0; + else if (strncmp (name, "new", 3) == 0) name += 3; else if (strncmp (name, "delete", 6) == 0) name += 6; else - return 0; + /* If it doesn't look like new or delete, it's a type conversion + operator. */ + return 1; /* Is that really the end of the name? */ if (('a' <= *name && *name <= 'z') @@ -523,19 +544,22 @@ c_type_print_varspec_suffix (struct type *type, struct ui_file *stream, / TYPE_LENGTH (TYPE_TARGET_TYPE (type)))); fprintf_filtered (stream, "]"); - c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0, 0); + c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, show, + 0, 0); break; case TYPE_CODE_MEMBER: if (passed_a_ptr) fprintf_filtered (stream, ")"); - c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0, 0); + c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, show, + 0, 0); break; case TYPE_CODE_METHOD: if (passed_a_ptr) fprintf_filtered (stream, ")"); - c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0, 0); + c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, show, + 0, 0); if (passed_a_ptr) { c_type_print_args (type, stream); @@ -544,7 +568,8 @@ c_type_print_varspec_suffix (struct type *type, struct ui_file *stream, case TYPE_CODE_PTR: case TYPE_CODE_REF: - c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 1, 0); + c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, show, + 1, 0); break; case TYPE_CODE_FUNC: @@ -554,7 +579,9 @@ c_type_print_varspec_suffix (struct type *type, struct ui_file *stream, { int i, len = TYPE_NFIELDS (type); fprintf_filtered (stream, "("); - if ((len == 0) && (current_language->la_language == language_cplus)) + if (len == 0 + && (TYPE_PROTOTYPED (type) + || current_language->la_language == language_cplus)) { fprintf_filtered (stream, "void"); } @@ -570,7 +597,12 @@ c_type_print_varspec_suffix (struct type *type, struct ui_file *stream, } fprintf_filtered (stream, ")"); } - c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, + c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, show, + passed_a_ptr, 0); + break; + + case TYPE_CODE_TYPEDEF: + c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, show, passed_a_ptr, 0); break; @@ -589,8 +621,8 @@ c_type_print_varspec_suffix (struct type *type, struct ui_file *stream, case TYPE_CODE_STRING: case TYPE_CODE_BITSTRING: case TYPE_CODE_COMPLEX: - case TYPE_CODE_TYPEDEF: case TYPE_CODE_TEMPLATE: + case TYPE_CODE_NAMESPACE: /* These types do not need a suffix. They are listed so that gcc -Wall will report types that may not have been considered. */ break; @@ -620,9 +652,9 @@ void c_type_print_base (struct type *type, struct ui_file *stream, int show, int level) { - register int i; - register int len; - register int lastval; + int i; + int len, real_len; + int lastval; char *mangled_name; char *demangled_name; char *demangled_no_static; @@ -652,7 +684,7 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, if (show <= 0 && TYPE_NAME (type) != NULL) { - c_type_print_cv_qualifier (type, stream, 0, 1); + c_type_print_modifier (type, stream, 0, 1); fputs_filtered (TYPE_NAME (type), stream); return; } @@ -672,7 +704,7 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, break; case TYPE_CODE_STRUCT: - c_type_print_cv_qualifier (type, stream, 0, 1); + c_type_print_modifier (type, stream, 0, 1); /* Note TYPE_CODE_STRUCT and TYPE_CODE_CLASS have the same value, * so we use another means for distinguishing them. */ @@ -705,7 +737,7 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, goto struct_union; case TYPE_CODE_UNION: - c_type_print_cv_qualifier (type, stream, 0, 1); + c_type_print_modifier (type, stream, 0, 1); fprintf_filtered (stream, "union "); struct_union: @@ -737,7 +769,7 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, fprintf_filtered (stream, "{\n"); if ((TYPE_NFIELDS (type) == 0) && (TYPE_NFN_FIELDS (type) == 0)) { - if (TYPE_FLAGS (type) & TYPE_FLAG_STUB) + if (TYPE_STUB (type)) fprintfi_filtered (level + 4, stream, "\n"); else fprintfi_filtered (level + 4, stream, "\n"); @@ -824,10 +856,11 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, QUIT; /* Don't print out virtual function table. */ /* HP ANSI C++ case */ - if (TYPE_HAS_VTABLE (type) && (STREQN (TYPE_FIELD_NAME (type, i), "__vfp", 5))) + if (TYPE_HAS_VTABLE (type) + && (strncmp (TYPE_FIELD_NAME (type, i), "__vfp", 5) == 0)) continue; /* Other compilers */ - if (STREQN (TYPE_FIELD_NAME (type, i), "_vptr", 5) + if (strncmp (TYPE_FIELD_NAME (type, i), "_vptr", 5) == 0 && is_cplus_marker ((TYPE_FIELD_NAME (type, i))[5])) continue; @@ -885,9 +918,21 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, fprintf_filtered (stream, ";\n"); } - /* If there are both fields and methods, put a space between. */ + /* If there are both fields and methods, put a blank line + between them. Make sure to count only method that we will + display; artificial methods will be hidden. */ len = TYPE_NFN_FIELDS (type); - if (len && section_type != s_none) + real_len = 0; + for (i = 0; i < len; i++) + { + struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i); + int len2 = TYPE_FN_FIELDLIST_LENGTH (type, i); + int j; + for (j = 0; j < len2; j++) + if (!TYPE_FN_FIELD_ARTIFICIAL (f, j)) + real_len++; + } + if (real_len > 0 && section_type != s_none) fprintf_filtered (stream, "\n"); /* C++: print out the methods */ @@ -897,16 +942,18 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, int j, len2 = TYPE_FN_FIELDLIST_LENGTH (type, i); char *method_name = TYPE_FN_FIELDLIST_NAME (type, i); char *name = type_name_no_tag (type); - int is_constructor = name && STREQ (method_name, name); + int is_constructor = name && strcmp (method_name, name) == 0; for (j = 0; j < len2; j++) { char *physname = TYPE_FN_FIELD_PHYSNAME (f, j); int is_full_physname_constructor = - ((physname[0] == '_' && physname[1] == '_' - && strchr ("0123456789Qt", physname[2])) - || STREQN (physname, "__ct__", 6) - || DESTRUCTOR_PREFIX_P (physname) - || STREQN (physname, "__dt__", 6)); + is_constructor_name (physname) + || is_destructor_name (physname) + || method_name[0] == '~'; + + /* Do not print out artificial methods. */ + if (TYPE_FN_FIELD_ARTIFICIAL (f, j)) + continue; QUIT; if (TYPE_FN_FIELD_PROTECTED (f, j)) @@ -972,10 +1019,15 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, Let's try to reconstruct the function signature from the symbol information */ if (!TYPE_FN_FIELD_STUB (f, j)) - cp_type_print_method_args (TYPE_FN_FIELD_ARGS (f, j), "", - method_name, - TYPE_FN_FIELD_STATIC_P (f, j), - stream); + { + int staticp = TYPE_FN_FIELD_STATIC_P (f, j); + struct type *mtype = TYPE_FN_FIELD_TYPE (f, j); + cp_type_print_method_args (mtype, + "", + method_name, + staticp, + stream); + } else fprintf_filtered (stream, "", mangled_name); @@ -1021,9 +1073,9 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, break; case TYPE_CODE_ENUM: - c_type_print_cv_qualifier (type, stream, 0, 1); + c_type_print_modifier (type, stream, 0, 1); /* HP C supports sized enums */ - if (hp_som_som_object_present) + if (deprecated_hp_som_som_object_present) switch (TYPE_LENGTH (type)) { case 1: @@ -1102,7 +1154,7 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, template class " and then merges with the struct/union/class code to print the rest of the definition. */ - c_type_print_cv_qualifier (type, stream, 0, 1); + c_type_print_modifier (type, stream, 0, 1); fprintf_filtered (stream, "template <"); for (i = 0; i < TYPE_NTEMPLATE_ARGS (type); i++) { @@ -1130,6 +1182,11 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, } break; + case TYPE_CODE_NAMESPACE: + fputs_filtered ("namespace ", stream); + fputs_filtered (TYPE_TAG_NAME (type), stream); + break; + default: /* Handle types not explicitly handled by the other cases, such as fundamental types. For these, just print whatever @@ -1137,7 +1194,7 @@ c_type_print_base (struct type *type, struct ui_file *stream, int show, is no type name, then complain. */ if (TYPE_NAME (type) != NULL) { - c_type_print_cv_qualifier (type, stream, 0, 1); + c_type_print_modifier (type, stream, 0, 1); fputs_filtered (TYPE_NAME (type), stream); } else