Do not consider reference types as dynamic

Message ID 551E5309.7090509@adacore.com
State New, archived
Headers

Commit Message

Pierre-Marie de Rodat April 3, 2015, 8:44 a.m. UTC
  Joel suggested in private that if we don't consider reference types as 
dynamic in is_dynamic_type_internal, maybe the corresponding handling of 
reference types in resolve_dynamic_type_internal could be removed too.

I've tried to do this and this still triggers no regression on 
x86_64-linux. It's not surprising actually, since 
resolve_dynamic_type_internal does nothing on a type when 
is_dynamic_type_internal returns false for it.

So here's the updated patch. Thanks Joel for the idea! :-)
  

Comments

Joel Brobecker April 3, 2015, 12:47 p.m. UTC | #1
> >From f3fd1a7e81fad7a0b8e4f483f79b2470a3cf1499 Mon Sep 17 00:00:00 2001
> From: Pierre-Marie de Rodat <derodat@adacore.com>
> Date: Fri, 3 Apr 2015 10:40:52 +0200
> Subject: [PATCH] Do not consider reference types as dynamic
> 
> Even when referenced types are dynamic, the corresponding referencing
> type should not be considered as dynamic: it's only a pointer.  This
> prevents reference type for values not in memory to be resolved.
> 
> gdb/ChangeLog:
> 2015-04-03  Pierre-Marie de Rodat  <derodat@adacore.com>
> 
> 	* gdbtypes.c (is_dynamic_type_internal): Remove special handling
> 	of TYPE_CODE_REF types so that they are not considered as
> 	dynamic depending on the referenced type.
> 	(resolve_dynamic_type_internal): Likewise.
> 
> gdb/testsuite/ChangeLog:
> 2015-04-03  Pierre-Marie de Rodat  <derodat@adacore.com>
> 
> 	* gdb.ada/funcall_ref.exp: New file.
> 	* gdb.ada/funcall_ref/foo.adb: New file.

This is OK, thank you, Pierre-Marie.

Note that the parameter "top_level" is no longer useful after
this patch is applied, which is actually quite a nice side-effect
of this patch. I hum'ed and ah'ed about whether to ask that it be
removed as part of this patch, but in the end, I decided that this patch
was fine without the cleanup, as "top_level" is used a several places,
and I felt that cleaning it up here would dilute a bit the essence of
this patch.  So, I think we can clean it up separately.

> diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
> index 217ec70..6fb2e9a 100644
> --- a/gdb/gdbtypes.c
> +++ b/gdb/gdbtypes.c
> @@ -1752,10 +1752,6 @@ is_dynamic_type_internal (struct type *type, int top_level)

Thank you,
  
Yao Qi April 17, 2015, 10:47 a.m. UTC | #2
Pierre-Marie de Rodat <derodat@adacore.com> writes:

> I've tried to do this and this still triggers no regression on
> x86_64-linux. It's not surprising actually, since
> resolve_dynamic_type_internal does nothing on a type when
> is_dynamic_type_internal returns false for it.

Hi, Pierre,
This patch causes a regression in gdb.cp/vla-cxx.exp unfortunately,

 print vlaref^M
 $2 = (int (&)[variable length]) @0x3fffffffe900: {5, 7, 9}^M
 (gdb) FAIL: gdb.cp/vla-cxx.exp: print vlaref

which is shown by buildbot
https://sourceware.org/ml/gdb-testers/2015-q2/msg00360.html

I am not familiar with gdb type and dynamic type, so can't give anything
useful on how to fix this regression.  Any thoughts?
  
Pierre-Marie de Rodat April 17, 2015, 11:20 a.m. UTC | #3
Yao,

On 04/17/2015 12:47 PM, Yao Qi wrote:
> Hi, Pierre,

(My first name is "Pierre-Marie" ;-))

> This patch causes a regression in gdb.cp/vla-cxx.exp unfortunately,
>
>   print vlaref^M
>   $2 = (int (&)[variable length]) @0x3fffffffe900: {5, 7, 9}^M
>   (gdb) FAIL: gdb.cp/vla-cxx.exp: print vlaref
>
> which is shown by buildbot
> https://sourceware.org/ml/gdb-testers/2015-q2/msg00360.html
>
> I am not familiar with gdb type and dynamic type, so can't give anything
> useful on how to fix this regression.  Any thoughts?

Thank you for the heads up! I don't know what happens, so I will 
investigate and keep you updated.
  
Pierre-Marie de Rodat April 17, 2015, 3:07 p.m. UTC | #4
On 04/17/2015 01:20 PM, Pierre-Marie de Rodat wrote:
>> This patch causes a regression in gdb.cp/vla-cxx.exp unfortunately,
>>
>>   print vlaref^M
>>   $2 = (int (&)[variable length]) @0x3fffffffe900: {5, 7, 9}^M
>>   (gdb) FAIL: gdb.cp/vla-cxx.exp: print vlaref
>>
>> which is shown by buildbot
>> https://sourceware.org/ml/gdb-testers/2015-q2/msg00360.html

This is tough!

For the record, I did not notice this regression because I ran the 
testsuite with GCC's development branch, and this testcase was already 
failing with it. It works with GCC 4.9.2, though.

So my understanding was that types are dynamic when we need runtime 
information to decode them properly (memory layout, range bounds, etc). 
With this definition, reference types are never dynamic since they are 
actually mere pointers (static size, no dynamic semantics).

Printing a reference value is supposed to automatically fetch and print 
the referenced object... and its type. This testcase also tells us that 
it's the "fully resolved type" that must be printed (I mean referenced 
types must be resolved, too).

Here, we have "vlaref": a reference to a VLA (variable-length array), 
hence a reference to a dynamic type (the bounds and thus the size of the 
array are dynamic). Because of the "dynamic type" definition above, the 
referenced type is kept as-is during evaluation. And then at 
type-printing time, we use the dynamic referenced type, hence the 
"variable length" in the output.

If the definition above is correct, then we should enhance 
typeprint.c/c-typeprint.c/etc. to resolve dynamic type as type printing 
goes in order to get the actual array bounds in the output. This means: 
propagating a (possibly null) value in a lot of functions and use it for 
type resolution when possible. I guess this would involve a big patch 
but would also cover the "ptype" case.

I guess another way to "just get things working" would be to revert my 
previous patch and to enhance the dynamic property mechanism 
(dwarf2loc.h) to handle reference values that are not present in memory. 
For instance: extend the property_addr_info structure to hold either the 
address of objects (as today) or the address of the referenced object 
(for reference types).

Thoughts?
  
Joel Brobecker April 17, 2015, 3:30 p.m. UTC | #5
> If the definition above is correct, then we should enhance
> typeprint.c/c-typeprint.c/etc. to resolve dynamic type as type
> printing goes in order to get the actual array bounds in the output.
> This means: propagating a (possibly null) value in a lot of
> functions and use it for type resolution when possible. I guess this
> would involve a big patch but would also cover the "ptype" case.
> 
> I guess another way to "just get things working" would be to revert
> my previous patch and to enhance the dynamic property mechanism
> (dwarf2loc.h) to handle reference values that are not present in
> memory. For instance: extend the property_addr_info structure to
> hold either the address of objects (as today) or the address of the
> referenced object (for reference types).
> 
> Thoughts?

Thanks for looking into that, Pierre-Marie.

My 2 cents, based on the little amount of experience we've had dealing
with dyanmic types in Ada, and the amount of experience we've had
dealing with the GNAT encodings, I have a feeling that it's best to
maintain reference types as being non-dynamic, and enhance the functions
that print reference objects instead. We should probably compare what
Ada does (ada_val_print_ref) compared to C, for instance, as we handle
those reference values correctly, I believe.
  
Pierre-Marie de Rodat April 20, 2015, 2:27 p.m. UTC | #6
On 04/17/2015 05:30 PM, Joel Brobecker wrote:
> My 2 cents, based on the little amount of experience we've had dealing
> with dyanmic types in Ada, and the amount of experience we've had
> dealing with the GNAT encodings, I have a feeling that it's best to
> maintain reference types as being non-dynamic, and enhance the functions
> that print reference objects instead. We should probably compare what
> Ada does (ada_val_print_ref) compared to C, for instance, as we handle
> those reference values correctly, I believe.

Joel and I discussed this live: doing the type printing change is 
probably the best way in terms of "implementation consistency", but it's 
also going to be a lot of work.

So the plan is instead to try to enhance type resolution to handle 
references that are not addressable. In the meantime, I've reverted my 
patches so that the regression disappears. I'll submit another patch...
  
Pierre-Marie de Rodat April 24, 2015, 2:21 p.m. UTC | #7
On 04/20/2015 04:27 PM, Pierre-Marie de Rodat wrote:
> Joel and I discussed this live: doing the type printing change is
> probably the best way in terms of "implementation consistency", but it's
> also going to be a lot of work.
>
> So the plan is instead to try to enhance type resolution to handle
> references that are not addressable. In the meantime, I've reverted my
> patches so that the regression disappears. I'll submit another patch...

The patch series Joel submitted last Tuesday[1] solves the original 
issue: the plan I was talking about is actually implemented by these 
patches! So there's no need to go further on this matter.

[1] <https://www.sourceware.org/ml/gdb-patches/2015-04/msg00768.html>
  

Patch

From f3fd1a7e81fad7a0b8e4f483f79b2470a3cf1499 Mon Sep 17 00:00:00 2001
From: Pierre-Marie de Rodat <derodat@adacore.com>
Date: Fri, 3 Apr 2015 10:40:52 +0200
Subject: [PATCH] Do not consider reference types as dynamic

Even when referenced types are dynamic, the corresponding referencing
type should not be considered as dynamic: it's only a pointer.  This
prevents reference type for values not in memory to be resolved.

gdb/ChangeLog:
2015-04-03  Pierre-Marie de Rodat  <derodat@adacore.com>

	* gdbtypes.c (is_dynamic_type_internal): Remove special handling
	of TYPE_CODE_REF types so that they are not considered as
	dynamic depending on the referenced type.
	(resolve_dynamic_type_internal): Likewise.

gdb/testsuite/ChangeLog:
2015-04-03  Pierre-Marie de Rodat  <derodat@adacore.com>

	* gdb.ada/funcall_ref.exp: New file.
	* gdb.ada/funcall_ref/foo.adb: New file.
---
 gdb/gdbtypes.c                            | 19 -------------
 gdb/testsuite/gdb.ada/funcall_ref.exp     | 44 +++++++++++++++++++++++++++++++
 gdb/testsuite/gdb.ada/funcall_ref/foo.adb | 34 ++++++++++++++++++++++++
 3 files changed, 78 insertions(+), 19 deletions(-)
 create mode 100644 gdb/testsuite/gdb.ada/funcall_ref.exp
 create mode 100644 gdb/testsuite/gdb.ada/funcall_ref/foo.adb

diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index 217ec70..6fb2e9a 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -1752,10 +1752,6 @@  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) == TYPE_CODE_REF)
-    type = check_typedef (TYPE_TARGET_TYPE (type));
-
   /* Types that have a dynamic TYPE_DATA_LOCATION are considered
      dynamic, even if the type itself is statically defined.
      From a user's point of view, this may appear counter-intuitive;
@@ -2045,21 +2041,6 @@  resolve_dynamic_type_internal (struct type *type,
 
       switch (TYPE_CODE (type))
 	{
-	case TYPE_CODE_REF:
-	  {
-	    struct property_addr_info pinfo;
-
-	    pinfo.type = check_typedef (TYPE_TARGET_TYPE (type));
-	    pinfo.addr = read_memory_typed_address (addr_stack->addr, type);
-	    pinfo.next = addr_stack;
-
-	    resolved_type = copy_type (type);
-	    TYPE_TARGET_TYPE (resolved_type)
-	      = resolve_dynamic_type_internal (TYPE_TARGET_TYPE (type),
-					       &pinfo, top_level);
-	    break;
-	  }
-
 	case TYPE_CODE_ARRAY:
 	  resolved_type = resolve_dynamic_array (type, addr_stack);
 	  break;
diff --git a/gdb/testsuite/gdb.ada/funcall_ref.exp b/gdb/testsuite/gdb.ada/funcall_ref.exp
new file mode 100644
index 0000000..444e9d2
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/funcall_ref.exp
@@ -0,0 +1,44 @@ 
+# Copyright 2008-2015 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/>.
+
+load_lib "ada.exp"
+
+standard_ada_testfile foo
+
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable \
+                     [list debug]] != "" } {
+  return -1
+}
+
+clean_restart ${testfile}
+
+set bp_location [gdb_get_line_number "STOP" ${testdir}/foo.adb]
+runto "foo.adb:$bp_location"
+
+# Test printing and type-printing of a discriminated record that a function
+# returns by reference.
+
+# Currently, GCC describes such functions as returning pointers (instead of
+# references).
+setup_xfail *-*-*
+gdb_test "p get (\"Hello world!\")" \
+         "= \\(n => 12, s => \"Hello world!\"\\)" \
+
+setup_xfail *-*-*
+gdb_test "ptype get (\"Hello world!\")" \
+         [multi_line "type = <ref> record" \
+                     "    n: natural;" \
+                     "    s: access array \\(1 \\.\\. n\\) of character;" \
+                     "end record"] \
diff --git a/gdb/testsuite/gdb.ada/funcall_ref/foo.adb b/gdb/testsuite/gdb.ada/funcall_ref/foo.adb
new file mode 100644
index 0000000..84655d3
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/funcall_ref/foo.adb
@@ -0,0 +1,34 @@ 
+--  Copyright 2008-2015 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/>.
+
+procedure Foo is
+   type Bar (N : Natural) is record
+      S : String (1 .. N);
+   end record;
+
+   function Get (S : String) return Bar is
+   begin
+      return (N => S'Length, S => S);
+   end Get;
+
+   procedure Do_Nothing (B : Bar) is
+   begin
+      null;
+   end Do_Nothing;
+
+   B : Bar := Get ("Foo");
+begin
+   Do_Nothing (B); --  STOP
+end Foo;
-- 
2.3.4