Skip to content

Rough draft of Section 3.5 conditionals: #if, #elif, etc. #61

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jun 4, 2025
158 changes: 143 additions & 15 deletions drafts/25-xxx-specifications.txt
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ li17. Preprocessor directive continuation processing described by the prior rule
li19. The maximum length of a preprocessor directive (including
continuation text) is one million characters.

li21. A source file that ends with a directive line shall neither end with a '\',
li21. A source file that ends with a directive line shall neither end with a '\',
nor a '\' followed immediately by a new-line (analogously to C 2023 5.1.1.2 bullet 2).

li31. Fortran comment lines are defined as in 25-007 6.3.2.3 and
Expand Down Expand Up @@ -177,9 +177,9 @@ Further definition of the recognized tokens is deferred to the upcoming preproce


to01. In the definitions of object macros and function-like macros,
the replacement list may include any arbitrary sequence of
the replacement list may include any arbitrary sequence of
characters that doesn't include a new-line. Once tokenized,
this for example may include any tokens allowed in Fortran
this for example may include any tokens allowed in Fortran
source lines, those allowed in C integer expressions,
and any additional tokens recognized by the processor.

Expand Down Expand Up @@ -221,6 +221,11 @@ syntax below, we denote these as just "token-list" or
"replacement-list".


di00. The directives listed in di01-di08 are only recognized as such
if the token immediately following the '#' introducing a
directive line exactly matches one of the standard directive
names ('define', 'if', 'pragma', etc.).

di01. The '#define' object-like macro directive

di02. The '#define' function-like macro directive
Expand All @@ -230,7 +235,7 @@ di03. The '#undef' directive
di04. The '#include' directive

di05. The '#if', '#ifdef', '#ifndef', '#elif', '#elifdef',
'#elifndef', '#else', '#endif' directives
'#elifndef', '#else', '#endif' conditional directives

di06. The '#error' and '#warning' directives

Expand Down Expand Up @@ -315,7 +320,7 @@ df04. The identifier-list is a comma-separated list of ID tokens.
df06. No identifier may appear more than once in the identifier-list.

df08. The identifier names in the identifier-list define macro "parameters" that affect
macro expansion of the replacement list. (See the section "Macro recognition and
macro expansion of the replacement list. (See the section "Macro recognition and
expansion" for the semantics of function-like macro expansion.)

df10. The replacement-list may be the empty sequence of tokens.
Expand Down Expand Up @@ -410,26 +415,151 @@ in24. If the file is located, the processor replaces the #include
in26. A #include directive may appear in an included file, up to a
processor-defined nesting limit.

in28. Unlike INCLUDE lines (see the section on "INCLUDE lines"),
in28. Unlike INCLUDE lines (see the section on "INCLUDE lines"),
the #include directive is not prohibited from including the
same source file at a deeper level of nesting.


3.5 The '#if', '#ifdef', '#ifndef', '#elif', '#elifdef',
'#elifndef', '#else', '#endif' directives
'#elifndef', '#else', '#endif' conditional directives
---------------------------------------------------------

Example syntax:
Example syntax (extra spacing for illustration purposes only):
General form:
<if-head> <if-elif-list> #endif EOL
<if-head> <if-elif-list> <if-else> #endif EOL

Where:
<if-head> is one of:
#if token-list EOL <group>
#ifdef ID EOL <group>
#ifndef ID EOL <group>

<if-elif-list> is zero or more of:
<if-elif>

<if-elif> is one of:
#elif token-list EOL <group>
#elifdef ID EOL <group>
#elifndef ID EOL <group>

<if-else> is one of:
#else EOL <group>

<group> is zero or more of:
directive lines
Fortran comment lines
Fortran source lines


3.5.1 Static semantics specifications
--------------------------------------
-------------------------------------

if05. A #if, #ifdef, or #ifndef directive signals the start of a chain
of conditional directives.

if15. The chain of #elif, #elifdef, and #elifndef directives, and the
#else directive (if present) are part of the same chain of
directives introduced by the #if directive.

if20. The chain of conditional directives ends with the #endif
directive.

if25. Within a conditional directive chain, a #if, #ifdef, or #ifndef
directive introduces a new chain of conditional directives, at a new
nesting level, within the enclosing conditional directive chain.

if30. The conditional directive chains must properly nest.



3.5.2 Evaluation semantics specifications
-----------------------------------------


ix05. The #ifdef and #ifndef directives are evaluated as if they had been
written "#if defined(ID)" and "#if !defined(ID)" respectively.
(For brevity, the descriptions of #ifdef and #ifndef directives
below are omitted, and assume this transformation.)

ix10. The #elifdef and #elifndef directives are evaluated as if they had
been written "#elif defined(ID)" and "#elif !defined(ID)"
respectively. (For brevity, the descriptions below
assume this transformation has been made).

ix12. In the descriptions below, <group> constructs may be "skipped".
When skipped:
- Conditional directives within the <group> are recognized only
to maintain proper nesting of conditional directives.
- No nested directives in the <group> are processed.
- No macro expansion takes place in directive lines, Fortran
comment lines or source lines in the <group>.
- No skipped lines of any kind in the <group> are made available
to subsequent processing by the processor.

ix14. In the descriptions below, <group> constructs that are not
skipped participate in further preprocessing and processing.
When participating:

- Macros are expanded in Fortran comment lines and source
lines.
- Nested directives in the <group> are processed.
- The resulting Fortran comment lines and source lines
are made available for subsequent processing by the
processor.

ix15. Before evaluating the token-lists in any <if-head> and <if-elif>
constructs that are not skipped, macros in the token-lists are
processed as described in the section "Macro recognition and expansion".

ix20. After expansion, the resulting token list in <if-head> and <if-elif>
constructs that are not skipped must be able to be parsed as a valid integer expression as
described in the section "Expressions allowed in #if and #elif
directives" static semantics. This expression is called the "controlling
expression" for the directive.

ix25. The values of controlling expressions in <if-head> and <if-elif>
constructs are evaluated according to the evaluation semantics
described in the section "Expressions allowed in #if and #elif
directives".

ix30. If the controlling expression in an <if-head> evaluates to a
nonzero value, then the <group> contained within that <if-head>
construct participates in further preprocessing, as described
above. Subsequent <if-elif> and <if-else> constructs at the same
level of nesting are skipped.

ix45. If the controlling expression in an <if-head> construct
evaluates to a zero value, then the <group> contained within
that <if-head> construct is skipped. Preprocessing continues
with any <if-elif> constructs at the same level of nesting, as
described below.

ix50. When the controlling expression in an <if-head> construct
evaluates to zero, the controlling expressions in each <if-elif>
construct at the same nesting level are evaluated in turn, until
one evaluates to a non-zero value. Those
<group>s whose controlling expression evaluates to zero are
skipped.

ix55. When the controlling expression in an <if-elif> construct
evaluates to a nonzero value, the <group> contained within that
<if-elif> construct continues to participate in preprocessing.
Subsequent <if-elif> constructs and any remaining <if-else>
constructs at the same nesting level are skipped.

ix60. When all controlling expressions in the <if-head> construct and
<if-elif> constructs evaluate to a zero value and an <if-else>
construct is present at the same nesting level, the <group>
contained in the <if-else> construct continues to participate in
preprocessing.

ix65. When all controlling expressions in the <if-head> construct and
all <if-elif> constructs evaluate to a zero value and no
<if-else> construct is present at the same nesting level, then
all <group>s in these constructs are skipped.


3.6 The '#error' and '#warning' directives
------------------------------------------

Expand Down Expand Up @@ -479,7 +609,7 @@ li04. The WHOLE_NUMBER shall not exceed 2147483647.
-----------------------------------------

li20. In both forms, the #line directive causes the processor
to behave as if the following sequence of lines begins with a
to behave as if the following sequence of lines begins with a
presumed line number specified by the WHOLE_NUMBER.

li24. In the second form, the #line directive causes the processor
Expand Down Expand Up @@ -612,8 +742,8 @@ The following macro names shall be defined by the processor:
7.1 __LINE__
------------

pm20. `__LINE__` shall be predefined to a WHOLE_NUMBER representing
the presumed line number (within the current source file)
pm20. `__LINE__` shall be predefined to a WHOLE_NUMBER representing
the presumed line number (within the current source file)
of the current source line.

7.2 __FILE__
Expand Down Expand Up @@ -665,7 +795,7 @@ Appendix A: Divergences from C
In many ways, the FPP specified by this document adheres to the
existing practice established by the C preprocessor over the past
several decades. However FPP semantics also deliberately diverge from
the analogous behavior of the C preprocessor as specified in C 2023.
the analogous behavior of the C preprocessor as specified in C 2023.
This non-normative section enumerates such deliberate differences,
as a reference for readers to assist in comparisons.

Expand Down Expand Up @@ -704,5 +834,3 @@ dfc90. FPP omits the `__has_embed` expression added in C 2023.

[dob: This section may need to be amended as we settle on unresolved
topics such as _Pragma]