[PATCH] Fix DW_AT_{lower,upper}_bound for VLAs (PR debug/43762)

Jakub Jelinek jakub@redhat.com
Fri Apr 16 14:19:00 GMT 2010


Hi!

If add_bound_info is called with an artificial VAR_DECL represented with
a location list with more than one range, GCC currently emits incorrect
DW_AT_location for the artificial DIE that is referenced (doesn't contain
DW_OP_stack_value at the end of the ranges).  On the other side, if
bound happened to be some arbitrary expressions and a single location
description could be useful for it, we'd not emit DW_OP_deref at the end
that needs to be there.

The problem is that unlike say DW_AT_location attribute whose argument is
a DWARF location description or location list pointer (list of ranges
with location description), DW_AT_upper_bound etc. can be a constant,
reference (then it references some DIE with its DW_AT_location and thus
again location description or location list pointer) or DWARF expression.
The difference between the two is that DWARF expression computes some value
on the stack and in DW_AT_upper_bound case the value from TOS is the bound.
DWARF location description is either some DW_OP_reg{N,x}, or DWARF
expression (then it is an address of a memory and the value is what the
memory contains) or DWARF expression + DW_OP_stack_value (then it is
that value) or a few other cases.

For add_bound_info this means that it needs to call loc_list_from_tree twice
(once with 2 for use in DW_AT_location for an artificial DIE, once with 0
to compute a DWARF expression if there is a chance the latter could be a
single expression).

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk
and 4.5?

2010-04-16  Jakub Jelinek  <jakub@redhat.com>

	PR debug/43762
	* dwarf2out.c (add_bound_info): Always call loc_list_from_tree
	with want_address 2 and in case a single element list might be
	possible, call it again with want_address 0.

--- gcc/dwarf2out.c.jj	2010-04-07 13:39:55.000000000 +0200
+++ gcc/dwarf2out.c	2010-04-16 13:55:16.000000000 +0200
@@ -16355,8 +16355,6 @@ lower_bound_default (void)
 static void
 add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr, tree bound)
 {
-  int want_address = 2;
-
   switch (TREE_CODE (bound))
     {
     case ERROR_MARK:
@@ -16419,7 +16417,6 @@ add_bound_info (dw_die_ref subrange_die,
 	    add_AT_die_ref (subrange_die, bound_attr, decl_die);
 	    break;
 	  }
-	want_address = 0;
       }
       /* FALLTHRU */
 
@@ -16431,15 +16428,23 @@ add_bound_info (dw_die_ref subrange_die,
 	dw_die_ref ctx, decl_die;
 	dw_loc_list_ref list;
 
-	list = loc_list_from_tree (bound, want_address);
-	if (list == NULL)
-	  break;
-
-	if (single_element_loc_list_p (list))
+	list = loc_list_from_tree (bound, 2);
+	if (list == NULL || single_element_loc_list_p (list))
 	  {
-	    add_AT_loc (subrange_die, bound_attr, list->expr);
-	    break;
+	    /* 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;
 
 	if (current_function_decl == 0)
 	  ctx = comp_unit_die;

	Jakub



More information about the Gcc-patches mailing list