Correctly compute length of DW_TAG_variant_part union
authorTom Tromey <tom@tromey.com>
Sat, 30 Nov 2019 17:05:23 +0000 (10:05 -0700)
committerTom Tromey <tom@tromey.com>
Sun, 1 Dec 2019 03:47:44 +0000 (20:47 -0700)
Currently, gdb internally transforms DW_TAG_variant_part into a union
(with some special attbributes).  When doing so, it computes the
length of this union from the length of the fields.  However, this
computation didn't include the offset of these fields, resulting in
the length being too short.

This is not a problem given the way the code currently works.
However, I have a patch series to switch gdb to value-based printing,
where this does have an impact.

Tested on x86-64 Fedora 28; and, considering that this only affects
Rust, I am checking it in.

gdb/ChangeLog
2019-11-30  Tom Tromey  <tom@tromey.com>

* dwarf2read.c (dwarf2_add_field): Include field offset when
computing variant part length.

Change-Id: I25d84fc237eb3c1e7f11f6eaf35ffe198efde6cc

gdb/ChangeLog
gdb/dwarf2read.c

index 96efdb0f40dad38393b14d3267221316c54cd015..621cbbbf95938c15d541fae4ce5667ee5715ca12 100644 (file)
@@ -1,3 +1,8 @@
+2019-11-30  Tom Tromey  <tom@tromey.com>
+
+       * dwarf2read.c (dwarf2_add_field): Include field offset when
+       computing variant part length.
+
 2019-11-30  Philippe Waroquiers  <philippe.waroquiers@skynet.be>
        * NEWS:  Mention define-prefix.  Tell that command names can now
        contain a . character.
index 40626a1562f0ca96106dfa78b727b0cb712e704f..fd7d21c02e949341167af19a4794b5489e6550ff 100644 (file)
@@ -15252,13 +15252,18 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
 
       /* Normally a DW_TAG_variant_part won't have a size, but our
         representation requires one, so set it to the maximum of the
-        child sizes.  */
+        child sizes, being sure to account for the offset at which
+        each child is seen.  */
       if (TYPE_LENGTH (fp->type) == 0)
        {
          unsigned max = 0;
          for (int i = 0; i < TYPE_NFIELDS (fp->type); ++i)
-           if (TYPE_LENGTH (TYPE_FIELD_TYPE (fp->type, i)) > max)
-             max = TYPE_LENGTH (TYPE_FIELD_TYPE (fp->type, i));
+           {
+             unsigned len = ((TYPE_FIELD_BITPOS (fp->type, i) + 7) / 8
+                             + TYPE_LENGTH (TYPE_FIELD_TYPE (fp->type, i)));
+             if (len > max)
+               max = len;
+           }
          TYPE_LENGTH (fp->type) = max;
        }
     }