[v3,2/4] gdb, types: Resolve pointer types dynamically

Message ID 20230904222956.15203-3-abdul.b.ijaz@intel.com
State New
Headers
Series Dynamic properties of pointers |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_gdb_build--master-arm success Testing passed

Commit Message

Abdul Basit Ijaz Sept. 4, 2023, 10:29 p.m. UTC
  From: "Ijaz, Abdul B" <abdul.b.ijaz@intel.com>

This commit allows pointers to be dynamic types (on the outmost
level).  Similar to references, a pointer is considered a dynamic type
if its target type is a dynamic type and it is on the outmost level.

The pointer resolution follows the one of references.

This generally makes the GDB output more verbose.  We are able to print
more details about a pointer's target like the dimension of an array.

In Fortran, if we have a pointer to a dynamic type

  type buffer
    real, dimension(:), pointer :: ptr
  end type buffer
  type(buffer), pointer :: buffer_ptr
  allocate (buffer_ptr)
  allocate (buffer_ptr%ptr (5))

which then gets allocated, we now resolve the dynamic type before
printing the pointer's type:

Before:

  (gdb) ptype buffer_ptr
  type = PTR TO -> ( Type buffer
    real(kind=4) :: alpha(:)
  End Type buffer )

After:

  (gdb) ptype buffer_ptr
  type = PTR TO -> ( Type buffer
    real(kind=4) :: alpha(5)
  End Type buffer )

Similarly in C++ we can dynamically resolve e.g. pointers to arrays:

  int len = 3;
  int arr[len];
  int (*ptr)[len];
  int ptr = &arr;

Once the pointer is assigned one gets:

Before:

  (gdb) p ptr
  $1 = (int (*)[variable length]) 0x123456
  (gdb) ptype ptr
  type = int (*)[variable length]

After:

  (gdb) p ptr
  $1 = (int (*)[3]) 0x123456
  (gdb) ptype ptr
  type = int (*)[3]

For more examples see the modified/added test cases.
---
 gdb/gdbtypes.c                                |   7 +-
 gdb/testsuite/gdb.cp/vla-cxx.cc               |   4 +
 gdb/testsuite/gdb.cp/vla-cxx.exp              |  15 +++
 gdb/testsuite/gdb.dwarf2/dynarr-ptr.exp       |  16 +--
 .../gdb.fortran/pointer-to-pointer.exp        |   2 +-
 gdb/testsuite/gdb.fortran/pointers.exp        | 115 ++++++++++++++++++
 gdb/testsuite/gdb.fortran/pointers.f90        |  29 +++++
 gdb/valprint.c                                |   6 -
 8 files changed, 177 insertions(+), 17 deletions(-)
 create mode 100644 gdb/testsuite/gdb.fortran/pointers.exp
  

Comments

Thiago Jung Bauermann Oct. 3, 2023, 12:07 a.m. UTC | #1
Hello,

I've been working a bit with dynamic types lately, but I'm not confident
enough to provide a Reviewed-by.

In any case, some small nits. Everything else LGTM FWIW.

Abdul Basit Ijaz via Gdb-patches <gdb-patches@sourceware.org> writes:

> diff --git a/gdb/testsuite/gdb.dwarf2/dynarr-ptr.exp b/gdb/testsuite/gdb.dwarf2/dynarr-ptr.exp
> index 6e4a331eca8..d6b20086c89 100644
> --- a/gdb/testsuite/gdb.dwarf2/dynarr-ptr.exp
> +++ b/gdb/testsuite/gdb.dwarf2/dynarr-ptr.exp
> @@ -154,7 +154,7 @@ gdb_test "print foo.three_ptr.all'length" \
>           " = 3"
>  
>  gdb_test "ptype foo.three_ptr.all" \
> -         " = array \\(<>\\) of integer"
> +    " = array \\(1 \\.\\. 3\\) of integer"

The new indentation level is inconsistent with the rest of the file.
Please preserve the original indentation level.

>  
>  # foo.three_ptr
>  
> @@ -177,7 +177,7 @@ gdb_test "print foo.three_ptr'length" \
>           " = 3"
>  
>  gdb_test "ptype foo.three_ptr" \
> -         " = access array \\(<>\\) of integer"
> +    " = access array \\(1 \\.\\. 3\\) of integer"

Ditto for the other changes in this file.

> diff --git a/gdb/testsuite/gdb.fortran/pointers.exp b/gdb/testsuite/gdb.fortran/pointers.exp
> new file mode 100644
> index 00000000000..ca2195bbfe6
> --- /dev/null
> +++ b/gdb/testsuite/gdb.fortran/pointers.exp
> @@ -0,0 +1,115 @@
> +# Copyright 2016-2023 Free Software Foundation, Inc.

This is a new file. The copyright starts in 2023.

> +
> +# This program is free software; you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation; either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +# GNU General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License
> +# along with this program.  If not, see <http://www.gnu.org/licenses/>.
  
Tom Tromey Oct. 10, 2023, 7:45 p.m. UTC | #2
>>>>> "Thiago" == Thiago Jung Bauermann via Gdb-patches <gdb-patches@sourceware.org> writes:

>> gdb_test "ptype foo.three_ptr.all" \
>> -         " = array \\(<>\\) of integer"
>> +    " = array \\(1 \\.\\. 3\\) of integer"

Thiago> The new indentation level is inconsistent with the rest of the file.
Thiago> Please preserve the original indentation level.

I think gdb standardized on 4 space indent for Tcl, but some files are
still wrong here.  However normally I think we'd want reindentations to
be a separate patch.  Fine to do that as a prelude if it makes your task
easier.

Tom
  
Tom Tromey Oct. 10, 2023, 7:49 p.m. UTC | #3
>>>>> Abdul Basit Ijaz via Gdb-patches <gdb-patches@sourceware.org> writes:

> -  /* We only want to recognize references at the outermost level.  */
> -  if (top_level && type->code () == TYPE_CODE_REF)
> +  /* We only want to recognize references and pointers at the outermost
> +     level.  */
> +  if (top_level
> +      && (type->code () == TYPE_CODE_REF || type->code () == TYPE_CODE_PTR))

Pre-existing but I wonder why this code checks TYPE_CODE_REF and not
TYPE_CODE_RVALUE_REF.

> diff --git a/gdb/valprint.c b/gdb/valprint.c
> index b65dda15c04..c71ae089f46 100644
> --- a/gdb/valprint.c
> +++ b/gdb/valprint.c
> @@ -1156,12 +1156,6 @@ value_check_printable (struct value *val, struct ui_file *stream,
>        return 0;
>      }
 
> -  if (type_not_associated (val->type ()))
> -    {
> -      val_print_not_associated (stream);
> -      return 0;
> -    }

I don't really know anything about Fortran, so I don't know why this
code was here in the first place, nor what its removal might mean.
Could you say why this is being removed?

Tom
  
Abdul Basit Ijaz Jan. 3, 2024, 9:06 p.m. UTC | #4
Hi Tom and Thiago,

Thanks a lot for the feedback.

>> gdb_test "ptype foo.three_ptr.all" \
>> -         " = array \\(<>\\) of integer"
>> +    " = array \\(1 \\.\\. 3\\) of integer"

Thiago> The new indentation level is inconsistent with the rest of the file.
Thiago> Please preserve the original indentation level.

Tom > I think gdb standardized on 4 space indent for Tcl, but some files are still wrong here.  However normally I think we'd want reindentations to be a separate patch.  Fine to do that as a prelude if it makes your task easier.

I will add an extra patch to this series for fixing existing indentation problem in test gdb.dwarf2/dynarr-ptr.exp and then add changes to test on top of it.


Thanks & Best Regards
Abdul Basit

-----Original Message-----
From: Tom Tromey <tom@tromey.com> 
Sent: Tuesday, October 10, 2023 9:46 PM
To: Thiago Jung Bauermann via Gdb-patches <gdb-patches@sourceware.org>
Cc: Ijaz, Abdul B <abdul.b.ijaz@intel.com>; Thiago Jung Bauermann <thiago.bauermann@linaro.org>; simark@simark.ca; tom@tromey.com
Subject: Re: [PATCH v3 2/4] gdb, types: Resolve pointer types dynamically

>>>>> "Thiago" == Thiago Jung Bauermann via Gdb-patches <gdb-patches@sourceware.org> writes:

>> gdb_test "ptype foo.three_ptr.all" \
>> -         " = array \\(<>\\) of integer"
>> +    " = array \\(1 \\.\\. 3\\) of integer"

Thiago> The new indentation level is inconsistent with the rest of the file.
Thiago> Please preserve the original indentation level.

I think gdb standardized on 4 space indent for Tcl, but some files are still wrong here.  However normally I think we'd want reindentations to be a separate patch.  Fine to do that as a prelude if it makes your task easier.

Tom
Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928
  
Abdul Basit Ijaz Jan. 3, 2024, 9:06 p.m. UTC | #5
Hi Thiago,

Thanks for the feedback.

> The new indentation level is inconsistent with the rest of the file.
> Please preserve the original indentation level.

Replied in other email also that will add an extra patch in this series to fix indentation in this test.

> This is a new file. The copyright starts in 2023.

Will update it to 2024 in v4 series.

Best Regards,
Abdul Basit

-----Original Message-----
From: Thiago Jung Bauermann <thiago.bauermann@linaro.org> 
Sent: Tuesday, October 3, 2023 2:08 AM
To: Ijaz, Abdul B <abdul.b.ijaz@intel.com>
Cc: simark@simark.ca; tom@tromey.com; gdb-patches@sourceware.org
Subject: Re: [PATCH v3 2/4] gdb, types: Resolve pointer types dynamically


Hello,

I've been working a bit with dynamic types lately, but I'm not confident enough to provide a Reviewed-by.

In any case, some small nits. Everything else LGTM FWIW.

Abdul Basit Ijaz via Gdb-patches <gdb-patches@sourceware.org> writes:

> diff --git a/gdb/testsuite/gdb.dwarf2/dynarr-ptr.exp 
> b/gdb/testsuite/gdb.dwarf2/dynarr-ptr.exp
> index 6e4a331eca8..d6b20086c89 100644
> --- a/gdb/testsuite/gdb.dwarf2/dynarr-ptr.exp
> +++ b/gdb/testsuite/gdb.dwarf2/dynarr-ptr.exp
> @@ -154,7 +154,7 @@ gdb_test "print foo.three_ptr.all'length" \
>           " = 3"
>  
>  gdb_test "ptype foo.three_ptr.all" \
> -         " = array \\(<>\\) of integer"
> +    " = array \\(1 \\.\\. 3\\) of integer"

The new indentation level is inconsistent with the rest of the file.
Please preserve the original indentation level.

>  
>  # foo.three_ptr
>  
> @@ -177,7 +177,7 @@ gdb_test "print foo.three_ptr'length" \
>           " = 3"
>  
>  gdb_test "ptype foo.three_ptr" \
> -         " = access array \\(<>\\) of integer"
> +    " = access array \\(1 \\.\\. 3\\) of integer"

Ditto for the other changes in this file.

> diff --git a/gdb/testsuite/gdb.fortran/pointers.exp 
> b/gdb/testsuite/gdb.fortran/pointers.exp
> new file mode 100644
> index 00000000000..ca2195bbfe6
> --- /dev/null
> +++ b/gdb/testsuite/gdb.fortran/pointers.exp
> @@ -0,0 +1,115 @@
> +# Copyright 2016-2023 Free Software Foundation, Inc.

This is a new file. The copyright starts in 2023.

> +
> +# This program is free software; you can redistribute it and/or 
> +modify # it under the terms of the GNU General Public License as 
> +published by # the Free Software Foundation; either version 3 of the 
> +License, or # (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful, # 
> +but WITHOUT ANY WARRANTY; without even the implied warranty of # 
> +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the # GNU 
> +General Public License for more details.
> +#
> +# You should have received a copy of the GNU General Public License # 
> +along with this program.  If not, see <http://www.gnu.org/licenses/>.

--
Thiago
Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928
  
Abdul Basit Ijaz Jan. 3, 2024, 9:31 p.m. UTC | #6
Hi Tom,

Thanks a lot for the feedback.

>> -  /* We only want to recognize references at the outermost level.  */
>> -  if (top_level && type->code () == TYPE_CODE_REF)
>> +  /* We only want to recognize references and pointers at the outermost
>> +     level.  */
>> +  if (top_level
>> +      && (type->code () == TYPE_CODE_REF || type->code () == 
>> + TYPE_CODE_PTR))

Tom > Pre-existing but I wonder why this code checks TYPE_CODE_REF and not TYPE_CODE_RVALUE_REF.

Here we are checking for LVALUE or Pointers dynamic value and for them need to resolve the target memory to resolve pointer/memory at outmost level.  So as far as I understood checking for rvalue here would not be needed.  In case you have some case to try then please let me know I can give it a try.

>> -  if (type_not_associated (val->type ()))
>> -    {
>> -      val_print_not_associated (stream);
>> -      return 0;
>> -    }

Tom > I don't really know anything about Fortran, so I don't know why this code was here in the first place, nor what its removal might mean.

This was originally added at time to support DW_AT_Associated/Allocated DIEs for Fortran dynamic arrays but this is a redundant code so no need to keep it. Also in existing testsuite there is no affect with or without it.  Will mention in the commit message in V4 series.

Best Regards,
Abdul Basit

-----Original Message-----
From: Tom Tromey <tom@tromey.com> 
Sent: Tuesday, October 10, 2023 9:50 PM
To: Abdul Basit Ijaz via Gdb-patches <gdb-patches@sourceware.org>
Cc: Ijaz, Abdul B <abdul.b.ijaz@intel.com>; simark@simark.ca; tom@tromey.com
Subject: Re: [PATCH v3 2/4] gdb, types: Resolve pointer types dynamically

>>>>> Abdul Basit Ijaz via Gdb-patches <gdb-patches@sourceware.org> writes:

> -  /* We only want to recognize references at the outermost level.  */
> -  if (top_level && type->code () == TYPE_CODE_REF)
> +  /* We only want to recognize references and pointers at the outermost
> +     level.  */
> +  if (top_level
> +      && (type->code () == TYPE_CODE_REF || type->code () == 
> + TYPE_CODE_PTR))

Pre-existing but I wonder why this code checks TYPE_CODE_REF and not TYPE_CODE_RVALUE_REF.

> diff --git a/gdb/valprint.c b/gdb/valprint.c index 
> b65dda15c04..c71ae089f46 100644
> --- a/gdb/valprint.c
> +++ b/gdb/valprint.c
> @@ -1156,12 +1156,6 @@ value_check_printable (struct value *val, struct ui_file *stream,
>        return 0;
>      }
 
> -  if (type_not_associated (val->type ()))
> -    {
> -      val_print_not_associated (stream);
> -      return 0;
> -    }

I don't really know anything about Fortran, so I don't know why this code was here in the first place, nor what its removal might mean.
Could you say why this is being removed?

Tom
Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928
  

Patch

diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index 5e15ec64c41..4b1787b62e6 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -2038,8 +2038,10 @@  is_dynamic_type_internal (struct type *type, int top_level)
 {
   type = check_typedef (type);
 
-  /* We only want to recognize references at the outermost level.  */
-  if (top_level && type->code () == TYPE_CODE_REF)
+  /* We only want to recognize references and pointers at the outermost
+     level.  */
+  if (top_level
+      && (type->code () == TYPE_CODE_REF || type->code () == TYPE_CODE_PTR))
     type = check_typedef (type->target_type ());
 
   /* Types that have a dynamic TYPE_DATA_LOCATION are considered
@@ -2775,6 +2777,7 @@  resolve_dynamic_type_internal (struct type *type,
       switch (type->code ())
 	{
 	case TYPE_CODE_REF:
+	case TYPE_CODE_PTR:
 	  {
 	    struct property_addr_info pinfo;
 
diff --git a/gdb/testsuite/gdb.cp/vla-cxx.cc b/gdb/testsuite/gdb.cp/vla-cxx.cc
index 0ecb130f676..83e238339ac 100644
--- a/gdb/testsuite/gdb.cp/vla-cxx.cc
+++ b/gdb/testsuite/gdb.cp/vla-cxx.cc
@@ -40,6 +40,10 @@  int main(int argc, char **argv)
   typedef typeof (vla) &vlareftypedef;
   vlareftypedef vlaref2 (vla);
   container c;
+  typeof (vla) *ptr = nullptr;
+
+  // Before pointer assignment.
+  ptr = &vla;
 
   for (int i = 0; i < z; ++i)
     vla[i] = 5 + 2 * i;
diff --git a/gdb/testsuite/gdb.cp/vla-cxx.exp b/gdb/testsuite/gdb.cp/vla-cxx.exp
index 0a588220679..ade688cedda 100644
--- a/gdb/testsuite/gdb.cp/vla-cxx.exp
+++ b/gdb/testsuite/gdb.cp/vla-cxx.exp
@@ -23,6 +23,18 @@  if ![runto_main] {
     return -1
 }
 
+gdb_breakpoint [gdb_get_line_number "Before pointer assignment"]
+gdb_continue_to_breakpoint "Before pointer assignment"
+
+gdb_test "ptype ptr" "= int \\(\\*\\)\\\[3\\\]" \
+    "ptype ptr, before pointer assignment"
+
+gdb_test "print ptr" "= \\(int \\(\\*\\)\\\[3\\\]\\) 0x0" \
+    "print ptr, before pointer assignment"
+
+gdb_test "print *ptr" "Cannot access memory at address 0x0" \
+    "print *ptr, before pointer assignment"
+
 gdb_breakpoint [gdb_get_line_number "vlas_filled"]
 gdb_continue_to_breakpoint "vlas_filled"
 
@@ -33,3 +45,6 @@  gdb_test "print vlaref" " = \\(int \\(&\\)\\\[3\\\]\\) @$hex: \\{5, 7, 9\\}"
 # bug being tested, it's better not to depend on the exact spelling.
 gdb_test "print vlaref2" " = \\(.*\\) @$hex: \\{5, 7, 9\\}"
 gdb_test "print c" " = \\{e = \\{c = @$hex\\}\\}"
+gdb_test "ptype ptr" "int \\(\\*\\)\\\[3\\\]"
+gdb_test "print ptr" "\\(int \\(\\*\\)\\\[3\\\]\\) $hex"
+gdb_test "print *ptr" " = \\{5, 7, 9\\}"
diff --git a/gdb/testsuite/gdb.dwarf2/dynarr-ptr.exp b/gdb/testsuite/gdb.dwarf2/dynarr-ptr.exp
index 6e4a331eca8..d6b20086c89 100644
--- a/gdb/testsuite/gdb.dwarf2/dynarr-ptr.exp
+++ b/gdb/testsuite/gdb.dwarf2/dynarr-ptr.exp
@@ -154,7 +154,7 @@  gdb_test "print foo.three_ptr.all'length" \
          " = 3"
 
 gdb_test "ptype foo.three_ptr.all" \
-         " = array \\(<>\\) of integer"
+    " = array \\(1 \\.\\. 3\\) of integer"
 
 # foo.three_ptr
 
@@ -177,7 +177,7 @@  gdb_test "print foo.three_ptr'length" \
          " = 3"
 
 gdb_test "ptype foo.three_ptr" \
-         " = access array \\(<>\\) of integer"
+    " = access array \\(1 \\.\\. 3\\) of integer"
 
 # foo.three_ptr_tdef.all
 
@@ -203,7 +203,7 @@  gdb_test "print foo.three_ptr_tdef.all'length" \
          " = 3"
 
 gdb_test "ptype foo.three_ptr_tdef.all" \
-         " = array \\(<>\\) of integer"
+    " = array \\(1 \\.\\. 3\\) of integer"
 
 # foo.three_ptr_tdef
 
@@ -226,7 +226,7 @@  gdb_test "print foo.three_ptr_tdef'length" \
          " = 3"
 
 gdb_test "ptype foo.three_ptr_tdef" \
-         " = access array \\(<>\\) of integer"
+    " = access array \\(1 \\.\\. 3\\) of integer"
 
 # foo.five_ptr.all
 
@@ -258,7 +258,7 @@  gdb_test "print foo.five_ptr.all'length" \
          " = 5"
 
 gdb_test "ptype foo.five_ptr.all" \
-         " = array \\(<>\\) of integer"
+    " = array \\(2 \\.\\. 6\\) of integer"
 
 # foo.five_ptr
 
@@ -287,7 +287,7 @@  gdb_test "print foo.five_ptr'length" \
          " = 5"
 
 gdb_test "ptype foo.five_ptr" \
-         " = access array \\(<>\\) of integer"
+    " = access array \\(2 \\.\\. 6\\) of integer"
 
 # foo.five_ptr_tdef.all
 
@@ -319,7 +319,7 @@  gdb_test "print foo.five_ptr_tdef.all'length" \
          " = 5"
 
 gdb_test "ptype foo.five_ptr_tdef.all" \
-         " = array \\(<>\\) of integer"
+    " = array \\(2 \\.\\. 6\\) of integer"
 
 # foo.five_ptr_tdef
 
@@ -348,4 +348,4 @@  gdb_test "print foo.five_ptr_tdef'length" \
          " = 5"
 
 gdb_test "ptype foo.five_ptr_tdef" \
-         " = access array \\(<>\\) of integer"
+    " = access array \\(2 \\.\\. 6\\) of integer"
diff --git a/gdb/testsuite/gdb.fortran/pointer-to-pointer.exp b/gdb/testsuite/gdb.fortran/pointer-to-pointer.exp
index 0fd5fb0996f..78b7ba17588 100644
--- a/gdb/testsuite/gdb.fortran/pointer-to-pointer.exp
+++ b/gdb/testsuite/gdb.fortran/pointer-to-pointer.exp
@@ -41,7 +41,7 @@  gdb_test "print buffer" \
 gdb_test "ptype buffer" \
     [multi_line \
 	 "type = PTR TO -> \\( Type l_buffer" \
-	 "    $real4 :: alpha\\(:\\)" \
+	 "    $real4 :: alpha\\(5\\)" \
 	 "End Type l_buffer \\)" ]
 gdb_test "ptype buffer%alpha" "type = $real4 \\(5\\)"
 
diff --git a/gdb/testsuite/gdb.fortran/pointers.exp b/gdb/testsuite/gdb.fortran/pointers.exp
new file mode 100644
index 00000000000..ca2195bbfe6
--- /dev/null
+++ b/gdb/testsuite/gdb.fortran/pointers.exp
@@ -0,0 +1,115 @@ 
+# Copyright 2016-2023 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+standard_testfile "pointers.f90"
+load_lib fortran.exp
+
+if {[prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} \
+    {debug f90 quiet}]} {
+    return -1
+}
+
+if {![fortran_runto_main]} {
+    untested "could not run to main"
+    return -1
+}
+
+# Depending on the compiler being used, the type names can be printed
+# differently.
+set logical [fortran_logical4]
+set real [fortran_real4]
+set int [fortran_int4]
+set complex [fortran_complex4]
+
+gdb_breakpoint [gdb_get_line_number "Before pointer assignment"]
+gdb_continue_to_breakpoint "Before pointer assignment"
+gdb_test "print logp" "= \\(PTR TO -> \\( $logical \\)\\) 0x0" \
+    "print logp, not associated"
+gdb_test "print *logp" "Cannot access memory at address 0x0" \
+    "print *logp, not associated"
+gdb_test "print comp" "= \\(PTR TO -> \\( $complex \\)\\) 0x0" \
+    "print comp, not associated"
+gdb_test "print *comp" "Cannot access memory at address 0x0" \
+    "print *comp, not associated"
+gdb_test "print charp" "= \\(PTR TO -> \\( character\\*1 \\)\\) 0x0" \
+    "print charp, not associated"
+gdb_test "print *charp" "Cannot access memory at address 0x0" \
+    "print *charp, not associated"
+gdb_test "print charap" "= \\(PTR TO -> \\( character\\*3 \\)\\) 0x0" \
+    "print charap, not associated"
+gdb_test "print *charap" "Cannot access memory at address 0x0" \
+    "print *charap, not associated"
+gdb_test "print intp" "= \\(PTR TO -> \\( $int \\)\\) 0x0" \
+    "print intp, not associated"
+gdb_test "print *intp" "Cannot access memory at address 0x0" \
+    "print *intp, not associated"
+gdb_test "print intap" " = <not associated>" "print intap, not associated"
+gdb_test "print realp" "= \\(PTR TO -> \\( $real \\)\\) 0x0" \
+    "print realp, not associated"
+gdb_test "print *realp" "Cannot access memory at address 0x0" \
+    "print *realp, not associated"
+gdb_test "print \$my_var = intp" "= \\(PTR TO -> \\( $int \\)\\) 0x0"
+gdb_test "print cyclicp1" "= \\( i = -?\\d+, p = 0x0 \\)" \
+    "print cyclicp1, not associated"
+gdb_test "print cyclicp1%p" \
+    "= \\(PTR TO -> \\( Type typewithpointer \\)\\) 0x0" \
+    "print cyclicp1%p, not associated"
+
+gdb_breakpoint [gdb_get_line_number "Before value assignment"]
+gdb_continue_to_breakpoint "Before value assignment"
+gdb_test "print *(twop)%ivla2" "= <not allocated>"
+
+gdb_breakpoint [gdb_get_line_number "After value assignment"]
+gdb_continue_to_breakpoint "After value assignment"
+gdb_test "print logp" "= \\(PTR TO -> \\( $logical \\)\\) $hex\( <.*>\)?"
+gdb_test "print *logp" "= \\.TRUE\\."
+gdb_test "print comp" "= \\(PTR TO -> \\( $complex \\)\\) $hex\( <.*>\)?"
+gdb_test "print *comp" "= \\(1,2\\)"
+gdb_test "print charp" "= \\(PTR TO -> \\( character\\*1 \\)\\) $hex\( <.*>\)?"
+gdb_test "print *charp" "= 'a'"
+gdb_test "print charap" "= \\(PTR TO -> \\( character\\*3 \\)\\) $hex\( <.*>\)?"
+gdb_test "print *charap" "= 'abc'"
+gdb_test "print intp" "= \\(PTR TO -> \\( $int \\)\\) $hex\( <.*>\)?"
+gdb_test "print *intp" "= 10"
+gdb_test "print intap" "= \\(\\(1, 1, 3(, 1){7}\\) \\(1(, 1){9}\\)\\)" \
+    "print intap, associated"
+gdb_test "print intvlap" "= \\(2, 2, 2, 4(, 2){6}\\)" \
+    "print intvlap, associated"
+gdb_test "print realp" "= \\(PTR TO -> \\( $real \\)\\) $hex\( <.*>\)?"
+gdb_test "print *realp" "= 3\\.14000\\d+"
+gdb_test "print arrayOfPtr(2)%p" "= \\(PTR TO -> \\( Type two \\)\\) $hex\( <.*>\)?"
+gdb_test "print *(arrayOfPtr(2)%p)" \
+    "= \\( ivla1 = \\(11, 12, 13\\), ivla2 = \\(\\(211, 221\\) \\(212, 222\\)\\) \\)"
+gdb_test "print arrayOfPtr(3)%p" "= \\(PTR TO -> \\( Type two \\)\\) 0x0" \
+    "print arrayOfPtr(3)%p"
+
+gdb_test_multiple "print *(arrayOfPtr(3)%p)" \
+    "print *(arrayOfPtr(3)%p), associated" {
+    # gfortran
+    -re -wrap "Cannot access memory at address 0x0" {
+	pass $gdb_test_name
+    }
+    # ifx
+    -re -wrap "Location address is not set." {
+	pass $gdb_test_name
+    }
+}
+
+gdb_test "print cyclicp1" "= \\( i = 1, p = $hex\( <.*>\)? \\)"
+gdb_test "print cyclicp1%p" "= \\(PTR TO -> \\( Type typewithpointer \\)\\) $hex\( <.*>\)?"
+gdb_test "print *((integer*) &inta + 2)" "= 3" "print temporary pointer, array"
+gdb_test "print *((integer*) &intvla + 3)" "= 4" "print temporary pointer, allocated vla"
+gdb_test "print \$pc" "\\(PTR TO -> \\( void \\(\\) \\(\\) \\)\\) $hex <pointers\\+\\d+>" \
+    "Print program counter"
diff --git a/gdb/testsuite/gdb.fortran/pointers.f90 b/gdb/testsuite/gdb.fortran/pointers.f90
index 8708d505ada..0fb6b36a25c 100644
--- a/gdb/testsuite/gdb.fortran/pointers.f90
+++ b/gdb/testsuite/gdb.fortran/pointers.f90
@@ -20,14 +20,26 @@  program pointers
     integer, allocatable :: ivla2 (:, :)
   end type two
 
+  type :: typeWithPointer
+    integer i
+    type(typeWithPointer), pointer:: p
+  end type typeWithPointer
+
+  type :: twoPtr
+    type (two), pointer :: p
+  end type twoPtr
+
   logical, target :: logv
   complex, target :: comv
   character, target :: charv
   character (len=3), target :: chara
   integer, target :: intv
   integer, target, dimension (10,2) :: inta
+  integer, target, allocatable, dimension (:) :: intvla
   real, target :: realv
   type(two), target :: twov
+  type(twoPtr) :: arrayOfPtr (3)
+  type(typeWithPointer), target:: cyclicp1,cyclicp2
 
   logical, pointer :: logp
   complex, pointer :: comp
@@ -35,6 +47,7 @@  program pointers
   character (len=3), pointer :: charap
   integer, pointer :: intp
   integer, pointer, dimension (:,:) :: intap
+  integer, pointer, dimension (:) :: intvlap
   real, pointer :: realp
   type(two), pointer :: twop
 
@@ -44,8 +57,14 @@  program pointers
   nullify (charap)
   nullify (intp)
   nullify (intap)
+  nullify (intvlap)
   nullify (realp)
   nullify (twop)
+  nullify (arrayOfPtr(1)%p)
+  nullify (arrayOfPtr(2)%p)
+  nullify (arrayOfPtr(3)%p)
+  nullify (cyclicp1%p)
+  nullify (cyclicp2%p)
 
   logp => logv    ! Before pointer assignment
   comp => comv
@@ -53,8 +72,14 @@  program pointers
   charap => chara
   intp => intv
   intap => inta
+  intvlap => intvla
   realp => realv
   twop => twov
+  arrayOfPtr(2)%p => twov
+  cyclicp1%i = 1
+  cyclicp1%p => cyclicp2
+  cyclicp2%i = 2
+  cyclicp2%p => cyclicp1
 
   logv = associated(logp)     ! Before value assignment
   comv = cmplx(1,2)
@@ -63,6 +88,10 @@  program pointers
   intv = 10
   inta(:,:) = 1
   inta(3,1) = 3
+  allocate (intvla(10))
+  intvla(:) = 2
+  intvla(4) = 4
+  intvlap => intvla
   realv = 3.14
 
   allocate (twov%ivla1(3))
diff --git a/gdb/valprint.c b/gdb/valprint.c
index b65dda15c04..c71ae089f46 100644
--- a/gdb/valprint.c
+++ b/gdb/valprint.c
@@ -1156,12 +1156,6 @@  value_check_printable (struct value *val, struct ui_file *stream,
       return 0;
     }
 
-  if (type_not_associated (val->type ()))
-    {
-      val_print_not_associated (stream);
-      return 0;
-    }
-
   if (type_not_allocated (val->type ()))
     {
       val_print_not_allocated (stream);