https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120778
--- Comment #8 from Jakub Jelinek <jakub at gcc dot gnu.org> --- The paper talks about gcc handling incorrectly #define A <std #define B io.h> #include A B I think this is due to glue_header_name being done with non-zero pfile->state.in_directive plus using cpp_get_token_no_padding rather than cpp_get_token and cpp_get_token_1 doing 3040 if (pfile->context->c.macro) 3041 ++num_expanded_macros_counter; 3042 _cpp_pop_context (pfile); 3043 if (pfile->state.in_directive) 3044 continue; 3045 result = &pfile->avoid_paste; 3046 goto out; I think at least for the glue_header_name parsing we want the avoid_paste tokens in. Note, clang seems to reject all of #define A <std #define B io.h> #include A B #define C < #define D stdio.h> #include C D #define E <stdio.h #define F > #include E F #define G <stdio #define H .h> #include G H complaining about not being able to open 'std io.h', ' stdio.h' and 'stdio.h ' Now, I guess whitespace in the middle of the filename might be hard to get in in the gcc way of handling it and in the clang way of handling stuff one might make it go away through token pasting etc. But one can't really paste the < token and some identifier or identifier and > or whitespace around say . or / So, maybe we should keep it as is? We do insert some spaces (for PREV_WHITE), but as mentioned earlier CPP_PADDING tokens are ignored. https://eel.is/c++draft/cpp.include#7.sentence-3 says that the treatment of whitespace is implementation defined in that case...