I have a (complex) code that works on IAR compiler. I took part of that code to make a snippet to improve it. But while moving a part of this code on an online compiler, it would not compile.
The "error: ‘_Generic’ specifies two compatible types"
Because I was using _Generic as this example:
#define GET_TYPE_(data) _Generic((&data)+0, \
_Bool * : TYPE_BOOL_, \
uint8_t* : TYPE_U8_, \
uint16_t* : TYPE_U16_, \
uint32_t* : TYPE_U32_, \
someEnum1_e* : TYPE_BOOL_, \
someEnum2_e* : TYPE_SPECIAL_A, \
someEnum3_e* : TYPE_SPECIAL_B, \
default: TYPE_DEFAULT_ )
With TYPE_XXX being a #define, then I can call
switch(GET_TYPE_(myVariable))
{
case TYPE_XXXX: do_something(); break;
...
}
But when I moved it with on the online compiler (online gdb) with gcc, i got the error:
error: ‘_Generic’ specifies two compatible types
someEnum1_e* : TYPE_BOOL_, \
error: ‘_Generic’ specifies two compatible types
someEnum2_e* : TYPE_SPECIAL_A, \
error: ‘_Generic’ specifies two compatible types
someEnum3_e* : TYPE_SPECIAL_B, \
I read that this was a normal behavior and that it should not compile. However, how is this possible to compile on IAR?
(yes, i'm asking you to believe me without a reproducible working example because I won't provide my propretary code)
Edit: On godbolt:
"type 'someEnum1_e*' in generic association compatible with previously specified type 'uint32_t *' (aka 'unsigned int *')""error: '_Generic' was not declared in this scope"1st bonus question: Could it be a compiler bug? What does the standard says?
2nd bonus question: Is there a way to avoid the error? (for all compilers)
A short snippet to test my sayings
#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
typedef enum
{
ENUM1_A,
ENUM1_B,
}someEnum1_e;
#define TYPE_E1_ 0
#define TYPE_U32_ 1
#define GET_TYPE_(data) _Generic((&data)+0, \
uint32_t* : TYPE_U32_, \
someEnum1_e* : TYPE_E1_, \
default: TYPE_U32_ )
int main (void)
{
uint32_t foo;
someEnum1_e bar;
switch(GET_TYPE_(foo)){default:break;};
switch(GET_TYPE_(bar)){default:break;};
}
I found a way to compile and run with all compiler in C11 (that accepts the _Generic keyword):
#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
typedef enum
{
ENUM1_A=0,
ENUM1_B,
}someEnum1_e;
typedef union
{
someEnum1_e value;
}someEnum1_e_t;
void print_uint32_t(uint32_t val)
{
printf("uint32_t val = %u\n",val);
}
void print_someEnum1_e_t(someEnum1_e_t val)
{
printf("someEnum1_e_t val = %u\n", val.value);
}
#define PRINT_(data) _Generic((&data)+0, \
uint32_t* : print_uint32_t((uint32_t)*((uint32_t*)&data)), \
someEnum1_e_t* : print_someEnum1_e_t((someEnum1_e_t)*((someEnum1_e_t*)&data)), \
default: printf("hello\n"))
int main (void)
{
uint32_t foo = 32;
someEnum1_e_t blah = {ENUM1_A};
PRINT_(foo);
PRINT_(blah);
}
For this solution to be working, I don't need the macro trick given by Lundin.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With