__has_include, and __has_embedAuthors: Jay Ghiron
Date: 2026-06-02
Submitted against: C23
Status: Open
For this issue, assume the following macros are always defined:
#define E
#define S <
#define C(A,B)A##B
#define H __has_include
#define G __has_include(
#define L (
#define X Y
#define Z <X>
Additionally, assume that the implementation has the header name <X>
identify a file named X and has the three preprocessing tokens <,
Y, and > with no whitespace between identify a file named Y when
used in place of a header name. GCC, Clang, MSVC, and EDG all agree
on the behavior of the following:
#include<X>
#include Z
Which includes a file named X and then a file named Y. <X> in
the first #include directive forms a header name, but the second
#include directive does not since the <X> is not present in the
#include directive. Since the second #include directive does not
form a header name the X inside of the angle brackets gets expanded
to become Y. The macro X here is used to test if a header name is
formed which contains X. Header name formation is also visible with
sequences of characters that can form preprocessing tokens other than
< and > punctuators:
#include<->
#define HYPHEN <->
#include HYPHEN
The first #include directive can be valid, but the second #include
directive is not valid because HYPHEN gets lexed as two
preprocessing tokens < and -> rather than three preprocessing
tokens <, -, and >. Implementations sometimes do not reject
using preprocessing tokens other than < and > at the beginning and
ending respectively, but the intent seems clear enough that other
punctuator preprocessing tokens cannot be used. In C++ CWG
3015
and C++ CWG
3078
the parsing of header names has been clarified there, but no compilers
seem to actually implement those defect reports yet. Most of the
following questions will be using #include and __has_include, but
the same issues exist for #embed and __has_embed as well. In the
following questions, assume that any included file exists and is
valid.
#include<X>E
Is this valid? That is, if an #include directive does not include
just a header name can the preprocessing tokens inside of it expand to
a header name? GCC, Clang, MSVC, and EDG all accept this as including
a file named X. All further questions assume that this is valid.
#include E<X>
Does this include a file named X or a file named Y? GCC and EDG
include a file named Y, Clang and MSVC include a file named X.
The wording "within #include and #embed preprocessing directives,
in __has_include and __has_embed expressions" (C23 6.4.1 paragraph
4) is not clear about whether this counts as within the preprocessing
directive. This also applies to __has_include:
#if __has_include(E<X>)
1
#else
0
#endif
Does this test for the existence of a file named X or a file named
Y? GCC and EDG test for the existence of a file named Y, Clang
and MSVC test for the existence of a file named X.
#include S<X>
If the answer to question two is that #include E<X> includes a file
named X, is this valid or invalid and does it expand X? If a
header name is formed, it appears that the result would be invalid.
GCC, Clang, and EDG all accept this as valid and do expand X. MSVC
with its old preprocessor accepts this as valid and does not expand
X. MSVC with its new preprocessor rejects this as invalid. This
also applies to __has_include:
#if __has_include(S<X>)
1
#else
0
#endif
If the answer to question two is that __has_include(E<X>) tests for
the existence of a file named X, is this valid or invalid and does
it expand X? If a header name is formed, it appears that the result
would be invalid. GCC, Clang, and EDG all accept this as valid and do
expand X. MSVC with its old preprocessor accepts this as valid and
does not expand X. MSVC with its new preprocessor rejects this as
invalid.
Can token concatenation form header names? For example:
#include C(<=,>)
Does this form the header name <=> in token concatenation? GCC,
Clang, MSVC, and EDG all do not allow this but the wording in the
standard does not clearly forbid it. If it is possible, the following
is an exhaustive list of all possible header names that could be
formed from concatenation: <->, <:>, <%>, <=>, <=->, <=:>,
<=%>, <<>, <<->, <<:>, <<%>, <<=>, <<=->, <<=:>,
<<=%>, <:->, <::>, <:%>, <%->, <%:>, and <%%>.
Can __has_include, __has_embed, and __has_c_attribute
expressions be the result of macro expansions?
The identifiers
__has_include,__has_embed, and__has_c_attributeshall not appear in any context not mentioned in this subclause.
(C23 6.10.2 "Conditional inclusion" paragraph 11.)
GCC, Clang, MSVC, and EDG all do not reject macros like H, though it
seems like the above sentence can be construed as making H
undefined. If it should be interpreted as making H undefined, then
in C++ which uses the same wording it should be ill-formed there due
to the different meaning of "shall". Note that there is a significant
amount of code which does roughly the following:
#ifdef __has_include
#define MY_HAS_INCLUDE(...)__has_include(__VA_ARGS__)
#else
#define MY_HAS_INCLUDE(...)0
#endif
#if H(<X>)
1
#else
0
#endif
If the answer to question five is that __has_include can be the
result of macro expansions, does this test for the existence of a file
named X or a file named Y? GCC, Clang, MSVC, and EDG all agree
that this tests for the existence of a file named X, even though
reaching such a result requires that translation phase three knows
about macro expansion.
#if G<X>)
1
#else
0
#endif
If the answer to question five is that __has_include can be the
result of macro expansions, does this test for the existence of a file
named X or a file named Y? GCC, MSVC, and EDG test for the
existence of a file named X, Clang tests for the existence of a file
named Y.
#if __has_include L<X>)
1
#else
0
#endif
Does this test for the existence of a file named X or a file named
Y? Clang, MSVC, and EDG test for the existence of a file named X,
GCC tests for the existence of a file named Y.
Depending upon how previous questions are answered, if lexing depends upon macro definitions then this creates awkward situations in skipped preprocessing directives:
#if 1
#elif __has_include("\"")
#elif H("\"")
#endif
Does the skipped __has_include("\"") attempt to form the invalid
header name "\" and then the invalid incomplete string literal? The
wording does not seem to make any distinction of lexing in skipped
preprocessing directives, but GCC and Clang seem to try to form string
literals here despite __has_include being used. MSVC and EDG will
accept any sequence of characters inside of skipped preprocessing
directives, even those that do not form valid preprocessing tokens.
Since H cannot be expanded here, it seems like H("\"") must be
lexed as containing a string literal "\"".
Can __has_include, __has_embed, and __has_c_attribute expressions be
passed as arguments to macros, and if they can are header names still
formed in __has_include and __has_embed? If it is possible and header
names are still formed, then those header names can be extracted:
#define HEADER__has_include(...)__VA_ARGS__
#define HEADER(...)HEADER##__VA_ARGS__
#if __has_include(HEADER(__has_include(<X>)))
1
#else
0
#endif
GCC, MSVC with its old preprocessor, and EDG test for the existence of
a file named Y, Clang and MSVC with its new preprocessor test for the
existence of a file named X. With the following slight variation:
#define HEADER__has_include
#define HEADER(...)HEADER##__VA_ARGS__
#if __has_include HEADER(__has_include(<X>))
1
#else
0
#endif
MSVC will test for a file named Y in both its old preprocessor and
new preprocessor. GCC, Clang, and EDG all behave the same in this
variation. If header names can be used in arguments to macros, then
they can also be subject to stringization and concatenation. In C++
header names are conditionally allowed to contain backslashes and
quotes, so stringization there mentions header names as needing
escaping. It appears that quoted header names can be concatenated
with an encoding prefix to form a string literal. Header name
formation is also visible in this context with header names such as
<)> or <,> since they would otherwise affect how the arguments to
a function-like macro are identified.
#if __has_embed("something"limit(defined __has_embed))
1
#else
0
#endif
Is this valid? That is, does the defined macro expression get
replaced inside of the __has_embed expression considering it gets
replaced first:
After all replacements due to macro expansion and evaluations of defined macro expressions, has_include expressions, has_embed expressions, and has_c_attribute expressions have been performed, all remaining identifiers other than
true(including those lexically identical to keywords such asfalse) are replaced with the pp-number0,trueis replaced with pp-number1, and then each preprocessing token is converted into a token.
(C23 6.10.2 "Conditional inclusion" paragraph 13.)
GCC and Clang reject this as invalid, MSVC and EDG do not support
__has_embed yet. C++ explicitly disallows this and it seems like
N3811 wants to disallow it. Though the wording in N3811 would not
actually disallow it if defined macro expressions in __has_embed
expressions get replaced before they are considered.