jacob navia wrote:
> Hi the experts!
>
> lccwin rejects this construct:
>
> #define assert(e) \
> ((void) ((e) ? 0 : __assert (#e, __FILE__, __LINE__)))
> #define __assert(e, file, line) \
> ((void)printf ("%s:%u: failed assertion `%s'\n", file, line, e),
> abort())
>
> lccwin reports
> deque.c: 118 operands of ?: have illegal types 'int' and 'void'
>
> The problem is that the two sides of the ? expression do not have the
> same type: the left hand side is zero, (int) and the right side is (void)
You can avoid the problem by using either (but not both!) of the
following two changes:
#define assert(e) \
(((e) ? (void)0 : __assert (#e, __FILE__, __LINE__)))
or
#define __assert(e, file, line) \
(printf ("%s:%u: failed assertion `%s'\n", file, line, e),
abort())
I prefer the second approach, if feasible, but whether or not it's
feasible depends upon whether or not you ever intend to use __assert()
directly, and if so, whether it would be in a context where it would
be a problem for it to expand into an expression with the type 'int'.
Note: C99 requires that the message printed by a failed assertion
should include the name of the enclosing function. The standard points
out that this name is the same as the value of __func__, which is new
in C99. However, it would have been perfectly feasible for C90 to have
imposed the same requirement without mentioning __func__; I have no
idea whether or not it actually did so. Is this meant to conform to
C99, or c90 (or neither)?
> gcc accepts that without any problem or warning.
Like almost all real-world compilers, gcc doesn't fully conform to any
C standard in its default mode, which is fine, since it does not claim
to be conforming in that mode. Adding the -pedantic option is
sufficient to turn on this mandatory diagnostic.
> Who is right?
6.5.15p3 lists the constraints on the types of the second and third
operands of the conditional operator. The combination (int, void)
doesn't fit any of the options listed in that section, so a conforming
implementation of C is required to generate a diagnostic, and is
permitted to reject such code.
gcc with no special options compiles GNU C, where the rules are
different; I don't know much about GNU C, but I would presume that gcc
handles this case correctly for that language.
gcc requires a minimum of -pedantic, and either -ansi or -std=c90 to
conform to C90, or -std=C99 to conform to C99. I don't remember
whether any of the additional -W options I normally turn on are also
required for conformance. I'd strongly recommend at least -Wall, even
if not needed for conformance.
gcc -pedantic and lccwin32 both print out the required diagnostic, so
both are correct.