One possibility would be to declare the operations of Record_Type
in a nested package, say Ops
, so that they aren't primitive:
package Union is
type Access_Kind is (Named, Indexed);
type Array_Type is array (0 .. 1) of Integer;
type Record_Type (Kind : Access_Kind := Access_Kind'First) is record
case Kind is
when Named =>
X, Y : Integer;
when Indexed =>
S : Array_Type;
end case;
end record;
pragma Unchecked_Union (Record_Type);
pragma Convention (C_Pass_By_Copy, Record_Type);
-- If P was declared immediately within Union, it would be
-- primitive, and it wouldn't be possible to declare
-- representation aspects for Integer2.
package Ops is
procedure P (R : Record_Type) is null;
-- "is null" only so that I can use -gnatR without needing a
-- body.
end Ops;
type Integer2 is new Record_Type;
pragma Unchecked_Union (Integer2);
pragma Convention (C_Pass_By_Copy, Integer2);
end Union;
Using -gnatR
to display the chosen representation, I get
$ gnatmake -c -u -f -gnatwa union.ads -gnatR
gcc -c -gnatwa -gnatR -gnat05 union.ads
Representation information for unit Union (spec)
------------------------------------------------
for Array_Type'Size use 64;
for Array_Type'Alignment use 4;
for Array_Type'Component_Size use 32;
for Record_Type'Size use 64;
for Record_Type'Alignment use 4;
for Record_Type use record
Kind at ?? range 0 .. -1;
X at 0 range 0 .. 31;
Y at 4 range 0 .. 31;
S at 0 range 0 .. 63;
end record;
for Integer2'Size use 64;
for Integer2'Alignment use 4;
for Integer2 use record
Kind at ?? range 0 .. -1;
X at 0 range 0 .. 31;
Y at 4 range 0 .. 31;
S at 0 range 0 .. 63;
end record;
That said, I think GNAT's behaviour is wrong.
ARM 13.1(0.1) says that there are representational and operational aspects, and (1) defines the representational aspects. (10) is why we need to avoid primitive operations. (15) says that representational aspects are inherited by derived types; but (15.1) says that operational aspects are not, "unless specified" for the specific aspect. I guess that "specified" means "in the ARM for language-defined aspects, or by the vendor for vendor-defined aspects".
B3.3(3.1) states that Unchecked_Union
is a representation aspect. It should therefore be inherited.
B3.1(0.1) states that interfacing aspects, including Convention
, are representation aspects. C_Pass_By_Copy
should therefore be inherited.
I'll work up a bug report.