diff --git a/gdb/ChangeLog b/gdb/ChangeLog index d189a0919b..b50a48ca1e 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,8 @@ +2021-02-24 Andrew Burgess + + * eval.c (evaluate_subexp_standard): Call value_ind for points to + dynamic types in UNOP_IND. + 2021-02-23 Simon Marchi PR gdb/26828 diff --git a/gdb/eval.c b/gdb/eval.c index 8256fdea14..7ba3ee5952 100644 --- a/gdb/eval.c +++ b/gdb/eval.c @@ -2425,19 +2425,29 @@ evaluate_subexp_standard (struct type *expect_type, else if (noside == EVAL_AVOID_SIDE_EFFECTS) { type = check_typedef (value_type (arg1)); - if (type->code () == TYPE_CODE_PTR - || TYPE_IS_REFERENCE (type) - /* In C you can dereference an array to get the 1st elt. */ - || type->code () == TYPE_CODE_ARRAY - ) - return value_zero (TYPE_TARGET_TYPE (type), - lval_memory); - else if (type->code () == TYPE_CODE_INT) - /* GDB allows dereferencing an int. */ - return value_zero (builtin_type (exp->gdbarch)->builtin_int, - lval_memory); - else - error (_("Attempt to take contents of a non-pointer value.")); + + /* If the type pointed to is dynamic then in order to resolve the + dynamic properties we must actually dereference the pointer. + There is a risk that this dereference will have side-effects + in the inferior, but being able to print accurate type + information seems worth the risk. */ + if ((type->code () != TYPE_CODE_PTR + && !TYPE_IS_REFERENCE (type)) + || !is_dynamic_type (TYPE_TARGET_TYPE (type))) + { + if (type->code () == TYPE_CODE_PTR + || TYPE_IS_REFERENCE (type) + /* In C you can dereference an array to get the 1st elt. */ + || type->code () == TYPE_CODE_ARRAY) + return value_zero (TYPE_TARGET_TYPE (type), + lval_memory); + else if (type->code () == TYPE_CODE_INT) + /* GDB allows dereferencing an int. */ + return value_zero (builtin_type (exp->gdbarch)->builtin_int, + lval_memory); + else + error (_("Attempt to take contents of a non-pointer value.")); + } } /* Allow * on an integer so we can cast it to whatever we want. diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 70b836b8c2..6f1cb0a852 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2021-02-24 Andrew Burgess + + * gdb.fortran/pointer-to-pointer.exp: Additional tests. + 2021-02-18 Andrew Burgess * gdb.arch/i386-biarch-core.exp: Add target check. diff --git a/gdb/testsuite/gdb.fortran/pointer-to-pointer.exp b/gdb/testsuite/gdb.fortran/pointer-to-pointer.exp index 27739cc6cf..306168b287 100644 --- a/gdb/testsuite/gdb.fortran/pointer-to-pointer.exp +++ b/gdb/testsuite/gdb.fortran/pointer-to-pointer.exp @@ -30,20 +30,29 @@ if ![fortran_runto_main] { return -1 } -# Depending on the compiler being used, the type names can be printed differently. +# Depending on the compiler being used, the type names can be printed +# differently. set real4 [fortran_real4] gdb_breakpoint [gdb_get_line_number "Break Here"] gdb_continue_to_breakpoint "Break Here" +gdb_test "print buffer" \ + " = \\(PTR TO -> \\( Type l_buffer \\)\\) $hex" +gdb_test "ptype buffer" \ + [multi_line \ + "type = PTR TO -> \\( Type l_buffer" \ + " $real4 :: alpha\\(:\\)" \ + "End Type l_buffer \\)" ] +gdb_test "ptype buffer%alpha" "type = $real4 \\(5\\)" + +# GDB allows pointer types to be dereferenced using '*'. This is not +# real Fortran syntax, just something extra that GDB supports. gdb_test "print *buffer" \ " = \\( alpha = \\(1\\.5, 2\\.5, 3\\.5, 4\\.5, 5\\.5\\) \\)" - -set l_buffer_type [multi_line \ - "Type l_buffer" \ - " $real4 :: alpha\\(:\\)" \ - "End Type l_buffer" ] - -gdb_test "ptype buffer" "type = PTR TO -> \\( ${l_buffer_type} \\)" -gdb_test "ptype *buffer" "type = ${l_buffer_type}" -gdb_test "ptype buffer%alpha" "type = $real4 \\(5\\)" +gdb_test "ptype *buffer" \ + [multi_line \ + "type = Type l_buffer" \ + " $real4 :: alpha\\(5\\)" \ + "End Type l_buffer" ] +gdb_test "ptype (*buffer)%alpha" "type = $real4 \\(5\\)"