It doesn't seem to be, according to the wording of the standard:
#define FOO sizeof(void *)
#ifdef FOO
#elif FOO /* expanded and evaluated - compile error? */
#endif
C99 6.10.1p2 indicate that #if and #elif evaluate their controlling
integer constant expressions. Nothing in 6.10.1p3 or elsewhere
seems to exclude #elif expressions whose values will not be used.
On the other hand, FOO in "#if FOO" is not evaluated here:
#define FOO sizeof(void *)
#ifdef FOO
#else
# if FOO /* not expanded */
# endif
#endif
but the reasons don't help #elif FOO:
6.10p7 says macros are not expanded unless stated, but 6.10.1p2 does
state it. 6.10p4/6.10.1p5 relax the rules for skipped groups, but
a "group" in the syntax are the text lines between #if/#elif/#endif,
not those statements themselves.
Encountered in the upcoming gcc 4.4. The #else-#if-#endif workaround
is easy enough, but I wonder if that's intented.
--
Hallvard
I understand your question, but how much sense does it make to test #if FOO
in the #else or #elif block where you know FOO is not defined ? I guess the
example is made up for illustration of the issue.
--
Chqrlie.
> Is #elif supposed to be equivalent to #else - #if ... #endif?
It is and you're right that the standard is completely silent
on this issue. Now that you have pointed it out I cannot
believe I did not notice years ago.
Yup. It started out differently, then everything irrelevant
disappeared as I wrote. Here is another:
#undef FOO
#ifndef FOO
#define FOO sizeof(void *)
#elif FOO
#endif
--
Hallvard
lcc-win reports an error in that example (line 4). It should be:
1 #undef FOO
2 #ifndef FOO
3 #define FOO sizeof(void *)
4 #elif defined(FOO)
5 #endif
With that change lcc-win reports nothing, as I think it should be.
Ignoring the standard, common sense dictates that
#ifndef FOO
// Since FOO is not defined this branch of the if will be
// passed through
#elif
This will never pass through since the if branch has already succeeded
#endif
--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.cs.virginia.edu/~lcc-win32
No, it should be "#elif FOO". Your modified version doesn't
illustrate the issue, which is the whole point here. We're not trying
to write useful code, we're trying to write code that explores how the
preprocessor behaves in this particular case.
> With that change lcc-win reports nothing, as I think it should be.
Agreed, but not particularly relevant.
> Ignoring the standard, common sense dictates that
>
> #ifndef FOO
> // Since FOO is not defined this branch of the if will be
> // passed through
> #elif
> This will never pass through since the if branch has already succeeded
> #endif
It's a bit odd to use the phrase "Ignoring the standard" in
comp.std.c. If your point is that the standard should be revised to
reflect common sense, I agree (at least in this case).
--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Excuse me but #if (and #elif) need a constant expression isn't it?
Not just a naked identifier.
Or are you confusing it with #ifdef ???
>> With that change lcc-win reports nothing, as I think it should be.
>
> Agreed, but not particularly relevant.
>
>> Ignoring the standard, common sense dictates that
>>
>> #ifndef FOO
>> // Since FOO is not defined this branch of the if will be
>> // passed through
>> #elif
>> This will never pass through since the if branch has already succeeded
>> #endif
>
> It's a bit odd to use the phrase "Ignoring the standard" in
> comp.std.c. If your point is that the standard should be revised to
> reflect common sense, I agree (at least in this case).
>
Obviously common sense is a higher standard, and the C standard should
follow THAT one :-)
Yes.
> Not just a naked identifier.
A "naked identifier" - an undefined macro - evaluates to 0 in #if/#elif.
--
Hallvard
Mmmm lcc-win's preprocessor doesn't treat FOO as an
identifier but as "sizeof(void)" or whatever... Hence the
error.
I see the problem now, it was unclear before.
Thanks
The example under discussion is:
#undef FOO
#ifndef FOO
#define FOO sizeof(void *)
#elif FOO
#endif
If the controlling expression of the #elif is evaluated, FOO will be
macro replaced with sizeof(void *) which will then be expanded by the
"all remaining identifiers are replaced with 0" rule to 0(0 *), which
is, of course, a syntax error. However, I am reasonably sure the intent
was that the controlling expression *not* be evaluated in this case
(i.e., once a group is processed, all remaing groups are skipped). I've
noted that we need to add semantics for #elif to the standard (and am
amazed that no one has noticed the oversight until now).
--
Larry Jones
You know how Einstein got bad grades as a kid? Well MINE are even WORSE!
-- Calvin
> The example under discussion is:
>
> #undef FOO
> #ifndef FOO
> #define FOO sizeof(void *)
> #elif FOO
> #endif
>
> If the controlling expression of the #elif is evaluated, FOO will be
> macro replaced with sizeof(void *) which will then be expanded by the
> "all remaining identifiers are replaced with 0" rule to 0(0 *), which
> is, of course, a syntax error. However, I am reasonably sure the intent
> was that the controlling expression *not* be evaluated in this case
> (i.e., once a group is processed, all remaing groups are skipped). I've
> noted that we need to add semantics for #elif to the standard (and am
> amazed that no one has noticed the oversight until now).
I agree with thi analysis, but disagree with you and Derek that the
semantics
of the #elif are not defined in the standard. The normative text of
the standard
mentions #elif everywhere it mentions #if, so they are just as defined
as each
other.
The preprocessor syntax is given in 6.10, the violation of which
requires a
diagnostic. 6.10.1p6 gives circumstances under which the syntax
is relaxed, and the case under discussion here does not fall under
them because the #elif is not part of a group controlled by a false
condition, again referring to the grammar in 6.10 for what is a
controlled group.
Indeed, the reason GCC behaviour changed here is my writing grammar
and semantic tests for my own front end. I noticed GCC failed this
one
and submitted a bug report.
Now whether these semantics are desirable or intended is a different
question, but I believe the standard as-written is unambigous that the
example here requires a diagnostic.
Neil.