Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

__builtin_types_compatible_p(t1, t2) and pointers to qualified types

The gcc documentation says that __builtin_types_compatible_p(t1, t2) "ignores top level qualifiers (e.g. const, volatile)", and indeed it does:

__builtin_types_compatible_p(int, const int)     returns 1
__builtin_types_compatible_p(int, volatile int)  also returns 1

I do not know what it means by "top level qualifiers", but pointers to things-which-are-compatible, are reported as not compatible:

__builtin_types_compatible_p(int *, const int *)     returns 0
__builtin_types_compatible_p(int *, volatile int *)  also returns 0
__builtin_types_compatible_p(void *, void *)         returns 1
__builtin_types_compatible_p(void *, const void *)   returns 0

which is, frankly, a surprise :-(

Can anyone provide a reason for this ? [Is my surprise a symptom of ignorance ?]


FWIW: I can work around this using __typeof__(), thus:

__builtin_types_compatible_p(__typeof__(*(void*)0), __typeof__(*(const void*)0))) returns 1

typedef int*       pi_t ;
typedef const int* pic_t ;
__builtin_types_compatible_p(__typeof__(*(pi_t)0), __typeof__(*(pic_t)0))) returns 1

Since __typeof__() accepts both an expression and a type, I have a macro:

#define Types_Compatible(_a, _b) \
  __builtin_types_compatible_p(__typeof__(_a), __typeof__(_b)) 

to slightly reduce the clutter.

like image 1000
Chris Hall Avatar asked Oct 15 '25 19:10

Chris Hall


1 Answers

int and const int are compatible as everywhere an int is expected (eg as a function parameter) a const int can be given. And, importantly, vice versa. The const and volatile only affect the variable, not the value.

That is not the case for int* and const int*. If a function requires an int* you can not supply a const int*. If you try that you will get an 'incompatible types' error. For pointers the const and volatile refer to the value, not the variable. (In most cases, it depends on where you put the const)

And your "workaround" just derefences the pointer so it gets rid of the pointer, so it ultimately answers a different question. It determines if the types pointed to are compatible, which is different from the pointer type itself.

like image 193
koder Avatar answered Oct 18 '25 12:10

koder