[cfe-users] __builtin_constant_p(), __builtin_expect() and __builtin_types_compatible_p() and __has_builtin()

Richard Smith via cfe-users cfe-users at lists.llvm.org
Fri Aug 9 14:58:50 PDT 2019

On Fri, 9 Aug 2019 at 10:32, Chris Hall via cfe-users <
cfe-users at lists.llvm.org> wrote:

> On 09/08/2019 15:00, Matthew Fernandez wrote:
> >> On Aug 9, 2019, at 05:23, Chris Hall via cfe-users wrote:
> >>
> >> I find that __builtin_constant_p() works as expected, but
> >> __has_builtin(constant_p) denies it !
> > I believe you need __has_builtin(__builtin_constant_p).
> Ah :-(  So you do... sorry... I have no idea why I thought otherwise :-(
> >> Similarly __builtin_expect() and __builtin_types_compatible_p() !
> Except that __has_builtin(__builtin_types_compatible_p) also denies it.
>     #include <stdio.h>
>     int
>     main(int argc, char* argv[])
>     {
>       printf("__has_builtin(__builtin_types_compatible_p)=%d\n"
>                            "__builtin_types_compatible_p(int, int)=%d\n"
>                            "__builtin_types_compatible_p(int, long)=%d\n",
>               __has_builtin(__builtin_types_compatible_p),
>                             __builtin_types_compatible_p(int, int),
>                             __builtin_types_compatible_p(int, long)) ;
>     }
> outputs:
>     __has_builtin(__builtin_types_compatible_p)=0
>     __builtin_types_compatible_p(int, int)=1
>     __builtin_types_compatible_p(int, long)=0
> I hope I haven't missed something blindingly obvious this time.

This is a historical accident.

__has_builtin detects builtin *functions*. We also have a bunch of things
that start with __builtin and look somewhat like functions, but that take
types as arguments so can't actually be functions -- instead, they're
keywords with custom parsing rules. __has_builtin doesn't detect those
(because they're not builtin functions).

We've fixed this for such things we added recently, such as
__builtin_bit_cast and __builtin_FILE, but the older ones like
__builtin_types_compatible_p and __builtin_choose_expr and
__builtin_offsetof are unfortunately not detectable by __has_builtin.

There is another way to detect these: use
!__is_identifier(__builtin_types_compatible_p). That will evaluate to 1
whenever __builtin_types_compatible_p is not a valid identifier (because
it's a keyword) -- that is, whenever the feature is available. However,
__is_identifier was added in April 2014, and nearly all the builtins that
__has_builtin can't detect are older than that. So this technique isn't
really useful.

In practice, every version of Clang from the past 10 years supports
__builtin_types_compatible_p (in C mode). So you can just assume it exists.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-users/attachments/20190809/97d5fc4e/attachment.html>

More information about the cfe-users mailing list