010302.2 A T. Allen Ada Byte size and bit offset as object attributes


First, some background for the non-Ada-aware:

Ada has the concept of a renaming declaration, which is a bit like a C++
reference. In cases where the renamee is a complex expression, the address
of the renamee may need to be frozen at the time of the renaming
declaration's elaboration. This is true if any part of the expression is a
variable which might change after the declaration. The identity of the
renamee must not change in such a case. For instance:

    procedure example is
        type teeny is range 0 .. 15;
        for teeny'size use 4;
        type arr is array (boolean) of teeny;
        pragma pack(arr);
        type ack is access arr;

        obj : ack := new arr'(false => 1,
                              true => 2);
        bool : boolean := true;
        ren : teeny renames obj.all(bool);
        bool := false;
        obj := new arr'(false => 4,
                        true => 8);
        -- at this point ren = 2
    end example;

This is an especially nefarious example because the first allocation has
almost become garbage at the point of the comment, since in the absence of
ren, there would be no references to it at all. And this is one important
reason the address of ren must be frozen. If it were not, there would be no
other way to reach the correct object.

Now, the heart of the matter:

The renamee is permitted to be a bit field, or other object not aligned on a
byte boundary or not byte sized.

By using the 'size clause on type teeny and pragma pack on type arr, I
instructed the compiler to make each element of the array 4 bits big, and to
pack them together as tightly as possible. So, ren is really referring to a
field 4 bits into the first allocation. I've got to indicate the bit offset
for that. And the bit offset is dynamic, depending on the value of bool.
(Yeah, we know what it is in the example. But it didn't have to be that

So, when ren is frozen, not only is its address saved, but also its bit
offset is saved. To indicate that to the debugger, we need to allow the
DW_AT_bit_offset to be a reference to another object.

Similarly, DW_AT_bit_size and DW_AT_byte_size could benefit from the ability
to reference another object, too. For instance, the size of array objects
with variable numbers of components might be stored somewhere in the program,
and could be referenced by these attributes.

And as long as DWARF 2.1 has DWARF expressions now, I see no reason not to
include them as a possibility, too. (Actually, given this, we could describe
the sizes of some of our Ada types that we can't describe now, instead of
burdening the debugger with having to do complicated size calculations.)

Also, it is convenient to allow objects to have the DW_AT_bit_offset and
DW_AT_bit_size attributes. This is a space saver. Otherwise, it would be
necessary to reiterate the type of each of these objects just to tweak the
offsets and/or sizes.


  | 2.18 Object Sizes and Offsets
  | Any debugging information entry describing a data object or component, or
  | a data type whose objects are all of the same size, may have any of the
  | DW_AT_byte_size, DW_AT_bit_size, or DW_AT_bit_offset attributes. Each can
  | be a constant, a reference to an object, or a DWARF expression.
  | If present, the value of DW_AT_byte_size gives the size in bytes. If
  | present, the value of DW_AT_bit_size gives the size in bits. If the size
  | is an integral number of bytes, then either the DW_AT_byte_size or
  | DW_AT_bit_size attributes should be present, but both are not required.
  | If the size is not an integral number of bytes, the DW_AT_bit_size
  | attribute should be present. If the DW_AT_byte_size attribute also is
  | present, it should give the next higher integral number of bytes
  | (i.e. round up).
  | If present, the DW_AT_bit_offset gives the offset in bits of the high
  | order bit of a value of the given type from the high order bit of the
  | storage unit used to contain that value.
  | Notwithstanding the above text, the DW_AT_byte_size, DW_AT_bit_size, and
  | DW_AT_bit_offset attributes need not be specified for any object if their
  | values are the same as those specified or implied for the object's type.

    5.1 Base Type Entries

  X [Remove the last 3 paragraphs from this section.]

    5.6.6 Data Member Entries

  X [Remove paragraphs:]
  X If the data member entry describes a bit field, ...
  X     :
  X A DW_AT_bit_size attribute whose integer constant value is the number of
  X bits occupied by the bit field value.

Partially adopted: Change 5.1, 5.5, 5.6.1, 5.6.6, (and any other appropriate sections) to permit expressions as well as constant values for DW_AT_byte_size and DW_AT_bit_offset.