@@ -1361,6 +1361,7 @@ dw_val_equal_p (dw_val_node *a, dw_val_node *b)
case dw_val_class_offset:
case dw_val_class_unsigned_const:
+ case dw_val_class_explicit_unsigned_const:
case dw_val_class_const:
case dw_val_class_range_list:
case dw_val_class_lineptr:
@@ -3947,6 +3948,29 @@ AT_unsigned (dw_attr_node *a)
return a->dw_attr_val.v.val_unsigned;
}
+/* Add an explicitely unsigned integer attribute value to a DIE. */
+
+static inline void
+add_AT_explicit_unsigned (dw_die_ref die, enum dwarf_attribute attr_kind,
+ unsigned HOST_WIDE_INT unsigned_val)
+{
+ dw_attr_node attr;
+
+ attr.dw_attr = attr_kind;
+ attr.dw_attr_val.val_class = dw_val_class_explicit_unsigned_const;
+ attr.dw_attr_val.val_entry = NULL;
+ attr.dw_attr_val.v.val_explicit_unsigned = unsigned_val;
+ add_dwarf_attr (die, &attr);
+}
+
+static inline unsigned HOST_WIDE_INT
+AT_explicit_unsigned (dw_attr_node *a)
+{
+ gcc_assert (a != NULL
+ && AT_class (a) == dw_val_class_explicit_unsigned_const);
+ return a->dw_attr_val.v.val_explicit_unsigned;
+}
+
/* Add an unsigned wide integer attribute value to a DIE. */
static inline void
@@ -5600,6 +5624,7 @@ print_dw_val (dw_val_node *val, bool recurse, FILE *outfile)
fprintf (outfile, HOST_WIDE_INT_PRINT_DEC, val->v.val_int);
break;
case dw_val_class_unsigned_const:
+ case dw_val_class_explicit_unsigned_const:
fprintf (outfile, HOST_WIDE_INT_PRINT_UNSIGNED, val->v.val_unsigned);
break;
case dw_val_class_const_double:
@@ -5998,6 +6023,7 @@ attr_checksum (dw_attr_node *at, struct md5_ctx *ctx, int *mark)
CHECKSUM (at->dw_attr_val.v.val_int);
break;
case dw_val_class_unsigned_const:
+ case dw_val_class_explicit_unsigned_const:
CHECKSUM (at->dw_attr_val.v.val_unsigned);
break;
case dw_val_class_const_double:
@@ -6277,6 +6303,7 @@ attr_checksum_ordered (enum dwarf_tag tag, dw_attr_node *at,
break;
case dw_val_class_unsigned_const:
+ case dw_val_class_explicit_unsigned_const:
CHECKSUM_ULEB128 (DW_FORM_sdata);
CHECKSUM_SLEB128 ((int) at->dw_attr_val.v.val_unsigned);
break;
@@ -6784,6 +6811,7 @@ same_dw_val_p (const dw_val_node *v1, const dw_val_node *v2, int *mark)
case dw_val_class_const:
return v1->v.val_int == v2->v.val_int;
case dw_val_class_unsigned_const:
+ case dw_val_class_explicit_unsigned_const:
return v1->v.val_unsigned == v2->v.val_unsigned;
case dw_val_class_const_double:
return v1->v.val_double.high == v2->v.val_double.high
@@ -8434,6 +8462,9 @@ size_of_die (dw_die_ref die)
size += csize;
}
break;
+ case dw_val_class_explicit_unsigned_const:
+ size += size_of_uleb128 (AT_explicit_unsigned (a));
+ break;
case dw_val_class_const_double:
size += HOST_BITS_PER_DOUBLE_INT / HOST_BITS_PER_CHAR;
if (HOST_BITS_PER_WIDE_INT >= 64)
@@ -8814,6 +8845,8 @@ value_format (dw_attr_node *a)
default:
gcc_unreachable ();
}
+ case dw_val_class_explicit_unsigned_const:
+ return DW_FORM_udata;
case dw_val_class_const_double:
switch (HOST_BITS_PER_WIDE_INT)
{
@@ -9280,6 +9313,10 @@ output_die (dw_die_ref die)
}
break;
+ case dw_val_class_explicit_unsigned_const:
+ dw2_asm_output_data_uleb128 (AT_explicit_unsigned (a), "%s", name);
+ break;
+
case dw_val_class_const_double:
{
unsigned HOST_WIDE_INT first, second;
@@ -19735,15 +19772,23 @@ gen_enumeration_type_die (tree type, dw_die_ref context_die)
if (simple_type_size_in_bits (TREE_TYPE (value))
<= HOST_BITS_PER_WIDE_INT || tree_fits_shwi_p (value))
{
- /* For constant forms created by add_AT_unsigned DWARF
- consumers (GDB, elfutils, etc.) always zero extend
- the value. Only when the actual value is negative
- do we need to use add_AT_int to generate a constant
- form that can represent negative values. */
+ /* DW_TAG_enumeration_type DIEs do not describe type signedness.
+ However, this information is required when enumeration
+ subranges are considered: this happens for instance in
+ DW_TAG_subrange_type DIEs or in DW_DSC_range discriminant
+ descriptions. Because of this, unsigned values must be
+ explicitely described as unsigned.
+
+ This satisfies with the DWARF recommandation (section 7.5.4
+ Attribute Encodings):
+
+ Producers are therefore strongly encouraged to use
+ DW_FORM_sdata or DW_FORM_udata for signed and unsigned
+ integers respectively, rather than DW_FORM_data<n>. */
HOST_WIDE_INT val = TREE_INT_CST_LOW (value);
- if (TYPE_UNSIGNED (TREE_TYPE (value)) || val >= 0)
- add_AT_unsigned (enum_die, DW_AT_const_value,
- (unsigned HOST_WIDE_INT) val);
+ if (TYPE_UNSIGNED (TREE_TYPE (value)))
+ add_AT_explicit_unsigned (enum_die, DW_AT_const_value,
+ (unsigned HOST_WIDE_INT) val);
else
add_AT_int (enum_die, DW_AT_const_value, val);
}
@@ -137,6 +137,7 @@ enum dw_val_class
dw_val_class_range_list,
dw_val_class_const,
dw_val_class_unsigned_const,
+ dw_val_class_explicit_unsigned_const,
dw_val_class_const_double,
dw_val_class_wide_int,
dw_val_class_vec,
@@ -199,6 +200,8 @@ struct GTY(()) dw_val_node {
dw_loc_descr_ref GTY ((tag ("dw_val_class_loc"))) val_loc;
HOST_WIDE_INT GTY ((default)) val_int;
unsigned HOST_WIDE_INT GTY ((tag ("dw_val_class_unsigned_const"))) val_unsigned;
+ unsigned HOST_WIDE_INT GTY ((tag ("dw_val_class_explicit_unsigned_const")))
+ val_explicit_unsigned;
double_int GTY ((tag ("dw_val_class_const_double"))) val_double;
wide_int_ptr GTY ((tag ("dw_val_class_wide_int"))) val_wide;
dw_vec_const GTY ((tag ("dw_val_class_vec"))) val_vec;
new file mode 100644
@@ -0,0 +1,39 @@
+-- { dg-options "-g -cargs -dA -margs" }
+--
+-- First, check that there are exactly:
+-- * two abbreviations for DW_TAG_enumerator
+-- * two DW_AT_const_value attributes in abbreviations
+--
+-- { dg-final { scan-assembler-times "\\(TAG: DW_TAG_enumerator\\)" 2 } }
+-- { dg-final { scan-assembler-times "\\(DW_AT_const_value\\)" 2 } }
+--
+-- Then, check that the const values are respectively explicitly unsigned
+-- (udata) and signed. The following pattern is kind of weak because it does
+-- not check that 1) DW_AT_const_value attributes are indeed related to
+-- DW_TAG_enumerator DIEs and that 2) the DW_FORM_* are related to the
+-- DW_AT_const_value attributes... but we're doing as much as we can with
+-- regexp matching...
+--
+-- { dg-final { scan-assembler "\\(TAG: DW_TAG_enumerator\\).*\\(DW_AT_const_value\\).*\\(DW_FORM_udata\\).*\\(TAG: DW_TAG_enumerator\\).*\\(DW_AT_const_value\\).*\\(DW_FORM_sdata\\)" } }
+
+procedure Debug10 is
+
+ type Default_Type is (A, B, C);
+
+ type Signed_Type is (X, Y, Z);
+ for Signed_Type use (-1, 0, 1);
+
+ procedure Ignore (E : Default_Type) is
+ begin
+ null;
+ end Ignore;
+
+ procedure Ignore (E : Signed_Type) is
+ begin
+ null;
+ end Ignore;
+
+begin
+ Ignore (A);
+ Ignore (X);
+end Debug10;