Placement of trailing record components

Suppose we have this code which defines a record with an array, the size of which depends on a discriminant.

   type Arr is array (Interfaces.Integer_32 range <>) of Interfaces.Integer_32;
   type MyRecord (D : Interfaces.Integer_32 := 0) is record
       X : Interfaces.Integer_32;
       A : Arr(1..D);
   end record;

I need to ensure a specific layout for the type, with the array (A) being placed at the end. So, I came up with this representation, omitting the array altogether.

   for MyRecord use record
     X at 0 range 0..31;
     D at 4 range 0..31;
   end record;

So far, regardless of how I order MyRecord components in the type definition, A gets correctly put at the bottom, -gnatR prints this:

for Myrecord use record
   D at 4 range  0 .. 31;
   X at 0 range  0 .. 31;
   A at 8 range  0 .. ??;
end record;

Question 1: is this in any way a stable/guaranteed behavior [of GNAT]?

Question 2: what if I wanted A to be in any other specific offset in the record, not having a static size to it, can I even write a representation clause for this?

Thank you!

Question 1:

I guess it depends on what location you are trying to avoid putting the array in? You didn’t specify the location you wanted to avoid.

You specify two components (at 0 [0…31] and 4 [0…31]), so nothing can go in those locations but the things you specified. Where are you concerned that the array component may get moved to? The compiler is technically allowed to padd the array component further down than at byte 8 since it isn’t specified. I don’t think that would be a problem in your case though. But we don’t know the location you want to avoid.

Question 2:
I don’t know of a way to do that offhand other than put a dummy component of a fixed size and specify the location of that component to force the array further down. That doesn’t prevent the compiler from moving the array further down though, it just cannot go up.

Maybe someone else has some ideas.

Question 1: Yeah, that is what I was wondering – if, for some reason, the compiler would pad the array component further down – even though I can’t think of a good reason why it would.

Question 2: The idea of a dummy component occurred to me – but as you said, making the compiler move the array won’t be achieved by that. As much I love the idea of trying to wrangle a specific representation in this case, it’s not as useful as the one above – where mapping a “trailing component” of runtime-determined size at the end is very useful.

Since all of the types agree, I’d just make the entire thing an array and treat the first element specially. Of course, if this example isn’t indicative of the true problem in this respect, then what I’ve written isn’t helpful at all.

Use the Pack pragma to avoid excess padding.

Pack is an optimization hint, it does not guarantee a specific layout and can include padding for alignment purposes.

My bad. This was a reduction of a real case, where component types are diverse and do not agree with the array element type.