<div dir="ltr"><div dir="ltr">On Fri, 9 Aug 2019 at 10:32, Chris Hall via cfe-users <<a href="mailto:cfe-users@lists.llvm.org">cfe-users@lists.llvm.org</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On 09/08/2019 15:00, Matthew Fernandez wrote:<br>
>> On Aug 9, 2019, at 05:23, Chris Hall via cfe-users wrote:<br>
>><br>
>> I find that __builtin_constant_p() works as expected, but <br>
>> __has_builtin(constant_p) denies it !<br>
<br>
> I believe you need __has_builtin(__builtin_constant_p).<br>
<br>
Ah :-(  So you do... sorry... I have no idea why I thought otherwise :-(<br>
<br>
>> Similarly __builtin_expect() and __builtin_types_compatible_p() !<br>
<br>
Except that __has_builtin(__builtin_types_compatible_p) also denies it.<br>
<br>
    #include <stdio.h><br>
<br>
    int<br>
    main(int argc, char* argv[])<br>
    {<br>
      printf("__has_builtin(__builtin_types_compatible_p)=%d\n"<br>
                           "__builtin_types_compatible_p(int, int)=%d\n"<br>
                           "__builtin_types_compatible_p(int, long)=%d\n",<br>
              __has_builtin(__builtin_types_compatible_p),<br>
                            __builtin_types_compatible_p(int, int),<br>
                            __builtin_types_compatible_p(int, long)) ;<br>
    }<br>
<br>
outputs:<br>
<br>
    __has_builtin(__builtin_types_compatible_p)=0<br>
    __builtin_types_compatible_p(int, int)=1<br>
    __builtin_types_compatible_p(int, long)=0<br>
<br>
I hope I haven't missed something blindingly obvious this time.<br></blockquote><div><br></div><div>This is a historical accident.</div><div><br></div><div>__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).</div><div><br></div><div>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.</div><div><br></div><div>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.</div><div><br></div><div>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.</div></div></div>