How can I use the result of a void expression? :p

imac:Desktop keith$ cat > conditionalvoid.c
extern void foo();
extern void bar();
void baz(int c) {
  c ? foo() : bar();
}
imac:Desktop keith$ gcc -fsyntax-only -Wall -Wextra conditionalvoid.c
imac:Desktop keith$ clang -fsyntax-only conditionalvoid.c
conditionalvoid.c:4:3: warning: expression result unused
  c ? foo() : bar();
  ^~~~~~~~~~~~~~~~~
1 diagnostic generated.

( ?: on void is perfectly legal according to C99 6.5.15 )

-Keith

Here's a patch for this.

-Keith

cond-side-effect.diff (617 Bytes)

imac:Desktop keith$ cat > conditionalvoid.c
extern void foo();
extern void bar();
void baz(int c) {
  c ? foo() : bar();
}
imac:Desktop keith$ gcc -fsyntax-only -Wall -Wextra conditionalvoid.c
imac:Desktop keith$ clang -fsyntax-only conditionalvoid.c
conditionalvoid.c:4:3: warning: expression result unused
  c ? foo() : bar();
  ^~~~~~~~~~~~~~~~~
1 diagnostic generated.

Yep, that's a bug, but not because ?: has side effects. It is because that warning should never be emitted for a void expression, patch here:
http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20070820/001680.html

( ?: on void is perfectly legal according to C99 6.5.15 )

Sure. Warnings are for code that is legal but questionable :slight_smile:

Thanks,

-Chris

Yep, that's a bug, but not because ?: has side effects. It is
because that warning should never be emitted for a void expression,
patch here:
http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-
Mon-20070820/001680.html

I think my patch is still necessary:

int r(void);
void foo(int f)
{
    f ? r() : r() + r();
}
imac:Desktop keith$ gcc -fsyntax-only -Wall -Wextra side-effect-test.c
imac:Desktop keith$ clang -fsyntax-only side-effect-test.c
side-effect-test.c:4:5: warning: expression result unused
    f ? r() : r() + r();
    ^~~~~~~~~~~~~~~~~~~
1 diagnostic generated.

( replacing + with , makes more sense but then my patch still isn't
sufficient :wink: )

Maybe the warning should never be emitted for expressions returning
void, but that's more of a consequence that a void expression should
always have a side effect than the underlying reason not to emit the
warning...

-Keith

Keith Bauer wrote:-

> Yep, that's a bug, but not because ?: has side effects. It is
> because that warning should never be emitted for a void expression,
> patch here:
> http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-
> Mon-20070820/001680.html

I think my patch is still necessary:

int r(void);
void foo(int f)
{
    f ? r() : r() + r();
}
imac:Desktop keith$ gcc -fsyntax-only -Wall -Wextra side-effect-test.c
imac:Desktop keith$ clang -fsyntax-only side-effect-test.c
side-effect-test.c:4:5: warning: expression result unused
    f ? r() : r() + r();
    ^~~~~~~~~~~~~~~~~~~
1 diagnostic generated.

( replacing + with , makes more sense but then my patch still isn't
sufficient :wink: )

Maybe the warning should never be emitted for expressions returning
void, but that's more of a consequence that a void expression should
always have a side effect than the underlying reason not to emit the
warning...

Though it's most likely a separate issue, for the above testcase,

  f ? r() : r() + r();
            ~~~ ^ ~~~

"unused operation" would be more appropriate I suspect.

Neil.

Aren't both correct? In this case ?: is an operator returning int, and you're ignoring the returned value. If you don't want this value, why not just use an if statement?

Keith, I'm saying that I think you *should* get a warning for your ?: line :slight_smile:

-Chris

My point is that in my mind, the warning is there to tell the
programmer that they've probably done something stupid. In the case
of an expression without side effects, that's clearly the case
(whether the result is void or not). Even in the situation where the
expression is nonvoid, if it has side effects, it's probably still
doing what I want.

Since the spec allows ?: to work on void, it's obviously intended that
it can be used as syntactic shorthand for an if statement. Why
shouldn't it be usable for expressions which happen to be nonvoid, but
where the side-effect is the more important part - printf/fprintf for
example?

Anyway, obviously, you're the ones with commit access, so you get to
make the final decision :wink:

-Keith

My point is that in my mind, the warning is there to tell the
programmer that they've probably done something stupid.

Yep.

In the case of an expression without side effects, that's clearly the case
(whether the result is void or not). Even in the situation where the
expression is nonvoid, if it has side effects, it's probably still
doing what I want.

Yes. This is why we don't warn for things like:

int x;
++x; // returns int
printf("foo"); // returns int

etc. However, we do warn for useless computation like:

(x);
+x;
printf("foo")+printf("foo");

etc.

We don't warn for operators that have side effects. ?: does not have a side effect, so we warn for it.

Similar to your use of ?:, we warn for:

foo() || bar();

because || does not have a side effect. Note that C is not perl, just like C is not ML :). If you want to use conditional code, using an if statement is a perfectly reasonable thing to do.

Since the spec allows ?: to work on void, it's obviously intended that
it can be used as syntactic shorthand for an if statement. Why
shouldn't it be usable for expressions which happen to be nonvoid, but
where the side-effect is the more important part - printf/fprintf for
example?

I'm not really sure what to say here. What the spec says is not the issue. Warnings, again, are for valid code - erroneous code is rejected by the compiler. Except for a couple of strange things, the standard has nothing to say about warnings.

-Chris