Petr Skocik
Petr Skocik

Reputation: 60067

Typechecking in gcc macros and type decay

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?

Upvotes: 3

Views: 283

Answers (1)

jxh
jxh

Reputation: 70422

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");

Upvotes: 4

Related Questions