Constraint_Error raised when using modular types not divisble by 8
With recent GNATs, you can achieve the behaviour you want by defining Buffer_Type_Two
as
type Buffer_Type_Two is array (1 .. 128) of Type_Two
with Pack;
ARM 13.2(9) warns that this may not do what you want for 13-bit values (recent GNATs do, though).
An alternative would be
type Buffer_Type_Two is array (1 .. 128) of Type_Two
with Component_Size => 12;
The results are
...
Testing type two
Test: 32
Test: 514
Test: 32
Test: 514
...
For 13 bits, with either approach,
...
Testing type two
Test: 32
Test: 257
Test: 2056
Test: 64
Test: 514
Test: 4112
Test: 128
Test: 1028
Test: 32
...
HOWEVER, for an embedded target, you’ll need to use the -full-
runtime system; for others, as pointed out by @egilhh above,
ajxs.adb:14:09: packing of 12-bit components not supported by configuration
Considering the compilation warnings, the code didn’t really deserve to work ...
31. Buffer_One : Buffer_Type_One
32. with Import,
33. Convention => Ada,
34. Address => Test_Buffer'Address;
|
>>> warning: specified address for "Buffer_One" may be inconsistent with alignment
>>> warning: program execution may be erroneous (RM 13.3(27))
>>> warning: alignment of "Buffer_One" is 2
>>> warning: alignment of "Test_Buffer" is 1
and
49. Buffer_Two : Buffer_Type_Two
50. with Import,
51. Convention => Ada,
52. Address => Test_Buffer'Address;
|
>>> warning: specified address for "Buffer_Two" may be inconsistent with alignment
>>> warning: program execution may be erroneous (RM 13.3(27))
>>> warning: alignment of "Buffer_Two" is 2
>>> warning: alignment of "Test_Buffer" is 1
but that’s not the problem, as it happens: Type_Two
is mod 2**12, i.e. mod 4096, but the value in Buffer_Two(1)
is 16#2020# (two space characters), which is 8224 in decimal.
"But why isn’t the stored value automatically masked to the 12 bits I asked for?" you say. For reasons of efficiency, "the size of an object is not necessarily the same as the size of the type of [the] object", GNAT RM 4.43, and GNAT expects the spare 4 bits at the top of the 16-bit word to be zero. On its own, a value of type Type_Two
occupies (has ’Object_Size
of) 16 bits. You could get the 12-bit size you want by including the Type_Two
field in a record and specifying its layout, but that does add complication.
The problem wasn’t detected here without the -gnatVa
(turn on all validity checking options).
The physical value of 16#2020# is not in the range of Type_Two
so Constraint_Error
is expected with -gnatVa.
GNAT CE 2020 raises Constraint_Error
.
Uncommenting the exception/when part leads to further information:
raised CONSTRAINT_ERROR : main.adb:51 invalid data