diff mbox

[V4,02/18] vla: make dynamic fortran arrays functional.

Message ID 1421243390-24015-3-git-send-email-keven.boell@intel.com
State New
Headers show

Commit Message

Keven Boell Jan. 14, 2015, 1:49 p.m. UTC
This patch enables GDB to print the value of a dynamic
array (VLA) if allocated/associated in fortran. If not the
allocation status will be printed to the command line.

(gdb) p vla_not_allocated
$1 = <not allocated>

(gdb) p vla_allocated
$1 = (1, 2, 3)

(gdb) p vla_not_associated
$1 = <not associated>

(gdb) p vla_associated
$1 = (3, 2, 1)

The patch covers various locations where the allocation/
association status makes sense to print.

2014-05-28  Keven Boell  <keven.boell@intel.com>
            Sanimir Agovic  <sanimir.agovic@intel.com>

	* dwarf2loc.c (dwarf2_address_data_valid): New
	function.
	* dwarf2loc.h (dwarf2_address_data_valid): New
	function.
	* f-typeprint.c (f_print_type): Print allocation/
	association status.
	(f_type_print_varspec_suffix): Print allocation/
	association status for &-operator usages.
	* gdbtypes.c (create_array_type_with_stride): Add
	query for valid data location.
	(is_dynamic_type): Extend dynamic type detection
	with allocated/associated. Add type detection for
	fields.
	(resolve_dynamic_range): Copy type before resolving
	it as dynamic attributes need to be preserved.
	(resolve_dynamic_array): Copy type before resolving
	it as dynamic attributes need to be preserved. Add
	resolving of allocated/associated attributes.
	(resolve_dynamic_type): Add call to nested
	type resolving.
	(copy_type_recursive): Add allocated/associated
	attributes to be copied.
	(copy_type): Copy allocated/associated/data_location
	as well as the fields structure if available.
	* valarith.c (value_subscripted_rvalue): Print allocated/
	associated status when indexing a VLA.
	* valprint.c (valprint_check_validity): Print allocated/
	associated status.
	(val_print_not_allocated): New function.
	(val_print_not_associated): New function.
	* valprint.h (val_print_not_allocated): New function.
	(val_print_not_associated): New function.
	* value.c (set_value_component_location): Adjust the value
	address for single value prints.



Signed-off-by: Keven Boell <keven.boell@intel.com>
---
 gdb/dwarf2loc.c   |   16 +++++++++
 gdb/dwarf2loc.h   |    6 ++++
 gdb/f-typeprint.c |   62 +++++++++++++++++++++------------
 gdb/gdbtypes.c    |   99 ++++++++++++++++++++++++++++++++++++++++++++++++++---
 gdb/valarith.c    |    9 ++++-
 gdb/valprint.c    |   40 ++++++++++++++++++++++
 gdb/valprint.h    |    4 +++
 gdb/value.c       |   20 +++++++++++
 8 files changed, 229 insertions(+), 27 deletions(-)

Comments

Joel Brobecker Feb. 9, 2015, 7:09 a.m. UTC | #1
On Wed, Jan 14, 2015 at 02:49:34PM +0100, Keven Boell wrote:
> This patch enables GDB to print the value of a dynamic
> array (VLA) if allocated/associated in fortran. If not the
> allocation status will be printed to the command line.
> 
> (gdb) p vla_not_allocated
> $1 = <not allocated>
> 
> (gdb) p vla_allocated
> $1 = (1, 2, 3)
> 
> (gdb) p vla_not_associated
> $1 = <not associated>
> 
> (gdb) p vla_associated
> $1 = (3, 2, 1)
> 
> The patch covers various locations where the allocation/
> association status makes sense to print.

There may be places where it easily makes sense, but there are
several hunks that I do not understand. I suspect that those
bits may have something to do with the 10 testcases that follow
this patch.

First of all, it's unclear to me which pieces of functionality
this patch is trying to address: It's clear that handling of
non-associated & non-allocated types is one. But are there
other pieces of functionality being added here as well?

What I propose is that we first clarify the question above, and
that once the question above is clarified, we work on the bare
minimum patch to provide the first piece of functionality on
the list, whichever one makes most sence to you. That patch
should provide not just this bare-minimum set of code changes,
but also the corresponding tests that verify the new piece of
functionality.That way, I can review code and test together,
and see why certain hunks are necessary.

Limitations that allow us to reduce the size of each patch are OK.
We can then have small patches at each iteration that lifts one
limitation at a time.

During this iterative process, I would stop and wait at each
iterative process. I think you'll be wasting a fair amout of
time at each iteration if you try to submit 20 patches each time.

Some general comments below:

> 2014-05-28  Keven Boell  <keven.boell@intel.com>
>             Sanimir Agovic  <sanimir.agovic@intel.com>
> 
> 	* dwarf2loc.c (dwarf2_address_data_valid): New
> 	function.
> 	* dwarf2loc.h (dwarf2_address_data_valid): New
> 	function.
> 	* f-typeprint.c (f_print_type): Print allocation/
> 	association status.
> 	(f_type_print_varspec_suffix): Print allocation/
> 	association status for &-operator usages.
> 	* gdbtypes.c (create_array_type_with_stride): Add
> 	query for valid data location.
> 	(is_dynamic_type): Extend dynamic type detection
> 	with allocated/associated. Add type detection for
> 	fields.
> 	(resolve_dynamic_range): Copy type before resolving
> 	it as dynamic attributes need to be preserved.
> 	(resolve_dynamic_array): Copy type before resolving
> 	it as dynamic attributes need to be preserved. Add
> 	resolving of allocated/associated attributes.
> 	(resolve_dynamic_type): Add call to nested
> 	type resolving.
> 	(copy_type_recursive): Add allocated/associated
> 	attributes to be copied.
> 	(copy_type): Copy allocated/associated/data_location
> 	as well as the fields structure if available.
> 	* valarith.c (value_subscripted_rvalue): Print allocated/
> 	associated status when indexing a VLA.
> 	* valprint.c (valprint_check_validity): Print allocated/
> 	associated status.
> 	(val_print_not_allocated): New function.
> 	(val_print_not_associated): New function.
> 	* valprint.h (val_print_not_allocated): New function.
> 	(val_print_not_associated): New function.
> 	* value.c (set_value_component_location): Adjust the value
> 	address for single value prints.
>  	    do_cleanups (value_chain);
> +
> +	    /* Select right frame to correctly evaluate VLA's during a backtrace.  */
> +	    if (is_dynamic_type (type))
> +	      select_frame (frame);

The comment has a line that's too long. There are several other
parts of this patch where lines are too long too.

> +
>  	    retval = value_at_lazy (type, address + byte_offset);
>  	    if (in_stack_memory)
>  	      set_value_stack (retval, 1);
> @@ -2546,6 +2551,17 @@ dwarf2_compile_property_to_c (struct ui_file *stream,
>  			     data, data + size, per_cu);
>  }
>  
> +int
> +dwarf2_address_data_valid (const struct type *type)

When the function documentation is in the .h file, we prefer
that comment explains where the function is documented. Eg:

/* See dwarf2loc.h.  */

This way, we do know at a single glance that the function is
documented, and where that documentation is.

> +{
> +  if (TYPE_NOT_ASSOCIATED (type))
> +    return 0;
> +
> +  if (TYPE_NOT_ALLOCATED (type))
> +    return 0;

Based on the implementation of those macros, you are definitely
making an assumption that for types that do have these properties,
those properties have been resolved. This needs to be documented,
and I am also wondering whether an assert might also be appropriate.
Keven Boell Feb. 18, 2015, 4:01 p.m. UTC | #2
On 09.02.2015 08:09, Joel Brobecker wrote:
> On Wed, Jan 14, 2015 at 02:49:34PM +0100, Keven Boell wrote:
>> This patch enables GDB to print the value of a dynamic
>> array (VLA) if allocated/associated in fortran. If not the
>> allocation status will be printed to the command line.
>>
>> (gdb) p vla_not_allocated
>> $1 = <not allocated>
>>
>> (gdb) p vla_allocated
>> $1 = (1, 2, 3)
>>
>> (gdb) p vla_not_associated
>> $1 = <not associated>
>>
>> (gdb) p vla_associated
>> $1 = (3, 2, 1)
>>
>> The patch covers various locations where the allocation/
>> association status makes sense to print.
> 
> There may be places where it easily makes sense, but there are
> several hunks that I do not understand. I suspect that those
> bits may have something to do with the 10 testcases that follow
> this patch.
> 
> First of all, it's unclear to me which pieces of functionality
> this patch is trying to address: It's clear that handling of
> non-associated & non-allocated types is one. But are there
> other pieces of functionality being added here as well?

Basically the whole support for Fortran dynamic arrays is covered in this patch, not only the support allocated/associated states.

> 
> What I propose is that we first clarify the question above, and
> that once the question above is clarified, we work on the bare
> minimum patch to provide the first piece of functionality on
> the list, whichever one makes most sence to you. That patch
> should provide not just this bare-minimum set of code changes,
> but also the corresponding tests that verify the new piece of
> functionality.That way, I can review code and test together,
> and see why certain hunks are necessary.

I thought it would be good to have one patch, which enables the dynamic array support completely and not having individual small patches, which might not functional at all. All the tests following this patch are testing various functionality in the area of dynamic arrays.
I will think about it if it's possible to split them.

> 
> Limitations that allow us to reduce the size of each patch are OK.
> We can then have small patches at each iteration that lifts one
> limitation at a time.
> 
> During this iterative process, I would stop and wait at each
> iterative process. I think you'll be wasting a fair amout of
> time at each iteration if you try to submit 20 patches each time.

I see, sounds reasonable to me.

> 
> Some general comments below:
> 
>> 2014-05-28  Keven Boell  <keven.boell@intel.com>
>>             Sanimir Agovic  <sanimir.agovic@intel.com>
>>
>> 	* dwarf2loc.c (dwarf2_address_data_valid): New
>> 	function.
>> 	* dwarf2loc.h (dwarf2_address_data_valid): New
>> 	function.
>> 	* f-typeprint.c (f_print_type): Print allocation/
>> 	association status.
>> 	(f_type_print_varspec_suffix): Print allocation/
>> 	association status for &-operator usages.
>> 	* gdbtypes.c (create_array_type_with_stride): Add
>> 	query for valid data location.
>> 	(is_dynamic_type): Extend dynamic type detection
>> 	with allocated/associated. Add type detection for
>> 	fields.
>> 	(resolve_dynamic_range): Copy type before resolving
>> 	it as dynamic attributes need to be preserved.
>> 	(resolve_dynamic_array): Copy type before resolving
>> 	it as dynamic attributes need to be preserved. Add
>> 	resolving of allocated/associated attributes.
>> 	(resolve_dynamic_type): Add call to nested
>> 	type resolving.
>> 	(copy_type_recursive): Add allocated/associated
>> 	attributes to be copied.
>> 	(copy_type): Copy allocated/associated/data_location
>> 	as well as the fields structure if available.
>> 	* valarith.c (value_subscripted_rvalue): Print allocated/
>> 	associated status when indexing a VLA.
>> 	* valprint.c (valprint_check_validity): Print allocated/
>> 	associated status.
>> 	(val_print_not_allocated): New function.
>> 	(val_print_not_associated): New function.
>> 	* valprint.h (val_print_not_allocated): New function.
>> 	(val_print_not_associated): New function.
>> 	* value.c (set_value_component_location): Adjust the value
>> 	address for single value prints.
>>  	    do_cleanups (value_chain);
>> +
>> +	    /* Select right frame to correctly evaluate VLA's during a backtrace.  */
>> +	    if (is_dynamic_type (type))
>> +	      select_frame (frame);
> 
> The comment has a line that's too long. There are several other
> parts of this patch where lines are too long too.
> 
>> +
>>  	    retval = value_at_lazy (type, address + byte_offset);
>>  	    if (in_stack_memory)
>>  	      set_value_stack (retval, 1);
>> @@ -2546,6 +2551,17 @@ dwarf2_compile_property_to_c (struct ui_file *stream,
>>  			     data, data + size, per_cu);
>>  }
>>  
>> +int
>> +dwarf2_address_data_valid (const struct type *type)
> 
> When the function documentation is in the .h file, we prefer
> that comment explains where the function is documented. Eg:
> 
> /* See dwarf2loc.h.  */
> 
> This way, we do know at a single glance that the function is
> documented, and where that documentation is.
> 
>> +{
>> +  if (TYPE_NOT_ASSOCIATED (type))
>> +    return 0;
>> +
>> +  if (TYPE_NOT_ALLOCATED (type))
>> +    return 0;
> 
> Based on the implementation of those macros, you are definitely
> making an assumption that for types that do have these properties,
> those properties have been resolved. This needs to be documented,
> and I am also wondering whether an assert might also be appropriate.
> 

Yes, this assumption is done as this is the main idea behind the implementation.
Will add add an assert.

Thanks,
Keven
Joel Brobecker Feb. 22, 2015, 4:23 a.m. UTC | #3
> Basically the whole support for Fortran dynamic arrays is covered in
> this patch, not only the support allocated/associated states.

That's just too much for me to grok, and I think that's also going
to make it harder later on to figure out why a certain piece of
your changes is needed or not. When testing is fairly complete
and it is affecting a mainstream language such as C, commenting
the code out can help figure things out. But this is still sub-
optimal, and nearly out of reach for less available languages such
as Fortran.

To give you an example showing that this is very necessary, we are
currently trying to figure out, at AdaCore, why reference types
are considered dynamic if their target type is dynamic. If I had
asked that question earlier on, we wouldn't be trying to find
the info a posteriori.

> I thought it would be good to have one patch, which enables the
> dynamic array support completely and not having individual small
> patches, which might not functional at all. All the tests following
> this patch are testing various functionality in the area of dynamic
> arrays.

Here's a suggestion of how I sometimes approach that problem.

Start from a clean checkout and build it. Then use a program
that has the simplest situation of an associated array, and
start by adding the code that reads the DWARF info, and then
keep adding code until GDB is able to print "<unassociated>"
for that array.

If you need additional changes to be able to print the correct
value of associated arrays, leave those for later. We can deal
deal with that as a separate patch (assuming no regression
elsewhere, but I don't see how this could happen).

Once we have that, we can start working on your testcase, and
test the feature that you just introduced, within the limitations
that your simplified patch currently have. Make that one patch,
and send it.

Once we have the first patch reviewed, and pushed to the GDB
repository, we can claim that as first progress, and show
that we have something for our efforts. Then we iterate, piece
by piece, feature by feature, special-case by special-case.
Each time, we need to handle the bare minimum, and have
a corresponding new set of tests. Note that the new tests do
not need to be in a new testcase - it is perfectly fine to
add tests to a pre-existing testcase too.

I apologize if it seems a little painful for you to be working
this way, but I truly believe that it'll make things a lot easier
to review, and as a result, I believe that it'll actually take
less time to get that code accepted.
diff mbox

Patch

diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index 2bd12d6..c6802aa 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -2287,6 +2287,11 @@  dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame,
 	    int in_stack_memory = dwarf_expr_fetch_in_stack_memory (ctx, 0);
 
 	    do_cleanups (value_chain);
+
+	    /* Select right frame to correctly evaluate VLA's during a backtrace.  */
+	    if (is_dynamic_type (type))
+	      select_frame (frame);
+
 	    retval = value_at_lazy (type, address + byte_offset);
 	    if (in_stack_memory)
 	      set_value_stack (retval, 1);
@@ -2546,6 +2551,17 @@  dwarf2_compile_property_to_c (struct ui_file *stream,
 			     data, data + size, per_cu);
 }
 
+int
+dwarf2_address_data_valid (const struct type *type)
+{
+  if (TYPE_NOT_ASSOCIATED (type))
+    return 0;
+
+  if (TYPE_NOT_ALLOCATED (type))
+    return 0;
+
+  return 1;
+}
 
 /* Helper functions and baton for dwarf2_loc_desc_needs_frame.  */
 
diff --git a/gdb/dwarf2loc.h b/gdb/dwarf2loc.h
index a369361..a1a059c 100644
--- a/gdb/dwarf2loc.h
+++ b/gdb/dwarf2loc.h
@@ -135,6 +135,12 @@  void dwarf2_compile_property_to_c (struct ui_file *stream,
 CORE_ADDR dwarf2_read_addr_index (struct dwarf2_per_cu_data *per_cu,
 				  unsigned int addr_index);
 
+/* Checks if a dwarf location definition is valid.
+   Returns 1 if valid; 0 otherwise.  */
+
+extern int dwarf2_address_data_valid (const struct type *type);
+
+
 /* The symbol location baton types used by the DWARF-2 reader (i.e.
    SYMBOL_LOCATION_BATON for a LOC_COMPUTED symbol).  "struct
    dwarf2_locexpr_baton" is for a symbol with a single location
diff --git a/gdb/f-typeprint.c b/gdb/f-typeprint.c
index 4957e1f..5754cd4 100644
--- a/gdb/f-typeprint.c
+++ b/gdb/f-typeprint.c
@@ -30,6 +30,7 @@ 
 #include "gdbcore.h"
 #include "target.h"
 #include "f-lang.h"
+#include "valprint.h"
 
 #if 0				/* Currently unused.  */
 static void f_type_print_args (struct type *, struct ui_file *);
@@ -53,6 +54,17 @@  f_print_type (struct type *type, const char *varstring, struct ui_file *stream,
   enum type_code code;
   int demangled_args;
 
+  if (TYPE_NOT_ASSOCIATED (type))
+    {
+      val_print_not_associated (stream);
+      return;
+    }
+  if (TYPE_NOT_ALLOCATED (type))
+    {
+      val_print_not_allocated (stream);
+      return;
+    }
+
   f_type_print_base (type, stream, show, level);
   code = TYPE_CODE (type);
   if ((varstring != NULL && *varstring != '\0')
@@ -167,28 +179,36 @@  f_type_print_varspec_suffix (struct type *type, struct ui_file *stream,
       if (arrayprint_recurse_level == 1)
 	fprintf_filtered (stream, "(");
 
-      if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_ARRAY)
-	f_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0, 0,
-				     arrayprint_recurse_level);
-
-      lower_bound = f77_get_lowerbound (type);
-      if (lower_bound != 1)	/* Not the default.  */
-	fprintf_filtered (stream, "%d:", lower_bound);
-
-      /* Make sure that, if we have an assumed size array, we
-         print out a warning and print the upperbound as '*'.  */
-
-      if (TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED (type))
-	fprintf_filtered (stream, "*");
+      if (TYPE_NOT_ASSOCIATED (type))
+        val_print_not_associated (stream);
+      else if (TYPE_NOT_ALLOCATED (type))
+        val_print_not_allocated (stream);
       else
-	{
-	  upper_bound = f77_get_upperbound (type);
-	  fprintf_filtered (stream, "%d", upper_bound);
-	}
-
-      if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_ARRAY)
-	f_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0, 0,
-				     arrayprint_recurse_level);
+        {
+
+          if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_ARRAY)
+            f_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0, 0,
+                 arrayprint_recurse_level);
+
+          lower_bound = f77_get_lowerbound (type);
+          if (lower_bound != 1)	/* Not the default.  */
+            fprintf_filtered (stream, "%d:", lower_bound);
+
+          /* Make sure that, if we have an assumed size array, we
+             print out a warning and print the upperbound as '*'.  */
+
+          if (TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED (type))
+            fprintf_filtered (stream, "*");
+          else
+            {
+              upper_bound = f77_get_upperbound (type);
+              fprintf_filtered (stream, "%d", upper_bound);
+            }
+
+          if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_ARRAY)
+            f_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, 0, 0, 0,
+                 arrayprint_recurse_level);
+      }
       if (arrayprint_recurse_level == 1)
 	fprintf_filtered (stream, ")");
       else
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index 6d3c084..6695adb 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -1020,7 +1020,8 @@  create_array_type_with_stride (struct type *result_type,
 
   TYPE_CODE (result_type) = TYPE_CODE_ARRAY;
   TYPE_TARGET_TYPE (result_type) = element_type;
-  if (has_static_range (TYPE_RANGE_DATA (range_type)))
+  if (has_static_range (TYPE_RANGE_DATA (range_type))
+      && dwarf2_address_data_valid (result_type))
     {
       LONGEST low_bound, high_bound;
 
@@ -1630,6 +1631,11 @@  stub_noname_complaint (void)
 static int
 is_dynamic_type_internal (struct type *type, int top_level)
 {
+  int index;
+
+  if (!type)
+    return 0;
+
   type = check_typedef (type);
 
   /* We only want to recognize references at the outermost level.  */
@@ -1647,6 +1653,20 @@  is_dynamic_type_internal (struct type *type, int top_level)
 	  || TYPE_DATA_LOCATION_KIND (type) == PROP_LOCLIST))
     return 1;
 
+  if (TYPE_ASSOCIATED_PROP (type))
+    return 1;
+
+  if (TYPE_ALLOCATED_PROP (type))
+    return 1;
+
+  /* Scan field types in the Fortran case for nested dynamic types.
+     This will be done only for Fortran as in the C++ case an endless recursion
+     can occur in the area of classes.  */
+  if (current_language->la_language == language_fortran)
+    for (index = 0; index < TYPE_NFIELDS (type); index++)
+      if (is_dynamic_type (TYPE_FIELD_TYPE (type, index)))
+        return 1;
+
   switch (TYPE_CODE (type))
     {
     case TYPE_CODE_RANGE:
@@ -1702,6 +1722,7 @@  resolve_dynamic_range (struct type *dyn_range_type, CORE_ADDR addr)
   const struct dynamic_prop *prop;
   const struct dwarf2_locexpr_baton *baton;
   struct dynamic_prop low_bound, high_bound;
+  struct type *range_copy = copy_type (dyn_range_type);
 
   gdb_assert (TYPE_CODE (dyn_range_type) == TYPE_CODE_RANGE);
 
@@ -1733,8 +1754,8 @@  resolve_dynamic_range (struct type *dyn_range_type, CORE_ADDR addr)
       high_bound.data.const_val = 0;
     }
 
-  static_range_type = create_range_type (copy_type (dyn_range_type),
-					 TYPE_TARGET_TYPE (dyn_range_type),
+  static_range_type = create_range_type (range_copy,
+					 TYPE_TARGET_TYPE (range_copy),
 					 &low_bound, &high_bound);
   TYPE_RANGE_DATA (static_range_type)->flag_bound_evaluated = 1;
   return static_range_type;
@@ -1751,6 +1772,8 @@  resolve_dynamic_array (struct type *type, CORE_ADDR addr)
   struct type *elt_type;
   struct type *range_type;
   struct type *ary_dim;
+  struct dynamic_prop *prop;
+  struct type *copy = copy_type (type);
 
   gdb_assert (TYPE_CODE (type) == TYPE_CODE_ARRAY);
 
@@ -1758,14 +1781,28 @@  resolve_dynamic_array (struct type *type, CORE_ADDR addr)
   range_type = check_typedef (TYPE_INDEX_TYPE (elt_type));
   range_type = resolve_dynamic_range (range_type, addr);
 
+  prop = TYPE_ALLOCATED_PROP (type);
+  if (dwarf2_evaluate_property (prop, addr, &value))
+    {
+      TYPE_ALLOCATED_PROP (copy)->kind = PROP_CONST;
+      TYPE_ALLOCATED_PROP (copy)->data.const_val = value;
+    }
+
+  prop = TYPE_ASSOCIATED_PROP (type);
+  if (dwarf2_evaluate_property (prop, addr, &value))
+    {
+      TYPE_ASSOCIATED_PROP (copy)->kind = PROP_CONST;
+      TYPE_ASSOCIATED_PROP (copy)->data.const_val = value;
+    }
+
   ary_dim = check_typedef (TYPE_TARGET_TYPE (elt_type));
 
   if (ary_dim != NULL && TYPE_CODE (ary_dim) == TYPE_CODE_ARRAY)
-    elt_type = resolve_dynamic_array (TYPE_TARGET_TYPE (type), addr);
+    elt_type = resolve_dynamic_array (TYPE_TARGET_TYPE (copy), addr);
   else
     elt_type = TYPE_TARGET_TYPE (type);
 
-  return create_array_type (copy_type (type),
+  return create_array_type (copy,
 			    elt_type,
 			    range_type);
 }
@@ -4174,6 +4211,20 @@  copy_type_recursive (struct objfile *objfile,
 	      sizeof (struct dynamic_prop));
     }
 
+  /* Copy allocated information.  */
+  if (TYPE_ALLOCATED_PROP (type) != NULL)
+    {
+      TYPE_ALLOCATED_PROP (new_type) = xmalloc (sizeof (struct dynamic_prop));
+      *TYPE_ALLOCATED_PROP (new_type) = *TYPE_ALLOCATED_PROP (type);
+    }
+
+  /* Copy associated information.  */
+  if (TYPE_ASSOCIATED_PROP (type) != NULL)
+    {
+      TYPE_ASSOCIATED_PROP (new_type) = xmalloc (sizeof (struct dynamic_prop));
+      *TYPE_ASSOCIATED_PROP (new_type) = *TYPE_ASSOCIATED_PROP (type);
+    }
+
   /* Copy pointers to other types.  */
   if (TYPE_TARGET_TYPE (type))
     TYPE_TARGET_TYPE (new_type) = 
@@ -4227,6 +4278,44 @@  copy_type (const struct type *type)
 	      sizeof (struct dynamic_prop));
     }
 
+  if (TYPE_ALLOCATED_PROP (type))
+    {
+      TYPE_ALLOCATED_PROP (new_type)
+              = OBSTACK_ZALLOC (&TYPE_OWNER (type).objfile->objfile_obstack,
+                                struct dynamic_prop);
+      memcpy (TYPE_ALLOCATED_PROP (new_type), TYPE_ALLOCATED_PROP (type),
+        sizeof (struct dynamic_prop));
+    }
+
+  if (TYPE_ASSOCIATED_PROP (type))
+    {
+      TYPE_ASSOCIATED_PROP (new_type)
+              = OBSTACK_ZALLOC (&TYPE_OWNER (type).objfile->objfile_obstack,
+                                struct dynamic_prop);
+      memcpy (TYPE_ASSOCIATED_PROP (new_type), TYPE_ASSOCIATED_PROP (type),
+        sizeof (struct dynamic_prop));
+    }
+
+  if (TYPE_DATA_LOCATION (type))
+    {
+      TYPE_DATA_LOCATION (new_type)
+              = OBSTACK_ZALLOC (&TYPE_OWNER (type).objfile->objfile_obstack,
+                                struct dynamic_prop);
+      memcpy (TYPE_DATA_LOCATION (new_type), TYPE_DATA_LOCATION (type),
+        sizeof (struct dynamic_prop));
+    }
+
+  if (TYPE_NFIELDS (type))
+    {
+      int nfields = TYPE_NFIELDS (type);
+
+      TYPE_FIELDS (new_type)
+              = OBSTACK_CALLOC (&TYPE_OWNER (type).objfile->objfile_obstack,
+                                nfields, struct field);
+      memcpy (TYPE_FIELDS (new_type), TYPE_FIELDS (type),
+        nfields * sizeof (struct field));
+   }
+
   return new_type;
 }
 
diff --git a/gdb/valarith.c b/gdb/valarith.c
index f33515c..e2af354 100644
--- a/gdb/valarith.c
+++ b/gdb/valarith.c
@@ -198,7 +198,14 @@  value_subscripted_rvalue (struct value *array, LONGEST index, int lowerbound)
 
   if (index < lowerbound || (!TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED (array_type)
 			     && elt_offs >= TYPE_LENGTH (array_type)))
-    error (_("no such vector element"));
+    {
+      if (TYPE_NOT_ASSOCIATED (array_type))
+        error (_("no such vector element because not associated"));
+      else if (TYPE_NOT_ALLOCATED (array_type))
+        error (_("no such vector element because not allocated"));
+      else
+        error (_("no such vector element"));
+    }
 
   if (VALUE_LVAL (array) == lval_memory && value_lazy (array))
     v = allocate_value_lazy (elt_type);
diff --git a/gdb/valprint.c b/gdb/valprint.c
index 29a3473..3ae8994 100644
--- a/gdb/valprint.c
+++ b/gdb/valprint.c
@@ -303,6 +303,18 @@  valprint_check_validity (struct ui_file *stream,
 {
   CHECK_TYPEDEF (type);
 
+  if (TYPE_NOT_ASSOCIATED (type))
+    {
+      val_print_not_associated (stream);
+      return 0;
+    }
+
+  if (TYPE_NOT_ALLOCATED (type))
+    {
+      val_print_not_allocated (stream);
+      return 0;
+    }
+
   if (TYPE_CODE (type) != TYPE_CODE_UNION
       && TYPE_CODE (type) != TYPE_CODE_STRUCT
       && TYPE_CODE (type) != TYPE_CODE_ARRAY)
@@ -359,6 +371,18 @@  val_print_invalid_address (struct ui_file *stream)
   fprintf_filtered (stream, _("<invalid address>"));
 }
 
+void
+val_print_not_allocated (struct ui_file *stream)
+{
+  fprintf_filtered (stream, _("<not allocated>"));
+}
+
+void
+val_print_not_associated (struct ui_file *stream)
+{
+  fprintf_filtered (stream, _("<not associated>"));
+}
+
 /* A generic val_print that is suitable for use by language
    implementations of the la_val_print method.  This function can
    handle most type codes, though not all, notably exception
@@ -800,12 +824,16 @@  static int
 value_check_printable (struct value *val, struct ui_file *stream,
 		       const struct value_print_options *options)
 {
+  const struct type *type;
+
   if (val == 0)
     {
       fprintf_filtered (stream, _("<address of value unknown>"));
       return 0;
     }
 
+  type = value_type (val);
+
   if (value_entirely_optimized_out (val))
     {
       if (options->summary && !val_print_scalar_type_p (value_type (val)))
@@ -831,6 +859,18 @@  value_check_printable (struct value *val, struct ui_file *stream,
       return 0;
     }
 
+  if (TYPE_NOT_ASSOCIATED (type))
+    {
+      val_print_not_associated (stream);
+      return 0;
+    }
+
+  if (TYPE_NOT_ALLOCATED (type))
+    {
+      val_print_not_allocated (stream);
+      return 0;
+    }
+
   return 1;
 }
 
diff --git a/gdb/valprint.h b/gdb/valprint.h
index e3d0137..46ca9c6 100644
--- a/gdb/valprint.h
+++ b/gdb/valprint.h
@@ -217,4 +217,8 @@  extern void output_command_const (const char *args, int from_tty);
 
 extern int val_print_scalar_type_p (struct type *type);
 
+extern void val_print_not_allocated (struct ui_file *stream);
+
+extern void val_print_not_associated (struct ui_file *stream);
+
 #endif
diff --git a/gdb/value.c b/gdb/value.c
index 9445f25..1a32347 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -40,6 +40,7 @@ 
 #include "tracepoint.h"
 #include "cp-abi.h"
 #include "user-regs.h"
+#include "dwarf2loc.h"
 
 /* Prototypes for exported functions.  */
 
@@ -1755,6 +1756,25 @@  set_value_component_location (struct value *component,
       if (funcs->copy_closure)
         component->location.computed.closure = funcs->copy_closure (whole);
     }
+
+  /* For dynamic types compute the address of the component value location in
+     sub range types based on the location of the sub range type, if not being
+     an internal GDB variable or parts of it.  */
+  if (VALUE_LVAL (component) != lval_internalvar
+      && VALUE_LVAL (component) != lval_internalvar_component)
+    {
+      CORE_ADDR addr;
+      struct type *type = value_type (whole);
+
+      addr = value_raw_address (component);
+
+      if (TYPE_DATA_LOCATION (type)
+          && TYPE_DATA_LOCATION_KIND (type) == PROP_CONST)
+        {
+          addr = TYPE_DATA_LOCATION_ADDR (type);
+          set_value_address (component, addr);
+        }
+    }
 }