https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66970
--- Comment #18 from felix <felix.von.s at posteo dot de> --- Proper built-ins are ordinary identifiers subject to ordinary name resolution and shadowing, so the 'keyword built-in' case is impossible. If you don't know if (or don't want to depend on the fact that) a given built-in is a keyword or an intrinsic function, `__has_builtin(x) || !__is_identifier(x)` should suffice. In a way, that detail is already exposed to user code: `int __builtin_abort = 0;` compiles, but `int __builtin_choose_expr = 0;` doesn't. The documentation doesn't mention this, however; keyword built-ins are actually documented as being functions in the manual, either explicitly or implicitly (by being listed alongside true intrinsic functions with no discriminating features). So even if this feature is adopted as-is, it will necessitate some changes in the documentation. And while I can sympathise with claims that this behaviour is surprising, what are the alternatives? If keywords should count as built-ins, should __has_builtin(sizeof) expand to 1? Should __has_builtin(volatile)?