Skip to content

Commit 5363def

Browse files
committed
Use correct sign extension for enumeration types
This changes update_enumeration_type_from_children to use the correct sign-extension method on the attribute. The logic here is a bit complicated: if the enum has an underlying type, then we use that type's signed-ness to interpret attributes; otherwise we must assume attributes are encoded as signed values. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32680
1 parent c2de2f7 commit 5363def

File tree

1 file changed

+37
-22
lines changed

1 file changed

+37
-22
lines changed

gdb/dwarf2/read.c

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11579,25 +11579,30 @@ die_byte_order (die_info *die, dwarf2_cu *cu, enum bfd_endian *byte_order)
1157911579

1158011580
/* Assuming DIE is an enumeration type, and TYPE is its associated
1158111581
type, update TYPE using some information only available in DIE's
11582-
children. In particular, the fields are computed. */
11582+
children. In particular, the fields are computed. If IS_UNSIGNED
11583+
is set, the enumeration type's sign is already known (a true value
11584+
means unsigned), and so examining the constants to determine the
11585+
sign isn't needed; when this is unset, the enumerator constants are
11586+
read as signed values. */
1158311587

1158411588
static void
1158511589
update_enumeration_type_from_children (struct die_info *die,
1158611590
struct type *type,
11587-
struct dwarf2_cu *cu)
11591+
struct dwarf2_cu *cu,
11592+
std::optional<bool> is_unsigned)
1158811593
{
11589-
bool unsigned_enum = true;
11594+
/* This is used to check whether the enum is signed or unsigned; for
11595+
simplicity, it is always correct regardless of whether
11596+
IS_UNSIGNED is set. */
11597+
bool unsigned_enum = is_unsigned.value_or (true);
1159011598
bool flag_enum = true;
1159111599

11592-
auto_obstack obstack;
1159311600
std::vector<struct field> fields;
1159411601

1159511602
for (die_info *child_die : die->children ())
1159611603
{
1159711604
struct attribute *attr;
1159811605
LONGEST value;
11599-
const gdb_byte *bytes;
11600-
struct dwarf2_locexpr_baton *baton;
1160111606
const char *name;
1160211607

1160311608
if (child_die->tag != DW_TAG_enumerator)
@@ -11611,19 +11616,26 @@ update_enumeration_type_from_children (struct die_info *die,
1161111616
if (name == NULL)
1161211617
name = "<anonymous enumerator>";
1161311618

11614-
dwarf2_const_value_attr (attr, type, name, &obstack, cu,
11615-
&value, &bytes, &baton);
11616-
if (value < 0)
11617-
{
11618-
unsigned_enum = false;
11619-
flag_enum = false;
11620-
}
11619+
/* Can't check UNSIGNED_ENUM here because that is
11620+
optimistic. */
11621+
if (is_unsigned.has_value () && *is_unsigned)
11622+
value = attr->unsigned_constant ().value_or (0);
1162111623
else
1162211624
{
11623-
if (count_one_bits_ll (value) >= 2)
11624-
flag_enum = false;
11625+
/* Read as signed, either because we don't know the sign or
11626+
because we know it is definitely signed. */
11627+
value = attr->signed_constant ().value_or (0);
11628+
11629+
if (value < 0)
11630+
{
11631+
unsigned_enum = false;
11632+
flag_enum = false;
11633+
}
1162511634
}
1162611635

11636+
if (flag_enum && count_one_bits_ll (value) >= 2)
11637+
flag_enum = false;
11638+
1162711639
struct field &field = fields.emplace_back ();
1162811640
field.set_name (dwarf2_physname (name, child_die, cu));
1162911641
field.set_loc_enumval (value);
@@ -11634,11 +11646,8 @@ update_enumeration_type_from_children (struct die_info *die,
1163411646
else
1163511647
flag_enum = false;
1163611648

11637-
if (unsigned_enum)
11638-
type->set_is_unsigned (true);
11639-
11640-
if (flag_enum)
11641-
type->set_is_flag_enum (true);
11649+
type->set_is_unsigned (unsigned_enum);
11650+
type->set_is_flag_enum (flag_enum);
1164211651
}
1164311652

1164411653
/* Given a DW_AT_enumeration_type die, set its type. We do not
@@ -11696,6 +11705,11 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu)
1169611705
if (die_is_declaration (die, cu))
1169711706
type->set_is_stub (true);
1169811707

11708+
/* If the underlying type is known, and is unsigned, then we'll
11709+
assume the enumerator constants are unsigned. Otherwise we have
11710+
to assume they are signed. */
11711+
std::optional<bool> is_unsigned;
11712+
1169911713
/* If this type has an underlying type that is not a stub, then we
1170011714
may use its attributes. We always use the "unsigned" attribute
1170111715
in this situation, because ordinarily we guess whether the type
@@ -11708,7 +11722,8 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu)
1170811722
struct type *underlying_type = type->target_type ();
1170911723
underlying_type = check_typedef (underlying_type);
1171011724

11711-
type->set_is_unsigned (underlying_type->is_unsigned ());
11725+
is_unsigned = underlying_type->is_unsigned ();
11726+
type->set_is_unsigned (*is_unsigned);
1171211727

1171311728
if (type->length () == 0)
1171411729
type->set_length (underlying_type->length ());
@@ -11728,7 +11743,7 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu)
1172811743
Note that, as usual, this must come after set_die_type to avoid
1172911744
infinite recursion when trying to compute the names of the
1173011745
enumerators. */
11731-
update_enumeration_type_from_children (die, type, cu);
11746+
update_enumeration_type_from_children (die, type, cu, is_unsigned);
1173211747

1173311748
return type;
1173411749
}

0 commit comments

Comments
 (0)