Description
Clang appears to have not implemented P2558R2, despite claiming to have done so.
This example is mishandled:
#define FOO$ 10
#define STR(x) #x
#define STR2(x) STR(x)
const char *p = STR2(FOO$)
This is valid under P2558R2, and p
should be initialized to the string $ 10$
:
- The first line defines a macro named
FOO
whose expansion is$ 10
. - The
STR2(FOO$)
macro expansion's argument expands to$ 10$
. - Therefore the result of stringization should be
"$ 10$"
.
Under [lex.pptoken], adding $
et al to the basic source character set means that when $
appears in a source file (outside of a string or character literal), it always forms a single-character preprocessing-token. Ultimately, the issue here is that the GNU "dollars in identifiers" extension is a non-conforming extension post-P2558R2, so presumably we should stop enabling it by default in our conforming mode. Maybe it should only be enabled in -std=gnu++2c
, not in -std=c++2c
?
Also, the handling of
#define STR(x) #x
#define STR2(x) STR(x)
const char *p = STR2(\u0024);
is incorrect. This is accepted in all C++ language modes prior to Clang 17, and rejected in all C++ language modes in Clang 17 onwards. Both behaviors are wrong: it should be accepted in C++23 and earlier, and rejected in C++2c, because $
is part of the basic source character set only in C++2c onwards. (Even if this were correct, cxx_status.html should say this paper is implemented in Clang 17, not simply "Yes".)