> It doesn't look to me like DW_AT_endianity is applicable to array types
> or members in DWARF 3/4; instead, it should be applied to the underlying
> base type.

OK, the attached patch does that so is more invasive as expected.

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


2016-01-05  Eric Botcazou  <ebotca...@adacore.com>

        * dwarf2out.c (need_endianity_attribute_p): New inline predicate.
        (base_type_die): Add REVERSE parameter and attach DW_AT_endianity to
        the DIE accordingly.
        (modified_type_die): Add REVERSE parameter and pass it recursively,
        as well as to base_type_die.  Adjust presence check accordingly.
        (base_type_for_mode): Adjust call to modified_type_die.
        (add_type_attribute): Add REVERSE parameter and pass it to
        modified_type_die.
        (generic_parameter_die): Adjust call to add_type_attribute.
        (add_scalar_info): Likewise.
        (add_subscript_info): Likewise.
        (gen_array_type_die): Likewise.
        (gen_descr_array_type_die): Likewise.
        (gen_entry_point_die): Likewise.
        (gen_enumeration_type_die): Likewise.
        (gen_formal_parameter_die): Likewise.
        (gen_subprogram_die): Likewise.
        (gen_variable_die ): Likewise.
        (gen_const_die): Likewise.
        (gen_field_die): Likewise.
        (gen_pointer_type_die): Likewise.
        (gen_reference_type_die): Likewise.
        (gen_ptr_to_mbr_type_die): Likewise.
        (gen_inheritance_die): Likewise.
        (gen_subroutine_type_die): Likewise.
        (gen_typedef_die): Likewise.
        (force_type_die): Adjust call to modified_type_die.

2016-01-05  Eric Botcazou  <ebotca...@adacore.com>

        * gcc.dg/debug/dwarf2/sso.c: New test.

-- 
Eric Botcazou
Index: dwarf2out.c
===================================================================
--- dwarf2out.c	(revision 232035)
+++ dwarf2out.c	(working copy)
@@ -3286,11 +3286,11 @@ static void output_ranges (void);
 static dw_line_info_table *new_line_info_table (void);
 static void output_line_info (bool);
 static void output_file_names (void);
-static dw_die_ref base_type_die (tree);
+static dw_die_ref base_type_die (tree, bool);
 static int is_base_type (tree);
 static dw_die_ref subrange_type_die (tree, tree, tree, tree, dw_die_ref);
 static int decl_quals (const_tree);
-static dw_die_ref modified_type_die (tree, int, dw_die_ref);
+static dw_die_ref modified_type_die (tree, int, bool, dw_die_ref);
 static dw_die_ref generic_parameter_die (tree, tree, bool, dw_die_ref);
 static dw_die_ref template_parameter_pack_die (tree, tree, dw_die_ref);
 static int type_is_enum (const_tree);
@@ -3362,7 +3362,7 @@ static dw_die_ref scope_die_for (tree, d
 static inline int local_scope_p (dw_die_ref);
 static inline int class_scope_p (dw_die_ref);
 static inline int class_or_namespace_scope_p (dw_die_ref);
-static void add_type_attribute (dw_die_ref, tree, int, dw_die_ref);
+static void add_type_attribute (dw_die_ref, tree, int, bool, dw_die_ref);
 static void add_calling_convention_attribute (dw_die_ref, tree);
 static const char *type_tag (const_tree);
 static tree member_declared_type (const_tree);
@@ -10796,14 +10796,23 @@ output_line_info (bool prologue_only)
   ASM_OUTPUT_LABEL (asm_out_file, l2);
 }
 
+/* Return true if DW_AT_endianity should be emitted according to REVERSE.  */
+
+static inline bool
+need_endianity_attribute_p (bool reverse)
+{
+  return reverse && (dwarf_version >= 3 || !dwarf_strict);
+}
+
 /* Given a pointer to a tree node for some base type, return a pointer to
-   a DIE that describes the given type.
+   a DIE that describes the given type.  REVERSE is true if this type is
+   to be interpreted in reverse storage order wrt to the target order.
 
    This routine must only be called for GCC type nodes that correspond to
    Dwarf base (fundamental) types.  */
 
 static dw_die_ref
-base_type_die (tree type)
+base_type_die (tree type, bool reverse)
 {
   dw_die_ref base_type_result;
   enum dwarf_type encoding;
@@ -10912,6 +10921,10 @@ base_type_die (tree type)
 		   int_size_in_bytes (type));
   add_AT_unsigned (base_type_result, DW_AT_encoding, encoding);
 
+  if (need_endianity_attribute_p (reverse))
+    add_AT_unsigned (base_type_result, DW_AT_endianity,
+		     BYTES_BIG_ENDIAN ? DW_END_little : DW_END_big);
+
   if (fpt_used)
     {
       switch (fpt_info.scale_factor_kind)
@@ -10948,12 +10961,14 @@ base_type_die (tree type)
 	  gcc_unreachable ();
 	}
     }
-  if (type_bias != NULL)
+
+  if (type_bias)
     add_scalar_info (base_type_result, DW_AT_GNU_bias, type_bias,
 		     dw_scalar_form_constant
 		     | dw_scalar_form_exprloc
 		     | dw_scalar_form_reference,
 		     NULL);
+
   add_pubtype (type, base_type_result);
 
   return base_type_result;
@@ -11138,7 +11153,8 @@ get_nearest_type_subqualifiers (tree typ
    entry that chains various modifiers in front of the given type.  */
 
 static dw_die_ref
-modified_type_die (tree type, int cv_quals, dw_die_ref context_die)
+modified_type_die (tree type, int cv_quals, bool reverse,
+		   dw_die_ref context_die)
 {
   enum tree_code code = TREE_CODE (type);
   dw_die_ref mod_type_die;
@@ -11159,7 +11175,7 @@ modified_type_die (tree type, int cv_qua
       tree debug_type = lang_hooks.types.get_debug_type (type);
 
       if (debug_type != NULL_TREE && debug_type != type)
-	return modified_type_die (debug_type, cv_quals, context_die);
+	return modified_type_die (debug_type, cv_quals, reverse, context_die);
     }
 
   cv_quals &= cv_qual_mask;
@@ -11196,7 +11212,12 @@ modified_type_die (tree type, int cv_qua
   if (qualified_type)
     {
       mod_type_die = lookup_type_die (qualified_type);
-      if (mod_type_die)
+
+      /* DW_AT_endianity doesn't come from a qualifier on the type.  */
+      if (mod_type_die
+	  && (!need_endianity_attribute_p (reverse)
+	      || !is_base_type (type)
+	      || get_AT_unsigned (mod_type_die, DW_AT_endianity)))
 	return mod_type_die;
     }
 
@@ -11222,8 +11243,8 @@ modified_type_die (tree type, int cv_qua
 	      || (cv_quals == dquals && DECL_ORIGINAL_TYPE (name) != type))
 	    /* cv-unqualified version of named type.  Just use
 	       the unnamed type to which it refers.  */
-	    return modified_type_die (DECL_ORIGINAL_TYPE (name),
-				      cv_quals, context_die);
+	    return modified_type_die (DECL_ORIGINAL_TYPE (name), cv_quals,
+				      reverse, context_die);
 	  /* Else cv-qualified version of named type; fall through.  */
 	}
     }
@@ -11248,7 +11269,7 @@ modified_type_die (tree type, int cv_qua
 	 qualifiers.  */
       sub_quals = get_nearest_type_subqualifiers (type, cv_quals,
 						  cv_qual_mask);
-      mod_type_die = modified_type_die (type, sub_quals, context_die);
+      mod_type_die = modified_type_die (type, sub_quals, reverse, context_die);
 
       for (i = 0; i < sizeof (qual_info) / sizeof (qual_info[0]); i++)
 	if (qual_info[i].q & cv_quals & ~sub_quals)
@@ -11304,7 +11325,7 @@ modified_type_die (tree type, int cv_qua
       item_type = TREE_TYPE (type);
     }
   else if (is_base_type (type))
-    mod_type_die = base_type_die (type);
+    mod_type_die = base_type_die (type, reverse);
   else
     {
       gen_type_die (type, context_die);
@@ -11361,6 +11382,7 @@ modified_type_die (tree type, int cv_qua
        types are possible in Ada.  */
     sub_die = modified_type_die (item_type,
 				 TYPE_QUALS_NO_ADDR_SPACE (item_type),
+				 reverse,
 				 context_die);
 
   if (sub_die != NULL)
@@ -11505,7 +11527,7 @@ generic_parameter_die (tree parm, tree a
 	  add_type_attribute (tmpl_die, tmpl_type,
 			      (TREE_THIS_VOLATILE (tmpl_type)
 			       ? TYPE_QUAL_VOLATILE : TYPE_UNQUALIFIED),
-			      parent_die);
+			      false, parent_die);
 	}
       else
 	{
@@ -12392,7 +12414,8 @@ base_type_for_mode (machine_mode mode, b
     }
   type_die = lookup_type_die (type);
   if (!type_die)
-    type_die = modified_type_die (type, TYPE_UNQUALIFIED, comp_unit_die ());
+    type_die = modified_type_die (type, TYPE_UNQUALIFIED, false,
+				  comp_unit_die ());
   if (type_die == NULL || type_die->die_tag != DW_TAG_base_type)
     return NULL;
   return type_die;
@@ -17988,7 +18011,7 @@ static void
 add_scalar_info (dw_die_ref die, enum dwarf_attribute attr, tree value,
 		 int forms, const struct loc_descr_context *context)
 {
-  dw_die_ref ctx, decl_die;
+  dw_die_ref context_die, decl_die;
   dw_loc_list_ref list;
 
   bool strip_conversions = true;
@@ -18105,13 +18128,14 @@ add_scalar_info (dw_die_ref die, enum dw
     return;
 
   if (current_function_decl == 0)
-    ctx = comp_unit_die ();
+    context_die = comp_unit_die ();
   else
-    ctx = lookup_decl_die (current_function_decl);
+    context_die = lookup_decl_die (current_function_decl);
 
-  decl_die = new_die (DW_TAG_variable, ctx, value);
+  decl_die = new_die (DW_TAG_variable, context_die, value);
   add_AT_flag (decl_die, DW_AT_artificial, 1);
-  add_type_attribute (decl_die, TREE_TYPE (value), TYPE_QUAL_CONST, ctx);
+  add_type_attribute (decl_die, TREE_TYPE (value), TYPE_QUAL_CONST, false,
+		      context_die);
   add_AT_location_description (decl_die, DW_AT_location, list);
   add_AT_die_ref (die, attr, decl_die);
 }
@@ -18285,7 +18309,7 @@ add_subscript_info (dw_die_ref type_die,
 		;
 	      else
 		add_type_attribute (subrange_die, TREE_TYPE (domain),
-				    TYPE_UNQUALIFIED, type_die);
+				    TYPE_UNQUALIFIED, false, type_die);
 	    }
 
 	  /* ??? If upper is NULL, the array has unspecified length,
@@ -18843,7 +18867,7 @@ class_or_namespace_scope_p (dw_die_ref c
 
 static void
 add_type_attribute (dw_die_ref object_die, tree type, int cv_quals,
-		    dw_die_ref context_die)
+		    bool reverse, dw_die_ref context_die)
 {
   enum tree_code code  = TREE_CODE (type);
   dw_die_ref type_die  = NULL;
@@ -18865,6 +18889,7 @@ add_type_attribute (dw_die_ref object_di
 
   type_die = modified_type_die (type,
 				cv_quals | TYPE_QUALS_NO_ADDR_SPACE (type),
+				reverse,
 				context_die);
 
   if (type_die != NULL)
@@ -19101,7 +19126,10 @@ gen_array_type_die (tree type, dw_die_re
 	element_type = TREE_TYPE (element_type);
       }
 
-  add_type_attribute (array_die, element_type, TYPE_UNQUALIFIED, context_die);
+  add_type_attribute (array_die, element_type, TYPE_UNQUALIFIED,
+		      TREE_CODE (type) == ARRAY_TYPE
+		      && TYPE_REVERSE_STORAGE_ORDER (type),
+		      context_die);
 
   add_gnat_descriptive_type_attribute (array_die, type, context_die);
   if (TYPE_ARTIFICIAL (type))
@@ -19178,8 +19206,8 @@ gen_descr_array_type_die (tree type, str
 
       if (info->dimen[dim].bounds_type)
 	add_type_attribute (subrange_die,
-			    info->dimen[dim].bounds_type, 0,
-			    context_die);
+			    info->dimen[dim].bounds_type, TYPE_UNQUALIFIED,
+			    false, context_die);
       if (info->dimen[dim].lower_bound)
 	add_bound_info (subrange_die, DW_AT_lower_bound,
 			info->dimen[dim].lower_bound, &context);
@@ -19197,7 +19225,7 @@ gen_descr_array_type_die (tree type, str
 
   gen_type_die (info->element_type, context_die);
   add_type_attribute (array_die, info->element_type, TYPE_UNQUALIFIED,
-		      context_die);
+		      TYPE_REVERSE_STORAGE_ORDER (type), context_die);
 
   if (get_AT (array_die, DW_AT_name))
     add_pubtype (type, array_die);
@@ -19216,7 +19244,7 @@ gen_entry_point_die (tree decl, dw_die_r
     {
       add_name_and_src_coords_attributes (decl_die, decl);
       add_type_attribute (decl_die, TREE_TYPE (TREE_TYPE (decl)),
-			  TYPE_UNQUALIFIED, context_die);
+			  TYPE_UNQUALIFIED, false, context_die);
     }
 
   if (DECL_ABSTRACT_P (decl))
@@ -19306,7 +19334,7 @@ gen_enumeration_type_die (tree type, dw_
       if (dwarf_version >= 3 || !dwarf_strict)
 	{
 	  tree underlying = lang_hooks.types.enum_underlying_base_type (type);
-	  add_type_attribute (type_die, underlying, TYPE_UNQUALIFIED,
+	  add_type_attribute (type_die, underlying, TYPE_UNQUALIFIED, false,
 			      context_die);
 	}
       if (TYPE_STUB_DECL (type) != NULL_TREE)
@@ -19472,11 +19500,12 @@ gen_formal_parameter_die (tree node, tre
 	  tree type = TREE_TYPE (node_or_origin);
 	  if (decl_by_reference_p (node_or_origin))
 	    add_type_attribute (parm_die, TREE_TYPE (type),
-				TYPE_UNQUALIFIED, context_die);
+				TYPE_UNQUALIFIED,
+				false, context_die);
 	  else
 	    add_type_attribute (parm_die, type,
 				decl_quals (node_or_origin),
-				context_die);
+				false, context_die);
 	}
       if (origin == NULL && DECL_ARTIFICIAL (node))
 	add_AT_flag (parm_die, DW_AT_artificial, 1);
@@ -19491,7 +19520,7 @@ gen_formal_parameter_die (tree node, tre
 
     case tcc_type:
       /* We were called with some kind of a ..._TYPE node.  */
-      add_type_attribute (parm_die, node_or_origin, TYPE_UNQUALIFIED,
+      add_type_attribute (parm_die, node_or_origin, TYPE_UNQUALIFIED, false,
 			  context_die);
       break;
 
@@ -20216,7 +20245,7 @@ gen_subprogram_die (tree decl, dw_die_re
 	      dw_die_ref die = get_AT_ref (old_die, DW_AT_type);
 	      if (die == auto_die || die == decltype_auto_die)
 		add_type_attribute (subr_die, TREE_TYPE (TREE_TYPE (decl)),
-				    TYPE_UNQUALIFIED, context_die);
+				    TYPE_UNQUALIFIED, false, context_die);
 	    }
 	}
     }
@@ -20234,7 +20263,7 @@ gen_subprogram_die (tree decl, dw_die_re
 	{
 	  add_prototyped_attribute (subr_die, TREE_TYPE (decl));
 	  add_type_attribute (subr_die, TREE_TYPE (TREE_TYPE (decl)),
-			      TYPE_UNQUALIFIED, context_die);
+			      TYPE_UNQUALIFIED, false, context_die);
 	}
 
       add_pure_or_virtual_attribute (subr_die, decl);
@@ -20901,7 +20930,7 @@ gen_variable_die (tree decl, tree origin
 	}
       var_die = new_die (DW_TAG_variable, com_die, decl);
       add_name_and_src_coords_attributes (var_die, decl);
-      add_type_attribute (var_die, TREE_TYPE (decl), decl_quals (decl),
+      add_type_attribute (var_die, TREE_TYPE (decl), decl_quals (decl), false,
 			  context_die);
       add_AT_flag (var_die, DW_AT_external, 1);
       if (loc)
@@ -21014,10 +21043,10 @@ gen_variable_die (tree decl, tree origin
       tree type = TREE_TYPE (decl_or_origin);
 
       if (decl_by_reference_p (decl_or_origin))
-	add_type_attribute (var_die, TREE_TYPE (type), TYPE_UNQUALIFIED,
+	add_type_attribute (var_die, TREE_TYPE (type), TYPE_UNQUALIFIED, false,
 			    context_die);
       else
-	add_type_attribute (var_die, type, decl_quals (decl_or_origin),
+	add_type_attribute (var_die, type, decl_quals (decl_or_origin), false,
 			    context_die);
     }
 
@@ -21077,7 +21106,7 @@ gen_const_die (tree decl, dw_die_ref con
   const_die = new_die (DW_TAG_constant, context_die, decl);
   equate_decl_number_to_die (decl, const_die);
   add_name_and_src_coords_attributes (const_die, decl);
-  add_type_attribute (const_die, type, TYPE_QUAL_CONST, context_die);
+  add_type_attribute (const_die, type, TYPE_QUAL_CONST, false, context_die);
   if (TREE_PUBLIC (decl))
     add_AT_flag (const_die, DW_AT_external, 1);
   if (DECL_ARTIFICIAL (decl))
@@ -21363,8 +21392,9 @@ gen_field_die (tree decl, struct vlr_con
 
   decl_die = new_die (DW_TAG_member, context_die, decl);
   add_name_and_src_coords_attributes (decl_die, decl);
-  add_type_attribute (decl_die, member_declared_type (decl),
-		      decl_quals (decl), context_die);
+  add_type_attribute (decl_die, member_declared_type (decl), decl_quals (decl),
+		      TYPE_REVERSE_STORAGE_ORDER (DECL_FIELD_CONTEXT (decl)),
+		      context_die);
 
   if (DECL_BIT_FIELD_TYPE (decl))
     {
@@ -21403,7 +21433,7 @@ gen_pointer_type_die (tree type, dw_die_
     = new_die (DW_TAG_pointer_type, scope_die_for (type, context_die), type);
 
   equate_type_number_to_die (type, ptr_die);
-  add_type_attribute (ptr_die, TREE_TYPE (type), TYPE_UNQUALIFIED,
+  add_type_attribute (ptr_die, TREE_TYPE (type), TYPE_UNQUALIFIED, false,
 		      context_die);
   add_AT_unsigned (mod_type_die, DW_AT_byte_size, PTR_SIZE);
 }
@@ -21424,7 +21454,7 @@ gen_reference_type_die (tree type, dw_di
     ref_die = new_die (DW_TAG_reference_type, scope_die, type);
 
   equate_type_number_to_die (type, ref_die);
-  add_type_attribute (ref_die, TREE_TYPE (type), TYPE_UNQUALIFIED,
+  add_type_attribute (ref_die, TREE_TYPE (type), TYPE_UNQUALIFIED, false,
 		      context_die);
   add_AT_unsigned (mod_type_die, DW_AT_byte_size, PTR_SIZE);
 }
@@ -21442,7 +21472,7 @@ gen_ptr_to_mbr_type_die (tree type, dw_d
   equate_type_number_to_die (type, ptr_die);
   add_AT_die_ref (ptr_die, DW_AT_containing_type,
 		  lookup_type_die (TYPE_OFFSET_BASETYPE (type)));
-  add_type_attribute (ptr_die, TREE_TYPE (type), TYPE_UNQUALIFIED,
+  add_type_attribute (ptr_die, TREE_TYPE (type), TYPE_UNQUALIFIED, false,
 		      context_die);
 }
 
@@ -21711,7 +21741,8 @@ gen_inheritance_die (tree binfo, tree ac
   dw_die_ref die = new_die (DW_TAG_inheritance, context_die, binfo);
   struct vlr_context ctx = { type, NULL };
 
-  add_type_attribute (die, BINFO_TYPE (binfo), TYPE_UNQUALIFIED, context_die);
+  add_type_attribute (die, BINFO_TYPE (binfo), TYPE_UNQUALIFIED, false,
+		      context_die);
   add_data_member_location_attribute (die, binfo, &ctx);
 
   if (BINFO_VIRTUAL_P (binfo))
@@ -22344,7 +22375,8 @@ gen_subroutine_type_die (tree type, dw_d
 
   equate_type_number_to_die (type, subr_die);
   add_prototyped_attribute (subr_die, type);
-  add_type_attribute (subr_die, return_type, TYPE_UNQUALIFIED, context_die);
+  add_type_attribute (subr_die, return_type, TYPE_UNQUALIFIED, false,
+		      context_die);
   gen_formal_types_die (type, subr_die);
 
   if (get_AT (subr_die, DW_AT_name))
@@ -22422,7 +22454,8 @@ gen_typedef_die (tree decl, dw_die_ref c
 	    }
 	}
 
-      add_type_attribute (type_die, type, decl_quals (decl), context_die);
+      add_type_attribute (type_die, type, decl_quals (decl), false,
+			  context_die);
 
       if (is_naming_typedef_decl (decl))
 	/* We want that all subsequent calls to lookup_type_die with
@@ -23053,7 +23086,7 @@ force_type_die (tree type)
       dw_die_ref context_die = get_context_die (TYPE_CONTEXT (type));
 
       type_die = modified_type_die (type, TYPE_QUALS_NO_ADDR_SPACE (type),
-				    context_die);
+				    false, context_die);
       gcc_assert (type_die);
     }
   return type_die;
/* { dg-do compile } */
/* { dg-options "-gdwarf-3 -dA" } */

#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define REVERSE_SSO __attribute__((scalar_storage_order("big-endian")));
#else
#define REVERSE_SSO __attribute__((scalar_storage_order("little-endian")));
#endif

struct S0 { int i; };

struct S1 { int i; struct S0 s; } REVERSE_SSO;

struct S2 { int a[4]; struct S0 s; } REVERSE_SSO;

struct S0 s0;
struct S1 s1;
struct S2 s2;

/* Verify that we have endianity on the common base type of 'i' in S1 and of
   the element of 'a' in S2.  */
/* { dg-final { scan-assembler-times " DW_AT_endianity" 1 } } */

Reply via email to