I don't know whether this is already a known problem (because I remember other structure packing/aligning related problems) but the following code provides an example that causes the FreeBasic compiler to fail when using the gcc backend and compiling for a 64-bit target. The problem is that a (e.g. 12-byte) field inside a UDT is not correctly padded by gcc if that inner field was defined using the "packed" attribute obviously overriding the default alignments. In the following example the inner field is declared with "field=1" and put into an UDT with "field=8".
Code: Select all
type t12byte field=1
as longint a
as long b
end type
type t16byte field=8
as t12byte a
end type
print sizeof(t12byte)
print sizeof(t16byte)
dim dummy as t16byte
The resulting size of the UDT should be 16-bytes (4 bytes padding) but gcc does not add padding. This results in a compilation error caused by an internal size check added by the compiler:
Code: Select all
test.c:15:47: error: size of array '__$fb_structsizecheck' is negative
#define __FB_STATIC_ASSERT( expr ) extern int __$fb_structsizecheck[(expr) ? 1 : -1]
^
test.c:20:1: note: in expansion of macro '__FB_STATIC_ASSERT'
__FB_STATIC_ASSERT( sizeof( struct $7T16BYTE ) == 16 );
^
When we have a look at the generated C code we'll see that the problem could be avoided (by the compiler) by adding an explicit alignment hint for the UDT field like this:
Code: Select all
struct __attribute__((gcc_struct)) $7T12BYTE {
int64 A __attribute__((packed, aligned(1)));
int32 B __attribute__((packed, aligned(1)));
};
struct __attribute__((gcc_struct)) $7T16BYTE {
struct $7T12BYTE A __attribute__((aligned(8)));
};
Of course, in this simple example it would be possible to declare the inner UDT with "field=4" instead of "field=1", which also solves the problem, but such a solution is not always available.
My questions: Is it a known problem or shall a bug report be created? Which workarounds exist? Are there any reasons for the compiler not always emitting the "alignment" attribute for each field?