https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120600
Bug ID: 120600 Summary: Inconsistent header name parsing in __has_include Product: gcc Version: 16.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: preprocessor Assignee: unassigned at gcc dot gnu.org Reporter: luigighiron at gmail dot com Target Milestone: --- The following code demonstrates how __has_include inconsistently parses header names: #define X stdio.h #define Y ( #define Z __has_include( int a= #if __has_include Y<X>) 1 #else 0 #endif ; int b= #if Z<X>) 1 #else 0 #endif ; #include<stdio.h> int main(){ printf("%i %i\n",a,b); } Assuming a file named X doesn't exist, 1 0 is printed by GCC. Furthermore, if the opening parenthesis in the definition of Z is replaced by Y then 1 1 is printed. That is, GCC only parses header names if the __has_include and opening parenthesis are not separated. Interestingly, 0 1 is printed when using Clang instead. MSVC prints 0 0 (with and without /Zc:preprocessor), and from my testing will always attempt to parse a header name in __has_include. Parsing header names inconsistently here seems like a bug, I don't see any reason for the behavior to be this way. Also, there is a divergence between compilers about uses of #include such as: #define X stdio.h #define NONE #include NONE<X> GCC has this include stdio.h, while Clang and MSVC (with and without /Zc:preprocessor) have this include X. Though all compilers accept this as including X: #define X stdio.h #define NONE #include<X>NONE The divergence of parsing header names when an empty macro is placed before the header name is also reflected in __has_include. I think the sentence "The identifiers __has_include, __has_embed, and __has_c_attribute shall not appear in any context not mentioned in this subclause." from C23 could be interpreted as making these cases undefined behavior, though macro expansion is described as happening first so that is not how I interpreted it. Moreover, it would be strange to support these uses at all if it is undefined.