#elif <unused> always evaluated?

#elif <unused> always evaluated?

Post by Hallvard B » Thu, 20 Nov 2008 02:05:47


Is #elif supposed to be equivalent to #else - #if ... #endif?

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
 
 
 

#elif <unused> always evaluated?

Post by Charlie Go » Thu, 20 Nov 2008 02:19:06

"Hallvard B Furuseth" < XXXX@XXXXX.COM > a rit dans le message de


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.

 
 
 

#elif <unused> always evaluated?

Post by Derek M. J » Thu, 20 Nov 2008 02:39:44

Hallvard,


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.
 
 
 

#elif <unused> always evaluated?

Post by Hallvard B » Thu, 20 Nov 2008 03:23:00

Charlie Gordon writes:

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
 
 
 

#elif <unused> always evaluated?

Post by jacob navi » Thu, 20 Nov 2008 03:39:17


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.yqcomputer.com/ . *** ia.edu/~lcc-win32
 
 
 

#elif <unused> always evaluated?

Post by Keith Thom » Thu, 20 Nov 2008 04:25:01

jacob navia < XXXX@XXXXX.COM > writes:


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.


Agreed, but not particularly relevant.


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) XXXX@XXXXX.COM < http://www.yqcomputer.com/ ~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
 
 

#elif <unused> always evaluated?

Post by jacob navi » Thu, 20 Nov 2008 07:12:45


Excuse me but #if (and #elif) need a constant expression isn't it?
Not just a *** identifier.

Or are you confusing it with #ifdef ???



Obviously common sense is a higher standard, and the C standard should
follow THAT one :-)


--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.yqcomputer.com/ . *** ia.edu/~lcc-win32
 
 
 

#elif <unused> always evaluated?

Post by Hallvard B » Thu, 20 Nov 2008 07:19:04

jacob navia writes:

Yes.


A " *** identifier" - an undefined macro - evaluates to 0 in #if/#elif.

--
Hallvard
 
 
 

#elif <unused> always evaluated?

Post by jacob navi » Thu, 20 Nov 2008 07:29:07


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

--
jacob navia
jacob at jacob point remcomp point fr
logiciels/informatique
http://www.yqcomputer.com/ . *** ia.edu/~lcc-win32
 
 
 

#elif <unused> always evaluated?

Post by lawrence.j » Thu, 20 Nov 2008 23:26:42


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
 
 
 

#elif <unused> always evaluated?

Post by kyuup » Tue, 25 Nov 2008 13:53:48


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.