diff options
author | Tom Tromey <tromey@adacore.com> | 2025-03-20 07:47:51 -0600 |
---|---|---|
committer | Tom Tromey <tromey@adacore.com> | 2025-04-24 13:25:08 -0600 |
commit | 6ad5f5b6c08ea6b9733d64f77ab710d0b30dde09 (patch) | |
tree | 4782b9c8c0032b501f98f627c3ab1516e33f5e7f /gdb | |
parent | 0c03db90812b50d3db4a149f679a994fa9cbee87 (diff) | |
download | binutils-6ad5f5b6c08ea6b9733d64f77ab710d0b30dde09.zip binutils-6ad5f5b6c08ea6b9733d64f77ab710d0b30dde09.tar.gz binutils-6ad5f5b6c08ea6b9733d64f77ab710d0b30dde09.tar.bz2 |
Use correct sign for variant part discriminants
The discriminant value for a variant part may be signed or unsigned,
depending on the type of the variant. This patch changes the DWARF
reader to delay interpretation of the relevant attribute until the
signed-ness is known.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32680
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/dwarf2/read.c | 34 |
1 files changed, 24 insertions, 10 deletions
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index c5e62dd..ee84835 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -622,15 +622,21 @@ struct variant_field /* A variant can contain other variant parts. */ std::vector<variant_part_builder> variant_parts; - /* If we see a DW_TAG_variant, then this will be set if this is the - default branch. */ - bool default_branch = false; /* If we see a DW_AT_discr_value, then this will be the discriminant - value. */ - ULONGEST discriminant_value = 0; + value. Just the attribute is stored here, because we have to + defer deciding whether the value is signed or unsigned until the + end. */ + const attribute *discriminant_attr = nullptr; /* If we see a DW_AT_discr_list, then this is a pointer to the list data. */ struct dwarf_block *discr_list_data = nullptr; + + /* If both DW_AT_discr_value and DW_AT_discr_list are absent, then + this is the default branch. */ + bool is_default () const + { + return discriminant_attr == nullptr && discr_list_data == nullptr; + } }; /* This represents a DW_TAG_variant_part. */ @@ -10269,13 +10275,19 @@ convert_variant_range (struct obstack *obstack, const variant_field &variant, { std::vector<discriminant_range> ranges; - if (variant.default_branch) + if (variant.is_default ()) return {}; if (variant.discr_list_data == nullptr) { - discriminant_range r - = {variant.discriminant_value, variant.discriminant_value}; + ULONGEST value; + + if (is_unsigned) + value = variant.discriminant_attr->unsigned_constant ().value_or (0); + else + value = variant.discriminant_attr->signed_constant ().value_or (0); + + discriminant_range r = { value, value }; ranges.push_back (r); } else @@ -11234,12 +11246,14 @@ handle_variant (struct die_info *die, struct type *type, { discr = dwarf2_attr (die, DW_AT_discr_list, cu); if (discr == nullptr || discr->as_block ()->size == 0) - variant.default_branch = true; + { + /* Nothing to do here -- default branch. */ + } else variant.discr_list_data = discr->as_block (); } else - variant.discriminant_value = discr->constant_value (0); + variant.discriminant_attr = discr; for (die_info *variant_child : die->children ()) handle_struct_member_die (variant_child, type, fi, template_args, cu); |