The 4.7 compiler introduces the DW_AT_GNAT_descriptive_type attribute for Ada:
  http://gcc.gnu.org/ml/gcc-patches/2011-02/msg01194.html
We just realized that the way it is current generated may lead to incomplete 
debug info because it is generated before the children of the DIE, for example 
the fields in a structure.  Now, under certain circumstances, this breaks the 
handling of recursive types.

I added a kludge some time ago to mitigate this:
  http://gcc.gnu.org/ml/gcc-patches/2011-10/msg02320.html
but it proved to be short-sighted.

The attached patch makes it so that the attribute is generated only after the 
complete DIE is.  There are 2 chunks, one for the Ada FE and one for the DWARF 
back-end, but this only affects the Ada compiler.  And it moves the generation 
of the DW_AT_artificial attribute for types as well (also used only by the Ada 
compiler) for the sake of consistency.

Tested on i586-suse-linux, OK for the mainline?


2012-02-27  Eric Botcazou  <ebotca...@adacore.com>

        * dwarf2out.c (modified_type_die): Set DW_AT_GNAT_descriptive_type and
        DW_AT_artificial attributes at the end of the processing.
        (gen_array_type_die): Likewise.
        (gen_enumeration_type_die): Likewise.
        (gen_struct_or_union_type_die): Likewise.
        (add_gnat_descriptive_type_attribute): Do not suppress debug info for
        the parent type.


2012-02-27  Eric Botcazou  <ebotca...@adacore.com>

        * gcc-interface/decl.c (components_to_record): Add ARTIFICIAL parameter
        and set TYPE_ARTIFICIAL according to it.  Adjust recursive call.
        (gnat_to_gnu_entity) <E_Record_Type>: Adjust call to above function.
        * gcc-interface/utils.c (rest_of_record_type_compilation): Do not
        invoke rest_of_type_decl_compilation on the parallel type, if any.
        

-- 
Eric Botcazou
Index: dwarf2out.c
===================================================================
--- dwarf2out.c	(revision 184585)
+++ dwarf2out.c	(working copy)
@@ -9929,9 +9929,6 @@ modified_type_die (tree type, int is_con
 	   useful source coordinates anyway.  */
 	name = DECL_NAME (name);
       add_name_attribute (mod_type_die, IDENTIFIER_POINTER (name));
-      add_gnat_descriptive_type_attribute (mod_type_die, type, context_die);
-      if (TYPE_ARTIFICIAL (type))
-	add_AT_flag (mod_type_die, DW_AT_artificial, 1);
     }
   /* This probably indicates a bug.  */
   else if (mod_type_die && mod_type_die->die_tag == DW_TAG_base_type)
@@ -9960,6 +9957,10 @@ modified_type_die (tree type, int is_con
   if (sub_die != NULL)
     add_AT_die_ref (mod_type_die, DW_AT_type, sub_die);
 
+  add_gnat_descriptive_type_attribute (mod_type_die, type, context_die);
+  if (TYPE_ARTIFICIAL (type))
+    add_AT_flag (mod_type_die, DW_AT_artificial, 1);
+
   return mod_type_die;
 }
 
@@ -15493,11 +15494,7 @@ add_gnat_descriptive_type_attribute (dw_
   dtype_die = lookup_type_die (dtype);
   if (!dtype_die)
     {
-      /* The descriptive type indirectly references TYPE if this is also the
-	 case for TYPE itself.  Do not deal with the circularity here.  */
-      TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (type)) = 1;
       gen_type_die (dtype, context_die);
-      TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (type)) = 0;
       dtype_die = lookup_type_die (dtype);
       gcc_assert (dtype_die);
     }
@@ -16384,9 +16381,6 @@ gen_array_type_die (tree type, dw_die_re
 
   array_die = new_die (DW_TAG_array_type, scope_die, type);
   add_name_attribute (array_die, type_tag (type));
-  add_gnat_descriptive_type_attribute (array_die, type, context_die);
-  if (TYPE_ARTIFICIAL (type))
-    add_AT_flag (array_die, DW_AT_artificial, 1);
   equate_type_number_to_die (type, array_die);
 
   if (TREE_CODE (type) == VECTOR_TYPE)
@@ -16446,6 +16440,10 @@ gen_array_type_die (tree type, dw_die_re
 
   add_type_attribute (array_die, element_type, 0, 0, context_die);
 
+  add_gnat_descriptive_type_attribute (array_die, type, context_die);
+  if (TYPE_ARTIFICIAL (type))
+    add_AT_flag (array_die, DW_AT_artificial, 1);
+
   if (get_AT (array_die, DW_AT_name))
     add_pubtype (type, array_die);
 }
@@ -16689,9 +16687,6 @@ gen_enumeration_type_die (tree type, dw_
 			  scope_die_for (type, context_die), type);
       equate_type_number_to_die (type, type_die);
       add_name_attribute (type_die, type_tag (type));
-      add_gnat_descriptive_type_attribute (type_die, type, context_die);
-      if (TYPE_ARTIFICIAL (type))
-	add_AT_flag (type_die, DW_AT_artificial, 1);
       if (dwarf_version >= 4 || !dwarf_strict)
 	{
 	  if (ENUM_IS_SCOPED (type))
@@ -16747,6 +16742,10 @@ gen_enumeration_type_die (tree type, dw_
 	    add_AT_int (enum_die, DW_AT_const_value,
 			tree_low_cst (value, tree_int_cst_sgn (value) > 0));
 	}
+
+      add_gnat_descriptive_type_attribute (type_die, type, context_die);
+      if (TYPE_ARTIFICIAL (type))
+	add_AT_flag (type_die, DW_AT_artificial, 1);
     }
   else
     add_AT_flag (type_die, DW_AT_declaration, 1);
@@ -18659,12 +18658,7 @@ gen_struct_or_union_type_die (tree type,
       if (old_die)
 	add_AT_specification (type_die, old_die);
       else
-	{
-	  add_name_attribute (type_die, type_tag (type));
-	  add_gnat_descriptive_type_attribute (type_die, type, context_die);
-	  if (TYPE_ARTIFICIAL (type))
-	    add_AT_flag (type_die, DW_AT_artificial, 1);
-	}
+	add_name_attribute (type_die, type_tag (type));
     }
   else
     remove_AT (type_die, DW_AT_declaration);
@@ -18697,6 +18691,10 @@ gen_struct_or_union_type_die (tree type,
       gen_member_die (type, type_die);
       pop_decl_scope ();
 
+      add_gnat_descriptive_type_attribute (type_die, type, context_die);
+      if (TYPE_ARTIFICIAL (type))
+	add_AT_flag (type_die, DW_AT_artificial, 1);
+
       /* GNU extension: Record what type our vtable lives in.  */
       if (TYPE_VFIELD (type))
 	{
Index: ada/gcc-interface/utils.c
===================================================================
--- ada/gcc-interface/utils.c	(revision 184594)
+++ ada/gcc-interface/utils.c	(working copy)
@@ -918,8 +918,6 @@ rest_of_record_type_compilation (tree re
       TYPE_SIZE_UNIT (new_record_type)
 	= size_int (TYPE_ALIGN (record_type) / BITS_PER_UNIT);
 
-      add_parallel_type (TYPE_STUB_DECL (record_type), new_record_type);
-
       /* Now scan all the fields, replacing each field with a new
 	 field corresponding to the new encoding.  */
       for (old_field = TYPE_FIELDS (record_type); old_field;
@@ -1058,7 +1056,12 @@ rest_of_record_type_compilation (tree re
       TYPE_FIELDS (new_record_type)
 	= nreverse (TYPE_FIELDS (new_record_type));
 
-      rest_of_type_decl_compilation (TYPE_STUB_DECL (new_record_type));
+      /* We used to explicitly invoke rest_of_type_decl_compilation on the
+	 parallel type for the sake of STABS.  We don't do it any more, so
+	 as to ensure that the parallel type be processed after the type
+	 by the debug back-end and, thus, prevent it from interfering with
+	 the processing of a recursive type.  */
+      add_parallel_type (TYPE_STUB_DECL (record_type), new_record_type);
     }
 
   rest_of_type_decl_compilation (TYPE_STUB_DECL (record_type));
Index: ada/gcc-interface/decl.c
===================================================================
--- ada/gcc-interface/decl.c	(revision 184594)
+++ ada/gcc-interface/decl.c	(working copy)
@@ -160,7 +160,7 @@ static bool compile_time_known_address_p
 static bool cannot_be_superflat_p (Node_Id);
 static bool constructor_address_p (tree);
 static void components_to_record (tree, Node_Id, tree, int, bool, bool, bool,
-				  bool, bool, bool, bool, tree, tree *);
+				  bool, bool, bool, bool, bool, tree, tree *);
 static Uint annotate_value (tree);
 static void annotate_rep (Entity_Id, tree);
 static tree build_position_list (tree, bool, tree, tree, unsigned int, tree);
@@ -3121,7 +3121,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entit
 	/* Add the fields into the record type and finish it up.  */
 	components_to_record (gnu_type, Component_List (record_definition),
 			      gnu_field_list, packed, definition, false,
-			      all_rep, is_unchecked_union, debug_info_p,
+			      all_rep, is_unchecked_union,
+			      !Comes_From_Source (gnat_entity), debug_info_p,
 			      false, OK_To_Reorder_Components (gnat_entity),
 			      all_rep ? NULL_TREE : bitsize_zero_node, NULL);
 
@@ -7268,6 +7269,8 @@ compare_field_bitpos (const PTR rt1, con
    UNCHECKED_UNION is true if we are building this type for a record with a
    Pragma Unchecked_Union.
 
+   ARTIFICIAL is true if this is a type that was generated by the compiler.
+
    DEBUG_INFO is true if we need to write debug information about the type.
 
    MAYBE_UNUSED is true if this type may be unused in the end; this doesn't
@@ -7287,8 +7290,8 @@ static void
 components_to_record (tree gnu_record_type, Node_Id gnat_component_list,
 		      tree gnu_field_list, int packed, bool definition,
 		      bool cancel_alignment, bool all_rep,
-		      bool unchecked_union, bool debug_info,
-		      bool maybe_unused, bool reorder,
+		      bool unchecked_union, bool artificial,
+		      bool debug_info, bool maybe_unused, bool reorder,
 		      tree first_free_pos, tree *p_gnu_rep_list)
 {
   bool all_rep_and_size = all_rep && TYPE_SIZE (gnu_record_type);
@@ -7457,7 +7460,8 @@ components_to_record (tree gnu_record_ty
 	  components_to_record (gnu_variant_type, Component_List (variant),
 				NULL_TREE, packed, definition,
 				!all_rep_and_size, all_rep, unchecked_union,
-				debug_info, true, reorder, this_first_free_pos,
+				true, debug_info, true, reorder,
+				this_first_free_pos,
 				all_rep || this_first_free_pos
 				? NULL : &gnu_rep_list);
 
@@ -7699,7 +7703,10 @@ components_to_record (tree gnu_record_ty
     TYPE_ALIGN (gnu_record_type) = 0;
 
   finish_record_type (gnu_record_type, nreverse (gnu_field_list),
-		      layout_with_rep ? 1 : 0, debug_info && !maybe_unused);
+		      layout_with_rep ? 1 : 0, false);
+  TYPE_ARTIFICIAL (gnu_record_type) = artificial;
+  if (debug_info && !maybe_unused)
+    rest_of_record_type_compilation (gnu_record_type);
 }
 
 /* Given GNU_SIZE, a GCC tree representing a size, return a Uint to be

Reply via email to