"error: invalid preprocessing directive #DEFINE"

R

Richard Bos

Tim Rentsch said:
My reading is that

#DEFINE <pp-tokens> <new-line>

(which presumably is what was there) is legal, and should not
have been rejected.

It is a non-directive. Since no meaning is defined for non-directives,
they have undefined behaviour. Therefore, if the implementation can show
that a non-directive will be reached, it is allowed to reject the source
code entirely.

Richard
 
K

Keith Thompson

It is a non-directive. Since no meaning is defined for non-directives,
they have undefined behaviour. Therefore, if the implementation can show
that a non-directive will be reached, it is allowed to reject the source
code entirely.

Or it an silently ignore it, which is the problem.
 
K

Keith Thompson

Eric Sosman said:
Richard said:
[...]
It is a non-directive. Since no meaning is defined for non-directives,
they have undefined behaviour. Therefore, if the implementation can show
that a non-directive will be reached, it is allowed to reject the source
code entirely.

If you're correct that a non-directive produces undefined
behavior, I don't think "reachability" matters. Some kinds of
U.B. are unrelated to the flow of program execution. For example,
declaring an identifier with both external and internal linkage
in the same translation unit yields undefined behavior, yet the
internal-linkage declaration is necessarily outside any executable
block and is thus "unreachable" by definition.

I'm still keeping an open mind about whether an N-D produces
undefined behavior. On the larger question of what an N-D is
*for*, my mind is not only open but empty ...

Assuming the intent is to allow implementation-specific preprocessor
directives, making the behavior undefined even if it's unreachable
would make it nearly useless.

For example, suppose Foo C supports a "#include_once" directive:

#ifdef __FOO_C__
#include_once "blah.h"
#else
#include "blah.h"
#endif

The obvious intent is that the #include_once directive will be seen
only by the Foo C compiler.

I still dislike what seems to be the intent; if an implementation
doesn't support "#include_once", a diagnostic should be mandatory for
that implementation.
 
J

jameskuyper

Eric said:
Richard said:
[...]
It is a non-directive. Since no meaning is defined for non-directives,
they have undefined behaviour. Therefore, if the implementation can show
that a non-directive will be reached, it is allowed to reject the source
code entirely.

If you're correct that a non-directive produces undefined
behavior, I don't think "reachability" matters. Some kinds of
U.B. are unrelated to the flow of program execution. For example,
declaring an identifier with both external and internal linkage
in the same translation unit yields undefined behavior, yet the
internal-linkage declaration is necessarily outside any executable
block and is thus "unreachable" by definition.


For a pre-processing directive "will be reached" means that it
survives conditional compilation.
 
J

James Kuyper

Dietmar said:
I cannot find anything in the Standard that would support the above
statement. Moreover, I cannot find anything in the Standard that would
indicate that any pre-processing directive can ever be /reached/.

The standard never defines what the term "reached" means, it only uses
the term in contexts where it refers to something that happens a run
time, not compile time. It does not use the term when explaining
undefined behavior.

What it does say is that behavior is undefined "upon use of a
nonportable or erroneous program construct or of erroneous data," a
sufficiently vague statement that the Committee has had to resolve some
defect reports based upon uncertainties about what precisely constitutes
a "use"; those rulings indicate that for most kinds of undefined
behavior, "use" requires that execution of the program must be
guaranteed (absent the undefined behavior) to reach the relevant line of
code.

However, Undefined behavior associated with preprocessing necessarily
involves a "use" that occurs at compile time, not run time.

The standard does specify that if conditional compilation causes a group
of lines to be 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." In
that case, the standard defines exactly what happens to such lines, so
it is not possible to claim undefined behavior "by the omission of any
explicit definition of behavior".
 
T

Tim Rentsch

It is a non-directive. Since no meaning is defined for non-directives,
they have undefined behaviour. Therefore, if the implementation can show
that a non-directive will be reached, it is allowed to reject the source
code entirely.

Yes, as I already explained two days earlier in my followup
posting.
 
T

Tim Rentsch

Eric Sosman said:
Richard said:
[...]
It is a non-directive. Since no meaning is defined for non-directives,
they have undefined behaviour. Therefore, if the implementation can show
that a non-directive will be reached, it is allowed to reject the source
code entirely.
[snip]
I'm still keeping an open mind about whether an N-D produces
undefined behavior. [snip]

Do you mean open as to whether non-directives are undefined
behavior, or whether non-directives were meant to be undefined
behavior? The case for non-directives being undefined behavior
seems pretty cut-and-dried, since no definition is given for
what happens when they are "executed".
 
T

Tim Rentsch

Keith Thompson said:

Assuming the intent is to allow implementation-specific preprocessor
directives, making the behavior undefined even if it's unreachable
would make it nearly useless.

For example, suppose Foo C supports a "#include_once" directive:

#ifdef __FOO_C__
#include_once "blah.h"
#else
#include "blah.h"
#endif

The obvious intent is that the #include_once directive will be seen
only by the Foo C compiler.

The behavior in such cases is covered, just as it is for #include,
etc, in 6.10.1p6 -- defined to skip the directive if __FOO_C__ has
not been #define'd.
 
T

Tim Rentsch

Keith Thompson said:
Tim Rentsch said:
Right. It's deleted at the end of phase 4 (assuming that the UB
that arises from "executing" it doesn't contradict that).


It gets deleted because of the last sentence of 5.1.1.2p1.4 says
it will be (oops, bad reference in a previous posting). The
question is what happens when it gets executed, and the Standard
doesn't say anything about that, which is what makes the behavior
undefined.

Ok. The reference paragraph, which describes translation phase 4,
says

Preprocessing directives are executed, macro invocations are
expanded, and _Pragma unary operator expressions are executed.
[snip]
All preprocessing directives are then deleted.

And yes, the meaning of executing a non-directive (which is a
directive) is the sticking point. Since the standard doesn't define
the behavior, the behavior is undefined.
It's there to make sure that every line starting with '#' is
considered a preprocessing directive, and it's undefined to
give implementations a chance to define them. It just would be
nice if that had been handled a little better and been made
a little more clear in the Standard.

I have a much clearer understanding of what the standard *says*
about non-directives. But I'm still waiting for a definitive
statement about the intent. (Such a statement cannot be based
only on the wording of the standard; it's about the state of mind
of the authors.)

You mean you don't consider my speculations and guesses to
have as much value as comments from someone who actually
knows what's going on? I'm crushed. :)

The standard would be substantially improved by an explicit
statement that the behavior of executing a non-directive is
undefined. It would be improved even more, IMHO, by a statement
that executing a non-directive is a constraint violation. If I
misspell a keyword, the compiler complains, and in most cases
it's required to complain. The (apparent) fact that this doesn't
apply to misspelled preprocessor directives is counterintuitive.
This would still leave room for implementation-defined extensions.

I would second a motion to propose such a change as
part of C1X. Possibly I would change my mind about
whether the change should be adopted after hearing
the discussion, but I'd like to hear the discussion
first.
 
T

Tim Rentsch

James Kuyper said:
Kenneth said:
jameskuyper said:
Kenneth Brody wrote: [...]
While useful as a way of adding implementation-specific features, a
catch-all "comment" doesn't sound good to me.

I agree; I was trying to figure out what the standard actually says,
and to suggest alternative wording that would make it clearer.
However, all the committee had to do to make a diagnostic mandatory
would have been to leave out non-directives entirely; they would then
have constituted syntax errors. In defining a "non-directive", the
committee went out of their way to make it not be a syntax error; I
presume they had a reason - I'm curious what it was. Until I know that
reason, and can judge it's validity, I didn't want to suggest changing
it to a syntax error.

It doesn't have to be a "syntax error" to be an "error". After all,
the following isn't a "syntax error", either:

I would want a diagnostic to be mandatory; the simplest way to make
that happen is to make it a syntax error, by removing 'non-directive'
from the grammar. [snip]

The /simplest/ way would be to add a statement saying that a
diagnostic is mandatory. Changing the syntax would mean
making a number of other changes in the subsequent text
of 6.10 and 6.10.x

My point is - the committee went out of their way to put
"non-directive" into the grammar. Why? [snip]

It seems clear that the point is to make non-directives be considered
similarly to other preprocessing directives, eg, should be deleted at
the end of phase 4, should be illegal in multi-line macro calls, etc.
Just because their behavior isn't defined doesn't mean that there is
no value in putting in clues of this sort. The Standard is read by
humans, not computers.
 
K

Keith Thompson

Dietmar Schindler said:
I cannot find anything in the Standard that would support the above
statement. Moreover, I cannot find anything in the Standard that would
indicate that any pre-processing directive can ever be /reached/.

As James said, the standard doesn't use the word "reached" in this context,
but you can see the idea in the description of #error (C99 4p4):

The implementation shall not successfully translate a
preprocessing translation unit containing a #error preprocessing
directive unless it is part of a group skipped by conditional
inclusion.
 
K

Keith Thompson

Tim Rentsch said:
I would want a diagnostic to be mandatory; the simplest way to make
that happen is to make it a syntax error, by removing 'non-directive'
from the grammar. [snip]

The /simplest/ way would be to add a statement saying that a
diagnostic is mandatory. Changing the syntax would mean
making a number of other changes in the subsequent text
of 6.10 and 6.10.x

The simplest way would be to make it a constraint violation; the
requirement for a diagnostic would fall out of that.

Explicitly stating that a constraint is required would add a fourth
special case to the existing things that require diagnostics: syntax
errors, constraint violations, and #error.
 
R

Richard Bos

Dietmar Schindler said:
I cannot find anything in the Standard that would support the above
statement. Moreover, I cannot find anything in the Standard that would
indicate that any pre-processing directive can ever be /reached/.

It is obvious from the requirements for the #error directive (spec. the
one in section 4), even though the phrasing used may be different. (Note
that I did not write "reached upon execution", and in fact meant
"reached during translation").

Richard
 
T

Tim Rentsch

Keith Thompson said:
Tim Rentsch said:
I would want a diagnostic to be mandatory; the simplest way to make
that happen is to make it a syntax error, by removing 'non-directive'
from the grammar. [snip]

The /simplest/ way would be to add a statement saying that a
diagnostic is mandatory. Changing the syntax would mean
making a number of other changes in the subsequent text
of 6.10 and 6.10.x

The simplest way would be to make it a constraint violation;

I'm not sure I agree; more below.
the requirement for a diagnostic would fall out of that.

Explicitly stating that a constraint is required would add a fourth
special case to the existing things that require diagnostics: syntax
errors, constraint violations, and #error.

The word 'constraint', especially as defined in 3.8p1, doesn't
describe the situation with non-directive very well. Making
executing a non-directive be a constraint violation would require
issuing a diagnostic, but this rule isn't so much a "restriction" as
a "prohibition". It seems likely that this same reasoning (or
similar reasoning) is why '#error' is defined as requiring a
diagnostic, rather than being identified as under a Constraints
section.

I understand the desire not to add more cases (be they special or
otherwise) to the set of things that require a diagnostic. At the
same time, it's not a good idea to lump something in with an existing
category, just for the sake of convenience, if it doesn't really fit
in that category. In my opinion the situation with 'non-directive'
is different enough from other conditions identified as Constraints
to think that this term may not be appropriate here. To say this
another way, I think the situation with 'non-directive' is more like
'#error' than it is like a constraint violation; if the Standard is
going to be consistent in how it uses terminology, then either both
'#error' and 'non-directive' should be constraint violations or
neither should be [assuming that we want 'non-directive' to require a
diagnostic, which I'm taking as a given for the sake of discussion].
I think I understand the reasoning that went into the decision on how
to handle '#error'; since the same reasoning seems to apply to
'non-directive', unless there's an argument I haven't thought of yet,
then just giving an explicit statement that a diagnostic must be
issued seems like the better course.

Returning to the larger issue, maybe the best way to clear up what's
going on with 'non-directive' would be to write a 'Recommended
practice' paragraph or two saying that encountering a 'non-directive'
should produce a diagnostic message, perhaps depending on a compiler
option that allows some implementation-specific preprocessing
directives. There is some precedent for such a provision, namely,
6.4.4.2p6 (and for convenience here it is):

The implementation should produce a diagnostic message if a
hexadecimal constant cannot be represented exactly in its
evaluation format; the implementation should then proceed
with the translation of the program.

Of course the specific wording for 'non-directive' would be
very different, but the general approach might be a good
idea here considering the current state of affairs.
 
K

Keith Thompson

Tim Rentsch said:
Keith Thompson said:
Tim Rentsch said:
I would want a diagnostic to be mandatory; the simplest way to make
that happen is to make it a syntax error, by removing 'non-directive'
from the grammar. [snip]

The /simplest/ way would be to add a statement saying that a
diagnostic is mandatory. Changing the syntax would mean
making a number of other changes in the subsequent text
of 6.10 and 6.10.x

The simplest way would be to make it a constraint violation;

I'm not sure I agree; more below.
the requirement for a diagnostic would fall out of that.

Explicitly stating that a constraint is required would add a fourth
special case to the existing things that require diagnostics: syntax
errors, constraint violations, and #error.

The word 'constraint', especially as defined in 3.8p1, doesn't
describe the situation with non-directive very well. Making
executing a non-directive be a constraint violation would require
issuing a diagnostic, but this rule isn't so much a "restriction" as
a "prohibition". It seems likely that this same reasoning (or
similar reasoning) is why '#error' is defined as requiring a
diagnostic, rather than being identified as under a Constraints
section.

I disagree. I think the main reason #error is handled separately is
that, unlike a constraint error, it requires the compilation to fail.
Another reason, I suppose, is that #error is something you'd write
intentionally.

I still think that a "non-directive" should be treated as a
constraint violation. Or the grammar production for "non-directive"
could just be dropped, making it a syntax error. The result would
be the same either way.

There are two reasons a non-directive might appear in a program:

1. It's an implementation-specific extension. Consider a core
language extension like "short float". A conforming implementation
must issue a diagnostic for "short float"; it can then accept the
translation unit anyway and do what it likes with the the semantics.
And it can also provide a non-conforming mode in which it doesn't
issue the diagnostic; the conforming mode is still there to warn
you that it's not portable.

I can think of no good reason why a preprocessor extension like, say,
"#include_once", should be treated any differently.

2. It's a typo. If I accidentally type "#elsif" rather than "#elif",
the compiler IMHO should be *required* to diagnose the error.
Even if the compiler "helpfully" treats "#elsif" as a synonym for
"#elif", I want to know that my code isn't portable. (I think most
compilers already do, so requiring it wouldn't be a burden.)

[snip]
 
T

Tim Rentsch

Keith Thompson said:
Tim Rentsch said:
Keith Thompson said:
[...]
I would want a diagnostic to be mandatory; the simplest way to make
that happen is to make it a syntax error, by removing 'non-directive'
from the grammar. [snip]

The /simplest/ way would be to add a statement saying that a
diagnostic is mandatory. Changing the syntax would mean
making a number of other changes in the subsequent text
of 6.10 and 6.10.x

The simplest way would be to make it a constraint violation;

I'm not sure I agree; more below.
the requirement for a diagnostic would fall out of that.

Explicitly stating that a constraint is required would add a fourth
special case to the existing things that require diagnostics: syntax
errors, constraint violations, and #error.

The word 'constraint', especially as defined in 3.8p1, doesn't
describe the situation with non-directive very well. Making
executing a non-directive be a constraint violation would require
issuing a diagnostic, but this rule isn't so much a "restriction" as
a "prohibition". It seems likely that this same reasoning (or
similar reasoning) is why '#error' is defined as requiring a
diagnostic, rather than being identified as under a Constraints
section.

I disagree. I think the main reason #error is handled separately is
that, unlike a constraint error, it requires the compilation to fail.
Another reason, I suppose, is that #error is something you'd write
intentionally.

I still think that a "non-directive" should be treated as a
constraint violation. [snip elaboration]

The most important thing, and the point we're most in agreement
on, is that the Standard would be improved if the question of
how 'non-directive's are treated were addressed more explicitly
and directly. After/if there is some level of consensus for
doing something, then we can take up again the question of
just what explicit requirements are most appropriate.
 
K

Keith Thompson

Tim Rentsch said:
I still think that a "non-directive" should be treated as a
constraint violation. [snip elaboration]

The most important thing, and the point we're most in agreement
on, is that the Standard would be improved if the question of
how 'non-directive's are treated were addressed more explicitly
and directly. After/if there is some level of consensus for
doing something, then we can take up again the question of
just what explicit requirements are most appropriate.

IMHO, there's no reason not to consider what the requirements
should be. Making the requirements more explicit and making them
"good" are two somewhat separate issues, but I have no problem
considering both issues simultaneously.

If the committee were to decide to make a change in this area, they
probably wouldn't (a) decide to make it more explicit and then (b)
wait for more feedback on what to do.
 
T

Tim Rentsch

Keith Thompson said:
Tim Rentsch said:
I still think that a "non-directive" should be treated as a
constraint violation. [snip elaboration]

The most important thing, and the point we're most in agreement
on, is that the Standard would be improved if the question of
how 'non-directive's are treated were addressed more explicitly
and directly. After/if there is some level of consensus for
doing something, then we can take up again the question of
just what explicit requirements are most appropriate.

IMHO, there's no reason not to consider what the requirements
should be. Making the requirements more explicit and making them
"good" are two somewhat separate issues, but I have no problem
considering both issues simultaneously.

If the committee were to decide to make a change in this area, they
probably wouldn't (a) decide to make it more explicit and then (b)
wait for more feedback on what to do.

It seems counterproductive to argue with someone who is
basically on the same side as I am. That's really all
I was trying to say.
 
L

lawrence.jones

jacob navia said:
The preprocessor of lcc-win uses is a version that was written by Dennis Ritchie.

Are you sure about that? As far as I know, DMR never wrote a preprocessor.
The original Unix cpp was written by John Reiser.
 

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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top