+2015-01-29  Joel Brobecker  <brobecker@adacore.com>
+
+       * gdbtypes.h (struct dynamic_prop): New PROP_ADDR_OFFSET enum
+       kind.
+       * gdbtypes.c (resolve_dynamic_type_internal): Replace "addr"
+       parameter by "addr_stack" parameter.
+       (resolve_dynamic_range): Replace "addr" parameter by
+       "stack_addr" parameter.  Update function documentation.
+       Update code accordingly.
+       (resolve_dynamic_array, resolve_dynamic_union)
+       (resolve_dynamic_struct, resolve_dynamic_type_internal): Likewise.
+       (resolve_dynamic_type): Update code, following the changes made
+       to resolve_dynamic_type_internal's interface.
+       * dwarf2loc.h (struct property_addr_info): New.
+       (dwarf2_evaluate_property): Replace "address" parameter
+       by "addr_stack" parameter.  Adjust function documentation.
+       (struct dwarf2_offset_baton): New.
+       (struct dwarf2_property_baton): Update documentation of
+       field "referenced_type" to be more general. New field
+       "offset_info" in union data field.
+       * dwarf2loc.c (dwarf2_evaluate_property): Replace "address"
+       parameter by "addr_stack" parameter.  Adjust code accordingly.
+       Add support for PROP_ADDR_OFFSET properties.
+       * dwarf2read.c (attr_to_dynamic_prop): Add support for
+       DW_AT_data_member_location attributes as well.  Use case
+       statements instead of if/else condition.
+
 2015-01-29  Joel Brobecker  <brobecker@adacore.com>
 
        * ada-varobj.c (ada_varobj_get_array_number_of_children):
 
 
 int
 dwarf2_evaluate_property (const struct dynamic_prop *prop,
-                         CORE_ADDR address, CORE_ADDR *value)
+                         struct property_addr_info *addr_stack,
+                         CORE_ADDR *value)
 {
   if (prop == NULL)
     return 0;
       {
        const struct dwarf2_property_baton *baton = prop->data.baton;
 
-       if (dwarf2_locexpr_baton_eval (&baton->locexpr, address, value))
+       if (dwarf2_locexpr_baton_eval (&baton->locexpr, addr_stack->addr,
+                                      value))
          {
            if (baton->referenced_type)
              {
     case PROP_CONST:
       *value = prop->data.const_val;
       return 1;
+
+    case PROP_ADDR_OFFSET:
+      {
+       struct dwarf2_property_baton *baton = prop->data.baton;
+       struct property_addr_info *pinfo;
+       struct value *val;
+
+       for (pinfo = addr_stack; pinfo != NULL; pinfo = pinfo->next)
+         if (pinfo->type == baton->referenced_type)
+           break;
+       if (pinfo == NULL)
+         error ("cannot find reference address for offset property");
+       val = value_at (baton->offset_info.type,
+                       pinfo->addr + baton->offset_info.offset);
+       *value = value_as_address (val);
+       return 1;
+      }
     }
 
   return 0;
 
                                        size_t size,
                                        struct dwarf2_per_cu_data *per_cu);
 
-/* Converts a dynamic property into a static one.  ADDRESS is the address
-   of the object currently being evaluated and might be nedded.
+/* A chain of addresses that might be needed to resolve a dynamic
+   property.  */
+
+struct property_addr_info
+{
+  /* The type of the object whose dynamic properties, if any, are
+     being resolved.  */
+  struct type *type;
+
+  /* The address of that object.  */
+  CORE_ADDR addr;
+
+  /* If not NULL, a pointer to the info for the object containing
+     the object described by this node.  */
+  struct property_addr_info *next;
+};
+
+/* Converts a dynamic property into a static one.  ADDR_STACK is the stack
+   of addresses that might be needed to evaluate the property.
    Returns 1 if PROP could be converted and the static value is passed back
    into VALUE, otherwise returns 0.  */
 
 int dwarf2_evaluate_property (const struct dynamic_prop *prop,
-                             CORE_ADDR address,
+                             struct property_addr_info *addr_stack,
                              CORE_ADDR *value);
 
 /* A helper for the compiler interface that compiles a single dynamic
   unsigned char from_dwo;
 };
 
+/* The baton used when a dynamic property is an offset to a parent
+   type.  This can be used, for instance, then the bound of an array
+   inside a record is determined by the value of another field inside
+   that record.  */
+
+struct dwarf2_offset_baton
+{
+  /* The offset from the parent type where the value of the property
+     is stored.  In the example provided above, this would be the offset
+     of the field being used as the array bound.  */
+  LONGEST offset;
+
+  /* The type of the object whose property is dynamic.  In the example
+     provided above, this would the the array's index type.  */
+  struct type *type;
+};
+
 /* A dynamic property is either expressed as a single location expression
    or a location list.  If the property is an indirection, pointing to
    another die, keep track of the targeted type in REFERENCED_TYPE.  */
 struct dwarf2_property_baton
 {
   /* If the property is an indirection, we need to evaluate the location
-     LOCEXPR or LOCLIST in the context of the type REFERENCED_TYPE.
+     in the context of the type REFERENCED_TYPE.
      If NULL, the location is the actual value of the property.  */
   struct type *referenced_type;
   union
 
     /* Location list to be evaluated in the context of REFERENCED_TYPE.  */
     struct dwarf2_loclist_baton loclist;
+
+    /* The location is an offset to REFERENCED_TYPE.  */
+    struct dwarf2_offset_baton offset_info;
   };
 };
 
 
 
       target_die = follow_die_ref (die, attr, &target_cu);
       target_attr = dwarf2_attr (target_die, DW_AT_location, target_cu);
+      if (target_attr == NULL)
+       target_attr = dwarf2_attr (target_die, DW_AT_data_member_location,
+                                  target_cu);
       if (target_attr == NULL)
        return 0;
 
-      if (attr_form_is_section_offset (target_attr))
-       {
-         baton = obstack_alloc (obstack, sizeof (*baton));
-         baton->referenced_type = die_type (target_die, target_cu);
-         fill_in_loclist_baton (cu, &baton->loclist, target_attr);
-         prop->data.baton = baton;
-         prop->kind = PROP_LOCLIST;
-         gdb_assert (prop->data.baton != NULL);
-       }
-      else if (attr_form_is_block (target_attr))
-       {
-         baton = obstack_alloc (obstack, sizeof (*baton));
-         baton->referenced_type = die_type (target_die, target_cu);
-         baton->locexpr.per_cu = cu->per_cu;
-         baton->locexpr.size = DW_BLOCK (target_attr)->size;
-         baton->locexpr.data = DW_BLOCK (target_attr)->data;
-         prop->data.baton = baton;
-         prop->kind = PROP_LOCEXPR;
-         gdb_assert (prop->data.baton != NULL);
-       }
-      else
+      switch (target_attr->name)
        {
-         dwarf2_invalid_attrib_class_complaint ("DW_AT_location",
-                                                "dynamic property");
-         return 0;
+         case DW_AT_location:
+           if (attr_form_is_section_offset (target_attr))
+             {
+               baton = obstack_alloc (obstack, sizeof (*baton));
+               baton->referenced_type = die_type (target_die, target_cu);
+               fill_in_loclist_baton (cu, &baton->loclist, target_attr);
+               prop->data.baton = baton;
+               prop->kind = PROP_LOCLIST;
+               gdb_assert (prop->data.baton != NULL);
+             }
+           else if (attr_form_is_block (target_attr))
+             {
+               baton = obstack_alloc (obstack, sizeof (*baton));
+               baton->referenced_type = die_type (target_die, target_cu);
+               baton->locexpr.per_cu = cu->per_cu;
+               baton->locexpr.size = DW_BLOCK (target_attr)->size;
+               baton->locexpr.data = DW_BLOCK (target_attr)->data;
+               prop->data.baton = baton;
+               prop->kind = PROP_LOCEXPR;
+               gdb_assert (prop->data.baton != NULL);
+             }
+           else
+             {
+               dwarf2_invalid_attrib_class_complaint ("DW_AT_location",
+                                                      "dynamic property");
+               return 0;
+             }
+           break;
+         case DW_AT_data_member_location:
+           {
+             LONGEST offset;
+
+             if (!handle_data_member_location (target_die, target_cu,
+                                               &offset))
+               return 0;
+
+             baton = obstack_alloc (obstack, sizeof (*baton));
+             baton->referenced_type = get_die_type (target_die->parent,
+                                                    target_cu);
+             baton->offset_info.offset = offset;
+             baton->offset_info.type = die_type (target_die, target_cu);
+             prop->data.baton = baton;
+             prop->kind = PROP_ADDR_OFFSET;
+             break;
+           }
        }
     }
   else if (attr_form_is_constant (attr))
 
   return is_dynamic_type_internal (type, 1);
 }
 
-static struct type *resolve_dynamic_type_internal (struct type *type,
-                                                  CORE_ADDR addr,
-                                                  int top_level);
+static struct type *resolve_dynamic_type_internal
+  (struct type *type, struct property_addr_info *addr_stack, int top_level);
 
-/* Given a dynamic range type (dyn_range_type) and address,
-   return a static version of that type.  */
+/* Given a dynamic range type (dyn_range_type) and a stack of
+   struct property_addr_info elements, return a static version
+   of that type.  */
 
 static struct type *
-resolve_dynamic_range (struct type *dyn_range_type, CORE_ADDR addr)
+resolve_dynamic_range (struct type *dyn_range_type,
+                      struct property_addr_info *addr_stack)
 {
   CORE_ADDR value;
   struct type *static_range_type, *static_target_type;
   gdb_assert (TYPE_CODE (dyn_range_type) == TYPE_CODE_RANGE);
 
   prop = &TYPE_RANGE_DATA (dyn_range_type)->low;
-  if (dwarf2_evaluate_property (prop, addr, &value))
+  if (dwarf2_evaluate_property (prop, addr_stack, &value))
     {
       low_bound.kind = PROP_CONST;
       low_bound.data.const_val = value;
     }
 
   prop = &TYPE_RANGE_DATA (dyn_range_type)->high;
-  if (dwarf2_evaluate_property (prop, addr, &value))
+  if (dwarf2_evaluate_property (prop, addr_stack, &value))
     {
       high_bound.kind = PROP_CONST;
       high_bound.data.const_val = value;
 
   static_target_type
     = resolve_dynamic_type_internal (TYPE_TARGET_TYPE (dyn_range_type),
-                                    addr, 0);
+                                    addr_stack, 0);
   static_range_type = create_range_type (copy_type (dyn_range_type),
                                         static_target_type,
                                         &low_bound, &high_bound);
 }
 
 /* Resolves dynamic bound values of an array type TYPE to static ones.
-   ADDRESS might be needed to resolve the subrange bounds, it is the location
-   of the associated array.  */
+   ADDR_STACK is a stack of struct property_addr_info to be used
+   if needed during the dynamic resolution.  */
 
 static struct type *
-resolve_dynamic_array (struct type *type, CORE_ADDR addr)
+resolve_dynamic_array (struct type *type,
+                      struct property_addr_info *addr_stack)
 {
   CORE_ADDR value;
   struct type *elt_type;
 
   elt_type = type;
   range_type = check_typedef (TYPE_INDEX_TYPE (elt_type));
-  range_type = resolve_dynamic_range (range_type, addr);
+  range_type = resolve_dynamic_range (range_type, addr_stack);
 
   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 (type), addr_stack);
   else
     elt_type = TYPE_TARGET_TYPE (type);
 
 }
 
 /* Resolve dynamic bounds of members of the union TYPE to static
-   bounds.  */
+   bounds.  ADDR_STACK is a stack of struct property_addr_info
+   to be used if needed during the dynamic resolution.  */
 
 static struct type *
-resolve_dynamic_union (struct type *type, CORE_ADDR addr)
+resolve_dynamic_union (struct type *type,
+                      struct property_addr_info *addr_stack)
 {
   struct type *resolved_type;
   int i;
        continue;
 
       t = resolve_dynamic_type_internal (TYPE_FIELD_TYPE (resolved_type, i),
-                                        addr, 0);
+                                        addr_stack, 0);
       TYPE_FIELD_TYPE (resolved_type, i) = t;
       if (TYPE_LENGTH (t) > max_len)
        max_len = TYPE_LENGTH (t);
 }
 
 /* Resolve dynamic bounds of members of the struct TYPE to static
-   bounds.  */
+   bounds.  ADDR_STACK is a stack of struct property_addr_info to
+   be used if needed during the dynamic resolution.  */
 
 static struct type *
-resolve_dynamic_struct (struct type *type, CORE_ADDR addr)
+resolve_dynamic_struct (struct type *type,
+                       struct property_addr_info *addr_stack)
 {
   struct type *resolved_type;
   int i;
   for (i = 0; i < TYPE_NFIELDS (resolved_type); ++i)
     {
       unsigned new_bit_length;
+      struct property_addr_info pinfo;
 
       if (field_is_static (&TYPE_FIELD (type, i)))
        continue;
 
-      TYPE_FIELD_TYPE (resolved_type, i)
-       = resolve_dynamic_type_internal (TYPE_FIELD_TYPE (resolved_type, i),
-                                        addr, 0);
-
       /* As we know this field is not a static field, the field's
         field_loc_kind should be FIELD_LOC_KIND_BITPOS.  Verify
         this is the case, but only trigger a simple error rather
         that verification indicates a bug in our code, the error
         is not severe enough to suggest to the user he stops
         his debugging session because of it.  */
-      if (TYPE_FIELD_LOC_KIND (resolved_type, i) != FIELD_LOC_KIND_BITPOS)
+      if (TYPE_FIELD_LOC_KIND (type, i) != FIELD_LOC_KIND_BITPOS)
        error (_("Cannot determine struct field location"
                 " (invalid location kind)"));
+
+      pinfo.type = check_typedef (TYPE_FIELD_TYPE (type, i));
+      pinfo.addr = addr_stack->addr;
+      pinfo.next = addr_stack;
+
+      TYPE_FIELD_TYPE (resolved_type, i)
+       = resolve_dynamic_type_internal (TYPE_FIELD_TYPE (resolved_type, i),
+                                        &pinfo, 0);
+      gdb_assert (TYPE_FIELD_LOC_KIND (resolved_type, i)
+                 == FIELD_LOC_KIND_BITPOS);
+
       new_bit_length = TYPE_FIELD_BITPOS (resolved_type, i);
       if (TYPE_FIELD_BITSIZE (resolved_type, i) != 0)
        new_bit_length += TYPE_FIELD_BITSIZE (resolved_type, i);
 /* Worker for resolved_dynamic_type.  */
 
 static struct type *
-resolve_dynamic_type_internal (struct type *type, CORE_ADDR addr,
+resolve_dynamic_type_internal (struct type *type,
+                              struct property_addr_info *addr_stack,
                               int top_level)
 {
   struct type *real_type = check_typedef (type);
     {
       resolved_type = copy_type (type);
       TYPE_TARGET_TYPE (resolved_type)
-       = resolve_dynamic_type_internal (TYPE_TARGET_TYPE (type), addr,
+       = resolve_dynamic_type_internal (TYPE_TARGET_TYPE (type), addr_stack,
                                         top_level);
     }
   else 
        {
        case TYPE_CODE_REF:
          {
-           CORE_ADDR target_addr = read_memory_typed_address (addr, type);
+           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),
-                                              target_addr, top_level);
+                                              &pinfo, top_level);
            break;
          }
 
        case TYPE_CODE_ARRAY:
-         resolved_type = resolve_dynamic_array (type, addr);
+         resolved_type = resolve_dynamic_array (type, addr_stack);
          break;
 
        case TYPE_CODE_RANGE:
-         resolved_type = resolve_dynamic_range (type, addr);
+         resolved_type = resolve_dynamic_range (type, addr_stack);
          break;
 
        case TYPE_CODE_UNION:
-         resolved_type = resolve_dynamic_union (type, addr);
+         resolved_type = resolve_dynamic_union (type, addr_stack);
          break;
 
        case TYPE_CODE_STRUCT:
-         resolved_type = resolve_dynamic_struct (type, addr);
+         resolved_type = resolve_dynamic_struct (type, addr_stack);
          break;
        }
     }
 
   /* Resolve data_location attribute.  */
   prop = TYPE_DATA_LOCATION (resolved_type);
-  if (dwarf2_evaluate_property (prop, addr, &value))
+  if (dwarf2_evaluate_property (prop, addr_stack, &value))
     {
       TYPE_DATA_LOCATION_ADDR (resolved_type) = value;
       TYPE_DATA_LOCATION_KIND (resolved_type) = PROP_CONST;
 struct type *
 resolve_dynamic_type (struct type *type, CORE_ADDR addr)
 {
-  return resolve_dynamic_type_internal (type, addr, 1);
+  struct property_addr_info pinfo = {check_typedef (type), addr, NULL};
+
+  return resolve_dynamic_type_internal (type, &pinfo, 1);
 }
 
 /* Find the real type of TYPE.  This function returns the real type,
 
   {
     PROP_UNDEFINED, /* Not defined.  */
     PROP_CONST,     /* Constant.  */
+    PROP_ADDR_OFFSET, /* Address offset.  */
     PROP_LOCEXPR,   /* Location expression.  */
     PROP_LOCLIST    /* Location list.  */
   } kind;
 
+2015-01-29  Joel Brobecker  <brobecker@adacore.com>
+
+       * gdb.ada/disc_arr_bound: New testcase.
+
 2015-01-29  Joel Brobecker  <brobecker@adacore.com>
 
        * gdb.ada/mi_var_array: New testcase.
 
--- /dev/null
+# Copyright 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_n612_026
+
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug ]] != "" } {
+  return -1
+}
+
+clean_restart ${testfile}
+
+set bp_location [gdb_get_line_number "STOP" ${testdir}/foo_n612_026.adb]
+if ![runto "foo_n612_026.adb:$bp_location" ] then {
+  perror "Couldn't run ${testfile}"
+  return
+}
+
+gdb_test "print r" \
+         " = \\(n => 10, a => \\(10, 20, 30, 40, 50, 60, 70, 80, 90, 100\\)\\)"
+
+gdb_test "print r.a" \
+         " = \\(10, 20, 30, 40, 50, 60, 70, 80, 90, 100\\)"
 
--- /dev/null
+--  Copyright 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/>.
+
+with Pck; use Pck;
+
+procedure Foo_N612_026 is
+   R : Record_Type := Get (10);
+begin
+   Do_Nothing (R'Address); -- STOP
+end Foo_N612_026;
 
--- /dev/null
+--  Copyright 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/>.
+
+package body Pck is
+
+   function Get (N : Integer) return Record_Type is
+      Result : Record_Type (N);
+   begin
+      for I in 1 .. N loop
+         Result.A (I) := 10 * I;
+      end loop;
+      return Result;
+   end Get;
+
+   procedure Do_Nothing (A : System.Address) is
+   begin
+      null;
+   end Do_Nothing;
+
+end Pck;
 
--- /dev/null
+--  Copyright 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/>.
+
+with System;
+
+package Pck is
+
+   type Array_Type is array (Integer range <>) of Integer;
+   type Record_Type (N : Integer) is record
+      A : Array_Type (1 .. N);
+   end record;
+
+   function Get (N : Integer) return Record_Type;
+
+   procedure Do_Nothing (A : System.Address);
+
+end Pck;