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