Jakub,

First, thank you very much for reviewing this set of patches.

I think it's better to start with an answer to your last mail:

On 10/03/2014 11:20 AM, Jakub Jelinek wrote:
What kind of more complex expressions do you need and why?

GNAT can produce array types that make sense only as part of a record type and whose bounds are equal to members of this record type. Such ARRAY_TYPE nodes get generated from the kind of example you could see on the Dwarf-Discuss mailing list:

    type Array_Type is array (Integer range <>) of Integer;
    type Record_Type (N : Integer) is record
       A : Array_Type (1 .. N);
    end record;

In this case, the "A" field's type is an ARRAY_TYPE node whose upper bound is:

    COMPONENT_REF (PLACEHOLDER_EXPR (<Record_Type>),
                   FIELD_DECL("N"))

Upcoming patches will actually extend the need to handle more complex expressions: Ada arrays can contain dynamically-sized objects (their size is bounded, though). As a consequence, debuggers need these arrays to have a DW_AT_byte_stride attribute in order to decode them. The size expressions that describe the array stride in GCC can contain fairly complex operations such as unsigned divisions, unsigned comparisons, bitwise operations, calls to size functions (see stor-layout.c:self_referencial_size).

On 10/03/2014 11:18 AM, Jakub Jelinek wrote:
+ /* Instead of producing a dedicated DW_TAG_array_type DIE for  this type, let
+    the circuitry wrap the main variant with DIEs for qualifiers  (for
+    instance: DW_TAG_const_type, ...). */
+ if (type != TYPE_MAIN_VARIANT (type))
+     {
+       gen_type_die (TYPE_MAIN_VARIANT (type), context_die);
+       return;
+     }

I don't like this, can you explain why? I'd say that if you only
want to see TYPE_MAIN_VARIANT here, it should be responsibility of
the callers to ensure that.

Agreed. I have updated the patch to:

 1. remove this hunk;
2. in gen_type_die_with_usage, which is the only caller, move the type_main_variant call on "type" right before the array descriptors handling.

@@ -19941,7 +19991,8 @@ gen_type_die_with_usage (tree type,  dw_die_ref 
context_die,
    /* If this is an array type with hidden descriptor, handle itfirst.  */
    if (!TREE_ASM_WRITTEN (type)
        && lang_hooks.types.get_array_descr_info
-      && lang_hooks.types.get_array_descr_info (type, &info)
+      && lang_hooks.types.get_array_descr_info (type,
+                                               init_array_descr_info (&info))

Just memset it to 0 instead?

Sure. I was not sure about whether is was considered good style, but it's done, now.

+  enum array_descr_ordering ordering;
    tree element_type;
    tree base_decl;
    tree data_location;
    tree allocated;
    tree associated;
+

Why the extra vertical space?
    struct array_descr_dimen
      {

It made the separation between "global" and "dimension-local" information clearer to me. As I suppose you don't like it and as there is already one indentation level, I removed it.

        * dwarf2out.c (gen_type_die_with_usage): Enable the array lang-hook
        even when (dwarf_version < 3 && dwarf_strict).
        (gen_descr_array_die): Do not output DW_AT_data_locationn,
        DW_AT_associated, DW_AT_allocated and DW_AT_byte_stride DWARF
        attributes when (dwarf_version < 3 && dwarf_strict).

This patch sounds very wrong.  DW_OP_push_object_address is not in DWARF2
either, and that is the basis of all the fields, so there is reallynothing
you can really output correctly for DWARF2.  It isn't the default on sane
targets, where GCC defaults to DWARF4 these days, so why bother?

Generating DW_OP_push_object_address in strict DWARF2 mode is indeed a bug (patch is adjusted). However, if I understand correctly all fields/attributes don't have to rely on it.

In the case of the first Ada example I quoted above, such an operation would not be emitted: instead, add_bound_info/add_scalar_info are going to output a DW_AT_upper_bound attribute that is a reference to another DIE. This is valid DWARF2 and, I think, justifies enabling the language hook in this case.

We have several platforms whose default to strict DWARF2. These are quite used platforms on which some DWARF consumers crash when provided DIEs and tags they do not handle.

gcc/fortran/
        * trans-types.c (gfc_get_array_descr_info): Use PLACEHOLDER_EXPR nodes
        instead of VAR_DECL ones in type-related expressions.  Remove base_decl
        initialization.

Ugh, I must say I don't like PLACEHOLDER_EXPRs at all.

Why so? I know that as far as supported front-ends are concerned, PLACEHOLDE_EXPR nodes are used only in GNAT, but it seems to me they describe the best what object the bound/stride/allocated/associated expressions (self-)reference.

I have attached to this mail the 3 patches that are updated thanks to your (Jakub and Jason's) comments and run successfuly the GCC testsuite on x86_64-pc-linux-gnu.

Thanks again for revewing!

--
Pierre-Marie de Rodat
>From 5ae605a24f0df5a8963fa84d0c07c278542977f1 Mon Sep 17 00:00:00 2001
From: Pierre-Marie de Rodat <dero...@adacore.com>
Date: Wed, 5 Feb 2014 12:00:02 +0100
Subject: [PATCH 1/5] Complete information generated through the array
 descriptor language hook

gcc/
	* dwarf2out.h (enum array_descr_ordering): New.
	(array_descr_dimen): Add a bounds_type structure field.
	(struct array_descr_info): Add a field to hold index type information
	and another one to hold ordering information.
	* dwarf2out.c (gen_type_die_with_usage): Get the main variant before
	invoking the array descriptor language hook.  Initialize the
	array_descr_info structure before calling the lang-hook.
	(gen_descr_array_type_die): Use gen_type_die if not processing the
	main type variant.  Replace Fortran-specific code with generic one
	using this new field.  Add a GNAT descriptive type, if any.  Output
	type information for the array bound subrange, if any.

gcc/fortran
	* trans-types.c (gfc_get_array_descr_info): Describe all Fortran
	arrays with column major ordering.
---
 gcc/dwarf2out.c           |   52 +++++++++++++++++++++++++++++----------------
 gcc/dwarf2out.h           |   12 +++++++++++
 gcc/fortran/trans-types.c |    1 +
 3 files changed, 47 insertions(+), 18 deletions(-)

diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 59c05ed..39b859e 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -17401,18 +17401,25 @@ static void
 gen_descr_array_type_die (tree type, struct array_descr_info *info,
 			  dw_die_ref context_die)
 {
-  dw_die_ref scope_die = scope_die_for (type, context_die);
-  dw_die_ref array_die;
+  const dw_die_ref scope_die = scope_die_for (type, context_die);
+  const dw_die_ref array_die = new_die (DW_TAG_array_type, scope_die, type);
   int dim;
 
-  array_die = new_die (DW_TAG_array_type, scope_die, type);
   add_name_attribute (array_die, type_tag (type));
   equate_type_number_to_die (type, array_die);
 
-  /* For Fortran multidimensional arrays use DW_ORD_col_major ordering.  */
-  if (is_fortran ()
-      && info->ndimensions >= 2)
-    add_AT_unsigned (array_die, DW_AT_ordering, DW_ORD_col_major);
+  if (info->ndimensions > 1)
+    switch (info->ordering)
+      {
+      case array_descr_ordering_row_major:
+	add_AT_unsigned (array_die, DW_AT_ordering, DW_ORD_row_major);
+	break;
+      case array_descr_ordering_column_major:
+	add_AT_unsigned (array_die, DW_AT_ordering, DW_ORD_col_major);
+	break;
+      default:
+	break;
+      }
 
   if (info->data_location)
     add_descr_info_field (array_die, DW_AT_data_location, info->data_location,
@@ -17424,11 +17431,17 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info,
     add_descr_info_field (array_die, DW_AT_allocated, info->allocated,
 			  info->base_decl);
 
+  add_gnat_descriptive_type_attribute (array_die, type, context_die);
+
   for (dim = 0; dim < info->ndimensions; dim++)
     {
       dw_die_ref subrange_die
 	= new_die (DW_TAG_subrange_type, array_die, NULL);
 
+      if (info->dimen[dim].bounds_type)
+	add_type_attribute (subrange_die,
+			    info->dimen[dim].bounds_type, 0,
+			    context_die);
       if (info->dimen[dim].lower_bound)
 	{
 	  /* If it is the default value, omit it.  */
@@ -19986,17 +19999,6 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
       return;
     }
 
-  /* If this is an array type with hidden descriptor, handle it first.  */
-  if (!TREE_ASM_WRITTEN (type)
-      && lang_hooks.types.get_array_descr_info
-      && lang_hooks.types.get_array_descr_info (type, &info)
-      && (dwarf_version >= 3 || !dwarf_strict))
-    {
-      gen_descr_array_type_die (type, &info, context_die);
-      TREE_ASM_WRITTEN (type) = 1;
-      return;
-    }
-
   /* We are going to output a DIE to represent the unqualified version
      of this type (i.e. without any const or volatile qualifiers) so
      get the main variant (i.e. the unqualified version) of this type
@@ -20005,6 +20007,20 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
   if (TREE_CODE (type) != VECTOR_TYPE)
     type = type_main_variant (type);
 
+  /* If this is an array type with hidden descriptor, handle it first.  */
+  if (!TREE_ASM_WRITTEN (type)
+      && lang_hooks.types.get_array_descr_info
+      && (dwarf_version >= 3 || !dwarf_strict))
+    {
+      memset (&info, 0, sizeof (info));
+      if (lang_hooks.types.get_array_descr_info (type, &info))
+	{
+	  gen_descr_array_type_die (type, &info, context_die);
+	  TREE_ASM_WRITTEN (type) = 1;
+	  return;
+	}
+    }
+
   if (TREE_ASM_WRITTEN (type))
     return;
 
diff --git a/gcc/dwarf2out.h b/gcc/dwarf2out.h
index 7843e0a..0cf290c 100644
--- a/gcc/dwarf2out.h
+++ b/gcc/dwarf2out.h
@@ -261,9 +261,17 @@ extern void dwarf2out_set_demangle_name_func (const char *(*) (const char *));
 extern void dwarf2out_vms_debug_main_pointer (void);
 #endif
 
+enum array_descr_ordering
+{
+  array_descr_ordering_default,
+  array_descr_ordering_row_major,
+  array_descr_ordering_column_major
+};
+
 struct array_descr_info
 {
   int ndimensions;
+  enum array_descr_ordering ordering;
   tree element_type;
   tree base_decl;
   tree data_location;
@@ -271,6 +279,10 @@ struct array_descr_info
   tree associated;
   struct array_descr_dimen
     {
+      /* GCC uses sizetype for array indices, so lower_bound and upper_bound
+	 will likely be "sizetype" values. However, bounds may have another
+	 type in the original source code.  */
+      tree bounds_type;
       tree lower_bound;
       tree upper_bound;
       tree stride;
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index 6bfe14c..1bfe920 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -3036,6 +3036,7 @@ gfc_get_array_descr_info (const_tree type, struct array_descr_info *info)
 
   memset (info, '\0', sizeof (*info));
   info->ndimensions = rank;
+  info->ordering = array_descr_ordering_column_major;
   info->element_type = etype;
   ptype = build_pointer_type (gfc_array_index_type);
   base_decl = GFC_TYPE_ARRAY_BASE_DECL (type, indirect);
-- 
1.7.10.4

>From a292821505560a7a27b7446db6ed439360da940b Mon Sep 17 00:00:00 2001
From: Pierre-Marie de Rodat <dero...@adacore.com>
Date: Fri, 7 Feb 2014 16:09:21 +0100
Subject: [PATCH 2/5] Enable the array descr language hook for all DWARF
 versions

	* dwarf2out.c (gen_type_die_with_usage): Enable the array lang-hook
	even when (dwarf_version < 3 && dwarf_strict).
	(gen_descr_array_die): Do not output DW_AT_data_locationn,
	DW_AT_associated, DW_AT_allocated and DW_AT_byte_stride DWARF
	attributes when (dwarf_version < 3 && dwarf_strict).
---
 gcc/dwarf2out.c |   34 ++++++++++++++++++++--------------
 1 file changed, 20 insertions(+), 14 deletions(-)

diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 39b859e..79cd8f5 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -17421,15 +17421,19 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info,
 	break;
       }
 
-  if (info->data_location)
-    add_descr_info_field (array_die, DW_AT_data_location, info->data_location,
-			  info->base_decl);
-  if (info->associated)
-    add_descr_info_field (array_die, DW_AT_associated, info->associated,
-			  info->base_decl);
-  if (info->allocated)
-    add_descr_info_field (array_die, DW_AT_allocated, info->allocated,
-			  info->base_decl);
+  if (dwarf_version >= 3 || !dwarf_strict)
+    {
+      if (info->data_location)
+	add_descr_info_field (array_die, DW_AT_data_location,
+			      info->data_location,
+			      info->base_decl);
+      if (info->associated)
+	add_descr_info_field (array_die, DW_AT_associated, info->associated,
+			      info->base_decl);
+      if (info->allocated)
+	add_descr_info_field (array_die, DW_AT_allocated, info->allocated,
+			      info->base_decl);
+    }
 
   add_gnat_descriptive_type_attribute (array_die, type, context_die);
 
@@ -17460,10 +17464,13 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info,
 	add_descr_info_field (subrange_die, DW_AT_upper_bound,
 			      info->dimen[dim].upper_bound,
 			      info->base_decl);
-      if (info->dimen[dim].stride)
-	add_descr_info_field (subrange_die, DW_AT_byte_stride,
-			      info->dimen[dim].stride,
-			      info->base_decl);
+      if (dwarf_version >= 3 || !dwarf_strict)
+	{
+	  if (info->dimen[dim].stride)
+	    add_descr_info_field (subrange_die, DW_AT_byte_stride,
+				  info->dimen[dim].stride,
+				  info->base_decl);
+	}
     }
 
   gen_type_die (info->element_type, context_die);
@@ -20010,7 +20017,6 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
   /* If this is an array type with hidden descriptor, handle it first.  */
   if (!TREE_ASM_WRITTEN (type)
       && lang_hooks.types.get_array_descr_info
-      && (dwarf_version >= 3 || !dwarf_strict))
     {
       memset (&info, 0, sizeof (info));
       if (lang_hooks.types.get_array_descr_info (type, &info))
-- 
1.7.10.4

>From 7e09d1d93f8edcc556b21e4f39fcb3d3252b4f31 Mon Sep 17 00:00:00 2001
From: Pierre-Marie de Rodat <dero...@adacore.com>
Date: Mon, 9 Jun 2014 15:13:45 +0200
Subject: [PATCH 5/5] dwarf2out.c: do not short-circuit add_bound_info in
 array descr. lang-hook

gcc/
	* dwarf2out.h (struct array_descr_info): Remove the base_decl field.
	* dwarf2out.c (enum dw_scalar_form): New.
	(add_scalar_info): New.
	(loc_list_from_tree): Handle PLACEHOLDER_EXPR nodes for type-related
	expressions.
	(add_bound_info): Use add_scalar_info.
	(descr_info_loc): Remove.
	(add_descr_info_field): Remove.
	(gen_descr_array_type_die): Switch add_descr_info_field calls into
	add_scalar_info/add_bound_info ones.

gcc/ada
	* gcc-interface/misc.c (gnat_get_array_descr_info): Remove base_decl
	initialization.

gcc/fortran/
	* trans-types.c (gfc_get_array_descr_info): Use PLACEHOLDER_EXPR
	nodes instead of VAR_DECL ones in type-related expressions.  Remove
	base_decl initialization.
---
 gcc/ada/gcc-interface/misc.c |    1 -
 gcc/dwarf2out.c              |  438 ++++++++++++++++++++----------------------
 gcc/dwarf2out.h              |    1 -
 gcc/fortran/trans-types.c    |    7 +-
 4 files changed, 208 insertions(+), 239 deletions(-)

diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c
index 7449ef9..0661d49 100644
--- a/gcc/ada/gcc-interface/misc.c
+++ b/gcc/ada/gcc-interface/misc.c
@@ -658,7 +658,6 @@ gnat_get_array_descr_info (const_tree type, struct array_descr_info *info)
   info->ordering = (convention_fortran_p
 		    ? array_descr_ordering_column_major
 		    : array_descr_ordering_row_major);
-  info->base_decl = NULL_TREE;
   info->data_location = NULL_TREE;
   info->allocated = NULL_TREE;
   info->associated = NULL_TREE;
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index c334e9f..bd5fee2 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -2981,6 +2981,15 @@ static bool frame_pointer_fb_offset_valid;
 
 static vec<dw_die_ref> base_types;
 
+/* Flags to represent a set of attribute classes for attributes that represent
+   a scalar value (bounds, pointers, ...).  */
+enum dw_scalar_form
+{
+  dw_scalar_form_constant = 0x01,
+  dw_scalar_form_exprloc = 0x02,
+  dw_scalar_form_reference = 0x04
+};
+
 /* Forward declarations for functions defined in this file.  */
 
 static int is_pseudo_reg (const_rtx);
@@ -3186,6 +3195,7 @@ static bool tree_add_const_value_attribute_for_decl (dw_die_ref, tree);
 static void add_name_attribute (dw_die_ref, const char *);
 static void add_gnat_descriptive_type_attribute (dw_die_ref, tree, dw_die_ref);
 static void add_comp_dir_attribute (dw_die_ref);
+static void add_scalar_info (dw_die_ref, enum dwarf_attribute, tree, int);
 static void add_bound_info (dw_die_ref, enum dwarf_attribute, tree);
 static void add_subscript_info (dw_die_ref, tree, bool);
 static void add_byte_size_attribute (dw_die_ref, tree);
@@ -14319,11 +14329,24 @@ loc_list_from_tree (tree loc, int want_address)
 
     case PLACEHOLDER_EXPR:
       /* This case involves extracting fields from an object to determine the
-	 position of other fields.  We don't try to encode this here.  The
-	 only user of this is Ada, which encodes the needed information using
-	 the names of types.  */
-      expansion_failed (loc, NULL_RTX, "PLACEHOLDER_EXPR");
-      return 0;
+	 position of other fields. It is supposed to appear only as the first
+	 operand of COMPONENT_REF nodes.  */
+      if (TREE_CODE (TREE_TYPE (loc)) == RECORD_TYPE
+	  && want_address >= 1)
+	{
+	  if (dwarf_version >= 3 || !dwarf_strict)
+	    {
+	      ret = new_loc_descr (DW_OP_push_object_address, 0, 0);
+	      have_address = 1;
+	      break;
+	    }
+	  else
+	    return NULL;
+	}
+      else
+	expansion_failed (loc, NULL_RTX,
+			  "PLACEHOLDER_EXPR for a non-structure");
+      break;
 
     case CALL_EXPR:
       expansion_failed (loc, NULL_RTX, "CALL_EXPR");
@@ -16432,6 +16455,141 @@ add_comp_dir_attribute (dw_die_ref die)
     add_AT_string (die, DW_AT_comp_dir, wd);
 }
 
+/* Given a tree node VALUE describing a scalar attribute ATTR (i.e. a bound, a
+   pointer computation, ...), output a representation for that bound according
+   to the accepted FORMS (see enum dw_scalar_form) and add it to DIE.  */
+
+static void
+add_scalar_info (dw_die_ref die, enum dwarf_attribute attr, tree value,
+		 int forms)
+{
+  dw_die_ref ctx, decl_die;
+  dw_loc_list_ref list;
+
+  bool strip_conversions = true;
+
+  while (strip_conversions)
+    switch (TREE_CODE (value))
+      {
+      case ERROR_MARK:
+      case SAVE_EXPR:
+	return;
+
+      CASE_CONVERT:
+      case VIEW_CONVERT_EXPR:
+	value = TREE_OPERAND (value, 0);
+	break;
+
+      default:
+	strip_conversions = false;
+	break;
+      }
+
+  /* If possible and permitted, output the attribute as a constant.  */
+  if ((forms & dw_scalar_form_constant) != 0
+      && TREE_CODE (value) == INTEGER_CST)
+    {
+      unsigned int prec = simple_type_size_in_bits (TREE_TYPE (value));
+
+      /* If HOST_WIDE_INT is big enough then represent the bound as
+	 a constant value.  We need to choose a form based on
+	 whether the type is signed or unsigned.  We cannot just
+	 call add_AT_unsigned if the value itself is positive
+	 (add_AT_unsigned might add the unsigned value encoded as
+	 DW_FORM_data[1248]).  Some DWARF consumers will lookup the
+	 bounds type and then sign extend any unsigned values found
+	 for signed types.  This is needed only for
+	 DW_AT_{lower,upper}_bound, since for most other attributes,
+	 consumers will treat DW_FORM_data[1248] as unsigned values,
+	 regardless of the underlying type.  */
+      if (prec <= HOST_BITS_PER_WIDE_INT
+	       || tree_fits_uhwi_p (value))
+	{
+	  if (TYPE_UNSIGNED (TREE_TYPE (value)))
+	    add_AT_unsigned (die, attr, TREE_INT_CST_LOW (value));
+	  else
+	    add_AT_int (die, attr, TREE_INT_CST_LOW (value));
+	}
+      else
+	/* Otherwise represent the bound as an unsigned value with
+	   the precision of its type.  The precision and signedness
+	   of the type will be necessary to re-interpret it
+	   unambiguously.  */
+	add_AT_wide (die, attr, value);
+    }
+
+  /* Otherwise, if it's possible and permitted too, output a reference to
+     another DIE.  */
+  if ((forms & dw_scalar_form_reference) != 0)
+    {
+      tree decl = NULL_TREE;
+
+      /* Some type attributes reference an outer type.  For instance, the upper
+	 bound of an array may reference an embedding record (this happens in
+	 Ada).  */
+      if (TREE_CODE (value) == COMPONENT_REF
+	  && TREE_CODE (TREE_OPERAND (value, 0)) == PLACEHOLDER_EXPR
+	  && TREE_CODE (TREE_OPERAND (value, 1)) == FIELD_DECL)
+	decl = TREE_OPERAND (value, 1);
+
+      else if (TREE_CODE (value) == VAR_DECL
+	       || TREE_CODE (value) == PARM_DECL
+	       || TREE_CODE (value) == RESULT_DECL)
+	decl = value;
+
+      if (decl != NULL_TREE)
+	{
+	  dw_die_ref decl_die = lookup_decl_die (decl);
+
+	  /* ??? Can this happen, or should the variable have been bound
+	     first?  Probably it can, since I imagine that we try to create
+	     the types of parameters in the order in which they exist in
+	     the list, and won't have created a forward reference to a
+	     later parameter.  */
+	  if (decl_die != NULL)
+	    {
+	      add_AT_die_ref (die, attr, decl_die);
+	      return;
+	    }
+	}
+    }
+
+  /* Last chance: try to create a stack operation procedure to evaluate the
+     value.  Do nothing if even that is not possible or permitted.  */
+  if ((forms & dw_scalar_form_exprloc) == 0)
+    return;
+
+  list = loc_list_from_tree (value, 2);
+  if (list == NULL || single_element_loc_list_p (list))
+    {
+      /* If this attribute is not a reference nor constant, it is
+	 a DWARF expression rather than location description.  For that
+	 loc_list_from_tree (value, 0) is needed.  */
+      dw_loc_list_ref list2 = loc_list_from_tree (value, 0);
+      if (list2 && single_element_loc_list_p (list2))
+	{
+	  add_AT_loc (die, attr, list2->expr);
+	  return;
+	}
+    }
+
+  /* If that failed to give a single element location list, fall back to
+     outputting this as a reference... still if permitted.  */
+  if (list == NULL || (forms & dw_scalar_form_reference) == 0)
+    return;
+
+  if (current_function_decl == 0)
+    ctx = comp_unit_die ();
+  else
+    ctx = lookup_decl_die (current_function_decl);
+
+  decl_die = new_die (DW_TAG_variable, ctx, value);
+  add_AT_flag (decl_die, DW_AT_artificial, 1);
+  add_type_attribute (decl_die, TREE_TYPE (value), TYPE_QUAL_CONST, ctx);
+  add_AT_location_description (decl_die, DW_AT_location, list);
+  add_AT_die_ref (die, attr, decl_die);
+}
+
 /* Return the default for DW_AT_lower_bound, or -1 if there is not any
    default.  */
 
@@ -16473,121 +16631,40 @@ lower_bound_default (void)
    a representation for that bound.  */
 
 static void
-add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr, tree bound)
+add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr,
+		tree bound)
 {
-  switch (TREE_CODE (bound))
-    {
-    case ERROR_MARK:
-      return;
+  int dflt;
 
-    /* All fixed-bounds are represented by INTEGER_CST nodes.  */
-    case INTEGER_CST:
+  while (1)
+    switch (TREE_CODE (bound))
       {
-	unsigned int prec = simple_type_size_in_bits (TREE_TYPE (bound));
-	int dflt;
+      /* Strip all conversions.  */
+      CASE_CONVERT:
+      case VIEW_CONVERT_EXPR:
+	bound = TREE_OPERAND (bound, 0);
+	break;
 
-	/* Use the default if possible.  */
+      /* All fixed-bounds are represented by INTEGER_CST nodes.  Lower bounds
+	 are even omitted when they are the default.  */
+      case INTEGER_CST:
+	/* If the value for this bound is the default one, we can even omit the
+	   attribute.  */
 	if (bound_attr == DW_AT_lower_bound
 	    && tree_fits_shwi_p (bound)
 	    && (dflt = lower_bound_default ()) != -1
 	    && tree_to_shwi (bound) == dflt)
-	  ;
-
-	/* If HOST_WIDE_INT is big enough then represent the bound as
-	   a constant value.  We need to choose a form based on
-	   whether the type is signed or unsigned.  We cannot just
-	   call add_AT_unsigned if the value itself is positive
-	   (add_AT_unsigned might add the unsigned value encoded as
-	   DW_FORM_data[1248]).  Some DWARF consumers will lookup the
-	   bounds type and then sign extend any unsigned values found
-	   for signed types.  This is needed only for
-	   DW_AT_{lower,upper}_bound, since for most other attributes,
-	   consumers will treat DW_FORM_data[1248] as unsigned values,
-	   regardless of the underlying type.  */
-	else if (prec <= HOST_BITS_PER_WIDE_INT
-		 || tree_fits_uhwi_p (bound))
-	  {
-	    if (TYPE_UNSIGNED (TREE_TYPE (bound)))
-	      add_AT_unsigned (subrange_die, bound_attr,
-			       TREE_INT_CST_LOW (bound));
-	    else
-	      add_AT_int (subrange_die, bound_attr, TREE_INT_CST_LOW (bound));
-	  }
-	else
-	  /* Otherwise represent the bound as an unsigned value with
-	     the precision of its type.  The precision and signedness
-	     of the type will be necessary to re-interpret it
-	     unambiguously.  */
-	  add_AT_wide (subrange_die, bound_attr, bound);
-      }
-      break;
-
-    CASE_CONVERT:
-    case VIEW_CONVERT_EXPR:
-      add_bound_info (subrange_die, bound_attr, TREE_OPERAND (bound, 0));
-      break;
-
-    case SAVE_EXPR:
-      break;
-
-    case VAR_DECL:
-    case PARM_DECL:
-    case RESULT_DECL:
-      {
-	dw_die_ref decl_die = lookup_decl_die (bound);
-
-	/* ??? Can this happen, or should the variable have been bound
-	   first?  Probably it can, since I imagine that we try to create
-	   the types of parameters in the order in which they exist in
-	   the list, and won't have created a forward reference to a
-	   later parameter.  */
-	if (decl_die != NULL)
-	  {
-	    add_AT_die_ref (subrange_die, bound_attr, decl_die);
-	    break;
-	  }
-      }
-      /* FALLTHRU */
-
-    default:
-      {
-	/* Otherwise try to create a stack operation procedure to
-	   evaluate the value of the array bound.  */
-
-	dw_die_ref ctx, decl_die;
-	dw_loc_list_ref list;
-
-	list = loc_list_from_tree (bound, 2);
-	if (list == NULL || single_element_loc_list_p (list))
-	  {
-	    /* If DW_AT_*bound is not a reference nor constant, it is
-	       a DWARF expression rather than location description.
-	       For that loc_list_from_tree (bound, 0) is needed.
-	       If that fails to give a single element list,
-	       fall back to outputting this as a reference anyway.  */
-	    dw_loc_list_ref list2 = loc_list_from_tree (bound, 0);
-	    if (list2 && single_element_loc_list_p (list2))
-	      {
-		add_AT_loc (subrange_die, bound_attr, list2->expr);
-		break;
-	      }
-	  }
-	if (list == NULL)
-	  break;
+	  return;
 
-	if (current_function_decl == 0)
-	  ctx = comp_unit_die ();
-	else
-	  ctx = lookup_decl_die (current_function_decl);
+	/* FALLTHRU */
 
-	decl_die = new_die (DW_TAG_variable, ctx, bound);
-	add_AT_flag (decl_die, DW_AT_artificial, 1);
-	add_type_attribute (decl_die, TREE_TYPE (bound), TYPE_QUAL_CONST, ctx);
-	add_AT_location_description (decl_die, DW_AT_location, list);
-	add_AT_die_ref (subrange_die, bound_attr, decl_die);
-	break;
+      default:
+	add_scalar_info (subrange_die, bound_attr, bound,
+			 dw_scalar_form_constant
+			 | dw_scalar_form_exprloc
+			 | dw_scalar_form_reference);
+	return;
       }
-    }
 }
 
 /* Add subscript info to TYPE_DIE, describing an array TYPE, collapsing
@@ -17375,99 +17452,6 @@ gen_array_type_die (tree type, dw_die_ref context_die)
     add_pubtype (type, array_die);
 }
 
-static dw_loc_descr_ref
-descr_info_loc (tree val, tree base_decl)
-{
-  HOST_WIDE_INT size;
-  dw_loc_descr_ref loc, loc2;
-  enum dwarf_location_atom op;
-
-  if (val == base_decl)
-    return new_loc_descr (DW_OP_push_object_address, 0, 0);
-
-  switch (TREE_CODE (val))
-    {
-    CASE_CONVERT:
-      return descr_info_loc (TREE_OPERAND (val, 0), base_decl);
-    case VAR_DECL:
-      return loc_descriptor_from_tree (val, 0);
-    case INTEGER_CST:
-      if (tree_fits_shwi_p (val))
-	return int_loc_descriptor (tree_to_shwi (val));
-      break;
-    case INDIRECT_REF:
-      size = int_size_in_bytes (TREE_TYPE (val));
-      if (size < 0)
-	break;
-      loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl);
-      if (!loc)
-	break;
-      if (size == DWARF2_ADDR_SIZE)
-	add_loc_descr (&loc, new_loc_descr (DW_OP_deref, 0, 0));
-      else
-	add_loc_descr (&loc, new_loc_descr (DW_OP_deref_size, size, 0));
-      return loc;
-    case POINTER_PLUS_EXPR:
-    case PLUS_EXPR:
-      if (tree_fits_uhwi_p (TREE_OPERAND (val, 1))
-	  && tree_to_uhwi (TREE_OPERAND (val, 1)) < 16384)
-	{
-	  loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl);
-	  if (!loc)
-	    break;
-	  loc_descr_plus_const (&loc, tree_to_shwi (TREE_OPERAND (val, 1)));
-	}
-      else
-	{
-	  op = DW_OP_plus;
-	do_binop:
-	  loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl);
-	  if (!loc)
-	    break;
-	  loc2 = descr_info_loc (TREE_OPERAND (val, 1), base_decl);
-	  if (!loc2)
-	    break;
-	  add_loc_descr (&loc, loc2);
-	  add_loc_descr (&loc2, new_loc_descr (op, 0, 0));
-	}
-      return loc;
-    case MINUS_EXPR:
-      op = DW_OP_minus;
-      goto do_binop;
-    case MULT_EXPR:
-      op = DW_OP_mul;
-      goto do_binop;
-    case EQ_EXPR:
-      op = DW_OP_eq;
-      goto do_binop;
-    case NE_EXPR:
-      op = DW_OP_ne;
-      goto do_binop;
-    default:
-      break;
-    }
-  return NULL;
-}
-
-static void
-add_descr_info_field (dw_die_ref die, enum dwarf_attribute attr,
-		      tree val, tree base_decl)
-{
-  dw_loc_descr_ref loc;
-
-  if (tree_fits_shwi_p (val))
-    {
-      add_AT_unsigned (die, attr, tree_to_shwi (val));
-      return;
-    }
-
-  loc = descr_info_loc (val, base_decl);
-  if (!loc)
-    return;
-
-  add_AT_loc (die, attr, loc);
-}
-
 /* This routine generates DIE for array with hidden descriptor, details
    are filled into *info by a langhook.  */
 
@@ -17498,15 +17482,18 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info,
   if (dwarf_version >= 3 || !dwarf_strict)
     {
       if (info->data_location)
-	add_descr_info_field (array_die, DW_AT_data_location,
-			      info->data_location,
-			      info->base_decl);
+	add_scalar_info (array_die, DW_AT_data_location, info->data_location,
+			 dw_scalar_form_exprloc);
       if (info->associated)
-	add_descr_info_field (array_die, DW_AT_associated, info->associated,
-			      info->base_decl);
+	add_scalar_info (array_die, DW_AT_associated, info->associated,
+			 dw_scalar_form_constant
+			 | dw_scalar_form_exprloc
+			 | dw_scalar_form_reference);
       if (info->allocated)
-	add_descr_info_field (array_die, DW_AT_allocated, info->allocated,
-			      info->base_decl);
+	add_scalar_info (array_die, DW_AT_allocated, info->allocated,
+			 dw_scalar_form_constant
+			 | dw_scalar_form_exprloc
+			 | dw_scalar_form_reference);
     }
 
   add_gnat_descriptive_type_attribute (array_die, type, context_die);
@@ -17521,30 +17508,17 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info,
 			    info->dimen[dim].bounds_type, 0,
 			    context_die);
       if (info->dimen[dim].lower_bound)
-	{
-	  /* If it is the default value, omit it.  */
-	  int dflt;
-
-	  if (tree_fits_shwi_p (info->dimen[dim].lower_bound)
-	      && (dflt = lower_bound_default ()) != -1
-	      && tree_to_shwi (info->dimen[dim].lower_bound) == dflt)
-	    ;
-	  else
-	    add_descr_info_field (subrange_die, DW_AT_lower_bound,
-				  info->dimen[dim].lower_bound,
-				  info->base_decl);
-	}
+	add_bound_info (subrange_die, DW_AT_lower_bound,
+			info->dimen[dim].lower_bound);
       if (info->dimen[dim].upper_bound)
-	add_descr_info_field (subrange_die, DW_AT_upper_bound,
-			      info->dimen[dim].upper_bound,
-			      info->base_decl);
-      if (dwarf_version >= 3 || !dwarf_strict)
-	{
-	  if (info->dimen[dim].stride)
-	    add_descr_info_field (subrange_die, DW_AT_byte_stride,
-				  info->dimen[dim].stride,
-				  info->base_decl);
-	}
+	add_bound_info (subrange_die, DW_AT_upper_bound,
+			info->dimen[dim].upper_bound);
+      if ((dwarf_version >= 3 || !dwarf_strict) && info->dimen[dim].stride)
+	add_scalar_info (subrange_die, DW_AT_byte_stride,
+			 info->dimen[dim].stride,
+			 dw_scalar_form_constant
+			 | dw_scalar_form_exprloc
+			 | dw_scalar_form_reference);
     }
 
   gen_type_die (info->element_type, context_die);
diff --git a/gcc/dwarf2out.h b/gcc/dwarf2out.h
index a73fdb4..b37ba5c 100644
--- a/gcc/dwarf2out.h
+++ b/gcc/dwarf2out.h
@@ -274,7 +274,6 @@ struct array_descr_info
   int ndimensions;
   enum array_descr_ordering ordering;
   tree element_type;
-  tree base_decl;
   tree data_location;
   tree allocated;
   tree associated;
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index 1bfe920..a108e81 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -3042,13 +3042,10 @@ gfc_get_array_descr_info (const_tree type, struct array_descr_info *info)
   base_decl = GFC_TYPE_ARRAY_BASE_DECL (type, indirect);
   if (!base_decl)
     {
-      base_decl = make_node (DEBUG_EXPR_DECL);
-      DECL_ARTIFICIAL (base_decl) = 1;
-      TREE_TYPE (base_decl) = indirect ? build_pointer_type (ptype) : ptype;
-      DECL_MODE (base_decl) = TYPE_MODE (TREE_TYPE (base_decl));
+      base_decl = build0 (PLACEHOLDER_EXPR,
+			  indirect ? build_pointer_type (ptype) : ptype);
       GFC_TYPE_ARRAY_BASE_DECL (type, indirect) = base_decl;
     }
-  info->base_decl = base_decl;
   if (indirect)
     base_decl = build1 (INDIRECT_REF, ptype, base_decl);
 
-- 
1.7.10.4

Reply via email to