Subject: Is it implementation-defined whether this errors?
This is a test case I constructed for a vaporware standalone C99 preprocessor:
#if 1 #elif #endif
The text did not permit quickly deciding whether the syntax relaxation for preprocessing directives in blocks that aren't processed (C99 6.10 paragraph 4) dominates knowing what an elif-block actually was (C99 6.10 paragraph 1). If 6.10 paragraph 4 dominates, this should warn (as the preprocessor got lucky). If C99 6.10 paragraph 1 dominates, this should error.
The obvious complementary test case
#if 0 #elif #endif
must error, as the control expression of the #elif is actually needed. So I tentatively decided to make the first test case behave like the obvious one: error [why should it only warn just because we got lucky?].
When I ran my test suite against GCC's cpp, the first test case only warned. Since this is a legitimate implementation: did I miss something that guarantees that the syntax relaxation dominates knowing that the elif-block is well-formed?
Eric Sosman
More options
Aug 27, 9:26 am
Newsgroups: comp.lang.c
From: Eric Sosman <Eric.Sos...@sun.com>
Date: Wed, 27 Aug 2008 10:26:59 -0400
Local: Wed, Aug 27 2008 9:26 am
Subject: Re: Is it implementation-defined whether this errors?
zaimoni@zaimoni.com wrote: > This is a test case I constructed for a vaporware standalone C99 > preprocessor:
> #if 1 > #elif > #endif
> The text did not permit quickly deciding whether the syntax relaxation > for preprocessing directives in blocks that aren't processed (C99 6.10 > paragraph 4) dominates knowing what an elif-block actually was (C99 > 6.10 paragraph 1). If 6.10 paragraph 4 dominates, this should warn > (as the preprocessor got lucky). If C99 6.10 paragraph 1 dominates, > this should error.
The question boils down to whether #elif by itself is a malformed #elif directive (because there's no expression) or whether it's just a non-directive (because it doesn't parse as a directive). 6.10p3 settles the issue:
"[...] A non-directive shall not begin with any of the directive names appearing in the syntax."
That is, no line beginning with #elif can be a non-directive, so it must be treated as a directive, and since an #elif alone does not match the syntax of any preprocessor directive it's an error.
> The obvious complementary test case
> #if 0 > #elif > #endif
> must error, as the control expression of the #elif is actually > needed.
I see no difference between this example and the first one.
-- Eric.Sos...@sun.com
zaimoni@zaimoni.com
More options
Aug 27, 11:23 am
Newsgroups: comp.lang.c
From: zaimoni@zaimoni.com
Date: Wed, 27 Aug 2008 09:23:20 -0700 (PDT)
Local: Wed, Aug 27 2008 11:23 am
Subject: Re: Is it implementation-defined whether this errors?
On Aug 27, 9:26 am, Eric Sosman <Eric.Sos...@sun.com> wrote:
> zaimoni@zaimoni.com wrote: > > This is a test case I constructed for a vaporware standalone C99 > > preprocessor:
> > #if 1 > > #elif > > #endif
> > The text did not permit quickly deciding whether the syntax relaxation > > for preprocessing directives in blocks that aren't processed (C99 6.10 > > paragraph 4) dominates knowing what an elif-block actually was (C99 > > 6.10 paragraph 1). If 6.10 paragraph 4 dominates, this should warn > > (as the preprocessor got lucky). If C99 6.10 paragraph 1 dominates, > > this should error.
> The question boils down to whether #elif by itself is a malformed > #elif directive (because there's no expression) or whether it's just > a non-directive (because it doesn't parse as a directive). 6.10p3 > settles the issue:
> "[...] A non-directive shall not begin with any of the > directive names appearing in the syntax."
> That is, no line beginning with #elif can be a non-directive, so it > must be treated as a directive, and since an #elif alone does not > match the syntax of any preprocessor directive it's an error.
Yes -- *if* the #elif directive is being preprocessed.
> > The obvious complementary test case
> > #if 0 > > #elif > > #endif
> > must error, as the control expression of the #elif is actually > > needed.
> I see no difference between this example and the first one.
Superficially: Whether the first case's malformed #elif directive is actually being preprocessed (as a top-level construct) is a "this sentence is false" paradox. (If I'm going off-course, this is why.) With the second case, it's a "this sentence is true" non-paradox.
We have to preprocess the #elif directive to determine that there is an elif-block to not preprocess. (I chose to error at that point, then discard the malformed elif-block.) But as the starting line of the not-preprocessed elif-block we're not supposed to preprocess it after all -- which trips the "any tokens allowed" override for blocks that aren't preprocessed.
Eric Sosman
More options
Aug 27, 12:32 pm
Newsgroups: comp.lang.c
From: Eric Sosman <Eric.Sos...@sun.com>
Date: Wed, 27 Aug 2008 13:32:24 -0400
Local: Wed, Aug 27 2008 12:32 pm
Subject: Re: Is it implementation-defined whether this errors?
zaimoni@zaimoni.com wrote: > On Aug 27, 9:26 am, Eric Sosman <Eric.Sos...@sun.com> wrote: >> zaimoni@zaimoni.com wrote: >>> This is a test case I constructed for a vaporware standalone C99 >>> preprocessor: >>> #if 1 >>> #elif >>> #endif >>> The text did not permit quickly deciding whether the syntax relaxation >>> for preprocessing directives in blocks that aren't processed (C99 6.10 >>> paragraph 4) dominates knowing what an elif-block actually was (C99 >>> 6.10 paragraph 1). If 6.10 paragraph 4 dominates, this should warn >>> (as the preprocessor got lucky). If C99 6.10 paragraph 1 dominates, >>> this should error. >> The question boils down to whether #elif by itself is a malformed >> #elif directive (because there's no expression) or whether it's just >> a non-directive (because it doesn't parse as a directive). 6.10p3 >> settles the issue:
>> "[...] A non-directive shall not begin with any of the >> directive names appearing in the syntax."
>> That is, no line beginning with #elif can be a non-directive, so it >> must be treated as a directive, and since an #elif alone does not >> match the syntax of any preprocessor directive it's an error.
> Yes -- *if* the #elif directive is being preprocessed.
It is a directive, and it is not inside a skipped group, so it is processed. The grammar of 6.10p1 makes it clear that the #elif is not part of the if-group that is included or omitted by the #if, but marks the start of the elif-group that follows the if-group in the same if-section. Thus, 6.10.1p5 does not apply.
>>> The obvious complementary test case >>> #if 0 >>> #elif >>> #endif >>> must error, as the control expression of the #elif is actually >>> needed. >> I see no difference between this example and the first one.
> Superficially: > Whether the first case's malformed #elif directive is actually being > preprocessed (as a top-level construct) is a "this sentence is false" > paradox. (If I'm going off-course, this is why.) With the second > case, it's a "this sentence is true" non-paradox.
I'm also susceptible to going off-course, but you've not yet convinced me that the course and I have become non-proximal ... As I understand the matter, the #elif directive *is* processed, no matter what the value of the controlling expression in the preceding #if or #elif, because the #elif is not part of the group that the preceding directive includes or suppresses.
6.10.1p5 applies to situations like this, which I think is valid C despite its unusual appearance:
#if 0 #if *-*-*-*-*-*-*-* #elif |-|-|-|-|-|-|-| #elif <<<<<-=-=->>>>> #endif you must this old grey head #elif 0 #else #endif
IMHO, the directives in the inner if-section -- fully contained within the if-group of the outer if-section -- are processed only as far as their names, as 6.10.1p5 says. The other four directives are, I think, fully processed regardless of the control expressions' values.
-- Eric.Sos...@sun.com
zaimoni@zaimoni.com
More options
Aug 27, 1:35 pm
Newsgroups: comp.lang.c
From: zaimoni@zaimoni.com
Date: Wed, 27 Aug 2008 11:35:21 -0700 (PDT)
Local: Wed, Aug 27 2008 1:35 pm
Subject: Re: Is it implementation-defined whether this errors?
On Aug 27, 12:32 pm, Eric Sosman <Eric.Sos...@sun.com>
wrote:
> zaimoni@zaimoni.com wrote: > > On Aug 27, 9:26 am, Eric Sosman <Eric.Sos...@sun.com> wrote: > >> zaimoni@zaimoni.com wrote: > >>> This is a test case I constructed for a vaporware standalone C99 > >>> preprocessor: > >>> #if 1 > >>> #elif > >>> #endif > >>> .... > >> That is, no line beginning with #elif can be a non-directive, so it > >> must be treated as a directive, and since an #elif alone does not > >> match the syntax of any preprocessor directive it's an error.
> > Yes -- *if* the #elif directive is being preprocessed.
> It is a directive, and it is not inside a skipped group, so > it is processed. The grammar of 6.10p1 makes it clear that the > #elif is not part of the if-group that is included or omitted by > the #if, but marks the start of the elif-group that follows the > if-group in the same if-section.
Agreed.
> Thus, 6.10.1p5 does not apply.
6.10.1p5 entails the tie-breaker I needed, however.
> >>> The obvious complementary test case > >>> #if 0 > >>> #elif > >>> #endif > >>> must error, as the control expression of the #elif is actually > >>> needed. > >> I see no difference between this example and the first one.
> > Superficially: > > Whether the first case's malformed #elif directive is actually being > > preprocessed (as a top-level construct) is a "this sentence is false" > > paradox. (If I'm going off-course, this is why.) With the second > > case, it's a "this sentence is true" non-paradox.
What I had not noticed: 6.10.1p5 entails that an #elif directive does not suppress itself. This dispels the claimed paradox. (I plausibly overlooked a more direct statement to that effect.)
> .... > 6.10.1p5 applies to situations like this, which I think is > valid C despite its unusual appearance:
I'm certain your following example is valid C.
> #if 0 > #if *-*-*-*-*-*-*-* > #elif |-|-|-|-|-|-|-| > #elif <<<<<-=-=->>>>> > #endif you must this old grey head > #elif 0 > #else > #endif
> IMHO, the directives in the inner if-section -- fully contained within > the if-group of the outer if-section -- are processed only as far as > their names, as 6.10.1p5 says.