Other compilers, such as AVR-GCC, require adding "__attribute__((__packed__))" bitfield struct definitions to signal that compiler that the struct should be combined in one data word (e.g. a byte).
SDCC does not require adding this attribute because it automatically infers that the bitfield is to be packed.
However, instead, an error is thrown when this attribute is encountered. For better compatibility to other compilers, I would suggest to ignore this attribute for now, so no code changes are needed when code is transferred between compilers.
struct PORT_bits
{
uint8_t p0:1;
uint8_t p1:1;
uint8_t p2:1;
uint8_t p3:1;
uint8_t p4:1;
uint8_t p5:1;
uint8_t p6:1;
uint8_t p7:1;
} __attribute__((__packed__));
The above struct example does not require any attribute. When the byte boundaries fall on bit-field boundaries, no internal padding is added:
"An implementation may allocate any addressable storage unit large enough to hold a bit-field. If
enough space remains, a bit-field that immediately follows another bit-field in a structure shall be
packed into adjacent bits of the same unit. If insufficient space remains, whether a bit-field that
does not fit is put into the next unit or overlaps adjacent units is implementation-defined." (from the C2X standard draft N2479, but AFAIK this has been the same since ASI C89).
AFAIK, SDCC, at least for mostbackends, does not support packing for cases where a bit-field spans multiple bytes with both boundaries not on byte boundaries, e.g.
will have padding bits in between i and j, so ignoring a __attribute(packed)__ would be misleading.
Also, I wonder if it really makes sense to support that legacy attribute syntax (SDCC already has some support for C2X attributes using the [[ ]] syntax).
Last edit: Philipp Klaus Krause 2020-06-30
Diff:
Furthermore, a simple macro definition can fix this problem.
I've been using
-D__attribute__(a)=on the command line for a while.It works as intended, i.e. discards all such attributes via preprocessor.
The motivation was the same, namely to be able to use unmodified source files.
If you want to translate GCC-style attribute syntax to C2X attribute syntax, the preprocessor can do that, too.
After a bit of stackoverflow research I came up with this preprocessor macro monstrosity:
It will happily transform something like
__attribute__((packed, foo(bar)))into[[packed, foo(bar)]].You could put it in a file named e.g.
attr_syntax_helper.hand include it via-Wp -include,attr_syntax_helper.h.That should work for most use-cases.
AFAIK, there are a few exceptions, where GCC attributes can be placed in a location different from the C23 attributes, though (I think in function declarations, GCC attributes that actually apply to the function type can be placed as if they'd apply to the declaration instead of the type).
P.S.: Interestingly, this difference in attribute placement means that the standard attribute placement works like the current SDCC "attribute" placement for stuff like __z88dk_fastcall, __naked etc, while the GCC attributes can also be placed in the location where the non-free competition (IAR, Cosmic, Raisonance, etc) place them.
Last edit: Philipp Klaus Krause 2022-03-09
Starting with [r13239], this style of conversion is provided in
gcc_attr.h, which can either be included normally or via--include gcc_attr.hon the command line.Related
Commit: [r13239]
I'd assume that that the GCC syntax will quickly die out. Now that we have the C23 attribute syntax approved by SC22 WG14, which is also the same syntax C++ uses.
Implemented using preprocessor magic:
Use
--include gcc_attr.hto pre-include a helper header that translates the GCC syntax to C23 syntax when in C23 mode and discards all attributes, otherwise.