Skip to content

CWG3078 [cpp.include][cpp.cond][lex.digraph] Discrepancy between domains of #include _pp-tokens_ and _header-name-tokens_ #770

Description

@hubert-reinterpretcast

Full name of submitter (unless configured in github; will be published with the issue): Hubert Tong

Reference (section label): [cpp.include], [cpp.cond], [lex.digraph]

Link to reflector thread (if any): N/A

Issue description:

The resolution of CWG 3015 (https://cplusplus.github.io/CWG/issues/3015.html) has further clarified that

#define X >
#include <<X

performs the same inclusion as

#include <<>

There is implementation divergence (https://godbolt.org/z/TvceKr39G): Clang "accepts". GCC, EDG, and both MSVC preprocessor implementations reject.

Additionally, there are two issues with respect to language-specification consistency.

Firstly, the following is rejected by the header-name-tokens grammar in [cpp.cond] (because <% is a digraph) although the token sequence is specified to succeed when used as the pp-tokens for #include:

#define X >
#if __has_include(<%X)
#endif

Secondly, the footnote from https://wg21.link/lex.digraph#2 seems to be too broad in its statement of interchangeability between alternative and primary tokens.

Note that header-name-tokens does not prevent IFNDR cases such as a sequence consisting of the tokens <, >>, and >.

Suggested resolution:

With reference to a non-IFNDR case such as <, <:, >; strike the footnote from https://wg21.link/lex.digraph#2:

Thus the “stringized” values [cpp.stringize] of [ and <: will be different, maintaining the source spelling, but the tokens can otherwise be freely interchanged.

Modify in https://wg21.link/cpp.include#7:

The preprocessing tokens after include in the directive 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). The resulting sequence of preprocessing tokens shall be of the form
 header-name-tokens
Then, an An attempt is then made to form a header-name preprocessing token ([lex.header]) from the whitespace and the characters of the spellings of the resulting sequence of preprocessing tokens header-name-tokens; the treatment of whitespace is implementation-defined.

Activity

  1. hubert-reinterpretcast commented on Sep 22, 2025

    @hubert-reinterpretcast
    MemberAuthor

    @jensmaurer, I would also like to go over this on Friday.

    This may be a case where splitting the resolutions between two Core Issues could help.

  2. jensmaurer commented on Sep 22, 2025

    @jensmaurer
    Member
  3. changed the title [-][cpp.include][cpp.cond][lex.digraph] Discrepancy between domains of `#include _pp-tokens_` and _header-name-tokens_[/-] [+]CWG3078 [cpp.include][cpp.cond][lex.digraph] Discrepancy between domains of `#include _pp-tokens_` and _header-name-tokens_[/+] on Sep 22, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions