@@ -3089,7 +3089,7 @@ static void add_AT_offset (dw_die_ref, enum dwarf_attribute,
static void add_AT_range_list (dw_die_ref, enum dwarf_attribute,
unsigned long, bool);
static inline const char *AT_lbl (dw_attr_ref);
-static dw_attr_ref get_AT (dw_die_ref, enum dwarf_attribute);
+static dw_attr_ref get_AT (dw_die_ref, enum dwarf_attribute, bool follow = true);
static const char *get_AT_low_pc (dw_die_ref);
static const char *get_AT_hi_pc (dw_die_ref);
static const char *get_AT_string (dw_die_ref, enum dwarf_attribute);
@@ -4579,10 +4579,14 @@ AT_lbl (dw_attr_ref a)
return a->dw_attr_val.v.val_lbl_id;
}
-/* Get the attribute of type attr_kind. */
+/* Get the attribute of type attr_kind.
+
+ FOLLOW is true if we should drill down through DW_AT_specification
+ and DW_AT_abstract_origin attributes. */
static dw_attr_ref
-get_AT (dw_die_ref die, enum dwarf_attribute attr_kind)
+get_AT (dw_die_ref die, enum dwarf_attribute attr_kind,
+ bool follow /*= true*/)
{
dw_attr_ref a;
unsigned ix;
@@ -4594,8 +4598,8 @@ get_AT (dw_die_ref die, enum dwarf_attribute attr_kind)
FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
if (a->dw_attr == attr_kind)
return a;
- else if (a->dw_attr == DW_AT_specification
- || a->dw_attr == DW_AT_abstract_origin)
+ else if (follow && (a->dw_attr == DW_AT_specification
+ || a->dw_attr == DW_AT_abstract_origin))
spec = AT_ref (a);
if (spec)
@@ -5690,20 +5694,55 @@ debug_dwarf (void)
static void
check_die (dw_die_ref die)
{
- /* A debugging information entry that is a member of an abstract
- instance tree [that has DW_AT_inline] should not contain any
- attributes which describe aspects of the subroutine which vary
- between distinct inlined expansions or distinct out-of-line
- expansions. */
unsigned ix;
dw_attr_ref a;
bool inline_found = false;
+ int n_location = 0, n_low_pc = 0, n_high_pc = 0, n_artificial = 0;
+ int n_decl_line = 0, n_decl_file = 0;
FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
- if (a->dw_attr == DW_AT_inline && a->dw_attr_val.v.val_unsigned)
- inline_found = true;
+ {
+ switch (a->dw_attr)
+ {
+ case DW_AT_inline:
+ if (a->dw_attr_val.v.val_unsigned)
+ inline_found = true;
+ break;
+ case DW_AT_location:
+ ++n_location;
+ break;
+ case DW_AT_low_pc:
+ ++n_low_pc;
+ break;
+ case DW_AT_high_pc:
+ ++n_high_pc;
+ break;
+ case DW_AT_artificial:
+ ++n_artificial;
+ break;
+ case DW_AT_decl_line:
+ ++n_decl_line;
+ break;
+ case DW_AT_decl_file:
+ ++n_decl_file;
+ break;
+ default:
+ break;
+ }
+ }
+ if (n_location > 1 || n_low_pc > 1 || n_high_pc > 1 || n_artificial > 1
+ || n_decl_line > 1 || n_decl_file > 1)
+ {
+ fprintf (stderr, "Duplicate attributes in DIE:\n");
+ debug_dwarf_die (die);
+ gcc_unreachable ();
+ }
if (inline_found)
{
- /* Catch the most common mistakes. */
+ /* A debugging information entry that is a member of an abstract
+ instance tree [that has DW_AT_inline] should not contain any
+ attributes which describe aspects of the subroutine which vary
+ between distinct inlined expansions or distinct out-of-line
+ expansions. */
FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
gcc_assert (a->dw_attr != DW_AT_low_pc
&& a->dw_attr != DW_AT_high_pc
@@ -16095,6 +16134,9 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl, bool cache_p,
if (TREE_CODE (decl) == ERROR_MARK)
return false;
+ if (get_AT (die, attr, /*follow=*/false))
+ return true;
+
gcc_assert (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL
|| TREE_CODE (decl) == RESULT_DECL);
@@ -18055,10 +18097,9 @@ gen_formal_parameter_die (tree node, tree origin, bool emit_name_p,
decl_quals (node_or_origin),
context_die);
}
- add_location:
if (origin == NULL && DECL_ARTIFICIAL (node))
add_AT_flag (parm_die, DW_AT_artificial, 1);
-
+ add_location:
if (node && node != origin)
equate_decl_number_to_die (node, parm_die);
if (! DECL_ABSTRACT_P (node_or_origin))
@@ -20354,15 +20395,19 @@ static void
gen_struct_or_union_type_die (tree type, dw_die_ref context_die,
enum debug_info_usage usage)
{
- /* Fill in the bound of variable-length fields in late dwarf if
- still incomplete. */
- if (TREE_ASM_WRITTEN (type)
- && variably_modified_type_p (type, NULL)
- && !early_dwarf)
+ if (TREE_ASM_WRITTEN (type))
{
- tree member;
- for (member = TYPE_FIELDS (type); member; member = DECL_CHAIN (member))
- fill_variable_array_bounds (TREE_TYPE (member));
+ /* Fill in the bound of variable-length fields in late dwarf if
+ still incomplete. */
+ if (variably_modified_type_p (type, NULL)
+ && !early_dwarf)
+ {
+ tree member;
+ for (member = TYPE_FIELDS (type);
+ member;
+ member = DECL_CHAIN (member))
+ fill_variable_array_bounds (TREE_TYPE (member));
+ }
return;
}
@@ -20842,7 +20887,13 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
static void
gen_type_die (tree type, dw_die_ref context_die)
{
- gen_type_die_with_usage (type, context_die, DINFO_USAGE_DIR_USE);
+ if (type != error_mark_node)
+ {
+ gen_type_die_with_usage (type, context_die, DINFO_USAGE_DIR_USE);
+ dw_die_ref die = lookup_type_die (type);
+ if (die)
+ check_die (die);
+ }
}
/* Generate a DW_TAG_lexical_block DIE followed by DIEs to represent all of the