Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Macro replacement is performed in a has-include-expression? #5192

Open
xmh0511 opened this issue Jan 10, 2022 · 2 comments
Open

Macro replacement is performed in a has-include-expression? #5192

xmh0511 opened this issue Jan 10, 2022 · 2 comments

Comments

@xmh0511
Copy link
Contributor

xmh0511 commented Jan 10, 2022

#include <iostream>
#define Head <iostream>
# if __has_include(Head)
#define Pn 0
#endif 

#ifndef Pn
#define Pn 1
#endif
int main(){
   std::cout<< Pn;
}

Consider this example, GCC and Clang both print 0. But rather, as per [cpp.cond] p4

The header or source file identified by the parenthesized preprocessing token sequence in each contained has-include-expression is searched for as if that preprocessing token sequence were the pp-tokens in a #include directive, except that no further macro expansion is performed.

A hazy point(also, see https://stackoverflow.com/questions/70617486/condition-inclusion-through-has-include-expression-and-has-attribute-expression) is that in [cpp.cond] p3.

The second form of has-include-expression is considered only if the first form does not match, in which case the preprocessing tokens are processed just as in normal text.

When we intend to say macro replacement would happen somewhere, we usually say "just as in normal text". The first form of has-include-expression is that

__has_­include ( header-name )

which can be further divided to

  • __has_­include ( < h-char-sequence > )
  • __has_­include ( " q-char-sequence " )

The second form is

__has_­include ( header-name-tokens )

which also can be further divided to

  • __has_­include ( string-literal )
  • __has_­include( < h-pp-tokens > )

I would say, even if [cpp.cond] p3 was intent to phrase that a macro-replacement would occur, it can only occur in the bold form. Since we have implied that the identifier-like sequences cannot be replaced in a string-literal [cpp.replace.footnote] 137

Since, by macro-replacement time, all character-literals and string-literals are preprocessing tokens, not sequences possibly containing identifier-like subsequences (see [lex.phases], translation phases), they are never scanned for macro names or parameters.

Back to this example, Head conforms to none of the above forms. The macro-expanded shouldn't occur for Head even if macro-expanded could be performed for has-include-expression.

@jensmaurer
Copy link
Member

jensmaurer commented Jan 10, 2022

I think __has_include should do macro expansion if and only if #include would do macro expansion for the arguments. I'm not seeing a reasoning in the above text that we would deviate from the #include treatment of the same preprocessing tokens.

@xmh0511
Copy link
Contributor Author

xmh0511 commented Jan 11, 2022

@jensmaurer __has_include(Head) is not a valid form of has-include-expression since the preprocessing token Head neither has the form header-name nor header-name-tokens. Consider this example

#include <iostream>
#define Head iostream
#define PL (
#define PR )
# if __has_include PL <Head> PR
#define Pn 0
#endif 

#ifndef Pn
#define Pn 1
#endif
int main(){
   std::cout<< Pn;
}

GCC and Clang have a divergence implementation for this example. Should we rephrase [cpp.cond] p3 to that

The second form of has-include-expression is considered only if the first form does not match, before the second form is considered the preprocessing tokens are processed just as in normal text(i.e., each identifier currently defined as a macro name is replaced by its replacement list of preprocessing tokens).

This means all preprocessing tokens are macro expanded immediately before the second form is considered to make them would be a valid form in the second.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants