Skip to content

[lex] Reserved preprocessing-tokens *can* be conditionally used in the program #8692

@TymianekPL

Description

@TymianekPL

In addition, some identifiers appearing as a token or preprocessing-token are reserved for use by C++ implementations and shall not be used otherwise; no diagnostic is required.

[lex.name]/3

  1. The source file is decomposed into preprocessing tokens ([lex.pptoken]) and sequences of whitespace characters (including comments). A source file shall not end in a partial preprocessing token or in a partial comment.9 Each comment ([lex.comment]) is replaced by one U+0020 space character. New-line characters are retained. Whether each nonempty sequence of whitespace characters other than new-line is retained or replaced by one U+0020 space character is unspecified. As characters from the source file are consumed to form the next preprocessing token (i.e., not being consumed as part of a comment or other forms of whitespace), except when matching a c-char-sequence, s-char-sequence, r-char-sequence, h-char-sequence, or q-char-sequence, universal-character-names are recognized ([lex.universal.char]) and replaced by the designated element of the translation character set ([lex.charset]). The process of dividing a source file's characters into preprocessing tokens is context-dependent.
    [Example 1: See the handling of < within a #include preprocessing directive ([lex.header], [cpp.include]). — end example]
  2. The source file is analyzed as a preprocessing-file ([cpp.pre]). Preprocessing directives ([cpp]) are executed, macro invocations are expanded ([cpp.replace]), and _Pragma unary operator expressions are executed ([cpp.pragma.op]). A #include preprocessing directive ([cpp.include]) causes the named header or source file to be processed from phase 1 through phase 4, recursively. All preprocessing directives are then deleted. Whitespace characters separating preprocessing tokens are no longer significant.

[lex.phases]/3,4

Each and every preprocessing-token is used in the translation before the 4th translation phase which executes preprocessing directives such as #ifdef.

Why is this a defect? You cannot use and query names like __cplusplus or feature-test macros, since these are preprocessing-tokens (not tokens) reserved for use by C++ implementations, and therefore shall not be used within a program. With such definition, this program is ill-formed (no diagnostics required):

#include <print>

int main()
{
     #if __cplusplus >= 202302L
     std::print("Hello C++23 and beyond!");
     #endif
}

I don't think this is the desired behaviour.

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