Non-directives

E

Eric Sosman

It seems to me the topic has come up before, but it doesn't
seem to me the question was ever answered satisfactorily:

What is a preprocessing non-directive?

6.10p1 describes its syntax, 6.10p3 states a requirement
(but not a constraint), a footnote to 6.10p11 asserts that a
non-directive is in fact a directive -- and that is all the
Standard says about the matter until it repeats itself in
Appendix A.

The (C99) Rationale says that non-directives are not
implementation-defined but are "strictly" defined, and mumbles
something about placeholders for intermediate translation states
having "no associated semantics in this phase."

So: Can anyone explain what a non-directive is, does,
or is for? Is

#import <stdio.h>

.... a non-directive?
 
J

James Kuyper

It seems to me the topic has come up before, but it doesn't
seem to me the question was ever answered satisfactorily:

What is a preprocessing non-directive?

6.10p1 describes its syntax, 6.10p3 states a requirement
(but not a constraint), a footnote to 6.10p11 asserts that a
non-directive is in fact a directive -- and that is all the
Standard says about the matter until it repeats itself in
Appendix A.

The (C99) Rationale says that non-directives are not
implementation-defined but are "strictly" defined, and mumbles
something about placeholders for intermediate translation states
having "no associated semantics in this phase."

So: Can anyone explain what a non-directive is, does,
or is for? Is

#import <stdio.h>

... a non-directive?

Yes.

The key thing to understand is that what qualifies as a non-directive is
defined by the standard, but there is no standard-defined behavior
associated with them. As such, a non-directive is something that has a
similarity to directives, but can be used to implement non-conforming
extensions. In that regard, there's a certain amount of overlap with
#pragma directives.

The fact that they are classified as directives means that everything
that the standard says about directives in general, rather than about
specific directives, applies to non-directives as well. This is
particularly important with respect to conditional compilation
(6.10.1p6). Non-directives get skipped or processed, depending which
part of a #if, #ifdef, #ifndef, or #elif they are in - they don't
interfere with the interpretation of those constructs. That allows them
to be protected against mis-interpretation by fully conforming
implementations by suitable use of #if, et. al.
 
E

Eric Sosman

Yes.

The key thing to understand is that what qualifies as a non-directive is
defined by the standard, but there is no standard-defined behavior
associated with them. As such, a non-directive is something that has a
similarity to directives, but can be used to implement non-conforming
extensions. In that regard, there's a certain amount of overlap with
#pragma directives.

The fact that they are classified as directives means that everything
that the standard says about directives in general, rather than about
specific directives, applies to non-directives as well. This is
particularly important with respect to conditional compilation
(6.10.1p6). Non-directives get skipped or processed, depending which
part of a #if, #ifdef, #ifndef, or #elif they are in - they don't
interfere with the interpretation of those constructs. That allows them
to be protected against mis-interpretation by fully conforming
implementations by suitable use of #if, et. al.

Thanks, James. It's plausible, but I'm not entirely
convinced you're right. The Rationale (non-normative, of
course) says

Neither /text-line/ nor /non-directive/ is implementation
defined. They are strictly defined as sequences of pp-tokens
followed by new-line. Each of these rules represents a
placeholder for an intermediate state in the phases of
translation, and is expressed as a non-terminal since it
has no associated semantics at this phase.

However, these sequences of pp-tokens are still subject to
normal processing in the subsequent phases of translation.

On re-reading, it seems this may mean non-directives are
pp-token sequences that get macro-replaced in Phase 4 but are
not otherwise preprocessed: They don't affect preprocessor
operation ("no semantics"), and are not removed. "Normal
processing" will convert the non-directive's pp-tokens to
tokens in Phase 7, and the parser will then report a syntax
error (the # token alone is sufficient offense against the
grammar).

So: Is "non-directive" just a way of describing how an
erroneous preprocessor construct gets turned into a syntax
error?
 
J

James Kuyper

On 9/10/2013 4:58 PM, James Kuyper wrote: ....

Thanks, James. It's plausible, but I'm not entirely
convinced you're right. The Rationale (non-normative, of
course) says

Neither /text-line/ nor /non-directive/ is implementation
defined. They are strictly defined as sequences of pp-tokens
followed by new-line. Each of these rules represents a
placeholder for an intermediate state in the phases of
translation, and is expressed as a non-terminal since it
has no associated semantics at this phase.

However, these sequences of pp-tokens are still subject to
normal processing in the subsequent phases of translation.

On re-reading, it seems this may mean non-directives are
pp-token sequences that get macro-replaced in Phase 4 but are

"The preprocessing tokens within a preprocessing directive are not
subject to macro expansion unless otherwise stated." (6.10p7)

It is "otherwise stated" that macro expansion applies to the controlling
condition of #if and #elif (6.10.1p4).

Both #include and #line have two forms for which no macro replacement
applies, but can be used in a more general form for which macro
replacement is not only allowed, but strongly recommended - the behavior
is undefined if macro replacement doesn't convert the general form to
one of the other two forms. (6.10.2p4, 6.10.4p5)

Since it is NOT "otherwise stated", macro expansion does not apply to
non-directives, #define, #undef, #error, or null directives, nor to
#pragma directives where #pragma is immediately followed by a STDC
token. It is not explicitly stated that macro expansion is allowed for
other #pragma directives, but "behave in an implementation-defined
manner" certainly allows the implementation to say that it does, which I
think qualifies as "otherwise stated". If it doesn't count, then the
references to "prior to any macro expansion" in 6.10.6 don't make sense.
not otherwise preprocessed: They don't affect preprocessor
operation ("no semantics"), and are not removed.

"... All preprocessing directives are then deleted." (5.1.1.2p4)

Keep in mind that non-directives, despite the implications of their
names, are pre-processing directives (footnote 172), and are therefore
covered by both 6.10p7 and 5.1.1.2p4. It is specifically for the purpose
of making such things work that the definition of "pre-processing
directive" (6.10p2) was not made more restrictive.
 
T

Tim Rentsch

Eric Sosman said:
It seems to me the topic has come up before, but it doesn't
seem to me the question was ever answered satisfactorily:

What is a preprocessing non-directive?

My reading of the Standard is that a 'non-directive' is a
preprocessing directive, and having one in program source
(assuming it isn't skipped by a preprocessing conditional)
is undefined behavior. Reasoning given below.
6.10p1 describes its syntax, 6.10p3 states a requirement
(but not a constraint), a footnote to 6.10p11 asserts that a
non-directive is in fact a directive -- and that is all the
Standard says about the matter until it repeats itself in
Appendix A.

(Presumably you meant 6.10.3p11 for the footnote.)

The statements in 6.10p3 are meant as restrictions on the definition
of the language, not as restrictions on programs. That is, the
statement "A non-directive shall not begin with any of the directive
names appearing in the syntax" means that any preprocessor line that
does begin with one of those directive names is not to be taken (by
an implementation) as a non-directive.

The (C99) Rationale says that non-directives are not
implementation-defined but are "strictly" defined, and mumbles
something about placeholders for intermediate translation states
having "no associated semantics in this phase."

So: Can anyone explain what a non-directive is, does,
or is for? Is

#import <stdio.h>

... a non-directive?

Yes. Based on the syntax, 6.10 p3, and the footnote in 6.10.3 p11,
it seems clear such a line is a non-directive, and is meant to be
a preprocessing directive despite the name.

An indirect argument that non-directives are undefined behavior
goes as follows. Clearly the behavior of non-directive lines is
not implementation-defined, since nothing says so. Hence the
behavior must either be defined or be undefined. If the behavior
were defined, then such a line would have to do the same thing in
all conforming implementations. Observing that in fact such lines
behave differently in different implementations, the behavior must
therefore be undefined.

A direct argument that non-directives are undefined behavior goes as
follows. 5.1.1.2 p4 says "Preprocessing directives are executed".
The semantics of executing a non-directive is not defined anywhere.
Hence under section 4 p2 the behavior upon attempting to execute
a non-directive is undefined.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,009
Latest member
GidgetGamb

Latest Threads

Top