Files
cppdraft_translate/cppdraft/cpp/pre.md
2025-10-25 03:02:53 +03:00

17 KiB
Raw Blame History

[cpp.pre]

15 Preprocessing directives [cpp]

15.1 Preamble [cpp.pre]

preprocessing-file:
groupopt
module-file

module-file:
pp-global-module-fragmentopt pp-module groupopt pp-private-module-fragmentopt

pp-global-module-fragment:
module ; new-line groupopt

pp-private-module-fragment:
module : private ; new-line groupopt

group:
group-part
group group-part

group-part:
control-line
if-section
text-line

conditionally-supported-directive

control-line:

include pp-tokens new-line

pp-import

embed pp-tokens new-line

define identifier replacement-list new-line

define identifier lparen identifier-listopt ) replacement-list new-line

define identifier lparen ... ) replacement-list new-line

define identifier lparen identifier-list , ... ) replacement-list new-line

undef identifier new-line

line pp-tokens new-line

error pp-tokensopt new-line

warning pp-tokensopt new-line

pragma pp-tokensopt new-line

new-line

if-section:
if-group elif-groupsopt else-groupopt endif-line

if-group:

if constant-expression new-line groupopt

ifdef identifier new-line groupopt

ifndef identifier new-line groupopt

elif-groups:
elif-group elif-groupsopt

elif-group:

elif constant-expression new-line groupopt

elifdef identifier new-line groupopt

elifndef identifier new-line groupopt

else-group:

else new-line groupopt

endif-line:

endif new-line

text-line:
pp-tokensopt new-line

conditionally-supported-directive:
pp-tokens new-line

lparen:
a ( character not immediately preceded by whitespace

identifier-list:
identifier
identifier-list , identifier

replacement-list:
pp-tokensopt

pp-tokens:
preprocessing-token pp-tokensopt

embed-parameter-seq:
embed-parameter embed-parameter-seqopt

embed-parameter:
embed-standard-parameter
embed-prefixed-parameter

embed-standard-parameter:
limit ( pp-balanced-token-seq )
prefix ( pp-balanced-token-seqopt )
suffix ( pp-balanced-token-seqopt )
if_empty ( pp-balanced-token-seqopt )

embed-prefixed-parameter:
identifier :: identifier
identifier :: identifier ( pp-balanced-token-seqopt )

pp-balanced-token-seq:
pp-balanced-token pp-balanced-token-seqopt

pp-balanced-token:
( pp-balanced-token-seqopt )
[ pp-balanced-token-seqopt ]
{ pp-balanced-token-seqopt }
any pp-token except:
parenthesis (U+0028 left parenthesis and U+0029 right parenthesis),
bracket (U+005b left square bracket and U+005d right square bracket), or
brace (U+007b left curly bracket and U+007d right curly bracket).

new-line:
the new-line character

1

#

A preprocessing directive consists of a sequence of preprocessing tokens that satisfies the following constraints: At the start of translation phase 4, the first preprocessing token in the sequence, referred to as a directive-introducing token, begins with the first character in the source file (optionally after whitespace containing no new-line characters) or follows whitespace containing at least one new-line character, and is

a # preprocessing token, or

an import preprocessing token immediately followed on the same logical source line by aheader-name,<,identifier,string-literal, or: preprocessing token, or

a module preprocessing token immediately followed on the same logical source line by anidentifier,:, or; preprocessing token, or

an export preprocessing token immediately followed on the same logical source line by one of the two preceding forms.

The last preprocessing token in the sequence is the first preprocessing token within the sequence that is immediately followed by whitespace containing a new-line character.122

[Note 1:

A new-line character ends the preprocessing directive even if it occurs within what would otherwise be an invocation of a function-like macro.

— end note]

[Example 1: # // preprocessing directivemodule ; // preprocessing directiveexport module leftpad; // preprocessing directiveimport ; // preprocessing directiveexport import "squee"; // preprocessing directiveimport rightpad; // preprocessing directiveimport :part; // preprocessing directivemodule // not a preprocessing directive ; // not a preprocessing directiveexport // not a preprocessing directiveimport // not a preprocessing directive foo; // not a preprocessing directiveexport // not a preprocessing directiveimport foo; // preprocessing directive (ill-formed at phase 7)import :: // not a preprocessing directiveimport -> // not a preprocessing directive — end example]

2

#

A sequence of preprocessing tokens is only a text-line if it does not begin with a directive-introducing token.

[Example 2: using module = int;module i; // not a text-line and not a control-lineint foo() {return i;}

The example is not a valid preprocessing-file.

— end example]

A sequence of preprocessing tokens is only a conditionally-supported-directive if it does not begin with any of the directive names appearing after a # in the syntax.

A conditionally-supported-directive is conditionally-supported withimplementation-defined semantics.

3

#

If one of the pp-tokens of a #embed directive (before macro replacement) is the identifierlimit, prefix, suffix, or if_empty and that identifier is defined as a macro ([cpp.replace.general]), the program is ill-formed.

Any embed-prefixed-parameter is conditionally-supported, with implementation-defined semantics.

4

#

At the start of phase 4 of translation, the group of a pp-global-module-fragment shall contain neither a text-line nor a pp-import.

5

#

When in a group that is skipped ([cpp.cond]), the directive syntax is relaxed to allow any sequence of preprocessing tokens to occur between the directive name and the following new-line character.

6

#

The only whitespace characters that shall appear between preprocessing tokens within a preprocessing directive (from just after the directive-introducing token through just before the terminating new-line character) are space and horizontal-tab (including spaces that have replaced comments or possibly other whitespace characters in translation phase 3).

7

#

The implementation can process and skip sections of source files conditionally, include other source files, import macros from header units, and replace macros.

These capabilities are calledpreprocessing, because conceptually they occur before translation of the resulting translation unit.

8

#

The preprocessing tokens within a preprocessing directive are not subject to macro expansion unless otherwise stated.

[Example 3:

In:#define EMPTY EMPTY # include <file.h> the sequence of preprocessing tokens on the second line is not a preprocessing directive, because it does not begin with a # at the start of translation phase 4, even though it will do so after the macro EMPTY has been replaced.

— end example]

122)122)

Thus, preprocessing directives are commonly called “lines”.

These “lines” have no other syntactic significance, as all whitespace is equivalent except in certain situations during preprocessing (see the# character string literal creation operator in [cpp.stringize], for example).