<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Aug 9, 2019, at 14:58, Richard Smith via cfe-users <<a href="mailto:cfe-users@lists.llvm.org" class="">cfe-users@lists.llvm.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><div dir="ltr" class="">On Fri, 9 Aug 2019 at 10:32, Chris Hall via cfe-users <<a href="mailto:cfe-users@lists.llvm.org" class="">cfe-users@lists.llvm.org</a>> wrote:<br class=""></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-style: solid; border-left-color: rgb(204, 204, 204); padding-left: 1ex;">On 09/08/2019 15:00, Matthew Fernandez wrote:<br class="">>> On Aug 9, 2019, at 05:23, Chris Hall via cfe-users wrote:<br class="">>><br class="">>> I find that __builtin_constant_p() works as expected, but<span class="Apple-converted-space"> </span><br class="">>> __has_builtin(constant_p) denies it !<br class=""><br class="">> I believe you need __has_builtin(__builtin_constant_p).<br class=""><br class="">Ah :-(  So you do... sorry... I have no idea why I thought otherwise :-(<br class=""><br class="">>> Similarly __builtin_expect() and __builtin_types_compatible_p() !<br class=""><br class="">Except that __has_builtin(__builtin_types_compatible_p) also denies it.<br class=""><br class="">   <span class="Apple-converted-space"> </span>#include <stdio.h><br class=""><br class="">   <span class="Apple-converted-space"> </span>int<br class="">   <span class="Apple-converted-space"> </span>main(int argc, char* argv[])<br class="">   <span class="Apple-converted-space"> </span>{<br class="">     <span class="Apple-converted-space"> </span>printf("__has_builtin(__builtin_types_compatible_p)=%d\n"<br class="">                          <span class="Apple-converted-space"> </span>"__builtin_types_compatible_p(int, int)=%d\n"<br class="">                          <span class="Apple-converted-space"> </span>"__builtin_types_compatible_p(int, long)=%d\n",<br class="">             <span class="Apple-converted-space"> </span>__has_builtin(__builtin_types_compatible_p),<br class="">                           <span class="Apple-converted-space"> </span>__builtin_types_compatible_p(int, int),<br class="">                           <span class="Apple-converted-space"> </span>__builtin_types_compatible_p(int, long)) ;<br class="">   <span class="Apple-converted-space"> </span>}<br class=""><br class="">outputs:<br class=""><br class="">   <span class="Apple-converted-space"> </span>__has_builtin(__builtin_types_compatible_p)=0<br class="">   <span class="Apple-converted-space"> </span>__builtin_types_compatible_p(int, int)=1<br class="">   <span class="Apple-converted-space"> </span>__builtin_types_compatible_p(int, long)=0<br class=""><br class="">I hope I haven't missed something blindingly obvious this time.<br class=""></blockquote><div class=""><br class=""></div><div class="">This is a historical accident.</div><div class=""><br class=""></div><div class="">__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 class=""><br class=""></div><div class="">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 class=""><br class=""></div><div class="">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></div></div></blockquote><div><br class=""></div>This thread taught me something too, thanks :) The __is_identifier trick seems even more tricky to use than this implies. E.g. it returns true for __builtin_constant_p because that one is implemented as a function, as you describe. Does this mean to fully detect support for __builtin_foo I need something like `__has_builtin(foo) || __has_builtin(__builtin_foo) || !__is_identifier(__builtin_foo)`?</div><div><br class=""></div><div>While we’re on this topic, are the semantics of __is_identifier just “is not a keyword”? I ask because even when it returns true for a __-prefixed symbol, it’s not an indication you can use it in user code because it’s still reserved for use by the implementation. In fact __is_identifier even returns true for itself, which I guess is technically correct.</div><div><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration: none;" class=""><div class="gmail_quote"><div class="">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></div></blockquote><div><br class=""></div>This is what I do too, as it’s widely supported back to every reasonable version of GCC as well.</div></body></html>