> Reply-To: "W. Wesley Groleau x4923" <[log in to unmask]>
> 5. Use re-specification of derived types.  This would also take some
>    amount of re-tooling.  Only you can say how much.  This is a technique
>    taught to me ten years ago when I was learning Ada 83, but I have since
>    met many Ada programmers that don't know about it.  (I don't recall
>    ever actually using it myself.)  Here is a partial example for
>    four-octet integers.  (I omitted the unchecked conversions, which
>    should be obvious):
[..]
>    -- the catch is that the compiler has to be smart enough to
>    handle it, instead of stupidly implementing the conversion as an
>    unchecked conversion.  I do not know whether the ACVC tests this,
>    and I have not yet had the time to test it on GNAT or Apex or
>    ObjectAda.  In fact, as you can see, I haven't even yet added the
>    print statements to verify whether it works.  But it SHOULD work.
>    If anyone else has a chance to test it on any compiler, please
>    share with me the test code and the results.

This is the technique we use with GNAT, using quite complex types,
successfully. The code below works (in its original context! a
Things.Value is a subtype of Interfaces.C.Int range -2**23 .. 2**23-1)

  type Address is mod 2**18;

  type Raw_Count is mod 2**6;

  type Pad is array (Natural range <>) of Boolean;
  pragma Pack (Pad);

  type Control_Word_2 is record
    Secondary_Address : Address;
    Count : Raw_Count;
    Padding_24_31 : Pad (24 .. 31);
  end record;

  package Control_Word_2_Conversions is
    function Convert (Item : Things.Value) return Control_Word_2;
    function Convert (Item : Control_Word_2) return Things.Value;
  end Control_Word_2_Conversions;

  package body Control_Word_2_Conversions is

    type Control_Word_2_Rep_L is new Control_Word_2;

    for Control_Word_2_Rep_L use record
      Secondary_Address at 0 range 0 .. 17;
      Count at 0 range 18 .. 23;
      Padding_24_31 at 0 range 24 .. 31;
    end record;
    for Control_Word_2_Rep_L'Size use Things.Value'Size;

    type Control_Word_2_Rep_B is new Control_Word_2;

    for Control_Word_2_Rep_B use record
      Secondary_Address at 0 range 14 .. 31;
      Count at 0 range 8 .. 13;
      Padding_24_31 at 0 range 0 .. 7;
    end record;
    for Control_Word_2_Rep_B'Size use Things.Value'Size;

    function Convert (Item : Things.Value) return Control_Word_2 is
      Result : Control_Word_2;
    begin
      if System.Default_Bit_Order = System.Low_Order_First then
        declare
          function Convert_To_Rep is
             new Unchecked_Conversion (Things.Value,
                                       Control_Word_2_Rep_L);
        begin
          Result := Control_Word_2 (Convert_To_Rep (Item));
        end;
      else
        declare
          function Convert_To_Rep is
             new Unchecked_Conversion (Things.Value,
                                       Control_Word_2_Rep_B);
        begin
          Result := Control_Word_2 (Convert_To_Rep (Item));
        end;
      end if;
      return Result;
    end Convert;

    function Convert (Item : Control_Word_2) return Things.Value is
      Result : Things.Value;
    begin
      if System.Default_Bit_Order = System.Low_Order_First then
        declare
          function Convert_From_Rep is
             new Unchecked_Conversion (Control_Word_2_Rep_L,
                                       Things.Value);
        begin
          Result := Convert_From_Rep (Control_Word_2_Rep_L (Item));
        end;
      else
        declare
          function Convert_From_Rep is
             new Unchecked_Conversion (Control_Word_2_Rep_B,
                                       Things.Value);
        begin
          Result := Convert_From_Rep (Control_Word_2_Rep_B (Item));
        end;
      end if;
      return Result;
    end Convert;

  end Control_Word_2_Conversions;