-
Notifications
You must be signed in to change notification settings - Fork 767
/
Copy pathpreprocessor.tex
2469 lines (2206 loc) · 84.1 KB
/
preprocessor.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
%!TEX root = std.tex
\rSec0[cpp]{Preprocessing directives}%
\indextext{preprocessing directive|(}
\indextext{compiler control line|see{preprocessing directive}}%
\indextext{control line|see{preprocessing directive}}%
\indextext{directive, preprocessing|see{preprocessing directive}}
\gramSec[gram.cpp]{Preprocessing directives}
\rSec1[cpp.pre]{Preamble}
\begin{bnf}
\nontermdef{preprocessing-file}\br
\opt{group}\br
module-file
\end{bnf}
\begin{bnf}
\nontermdef{module-file}\br
\opt{pp-global-module-fragment} pp-module \opt{group} \opt{pp-private-module-fragment}
\end{bnf}
\begin{bnf}
\nontermdef{pp-global-module-fragment}\br
\keyword{module} \terminal{;} new-line \opt{group}
\end{bnf}
\begin{bnf}
\nontermdef{pp-private-module-fragment}\br
\keyword{module} \terminal{:} \keyword{private} \terminal{;} new-line \opt{group}
\end{bnf}
\begin{bnf}
\nontermdef{group}\br
group-part\br
group group-part
\end{bnf}
\begin{bnf}
\nontermdef{group-part}\br
control-line\br
if-section\br
text-line\br
\terminal{\#} conditionally-supported-directive
\end{bnf}
\begin{bnf}
\nontermdef{embed-parameter}\br
embed-standard-parameter\br
embed-prefixed-parameter
\end{bnf}
\begin{bnf}
\nontermdef{embed-parameter-seq}\br
embed-parameter \opt{embed-parameter-seq}
\end{bnf}
\begin{bnf}
\nontermdef{embed-standard-parameter}\br
\terminal{limit} \terminal{(} pp-balanced-token-seq \terminal{)}\br
\terminal{prefix} \terminal{(} \opt{pp-balanced-token-seq} \terminal{)}\br
\terminal{suffix} \terminal{(} \opt{pp-balanced-token-seq} \terminal{)}\br
\terminal{if_empty} \terminal{(} \opt{pp-balanced-token-seq} \terminal{)}
\end{bnf}
\begin{bnf}
\nontermdef{embed-prefixed-parameter}\br
identifier :: identifier\br
identifier :: identifier \terminal{(} \opt{pp-balanced-token-seq} )
\end{bnf}
\begin{bnf}\obeyspaces
\nontermdef{control-line}\br
\terminal{\# include} pp-tokens new-line\br
pp-import\br
\terminal{\# embed } pp-tokens new-line\br
\terminal{\# define } identifier replacement-list new-line\br
\terminal{\# define } identifier lparen \opt{identifier-list} \terminal{)} replacement-list new-line\br
\terminal{\# define } identifier lparen \terminal{... )} replacement-list new-line\br
\terminal{\# define } identifier lparen identifier-list \terminal{, ... )} replacement-list new-line\br
\terminal{\# undef } identifier new-line\br
\terminal{\# line } pp-tokens new-line\br
\terminal{\# error } \opt{pp-tokens} new-line\br
\terminal{\# warning} \opt{pp-tokens} new-line\br
\terminal{\# pragma } \opt{pp-tokens} new-line\br
\terminal{\# }new-line
\end{bnf}
\begin{bnf}
\nontermdef{if-section}\br
if-group \opt{elif-groups} \opt{else-group} endif-line
\end{bnf}
\begin{bnf}\obeyspaces
\nontermdef{if-group}\br
\terminal{\# if } constant-expression new-line \opt{group}\br
\terminal{\# ifdef } identifier new-line \opt{group}\br
\terminal{\# ifndef } identifier new-line \opt{group}
\end{bnf}
\begin{bnf}
\nontermdef{elif-groups}\br
elif-group \opt{elif-groups}
\end{bnf}
\begin{bnf}\obeyspaces
\nontermdef{elif-group}\br
\terminal{\# elif } constant-expression new-line \opt{group}\br
\terminal{\# elifdef } identifier new-line \opt{group}\br
\terminal{\# elifndef} identifier new-line \opt{group}
\end{bnf}
\begin{bnf}\obeyspaces
\nontermdef{else-group}\br
\terminal{\# else } new-line \opt{group}
\end{bnf}
\begin{bnf}\obeyspaces
\nontermdef{endif-line}\br
\terminal{\# endif } new-line
\end{bnf}
\begin{bnf}
\nontermdef{text-line}\br
\opt{pp-tokens} new-line
\end{bnf}
\begin{bnf}
\nontermdef{conditionally-supported-directive}\br
pp-tokens new-line
\end{bnf}
\begin{bnf}
\nontermdef{lparen}\br
\descr{a \terminal{(} character not immediately preceded by whitespace}
\end{bnf}
\begin{bnf}
\nontermdef{identifier-list}\br
identifier\br
identifier-list \terminal{,} identifier
\end{bnf}
\begin{bnf}
\nontermdef{replacement-list}\br
\opt{pp-tokens}
\end{bnf}
\begin{bnf}
\nontermdef{pp-tokens}\br
preprocessing-token \opt{pp-tokens}
\end{bnf}
\begin{bnf}
\nontermdef{pp-balanced-token-seq}\br
pp-balanced-token \opt{pp-balanced-token-seq}
\end{bnf}
\begin{bnf}
\nontermdef{pp-balanced-token}\br
\terminal{(} \opt{pp-balanced-token-seq} \terminal{)}\br
\terminal{[} \opt{pp-balanced-token-seq} \terminal{]}\br
\terminal{\{} \opt{pp-balanced-token-seq} \terminal{\}}\br
\textnormal{any} pp-token \textnormal{except:}\br
\bnfindent\textnormal{parenthesis (\unicode{0028}{left parenthesis} and \unicode{0029}{right parenthesis}),}\br
\bnfindent\textnormal{bracket (\unicode{005b}{left square bracket} and \unicode{005d}{right square bracket}), or}\br
\bnfindent\textnormal{brace (\unicode{007b}{left curly bracket} and \unicode{007d}{right curly bracket}).}
\end{bnf}
\begin{bnf}
\nontermdef{new-line}\br
\descr{the new-line character}
\end{bnf}
\pnum
A \defn{preprocessing directive} consists of a sequence of preprocessing tokens
that satisfies the following constraints:
At the start of translation phase 4,
the first preprocessing token in the sequence,
referred to as a \defnadj{directive-introducing}{token},
begins with the first character in the source file
(optionally after whitespace containing no new-line characters) or
follows whitespace containing at least one new-line character,
and is
\begin{itemize}
\item
a \tcode{\#} preprocessing token, or
\item
an \keyword{import} preprocessing token
immediately followed on the same logical source line by a
\grammarterm{header-name},
\tcode{<},
\grammarterm{identifier},
\grammarterm{string-literal}, or
\tcode{:}
preprocessing token, or
\item
a \keyword{module} preprocessing token
immediately followed on the same logical source line by an
\grammarterm{identifier},
\tcode{:}, or
\tcode{;}
preprocessing token, or
\item
an \keyword{export} preprocessing token
immediately followed on the same logical source line by
one of the two preceding forms.
\end{itemize}
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.
\begin{footnote}
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
\tcode{\#}
character string literal creation operator in~\ref{cpp.stringize}, for example).
\end{footnote}
\begin{note}
A new-line character ends the preprocessing directive even if it occurs
within what would otherwise be an invocation of a function-like macro.
\end{note}
\begin{example}
\begin{codeblock}
# // preprocessing directive
module ; // preprocessing directive
export module leftpad; // preprocessing directive
import <string>; // preprocessing directive
export import "squee"; // preprocessing directive
import rightpad; // preprocessing directive
import :part; // preprocessing directive
module // not a preprocessing directive
; // not a preprocessing directive
export // not a preprocessing directive
import // not a preprocessing directive
foo; // not a preprocessing directive
export // not a preprocessing directive
import foo; // preprocessing directive (ill-formed at phase 7)
import :: // not a preprocessing directive
import -> // not a preprocessing directive
\end{codeblock}
\end{example}
\pnum
A sequence of preprocessing tokens is only a \grammarterm{text-line}
if it does not begin with a directive-introducing token.
\begin{example}
\begin{codeblock}
using module = int;
module i; // not a \grammarterm{text-line} and not a \grammarterm{control-line}
int foo() {
return i;
}
\end{codeblock}
The example is not a valid \grammarterm{preprocessing-file}.
\end{example}
A sequence of preprocessing tokens is only a \grammarterm{conditionally-supported-directive}
if it does not begin with any of the directive names
appearing after a \tcode{\#} in the syntax.
A \grammarterm{conditionally-supported-directive} is
conditionally-supported with
\impldef{additional supported forms of preprocessing directive}
semantics.
\pnum
Any \grammarterm{embed-prefixed-parameter} is conditionally-supported, with
\impldef{supported forms of \#embed prefix parameters}
semantics.
\pnum
At the start of phase 4 of translation,
the \grammarterm{group} of a \grammarterm{pp-global-module-fragment} shall
contain neither a \grammarterm{text-line} nor a \grammarterm{pp-import}.
\pnum
When in a group that is skipped\iref{cpp.cond}, the directive
syntax is relaxed to allow any sequence of preprocessing tokens to occur between
the directive name and the following new-line character.
\pnum
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).
\pnum
The implementation can
process and skip sections of source files conditionally,
include other source files,
import macros from header units,
and replace macros.
These capabilities are called
\defn{preprocessing},
because conceptually they occur
before translation of the resulting translation unit.
\pnum
The preprocessing tokens within a preprocessing directive
are not subject to macro expansion unless otherwise stated.
\begin{example}
In:
\begin{codeblock}
#define EMPTY
EMPTY # include <file.h>
\end{codeblock}
the sequence of preprocessing tokens on the second line is \textit{not}
a preprocessing directive, because it does not begin with a \tcode{\#} at the start of
translation phase 4, even though it will do so after the macro \tcode{EMPTY}
has been replaced.
\end{example}
\rSec1[cpp.cond]{Conditional inclusion}%
\indextext{preprocessing directive!conditional inclusion}%
\indextext{inclusion!conditional|see{preprocessing directive, conditional inclusion}}
\indextext{\idxcode{defined}}%
\begin{bnf}
\nontermdef{defined-macro-expression}\br
\terminal{defined} identifier\br
\terminal{defined (} identifier \terminal{)}
\end{bnf}
\begin{bnf}
\nontermdef{h-preprocessing-token}\br
\textnormal{any \grammarterm{preprocessing-token} other than \terminal{>}}
\end{bnf}
\begin{bnf}
\nontermdef{h-pp-tokens}\br
h-preprocessing-token \opt{h-pp-tokens}
\end{bnf}
\begin{bnf}
\nontermdef{header-name-tokens}\br
string-literal\br
\terminal{<} h-pp-tokens \terminal{>}
\end{bnf}
\indextext{\idxxname{has_include}}%
\begin{bnf}
\nontermdef{has-include-expression}\br
\terminal{\xname{has_include}} \terminal{(} header-name \terminal{)}\br
\terminal{\xname{has_include}} \terminal{(} header-name-tokens \terminal{)}
\end{bnf}
\indextext{\idxxname{has_embed}}%
\begin{bnf}
\nontermdef{has-embed-expression}\br
\terminal{\xname{has_embed}} \terminal{(} pp-balanced-token-seq \terminal{)}
\end{bnf}
\indextext{\idxxname{has_cpp_attribute}}%
\begin{bnf}
\nontermdef{has-attribute-expression}\br
\terminal{\xname{has_cpp_attribute} (} pp-tokens \terminal{)}
\end{bnf}
\pnum
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
\begin{footnote}
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.
\end{footnote}
and it may contain zero or more \grammarterm{defined-macro-expression}{s},
\grammarterm{has-include-expression}{s},
\grammarterm{has-embed-expression}{s}, and/or
\grammarterm{has-attribute-expression}{s} as unary operator expressions.
\pnum
A \grammarterm{defined-macro-expression} evaluates to \tcode{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\iref{cpp.import},
for example because
it has been the subject of a
\tcode{\#define}
preprocessing directive
without an intervening
\tcode{\#undef}
directive with the same subject identifier), \tcode{0} if it is not.
\pnum
The second form of \grammarterm{has-include-expression}
is considered only if the first form does not match,
in which case the preprocessing tokens are processed just as in normal text.
\pnum
The header or source file identified by
the parenthesized preprocessing token sequence
in each contained \grammarterm{has-include-expression}
is searched for as if that preprocessing token sequence
were the \grammarterm{pp-tokens} in a \tcode{\#include} directive,
except that no further macro expansion is performed.
If such a directive would not satisfy the syntactic requirements
of a \tcode{\#include} directive, the program is ill-formed.
The \grammarterm{has-include-expression} evaluates
to \tcode{1} if the search for the source file succeeds, and
to \tcode{0} if the search fails.
\pnum
The parenthesized \grammarterm{pp-balanced-token-seq} in each contained
\grammarterm{has-embed-expression} is processed as if that
\grammarterm{pp-balanced-token-seq} were the \grammarterm{pp-tokens} in the
third form of a \tcode{\#embed} directive\iref{cpp.embed}.
If such a directive would not satisfy the syntactic requirements of a
\tcode{\#embed} directive, the program is ill-formed.
The \grammarterm{has-embed-expression} evaluates to:
\begin{itemize}
\item
\mname{STDC_EMBED_FOUND} if the search for the resource succeeds,
all the given \grammarterm{embed-parameter}s in the \grammarterm{embed-parameter-seq}
are supported, and the resource is not empty.
\item
Otherwise, \mname{STDC_EMBED_EMPTY} if the search for the resource succeeds,
all the given \grammarterm{embed-parameter}s in the \grammarterm{embed-parameter-seq}
are supported, and the resource is empty.
\item
Otherwise, \mname{STDC_EMBED_NOT_FOUND}.
\end{itemize}
\begin{note}
An unrecognized \grammarterm{embed-parameter} in an \grammarterm{has-embed-expression}
is not ill-formed and is instead treated as not supported.
\end{note}
\pnum
Each \grammarterm{has-attribute-expression} is replaced by
a non-zero \grammarterm{pp-number}
matching the form of an \grammarterm{integer-literal}
if the implementation supports an attribute
with the name specified by interpreting
the \grammarterm{pp-tokens}, after macro expansion,
as an \grammarterm{attribute-token},
and by \tcode{0} otherwise.
The program is ill-formed if the \grammarterm{pp-tokens}
do not match the form of an \grammarterm{attribute-token}.
\pnum
For an attribute specified in this document,
it is \impldef{value of \grammarterm{has-attribute-expression}
for standard attributes}
whether the value of the \grammarterm{has-attribute-expression}
is \tcode{0} or is given by \tref{cpp.cond.ha}.
For other attributes recognized by the implementation,
the value is
\impldef{value of \grammarterm{has-attribute-expression}
for non-standard attributes}.
\begin{note}
It is expected
that the availability of an attribute can be detected by any non-zero result.
\end{note}
\begin{floattable}{\xname{has_cpp_attribute} values}{cpp.cond.ha}
{ll}
\topline
\lhdr{Attribute} & \rhdr{Value} \\ \rowsep
\tcode{assume} & \tcode{202207L} \\
\tcode{carries_dependency} & \tcode{200809L} \\
\tcode{deprecated} & \tcode{201309L} \\
\tcode{fallthrough} & \tcode{201603L} \\
\tcode{likely} & \tcode{201803L} \\
\tcode{maybe_unused} & \tcode{201603L} \\
\tcode{no_unique_address} & \tcode{201803L} \\
\tcode{nodiscard} & \tcode{201907L} \\
\tcode{noreturn} & \tcode{200809L} \\
\tcode{unlikely} & \tcode{201803L} \\
\end{floattable}
\pnum
The
\tcode{\#ifdef}, \tcode{\#ifndef}, \tcode{\#elifdef}, and \tcode{\#elifndef}
directives, and
the \tcode{defined} conditional inclusion operator,
shall treat \xname{has_include}, \xname{has_embed}, and \xname{has_cpp_attribute}
as if they were the names of defined macros.
The identifiers \xname{has_include}, \xname{has_embed}, and \xname{has_cpp_attribute}
shall not appear in any context not mentioned in this subclause.
\pnum
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\iref{lex.token}.
\pnum
Preprocessing directives of the forms
\begin{ncsimplebnf}\obeyspaces
\indextext{\idxcode{\#if}}%
\terminal{\# if } constant-expression new-line \opt{group}\br
\indextext{\idxcode{\#elif}}%
\terminal{\# elif } constant-expression new-line \opt{group}
\end{ncsimplebnf}
check whether the controlling constant expression evaluates to nonzero.
\pnum
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 the
\tcode{defined}
unary operator),
just as in normal text.
If the preprocessing token
\tcode{defined}
is generated as a result of this replacement process
or use of the
\tcode{defined}
unary operator does not match one of the two specified forms
prior to macro replacement,
the behavior is undefined.
\pnum
After all replacements due to macro expansion and
evaluations of
\grammarterm{defined-macro-expression}s,
\grammarterm{has-include-expression}s, and
\grammarterm{has-attribute-expression}s
have been performed,
all remaining identifiers and keywords,
except for
\tcode{true}
and
\tcode{false},
are replaced with the \grammarterm{pp-number}
\tcode{0},
and then each preprocessing token is converted into a token.
\begin{note}
An alternative
token\iref{lex.digraph} is not an identifier,
even when its spelling consists entirely of letters and underscores.
Therefore it is not subject to this replacement.
\end{note}
\pnum
The resulting tokens comprise the controlling constant expression
which is evaluated according to the rules of~\ref{expr.const}
using arithmetic that has at least the ranges specified
in~\ref{support.limits}. 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,
\tcode{intmax_t} or \tcode{uintmax_t}\iref{cstdint.syn}.
\begin{note}
Thus on an
implementation where \tcode{std::numeric_limits<int>::max()} is \tcode{0x7FFF}
and \tcode{std::numeric_limits<unsigned int>::max()} is \tcode{0xFFFF},
the integer literal \tcode{0x8000} is signed and positive within a \tcode{\#if}
expression even though it is unsigned in translation phase
7\iref{lex.phases}.
\end{note}
This includes interpreting \grammarterm{character-literal}s
according to the rules in \ref{lex.ccon}.
\begin{note}
The associated character encodings of literals are the same
in \tcode{\#if} and \tcode{\#elif} directives and in any expression.
\end{note}
Each subexpression with type
\tcode{bool}
is subjected to integral promotion before processing continues.
\pnum
Preprocessing directives of the forms
\begin{ncsimplebnf}\obeyspaces
\terminal{\# ifdef } identifier new-line \opt{group}\br
\indextext{\idxcode{\#ifdef}}%
\terminal{\# ifndef } identifier new-line \opt{group}\br
\indextext{\idxcode{\#ifndef}}%
\terminal{\# elifdef } identifier new-line \opt{group}\br
\indextext{\idxcode{\#elifdef}}%
\terminal{\# elifndef} identifier new-line \opt{group}
\indextext{\idxcode{\#elifndef}}%
\end{ncsimplebnf}
check whether the identifier is or is not currently defined as a macro name.
Their conditions are equivalent to
\tcode{\#if} \tcode{defined} \grammarterm{identifier},
\tcode{\#if} \tcode{!defined} \grammarterm{identifier},
\tcode{\#elif} \tcode{defined} \grammarterm{identifier}, and
\tcode{\#elif} \tcode{!defined} \grammarterm{identifier},
respectively.
\pnum
Each directive's condition is checked in order.
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.
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.
If none of the conditions evaluates to true,
and there is a
\tcode{\#else}
\indextext{\idxcode{\#else}}%
directive,
the group controlled by the
\tcode{\#else}
is processed; lacking a
\tcode{\#else}
directive, all the groups until the
\tcode{\#endif}
\indextext{\idxcode{\#endif}}%
are skipped.%
\begin{footnote}
As indicated by the syntax,
a preprocessing token cannot follow a
\tcode{\#else}
or
\tcode{\#endif}
directive before the terminating new-line character.
However,
comments can appear anywhere in a source file,
including within a preprocessing directive.
\end{footnote}
\pnum
\begin{example}
This demonstrates a way to include a library \tcode{optional} facility
only if it is available:
\begin{codeblock}
#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{codeblock}
\end{example}
\pnum
\begin{example}
This demonstrates a way to use the attribute \tcode{[[acme::deprecated]]}
only if it is available.
\begin{codeblock}
#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{codeblock}
\end{example}
\rSec1[cpp.include]{Source file inclusion}
\indextext{preprocessing directive!embed a resource}
\indextext{\idxcode{\#embed}}%
\pnum
A
\tcode{\#include}
directive shall identify a header or source file
that can be processed by the implementation.
\pnum
A preprocessing directive of the form
\begin{ncsimplebnf}
\terminal{\# include <} h-char-sequence \terminal{>} new-line
\end{ncsimplebnf}
searches a sequence of
\impldef{sequence of places searched for a header}
places
for a header identified uniquely by the specified sequence
between the
\tcode{<}
and
\tcode{>}
delimiters,
and causes the replacement of that
directive by the entire contents of the header.
How the places are specified
or the header identified
is \impldef{search locations for \tcode{<>} header}.
\pnum
A preprocessing directive of the form
\begin{ncsimplebnf}
\terminal{\# include "} q-char-sequence \terminal{"} new-line
\end{ncsimplebnf}
causes the replacement of that
directive by the entire contents of the
source file identified by the specified sequence between the
\tcode{"}
delimiters.
The named source file is searched for in an
\impldef{manner of search for included source file}
manner.
If this search is not supported,
or if the search fails,
the directive is reprocessed as if it read
\begin{ncsimplebnf}
\terminal{\# include <} h-char-sequence \terminal{>} new-line
\end{ncsimplebnf}
with the identical contained sequence (including
\tcode{>}
characters, if any) from the original directive.
\pnum
A preprocessing directive of the form
\begin{ncsimplebnf}
\terminal{\# include} pp-tokens new-line
\end{ncsimplebnf}
(that does not match one of the two previous forms) is permitted.
The preprocessing tokens after
\tcode{include}
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).
If the directive resulting after all replacements does not match
one of the two previous forms, the behavior is
undefined.
\begin{footnote}
Note that adjacent \grammarterm{string-literal}s are not concatenated into
a single \grammarterm{string-literal}
(see the translation phases in~\ref{lex.phases});
thus, an expansion that results in two \grammarterm{string-literal}s is an
invalid directive.
\end{footnote}
The method by which a sequence of preprocessing tokens between a
\tcode{<}
and a
\tcode{>}
preprocessing token pair or a pair of
\tcode{"}
characters is combined into a single header name
preprocessing token is \impldef{search locations for \tcode{""""} header}.
\pnum
The implementation shall provide unique mappings for
sequences consisting of one or more
\grammarterm{nondigit}{s} or \grammarterm{digit}{s}\iref{lex.name}
followed by a period
(\tcode{.})
and a single
\grammarterm{nondigit}.
The first character shall not be a \grammarterm{digit}.
The implementation may ignore distinctions of alphabetical case.
\pnum
A
\tcode{\#include}
preprocessing directive may appear
in a source file that has been read because of a
\tcode{\#include}
directive in another file,
up to an \impldef{nesting limit for \tcode{\#include} directives} nesting limit.
\pnum
If the header identified by the \grammarterm{header-name}
denotes an importable header\iref{module.import},
it is
\impldef{whether source file inclusion of importable header
is replaced with \tcode{import} directive}
whether the \tcode{\#include} preprocessing directive
is instead replaced by an \tcode{import} directive\iref{cpp.import} of the form
\begin{ncbnf}
\terminal{import} header-name \terminal{;} new-line
\end{ncbnf}
\pnum
\begin{note}
An implementation can provide a mechanism for making arbitrary
source files available to the \tcode{< >} search.
However, using the \tcode{< >} form for headers provided
with the implementation and the \tcode{" "} form for sources
outside the control of the implementation
achieves wider portability. For instance:
\begin{codeblock}
#include <stdio.h>
#include <unistd.h>
#include "usefullib.h"
#include "myprog.h"
\end{codeblock}
\end{note}
\pnum
\begin{example}
This illustrates macro-replaced
\tcode{\#include}
directives:
\begin{codeblock}
#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{codeblock}
\end{example}
\rSec1[cpp.embed]{Resource inclusion}
\indextext{preprocessing directive!header inclusion}
\indextext{preprocessing directive!source-file inclusion}
\indextext{inclusion!source file|see{preprocessing directive, source-file inclusion}}%
\indextext{\idxcode{\#include}}%
\rSec2[cpp.embed.gen]{General}
\pnum
A preprocessing directive of the form
\begin{ncsimplebnf}
\terminal{\# embed <} h-char-sequence \terminal{>} \opt{pp-tokens} new-line
\end{ncsimplebnf}
searches a sequence of
\impldef{sequence of places searched for an embedded resource}
places for a resource identified uniquely by the specified sequence between
the \tcode{<} and \tcode{>} delimiters.
How the places are specified or the resource identified is
\impldef{search locations for embedded resources specified with \tcode{<>}}.
\pnum
A preprocessing directive of the form
\begin{ncsimplebnf}
\terminal{\# embed "} q-char-sequence \terminal{"} \opt{pp-tokens} new-line
\end{ncsimplebnf}
searches for a resource identified by the specified sequence between the
\tcode{"} delimiters.
The named resource is searched for in an
\impldef{manner of search for named resource}
manner.
If this search is not supported, or if the search fails, the directive is
reprocessed as if it read
\begin{ncsimplebnf}
\terminal{\# embed <} h-char-sequence \terminal{>} \opt{pp-tokens} new-line
\end{ncsimplebnf}
with the identical contained sequence (including \tcode{>} characters, if any)
from the original directive.
\pnum
\recommended A mechanism similar to, but distinct from, the
\impldef{sequence of places searched for a header}
search paths used for \tcode{\#include} \iref{cpp.include}
is encouraged.
\pnum
Either form of the \tcode{\#embed} directive processes the
\grammarterm{pp-tokens}, if present, just as in normal text.
The \grammarterm{pp-tokens} shall then have the form
\grammarterm{embed-parameter-seq}.
\pnum
A resource is a source of data accessible from the translation environment.
A resource has an \gterm{implementation-resource-width}, which is the
\impldef{size in bits of a resource}
size in bits of the resource.
If the \gterm{implementation-resource-width} is not an integral multiple of
\libmacro{CHAR_BIT}, the program is ill-formed.
Let \gterm{implementation-resource-count} be
\gterm{implementation-resource-width} divided by \libmacro{CHAR_BIT}.
Every resource also has a \gterm{resource-count}, which is
\begin{itemize}
\item
the value as computed from the optionally-provided \tcode{limit}
\grammarterm{embed-parameter}\iref{cpp.embed.param.limit}, if present;
\item
otherwise, the \gterm{implementation-resource-count}.
\end{itemize}
A resource is empty if the resource-count is zero.
\pnum
\begin{example}
\begin{codeblock}
// ill-formed if the implementation-resource-width is 6 bits
#embed "6_bits.bin"
\end{codeblock}
\end{example}
\pnum
The \tcode{\#embed} directive is replaced by a comma-delimited list of integer
literals of type \tcode{int}, unless otherwise modified by embed
parameters\iref{cpp.embed.param}.
\pnum
The integer literals in the comma-delimited list correspond to
\gterm{resource-count} consecutive calls to \tcode{std::fgetc} \iref{cstdio.syn}
from the resource, as a binary file.
If any call to \tcode{std::fgetc} returns \tcode{EOF}, the program is
ill-formed.
\pnum
\recommended The value of each integer literal should closely represent
the bit stream of the resource unmodified.
This can require an implementation to consider potential differences between
translation and execution environments, as well as any other applicable
sources of mismatch.
\begin{example}
\begin{codeblock}
#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{codeblock}
\end{example}
\begin{example}
\begin{codeblock}
int i = {
#embed "i.dat"
}; // well-formed if i.dat produces a single value
int i2 =
#embed "i.dat"
; // also well-formed if i.dat produces a single value
struct s {
double a, b, c;
struct { double e, f, g; } x;
double h, i, j;
};
is x = {
// well-formed if the directive
// produces nine or fewer values
#embed "s.dat"
};
\end{codeblock}
\end{example}
\pnum
A preprocessing directive of the form
\begin{ncsimplebnf}
\terminal{\# embed} pp-tokens new-line
\end{ncsimplebnf}
(that does not match one of the two previous forms) is permitted.
The preprocessing tokens after \tcode{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).
The directive resulting after all replacements of the third form shall match