Init
This commit is contained in:
103
cppdraft/cpp/concat.md
Normal file
103
cppdraft/cpp/concat.md
Normal file
@@ -0,0 +1,103 @@
|
||||
[cpp.concat]
|
||||
|
||||
# 15 Preprocessing directives [[cpp]](./#cpp)
|
||||
|
||||
## 15.7 Macro replacement [[cpp.replace]](cpp.replace#cpp.concat)
|
||||
|
||||
### 15.7.4 The ## operator [cpp.concat]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1847)
|
||||
|
||||
A## preprocessing token shall not occur at the beginning or
|
||||
at the end of a replacement list for either form
|
||||
of macro definition[.](#1.sentence-1)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1854)
|
||||
|
||||
If, in the replacement list of a function-like macro, a parameter is
|
||||
immediately preceded or followed by a## preprocessing token, the parameter is replaced by the
|
||||
corresponding argument's preprocessing token sequence; however, if an argument consists of no preprocessing tokens, the parameter is
|
||||
replaced by a placemarker preprocessing token instead[.](#2.sentence-1)[128](#footnote-128 "Placemarker preprocessing tokens do not appear in the syntax because they are temporary entities that exist only within translation phase 4.")
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1866)
|
||||
|
||||
For both object-like and function-like macro invocations, before the
|
||||
replacement list is reexamined for more macro names to replace,
|
||||
each instance of a## preprocessing token in the replacement list
|
||||
(not from an argument) is deleted and the
|
||||
preceding preprocessing token is concatenated
|
||||
with the following preprocessing token[.](#3.sentence-1)
|
||||
|
||||
Placemarker preprocessing tokens are handled specially: concatenation
|
||||
of two placemarkers results in a single placemarker preprocessing token, and
|
||||
concatenation of a placemarker with a non-placemarker preprocessing token results
|
||||
in the non-placemarker preprocessing token[.](#3.sentence-2)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
Concatenation can form
|
||||
a [*universal-character-name*](lex.universal.char#nt:universal-character-name "5.3.2 Universal character names [lex.universal.char]") ([[lex.charset]](lex.charset "5.3.1 Character sets"))[.](#3.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
If the result is not a valid preprocessing token,
|
||||
the program is ill-formed[.](#3.sentence-4)
|
||||
|
||||
The resulting preprocessing token is available for further macro replacement[.](#3.sentence-5)
|
||||
|
||||
The order of evaluation of## operators is unspecified[.](#3.sentence-6)
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1890)
|
||||
|
||||
[*Example [1](#example-1)*:
|
||||
|
||||
The sequence#define str(s) # s#define xstr(s) str(s)#define debug(s, t) printf("x" # s "= %d, x" # t "= %s", \
|
||||
x ## s, x ## t)#define INCFILE(n) vers ## n#define glue(a, b) a ## b#define xglue(a, b) glue(a, b)#define HIGHLOW "hello"#define LOW LOW ", world" debug(1, 2);
|
||||
fputs(str(strncmp("abc\0d", "abc", '\4') // this goes away== 0) str(: @\n), s);#include xstr(INCFILE(2).h) glue(HIGH, LOW);
|
||||
xglue(HIGH, LOW) results inprintf("x" "1" "= %d, x" "2" "= %s", x1, x2);
|
||||
fputs("strncmp(\"abc\\0d\", \"abc\", '\\4') == 0" ": @\n", s);#include "vers2.h" (*after macro replacement, before file access*)"hello";"hello" ", world" or, after concatenation of the character string literals,printf("x1= %d, x2= %s", x1, x2);
|
||||
fputs("strncmp(\"abc\\0d\", \"abc\", '\\4') == 0: @\n", s);#include "vers2.h" (*after macro replacement, before file access*)"hello";"hello, world"
|
||||
|
||||
Space around the # and ## preprocessing tokens in the macro definition
|
||||
is optional[.](#4.sentence-2)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1932)
|
||||
|
||||
[*Example [2](#example-2)*:
|
||||
|
||||
In the following fragment:#define hash_hash # ## ##define mkstr(a) # a#define in_between(a) mkstr(a)#define join(c, d) in_between(c hash_hash d)char p[] = join(x, y); // equivalent to char p[] = "x ## y";
|
||||
|
||||
The expansion produces, at various stages:join(x, y) in_between(x hash_hash y) in_between(x ## y) mkstr(x ## y)"x ## y"
|
||||
|
||||
In other words, expanding hash_hash produces a new preprocessing token,
|
||||
consisting of two adjacent sharp signs, but this new preprocessing token is not the## operator[.](#5.sentence-3)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1957)
|
||||
|
||||
[*Example [3](#example-3)*:
|
||||
|
||||
To illustrate the rules for placemarker preprocessing tokens, the sequence#define t(x,y,z) x ## y ## zint j[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,),
|
||||
t(10,,), t(,11,), t(,,12), t(,,) }; results inint j[] = { 123, 45, 67, 89, 10, 11, 12, };
|
||||
|
||||
â *end example*]
|
||||
|
||||
[128)](#footnote-128)[128)](#footnoteref-128)
|
||||
|
||||
Placemarker preprocessing tokens do not appear in the syntax
|
||||
because they are temporary entities that exist only within translation phase 4[.](#footnote-128.sentence-1)
|
||||
327
cppdraft/cpp/cond.md
Normal file
327
cppdraft/cpp/cond.md
Normal file
@@ -0,0 +1,327 @@
|
||||
[cpp.cond]
|
||||
|
||||
# 15 Preprocessing directives [[cpp]](./#cpp)
|
||||
|
||||
## 15.2 Conditional inclusion [cpp.cond]
|
||||
|
||||
[defined-macro-expression:](#nt:defined-macro-expression "15.2 Conditional inclusion [cpp.cond]")
|
||||
defined [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")
|
||||
defined ( [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") )
|
||||
|
||||
[h-preprocessing-token:](#nt:h-preprocessing-token "15.2 Conditional inclusion [cpp.cond]")
|
||||
any [*preprocessing-token*](lex.pptoken#nt:preprocessing-token "5.5 Preprocessing tokens [lex.pptoken]") other than >
|
||||
|
||||
[h-pp-tokens:](#nt:h-pp-tokens "15.2 Conditional inclusion [cpp.cond]")
|
||||
[*h-preprocessing-token*](#nt:h-preprocessing-token "15.2 Conditional inclusion [cpp.cond]") [*h-pp-tokens*](#nt:h-pp-tokens "15.2 Conditional inclusion [cpp.cond]")opt
|
||||
|
||||
[header-name-tokens:](#nt:header-name-tokens "15.2 Conditional inclusion [cpp.cond]")
|
||||
[*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]")
|
||||
< [*h-pp-tokens*](#nt:h-pp-tokens "15.2 Conditional inclusion [cpp.cond]") >
|
||||
|
||||
[has-include-expression:](#nt:has-include-expression "15.2 Conditional inclusion [cpp.cond]")
|
||||
__has_include ( [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") )
|
||||
__has_include ( [*header-name-tokens*](#nt:header-name-tokens "15.2 Conditional inclusion [cpp.cond]") )
|
||||
|
||||
[has-embed-expression:](#nt:has-embed-expression "15.2 Conditional inclusion [cpp.cond]")
|
||||
__has_embed ( [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")opt )
|
||||
__has_embed ( [*header-name-tokens*](#nt:header-name-tokens "15.2 Conditional inclusion [cpp.cond]") [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")opt )
|
||||
|
||||
[has-attribute-expression:](#nt:has-attribute-expression "15.2 Conditional inclusion [cpp.cond]")
|
||||
__has_cpp_attribute ( [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]") )
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L380)
|
||||
|
||||
The expression that controls conditional inclusion
|
||||
shall be an integral constant expression except that
|
||||
identifiers
|
||||
(including those lexically identical to keywords)
|
||||
are interpreted as described below[123](#footnote-123 "Because the controlling constant expression is evaluated during translation phase 4, all identifiers either are or are not macro names â there simply are no keywords, enumeration constants, etc.") and it may contain zero or more[*defined-macro-expression*](#nt:defined-macro-expression "15.2 Conditional inclusion [cpp.cond]")*s*,[*has-include-expression*](#nt:has-include-expression "15.2 Conditional inclusion [cpp.cond]")*s*,[*has-attribute-expression*](#nt:has-attribute-expression "15.2 Conditional inclusion [cpp.cond]")*s*,
|
||||
and/or [*has-embed-expression*](#nt:has-embed-expression "15.2 Conditional inclusion [cpp.cond]")*s* as unary operator expressions[.](#1.sentence-1)
|
||||
|
||||
A [*defined-macro-expression*](#nt:defined-macro-expression "15.2 Conditional inclusion [cpp.cond]") shall not appear
|
||||
within a [*has-include-expression*](#nt:has-include-expression "15.2 Conditional inclusion [cpp.cond]") or [*has-embed-expression*](#nt:has-embed-expression "15.2 Conditional inclusion [cpp.cond]")[.](#1.sentence-2)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L401)
|
||||
|
||||
A [*defined-macro-expression*](#nt:defined-macro-expression "15.2 Conditional inclusion [cpp.cond]") evaluates to 1 if the identifier is currently defined
|
||||
as a macro name
|
||||
(that is, if it is predefined
|
||||
or if it has one or more active macro definitions ([[cpp.import]](cpp.import "15.6 Header unit importation")),
|
||||
for example because
|
||||
it has been the subject of a#define preprocessing directive
|
||||
without an intervening#undef directive with the same subject identifier), 0 if it is not[.](#2.sentence-1)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L415)
|
||||
|
||||
The header or source file identified by
|
||||
the parenthesized preprocessing token sequence
|
||||
in each contained [*has-include-expression*](#nt:has-include-expression "15.2 Conditional inclusion [cpp.cond]") is searched for as if that preprocessing token sequence
|
||||
were the [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]") of a #include directive,
|
||||
except that no further macro expansion is performed[.](#3.sentence-1)
|
||||
|
||||
If the preprocessing token sequence does not consist solely of a [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") or cannot be combined ([[cpp.include]](cpp.include "15.3 Source file inclusion")) into a single[*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") preprocessing token, the program is ill-formed[.](#3.sentence-2)
|
||||
|
||||
The [*has-include-expression*](#nt:has-include-expression "15.2 Conditional inclusion [cpp.cond]") evaluates
|
||||
to 1 if the search for the source file succeeds, and
|
||||
to 0 if the search fails[.](#3.sentence-3)
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L429)
|
||||
|
||||
The parenthesized preprocessing token sequence of each contained[*has-embed-expression*](#nt:has-embed-expression "15.2 Conditional inclusion [cpp.cond]") is processed as if that
|
||||
preprocessing token sequence were the [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]") of a #embed directive ([[cpp.embed]](cpp.embed "15.4 Resource inclusion")),
|
||||
except that no further macro expansion is performed[.](#4.sentence-1)
|
||||
|
||||
The [*has-embed-expression*](#nt:has-embed-expression "15.2 Conditional inclusion [cpp.cond]") evaluates to:
|
||||
|
||||
- [(4.1)](#4.1)
|
||||
|
||||
__STDC_EMBED_FOUND__ if the search for the resource succeeds,
|
||||
all the given [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]")*s* in the [*embed-parameter-seq*](cpp.pre#nt:embed-parameter-seq "15.1 Preamble [cpp.pre]") are supported, and the resource is not empty[.](#4.1.sentence-1)
|
||||
|
||||
- [(4.2)](#4.2)
|
||||
|
||||
Otherwise, __STDC_EMBED_EMPTY__ if the search for the resource succeeds,
|
||||
all the given [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]")*s* in the [*embed-parameter-seq*](cpp.pre#nt:embed-parameter-seq "15.1 Preamble [cpp.pre]") are supported, and the resource is empty[.](#4.2.sentence-1)
|
||||
|
||||
- [(4.3)](#4.3)
|
||||
|
||||
Otherwise, __STDC_EMBED_NOT_FOUND__[.](#4.3.sentence-1)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
An unrecognized [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]") in an [*has-embed-expression*](#nt:has-embed-expression "15.2 Conditional inclusion [cpp.cond]") is not ill-formed and is instead treated as not supported[.](#4.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L453)
|
||||
|
||||
Each [*has-attribute-expression*](#nt:has-attribute-expression "15.2 Conditional inclusion [cpp.cond]") is replaced by
|
||||
a non-zero [*pp-number*](lex.ppnumber#nt:pp-number "5.7 Preprocessing numbers [lex.ppnumber]") matching the form of an [*integer-literal*](lex.icon#nt:integer-literal "5.13.2 Integer literals [lex.icon]") if the implementation supports an attribute
|
||||
with the name specified by interpreting
|
||||
the [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]"), after macro expansion,
|
||||
as an [*attribute-token*](dcl.attr.grammar#nt:attribute-token "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]"),
|
||||
and by 0 otherwise[.](#5.sentence-1)
|
||||
|
||||
The program is ill-formed if the [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]") do not match the form of an [*attribute-token*](dcl.attr.grammar#nt:attribute-token "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")[.](#5.sentence-2)
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L465)
|
||||
|
||||
For an attribute specified in this document,
|
||||
it is implementation-defined
|
||||
whether the value of the [*has-attribute-expression*](#nt:has-attribute-expression "15.2 Conditional inclusion [cpp.cond]") is 0 or is given by Table [21](#tab:cpp.cond.ha "Table 21: __has_cpp_attribute values")[.](#6.sentence-1)
|
||||
|
||||
For other attributes recognized by the implementation,
|
||||
the value isimplementation-defined[.](#6.sentence-2)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
It is expected
|
||||
that the availability of an attribute can be detected by any non-zero result[.](#6.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
Table [21](#tab:cpp.cond.ha) — __has_cpp_attribute values [[tab:cpp.cond.ha]](./tab:cpp.cond.ha)
|
||||
|
||||
| [ð](#tab:cpp.cond.ha-row-1)<br>**Attribute** | **Value** |
|
||||
| --- | --- |
|
||||
| [ð](#tab:cpp.cond.ha-row-2)<br>assume | 202207L |
|
||||
| [ð](#tab:cpp.cond.ha-row-3)<br>deprecated | 201309L |
|
||||
| [ð](#tab:cpp.cond.ha-row-4)<br>fallthrough | 201603L |
|
||||
| [ð](#tab:cpp.cond.ha-row-5)<br>indeterminate | 202403L |
|
||||
| [ð](#tab:cpp.cond.ha-row-6)<br>likely | 201803L |
|
||||
| [ð](#tab:cpp.cond.ha-row-7)<br>maybe_unused | 201603L |
|
||||
| [ð](#tab:cpp.cond.ha-row-8)<br>no_unique_address | 201803L |
|
||||
| [ð](#tab:cpp.cond.ha-row-9)<br>nodiscard | 201907L |
|
||||
| [ð](#tab:cpp.cond.ha-row-10)<br>noreturn | 200809L |
|
||||
| [ð](#tab:cpp.cond.ha-row-11)<br>unlikely | 201803L |
|
||||
|
||||
[7](#7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L496)
|
||||
|
||||
The#ifdef, #ifndef, #elifdef, and #elifndef directives, and
|
||||
the defined conditional inclusion operator,
|
||||
shall treat __has_include, __has_embed, and __has_cpp_attribute as if they were the names of defined macros[.](#7.sentence-1)
|
||||
|
||||
The identifiers __has_include, __has_embed, and __has_cpp_attribute shall not appear in any context not mentioned in this subclause[.](#7.sentence-2)
|
||||
|
||||
[8](#8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L506)
|
||||
|
||||
Each preprocessing token that remains (in the list of preprocessing tokens that
|
||||
will become the controlling expression)
|
||||
after all macro replacements have occurred
|
||||
shall be in the lexical form of a [token](lex.token "5.10 Tokens [lex.token]")[.](#8.sentence-1)
|
||||
|
||||
[9](#9)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L512)
|
||||
|
||||
Preprocessing directives of the forms
|
||||
|
||||
# if [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]") [*group*](cpp.pre#nt:group "15.1 Preamble [cpp.pre]")opt
|
||||
# elif [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]") [*group*](cpp.pre#nt:group "15.1 Preamble [cpp.pre]")opt
|
||||
|
||||
check whether the controlling constant expression evaluates to nonzero[.](#9.sentence-1)
|
||||
|
||||
[10](#10)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L522)
|
||||
|
||||
Prior to evaluation,
|
||||
macro invocations in the list of preprocessing tokens
|
||||
that will become the controlling constant expression
|
||||
are replaced
|
||||
(except for those macro names modified by thedefined unary operator),
|
||||
just as in normal text[.](#10.sentence-1)
|
||||
|
||||
If replacement of macros in the preprocessing tokens following the sequence__has_embed ( and before a matching ) (possibly produced by macro expansion)
|
||||
encounters a preprocessing token that is one of the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")*s*limit, prefix, suffix, or if_empty and that [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") is defined
|
||||
as a macro ([[cpp.replace.general]](cpp.replace.general "15.7.1 General")), the program is ill-formed[.](#10.sentence-2)
|
||||
|
||||
If the preprocessing tokendefined is generated as a result of this replacement process
|
||||
or use of thedefined unary operator does not match one of the two specified forms
|
||||
prior to macro replacement,
|
||||
the program is ill-formed, no diagnostic required[.](#10.sentence-3)
|
||||
|
||||
[11](#11)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L547)
|
||||
|
||||
After all replacements due to macro expansion and
|
||||
evaluations of[*defined-macro-expression*](#nt:defined-macro-expression "15.2 Conditional inclusion [cpp.cond]")*s*,[*has-include-expression*](#nt:has-include-expression "15.2 Conditional inclusion [cpp.cond]")*s*,[*has-embed-expression*](#nt:has-embed-expression "15.2 Conditional inclusion [cpp.cond]")*s*, and[*has-attribute-expression*](#nt:has-attribute-expression "15.2 Conditional inclusion [cpp.cond]")*s* have been performed,
|
||||
all remaining identifiers and keywords,
|
||||
except fortrue andfalse,
|
||||
are replaced with the [*pp-number*](lex.ppnumber#nt:pp-number "5.7 Preprocessing numbers [lex.ppnumber]")0,
|
||||
and then each preprocessing token is converted into a token[.](#11.sentence-1)
|
||||
|
||||
[*Note [3](#note-3)*:
|
||||
|
||||
An [alternative
|
||||
token](lex.digraph "5.9 Alternative tokens [lex.digraph]") is not an identifier,
|
||||
even when its spelling consists entirely of letters and underscores[.](#11.sentence-2)
|
||||
|
||||
Therefore it is not subject to this replacement[.](#11.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[12](#12)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L570)
|
||||
|
||||
The resulting tokens comprise the controlling constant expression
|
||||
which is evaluated according to the rules of [[expr.const]](expr.const "7.7 Constant expressions") using arithmetic that has at least the ranges specified
|
||||
in [[support.limits]](support.limits "17.3 Implementation properties")[.](#12.sentence-1)
|
||||
|
||||
For the purposes of this token conversion and evaluation
|
||||
all signed and unsigned integer types
|
||||
act as if they have the same representation as, respectively,intmax_t or uintmax_t ([[cstdint.syn]](cstdint.syn "17.4.1 Header <cstdint> synopsis"))[.](#12.sentence-2)
|
||||
|
||||
[*Note [4](#note-4)*:
|
||||
|
||||
Thus on an
|
||||
implementation where std::numeric_limits<int>::max() is 0x7FFF and std::numeric_limits<unsigned int>::max() is 0xFFFF,
|
||||
the integer literal 0x8000 is signed and positive within a #if expression even though it is unsigned in [translation phase
|
||||
7](lex.phases "5.2 Phases of translation [lex.phases]")[.](#12.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
This includes interpreting [*character-literal*](lex.ccon#nt:character-literal "5.13.3 Character literals [lex.ccon]")*s* according to the rules in [[lex.ccon]](lex.ccon "5.13.3 Character literals")[.](#12.sentence-4)
|
||||
|
||||
[*Note [5](#note-5)*:
|
||||
|
||||
The associated character encodings of literals are the same
|
||||
in #if and #elif directives and in any expression[.](#12.sentence-5)
|
||||
|
||||
â *end note*]
|
||||
|
||||
Each subexpression with typebool is subjected to integral promotion before processing continues[.](#12.sentence-6)
|
||||
|
||||
[13](#13)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L596)
|
||||
|
||||
Preprocessing directives of the forms
|
||||
|
||||
# ifdef [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]") [*group*](cpp.pre#nt:group "15.1 Preamble [cpp.pre]")opt
|
||||
# ifndef [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]") [*group*](cpp.pre#nt:group "15.1 Preamble [cpp.pre]")opt
|
||||
# elifdef [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]") [*group*](cpp.pre#nt:group "15.1 Preamble [cpp.pre]")opt
|
||||
# elifndef [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]") [*group*](cpp.pre#nt:group "15.1 Preamble [cpp.pre]")opt
|
||||
|
||||
check whether the identifier is or is not currently defined as a macro name[.](#13.sentence-1)
|
||||
|
||||
Their conditions are equivalent to#if defined [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]"),#if !defined [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]"),#elif defined [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]"), and#elif !defined [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]"),
|
||||
respectively[.](#13.sentence-2)
|
||||
|
||||
[14](#14)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L616)
|
||||
|
||||
Each directive's condition is checked in order[.](#14.sentence-1)
|
||||
|
||||
If it evaluates to false (zero),
|
||||
the group that it controls is skipped:
|
||||
directives are processed only through the name that determines
|
||||
the directive in order to keep track of the level
|
||||
of nested conditionals;
|
||||
the rest of the directives' preprocessing tokens are ignored,
|
||||
as are the other preprocessing tokens in the group[.](#14.sentence-2)
|
||||
|
||||
Only the first group
|
||||
whose control condition evaluates to true (nonzero) is processed;
|
||||
any following groups are skipped and their controlling directives
|
||||
are processed as if they were in a group that is skipped[.](#14.sentence-3)
|
||||
|
||||
If none of the conditions evaluates to true,
|
||||
and there is a#elsedirective,
|
||||
the group controlled by the#else is processed; lacking a#else directive, all the groups until the#endifare skipped[.](#14.sentence-4)[124](#footnote-124 "As indicated by the syntax, a preprocessing token cannot follow a #else or #endif directive before the terminating new-line character. However, comments can appear anywhere in a source file, including within a preprocessing directive.")
|
||||
|
||||
[15](#15)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L654)
|
||||
|
||||
[*Example [1](#example-1)*:
|
||||
|
||||
This demonstrates a way to include a library optional facility
|
||||
only if it is available:#if __has_include(<optional>)# include <optional># if __cpp_lib_optional >= 201603# define have_optional 1# endif#elif __has_include(<experimental/optional>)# include <experimental/optional># if __cpp_lib_experimental_optional >= 201411# define have_optional 1# define experimental_optional 1# endif#endif#ifndef have_optional# define have_optional 0#endif
|
||||
|
||||
â *end example*]
|
||||
|
||||
[16](#16)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L677)
|
||||
|
||||
[*Example [2](#example-2)*:
|
||||
|
||||
This demonstrates a way to use the attribute [[acme::deprecated]] only if it is available[.](#16.sentence-1)
|
||||
|
||||
#if __has_cpp_attribute(acme::deprecated)# define ATTR_DEPRECATED(msg) [[acme::deprecated(msg)]]#else# define ATTR_DEPRECATED(msg) [[deprecated(msg)]]#endif ATTR_DEPRECATED("This function is deprecated") void anvil(); â *end example*]
|
||||
|
||||
[123)](#footnote-123)[123)](#footnoteref-123)
|
||||
|
||||
Because the controlling constant expression is evaluated
|
||||
during translation phase 4,
|
||||
all identifiers either are or are not macro names â
|
||||
there simply are no keywords, enumeration constants, etc[.](#footnote-123.sentence-1)
|
||||
|
||||
[124)](#footnote-124)[124)](#footnoteref-124)
|
||||
|
||||
As indicated by the syntax,
|
||||
a preprocessing token cannot follow a#else or#endif directive before the terminating new-line character[.](#footnote-124.sentence-1)
|
||||
|
||||
However,
|
||||
comments can appear anywhere in a source file,
|
||||
including within a preprocessing directive[.](#footnote-124.sentence-2)
|
||||
353
cppdraft/cpp/embed.md
Normal file
353
cppdraft/cpp/embed.md
Normal file
@@ -0,0 +1,353 @@
|
||||
[cpp.embed]
|
||||
|
||||
# 15 Preprocessing directives [[cpp]](./#cpp)
|
||||
|
||||
## 15.4 Resource inclusion [cpp.embed]
|
||||
|
||||
### [15.4.1](#gen) General [[cpp.embed.gen]](cpp.embed.gen)
|
||||
|
||||
[1](#gen-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L845)
|
||||
|
||||
A [*bracket resource search*](#def:search,bracket_resource "15.4.1 General [cpp.embed.gen]") for a sequence of characters
|
||||
searches a sequence of places for a resource identified uniquely
|
||||
by that sequence of characters[.](#gen-1.sentence-1)
|
||||
|
||||
How the places are determined or the resource identified
|
||||
is implementation-defined[.](#gen-1.sentence-2)
|
||||
|
||||
[2](#gen-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L852)
|
||||
|
||||
A [*quote resource search*](#def:search,quote_resource "15.4.1 General [cpp.embed.gen]") for a sequence of characters
|
||||
attempts to identify a resource that is named by the sequence of characters[.](#gen-2.sentence-1)
|
||||
|
||||
The named resource is searched for
|
||||
in an implementation-defined manner[.](#gen-2.sentence-2)
|
||||
|
||||
If the implementation does not support a quote resource search
|
||||
for that sequence of characters, or if the search fails,
|
||||
the result of the quote resource search
|
||||
is the result of a bracket resource search for the same sequence of characters[.](#gen-2.sentence-3)
|
||||
|
||||
[3](#gen-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L862)
|
||||
|
||||
A preprocessing directive of the form
|
||||
|
||||
# embed [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]")opt [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
|
||||
causes the replacement of that directive
|
||||
by preprocessing tokens derived from data
|
||||
in the resource identified by [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]"),
|
||||
as specified below[.](#gen-3.sentence-1)
|
||||
|
||||
[4](#gen-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L872)
|
||||
|
||||
If the [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") is of the form
|
||||
|
||||
< [*h-char-sequence*](lex.header#nt:h-char-sequence "5.6 Header names [lex.header]") >
|
||||
|
||||
the resource is identified by a bracket resource search
|
||||
for the sequence of characters of the [*h-char-sequence*](lex.header#nt:h-char-sequence "5.6 Header names [lex.header]")[.](#gen-4.sentence-1)
|
||||
|
||||
[5](#gen-5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L880)
|
||||
|
||||
If the [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") is of the form
|
||||
|
||||
" [*q-char-sequence*](lex.header#nt:q-char-sequence "5.6 Header names [lex.header]") "
|
||||
|
||||
the resource is identified by a quote resource search
|
||||
for the sequence of characters of the [*q-char-sequence*](lex.header#nt:q-char-sequence "5.6 Header names [lex.header]")[.](#gen-5.sentence-1)
|
||||
|
||||
[6](#gen-6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L888)
|
||||
|
||||
If a bracket resource search fails,
|
||||
or if a quote or bracket resource search identifies a resource
|
||||
that cannot be processed by the implementation, the program is ill-formed[.](#gen-6.sentence-1)
|
||||
|
||||
[*Note [1](#gen-note-1)*:
|
||||
|
||||
If the resource cannot be processed, the program is ill-formed
|
||||
even when processing #embed with limit(0) ([[cpp.embed.param.limit]](#param.limit "15.4.2.1 limit parameter"))
|
||||
or evaluating __has_embed[.](#gen-6.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[7](#gen-7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L898)
|
||||
|
||||
*Recommended practice*: A mechanism similar to, but distinct from, theimplementation-defined
|
||||
search paths used for #include ([[cpp.include]](cpp.include "15.3 Source file inclusion"))
|
||||
is encouraged[.](#gen-7.sentence-1)
|
||||
|
||||
[8](#gen-8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L904)
|
||||
|
||||
Either form of the #embed directive processes the[*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]"), if present, just as in normal text[.](#gen-8.sentence-1)
|
||||
|
||||
The [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]") shall then have the form[*embed-parameter-seq*](cpp.pre#nt:embed-parameter-seq "15.1 Preamble [cpp.pre]")[.](#gen-8.sentence-2)
|
||||
|
||||
[9](#gen-9)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L910)
|
||||
|
||||
A resource is a source of data accessible from the translation environment[.](#gen-9.sentence-1)
|
||||
|
||||
A resource has an [*implementation-resource-width*](#def:implementation-resource-width "15.4.1 General [cpp.embed.gen]"), which is theimplementation-defined
|
||||
size in bits of the resource[.](#gen-9.sentence-2)
|
||||
|
||||
If the implementation-resource-width is not an integral multiple ofCHAR_BIT, the program is ill-formed[.](#gen-9.sentence-3)
|
||||
|
||||
Let [*implementation-resource-count*](#def:implementation-resource-count "15.4.1 General [cpp.embed.gen]") be
|
||||
implementation-resource-width divided by CHAR_BIT[.](#gen-9.sentence-4)
|
||||
|
||||
Every resource also has a [*resource-count*](#def:resource-count "15.4.1 General [cpp.embed.gen]"), which is
|
||||
|
||||
- [(9.1)](#gen-9.1)
|
||||
|
||||
the value as computed from the optionally-provided limit[*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]") ([[cpp.embed.param.limit]](#param.limit "15.4.2.1 limit parameter")), if present;
|
||||
|
||||
- [(9.2)](#gen-9.2)
|
||||
|
||||
otherwise, the implementation-resource-count.
|
||||
|
||||
A resource is empty if the resource-count is zero[.](#gen-9.sentence-6)
|
||||
|
||||
[10](#gen-10)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L931)
|
||||
|
||||
[*Example [1](#gen-example-1)*: // ill-formed if the implementation-resource-width is 6 bits#embed "6_bits.bin" â *end example*]
|
||||
|
||||
[11](#gen-11)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L939)
|
||||
|
||||
The #embed directive is replaced by a comma-separated list of integer
|
||||
literals of type int, unless otherwise modified by embed
|
||||
parameters ([[cpp.embed.param]](#param "15.4.2 Embed parameters"))[.](#gen-11.sentence-1)
|
||||
|
||||
[12](#gen-12)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L944)
|
||||
|
||||
The integer literals in the comma-separated list correspond to
|
||||
resource-count consecutive calls to std::fgetc ([[cstdio.syn]](cstdio.syn "31.13.1 Header <cstdio> synopsis"))
|
||||
from the resource, as a binary file[.](#gen-12.sentence-1)
|
||||
|
||||
If any call to std::fgetc returns EOF, the program is
|
||||
ill-formed[.](#gen-12.sentence-2)
|
||||
|
||||
[13](#gen-13)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L951)
|
||||
|
||||
*Recommended practice*: The value of each integer literal should closely represent
|
||||
the bit stream of the resource unmodified[.](#gen-13.sentence-1)
|
||||
|
||||
This can require an implementation to consider potential differences between
|
||||
translation and execution environments, as well as any other applicable
|
||||
sources of mismatch[.](#gen-13.sentence-2)
|
||||
|
||||
[*Example [2](#gen-example-2)*: #include <cstring>#include <cstddef>#include <fstream>#include <vector>#include <cassert>int main() {// If the file is the same as the resource in the translation environment, no assert in this program should fail.constexpr unsigned char d[] = {#embed <data.dat>}; const std::vector<unsigned char> vec_d = {#embed <data.dat>}; constexpr std::size_t expected_size = sizeof(d); // same file in execution environment as was embedded std::ifstream f_source("data.dat", std::ios::binary | std::ios::in); unsigned char runtime_d[expected_size]; char* ifstream_ptr = reinterpret_cast<char*>(runtime_d);
|
||||
assert(!f_source.read(ifstream_ptr, expected_size));
|
||||
std::size_t ifstream_size = f_source.gcount();
|
||||
assert (ifstream_size == expected_size); int is_same = std::memcmp(&d[0], ifstream_ptr, ifstream_size);
|
||||
assert(is_same == 0); int is_same_vec = std::memcmp(vec_d.data(), ifstream_ptr, ifstream_size);
|
||||
assert(is_same_vec == 0);} â *end example*]
|
||||
|
||||
[*Example [3](#gen-example-3)*: int i = {#embed "i.dat"}; // well-formed if i.dat produces a single valueint i2 =#embed "i.dat" ; // also well-formed if i.dat produces a single valuestruct s {double a, b, c; struct { double e, f, g; } x; double h, i, j;};
|
||||
s x = {// well-formed if the directive produces nine or fewer values#embed "s.dat"}; â *end example*]
|
||||
|
||||
[14](#gen-14)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1012)
|
||||
|
||||
A preprocessing directive of the form
|
||||
|
||||
# embed [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]") [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
|
||||
(that does not match the previous form) is permitted[.](#gen-14.sentence-1)
|
||||
|
||||
The preprocessing tokens after embed 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)[.](#gen-14.sentence-2)
|
||||
|
||||
Then, an attempt is made to form a [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") preprocessing token ([[lex.header]](lex.header "5.6 Header names")) from the whitespace and the characters
|
||||
of the spellings of the resulting sequence of preprocessing tokens immediately after embed;
|
||||
the treatment of whitespace
|
||||
is implementation-defined[.](#gen-14.sentence-3)
|
||||
|
||||
If the attempt succeeds, the directive with the so-formed [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") is processed as specified for the previous form[.](#gen-14.sentence-4)
|
||||
|
||||
Otherwise, the program is ill-formed[.](#gen-14.sentence-5)
|
||||
|
||||
[*Note [2](#gen-note-2)*:
|
||||
|
||||
Adjacent [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]")*s* are not concatenated into a single[*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]") (see the translation phases in [[lex.phases]](lex.phases "5.2 Phases of translation"));
|
||||
thus, an expansion that results in two [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]")*s* is an
|
||||
invalid directive[.](#gen-14.sentence-6)
|
||||
|
||||
â *end note*]
|
||||
|
||||
Any further processing as in normal text described for the previous
|
||||
form is not performed[.](#gen-14.sentence-7)
|
||||
|
||||
[*Note [3](#gen-note-3)*:
|
||||
|
||||
That is, processing as in normal text happens once and only once for the entire
|
||||
directive[.](#gen-14.sentence-8)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [4](#gen-example-4)*:
|
||||
|
||||
If the directive matches the second form, the whole directive is replaced[.](#gen-14.sentence-9)
|
||||
|
||||
If the directive matches the first form, everything after the name is replaced[.](#gen-14.sentence-10)
|
||||
|
||||
#define EMPTY#define X myfile#define Y rsc#define Z 42#embed <myfile.rsc> prefix(Z)#embed EMPTY <X.Y> prefix(Z) is equivalent to:#embed <myfile.rsc> prefix(42)#embed <myfile.rsc> prefix(42)
|
||||
|
||||
â *end example*]
|
||||
|
||||
### [15.4.2](#param) Embed parameters [[cpp.embed.param]](cpp.embed.param)
|
||||
|
||||
#### [15.4.2.1](#param.limit) limit parameter [[cpp.embed.param.limit]](cpp.embed.param.limit)
|
||||
|
||||
[1](#param.limit-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1063)
|
||||
|
||||
An [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]") of the formlimit ( [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]") ) specifies the
|
||||
maximum possible number of elements in the comma-delimited list[.](#param.limit-1.sentence-1)
|
||||
|
||||
It shall appear at most once in the [*embed-parameter-seq*](cpp.pre#nt:embed-parameter-seq "15.1 Preamble [cpp.pre]")[.](#param.limit-1.sentence-2)
|
||||
|
||||
The preprocessing token defined shall not appear in the[*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")[.](#param.limit-1.sentence-3)
|
||||
|
||||
[2](#param.limit-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1072)
|
||||
|
||||
The [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]") is evaluated as a[*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") using the rules as described in conditional
|
||||
inclusion ([[cpp.cond]](cpp.cond "15.2 Conditional inclusion")), but without being processed as in normal text an
|
||||
additional time[.](#param.limit-2.sentence-1)
|
||||
|
||||
[*Example [1](#param.limit-example-1)*: #undef DATA_LIMIT#if __has_embed(<data.dat> limit(DATA_LIMIT))#endif
|
||||
|
||||
is equivalent to:
|
||||
|
||||
#if __has_embed(<data.dat> limit(0))#endif â *end example*]
|
||||
|
||||
[*Example [2](#param.limit-example-2)*: #embed <data.dat> limit(__has_include("a.h"))#if __has_embed(<data.dat> limit(__has_include("a.h")))// ill-formed: __has_include ([[cpp.cond]](cpp.cond "15.2 Conditional inclusion")) cannot appear here#endif â *end example*]
|
||||
|
||||
[3](#param.limit-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1103)
|
||||
|
||||
The [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") shall be an integral constant expression
|
||||
whose value is greater than or equal to zero[.](#param.limit-3.sentence-1)
|
||||
|
||||
The resource-count ([[cpp.embed.gen]](#gen "15.4.1 General")) becomes
|
||||
implementation-resource-count, if the value of the[*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") is greater than
|
||||
implementation-resource-count; otherwise, the value of the[*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]")[.](#param.limit-3.sentence-2)
|
||||
|
||||
[*Example [3](#param.limit-example-3)*: constexpr unsigned char sound_signature[] = {// a hypothetical resource capable of expanding to four or more elements#embed <sdk/jump.wav> limit(2+2)};
|
||||
|
||||
static_assert(sizeof(sound_signature) == 4); // OK â *end example*]
|
||||
|
||||
#### [15.4.2.2](#param.prefix) prefix parameter [[cpp.embed.param.prefix]](cpp.embed.param.prefix)
|
||||
|
||||
[1](#param.prefix-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1123)
|
||||
|
||||
An [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]") of the form
|
||||
|
||||
prefix ( [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")opt )
|
||||
|
||||
shall appear at most once in the [*embed-parameter-seq*](cpp.pre#nt:embed-parameter-seq "15.1 Preamble [cpp.pre]")[.](#param.prefix-1.sentence-1)
|
||||
|
||||
[2](#param.prefix-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1130)
|
||||
|
||||
If the resource is empty, this [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]") is ignored[.](#param.prefix-2.sentence-1)
|
||||
|
||||
Otherwise, the [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]") is placed immediately
|
||||
before the comma-delimited list of integral literals[.](#param.prefix-2.sentence-2)
|
||||
|
||||
#### [15.4.2.3](#param.suffix) suffix parameter [[cpp.embed.param.suffix]](cpp.embed.param.suffix)
|
||||
|
||||
[1](#param.suffix-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1136)
|
||||
|
||||
An [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]") of the form
|
||||
|
||||
suffix ( [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")opt )
|
||||
|
||||
shall appear at most once in the [*embed-parameter-seq*](cpp.pre#nt:embed-parameter-seq "15.1 Preamble [cpp.pre]")[.](#param.suffix-1.sentence-1)
|
||||
|
||||
[2](#param.suffix-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1143)
|
||||
|
||||
If the resource is empty, this [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]") is ignored[.](#param.suffix-2.sentence-1)
|
||||
|
||||
Otherwise, the [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]") is placed immediately after
|
||||
the comma-delimited list of the integral constant expressions[.](#param.suffix-2.sentence-2)
|
||||
|
||||
[*Example [1](#param.suffix-example-1)*: constexpr unsigned char whl[] = {#embed "ches.glsl" \
|
||||
prefix(0xEF, 0xBB, 0xBF, ) /* a sequence of bytes */ \
|
||||
suffix(,)0};// always null-terminated, contains the sequence if not emptyconstexpr bool is_empty = sizeof(whl) == 1 && whl[0] == '\0';constexpr bool is_not_empty = sizeof(whl) >= 4&& whl[sizeof(whl) - 1] == '\0'&& whl[0] == '\xEF' && whl[1] == '\xBB' && whl[2] == '\xBF';static_assert(is_empty || is_not_empty); â *end example*]
|
||||
|
||||
#### [15.4.2.4](#param.if.empty) if_empty parameter [[cpp.embed.param.if.empty]](cpp.embed.param.if.empty)
|
||||
|
||||
[1](#param.if.empty-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1166)
|
||||
|
||||
An embed-parameter of the form
|
||||
|
||||
if_empty ( [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")opt )
|
||||
|
||||
shall appear at most once in the [*embed-parameter-seq*](cpp.pre#nt:embed-parameter-seq "15.1 Preamble [cpp.pre]")[.](#param.if.empty-1.sentence-1)
|
||||
|
||||
[2](#param.if.empty-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1173)
|
||||
|
||||
If the resource is not empty, this [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]") is ignored[.](#param.if.empty-2.sentence-1)
|
||||
|
||||
Otherwise, the #embed directive is replaced by the[*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")[.](#param.if.empty-2.sentence-2)
|
||||
|
||||
[*Example [1](#param.if.empty-example-1)*:
|
||||
|
||||
limit(0) affects when a resource is considered empty[.](#param.if.empty-2.sentence-3)
|
||||
|
||||
Therefore, the following program:
|
||||
|
||||
#embed </owo/uwurandom> \
|
||||
if_empty(42203) limit(0) expands to42203
|
||||
|
||||
â *end example*]
|
||||
|
||||
[*Example [2](#param.if.empty-example-2)*:
|
||||
|
||||
This resource is considered empty due to the limit(0) [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]"),
|
||||
always, including in __has_embed clauses[.](#param.if.empty-2.sentence-6)
|
||||
|
||||
int infinity_zero () {#if __has_embed(</owo/uwurandom> limit(0) prefix(some tokens)) == __STDC_EMBED_EMPTY__ // if </owo/uwurandom> exists, this conditional inclusion branch is taken and the function returns 0.return 0;#else// otherwise, the resource does not exist#error "The resource does not exist"#endif} â *end example*]
|
||||
223
cppdraft/cpp/embed/gen.md
Normal file
223
cppdraft/cpp/embed/gen.md
Normal file
@@ -0,0 +1,223 @@
|
||||
[cpp.embed.gen]
|
||||
|
||||
# 15 Preprocessing directives [[cpp]](./#cpp)
|
||||
|
||||
## 15.4 Resource inclusion [[cpp.embed]](cpp.embed#gen)
|
||||
|
||||
### 15.4.1 General [cpp.embed.gen]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L845)
|
||||
|
||||
A [*bracket resource search*](#def:search,bracket_resource "15.4.1 General [cpp.embed.gen]") for a sequence of characters
|
||||
searches a sequence of places for a resource identified uniquely
|
||||
by that sequence of characters[.](#1.sentence-1)
|
||||
|
||||
How the places are determined or the resource identified
|
||||
is implementation-defined[.](#1.sentence-2)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L852)
|
||||
|
||||
A [*quote resource search*](#def:search,quote_resource "15.4.1 General [cpp.embed.gen]") for a sequence of characters
|
||||
attempts to identify a resource that is named by the sequence of characters[.](#2.sentence-1)
|
||||
|
||||
The named resource is searched for
|
||||
in an implementation-defined manner[.](#2.sentence-2)
|
||||
|
||||
If the implementation does not support a quote resource search
|
||||
for that sequence of characters, or if the search fails,
|
||||
the result of the quote resource search
|
||||
is the result of a bracket resource search for the same sequence of characters[.](#2.sentence-3)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L862)
|
||||
|
||||
A preprocessing directive of the form
|
||||
|
||||
# embed [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]")opt [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
|
||||
causes the replacement of that directive
|
||||
by preprocessing tokens derived from data
|
||||
in the resource identified by [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]"),
|
||||
as specified below[.](#3.sentence-1)
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L872)
|
||||
|
||||
If the [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") is of the form
|
||||
|
||||
< [*h-char-sequence*](lex.header#nt:h-char-sequence "5.6 Header names [lex.header]") >
|
||||
|
||||
the resource is identified by a bracket resource search
|
||||
for the sequence of characters of the [*h-char-sequence*](lex.header#nt:h-char-sequence "5.6 Header names [lex.header]")[.](#4.sentence-1)
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L880)
|
||||
|
||||
If the [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") is of the form
|
||||
|
||||
" [*q-char-sequence*](lex.header#nt:q-char-sequence "5.6 Header names [lex.header]") "
|
||||
|
||||
the resource is identified by a quote resource search
|
||||
for the sequence of characters of the [*q-char-sequence*](lex.header#nt:q-char-sequence "5.6 Header names [lex.header]")[.](#5.sentence-1)
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L888)
|
||||
|
||||
If a bracket resource search fails,
|
||||
or if a quote or bracket resource search identifies a resource
|
||||
that cannot be processed by the implementation, the program is ill-formed[.](#6.sentence-1)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
If the resource cannot be processed, the program is ill-formed
|
||||
even when processing #embed with limit(0) ([[cpp.embed.param.limit]](cpp.embed.param.limit "15.4.2.1 limit parameter"))
|
||||
or evaluating __has_embed[.](#6.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[7](#7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L898)
|
||||
|
||||
*Recommended practice*: A mechanism similar to, but distinct from, theimplementation-defined
|
||||
search paths used for #include ([[cpp.include]](cpp.include "15.3 Source file inclusion"))
|
||||
is encouraged[.](#7.sentence-1)
|
||||
|
||||
[8](#8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L904)
|
||||
|
||||
Either form of the #embed directive processes the[*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]"), if present, just as in normal text[.](#8.sentence-1)
|
||||
|
||||
The [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]") shall then have the form[*embed-parameter-seq*](cpp.pre#nt:embed-parameter-seq "15.1 Preamble [cpp.pre]")[.](#8.sentence-2)
|
||||
|
||||
[9](#9)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L910)
|
||||
|
||||
A resource is a source of data accessible from the translation environment[.](#9.sentence-1)
|
||||
|
||||
A resource has an [*implementation-resource-width*](#def:implementation-resource-width "15.4.1 General [cpp.embed.gen]"), which is theimplementation-defined
|
||||
size in bits of the resource[.](#9.sentence-2)
|
||||
|
||||
If the implementation-resource-width is not an integral multiple ofCHAR_BIT, the program is ill-formed[.](#9.sentence-3)
|
||||
|
||||
Let [*implementation-resource-count*](#def:implementation-resource-count "15.4.1 General [cpp.embed.gen]") be
|
||||
implementation-resource-width divided by CHAR_BIT[.](#9.sentence-4)
|
||||
|
||||
Every resource also has a [*resource-count*](#def:resource-count "15.4.1 General [cpp.embed.gen]"), which is
|
||||
|
||||
- [(9.1)](#9.1)
|
||||
|
||||
the value as computed from the optionally-provided limit[*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]") ([[cpp.embed.param.limit]](cpp.embed.param.limit "15.4.2.1 limit parameter")), if present;
|
||||
|
||||
- [(9.2)](#9.2)
|
||||
|
||||
otherwise, the implementation-resource-count.
|
||||
|
||||
A resource is empty if the resource-count is zero[.](#9.sentence-6)
|
||||
|
||||
[10](#10)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L931)
|
||||
|
||||
[*Example [1](#example-1)*: // ill-formed if the implementation-resource-width is 6 bits#embed "6_bits.bin" â *end example*]
|
||||
|
||||
[11](#11)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L939)
|
||||
|
||||
The #embed directive is replaced by a comma-separated list of integer
|
||||
literals of type int, unless otherwise modified by embed
|
||||
parameters ([[cpp.embed.param]](cpp.embed.param "15.4.2 Embed parameters"))[.](#11.sentence-1)
|
||||
|
||||
[12](#12)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L944)
|
||||
|
||||
The integer literals in the comma-separated list correspond to
|
||||
resource-count consecutive calls to std::fgetc ([[cstdio.syn]](cstdio.syn "31.13.1 Header <cstdio> synopsis"))
|
||||
from the resource, as a binary file[.](#12.sentence-1)
|
||||
|
||||
If any call to std::fgetc returns EOF, the program is
|
||||
ill-formed[.](#12.sentence-2)
|
||||
|
||||
[13](#13)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L951)
|
||||
|
||||
*Recommended practice*: The value of each integer literal should closely represent
|
||||
the bit stream of the resource unmodified[.](#13.sentence-1)
|
||||
|
||||
This can require an implementation to consider potential differences between
|
||||
translation and execution environments, as well as any other applicable
|
||||
sources of mismatch[.](#13.sentence-2)
|
||||
|
||||
[*Example [2](#example-2)*: #include <cstring>#include <cstddef>#include <fstream>#include <vector>#include <cassert>int main() {// If the file is the same as the resource in the translation environment, no assert in this program should fail.constexpr unsigned char d[] = {#embed <data.dat>}; const std::vector<unsigned char> vec_d = {#embed <data.dat>}; constexpr std::size_t expected_size = sizeof(d); // same file in execution environment as was embedded std::ifstream f_source("data.dat", std::ios::binary | std::ios::in); unsigned char runtime_d[expected_size]; char* ifstream_ptr = reinterpret_cast<char*>(runtime_d);
|
||||
assert(!f_source.read(ifstream_ptr, expected_size));
|
||||
std::size_t ifstream_size = f_source.gcount();
|
||||
assert (ifstream_size == expected_size); int is_same = std::memcmp(&d[0], ifstream_ptr, ifstream_size);
|
||||
assert(is_same == 0); int is_same_vec = std::memcmp(vec_d.data(), ifstream_ptr, ifstream_size);
|
||||
assert(is_same_vec == 0);} â *end example*]
|
||||
|
||||
[*Example [3](#example-3)*: int i = {#embed "i.dat"}; // well-formed if i.dat produces a single valueint i2 =#embed "i.dat" ; // also well-formed if i.dat produces a single valuestruct s {double a, b, c; struct { double e, f, g; } x; double h, i, j;};
|
||||
s x = {// well-formed if the directive produces nine or fewer values#embed "s.dat"}; â *end example*]
|
||||
|
||||
[14](#14)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1012)
|
||||
|
||||
A preprocessing directive of the form
|
||||
|
||||
# embed [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]") [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
|
||||
(that does not match the previous form) is permitted[.](#14.sentence-1)
|
||||
|
||||
The preprocessing tokens after embed 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)[.](#14.sentence-2)
|
||||
|
||||
Then, an attempt is made to form a [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") preprocessing token ([[lex.header]](lex.header "5.6 Header names")) from the whitespace and the characters
|
||||
of the spellings of the resulting sequence of preprocessing tokens immediately after embed;
|
||||
the treatment of whitespace
|
||||
is implementation-defined[.](#14.sentence-3)
|
||||
|
||||
If the attempt succeeds, the directive with the so-formed [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") is processed as specified for the previous form[.](#14.sentence-4)
|
||||
|
||||
Otherwise, the program is ill-formed[.](#14.sentence-5)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
Adjacent [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]")*s* are not concatenated into a single[*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]") (see the translation phases in [[lex.phases]](lex.phases "5.2 Phases of translation"));
|
||||
thus, an expansion that results in two [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]")*s* is an
|
||||
invalid directive[.](#14.sentence-6)
|
||||
|
||||
â *end note*]
|
||||
|
||||
Any further processing as in normal text described for the previous
|
||||
form is not performed[.](#14.sentence-7)
|
||||
|
||||
[*Note [3](#note-3)*:
|
||||
|
||||
That is, processing as in normal text happens once and only once for the entire
|
||||
directive[.](#14.sentence-8)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [4](#example-4)*:
|
||||
|
||||
If the directive matches the second form, the whole directive is replaced[.](#14.sentence-9)
|
||||
|
||||
If the directive matches the first form, everything after the name is replaced[.](#14.sentence-10)
|
||||
|
||||
#define EMPTY#define X myfile#define Y rsc#define Z 42#embed <myfile.rsc> prefix(Z)#embed EMPTY <X.Y> prefix(Z) is equivalent to:#embed <myfile.rsc> prefix(42)#embed <myfile.rsc> prefix(42)
|
||||
|
||||
â *end example*]
|
||||
135
cppdraft/cpp/embed/param.md
Normal file
135
cppdraft/cpp/embed/param.md
Normal file
@@ -0,0 +1,135 @@
|
||||
[cpp.embed.param]
|
||||
|
||||
# 15 Preprocessing directives [[cpp]](./#cpp)
|
||||
|
||||
## 15.4 Resource inclusion [[cpp.embed]](cpp.embed#param)
|
||||
|
||||
### 15.4.2 Embed parameters [cpp.embed.param]
|
||||
|
||||
#### [15.4.2.1](#limit) limit parameter [[cpp.embed.param.limit]](cpp.embed.param.limit)
|
||||
|
||||
[1](#limit-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1063)
|
||||
|
||||
An [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]") of the formlimit ( [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]") ) specifies the
|
||||
maximum possible number of elements in the comma-delimited list[.](#limit-1.sentence-1)
|
||||
|
||||
It shall appear at most once in the [*embed-parameter-seq*](cpp.pre#nt:embed-parameter-seq "15.1 Preamble [cpp.pre]")[.](#limit-1.sentence-2)
|
||||
|
||||
The preprocessing token defined shall not appear in the[*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")[.](#limit-1.sentence-3)
|
||||
|
||||
[2](#limit-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1072)
|
||||
|
||||
The [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]") is evaluated as a[*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") using the rules as described in conditional
|
||||
inclusion ([[cpp.cond]](cpp.cond "15.2 Conditional inclusion")), but without being processed as in normal text an
|
||||
additional time[.](#limit-2.sentence-1)
|
||||
|
||||
[*Example [1](#limit-example-1)*: #undef DATA_LIMIT#if __has_embed(<data.dat> limit(DATA_LIMIT))#endif
|
||||
|
||||
is equivalent to:
|
||||
|
||||
#if __has_embed(<data.dat> limit(0))#endif â *end example*]
|
||||
|
||||
[*Example [2](#limit-example-2)*: #embed <data.dat> limit(__has_include("a.h"))#if __has_embed(<data.dat> limit(__has_include("a.h")))// ill-formed: __has_include ([[cpp.cond]](cpp.cond "15.2 Conditional inclusion")) cannot appear here#endif â *end example*]
|
||||
|
||||
[3](#limit-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1103)
|
||||
|
||||
The [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") shall be an integral constant expression
|
||||
whose value is greater than or equal to zero[.](#limit-3.sentence-1)
|
||||
|
||||
The resource-count ([[cpp.embed.gen]](cpp.embed.gen "15.4.1 General")) becomes
|
||||
implementation-resource-count, if the value of the[*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") is greater than
|
||||
implementation-resource-count; otherwise, the value of the[*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]")[.](#limit-3.sentence-2)
|
||||
|
||||
[*Example [3](#limit-example-3)*: constexpr unsigned char sound_signature[] = {// a hypothetical resource capable of expanding to four or more elements#embed <sdk/jump.wav> limit(2+2)};
|
||||
|
||||
static_assert(sizeof(sound_signature) == 4); // OK â *end example*]
|
||||
|
||||
#### [15.4.2.2](#prefix) prefix parameter [[cpp.embed.param.prefix]](cpp.embed.param.prefix)
|
||||
|
||||
[1](#prefix-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1123)
|
||||
|
||||
An [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]") of the form
|
||||
|
||||
prefix ( [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")opt )
|
||||
|
||||
shall appear at most once in the [*embed-parameter-seq*](cpp.pre#nt:embed-parameter-seq "15.1 Preamble [cpp.pre]")[.](#prefix-1.sentence-1)
|
||||
|
||||
[2](#prefix-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1130)
|
||||
|
||||
If the resource is empty, this [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]") is ignored[.](#prefix-2.sentence-1)
|
||||
|
||||
Otherwise, the [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]") is placed immediately
|
||||
before the comma-delimited list of integral literals[.](#prefix-2.sentence-2)
|
||||
|
||||
#### [15.4.2.3](#suffix) suffix parameter [[cpp.embed.param.suffix]](cpp.embed.param.suffix)
|
||||
|
||||
[1](#suffix-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1136)
|
||||
|
||||
An [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]") of the form
|
||||
|
||||
suffix ( [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")opt )
|
||||
|
||||
shall appear at most once in the [*embed-parameter-seq*](cpp.pre#nt:embed-parameter-seq "15.1 Preamble [cpp.pre]")[.](#suffix-1.sentence-1)
|
||||
|
||||
[2](#suffix-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1143)
|
||||
|
||||
If the resource is empty, this [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]") is ignored[.](#suffix-2.sentence-1)
|
||||
|
||||
Otherwise, the [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]") is placed immediately after
|
||||
the comma-delimited list of the integral constant expressions[.](#suffix-2.sentence-2)
|
||||
|
||||
[*Example [1](#suffix-example-1)*: constexpr unsigned char whl[] = {#embed "ches.glsl" \
|
||||
prefix(0xEF, 0xBB, 0xBF, ) /* a sequence of bytes */ \
|
||||
suffix(,)0};// always null-terminated, contains the sequence if not emptyconstexpr bool is_empty = sizeof(whl) == 1 && whl[0] == '\0';constexpr bool is_not_empty = sizeof(whl) >= 4&& whl[sizeof(whl) - 1] == '\0'&& whl[0] == '\xEF' && whl[1] == '\xBB' && whl[2] == '\xBF';static_assert(is_empty || is_not_empty); â *end example*]
|
||||
|
||||
#### [15.4.2.4](#if.empty) if_empty parameter [[cpp.embed.param.if.empty]](cpp.embed.param.if.empty)
|
||||
|
||||
[1](#if.empty-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1166)
|
||||
|
||||
An embed-parameter of the form
|
||||
|
||||
if_empty ( [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")opt )
|
||||
|
||||
shall appear at most once in the [*embed-parameter-seq*](cpp.pre#nt:embed-parameter-seq "15.1 Preamble [cpp.pre]")[.](#if.empty-1.sentence-1)
|
||||
|
||||
[2](#if.empty-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1173)
|
||||
|
||||
If the resource is not empty, this [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]") is ignored[.](#if.empty-2.sentence-1)
|
||||
|
||||
Otherwise, the #embed directive is replaced by the[*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")[.](#if.empty-2.sentence-2)
|
||||
|
||||
[*Example [1](#if.empty-example-1)*:
|
||||
|
||||
limit(0) affects when a resource is considered empty[.](#if.empty-2.sentence-3)
|
||||
|
||||
Therefore, the following program:
|
||||
|
||||
#embed </owo/uwurandom> \
|
||||
if_empty(42203) limit(0) expands to42203
|
||||
|
||||
â *end example*]
|
||||
|
||||
[*Example [2](#if.empty-example-2)*:
|
||||
|
||||
This resource is considered empty due to the limit(0) [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]"),
|
||||
always, including in __has_embed clauses[.](#if.empty-2.sentence-6)
|
||||
|
||||
int infinity_zero () {#if __has_embed(</owo/uwurandom> limit(0) prefix(some tokens)) == __STDC_EMBED_EMPTY__ // if </owo/uwurandom> exists, this conditional inclusion branch is taken and the function returns 0.return 0;#else// otherwise, the resource does not exist#error "The resource does not exist"#endif} â *end example*]
|
||||
45
cppdraft/cpp/embed/param/if/empty.md
Normal file
45
cppdraft/cpp/embed/param/if/empty.md
Normal file
@@ -0,0 +1,45 @@
|
||||
[cpp.embed.param.if.empty]
|
||||
|
||||
# 15 Preprocessing directives [[cpp]](./#cpp)
|
||||
|
||||
## 15.4 Resource inclusion [[cpp.embed]](cpp.embed#param.if.empty)
|
||||
|
||||
### 15.4.2 Embed parameters [[cpp.embed.param]](cpp.embed.param#if.empty)
|
||||
|
||||
#### 15.4.2.4 if_empty parameter [cpp.embed.param.if.empty]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1166)
|
||||
|
||||
An embed-parameter of the form
|
||||
|
||||
if_empty ( [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")opt )
|
||||
|
||||
shall appear at most once in the [*embed-parameter-seq*](cpp.pre#nt:embed-parameter-seq "15.1 Preamble [cpp.pre]")[.](#1.sentence-1)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1173)
|
||||
|
||||
If the resource is not empty, this [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]") is ignored[.](#2.sentence-1)
|
||||
|
||||
Otherwise, the #embed directive is replaced by the[*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")[.](#2.sentence-2)
|
||||
|
||||
[*Example [1](#example-1)*:
|
||||
|
||||
limit(0) affects when a resource is considered empty[.](#2.sentence-3)
|
||||
|
||||
Therefore, the following program:
|
||||
|
||||
#embed </owo/uwurandom> \
|
||||
if_empty(42203) limit(0) expands to42203
|
||||
|
||||
â *end example*]
|
||||
|
||||
[*Example [2](#example-2)*:
|
||||
|
||||
This resource is considered empty due to the limit(0) [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]"),
|
||||
always, including in __has_embed clauses[.](#2.sentence-6)
|
||||
|
||||
int infinity_zero () {#if __has_embed(</owo/uwurandom> limit(0) prefix(some tokens)) == __STDC_EMBED_EMPTY__ // if </owo/uwurandom> exists, this conditional inclusion branch is taken and the function returns 0.return 0;#else// otherwise, the resource does not exist#error "The resource does not exist"#endif} â *end example*]
|
||||
51
cppdraft/cpp/embed/param/limit.md
Normal file
51
cppdraft/cpp/embed/param/limit.md
Normal file
@@ -0,0 +1,51 @@
|
||||
[cpp.embed.param.limit]
|
||||
|
||||
# 15 Preprocessing directives [[cpp]](./#cpp)
|
||||
|
||||
## 15.4 Resource inclusion [[cpp.embed]](cpp.embed#param.limit)
|
||||
|
||||
### 15.4.2 Embed parameters [[cpp.embed.param]](cpp.embed.param#limit)
|
||||
|
||||
#### 15.4.2.1 limit parameter [cpp.embed.param.limit]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1063)
|
||||
|
||||
An [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]") of the formlimit ( [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]") ) specifies the
|
||||
maximum possible number of elements in the comma-delimited list[.](#1.sentence-1)
|
||||
|
||||
It shall appear at most once in the [*embed-parameter-seq*](cpp.pre#nt:embed-parameter-seq "15.1 Preamble [cpp.pre]")[.](#1.sentence-2)
|
||||
|
||||
The preprocessing token defined shall not appear in the[*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")[.](#1.sentence-3)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1072)
|
||||
|
||||
The [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]") is evaluated as a[*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") using the rules as described in conditional
|
||||
inclusion ([[cpp.cond]](cpp.cond "15.2 Conditional inclusion")), but without being processed as in normal text an
|
||||
additional time[.](#2.sentence-1)
|
||||
|
||||
[*Example [1](#example-1)*: #undef DATA_LIMIT#if __has_embed(<data.dat> limit(DATA_LIMIT))#endif
|
||||
|
||||
is equivalent to:
|
||||
|
||||
#if __has_embed(<data.dat> limit(0))#endif â *end example*]
|
||||
|
||||
[*Example [2](#example-2)*: #embed <data.dat> limit(__has_include("a.h"))#if __has_embed(<data.dat> limit(__has_include("a.h")))// ill-formed: __has_include ([[cpp.cond]](cpp.cond "15.2 Conditional inclusion")) cannot appear here#endif â *end example*]
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1103)
|
||||
|
||||
The [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") shall be an integral constant expression
|
||||
whose value is greater than or equal to zero[.](#3.sentence-1)
|
||||
|
||||
The resource-count ([[cpp.embed.gen]](cpp.embed.gen "15.4.1 General")) becomes
|
||||
implementation-resource-count, if the value of the[*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") is greater than
|
||||
implementation-resource-count; otherwise, the value of the[*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]")[.](#3.sentence-2)
|
||||
|
||||
[*Example [3](#example-3)*: constexpr unsigned char sound_signature[] = {// a hypothetical resource capable of expanding to four or more elements#embed <sdk/jump.wav> limit(2+2)};
|
||||
|
||||
static_assert(sizeof(sound_signature) == 4); // OK â *end example*]
|
||||
28
cppdraft/cpp/embed/param/prefix.md
Normal file
28
cppdraft/cpp/embed/param/prefix.md
Normal file
@@ -0,0 +1,28 @@
|
||||
[cpp.embed.param.prefix]
|
||||
|
||||
# 15 Preprocessing directives [[cpp]](./#cpp)
|
||||
|
||||
## 15.4 Resource inclusion [[cpp.embed]](cpp.embed#param.prefix)
|
||||
|
||||
### 15.4.2 Embed parameters [[cpp.embed.param]](cpp.embed.param#prefix)
|
||||
|
||||
#### 15.4.2.2 prefix parameter [cpp.embed.param.prefix]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1123)
|
||||
|
||||
An [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]") of the form
|
||||
|
||||
prefix ( [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")opt )
|
||||
|
||||
shall appear at most once in the [*embed-parameter-seq*](cpp.pre#nt:embed-parameter-seq "15.1 Preamble [cpp.pre]")[.](#1.sentence-1)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1130)
|
||||
|
||||
If the resource is empty, this [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]") is ignored[.](#2.sentence-1)
|
||||
|
||||
Otherwise, the [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]") is placed immediately
|
||||
before the comma-delimited list of integral literals[.](#2.sentence-2)
|
||||
32
cppdraft/cpp/embed/param/suffix.md
Normal file
32
cppdraft/cpp/embed/param/suffix.md
Normal file
@@ -0,0 +1,32 @@
|
||||
[cpp.embed.param.suffix]
|
||||
|
||||
# 15 Preprocessing directives [[cpp]](./#cpp)
|
||||
|
||||
## 15.4 Resource inclusion [[cpp.embed]](cpp.embed#param.suffix)
|
||||
|
||||
### 15.4.2 Embed parameters [[cpp.embed.param]](cpp.embed.param#suffix)
|
||||
|
||||
#### 15.4.2.3 suffix parameter [cpp.embed.param.suffix]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1136)
|
||||
|
||||
An [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]") of the form
|
||||
|
||||
suffix ( [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")opt )
|
||||
|
||||
shall appear at most once in the [*embed-parameter-seq*](cpp.pre#nt:embed-parameter-seq "15.1 Preamble [cpp.pre]")[.](#1.sentence-1)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1143)
|
||||
|
||||
If the resource is empty, this [*embed-parameter*](cpp.pre#nt:embed-parameter "15.1 Preamble [cpp.pre]") is ignored[.](#2.sentence-1)
|
||||
|
||||
Otherwise, the [*pp-balanced-token-seq*](cpp.pre#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]") is placed immediately after
|
||||
the comma-delimited list of the integral constant expressions[.](#2.sentence-2)
|
||||
|
||||
[*Example [1](#example-1)*: constexpr unsigned char whl[] = {#embed "ches.glsl" \
|
||||
prefix(0xEF, 0xBB, 0xBF, ) /* a sequence of bytes */ \
|
||||
suffix(,)0};// always null-terminated, contains the sequence if not emptyconstexpr bool is_empty = sizeof(whl) == 1 && whl[0] == '\0';constexpr bool is_not_empty = sizeof(whl) >= 4&& whl[sizeof(whl) - 1] == '\0'&& whl[0] == '\xEF' && whl[1] == '\xBB' && whl[2] == '\xBF';static_assert(is_empty || is_not_empty); â *end example*]
|
||||
29
cppdraft/cpp/error.md
Normal file
29
cppdraft/cpp/error.md
Normal file
@@ -0,0 +1,29 @@
|
||||
[cpp.error]
|
||||
|
||||
# 15 Preprocessing directives [[cpp]](./#cpp)
|
||||
|
||||
## 15.9 Diagnostic directives [cpp.error]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L2126)
|
||||
|
||||
A preprocessing directive of the form
|
||||
|
||||
# error [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]")opt [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
|
||||
renders the program ill-formed[.](#1.sentence-1)
|
||||
|
||||
A preprocessing directive of the form
|
||||
|
||||
# warning [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]")opt [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
|
||||
requires the implementation to produce at least one diagnostic message
|
||||
for the preprocessing translation unit ([[intro.compliance.general]](intro.compliance.general "4.1.1 General"))[.](#1.sentence-2)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L2139)
|
||||
|
||||
*Recommended practice*: Any diagnostic message caused by either of these directives
|
||||
should include the specified sequence of preprocessing tokens[.](#2.sentence-1)
|
||||
177
cppdraft/cpp/import.md
Normal file
177
cppdraft/cpp/import.md
Normal file
@@ -0,0 +1,177 @@
|
||||
[cpp.import]
|
||||
|
||||
# 15 Preprocessing directives [[cpp]](./#cpp)
|
||||
|
||||
## 15.6 Header unit importation [cpp.import]
|
||||
|
||||
[pp-import:](#nt:pp-import "15.6 Header unit importation [cpp.import]")
|
||||
exportopt import [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]")opt ; [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
exportopt import [*header-name-tokens*](cpp.cond#nt:header-name-tokens "15.2 Conditional inclusion [cpp.cond]") [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]")opt ; [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
exportopt import [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]") ; [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1278)
|
||||
|
||||
A [*pp-import*](#nt:pp-import "15.6 Header unit importation [cpp.import]") shall not
|
||||
appear in a context where import or (if it is the first preprocessing token of the [*pp-import*](#nt:pp-import "15.6 Header unit importation [cpp.import]")) export is an identifier defined as an object-like macro[.](#1.sentence-1)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1284)
|
||||
|
||||
The preprocessing tokens after the import preprocessing token
|
||||
in the import [*control-line*](cpp.pre#nt:control-line "15.1 Preamble [cpp.pre]") 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)[.](#2.sentence-1)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
An import directive
|
||||
matching the first two forms of a [*pp-import*](#nt:pp-import "15.6 Header unit importation [cpp.import]") instructs the preprocessor to import macros
|
||||
from the header unit ([[module.import]](module.import "10.3 Import declaration"))
|
||||
denoted by the [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]"),
|
||||
as described below[.](#2.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
The [*point of macro import*](#def:macro,point_of_import "15.6 Header unit importation [cpp.import]") for the
|
||||
first two forms of [*pp-import*](#nt:pp-import "15.6 Header unit importation [cpp.import]") is
|
||||
immediately after the [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]") terminating
|
||||
the [*pp-import*](#nt:pp-import "15.6 Header unit importation [cpp.import]")[.](#2.sentence-3)
|
||||
|
||||
The last form of [*pp-import*](#nt:pp-import "15.6 Header unit importation [cpp.import]") is only considered
|
||||
if the first two forms did not match, and
|
||||
does not have a point of macro import[.](#2.sentence-4)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1307)
|
||||
|
||||
If a [*pp-import*](#nt:pp-import "15.6 Header unit importation [cpp.import]") is produced by source file inclusion
|
||||
(including by the rewrite produced
|
||||
when a #include directive names an importable header)
|
||||
while processing the [*group*](cpp.pre#nt:group "15.1 Preamble [cpp.pre]") of a [*module-file*](cpp.pre#nt:module-file "15.1 Preamble [cpp.pre]"),
|
||||
the program is ill-formed[.](#3.sentence-1)
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1314)
|
||||
|
||||
In all three forms of [*pp-import*](#nt:pp-import "15.6 Header unit importation [cpp.import]"),
|
||||
the import and export (if it exists) preprocessing tokens
|
||||
are replaced by the *import-keyword* and*export-keyword* preprocessing tokens respectively[.](#4.sentence-1)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
This makes the line no longer a directive
|
||||
so it is not removed at the end of phase 4[.](#4.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
Additionally, in the second form of [*pp-import*](#nt:pp-import "15.6 Header unit importation [cpp.import]"),
|
||||
a [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") token is formed as if
|
||||
the [*header-name-tokens*](cpp.cond#nt:header-name-tokens "15.2 Conditional inclusion [cpp.cond]") were the [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]") of a #include directive[.](#4.sentence-3)
|
||||
|
||||
The [*header-name-tokens*](cpp.cond#nt:header-name-tokens "15.2 Conditional inclusion [cpp.cond]") are replaced by
|
||||
the [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") token[.](#4.sentence-4)
|
||||
|
||||
[*Note [3](#note-3)*:
|
||||
|
||||
This ensures that imports are treated consistently by
|
||||
the preprocessor and later phases of translation[.](#4.sentence-5)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1334)
|
||||
|
||||
Each #define directive encountered when preprocessing
|
||||
each translation unit in a program results in a distinct[*macro definition*](#def:macro,definition "15.6 Header unit importation [cpp.import]")[.](#5.sentence-1)
|
||||
|
||||
[*Note [4](#note-4)*:
|
||||
|
||||
A predefined macro name ([[cpp.predefined]](cpp.predefined "15.12 Predefined macro names"))
|
||||
is not introduced by a #define directive[.](#5.sentence-2)
|
||||
|
||||
Implementations providing mechanisms to predefine additional macros
|
||||
are encouraged to not treat them
|
||||
as being introduced by a #define directive[.](#5.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
Each macro definition has at most one point of definition in
|
||||
each translation unit and at most one point of undefinition, as follows:
|
||||
|
||||
- [(5.1)](#5.1)
|
||||
|
||||
The [*point of definition*](#def:macro,point_of_definition "15.6 Header unit importation [cpp.import]") of a macro definition within a translation unit T is
|
||||
* [(5.1.1)](#5.1.1)
|
||||
|
||||
if the #define directive of the macro definition occurs within T,
|
||||
the point at which that directive occurs, or otherwise,
|
||||
|
||||
* [(5.1.2)](#5.1.2)
|
||||
|
||||
if the macro name is not lexically identical to a keyword ([[lex.key]](lex.key "5.12 Keywords"))
|
||||
or to the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")*s* module or import,
|
||||
the first point of macro import in T of a header unit
|
||||
containing a point of definition for the macro definition, if any[.](#5.1.sentence-1)
|
||||
|
||||
In the latter case, the macro is said
|
||||
to be [*imported*](#def:macro,import "15.6 Header unit importation [cpp.import]") from the header unit[.](#5.1.sentence-2)
|
||||
|
||||
- [(5.2)](#5.2)
|
||||
|
||||
The [*point of undefinition*](#def:macro,point_of_undefinition "15.6 Header unit importation [cpp.import]") of a macro definition within a translation unit
|
||||
is the first point at which a #undef directive naming the macro occurs
|
||||
after its point of definition, or the first point
|
||||
of macro import of a header unit containing a point of undefinition for the
|
||||
macro definition, whichever (if any) occurs first[.](#5.2.sentence-1)
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1375)
|
||||
|
||||
A macro definition is [*active*](#def:macro,active "15.6 Header unit importation [cpp.import]") at a source location
|
||||
if it has a point of definition in that translation unit preceding the location,
|
||||
and does not have a point of undefinition in that translation unit preceding
|
||||
the location[.](#6.sentence-1)
|
||||
|
||||
[7](#7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1382)
|
||||
|
||||
If a macro would be replaced or redefined, and multiple macro definitions
|
||||
are active for that macro name, the active macro definitions shall all be
|
||||
valid redefinitions of the same macro ([[cpp.replace]](cpp.replace "15.7 Macro replacement"))[.](#7.sentence-1)
|
||||
|
||||
[*Note [5](#note-5)*:
|
||||
|
||||
The relative order of [*pp-import*](#nt:pp-import "15.6 Header unit importation [cpp.import]")*s* has no bearing on whether a
|
||||
particular macro definition is active[.](#7.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[8](#8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1391)
|
||||
|
||||
[*Example [1](#example-1)*:
|
||||
|
||||
Importable header "a.h":#define X 123 // #1#define Y 45 // #2#define Z a // #3#undef X // point of undefinition of #1 in "a.h"
|
||||
|
||||
Importable header "b.h":import "a.h"; // point of definition of #1, #2, and #3, point of undefinition of #1 in "b.h"#define X 456 // OK, #1 is not active#define Y 6 // error: #2 is active
|
||||
|
||||
Importable header "c.h":#define Y 45 // #4#define Z c // #5
|
||||
|
||||
Importable header "d.h":import "c.h"; // point of definition of #4 and #5 in "d.h"
|
||||
|
||||
Importable header "e.h":import "a.h"; // point of definition of #1, #2, and #3, point of undefinition of #1 in "e.h"import "d.h"; // point of definition of #4 and #5 in "e.h"int a = Y; // OK, active macro definitions #2 and #4 are valid redefinitionsint c = Z; // error: active macro definitions #3 and #5 are not valid redefinitions of Z
|
||||
|
||||
Module unit f:export module f;export import "a.h";
|
||||
|
||||
int a = Y; // OK
|
||||
|
||||
Translation unit #1:import f;int x = Y; // error: Y is neither a defined macro nor a declared name â *end example*]
|
||||
172
cppdraft/cpp/include.md
Normal file
172
cppdraft/cpp/include.md
Normal file
@@ -0,0 +1,172 @@
|
||||
[cpp.include]
|
||||
|
||||
# 15 Preprocessing directives [[cpp]](./#cpp)
|
||||
|
||||
## 15.3 Source file inclusion [cpp.include]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L697)
|
||||
|
||||
A [*header search*](#def:search,header "15.3 Source file inclusion [cpp.include]") for a sequence of characters
|
||||
searches a sequence of places for a header
|
||||
identified uniquely by that sequence of characters[.](#1.sentence-1)
|
||||
|
||||
How the places are determined or the header identified
|
||||
is implementation-defined[.](#1.sentence-2)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L704)
|
||||
|
||||
A [*source file search*](#def:search,source_file "15.3 Source file inclusion [cpp.include]") for a sequence of characters
|
||||
attempts to identify a source file that is named by the sequence of characters[.](#2.sentence-1)
|
||||
|
||||
The named source file is searched for
|
||||
in an implementation-defined manner[.](#2.sentence-2)
|
||||
|
||||
If the implementation does not support a source file search
|
||||
for that sequence of characters, or if the search fails,
|
||||
the result of the source file search
|
||||
is the result of a header search for the same sequence of characters[.](#2.sentence-3)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L714)
|
||||
|
||||
A preprocessing directive of the form
|
||||
|
||||
# include [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
|
||||
causes the replacement of that directive by the entire contents
|
||||
of the header or source file identified by [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]")[.](#3.sentence-1)
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L722)
|
||||
|
||||
If the [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") is of the form
|
||||
|
||||
< [*h-char-sequence*](lex.header#nt:h-char-sequence "5.6 Header names [lex.header]") >
|
||||
|
||||
a header is identified by a header search for the sequence of characters
|
||||
of the [*h-char-sequence*](lex.header#nt:h-char-sequence "5.6 Header names [lex.header]")[.](#4.sentence-1)
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L730)
|
||||
|
||||
If the [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") is of the form
|
||||
|
||||
" [*q-char-sequence*](lex.header#nt:q-char-sequence "5.6 Header names [lex.header]") "
|
||||
|
||||
the source file or header is identified by a source file search
|
||||
for the sequence of characters of the [*q-char-sequence*](lex.header#nt:q-char-sequence "5.6 Header names [lex.header]")[.](#5.sentence-1)
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L738)
|
||||
|
||||
If a header search fails, or if a source file search or header search
|
||||
identifies a header or source file that cannot be processed by the implementation,
|
||||
the program is ill-formed[.](#6.sentence-1)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
If the header or source file cannot be processed,
|
||||
the program is ill-formed even when evaluating __has_include[.](#6.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[7](#7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L747)
|
||||
|
||||
A preprocessing directive of the form
|
||||
|
||||
# include [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]") [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
|
||||
(that does not match the previous form) is permitted[.](#7.sentence-1)
|
||||
|
||||
The preprocessing tokens afterinclude 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)[.](#7.sentence-2)
|
||||
|
||||
Then, an attempt is made to form a [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") preprocessing token ([[lex.header]](lex.header "5.6 Header names")) from the whitespace and the characters
|
||||
of the spellings of the resulting sequence of preprocessing tokens;
|
||||
the treatment of whitespace
|
||||
is implementation-defined[.](#7.sentence-3)
|
||||
|
||||
If the attempt succeeds, the directive with the so-formed [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") is processed as specified for the previous form[.](#7.sentence-4)
|
||||
|
||||
Otherwise, the program is ill-formed, no diagnostic required[.](#7.sentence-5)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
Adjacent [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]")*s* are not concatenated into
|
||||
a single [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]") (see the translation phases in [[lex.phases]](lex.phases "5.2 Phases of translation"));
|
||||
thus, an expansion that results in two [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]")*s* is an
|
||||
invalid directive[.](#7.sentence-6)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[8](#8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L774)
|
||||
|
||||
The implementation shall provide unique mappings for
|
||||
sequences consisting of one or more[*nondigit*](lex.name#nt:nondigit "5.11 Identifiers [lex.name]")*s* or [*digit*](lex.name#nt:digit "5.11 Identifiers [lex.name]")*s* ([[lex.name]](lex.name "5.11 Identifiers"))
|
||||
followed by a period
|
||||
(.)
|
||||
and a single[*nondigit*](lex.name#nt:nondigit "5.11 Identifiers [lex.name]")[.](#8.sentence-1)
|
||||
|
||||
The first character shall not be a [*digit*](lex.name#nt:digit "5.11 Identifiers [lex.name]")[.](#8.sentence-2)
|
||||
|
||||
The implementation may ignore distinctions of alphabetical case[.](#8.sentence-3)
|
||||
|
||||
[9](#9)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L785)
|
||||
|
||||
A#include preprocessing directive may appear
|
||||
in a source file that has been read because of a#include directive in another file,
|
||||
up to an implementation-defined nesting limit[.](#9.sentence-1)
|
||||
|
||||
[10](#10)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L794)
|
||||
|
||||
If the header identified by the [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") denotes an importable header ([[module.import]](module.import "10.3 Import declaration")),
|
||||
it isimplementation-defined
|
||||
whether the #include preprocessing directive
|
||||
is instead replaced by an import directive ([[cpp.import]](cpp.import "15.6 Header unit importation")) of the form
|
||||
|
||||
import [*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]") ; [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
|
||||
[11](#11)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L806)
|
||||
|
||||
[*Note [3](#note-3)*:
|
||||
|
||||
An implementation can provide a mechanism for making arbitrary
|
||||
source files available to the < > search[.](#11.sentence-1)
|
||||
|
||||
However, using the < > form for headers provided
|
||||
with the implementation and the " " form for sources
|
||||
outside the control of the implementation
|
||||
achieves wider portability[.](#11.sentence-2)
|
||||
|
||||
For instance:#include <stdio.h>#include <unistd.h>#include "usefullib.h"#include "myprog.h"
|
||||
|
||||
â *end note*]
|
||||
|
||||
[12](#12)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L822)
|
||||
|
||||
[*Example [1](#example-1)*:
|
||||
|
||||
This illustrates macro-replaced#include directives:#if VERSION == 1#define INCFILE "vers1.h"#elif VERSION == 2#define INCFILE "vers2.h" // and so on#else#define INCFILE "versN.h"#endif#include INCFILE
|
||||
|
||||
â *end example*]
|
||||
70
cppdraft/cpp/line.md
Normal file
70
cppdraft/cpp/line.md
Normal file
@@ -0,0 +1,70 @@
|
||||
[cpp.line]
|
||||
|
||||
# 15 Preprocessing directives [[cpp]](./#cpp)
|
||||
|
||||
## 15.8 Line control [cpp.line]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L2066)
|
||||
|
||||
The [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]") of a#line directive, if present,
|
||||
shall be a character string literal[.](#1.sentence-1)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L2072)
|
||||
|
||||
The[*line number*](#def:line_number "15.8 Line control [cpp.line]") of the current source line is
|
||||
the line number of the current physical source line,
|
||||
i.e., it is one greater than
|
||||
the number of new-line characters read or introduced
|
||||
in [translation phase 1](lex.phases "5.2 Phases of translation [lex.phases]") while processing the source file to the current preprocessing token[.](#2.sentence-1)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L2082)
|
||||
|
||||
A preprocessing directive of the form
|
||||
|
||||
# line [*digit-sequence*](lex.fcon#nt:digit-sequence "5.13.4 Floating-point literals [lex.fcon]") [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
|
||||
causes the implementation to behave as if
|
||||
the following sequence of source lines begins with a
|
||||
source line that has a line number as specified
|
||||
by the digit sequence (interpreted as a decimal integer)[.](#3.sentence-1)
|
||||
|
||||
If the digit sequence specifies zero
|
||||
or a number greater than 2147483647,
|
||||
the program is ill-formed[.](#3.sentence-2)
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L2095)
|
||||
|
||||
A preprocessing directive of the form
|
||||
|
||||
# line [*digit-sequence*](lex.fcon#nt:digit-sequence "5.13.4 Floating-point literals [lex.fcon]") " [*s-char-sequence*](lex.string#nt:s-char-sequence "5.13.5 String literals [lex.string]")opt " [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
|
||||
sets the presumed line number similarly and changes the
|
||||
presumed name of the source file to be the contents
|
||||
of the character string literal[.](#4.sentence-1)
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L2104)
|
||||
|
||||
A preprocessing directive of the form
|
||||
|
||||
# line [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]") [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
|
||||
(that does not match one of the two previous forms)
|
||||
is permitted[.](#5.sentence-1)
|
||||
|
||||
The preprocessing tokens afterline on the directive are processed just as in normal text
|
||||
(each identifier currently defined as a macro name is replaced by its
|
||||
replacement list of preprocessing tokens)[.](#5.sentence-2)
|
||||
|
||||
If the directive resulting after all replacements does not match
|
||||
one of the two previous forms, the program is ill-formed;
|
||||
otherwise, the result is processed as appropriate[.](#5.sentence-3)
|
||||
68
cppdraft/cpp/module.md
Normal file
68
cppdraft/cpp/module.md
Normal file
@@ -0,0 +1,68 @@
|
||||
[cpp.module]
|
||||
|
||||
# 15 Preprocessing directives [[cpp]](./#cpp)
|
||||
|
||||
## 15.5 Module directive [cpp.module]
|
||||
|
||||
[pp-module:](#nt:pp-module "15.5 Module directive [cpp.module]")
|
||||
exportopt module [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]")opt ; [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1217)
|
||||
|
||||
A [*pp-module*](#nt:pp-module "15.5 Module directive [cpp.module]") shall not
|
||||
appear in a context where module or (if it is the first preprocessing token of the [*pp-module*](#nt:pp-module "15.5 Module directive [cpp.module]")) export is an identifier defined as an object-like macro[.](#1.sentence-1)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1223)
|
||||
|
||||
The [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]"), if any, of a [*pp-module*](#nt:pp-module "15.5 Module directive [cpp.module]") shall be of the form:
|
||||
|
||||
[*pp-module-name*](#nt:pp-module-name "15.5 Module directive [cpp.module]") [*pp-module-partition*](#nt:pp-module-partition "15.5 Module directive [cpp.module]")opt [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]")opt
|
||||
|
||||
where the [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]") (if any) shall not begin with
|
||||
a ( preprocessing token and
|
||||
the grammar non-terminals are defined as:
|
||||
|
||||
[pp-module-name:](#nt:pp-module-name "15.5 Module directive [cpp.module]")
|
||||
[*pp-module-name-qualifier*](#nt:pp-module-name-qualifier "15.5 Module directive [cpp.module]")opt [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")
|
||||
|
||||
[pp-module-partition:](#nt:pp-module-partition "15.5 Module directive [cpp.module]")
|
||||
: [*pp-module-name-qualifier*](#nt:pp-module-name-qualifier "15.5 Module directive [cpp.module]")opt [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")
|
||||
|
||||
[pp-module-name-qualifier:](#nt:pp-module-name-qualifier "15.5 Module directive [cpp.module]")
|
||||
[*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") .
|
||||
[*pp-module-name-qualifier*](#nt:pp-module-name-qualifier "15.5 Module directive [cpp.module]") [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") .
|
||||
|
||||
No [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") in
|
||||
the [*pp-module-name*](#nt:pp-module-name "15.5 Module directive [cpp.module]") or [*pp-module-partition*](#nt:pp-module-partition "15.5 Module directive [cpp.module]") shall currently be defined as an object-like macro[.](#2.sentence-1)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1249)
|
||||
|
||||
Any preprocessing tokens after the module preprocessing token
|
||||
in the module directive are processed just as in normal text[.](#3.sentence-1)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
Each identifier currently defined as a macro name
|
||||
is replaced by its replacement list of preprocessing tokens[.](#3.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1257)
|
||||
|
||||
The module and export (if it exists) preprocessing tokens
|
||||
are replaced by the *module-keyword* and*export-keyword* preprocessing tokens respectively[.](#4.sentence-1)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
This makes the line no longer a directive
|
||||
so it is not removed at the end of phase 4[.](#4.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
15
cppdraft/cpp/null.md
Normal file
15
cppdraft/cpp/null.md
Normal file
@@ -0,0 +1,15 @@
|
||||
[cpp.null]
|
||||
|
||||
# 15 Preprocessing directives [[cpp]](./#cpp)
|
||||
|
||||
## 15.11 Null directive [cpp.null]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L2162)
|
||||
|
||||
A preprocessing directive of the form
|
||||
|
||||
# [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
|
||||
has no effect[.](#1.sentence-1)
|
||||
21
cppdraft/cpp/pragma.md
Normal file
21
cppdraft/cpp/pragma.md
Normal file
@@ -0,0 +1,21 @@
|
||||
[cpp.pragma]
|
||||
|
||||
# 15 Preprocessing directives [[cpp]](./#cpp)
|
||||
|
||||
## 15.10 Pragma directive [cpp.pragma]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L2148)
|
||||
|
||||
A preprocessing directive of the form
|
||||
|
||||
# pragma [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]")opt [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
|
||||
causes the implementation to behave
|
||||
in an implementation-defined manner[.](#1.sentence-1)
|
||||
|
||||
The behavior may cause translation to fail or cause the translator or
|
||||
the resulting program to behave in a non-conforming manner[.](#1.sentence-2)
|
||||
|
||||
Any pragma that is not recognized by the implementation is ignored[.](#1.sentence-3)
|
||||
37
cppdraft/cpp/pragma/op.md
Normal file
37
cppdraft/cpp/pragma/op.md
Normal file
@@ -0,0 +1,37 @@
|
||||
[cpp.pragma.op]
|
||||
|
||||
# 15 Preprocessing directives [[cpp]](./#cpp)
|
||||
|
||||
## 15.13 Pragma operator [cpp.pragma.op]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L2469)
|
||||
|
||||
A unary operator expression of the form:
|
||||
|
||||
_Pragma ( [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]") )
|
||||
|
||||
is processed as follows: The [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]") is [*destringized*](#def:destringization "15.13 Pragma operator [cpp.pragma.op]") by deleting the L prefix, if present, deleting the leading and trailing
|
||||
double-quotes, replacing each escape sequence \" by a double-quote, and
|
||||
replacing each escape sequence \\ by a single
|
||||
backslash[.](#1.sentence-1)
|
||||
|
||||
The resulting sequence of characters is processed through translation phase 3
|
||||
to produce preprocessing tokens that are executed as if they were the[*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]") in a pragma directive[.](#1.sentence-2)
|
||||
|
||||
The original four preprocessing
|
||||
tokens in the unary operator expression are removed[.](#1.sentence-3)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L2483)
|
||||
|
||||
[*Example [1](#example-1)*:
|
||||
|
||||
#pragma listing on "..\listing.dir" can also be expressed as:_Pragma ( "listing on \"..\\listing.dir\"" )
|
||||
|
||||
The latter form is processed in the same way whether it appears literally
|
||||
as shown, or results from macro replacement, as in:#define LISTING(x) PRAGMA(listing on #x)#define PRAGMA(x) _Pragma(#x) LISTING( ..\listing.dir )
|
||||
|
||||
â *end example*]
|
||||
260
cppdraft/cpp/pre.md
Normal file
260
cppdraft/cpp/pre.md
Normal file
@@ -0,0 +1,260 @@
|
||||
[cpp.pre]
|
||||
|
||||
# 15 Preprocessing directives [[cpp]](./#cpp)
|
||||
|
||||
## 15.1 Preamble [cpp.pre]
|
||||
|
||||
[preprocessing-file:](#nt:preprocessing-file "15.1 Preamble [cpp.pre]")
|
||||
[*group*](#nt:group "15.1 Preamble [cpp.pre]")opt
|
||||
[*module-file*](#nt:module-file "15.1 Preamble [cpp.pre]")
|
||||
|
||||
[module-file:](#nt:module-file "15.1 Preamble [cpp.pre]")
|
||||
[*pp-global-module-fragment*](#nt:pp-global-module-fragment "15.1 Preamble [cpp.pre]")opt [*pp-module*](cpp.module#nt:pp-module "15.5 Module directive [cpp.module]") [*group*](#nt:group "15.1 Preamble [cpp.pre]")opt [*pp-private-module-fragment*](#nt:pp-private-module-fragment "15.1 Preamble [cpp.pre]")opt
|
||||
|
||||
[pp-global-module-fragment:](#nt:pp-global-module-fragment "15.1 Preamble [cpp.pre]")
|
||||
module ; [*new-line*](#nt:new-line "15.1 Preamble [cpp.pre]") [*group*](#nt:group "15.1 Preamble [cpp.pre]")opt
|
||||
|
||||
[pp-private-module-fragment:](#nt:pp-private-module-fragment "15.1 Preamble [cpp.pre]")
|
||||
module : private ; [*new-line*](#nt:new-line "15.1 Preamble [cpp.pre]") [*group*](#nt:group "15.1 Preamble [cpp.pre]")opt
|
||||
|
||||
[group:](#nt:group "15.1 Preamble [cpp.pre]")
|
||||
[*group-part*](#nt:group-part "15.1 Preamble [cpp.pre]")
|
||||
[*group*](#nt:group "15.1 Preamble [cpp.pre]") [*group-part*](#nt:group-part "15.1 Preamble [cpp.pre]")
|
||||
|
||||
[group-part:](#nt:group-part "15.1 Preamble [cpp.pre]")
|
||||
[*control-line*](#nt:control-line "15.1 Preamble [cpp.pre]")
|
||||
[*if-section*](#nt:if-section "15.1 Preamble [cpp.pre]")
|
||||
[*text-line*](#nt:text-line "15.1 Preamble [cpp.pre]")
|
||||
# [*conditionally-supported-directive*](#nt:conditionally-supported-directive "15.1 Preamble [cpp.pre]")
|
||||
|
||||
[control-line:](#nt:control-line "15.1 Preamble [cpp.pre]")
|
||||
# include [*pp-tokens*](#nt:pp-tokens "15.1 Preamble [cpp.pre]") [*new-line*](#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
[*pp-import*](cpp.import#nt:pp-import "15.6 Header unit importation [cpp.import]")
|
||||
# embed [*pp-tokens*](#nt:pp-tokens "15.1 Preamble [cpp.pre]") [*new-line*](#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
# define [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [*replacement-list*](#nt:replacement-list "15.1 Preamble [cpp.pre]") [*new-line*](#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
# define [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [*lparen*](#nt:lparen "15.1 Preamble [cpp.pre]") [*identifier-list*](#nt:identifier-list "15.1 Preamble [cpp.pre]")opt ) [*replacement-list*](#nt:replacement-list "15.1 Preamble [cpp.pre]") [*new-line*](#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
# define [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [*lparen*](#nt:lparen "15.1 Preamble [cpp.pre]") ... ) [*replacement-list*](#nt:replacement-list "15.1 Preamble [cpp.pre]") [*new-line*](#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
# define [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [*lparen*](#nt:lparen "15.1 Preamble [cpp.pre]") [*identifier-list*](#nt:identifier-list "15.1 Preamble [cpp.pre]") , ... ) [*replacement-list*](#nt:replacement-list "15.1 Preamble [cpp.pre]") [*new-line*](#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
# undef [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [*new-line*](#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
# line [*pp-tokens*](#nt:pp-tokens "15.1 Preamble [cpp.pre]") [*new-line*](#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
# error [*pp-tokens*](#nt:pp-tokens "15.1 Preamble [cpp.pre]")opt [*new-line*](#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
# warning [*pp-tokens*](#nt:pp-tokens "15.1 Preamble [cpp.pre]")opt [*new-line*](#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
# pragma [*pp-tokens*](#nt:pp-tokens "15.1 Preamble [cpp.pre]")opt [*new-line*](#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
# [*new-line*](#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
|
||||
[if-section:](#nt:if-section "15.1 Preamble [cpp.pre]")
|
||||
[*if-group*](#nt:if-group "15.1 Preamble [cpp.pre]") [*elif-groups*](#nt:elif-groups "15.1 Preamble [cpp.pre]")opt [*else-group*](#nt:else-group "15.1 Preamble [cpp.pre]")opt [*endif-line*](#nt:endif-line "15.1 Preamble [cpp.pre]")
|
||||
|
||||
[if-group:](#nt:if-group "15.1 Preamble [cpp.pre]")
|
||||
# if [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") [*new-line*](#nt:new-line "15.1 Preamble [cpp.pre]") [*group*](#nt:group "15.1 Preamble [cpp.pre]")opt
|
||||
# ifdef [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [*new-line*](#nt:new-line "15.1 Preamble [cpp.pre]") [*group*](#nt:group "15.1 Preamble [cpp.pre]")opt
|
||||
# ifndef [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [*new-line*](#nt:new-line "15.1 Preamble [cpp.pre]") [*group*](#nt:group "15.1 Preamble [cpp.pre]")opt
|
||||
|
||||
[elif-groups:](#nt:elif-groups "15.1 Preamble [cpp.pre]")
|
||||
[*elif-group*](#nt:elif-group "15.1 Preamble [cpp.pre]") [*elif-groups*](#nt:elif-groups "15.1 Preamble [cpp.pre]")opt
|
||||
|
||||
[elif-group:](#nt:elif-group "15.1 Preamble [cpp.pre]")
|
||||
# elif [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") [*new-line*](#nt:new-line "15.1 Preamble [cpp.pre]") [*group*](#nt:group "15.1 Preamble [cpp.pre]")opt
|
||||
# elifdef [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [*new-line*](#nt:new-line "15.1 Preamble [cpp.pre]") [*group*](#nt:group "15.1 Preamble [cpp.pre]")opt
|
||||
# elifndef [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [*new-line*](#nt:new-line "15.1 Preamble [cpp.pre]") [*group*](#nt:group "15.1 Preamble [cpp.pre]")opt
|
||||
|
||||
[else-group:](#nt:else-group "15.1 Preamble [cpp.pre]")
|
||||
# else [*new-line*](#nt:new-line "15.1 Preamble [cpp.pre]") [*group*](#nt:group "15.1 Preamble [cpp.pre]")opt
|
||||
|
||||
[endif-line:](#nt:endif-line "15.1 Preamble [cpp.pre]")
|
||||
# endif [*new-line*](#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
|
||||
[text-line:](#nt:text-line "15.1 Preamble [cpp.pre]")
|
||||
[*pp-tokens*](#nt:pp-tokens "15.1 Preamble [cpp.pre]")opt [*new-line*](#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
|
||||
[conditionally-supported-directive:](#nt:conditionally-supported-directive "15.1 Preamble [cpp.pre]")
|
||||
[*pp-tokens*](#nt:pp-tokens "15.1 Preamble [cpp.pre]") [*new-line*](#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
|
||||
[lparen:](#nt:lparen "15.1 Preamble [cpp.pre]")
|
||||
a ( character not immediately preceded by whitespace
|
||||
|
||||
[identifier-list:](#nt:identifier-list "15.1 Preamble [cpp.pre]")
|
||||
[*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")
|
||||
[*identifier-list*](#nt:identifier-list "15.1 Preamble [cpp.pre]") , [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")
|
||||
|
||||
[replacement-list:](#nt:replacement-list "15.1 Preamble [cpp.pre]")
|
||||
[*pp-tokens*](#nt:pp-tokens "15.1 Preamble [cpp.pre]")opt
|
||||
|
||||
[pp-tokens:](#nt:pp-tokens "15.1 Preamble [cpp.pre]")
|
||||
[*preprocessing-token*](lex.pptoken#nt:preprocessing-token "5.5 Preprocessing tokens [lex.pptoken]") [*pp-tokens*](#nt:pp-tokens "15.1 Preamble [cpp.pre]")opt
|
||||
|
||||
[embed-parameter-seq:](#nt:embed-parameter-seq "15.1 Preamble [cpp.pre]")
|
||||
[*embed-parameter*](#nt:embed-parameter "15.1 Preamble [cpp.pre]") [*embed-parameter-seq*](#nt:embed-parameter-seq "15.1 Preamble [cpp.pre]")opt
|
||||
|
||||
[embed-parameter:](#nt:embed-parameter "15.1 Preamble [cpp.pre]")
|
||||
[*embed-standard-parameter*](#nt:embed-standard-parameter "15.1 Preamble [cpp.pre]")
|
||||
[*embed-prefixed-parameter*](#nt:embed-prefixed-parameter "15.1 Preamble [cpp.pre]")
|
||||
|
||||
[embed-standard-parameter:](#nt:embed-standard-parameter "15.1 Preamble [cpp.pre]")
|
||||
limit ( [*pp-balanced-token-seq*](#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]") )
|
||||
prefix ( [*pp-balanced-token-seq*](#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")opt )
|
||||
suffix ( [*pp-balanced-token-seq*](#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")opt )
|
||||
if_empty ( [*pp-balanced-token-seq*](#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")opt )
|
||||
|
||||
[embed-prefixed-parameter:](#nt:embed-prefixed-parameter "15.1 Preamble [cpp.pre]")
|
||||
[*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") :: [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")
|
||||
[*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") :: [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") ( [*pp-balanced-token-seq*](#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")opt )
|
||||
|
||||
[pp-balanced-token-seq:](#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")
|
||||
[*pp-balanced-token*](#nt:pp-balanced-token "15.1 Preamble [cpp.pre]") [*pp-balanced-token-seq*](#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")opt
|
||||
|
||||
[pp-balanced-token:](#nt:pp-balanced-token "15.1 Preamble [cpp.pre]")
|
||||
( [*pp-balanced-token-seq*](#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")opt )
|
||||
[ [*pp-balanced-token-seq*](#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")opt ]
|
||||
{ [*pp-balanced-token-seq*](#nt:pp-balanced-token-seq "15.1 Preamble [cpp.pre]")opt }
|
||||
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:](#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
the new-line character
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L176)
|
||||
|
||||
A [*preprocessing directive*](#def:preprocessing_directive "15.1 Preamble [cpp.pre]") 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*](#def:token,directive-introducing "15.1 Preamble [cpp.pre]"),
|
||||
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
|
||||
|
||||
- [(1.1)](#1.1)
|
||||
|
||||
a # preprocessing token, or
|
||||
|
||||
- [(1.2)](#1.2)
|
||||
|
||||
an import preprocessing token
|
||||
immediately followed on the same logical source line by a[*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]"),<,[*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]"),[*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]"), or: preprocessing token, or
|
||||
|
||||
- [(1.3)](#1.3)
|
||||
|
||||
a module preprocessing token
|
||||
immediately followed on the same logical source line by an[*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]"),:, or; preprocessing token, or
|
||||
|
||||
- [(1.4)](#1.4)
|
||||
|
||||
an export preprocessing token
|
||||
immediately followed on the same logical source line by
|
||||
one of the two preceding forms[.](#1.sentence-1)
|
||||
|
||||
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[.](#1.sentence-2)[122](#footnote-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).")
|
||||
|
||||
[*Note [1](#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[.](#1.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [1](#example-1)*: # // preprocessing directivemodule ; // preprocessing directiveexport module leftpad; // preprocessing directiveimport <string>; // 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](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L255)
|
||||
|
||||
A sequence of preprocessing tokens is only a [*text-line*](#nt:text-line "15.1 Preamble [cpp.pre]") if it does not begin with a directive-introducing token[.](#2.sentence-1)
|
||||
|
||||
[*Example [2](#example-2)*: using module = int;module i; // not a [*text-line*](#nt:text-line "15.1 Preamble [cpp.pre]") and not a [*control-line*](#nt:control-line "15.1 Preamble [cpp.pre]")int foo() {return i;}
|
||||
|
||||
The example is not a valid [*preprocessing-file*](#nt:preprocessing-file "15.1 Preamble [cpp.pre]")[.](#2.sentence-2)
|
||||
|
||||
â *end example*]
|
||||
|
||||
A sequence of preprocessing tokens is only a [*conditionally-supported-directive*](#nt:conditionally-supported-directive "15.1 Preamble [cpp.pre]") if it does not begin with any of the directive names
|
||||
appearing after a # in the syntax[.](#2.sentence-3)
|
||||
|
||||
A [*conditionally-supported-directive*](#nt:conditionally-supported-directive "15.1 Preamble [cpp.pre]") is
|
||||
conditionally-supported withimplementation-defined
|
||||
semantics[.](#2.sentence-4)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L276)
|
||||
|
||||
If one of the [*pp-tokens*](#nt:pp-tokens "15.1 Preamble [cpp.pre]") of a #embed directive
|
||||
(before macro replacement) is the [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")limit, prefix, suffix, or if_empty and that [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") is defined
|
||||
as a macro ([[cpp.replace.general]](cpp.replace.general "15.7.1 General")), the program is ill-formed[.](#3.sentence-1)
|
||||
|
||||
Any [*embed-prefixed-parameter*](#nt:embed-prefixed-parameter "15.1 Preamble [cpp.pre]") is conditionally-supported,
|
||||
with implementation-defined semantics[.](#3.sentence-2)
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L285)
|
||||
|
||||
At the start of phase 4 of translation,
|
||||
the [*group*](#nt:group "15.1 Preamble [cpp.pre]") of a [*pp-global-module-fragment*](#nt:pp-global-module-fragment "15.1 Preamble [cpp.pre]") shall
|
||||
contain neither a [*text-line*](#nt:text-line "15.1 Preamble [cpp.pre]") nor a [*pp-import*](cpp.import#nt:pp-import "15.6 Header unit importation [cpp.import]")[.](#4.sentence-1)
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L290)
|
||||
|
||||
When in a group that is skipped ([[cpp.cond]](cpp.cond "15.2 Conditional inclusion")), the directive
|
||||
syntax is relaxed to allow any sequence of preprocessing tokens to occur between
|
||||
the directive name and the following new-line character[.](#5.sentence-1)
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L295)
|
||||
|
||||
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)[.](#6.sentence-1)
|
||||
|
||||
[7](#7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L306)
|
||||
|
||||
The implementation can
|
||||
process and skip sections of source files conditionally,
|
||||
include other source files,
|
||||
import macros from header units,
|
||||
and replace macros[.](#7.sentence-1)
|
||||
|
||||
These capabilities are called[*preprocessing*](#def:preprocessing "15.1 Preamble [cpp.pre]"),
|
||||
because conceptually they occur
|
||||
before translation of the resulting translation unit[.](#7.sentence-2)
|
||||
|
||||
[8](#8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L317)
|
||||
|
||||
The preprocessing tokens within a preprocessing directive
|
||||
are not subject to macro expansion unless otherwise stated[.](#8.sentence-1)
|
||||
|
||||
[*Example [3](#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[.](#8.sentence-2)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[122)](#footnote-122)[122)](#footnoteref-122)
|
||||
|
||||
Thus,
|
||||
preprocessing directives are commonly called âlinesâ[.](#footnote-122.sentence-1)
|
||||
|
||||
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]](cpp.stringize "15.7.3 The # operator"), for example)[.](#footnote-122.sentence-2)
|
||||
272
cppdraft/cpp/predefined.md
Normal file
272
cppdraft/cpp/predefined.md
Normal file
@@ -0,0 +1,272 @@
|
||||
[cpp.predefined]
|
||||
|
||||
# 15 Preprocessing directives [[cpp]](./#cpp)
|
||||
|
||||
## 15.12 Predefined macro names [cpp.predefined]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L2173)
|
||||
|
||||
The following macro names shall be defined by the implementation:
|
||||
|
||||
- [(1.1)](#1.1)
|
||||
|
||||
__cplusplus
|
||||
The integer literal 202302L[.](#1.1.sentence-2)
|
||||
[*Note [1](#note-1)*:
|
||||
Future revisions of this document will
|
||||
replace the value of this macro with a greater value[.](#1.1.sentence-3)
|
||||
â *end note*]
|
||||
|
||||
- [(1.2)](#1.2)
|
||||
|
||||
The names listed in Table [22](#tab:cpp.predefined.ft "Table 22: Feature-test macros")[.](#1.2.sentence-1)
|
||||
|
||||
The macros defined in Table [22](#tab:cpp.predefined.ft "Table 22: Feature-test macros") shall be defined to
|
||||
the corresponding integer literal[.](#1.2.sentence-2)
|
||||
[*Note [2](#note-2)*:
|
||||
Future revisions of this document might replace
|
||||
the values of these macros with greater values[.](#1.2.sentence-3)
|
||||
â *end note*]
|
||||
|
||||
- [(1.3)](#1.3)
|
||||
|
||||
__DATE__
|
||||
The date of translation of the source file:
|
||||
a character string literal of the form"Mmm dd yyyy",
|
||||
where the names of the months are the same as those generated
|
||||
by theasctime function,
|
||||
and the first character ofdd is a space character if the value is less than 10[.](#1.3.sentence-2)
|
||||
If the date of translation is not available,
|
||||
an implementation-defined valid date
|
||||
shall be supplied[.](#1.3.sentence-3)
|
||||
|
||||
- [(1.4)](#1.4)
|
||||
|
||||
__FILE__
|
||||
The presumed name of the current source file (a character string
|
||||
literal)[.](#1.4.sentence-2)[129](#footnote-129 "The presumed source file name can be changed by the #line directive.")
|
||||
|
||||
- [(1.5)](#1.5)
|
||||
|
||||
__LINE__
|
||||
The presumed line number (within the current source file) of the current source line
|
||||
(an integer literal)[.](#1.5.sentence-2)[130](#footnote-130 "The presumed line number can be changed by the #line directive.")
|
||||
|
||||
- [(1.6)](#1.6)
|
||||
|
||||
__STDC_EMBED_NOT_FOUND__, __STDC_EMBED_FOUND__, and __STDC_EMBED_EMPTY__
|
||||
The integer literals 0, 1, and 2, respectively[.](#1.6.sentence-2)
|
||||
[*Note [3](#note-3)*:
|
||||
These represent values replaced from [*has-embed-expression*](cpp.cond#nt:has-embed-expression "15.2 Conditional inclusion [cpp.cond]")*s* ([[cpp.cond]](cpp.cond "15.2 Conditional inclusion"))[.](#1.6.sentence-3)
|
||||
â *end note*]
|
||||
|
||||
- [(1.7)](#1.7)
|
||||
|
||||
__STDC_HOSTED__
|
||||
The integer literal 1 if the implementation is a hosted implementation or
|
||||
the integer literal 0 if it is a freestanding implementation ([[intro.compliance]](intro.compliance "4.1 Implementation compliance"))[.](#1.7.sentence-2)
|
||||
|
||||
- [(1.8)](#1.8)
|
||||
|
||||
__STDCPP_DEFAULT_NEW_ALIGNMENT__
|
||||
An integer literal of type std::size_t whose value is the alignment guaranteed
|
||||
by a call to operator new(std::size_t) or operator new[](std::size_t)[.](#1.8.sentence-2)
|
||||
[*Note [4](#note-4)*:
|
||||
Larger alignments will be passed tooperator new(std::size_t, std::align_val_t), etc[.](#1.8.sentence-3)
|
||||
([[expr.new]](expr.new "7.6.2.8 New"))[.](#1.8.sentence-4)
|
||||
â *end note*]
|
||||
|
||||
- [(1.9)](#1.9)
|
||||
|
||||
__STDCPP_FLOAT16_T__
|
||||
Defined as the integer literal 1 if and only if the implementation supports
|
||||
the ISO/IEC 60559 floating-point interchange format binary16
|
||||
as an extended floating-point type ([[basic.extended.fp]](basic.extended.fp "6.9.3 Optional extended floating-point types"))[.](#1.9.sentence-2)
|
||||
|
||||
- [(1.10)](#1.10)
|
||||
|
||||
__STDCPP_FLOAT32_T__
|
||||
Defined as the integer literal 1 if and only if the implementation supports
|
||||
the ISO/IEC 60559 floating-point interchange format binary32
|
||||
as an extended floating-point type[.](#1.10.sentence-2)
|
||||
|
||||
- [(1.11)](#1.11)
|
||||
|
||||
__STDCPP_FLOAT64_T__
|
||||
Defined as the integer literal 1 if and only if the implementation supports
|
||||
the ISO/IEC 60559 floating-point interchange format binary64
|
||||
as an extended floating-point type[.](#1.11.sentence-2)
|
||||
|
||||
- [(1.12)](#1.12)
|
||||
|
||||
__STDCPP_FLOAT128_T__
|
||||
Defined as the integer literal 1 if and only if the implementation supports
|
||||
the ISO/IEC 60559 floating-point interchange format binary128
|
||||
as an extended floating-point type[.](#1.12.sentence-2)
|
||||
|
||||
- [(1.13)](#1.13)
|
||||
|
||||
__STDCPP_BFLOAT16_T__
|
||||
Defined as the integer literal 1 if and only if the implementation supports an extended floating-point type
|
||||
with the properties of the [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") std::bfloat16_t as described in [[basic.extended.fp]](basic.extended.fp "6.9.3 Optional extended floating-point types")[.](#1.13.sentence-2)
|
||||
|
||||
- [(1.14)](#1.14)
|
||||
|
||||
__TIME__
|
||||
The time of translation of the source file:
|
||||
a character string literal of the form"hh:mm:ss" as in the time generated by theasctime function[.](#1.14.sentence-2)
|
||||
If the time of translation is not available,
|
||||
an implementation-defined valid time shall be supplied[.](#1.14.sentence-3)
|
||||
|
||||
Table [22](#tab:cpp.predefined.ft) — Feature-test macros [[tab:cpp.predefined.ft]](./tab:cpp.predefined.ft)
|
||||
|
||||
| [ð](#tab:cpp.predefined.ft-row-1)<br>**Macro name** | **Value** |
|
||||
| --- | --- |
|
||||
| [ð](#tab:cpp.predefined.ft-row-2)<br>__cpp_aggregate_bases | 201603L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-3)<br>__cpp_aggregate_nsdmi | 201304L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-4)<br>__cpp_aggregate_paren_init | 201902L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-5)<br>__cpp_alias_templates | 200704L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-6)<br>__cpp_aligned_new | 201606L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-7)<br>__cpp_attributes | 200809L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-8)<br>__cpp_auto_cast | 202110L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-9)<br>__cpp_binary_literals | 201304L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-10)<br>__cpp_capture_star_this | 201603L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-11)<br>__cpp_char8_t | 202207L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-12)<br>__cpp_concepts | 202002L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-13)<br>__cpp_conditional_explicit | 201806L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-14)<br>__cpp_constexpr | 202406L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-15)<br>__cpp_constexpr_dynamic_alloc | 201907L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-16)<br>__cpp_constexpr_exceptions | 202411L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-17)<br>__cpp_constexpr_in_decltype | 201711L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-18)<br>__cpp_constexpr_virtual_inheritance | 202506L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-19)<br>__cpp_consteval | 202211L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-20)<br>__cpp_constinit | 201907L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-21)<br>__cpp_contracts | 202502L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-22)<br>__cpp_decltype | 200707L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-23)<br>__cpp_decltype_auto | 201304L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-24)<br>__cpp_deduction_guides | 201907L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-25)<br>__cpp_delegating_constructors | 200604L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-26)<br>__cpp_deleted_function | 202403L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-27)<br>__cpp_designated_initializers | 201707L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-28)<br>__cpp_enumerator_attributes | 201411L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-29)<br>__cpp_expansion_statements | 202506L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-30)<br>__cpp_explicit_this_parameter | 202110L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-31)<br>__cpp_fold_expressions | 201603L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-32)<br>__cpp_generic_lambdas | 201707L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-33)<br>__cpp_guaranteed_copy_elision | 201606L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-34)<br>__cpp_hex_float | 201603L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-35)<br>__cpp_if_consteval | 202106L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-36)<br>__cpp_if_constexpr | 201606L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-37)<br>__cpp_impl_coroutine | 201902L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-38)<br>__cpp_impl_destroying_delete | 201806L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-39)<br>__cpp_impl_three_way_comparison | 201907L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-40)<br>__cpp_impl_reflection | 202506L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-41)<br>__cpp_implicit_move | 202207L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-42)<br>__cpp_inheriting_constructors | 201511L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-43)<br>__cpp_init_captures | 201803L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-44)<br>__cpp_initializer_lists | 200806L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-45)<br>__cpp_inline_variables | 201606L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-46)<br>__cpp_lambdas | 200907L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-47)<br>__cpp_modules | 201907L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-48)<br>__cpp_multidimensional_subscript | 202211L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-49)<br>__cpp_named_character_escapes | 202207L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-50)<br>__cpp_namespace_attributes | 201411L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-51)<br>__cpp_noexcept_function_type | 201510L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-52)<br>__cpp_nontype_template_args | 201911L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-53)<br>__cpp_nontype_template_parameter_auto | 201606L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-54)<br>__cpp_nsdmi | 200809L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-55)<br>__cpp_pack_indexing | 202311L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-56)<br>__cpp_placeholder_variables | 202306L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-57)<br>__cpp_pp_embed | 202502L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-58)<br>__cpp_range_based_for | 202211L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-59)<br>__cpp_raw_strings | 200710L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-60)<br>__cpp_ref_qualifiers | 200710L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-61)<br>__cpp_return_type_deduction | 201304L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-62)<br>__cpp_rvalue_references | 200610L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-63)<br>__cpp_size_t_suffix | 202011L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-64)<br>__cpp_sized_deallocation | 201309L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-65)<br>__cpp_static_assert | 202306L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-66)<br>__cpp_static_call_operator | 202207L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-67)<br>__cpp_structured_bindings | 202411L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-68)<br>__cpp_template_parameters | 202502L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-69)<br>__cpp_template_template_args | 201611L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-70)<br>__cpp_threadsafe_static_init | 200806L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-71)<br>__cpp_trivial_relocatability | 202502L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-72)<br>__cpp_trivial_union | 202502L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-73)<br>__cpp_unicode_characters | 200704L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-74)<br>__cpp_unicode_literals | 200710L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-75)<br>__cpp_user_defined_literals | 200809L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-76)<br>__cpp_using_enum | 201907L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-77)<br>__cpp_variable_templates | 201304L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-78)<br>__cpp_variadic_friend | 202403L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-79)<br>__cpp_variadic_templates | 200704L |
|
||||
| [ð](#tab:cpp.predefined.ft-row-80)<br>__cpp_variadic_using | 201611L |
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L2405)
|
||||
|
||||
The following macro names are conditionally defined by the implementation:
|
||||
|
||||
- [(2.1)](#2.1)
|
||||
|
||||
__STDC__
|
||||
Whether __STDC__ is predefined and if so, what its value is,
|
||||
are implementation-defined[.](#2.1.sentence-2)
|
||||
|
||||
- [(2.2)](#2.2)
|
||||
|
||||
__STDC_MB_MIGHT_NEQ_WC__
|
||||
The integer literal 1, intended to indicate that, in the encoding forwchar_t, a member of the basic character set need not have a code value equal to
|
||||
its value when used as the lone character in an ordinary character literal[.](#2.2.sentence-2)
|
||||
|
||||
- [(2.3)](#2.3)
|
||||
|
||||
__STDC_VERSION__
|
||||
Whether __STDC_VERSION__ is predefined and if so, what its value is,
|
||||
are implementation-defined[.](#2.3.sentence-2)
|
||||
|
||||
- [(2.4)](#2.4)
|
||||
|
||||
__STDC_ISO_10646__
|
||||
An integer literal of the form yyyymmL (for example, 199712L)[.](#2.4.sentence-2)
|
||||
Whether __STDC_ISO_10646__ is predefined and
|
||||
if so, what its value is,
|
||||
are implementation-defined[.](#2.4.sentence-3)
|
||||
|
||||
- [(2.5)](#2.5)
|
||||
|
||||
__STDCPP_THREADS__
|
||||
Defined, and has the value integer literal 1, if and only if a program
|
||||
can have more than one [thread of execution](intro.multithread "6.10.2 Multi-threaded executions and data races [intro.multithread]")[.](#2.5.sentence-2)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L2443)
|
||||
|
||||
The values of the predefined macros
|
||||
(except for__FILE__ and__LINE__)
|
||||
remain constant throughout the translation unit[.](#3.sentence-1)
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L2451)
|
||||
|
||||
If any of the pre-defined macro names in this subclause,
|
||||
or the identifierdefined,
|
||||
is the subject of a#define or a#undef preprocessing directive,
|
||||
the program is ill-formed[.](#4.sentence-1)
|
||||
|
||||
Any other predefined macro names shall begin with a
|
||||
leading underscore followed by an uppercase letter or a second
|
||||
underscore[.](#4.sentence-2)
|
||||
|
||||
[129)](#footnote-129)[129)](#footnoteref-129)
|
||||
|
||||
The presumed source file name can be changed by the #line directive[.](#footnote-129.sentence-1)
|
||||
|
||||
[130)](#footnote-130)[130)](#footnoteref-130)
|
||||
|
||||
The presumed line number can be changed by the #line directive[.](#footnote-130.sentence-1)
|
||||
571
cppdraft/cpp/replace.md
Normal file
571
cppdraft/cpp/replace.md
Normal file
@@ -0,0 +1,571 @@
|
||||
[cpp.replace]
|
||||
|
||||
# 15 Preprocessing directives [[cpp]](./#cpp)
|
||||
|
||||
## 15.7 Macro replacement [cpp.replace]
|
||||
|
||||
### [15.7.1](#general) General [[cpp.replace.general]](cpp.replace.general)
|
||||
|
||||
[1](#general-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1443)
|
||||
|
||||
Two replacement lists are identical if and only if
|
||||
the preprocessing tokens in both have
|
||||
the same number, ordering, spelling, and whitespace separation,
|
||||
where all whitespace separations are considered identical[.](#general-1.sentence-1)
|
||||
|
||||
[2](#general-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1450)
|
||||
|
||||
An identifier currently defined as anobject-like macro (see below) may be redefined by another#define preprocessing directive provided that the second definition is an
|
||||
object-like macro definition and the two replacement lists
|
||||
are identical, otherwise the program is ill-formed[.](#general-2.sentence-1)
|
||||
|
||||
Likewise, an identifier currently defined as afunction-like macro (see below) may be redefined by another#define preprocessing directive provided that the second definition is a
|
||||
function-like macro definition that has the same number and spelling
|
||||
of parameters,
|
||||
and the two replacement lists are identical,
|
||||
otherwise the program is ill-formed[.](#general-2.sentence-2)
|
||||
|
||||
[3](#general-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1468)
|
||||
|
||||
[*Example [1](#general-example-1)*:
|
||||
|
||||
The following sequence is valid:#define OBJ_LIKE (1-1)#define OBJ_LIKE /* whitespace */ (1-1) /* other */#define FUNC_LIKE(a) ( a )#define FUNC_LIKE( a )( /* note the whitespace */ \
|
||||
a /* other stuff on this line
|
||||
*/ )
|
||||
|
||||
But the following redefinitions are invalid:#define OBJ_LIKE (0) // different token sequence#define OBJ_LIKE (1 - 1) // different whitespace#define FUNC_LIKE(b) ( a ) // different parameter usage#define FUNC_LIKE(b) ( b ) // different parameter spelling
|
||||
|
||||
â *end example*]
|
||||
|
||||
[4](#general-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1488)
|
||||
|
||||
There shall be whitespace between the identifier and the replacement list
|
||||
in the definition of an object-like macro[.](#general-4.sentence-1)
|
||||
|
||||
[5](#general-5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1493)
|
||||
|
||||
If the [*identifier-list*](cpp.pre#nt:identifier-list "15.1 Preamble [cpp.pre]") in the macro definition does not end with
|
||||
an ellipsis, the number of arguments (including those arguments consisting
|
||||
of no preprocessing tokens)
|
||||
in an invocation of a function-like macro shall
|
||||
equal the number of parameters in the macro definition[.](#general-5.sentence-1)
|
||||
|
||||
Otherwise, there shall be at least as many arguments in the invocation as there are
|
||||
parameters in the macro definition (excluding the ...)[.](#general-5.sentence-2)
|
||||
|
||||
There
|
||||
shall exist a) preprocessing token that terminates the invocation[.](#general-5.sentence-3)
|
||||
|
||||
[6](#general-6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1505)
|
||||
|
||||
The identifiers __VA_ARGS__ and __VA_OPT__ shall occur only in the [*replacement-list*](cpp.pre#nt:replacement-list "15.1 Preamble [cpp.pre]") of a function-like macro that uses the ellipsis notation in the parameters[.](#general-6.sentence-1)
|
||||
|
||||
[7](#general-7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1512)
|
||||
|
||||
A parameter identifier in a function-like macro
|
||||
shall be uniquely declared within its scope[.](#general-7.sentence-1)
|
||||
|
||||
[8](#general-8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1516)
|
||||
|
||||
The identifier immediately following thedefine is called the[*macro name*](#def:macro,name "15.7.1 General [cpp.replace.general]")[.](#general-8.sentence-1)
|
||||
|
||||
There is one name space for macro names[.](#general-8.sentence-2)
|
||||
|
||||
Any whitespace characters preceding or following the
|
||||
replacement list of preprocessing tokens are not considered
|
||||
part of the replacement list for either form of macro[.](#general-8.sentence-3)
|
||||
|
||||
[9](#general-9)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1527)
|
||||
|
||||
A translation unit shall not #define or #undef names lexically identical
|
||||
to keywords,
|
||||
to the identifiers listed in Table [4](lex.name#tab:lex.name.special "Table 4: Identifiers with special meaning"), or
|
||||
to the [*attribute-token*](dcl.attr.grammar#nt:attribute-token "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")*s* described in [[dcl.attr]](dcl.attr "9.13 Attributes"),
|
||||
except that the names likely and unlikely may be
|
||||
defined as function-like macros[.](#general-9.sentence-1)
|
||||
|
||||
[10](#general-10)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1537)
|
||||
|
||||
If a# preprocessing token,
|
||||
followed by an identifier,
|
||||
occurs lexically
|
||||
at the point at which a preprocessing directive can begin,
|
||||
the identifier is not subject to macro replacement[.](#general-10.sentence-1)
|
||||
|
||||
[11](#general-11)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1547)
|
||||
|
||||
A preprocessing directive of the form
|
||||
|
||||
# define [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [*replacement-list*](cpp.pre#nt:replacement-list "15.1 Preamble [cpp.pre]") [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
|
||||
defines an[*object-like macro*](#def:macro,object-like "15.7.1 General [cpp.replace.general]") that
|
||||
causes each subsequent instance of the macro name[125](#footnote-125 "Since, by macro-replacement time, all character-literals and string-literals are preprocessing tokens, not sequences possibly containing identifier-like subsequences (see [lex.phases], translation phases), they are never scanned for macro names or parameters.") to be replaced by the replacement list of preprocessing tokens
|
||||
that constitute the remainder of the directive[.](#general-11.sentence-1)[126](#footnote-126 "An alternative token ([lex.digraph]) is not an identifier, even when its spelling consists entirely of letters and underscores. Therefore it is not possible to define a macro whose name is the same as that of an alternative token.")
|
||||
|
||||
The replacement list is then rescanned for more macro names as
|
||||
specified below[.](#general-11.sentence-2)
|
||||
|
||||
[12](#general-12)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1574)
|
||||
|
||||
[*Example [2](#general-example-2)*:
|
||||
|
||||
The simplest use of this facility is to define a âmanifest constantâ,
|
||||
as in#define TABSIZE 100int table[TABSIZE];
|
||||
|
||||
â *end example*]
|
||||
|
||||
[13](#general-13)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1584)
|
||||
|
||||
A preprocessing directive of the form
|
||||
|
||||
# define [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [*lparen*](cpp.pre#nt:lparen "15.1 Preamble [cpp.pre]") [*identifier-list*](cpp.pre#nt:identifier-list "15.1 Preamble [cpp.pre]")opt ) [*replacement-list*](cpp.pre#nt:replacement-list "15.1 Preamble [cpp.pre]") [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
# define [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [*lparen*](cpp.pre#nt:lparen "15.1 Preamble [cpp.pre]") ... ) [*replacement-list*](cpp.pre#nt:replacement-list "15.1 Preamble [cpp.pre]") [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
# define [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [*lparen*](cpp.pre#nt:lparen "15.1 Preamble [cpp.pre]") [*identifier-list*](cpp.pre#nt:identifier-list "15.1 Preamble [cpp.pre]") , ... ) [*replacement-list*](cpp.pre#nt:replacement-list "15.1 Preamble [cpp.pre]") [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
|
||||
defines a [*function-like macro*](#def:macro,function-like "15.7.1 General [cpp.replace.general]") with parameters, whose use is
|
||||
similar syntactically to a function call[.](#general-13.sentence-1)
|
||||
|
||||
The parametersare specified by the optional list of identifiers[.](#general-13.sentence-2)
|
||||
|
||||
Each subsequent instance of the function-like macro name followed by a( as the next preprocessing token
|
||||
introduces the sequence of preprocessing tokens that is replaced
|
||||
by the replacement list in the definition
|
||||
(an invocation of the macro)[.](#general-13.sentence-3)
|
||||
|
||||
The replaced sequence of preprocessing tokens is terminated by the matching) preprocessing token, skipping intervening matched pairs of left and
|
||||
right parenthesis preprocessing tokens[.](#general-13.sentence-4)
|
||||
|
||||
Within the sequence of preprocessing tokens making up an invocation
|
||||
of a function-like macro,
|
||||
new-line is considered a normal whitespace character[.](#general-13.sentence-5)
|
||||
|
||||
[14](#general-14)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1612)
|
||||
|
||||
The sequence of preprocessing tokens
|
||||
bounded by the outside-most matching parentheses
|
||||
forms the list of arguments for the function-like macro[.](#general-14.sentence-1)
|
||||
|
||||
The individual arguments within the list
|
||||
are separated by comma preprocessing tokens,
|
||||
but comma preprocessing tokens between matching
|
||||
inner parentheses do not separate arguments[.](#general-14.sentence-2)
|
||||
|
||||
If there are sequences of preprocessing tokens within the list of
|
||||
arguments that would otherwise act as preprocessing directives,[127](#footnote-127 "A conditionally-supported-directive is a preprocessing directive regardless of whether the implementation supports it.") the program is ill-formed[.](#general-14.sentence-3)
|
||||
|
||||
[15](#general-15)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1628)
|
||||
|
||||
[*Example [3](#general-example-3)*:
|
||||
|
||||
The following defines a function-like
|
||||
macro whose value is the maximum of its arguments[.](#general-15.sentence-1)
|
||||
|
||||
It has the disadvantages of evaluating one or the other of its arguments
|
||||
a second time
|
||||
(includingside effects)
|
||||
and generating more code than a function if invoked several times[.](#general-15.sentence-2)
|
||||
|
||||
It also cannot have its address taken,
|
||||
as it has none[.](#general-15.sentence-3)
|
||||
|
||||
#define max(a, b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
The parentheses ensure that the arguments and
|
||||
the resulting expression are bound properly[.](#general-15.sentence-4)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[16](#general-16)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1649)
|
||||
|
||||
If there is a ... immediately preceding the ) in the
|
||||
function-like macro
|
||||
definition, then the trailing arguments (if any), including any separating comma preprocessing
|
||||
tokens, are merged to form a single item: the [*variable arguments*](#def:variable_arguments "15.7.1 General [cpp.replace.general]")[.](#general-16.sentence-1)
|
||||
|
||||
The number of
|
||||
arguments so combined is such that, following merger, the number of arguments is
|
||||
either equal to or
|
||||
one more than the number of parameters in the macro definition (excluding the...)[.](#general-16.sentence-2)
|
||||
|
||||
[125)](#footnote-125)[125)](#footnoteref-125)
|
||||
|
||||
Since, by macro-replacement time,
|
||||
all [*character-literal*](lex.ccon#nt:character-literal "5.13.3 Character literals [lex.ccon]")*s* and [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]")*s* are preprocessing tokens,
|
||||
not sequences possibly containing identifier-like subsequences
|
||||
(see [[lex.phases]](lex.phases "5.2 Phases of translation"), translation phases),
|
||||
they are never scanned for macro names or parameters[.](#footnote-125.sentence-1)
|
||||
|
||||
[126)](#footnote-126)[126)](#footnoteref-126)
|
||||
|
||||
An alternative token ([[lex.digraph]](lex.digraph "5.9 Alternative tokens")) is not an identifier,
|
||||
even when its spelling consists entirely of letters and underscores[.](#footnote-126.sentence-1)
|
||||
|
||||
Therefore it is not possible to define a macro
|
||||
whose name is the same as that of an alternative token[.](#footnote-126.sentence-2)
|
||||
|
||||
[127)](#footnote-127)[127)](#footnoteref-127)
|
||||
|
||||
A [*conditionally-supported-directive*](cpp.pre#nt:conditionally-supported-directive "15.1 Preamble [cpp.pre]") is a preprocessing directive regardless of whether the implementation supports it[.](#footnote-127.sentence-1)
|
||||
|
||||
### [15.7.2](#cpp.subst) Argument substitution [[cpp.subst]](cpp.subst)
|
||||
|
||||
[va-opt-replacement:](#nt:va-opt-replacement "15.7.2 Argument substitution [cpp.subst]")
|
||||
__VA_OPT__ ( [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]")opt )
|
||||
|
||||
[1](#cpp.subst-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1670)
|
||||
|
||||
After the arguments for the invocation of a function-like macro have
|
||||
been identified, argument substitution takes place[.](#cpp.subst-1.sentence-1)
|
||||
|
||||
For each parameter in the replacement list that is neither
|
||||
preceded by a # or ## preprocessing token nor
|
||||
followed by a ## preprocessing token, the preprocessing tokens
|
||||
naming the parameter are replaced by a preprocessing token sequence determined as follows:
|
||||
|
||||
- [(1.1)](#cpp.subst-1.1)
|
||||
|
||||
If the parameter is of the form [*va-opt-replacement*](#nt:va-opt-replacement "15.7.2 Argument substitution [cpp.subst]"),
|
||||
the replacement preprocessing tokens are the
|
||||
preprocessing token sequence for the corresponding argument,
|
||||
as specified below[.](#cpp.subst-1.1.sentence-1)
|
||||
|
||||
- [(1.2)](#cpp.subst-1.2)
|
||||
|
||||
Otherwise, the replacement preprocessing tokens are the
|
||||
preprocessing tokens of corresponding argument after all
|
||||
macros contained therein have been expanded[.](#cpp.subst-1.2.sentence-1)
|
||||
The argument's
|
||||
preprocessing tokens are completely macro replaced before
|
||||
being substituted as if they formed the rest of the preprocessing
|
||||
translation unit with no other preprocessing tokens being available[.](#cpp.subst-1.2.sentence-2)
|
||||
|
||||
[*Example [1](#cpp.subst-example-1)*: #define LPAREN() (#define G(Q) 42#define F(R, X, ...) __VA_OPT__(G R X) )int x = F(LPAREN(), 0, <:-); // replaced by int x = 42; â *end example*]
|
||||
|
||||
[2](#cpp.subst-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1700)
|
||||
|
||||
An identifier __VA_ARGS__ that occurs in the replacement list
|
||||
shall be treated as if it were a parameter, and the variable arguments shall form
|
||||
the preprocessing tokens used to replace it[.](#cpp.subst-2.sentence-1)
|
||||
|
||||
[3](#cpp.subst-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1706)
|
||||
|
||||
[*Example [2](#cpp.subst-example-2)*:
|
||||
|
||||
#define debug(...) fprintf(stderr, __VA_ARGS__)#define showlist(...) puts(#__VA_ARGS__)#define report(test, ...) ((test) ? puts(#test) : printf(__VA_ARGS__)) debug("Flag");
|
||||
debug("X = %d\n", x);
|
||||
showlist(The first, second, and third items.);
|
||||
report(x>y, "x is %d but y is %d", x, y); results infprintf(stderr, "Flag");
|
||||
fprintf(stderr, "X = %d\n", x);
|
||||
puts("The first, second, and third items.");((x>y) ? puts("x>y") : printf("x is %d but y is %d", x, y));
|
||||
|
||||
â *end example*]
|
||||
|
||||
[4](#cpp.subst-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1726)
|
||||
|
||||
The identifier __VA_OPT__ shall always occur as part of the preprocessing token sequence[*va-opt-replacement*](#nt:va-opt-replacement "15.7.2 Argument substitution [cpp.subst]");
|
||||
its closing ) is determined by skipping
|
||||
intervening pairs of matching left and right parentheses
|
||||
in its [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]")[.](#cpp.subst-4.sentence-1)
|
||||
|
||||
The [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]") of a [*va-opt-replacement*](#nt:va-opt-replacement "15.7.2 Argument substitution [cpp.subst]") shall not contain __VA_OPT__[.](#cpp.subst-4.sentence-2)
|
||||
|
||||
If the [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]") would be ill-formed
|
||||
as the replacement list of the current function-like macro,
|
||||
the program is ill-formed[.](#cpp.subst-4.sentence-3)
|
||||
|
||||
A [*va-opt-replacement*](#nt:va-opt-replacement "15.7.2 Argument substitution [cpp.subst]") is treated as if it were a parameter,
|
||||
and the preprocessing token sequence for the corresponding
|
||||
argument is defined as follows[.](#cpp.subst-4.sentence-4)
|
||||
|
||||
If the substitution of __VA_ARGS__ as neither an operand
|
||||
of # nor ## consists of no preprocessing tokens,
|
||||
the argument consists of
|
||||
a single placemarker preprocessing token ([[cpp.concat]](#cpp.concat "15.7.4 The ## operator"), [[cpp.rescan]](#cpp.rescan "15.7.5 Rescanning and further replacement"))[.](#cpp.subst-4.sentence-5)
|
||||
|
||||
Otherwise, the argument consists of
|
||||
the results of the expansion of the contained [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]") as the replacement list of the current function-like macro
|
||||
before removal of placemarker tokens, rescanning, and further replacement[.](#cpp.subst-4.sentence-6)
|
||||
|
||||
[*Note [1](#cpp.subst-note-1)*:
|
||||
|
||||
The placemarker tokens are removed before stringization ([[cpp.stringize]](#cpp.stringize "15.7.3 The # operator")),
|
||||
and can be removed by rescanning and further replacement ([[cpp.rescan]](#cpp.rescan "15.7.5 Rescanning and further replacement"))[.](#cpp.subst-4.sentence-7)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [3](#cpp.subst-example-3)*: #define F(...) f(0 __VA_OPT__(,) __VA_ARGS__)#define G(X, ...) f(0, X __VA_OPT__(,) __VA_ARGS__)#define SDEF(sname, ...) S sname __VA_OPT__(= { __VA_ARGS__ })#define EMP
|
||||
|
||||
F(a, b, c) // replaced by f(0, a, b, c) F() // replaced by f(0) F(EMP) // replaced by f(0) G(a, b, c) // replaced by f(0, a, b, c) G(a, ) // replaced by f(0, a) G(a) // replaced by f(0, a) SDEF(foo); // replaced by S foo; SDEF(bar, 1, 2); // replaced by S bar = { 1, 2 };#define H1(X, ...) X __VA_OPT__(##) __VA_ARGS__ // error: ## may not appear at// the beginning of a replacement list ([[cpp.concat]](#cpp.concat "15.7.4 The ## operator"))#define H2(X, Y, ...) __VA_OPT__(X ## Y,) __VA_ARGS__
|
||||
H2(a, b, c, d) // replaced by ab, c, d#define H3(X, ...) #__VA_OPT__(X##X X##X) H3(, 0) // replaced by ""#define H4(X, ...) __VA_OPT__(a X ## X) ## b
|
||||
H4(, 1) // replaced by a b#define H5A(...) __VA_OPT__()/**/__VA_OPT__()#define H5B(X) a ## X ## b#define H5C(X) H5B(X) H5C(H5A()) // replaced by ab â *end example*]
|
||||
|
||||
### [15.7.3](#cpp.stringize) The # operator [[cpp.stringize]](cpp.stringize)
|
||||
|
||||
[1](#cpp.stringize-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1795)
|
||||
|
||||
Each# preprocessing token in the replacement list for a function-like
|
||||
macro shall be followed by a parameter as the next preprocessing
|
||||
token in the replacement list[.](#cpp.stringize-1.sentence-1)
|
||||
|
||||
[2](#cpp.stringize-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1802)
|
||||
|
||||
A [*character string literal*](#def:character_string_literal "15.7.3 The # operator [cpp.stringize]") is a [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]") with no prefix[.](#cpp.stringize-2.sentence-1)
|
||||
|
||||
If, in the replacement list, a parameter is immediately
|
||||
preceded by a# preprocessing token,
|
||||
both are replaced by a single character string literal preprocessing token that
|
||||
contains the spelling of the preprocessing token sequence for the
|
||||
corresponding argument (excluding placemarker tokens)[.](#cpp.stringize-2.sentence-2)
|
||||
|
||||
Let the [*stringizing argument*](#def:stringizing_argument "15.7.3 The # operator [cpp.stringize]") be the preprocessing token sequence
|
||||
for the corresponding argument with placemarker tokens removed[.](#cpp.stringize-2.sentence-3)
|
||||
|
||||
Each occurrence of whitespace between the stringizing argument's preprocessing
|
||||
tokens becomes a single space character in the character string literal[.](#cpp.stringize-2.sentence-4)
|
||||
|
||||
Whitespace before the first preprocessing token and after the last
|
||||
preprocessing token comprising the stringizing argument is deleted[.](#cpp.stringize-2.sentence-5)
|
||||
|
||||
Otherwise, the original spelling of each preprocessing token in the
|
||||
stringizing argument is retained in the character string literal,
|
||||
except for special handling for producing the spelling of[*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]")*s*,[*character-literal*](lex.ccon#nt:character-literal "5.13.3 Character literals [lex.ccon]")*s*,
|
||||
and [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]")*s* (including the delimiting U+0022 quotation mark ("))
|
||||
contained within the preprocessing token:
|
||||
a U+005c reverse solidus character (\)
|
||||
is inserted before each U+0022 quotation mark andU+005c reverse solidus character of a[*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]"),[*character-literal*](lex.ccon#nt:character-literal "5.13.3 Character literals [lex.ccon]"),
|
||||
or [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]"),
|
||||
and each new-line character is
|
||||
replaced by the two-character sequence \n[.](#cpp.stringize-2.sentence-6)
|
||||
|
||||
If the replacement that results is not a valid character string literal,
|
||||
the program is ill-formed[.](#cpp.stringize-2.sentence-7)
|
||||
|
||||
The character string literal corresponding to
|
||||
an empty stringizing argument is ""[.](#cpp.stringize-2.sentence-8)
|
||||
|
||||
The order of evaluation of# and## operators is unspecified[.](#cpp.stringize-2.sentence-9)
|
||||
|
||||
### [15.7.4](#cpp.concat) The ## operator [[cpp.concat]](cpp.concat)
|
||||
|
||||
[1](#cpp.concat-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1847)
|
||||
|
||||
A## preprocessing token shall not occur at the beginning or
|
||||
at the end of a replacement list for either form
|
||||
of macro definition[.](#cpp.concat-1.sentence-1)
|
||||
|
||||
[2](#cpp.concat-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1854)
|
||||
|
||||
If, in the replacement list of a function-like macro, a parameter is
|
||||
immediately preceded or followed by a## preprocessing token, the parameter is replaced by the
|
||||
corresponding argument's preprocessing token sequence; however, if an argument consists of no preprocessing tokens, the parameter is
|
||||
replaced by a placemarker preprocessing token instead[.](#cpp.concat-2.sentence-1)[128](#footnote-128 "Placemarker preprocessing tokens do not appear in the syntax because they are temporary entities that exist only within translation phase 4.")
|
||||
|
||||
[3](#cpp.concat-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1866)
|
||||
|
||||
For both object-like and function-like macro invocations, before the
|
||||
replacement list is reexamined for more macro names to replace,
|
||||
each instance of a## preprocessing token in the replacement list
|
||||
(not from an argument) is deleted and the
|
||||
preceding preprocessing token is concatenated
|
||||
with the following preprocessing token[.](#cpp.concat-3.sentence-1)
|
||||
|
||||
Placemarker preprocessing tokens are handled specially: concatenation
|
||||
of two placemarkers results in a single placemarker preprocessing token, and
|
||||
concatenation of a placemarker with a non-placemarker preprocessing token results
|
||||
in the non-placemarker preprocessing token[.](#cpp.concat-3.sentence-2)
|
||||
|
||||
[*Note [1](#cpp.concat-note-1)*:
|
||||
|
||||
Concatenation can form
|
||||
a [*universal-character-name*](lex.universal.char#nt:universal-character-name "5.3.2 Universal character names [lex.universal.char]") ([[lex.charset]](lex.charset "5.3.1 Character sets"))[.](#cpp.concat-3.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
If the result is not a valid preprocessing token,
|
||||
the program is ill-formed[.](#cpp.concat-3.sentence-4)
|
||||
|
||||
The resulting preprocessing token is available for further macro replacement[.](#cpp.concat-3.sentence-5)
|
||||
|
||||
The order of evaluation of## operators is unspecified[.](#cpp.concat-3.sentence-6)
|
||||
|
||||
[4](#cpp.concat-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1890)
|
||||
|
||||
[*Example [1](#cpp.concat-example-1)*:
|
||||
|
||||
The sequence#define str(s) # s#define xstr(s) str(s)#define debug(s, t) printf("x" # s "= %d, x" # t "= %s", \
|
||||
x ## s, x ## t)#define INCFILE(n) vers ## n#define glue(a, b) a ## b#define xglue(a, b) glue(a, b)#define HIGHLOW "hello"#define LOW LOW ", world" debug(1, 2);
|
||||
fputs(str(strncmp("abc\0d", "abc", '\4') // this goes away== 0) str(: @\n), s);#include xstr(INCFILE(2).h) glue(HIGH, LOW);
|
||||
xglue(HIGH, LOW) results inprintf("x" "1" "= %d, x" "2" "= %s", x1, x2);
|
||||
fputs("strncmp(\"abc\\0d\", \"abc\", '\\4') == 0" ": @\n", s);#include "vers2.h" (*after macro replacement, before file access*)"hello";"hello" ", world" or, after concatenation of the character string literals,printf("x1= %d, x2= %s", x1, x2);
|
||||
fputs("strncmp(\"abc\\0d\", \"abc\", '\\4') == 0: @\n", s);#include "vers2.h" (*after macro replacement, before file access*)"hello";"hello, world"
|
||||
|
||||
Space around the # and ## preprocessing tokens in the macro definition
|
||||
is optional[.](#cpp.concat-4.sentence-2)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[5](#cpp.concat-5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1932)
|
||||
|
||||
[*Example [2](#cpp.concat-example-2)*:
|
||||
|
||||
In the following fragment:#define hash_hash # ## ##define mkstr(a) # a#define in_between(a) mkstr(a)#define join(c, d) in_between(c hash_hash d)char p[] = join(x, y); // equivalent to char p[] = "x ## y";
|
||||
|
||||
The expansion produces, at various stages:join(x, y) in_between(x hash_hash y) in_between(x ## y) mkstr(x ## y)"x ## y"
|
||||
|
||||
In other words, expanding hash_hash produces a new preprocessing token,
|
||||
consisting of two adjacent sharp signs, but this new preprocessing token is not the## operator[.](#cpp.concat-5.sentence-3)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[6](#cpp.concat-6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1957)
|
||||
|
||||
[*Example [3](#cpp.concat-example-3)*:
|
||||
|
||||
To illustrate the rules for placemarker preprocessing tokens, the sequence#define t(x,y,z) x ## y ## zint j[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,),
|
||||
t(10,,), t(,11,), t(,,12), t(,,) }; results inint j[] = { 123, 45, 67, 89, 10, 11, 12, };
|
||||
|
||||
â *end example*]
|
||||
|
||||
[128)](#footnote-128)[128)](#footnoteref-128)
|
||||
|
||||
Placemarker preprocessing tokens do not appear in the syntax
|
||||
because they are temporary entities that exist only within translation phase 4[.](#footnote-128.sentence-1)
|
||||
|
||||
### [15.7.5](#cpp.rescan) Rescanning and further replacement [[cpp.rescan]](cpp.rescan)
|
||||
|
||||
[1](#cpp.rescan-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1976)
|
||||
|
||||
After all parameters in the replacement list have been substituted and # and ## processing has taken
|
||||
place, all placemarker preprocessing tokens are removed[.](#cpp.rescan-1.sentence-1)
|
||||
|
||||
Then
|
||||
the resulting preprocessing token sequence is rescanned, along with all
|
||||
subsequent preprocessing tokens of the source file, for more macro names
|
||||
to replace[.](#cpp.rescan-1.sentence-2)
|
||||
|
||||
[2](#cpp.rescan-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1983)
|
||||
|
||||
[*Example [1](#cpp.rescan-example-1)*:
|
||||
|
||||
The sequence#define x 3#define f(a) f(x * (a))#undef x#define x 2#define g f#define z z[0]#define h g(~#define m(a) a(w)#define w 0,1#define t(a) a#define p() int#define q(x) x#define r(x,y) x ## y#define str(x) # x
|
||||
|
||||
f(y+1) + f(f(z)) % t(t(g)(0) + t)(1);
|
||||
g(x+(3,4)-w) | h 5) & m (f)^m(m);
|
||||
p() i[q()] = { q(1), r(2,3), r(4,), r(,5), r(,) };char c[2][6] = { str(hello), str() }; results inf(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1);
|
||||
f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1);int i[] = { 1, 23, 4, 5, };char c[2][6] = { "hello", "" };
|
||||
|
||||
â *end example*]
|
||||
|
||||
[3](#cpp.rescan-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L2017)
|
||||
|
||||
If the name of the macro being replaced is found during this scan of
|
||||
the replacement list
|
||||
(not including the rest of the source file's preprocessing tokens),
|
||||
it is not replaced[.](#cpp.rescan-3.sentence-1)
|
||||
|
||||
Furthermore,
|
||||
if any nested replacements encounter the name of the macro being replaced,
|
||||
it is not replaced[.](#cpp.rescan-3.sentence-2)
|
||||
|
||||
These nonreplaced macro name preprocessing tokens are no longer available
|
||||
for further replacement even if they are later (re)examined in contexts
|
||||
in which that macro name preprocessing token would otherwise have been
|
||||
replaced[.](#cpp.rescan-3.sentence-3)
|
||||
|
||||
[4](#cpp.rescan-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L2030)
|
||||
|
||||
The resulting completely macro-replaced preprocessing token sequence
|
||||
is not processed as a preprocessing directive even if it resembles one,
|
||||
but all pragma unary operator expressions within it are then processed as
|
||||
specified in [[cpp.pragma.op]](cpp.pragma.op "15.13 Pragma operator") below[.](#cpp.rescan-4.sentence-1)
|
||||
|
||||
### [15.7.6](#cpp.scope) Scope of macro definitions [[cpp.scope]](cpp.scope)
|
||||
|
||||
[1](#cpp.scope-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L2040)
|
||||
|
||||
A macro definition lasts
|
||||
(independent of block structure)
|
||||
until a corresponding#undef directive is encountered or
|
||||
(if none is encountered)
|
||||
until the end of the translation unit[.](#cpp.scope-1.sentence-1)
|
||||
|
||||
Macro definitions have no significance after translation phase 4[.](#cpp.scope-1.sentence-2)
|
||||
|
||||
[2](#cpp.scope-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L2050)
|
||||
|
||||
A preprocessing directive of the form
|
||||
|
||||
# undef [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
|
||||
causes the specified identifier no longer to be defined as a macro name[.](#cpp.scope-2.sentence-1)
|
||||
|
||||
It is ignored if the specified identifier is not currently defined as
|
||||
a macro name[.](#cpp.scope-2.sentence-2)
|
||||
240
cppdraft/cpp/replace/general.md
Normal file
240
cppdraft/cpp/replace/general.md
Normal file
@@ -0,0 +1,240 @@
|
||||
[cpp.replace.general]
|
||||
|
||||
# 15 Preprocessing directives [[cpp]](./#cpp)
|
||||
|
||||
## 15.7 Macro replacement [[cpp.replace]](cpp.replace#general)
|
||||
|
||||
### 15.7.1 General [cpp.replace.general]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1443)
|
||||
|
||||
Two replacement lists are identical if and only if
|
||||
the preprocessing tokens in both have
|
||||
the same number, ordering, spelling, and whitespace separation,
|
||||
where all whitespace separations are considered identical[.](#1.sentence-1)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1450)
|
||||
|
||||
An identifier currently defined as anobject-like macro (see below) may be redefined by another#define preprocessing directive provided that the second definition is an
|
||||
object-like macro definition and the two replacement lists
|
||||
are identical, otherwise the program is ill-formed[.](#2.sentence-1)
|
||||
|
||||
Likewise, an identifier currently defined as afunction-like macro (see below) may be redefined by another#define preprocessing directive provided that the second definition is a
|
||||
function-like macro definition that has the same number and spelling
|
||||
of parameters,
|
||||
and the two replacement lists are identical,
|
||||
otherwise the program is ill-formed[.](#2.sentence-2)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1468)
|
||||
|
||||
[*Example [1](#example-1)*:
|
||||
|
||||
The following sequence is valid:#define OBJ_LIKE (1-1)#define OBJ_LIKE /* whitespace */ (1-1) /* other */#define FUNC_LIKE(a) ( a )#define FUNC_LIKE( a )( /* note the whitespace */ \
|
||||
a /* other stuff on this line
|
||||
*/ )
|
||||
|
||||
But the following redefinitions are invalid:#define OBJ_LIKE (0) // different token sequence#define OBJ_LIKE (1 - 1) // different whitespace#define FUNC_LIKE(b) ( a ) // different parameter usage#define FUNC_LIKE(b) ( b ) // different parameter spelling
|
||||
|
||||
â *end example*]
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1488)
|
||||
|
||||
There shall be whitespace between the identifier and the replacement list
|
||||
in the definition of an object-like macro[.](#4.sentence-1)
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1493)
|
||||
|
||||
If the [*identifier-list*](cpp.pre#nt:identifier-list "15.1 Preamble [cpp.pre]") in the macro definition does not end with
|
||||
an ellipsis, the number of arguments (including those arguments consisting
|
||||
of no preprocessing tokens)
|
||||
in an invocation of a function-like macro shall
|
||||
equal the number of parameters in the macro definition[.](#5.sentence-1)
|
||||
|
||||
Otherwise, there shall be at least as many arguments in the invocation as there are
|
||||
parameters in the macro definition (excluding the ...)[.](#5.sentence-2)
|
||||
|
||||
There
|
||||
shall exist a) preprocessing token that terminates the invocation[.](#5.sentence-3)
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1505)
|
||||
|
||||
The identifiers __VA_ARGS__ and __VA_OPT__ shall occur only in the [*replacement-list*](cpp.pre#nt:replacement-list "15.1 Preamble [cpp.pre]") of a function-like macro that uses the ellipsis notation in the parameters[.](#6.sentence-1)
|
||||
|
||||
[7](#7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1512)
|
||||
|
||||
A parameter identifier in a function-like macro
|
||||
shall be uniquely declared within its scope[.](#7.sentence-1)
|
||||
|
||||
[8](#8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1516)
|
||||
|
||||
The identifier immediately following thedefine is called the[*macro name*](#def:macro,name "15.7.1 General [cpp.replace.general]")[.](#8.sentence-1)
|
||||
|
||||
There is one name space for macro names[.](#8.sentence-2)
|
||||
|
||||
Any whitespace characters preceding or following the
|
||||
replacement list of preprocessing tokens are not considered
|
||||
part of the replacement list for either form of macro[.](#8.sentence-3)
|
||||
|
||||
[9](#9)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1527)
|
||||
|
||||
A translation unit shall not #define or #undef names lexically identical
|
||||
to keywords,
|
||||
to the identifiers listed in Table [4](lex.name#tab:lex.name.special "Table 4: Identifiers with special meaning"), or
|
||||
to the [*attribute-token*](dcl.attr.grammar#nt:attribute-token "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")*s* described in [[dcl.attr]](dcl.attr "9.13 Attributes"),
|
||||
except that the names likely and unlikely may be
|
||||
defined as function-like macros[.](#9.sentence-1)
|
||||
|
||||
[10](#10)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1537)
|
||||
|
||||
If a# preprocessing token,
|
||||
followed by an identifier,
|
||||
occurs lexically
|
||||
at the point at which a preprocessing directive can begin,
|
||||
the identifier is not subject to macro replacement[.](#10.sentence-1)
|
||||
|
||||
[11](#11)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1547)
|
||||
|
||||
A preprocessing directive of the form
|
||||
|
||||
# define [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [*replacement-list*](cpp.pre#nt:replacement-list "15.1 Preamble [cpp.pre]") [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
|
||||
defines an[*object-like macro*](#def:macro,object-like "15.7.1 General [cpp.replace.general]") that
|
||||
causes each subsequent instance of the macro name[125](#footnote-125 "Since, by macro-replacement time, all character-literals and string-literals are preprocessing tokens, not sequences possibly containing identifier-like subsequences (see [lex.phases], translation phases), they are never scanned for macro names or parameters.") to be replaced by the replacement list of preprocessing tokens
|
||||
that constitute the remainder of the directive[.](#11.sentence-1)[126](#footnote-126 "An alternative token ([lex.digraph]) is not an identifier, even when its spelling consists entirely of letters and underscores. Therefore it is not possible to define a macro whose name is the same as that of an alternative token.")
|
||||
|
||||
The replacement list is then rescanned for more macro names as
|
||||
specified below[.](#11.sentence-2)
|
||||
|
||||
[12](#12)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1574)
|
||||
|
||||
[*Example [2](#example-2)*:
|
||||
|
||||
The simplest use of this facility is to define a âmanifest constantâ,
|
||||
as in#define TABSIZE 100int table[TABSIZE];
|
||||
|
||||
â *end example*]
|
||||
|
||||
[13](#13)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1584)
|
||||
|
||||
A preprocessing directive of the form
|
||||
|
||||
# define [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [*lparen*](cpp.pre#nt:lparen "15.1 Preamble [cpp.pre]") [*identifier-list*](cpp.pre#nt:identifier-list "15.1 Preamble [cpp.pre]")opt ) [*replacement-list*](cpp.pre#nt:replacement-list "15.1 Preamble [cpp.pre]") [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
# define [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [*lparen*](cpp.pre#nt:lparen "15.1 Preamble [cpp.pre]") ... ) [*replacement-list*](cpp.pre#nt:replacement-list "15.1 Preamble [cpp.pre]") [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
# define [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [*lparen*](cpp.pre#nt:lparen "15.1 Preamble [cpp.pre]") [*identifier-list*](cpp.pre#nt:identifier-list "15.1 Preamble [cpp.pre]") , ... ) [*replacement-list*](cpp.pre#nt:replacement-list "15.1 Preamble [cpp.pre]") [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
|
||||
defines a [*function-like macro*](#def:macro,function-like "15.7.1 General [cpp.replace.general]") with parameters, whose use is
|
||||
similar syntactically to a function call[.](#13.sentence-1)
|
||||
|
||||
The parametersare specified by the optional list of identifiers[.](#13.sentence-2)
|
||||
|
||||
Each subsequent instance of the function-like macro name followed by a( as the next preprocessing token
|
||||
introduces the sequence of preprocessing tokens that is replaced
|
||||
by the replacement list in the definition
|
||||
(an invocation of the macro)[.](#13.sentence-3)
|
||||
|
||||
The replaced sequence of preprocessing tokens is terminated by the matching) preprocessing token, skipping intervening matched pairs of left and
|
||||
right parenthesis preprocessing tokens[.](#13.sentence-4)
|
||||
|
||||
Within the sequence of preprocessing tokens making up an invocation
|
||||
of a function-like macro,
|
||||
new-line is considered a normal whitespace character[.](#13.sentence-5)
|
||||
|
||||
[14](#14)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1612)
|
||||
|
||||
The sequence of preprocessing tokens
|
||||
bounded by the outside-most matching parentheses
|
||||
forms the list of arguments for the function-like macro[.](#14.sentence-1)
|
||||
|
||||
The individual arguments within the list
|
||||
are separated by comma preprocessing tokens,
|
||||
but comma preprocessing tokens between matching
|
||||
inner parentheses do not separate arguments[.](#14.sentence-2)
|
||||
|
||||
If there are sequences of preprocessing tokens within the list of
|
||||
arguments that would otherwise act as preprocessing directives,[127](#footnote-127 "A conditionally-supported-directive is a preprocessing directive regardless of whether the implementation supports it.") the program is ill-formed[.](#14.sentence-3)
|
||||
|
||||
[15](#15)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1628)
|
||||
|
||||
[*Example [3](#example-3)*:
|
||||
|
||||
The following defines a function-like
|
||||
macro whose value is the maximum of its arguments[.](#15.sentence-1)
|
||||
|
||||
It has the disadvantages of evaluating one or the other of its arguments
|
||||
a second time
|
||||
(includingside effects)
|
||||
and generating more code than a function if invoked several times[.](#15.sentence-2)
|
||||
|
||||
It also cannot have its address taken,
|
||||
as it has none[.](#15.sentence-3)
|
||||
|
||||
#define max(a, b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
The parentheses ensure that the arguments and
|
||||
the resulting expression are bound properly[.](#15.sentence-4)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[16](#16)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1649)
|
||||
|
||||
If there is a ... immediately preceding the ) in the
|
||||
function-like macro
|
||||
definition, then the trailing arguments (if any), including any separating comma preprocessing
|
||||
tokens, are merged to form a single item: the [*variable arguments*](#def:variable_arguments "15.7.1 General [cpp.replace.general]")[.](#16.sentence-1)
|
||||
|
||||
The number of
|
||||
arguments so combined is such that, following merger, the number of arguments is
|
||||
either equal to or
|
||||
one more than the number of parameters in the macro definition (excluding the...)[.](#16.sentence-2)
|
||||
|
||||
[125)](#footnote-125)[125)](#footnoteref-125)
|
||||
|
||||
Since, by macro-replacement time,
|
||||
all [*character-literal*](lex.ccon#nt:character-literal "5.13.3 Character literals [lex.ccon]")*s* and [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]")*s* are preprocessing tokens,
|
||||
not sequences possibly containing identifier-like subsequences
|
||||
(see [[lex.phases]](lex.phases "5.2 Phases of translation"), translation phases),
|
||||
they are never scanned for macro names or parameters[.](#footnote-125.sentence-1)
|
||||
|
||||
[126)](#footnote-126)[126)](#footnoteref-126)
|
||||
|
||||
An alternative token ([[lex.digraph]](lex.digraph "5.9 Alternative tokens")) is not an identifier,
|
||||
even when its spelling consists entirely of letters and underscores[.](#footnote-126.sentence-1)
|
||||
|
||||
Therefore it is not possible to define a macro
|
||||
whose name is the same as that of an alternative token[.](#footnote-126.sentence-2)
|
||||
|
||||
[127)](#footnote-127)[127)](#footnoteref-127)
|
||||
|
||||
A [*conditionally-supported-directive*](cpp.pre#nt:conditionally-supported-directive "15.1 Preamble [cpp.pre]") is a preprocessing directive regardless of whether the implementation supports it[.](#footnote-127.sentence-1)
|
||||
61
cppdraft/cpp/rescan.md
Normal file
61
cppdraft/cpp/rescan.md
Normal file
@@ -0,0 +1,61 @@
|
||||
[cpp.rescan]
|
||||
|
||||
# 15 Preprocessing directives [[cpp]](./#cpp)
|
||||
|
||||
## 15.7 Macro replacement [[cpp.replace]](cpp.replace#cpp.rescan)
|
||||
|
||||
### 15.7.5 Rescanning and further replacement [cpp.rescan]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1976)
|
||||
|
||||
After all parameters in the replacement list have been substituted and # and ## processing has taken
|
||||
place, all placemarker preprocessing tokens are removed[.](#1.sentence-1)
|
||||
|
||||
Then
|
||||
the resulting preprocessing token sequence is rescanned, along with all
|
||||
subsequent preprocessing tokens of the source file, for more macro names
|
||||
to replace[.](#1.sentence-2)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1983)
|
||||
|
||||
[*Example [1](#example-1)*:
|
||||
|
||||
The sequence#define x 3#define f(a) f(x * (a))#undef x#define x 2#define g f#define z z[0]#define h g(~#define m(a) a(w)#define w 0,1#define t(a) a#define p() int#define q(x) x#define r(x,y) x ## y#define str(x) # x
|
||||
|
||||
f(y+1) + f(f(z)) % t(t(g)(0) + t)(1);
|
||||
g(x+(3,4)-w) | h 5) & m (f)^m(m);
|
||||
p() i[q()] = { q(1), r(2,3), r(4,), r(,5), r(,) };char c[2][6] = { str(hello), str() }; results inf(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1);
|
||||
f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1);int i[] = { 1, 23, 4, 5, };char c[2][6] = { "hello", "" };
|
||||
|
||||
â *end example*]
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L2017)
|
||||
|
||||
If the name of the macro being replaced is found during this scan of
|
||||
the replacement list
|
||||
(not including the rest of the source file's preprocessing tokens),
|
||||
it is not replaced[.](#3.sentence-1)
|
||||
|
||||
Furthermore,
|
||||
if any nested replacements encounter the name of the macro being replaced,
|
||||
it is not replaced[.](#3.sentence-2)
|
||||
|
||||
These nonreplaced macro name preprocessing tokens are no longer available
|
||||
for further replacement even if they are later (re)examined in contexts
|
||||
in which that macro name preprocessing token would otherwise have been
|
||||
replaced[.](#3.sentence-3)
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L2030)
|
||||
|
||||
The resulting completely macro-replaced preprocessing token sequence
|
||||
is not processed as a preprocessing directive even if it resembles one,
|
||||
but all pragma unary operator expressions within it are then processed as
|
||||
specified in [[cpp.pragma.op]](cpp.pragma.op "15.13 Pragma operator") below[.](#4.sentence-1)
|
||||
32
cppdraft/cpp/scope.md
Normal file
32
cppdraft/cpp/scope.md
Normal file
@@ -0,0 +1,32 @@
|
||||
[cpp.scope]
|
||||
|
||||
# 15 Preprocessing directives [[cpp]](./#cpp)
|
||||
|
||||
## 15.7 Macro replacement [[cpp.replace]](cpp.replace#cpp.scope)
|
||||
|
||||
### 15.7.6 Scope of macro definitions [cpp.scope]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L2040)
|
||||
|
||||
A macro definition lasts
|
||||
(independent of block structure)
|
||||
until a corresponding#undef directive is encountered or
|
||||
(if none is encountered)
|
||||
until the end of the translation unit[.](#1.sentence-1)
|
||||
|
||||
Macro definitions have no significance after translation phase 4[.](#1.sentence-2)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L2050)
|
||||
|
||||
A preprocessing directive of the form
|
||||
|
||||
# undef [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") [*new-line*](cpp.pre#nt:new-line "15.1 Preamble [cpp.pre]")
|
||||
|
||||
causes the specified identifier no longer to be defined as a macro name[.](#2.sentence-1)
|
||||
|
||||
It is ignored if the specified identifier is not currently defined as
|
||||
a macro name[.](#2.sentence-2)
|
||||
55
cppdraft/cpp/stringize.md
Normal file
55
cppdraft/cpp/stringize.md
Normal file
@@ -0,0 +1,55 @@
|
||||
[cpp.stringize]
|
||||
|
||||
# 15 Preprocessing directives [[cpp]](./#cpp)
|
||||
|
||||
## 15.7 Macro replacement [[cpp.replace]](cpp.replace#cpp.stringize)
|
||||
|
||||
### 15.7.3 The # operator [cpp.stringize]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1795)
|
||||
|
||||
Each# preprocessing token in the replacement list for a function-like
|
||||
macro shall be followed by a parameter as the next preprocessing
|
||||
token in the replacement list[.](#1.sentence-1)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1802)
|
||||
|
||||
A [*character string literal*](#def:character_string_literal "15.7.3 The # operator [cpp.stringize]") is a [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]") with no prefix[.](#2.sentence-1)
|
||||
|
||||
If, in the replacement list, a parameter is immediately
|
||||
preceded by a# preprocessing token,
|
||||
both are replaced by a single character string literal preprocessing token that
|
||||
contains the spelling of the preprocessing token sequence for the
|
||||
corresponding argument (excluding placemarker tokens)[.](#2.sentence-2)
|
||||
|
||||
Let the [*stringizing argument*](#def:stringizing_argument "15.7.3 The # operator [cpp.stringize]") be the preprocessing token sequence
|
||||
for the corresponding argument with placemarker tokens removed[.](#2.sentence-3)
|
||||
|
||||
Each occurrence of whitespace between the stringizing argument's preprocessing
|
||||
tokens becomes a single space character in the character string literal[.](#2.sentence-4)
|
||||
|
||||
Whitespace before the first preprocessing token and after the last
|
||||
preprocessing token comprising the stringizing argument is deleted[.](#2.sentence-5)
|
||||
|
||||
Otherwise, the original spelling of each preprocessing token in the
|
||||
stringizing argument is retained in the character string literal,
|
||||
except for special handling for producing the spelling of[*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]")*s*,[*character-literal*](lex.ccon#nt:character-literal "5.13.3 Character literals [lex.ccon]")*s*,
|
||||
and [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]")*s* (including the delimiting U+0022 quotation mark ("))
|
||||
contained within the preprocessing token:
|
||||
a U+005c reverse solidus character (\)
|
||||
is inserted before each U+0022 quotation mark andU+005c reverse solidus character of a[*header-name*](lex.header#nt:header-name "5.6 Header names [lex.header]"),[*character-literal*](lex.ccon#nt:character-literal "5.13.3 Character literals [lex.ccon]"),
|
||||
or [*string-literal*](lex.string#nt:string-literal "5.13.5 String literals [lex.string]"),
|
||||
and each new-line character is
|
||||
replaced by the two-character sequence \n[.](#2.sentence-6)
|
||||
|
||||
If the replacement that results is not a valid character string literal,
|
||||
the program is ill-formed[.](#2.sentence-7)
|
||||
|
||||
The character string literal corresponding to
|
||||
an empty stringizing argument is ""[.](#2.sentence-8)
|
||||
|
||||
The order of evaluation of# and## operators is unspecified[.](#2.sentence-9)
|
||||
105
cppdraft/cpp/subst.md
Normal file
105
cppdraft/cpp/subst.md
Normal file
@@ -0,0 +1,105 @@
|
||||
[cpp.subst]
|
||||
|
||||
# 15 Preprocessing directives [[cpp]](./#cpp)
|
||||
|
||||
## 15.7 Macro replacement [[cpp.replace]](cpp.replace#cpp.subst)
|
||||
|
||||
### 15.7.2 Argument substitution [cpp.subst]
|
||||
|
||||
[va-opt-replacement:](#nt:va-opt-replacement "15.7.2 Argument substitution [cpp.subst]")
|
||||
__VA_OPT__ ( [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]")opt )
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1670)
|
||||
|
||||
After the arguments for the invocation of a function-like macro have
|
||||
been identified, argument substitution takes place[.](#1.sentence-1)
|
||||
|
||||
For each parameter in the replacement list that is neither
|
||||
preceded by a # or ## preprocessing token nor
|
||||
followed by a ## preprocessing token, the preprocessing tokens
|
||||
naming the parameter are replaced by a preprocessing token sequence determined as follows:
|
||||
|
||||
- [(1.1)](#1.1)
|
||||
|
||||
If the parameter is of the form [*va-opt-replacement*](#nt:va-opt-replacement "15.7.2 Argument substitution [cpp.subst]"),
|
||||
the replacement preprocessing tokens are the
|
||||
preprocessing token sequence for the corresponding argument,
|
||||
as specified below[.](#1.1.sentence-1)
|
||||
|
||||
- [(1.2)](#1.2)
|
||||
|
||||
Otherwise, the replacement preprocessing tokens are the
|
||||
preprocessing tokens of corresponding argument after all
|
||||
macros contained therein have been expanded[.](#1.2.sentence-1)
|
||||
The argument's
|
||||
preprocessing tokens are completely macro replaced before
|
||||
being substituted as if they formed the rest of the preprocessing
|
||||
translation unit with no other preprocessing tokens being available[.](#1.2.sentence-2)
|
||||
|
||||
[*Example [1](#example-1)*: #define LPAREN() (#define G(Q) 42#define F(R, X, ...) __VA_OPT__(G R X) )int x = F(LPAREN(), 0, <:-); // replaced by int x = 42; â *end example*]
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1700)
|
||||
|
||||
An identifier __VA_ARGS__ that occurs in the replacement list
|
||||
shall be treated as if it were a parameter, and the variable arguments shall form
|
||||
the preprocessing tokens used to replace it[.](#2.sentence-1)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1706)
|
||||
|
||||
[*Example [2](#example-2)*:
|
||||
|
||||
#define debug(...) fprintf(stderr, __VA_ARGS__)#define showlist(...) puts(#__VA_ARGS__)#define report(test, ...) ((test) ? puts(#test) : printf(__VA_ARGS__)) debug("Flag");
|
||||
debug("X = %d\n", x);
|
||||
showlist(The first, second, and third items.);
|
||||
report(x>y, "x is %d but y is %d", x, y); results infprintf(stderr, "Flag");
|
||||
fprintf(stderr, "X = %d\n", x);
|
||||
puts("The first, second, and third items.");((x>y) ? puts("x>y") : printf("x is %d but y is %d", x, y));
|
||||
|
||||
â *end example*]
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1726)
|
||||
|
||||
The identifier __VA_OPT__ shall always occur as part of the preprocessing token sequence[*va-opt-replacement*](#nt:va-opt-replacement "15.7.2 Argument substitution [cpp.subst]");
|
||||
its closing ) is determined by skipping
|
||||
intervening pairs of matching left and right parentheses
|
||||
in its [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]")[.](#4.sentence-1)
|
||||
|
||||
The [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]") of a [*va-opt-replacement*](#nt:va-opt-replacement "15.7.2 Argument substitution [cpp.subst]") shall not contain __VA_OPT__[.](#4.sentence-2)
|
||||
|
||||
If the [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]") would be ill-formed
|
||||
as the replacement list of the current function-like macro,
|
||||
the program is ill-formed[.](#4.sentence-3)
|
||||
|
||||
A [*va-opt-replacement*](#nt:va-opt-replacement "15.7.2 Argument substitution [cpp.subst]") is treated as if it were a parameter,
|
||||
and the preprocessing token sequence for the corresponding
|
||||
argument is defined as follows[.](#4.sentence-4)
|
||||
|
||||
If the substitution of __VA_ARGS__ as neither an operand
|
||||
of # nor ## consists of no preprocessing tokens,
|
||||
the argument consists of
|
||||
a single placemarker preprocessing token ([[cpp.concat]](cpp.concat "15.7.4 The ## operator"), [[cpp.rescan]](cpp.rescan "15.7.5 Rescanning and further replacement"))[.](#4.sentence-5)
|
||||
|
||||
Otherwise, the argument consists of
|
||||
the results of the expansion of the contained [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]") as the replacement list of the current function-like macro
|
||||
before removal of placemarker tokens, rescanning, and further replacement[.](#4.sentence-6)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
The placemarker tokens are removed before stringization ([[cpp.stringize]](cpp.stringize "15.7.3 The # operator")),
|
||||
and can be removed by rescanning and further replacement ([[cpp.rescan]](cpp.rescan "15.7.5 Rescanning and further replacement"))[.](#4.sentence-7)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [3](#example-3)*: #define F(...) f(0 __VA_OPT__(,) __VA_ARGS__)#define G(X, ...) f(0, X __VA_OPT__(,) __VA_ARGS__)#define SDEF(sname, ...) S sname __VA_OPT__(= { __VA_ARGS__ })#define EMP
|
||||
|
||||
F(a, b, c) // replaced by f(0, a, b, c) F() // replaced by f(0) F(EMP) // replaced by f(0) G(a, b, c) // replaced by f(0, a, b, c) G(a, ) // replaced by f(0, a) G(a) // replaced by f(0, a) SDEF(foo); // replaced by S foo; SDEF(bar, 1, 2); // replaced by S bar = { 1, 2 };#define H1(X, ...) X __VA_OPT__(##) __VA_ARGS__ // error: ## may not appear at// the beginning of a replacement list ([[cpp.concat]](cpp.concat "15.7.4 The ## operator"))#define H2(X, Y, ...) __VA_OPT__(X ## Y,) __VA_ARGS__
|
||||
H2(a, b, c, d) // replaced by ab, c, d#define H3(X, ...) #__VA_OPT__(X##X X##X) H3(, 0) // replaced by ""#define H4(X, ...) __VA_OPT__(a X ## X) ## b
|
||||
H4(, 1) // replaced by a b#define H5A(...) __VA_OPT__()/**/__VA_OPT__()#define H5B(X) a ## X ## b#define H5C(X) H5B(X) H5C(H5A()) // replaced by ab â *end example*]
|
||||
Reference in New Issue
Block a user