directly. */
bool is_reference;
+ /* True if this object is actually a dwarf2_field_location_baton. */
+ bool is_field_location;
+
/* The objfile that was used when creating this. */
dwarf2_per_objfile *per_objfile;
dwarf2_per_cu *per_cu;
};
+/* If the DWARF location for a field used DW_AT_bit_size, then an
+ object of this type is created to represent the field location.
+ This is then used to apply the bit offset after computing the
+ field's byte offset. Objects of this type always set the
+ 'is_field_location' member in dwarf2_locexpr_baton. See also
+ apply_bit_offset_to_field. */
+
+struct dwarf2_field_location_baton : public dwarf2_locexpr_baton
+{
+ /* The bit offset, coming from DW_AT_bit_offset. */
+ LONGEST bit_offset;
+
+ /* The DW_AT_byte_size of the field. If no explicit byte size was
+ specified, this is 0. */
+ LONGEST explicit_byte_size;
+};
+
struct dwarf2_loclist_baton
{
/* The initial base address for the location list, based on the compilation
attr = dwarf2_attr (die, DW_AT_data_member_location, cu);
if (attr != NULL)
{
+ bool has_bit_offset = false;
+ LONGEST bit_offset = 0;
+ LONGEST anonymous_size = 0;
+
+ attribute *attr2 = dwarf2_attr (die, DW_AT_bit_offset, cu);
+ if (attr2 != nullptr && attr2->form_is_constant ())
+ {
+ has_bit_offset = true;
+ bit_offset = attr2->unsigned_constant ().value_or (0);
+ attr2 = dwarf2_attr (die, DW_AT_byte_size, cu);
+ if (attr2 != nullptr && attr2->form_is_constant ())
+ {
+ /* The size of the anonymous object containing
+ the bit field is explicit, so use the
+ indicated size (in bytes). */
+ anonymous_size = attr2->unsigned_constant ().value_or (0);
+ }
+ }
+
if (attr->form_is_constant ())
{
LONGEST offset = attr->unsigned_constant ().value_or (0);
}
field->set_loc_bitpos (offset * bits_per_byte);
+ if (has_bit_offset)
+ apply_bit_offset_to_field (*field, bit_offset, anonymous_size);
}
else if (attr->form_is_block ())
{
{
dwarf2_per_objfile *per_objfile = cu->per_objfile;
struct objfile *objfile = per_objfile->objfile;
- struct dwarf2_locexpr_baton *dlbaton
- = OBSTACK_ZALLOC (&objfile->objfile_obstack,
- struct dwarf2_locexpr_baton);
+ struct dwarf2_locexpr_baton *dlbaton;
+ if (has_bit_offset)
+ {
+ dwarf2_field_location_baton *flbaton
+ = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+ dwarf2_field_location_baton);
+ flbaton->is_field_location = true;
+ flbaton->bit_offset = bit_offset;
+ flbaton->explicit_byte_size = anonymous_size;
+ dlbaton = flbaton;
+ }
+ else
+ dlbaton = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+ struct dwarf2_locexpr_baton);
dlbaton->data = attr->as_block ()->data;
dlbaton->size = attr->as_block ()->size;
/* When using this baton, we want to compute the address
/* Get bit offset of field. */
handle_member_location (die, cu, fp);
- attr = dwarf2_attr (die, DW_AT_bit_offset, cu);
- if (attr != nullptr && attr->form_is_constant ())
- {
- LONGEST bit_offset = attr->unsigned_constant ().value_or (0);
-
- LONGEST anonymous_size = 0;
- attr = dwarf2_attr (die, DW_AT_byte_size, cu);
- if (attr != nullptr && attr->form_is_constant ())
- {
- /* The size of the anonymous object containing
- the bit field is explicit, so use the
- indicated size (in bytes). */
- anonymous_size = attr->unsigned_constant ().value_or (0);
- }
-
- apply_bit_offset_to_field (*fp, bit_offset, anonymous_size);
- }
/* Get name of field. */
fieldname = dwarf2_name (die, cu);
if (field.loc_kind () == FIELD_LOC_KIND_DWARF_BLOCK)
{
+ dwarf2_locexpr_baton *field_loc
+ = field.loc_dwarf_block ();
+
struct dwarf2_property_baton baton;
baton.property_type = lookup_pointer_type (field.type ());
- baton.locexpr = *field.loc_dwarf_block ();
+ baton.locexpr = *field_loc;
struct dynamic_prop prop;
prop.set_locexpr (&baton);
CORE_ADDR vals[1] = {addr_stack->addr};
CORE_ADDR addr;
if (dwarf2_evaluate_property (&prop, frame, addr_stack, &addr, vals))
- field.set_loc_bitpos (TARGET_CHAR_BIT * (addr - addr_stack->addr));
+ {
+ field.set_loc_bitpos (TARGET_CHAR_BIT * (addr - addr_stack->addr));
+
+ if (field_loc->is_field_location)
+ {
+ dwarf2_field_location_baton *fl_baton
+ = static_cast<dwarf2_field_location_baton *> (field_loc);
+ apply_bit_offset_to_field (field, fl_baton->bit_offset,
+ fl_baton->explicit_byte_size);
+ }
+ }
}
/* As we know this field is not a static field, the field's
--- /dev/null
+# Copyright 2025 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+load_lib "ada.exp"
+
+require allow_ada_tests
+
+standard_ada_testfile exam
+
+set flags {debug}
+if {[ada_minimal_encodings]} {
+ lappend flags additional_flags=-fgnat-encodings=minimal
+}
+
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable $flags] != ""} {
+ return -1
+}
+
+clean_restart ${testfile}
+
+set bp_location [gdb_get_line_number "STOP" ${testdir}/exam.adb]
+runto "exam.adb:$bp_location"
+
+gdb_test_multiple "print spr" "" {
+ -re -wrap " = \\(discr => 3, array_field => \\(-5, -6, -7\\), field => -4, another_field => -6\\)" {
+ pass $gdb_test_name
+ }
+ -re -wrap " = \\(discr => 3, array_field => \\(-5, -6, -7\\), field => -4, another_field => -4\\)" {
+ # A known GCC bug.
+ xfail $gdb_test_name
+ }
+}
+
+gdb_test "print spr.field" " = -4"
--- /dev/null
+-- Copyright 2025 Free Software Foundation, Inc.
+--
+-- This program is free software; you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation; either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+procedure Exam is
+ type Small is range -7 .. -4;
+ for Small'Size use 2;
+
+ type Packed_Array is array (Integer range <>) of Small;
+ pragma pack (Packed_Array);
+
+ subtype Range_Int is Natural range 0 .. 7;
+
+ type Some_Packed_Record (Discr : Range_Int := 3) is record
+ Array_Field : Packed_Array (1 .. Discr);
+ Field: Small;
+ case Discr is
+ when 3 =>
+ Another_Field : Small;
+ when others =>
+ null;
+ end case;
+ end record;
+ pragma Pack (Some_Packed_Record);
+ pragma No_Component_Reordering (Some_Packed_Record);
+
+ SPR : Some_Packed_Record := (Discr => 3,
+ Field => -4,
+ Another_Field => -6,
+ Array_Field => (-5, -6, -7));
+
+begin
+ null; -- STOP
+end Exam;