LemonBoy/bar

Compilation error

shameempk opened this issue · 3 comments

OS: CentOS 6.9
gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-18)

make fails at:

 $ make
cc -Wall -std=c99 -Os -DVERSION="\"35183ab\"" -o lemonbar.o -c lemonbar.c
lemonbar.c:57: warning: declaration does not declare anything
lemonbar.c: In function ‘fill_gradient’:
lemonbar.c:120: error: ‘rgba_t’ has no member named ‘r’
lemonbar.c:120: error: ‘rgba_t’ has no member named ‘r’
lemonbar.c:121: error: ‘rgba_t’ has no member named ‘g’
lemonbar.c:121: error: ‘rgba_t’ has no member named ‘g’
lemonbar.c:122: error: ‘rgba_t’ has no member named ‘b’
lemonbar.c:122: error: ‘rgba_t’ has no member named ‘b’
lemonbar.c:126: error: unknown field ‘r’ specified in initializer
lemonbar.c:127: error: unknown field ‘g’ specified in initializer
lemonbar.c:127: warning: excess elements in union initializer
lemonbar.c:127: warning: (near initialization for ‘step’)
lemonbar.c:128: error: unknown field ‘b’ specified in initializer
lemonbar.c:128: warning: excess elements in union initializer
lemonbar.c:128: warning: (near initialization for ‘step’)
lemonbar.c:129: error: unknown field ‘a’ specified in initializer
lemonbar.c:129: warning: excess elements in union initializer
lemonbar.c:129: warning: (near initialization for ‘step’)
lemonbar.c: In function ‘parse_color’:
lemonbar.c:303: error: ‘rgba_t’ has no member named ‘a’
lemonbar.c:315: error: ‘rgba_t’ has no member named ‘a’
lemonbar.c:318: error: unknown field ‘r’ specified in initializer
lemonbar.c:318: error: ‘rgba_t’ has no member named ‘r’
lemonbar.c:318: error: ‘rgba_t’ has no member named ‘a’
lemonbar.c:319: error: unknown field ‘g’ specified in initializer
lemonbar.c:319: error: ‘rgba_t’ has no member named ‘g’
lemonbar.c:319: error: ‘rgba_t’ has no member named ‘a’
lemonbar.c:319: warning: excess elements in union initializer
lemonbar.c:319: warning: (near initialization for ‘(anonymous)’)
lemonbar.c:320: error: unknown field ‘b’ specified in initializer
lemonbar.c:320: error: ‘rgba_t’ has no member named ‘b’
lemonbar.c:320: error: ‘rgba_t’ has no member named ‘a’
lemonbar.c:320: warning: excess elements in union initializer
lemonbar.c:320: warning: (near initialization for ‘(anonymous)’)
lemonbar.c:321: error: unknown field ‘a’ specified in initializer
lemonbar.c:321: error: ‘rgba_t’ has no member named ‘a’
lemonbar.c:321: warning: excess elements in union initializer
lemonbar.c:321: warning: (near initialization for ‘(anonymous)’)
make: *** [lemonbar.o] Error 1

I was able to bypass this error by changing:

typedef union rgba_t {
    struct {
        uint8_t b;
        uint8_t g;
        uint8_t r;
        uint8_t a;
    };
    uint32_t v;
} rgba_t;

to:

typedef union rgba_t {
    //struct {
        uint8_t b;
        uint8_t g;
        uint8_t r;
        uint8_t a;
    //};
    uint32_t v;
} rgba_t;

then it gets compiled but bar does not show up.

Bleh, try changing -std=c99 into -std=gnu99 in the Makefile.
The anonymous-struct-in-union trick isn't quite C99 compliant but it's quite nice, the proper (?) solution would be to change the declaration above into

typedef union rgba_t {
    struct {
        uint8_t b;
        uint8_t g;
        uint8_t r;
        uint8_t a;
    } c;
    uint32_t v;
} rgba_t;

And change every <obj>.{argb} into <obj>.c.{argb} but I'm not interested in doing so.
Feel free to re-open the ticket if you have further problems.

changing -std=c99 into -std=gnu99 in the Makefile

Yeah it solved the compilation error.

The anonymous-struct-in-union trick isn't quite C99 compliant but it's quite nice ...

This union (and accompanying code) seems to have other issues, besides the anonymous struct:

  • Storing to one member of a union and then loading from another is implementation-defined behaviour in C99.
  • Even if the above is defined the way you want, it still seems to assume little endian layout.
  • It assumes no padding is added to the struct, even though compilers are well within their rights to do so (albeit unlikely in this case).

... the proper (?) solution would be to change the declaration ...

A C99 compliant solution would be to use a plain uint32_t, with shifting and masking to get/set the components.