aboutsummaryrefslogtreecommitdiff
path: root/gdb/c-valprint.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/c-valprint.c')
-rw-r--r--gdb/c-valprint.c83
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);