Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typechecking in gcc macros and type decay

Tags:

c

gcc

macros

This:

#define MC_tpchk(X,Y) \
    ({  __typeof(X) _x; __typeof(Y) _y; (void)(&_x == &_y);  1; })

is stolen (with renames) from the Linux source. I'd like to use it to typecheck some stuff in some of my generic macros (can't use inline functions there).

Unfortunately, it has some issues with string literals:

This all works:

char c_a, c_b;
int i_a, i_b;
char *s_a, *s_b;
MC_tpchk(c_a,c_b);
MC_tpchk(i_a,i_b);
MC_tpchk(s_a,s_b);
char *foo = "foo";
MC_tpchk(s_a,foo);

But this is a compile error:

MC_tpchk(s_a, "foo");

The error:

error: comparison of distinct pointer types lacks a cast [-Werror]

is just a warning if I compile without -Werror, but I would like to keep the -Werror there.

How else can I deal with this error?

My guess is that the detected type is probably char[]. How can I make the compiler show this? Can I make the macro arguments decay (in this case to char*) so this is no longer an error?

like image 272
PSkocik Avatar asked Dec 20 '25 15:12

PSkocik


1 Answers

It does appear to be because the string literal is being detected as an array type. A pointer to an array type does not match a pointer to a pointer type.

I wrote a different macro:

#define MC_tpchk(X,Y) \
    do { \
        break; \
        void (*CHK) (__typeof(X) *); \
        __typeof(Y) _y; \
        CHK(&_y); \
    } while (0)

This seems to provide a more descriptive error:

error: passing argument 1 of 'CHK' from incompatible pointer type
note: expected 'const char **' but argument is of type 'char (*)[4]'

I can't think of a way to decay the array within the macro to properly detect its compatibility with a pointer type. However, the caller of your macro could be conditioned to handle an array differently. So, this would work:

MC_tpchk(s_a, &*"foo");
like image 157
jxh Avatar answered Dec 23 '25 06:12

jxh