diff --git a/gdb/ChangeLog b/gdb/ChangeLog index f43c406e3f..a66a918424 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,7 @@ +2020-03-13 Tom Tromey + + * c-valprint.c (c_value_print): Use common_val_print. + 2020-03-13 Tom Tromey * cp-valprint.c (cp_print_static_field): Use common_val_print. diff --git a/gdb/c-valprint.c b/gdb/c-valprint.c index 157ffd7ff7..759ab43c72 100644 --- a/gdb/c-valprint.c +++ b/gdb/c-valprint.c @@ -567,7 +567,7 @@ void c_value_print (struct value *val, struct ui_file *stream, const struct value_print_options *options) { - struct type *type, *real_type, *val_type; + struct type *type, *real_type; int full, using_enc; LONGEST top; struct value_print_options opts = *options; @@ -581,24 +581,22 @@ 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. */ - /* 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); + type = check_typedef (value_type (val)); if (TYPE_CODE (type) == TYPE_CODE_PTR || TYPE_IS_REFERENCE (type)) { + struct type *original_type = value_type (val); + /* Hack: remove (char *) for char strings. Their type is indicated by the quoted string anyway. (Don't use c_textual_element_type here; quoted strings 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)), + if (TYPE_CODE (original_type) == TYPE_CODE_PTR + && TYPE_NAME (original_type) == NULL + && TYPE_NAME (TYPE_TARGET_TYPE (original_type)) != NULL + && (strcmp (TYPE_NAME (TYPE_TARGET_TYPE (original_type)), "char") == 0 - || textual_name (TYPE_NAME (TYPE_TARGET_TYPE (val_type))))) + || textual_name (TYPE_NAME (TYPE_TARGET_TYPE (original_type))))) { /* Print nothing. */ } @@ -624,7 +622,6 @@ c_value_print (struct value *val, struct ui_file *stream, if (real_type) { /* RTTI entry found. */ - type = real_type; /* Need to adjust pointer value. */ val = value_from_pointer (real_type, @@ -637,14 +634,11 @@ c_value_print (struct value *val, struct ui_file *stream, } if (is_ref) - { - val = value_ref (value_ind (val), refcode); - type = value_type (val); - } + val = value_ref (value_ind (val), refcode); + type = value_type (val); type_print (type, "", stream, -1); fprintf_filtered (stream, ") "); - val_type = type; } else { @@ -667,36 +661,25 @@ c_value_print (struct value *val, struct ui_file *stream, /* We have RTTI information, so use it. */ val = value_full_object (val, real_type, full, top, using_enc); + /* In a destructor we might see a real type that is a + superclass of the object's type. In this case it is + better to leave the object as-is. */ + if (!(full + && (TYPE_LENGTH (real_type) + < TYPE_LENGTH (value_enclosing_type (val))))) + val = value_cast (real_type, val); fprintf_filtered (stream, "(%s%s) ", TYPE_NAME (real_type), full ? "" : _(" [incomplete object]")); - /* Print out object: enclosing type is same as real_type if - full. */ - val_print (value_enclosing_type (val), - 0, - value_address (val), stream, 0, - val, &opts, current_language); - return; - /* Note: When we look up RTTI entries, we don't get any - information on const or volatile attributes. */ } else if (type != check_typedef (value_enclosing_type (val))) { /* No RTTI information, so let's do our best. */ fprintf_filtered (stream, "(%s ?) ", TYPE_NAME (value_enclosing_type (val))); - val_print (value_enclosing_type (val), - 0, - value_address (val), stream, 0, - val, &opts, current_language); - return; + val = value_cast (value_enclosing_type (val), val); } - /* Otherwise, we end up at the return outside this "if". */ } - val_print (val_type, - value_embedded_offset (val), - value_address (val), - stream, 0, - val, &opts, current_language); + common_val_print (val, stream, 0, &opts, current_language); } diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 500aa51c34..ec22de89d5 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2020-03-13 Tom Tromey + + * gdb.base/printcmds.exp (test_print_strings): Add regression + test. + * gdb.base/printcmds.c (charptr): New typedef. + (teststring2): New global. + 2020-03-13 Andrew Burgess * gdb.base/break-interp.exp: Use the tail of the filename, not the diff --git a/gdb/testsuite/gdb.base/printcmds.c b/gdb/testsuite/gdb.base/printcmds.c index ed1e26b12a..04b766fc0c 100644 --- a/gdb/testsuite/gdb.base/printcmds.c +++ b/gdb/testsuite/gdb.base/printcmds.c @@ -72,6 +72,9 @@ int int4dim[1][2][3][2] = {{{{0,1},{2,3},{4,5}},{{6,7},{8,9},{10,11}}}}; char *teststring = (char*)"teststring contents"; +typedef char *charptr; +charptr teststring2 = "more contents"; + /* Test printing of a struct containing character arrays. */ struct some_arrays { diff --git a/gdb/testsuite/gdb.base/printcmds.exp b/gdb/testsuite/gdb.base/printcmds.exp index c87a1517f0..2c8baad5aa 100644 --- a/gdb/testsuite/gdb.base/printcmds.exp +++ b/gdb/testsuite/gdb.base/printcmds.exp @@ -519,6 +519,9 @@ proc test_print_strings {} { gdb_test "p teststring" \ " = (.unsigned char .. )?\"teststring contents\"" "p teststring with elements set to 20" + gdb_test "print teststring2" \ + " = (charptr) \"more contents\"" + gdb_test_no_output "set print elements 8" # Set the target-charset to ASCII, because the output varies from