https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66970
--- Comment #17 from Jonathan Wakely <redi at gcc dot gnu.org> --- (In reply to felix from comment #7) > I made the feature closely mimic The Other Compiler's behaviour: only > function built-ins are recognised. This includes generic functions like > __builtin_add_overflow and C library functions specially handled by the > front-end like printf (unless -fno-builtin is used), but excludes types like > __builtin_va_list and function-like constructs (implemented as keywords) > like __builtin_offsetof and __builtin_types_compatible_p. This is not so > much of a problem for them, since they also provide __has_feature(), > __has_extension() and __is_identifier() macros. The former has been > requested in PR 60512 and rejected; it may be reasonable to revisit the > issue. I still hate this nonsense. __builtin_offsetof is a keyword not a built-in, similar to __is_aggregate. But __builtin_launder is a built-in not a keyword, like __builtin_add_overflow. Given a built-in name, how on earth am I supposed to know how to detect it? How does a user know whether something is a "function built-in" or a "function-like construct"? #if __has_builtin(__is_aggregate) # if __is_identifier(__is_aggregate) # pragma message("__is_aggregate is a builtin and an identifier") # else # pragma message("__is_aggregate is a builtin but not an identifier") # endif #elif __is_identifier(__is_aggregate) # pragma message("__is_aggregate is not a builtin or a keyword") #else # pragma message("__is_aggregate is not a builtin but is a keyword") #endif #if __has_builtin(__builtin_launder) # if __is_identifier(__builtin_launder) # pragma message("__builtin_launder is a builtin and an identifier") # else # pragma message("__builtin_launder is a builtin but not an identifier") # endif #elif __is_identifier(__builtin_launder) # pragma message("__builtin_launder is not a builtin or a keyword") #else # pragma message("__builtin_launder is not a builtin but is a keyword") #endif #if __has_builtin(__builtin_offsetof) # if __is_identifier(__builtin_offsetof) # pragma message("__builtin_offsetof is a builtin and an identifier") # else # pragma message("__builtin_offsetof is a builtin but not an identifier") # endif #elif __is_identifier(__builtin_offsetof) # pragma message("__builtin_offsetof is not a builtin or a keyword") #else # pragma message("__builtin_offsetof is not a builtin but is a keyword") #endif __is_aggregate is not a builtin but is a keyword __builtin_launder is a builtin and an identifier __builtin_offsetof is not a builtin but is a keyword Anybody who thinks this is a clean way to detect built-ins hasn't actually had to use it.