diff options
Diffstat (limited to 'gdb/c-valprint.c')
-rw-r--r-- | gdb/c-valprint.c | 83 |
1 files changed, 58 insertions, 25 deletions
diff --git a/gdb/c-valprint.c b/gdb/c-valprint.c index 0b616f7..cfdf2c0 100644 --- a/gdb/c-valprint.c +++ b/gdb/c-valprint.c @@ -55,6 +55,18 @@ print_function_pointer_address (CORE_ADDR address, struct ui_file *stream, } +/* A helper for textual_element_type. This checks the name of the + typedef. This is bogus but it isn't apparent that the compiler + provides us the help we may need. */ + +static int +textual_name (const char *name) +{ + return (!strcmp (name, "wchar_t") + || !strcmp (name, "char16_t") + || !strcmp (name, "char32_t")); +} + /* Apply a heuristic to decide whether an array of TYPE or a pointer to TYPE should be printed as a textual string. Return non-zero if it should, or zero if it should be treated as an array of integers @@ -77,6 +89,15 @@ textual_element_type (struct type *type, char format) /* TYPE_CODE_CHAR is always textual. */ if (TYPE_CODE (true_type) == TYPE_CODE_CHAR) return 1; + /* Any other character-like types must be integral. */ + if (TYPE_CODE (true_type) != TYPE_CODE_INT) + return 0; + + /* Check the names of the type and the typedef. */ + if (TYPE_NAME (type) && textual_name (TYPE_NAME (type))) + return 1; + if (TYPE_NAME (true_type) && textual_name (TYPE_NAME (true_type))) + return 1; if (format == 's') { @@ -115,7 +136,8 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, { unsigned int i = 0; /* Number of characters printed */ unsigned len; - struct type *elttype; + struct type *elttype, *unresolved_elttype; + struct type *unresolved_type = type; unsigned eltlen; LONGEST val; CORE_ADDR addr; @@ -124,8 +146,9 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, switch (TYPE_CODE (type)) { case TYPE_CODE_ARRAY: - elttype = check_typedef (TYPE_TARGET_TYPE (type)); - if (TYPE_LENGTH (type) > 0 && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0) + unresolved_elttype = TYPE_TARGET_TYPE (type); + elttype = check_typedef (unresolved_elttype); + if (TYPE_LENGTH (type) > 0 && TYPE_LENGTH (unresolved_elttype) > 0) { eltlen = TYPE_LENGTH (elttype); len = TYPE_LENGTH (type) / eltlen; @@ -135,7 +158,7 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, } /* Print arrays of textual chars with a string syntax. */ - if (textual_element_type (elttype, options->format)) + if (textual_element_type (unresolved_elttype, options->format)) { /* If requested, look for the first null char and only print elements up to it. */ @@ -143,15 +166,19 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, { unsigned int temp_len; - /* Look for a NULL char. */ for (temp_len = 0; - (valaddr + embedded_offset)[temp_len] - && temp_len < len && temp_len < options->print_max; - temp_len++); + (temp_len < len + && temp_len < options->print_max + && extract_unsigned_integer (valaddr + embedded_offset + + temp_len * eltlen, + eltlen) == 0); + ++temp_len) + ; len = temp_len; } - LA_PRINT_STRING (stream, valaddr + embedded_offset, len, eltlen, 0, options); + LA_PRINT_STRING (stream, unresolved_elttype, + valaddr + embedded_offset, len, 0, options); i = len; } else @@ -209,7 +236,8 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, print_function_pointer_address (addr, stream, options->addressprint); break; } - elttype = check_typedef (TYPE_TARGET_TYPE (type)); + unresolved_elttype = TYPE_TARGET_TYPE (type); + elttype = check_typedef (unresolved_elttype); { addr = unpack_pointer (type, valaddr + embedded_offset); print_unpacked_pointer: @@ -228,12 +256,11 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, /* For a pointer to a textual type, also print the string pointed to, unless pointer is null. */ - /* FIXME: need to handle wchar_t here... */ - if (textual_element_type (elttype, options->format) + if (textual_element_type (unresolved_elttype, options->format) && addr != 0) { - i = val_print_string (addr, -1, TYPE_LENGTH (elttype), stream, + i = val_print_string (unresolved_elttype, addr, -1, stream, options); } else if (cp_is_vtbl_member (type)) @@ -268,7 +295,7 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, } else { - wtype = TYPE_TARGET_TYPE (type); + wtype = unresolved_elttype; } vt_val = value_at (wtype, vt_address); common_val_print (vt_val, stream, recurse + 1, options, @@ -442,11 +469,11 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, Since we don't know whether the value is really intended to be used as an integer or a character, print the character equivalent as well. */ - if (textual_element_type (type, options->format)) + if (textual_element_type (unresolved_type, options->format)) { fputs_filtered (" ", stream); LA_PRINT_CHAR ((unsigned char) unpack_long (type, valaddr + embedded_offset), - stream); + unresolved_type, stream); } } break; @@ -468,7 +495,7 @@ c_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, else fprintf_filtered (stream, "%d", (int) val); fputs_filtered (" ", stream); - LA_PRINT_CHAR ((unsigned char) val, stream); + LA_PRINT_CHAR ((unsigned char) val, unresolved_type, stream); } break; @@ -540,7 +567,7 @@ int c_value_print (struct value *val, struct ui_file *stream, const struct value_print_options *options) { - struct type *type, *real_type; + struct type *type, *real_type, *val_type; int full, top, using_enc; struct value_print_options opts = *options; @@ -553,7 +580,11 @@ c_value_print (struct value *val, struct ui_file *stream, C++: if it is a member pointer, we will take care of that when we print it. */ - type = check_typedef (value_type (val)); + /* Preserve the original type before stripping typedefs. We prefer + to pass down the original type when possible, but for local + checks it is better to look past the typedefs. */ + val_type = value_type (val); + type = check_typedef (val_type); if (TYPE_CODE (type) == TYPE_CODE_PTR || TYPE_CODE (type) == TYPE_CODE_REF) @@ -561,11 +592,12 @@ c_value_print (struct value *val, struct ui_file *stream, /* Hack: remove (char *) for char strings. Their type is indicated by the quoted string anyway. (Don't use textual_element_type here; quoted strings - are always exactly (char *). */ - if (TYPE_CODE (type) == TYPE_CODE_PTR - && TYPE_NAME (type) == NULL - && TYPE_NAME (TYPE_TARGET_TYPE (type)) != NULL - && strcmp (TYPE_NAME (TYPE_TARGET_TYPE (type)), "char") == 0) + are always exactly (char *), (wchar_t *), or the like. */ + if (TYPE_CODE (val_type) == TYPE_CODE_PTR + && TYPE_NAME (val_type) == NULL + && TYPE_NAME (TYPE_TARGET_TYPE (val_type)) != NULL + && (strcmp (TYPE_NAME (TYPE_TARGET_TYPE (val_type)), "char") == 0 + || textual_name (TYPE_NAME (TYPE_TARGET_TYPE (val_type))))) { /* Print nothing */ } @@ -608,6 +640,7 @@ c_value_print (struct value *val, struct ui_file *stream, } type_print (type, "", stream, -1); fprintf_filtered (stream, ") "); + val_type = type; } else { @@ -653,7 +686,7 @@ c_value_print (struct value *val, struct ui_file *stream, /* Otherwise, we end up at the return outside this "if" */ } - return val_print (type, value_contents_all (val), + return val_print (val_type, value_contents_all (val), value_embedded_offset (val), VALUE_ADDRESS (val) + value_offset (val), stream, 0, &opts, current_language); |