g++-2.95 rejects cast to void

Bruno Haible haible@ilog.fr
Thu Jun 17 03:21:00 GMT 1999


> 3.2/2 says `an expresion is potentially evaluated unless ...'
> The unless part does not mention casting to void.

In 3.2/2 the term "potentially evaluated" is only defined as an auxiliary
term in order to define the term "used". (That's what I infer from the
nicely HTMLized copy at http://www.cygnus.com/misc/wp/nov97/ .) This term,
in turn, specifies when the linker is justified in emitting error messages
about undefined member functions / conversion operators etc.

Seems to me that 5.2.9 and 5.4 contain all the lawyer language you need:

5.2.9/4:

     Any expression can be explicitly converted  to  type  cv  void.  The
     expression  value  is discarded.  ... The
     lvalue-to-rvalue  (_conv.lval_),  array-to-pointer (_conv.array_), and
     function-to-pointer (_conv.func_) standard conversions are not applied
     to the expression.

5.4/5:

     The conversions performed by
       --a static_cast (_expr.static.cast_),
       ...
     can be performed using the cast notation of explicit type conversion.

> 5.2.9/4 says `any expression can be explicitly converted to cv void,
> The value is discarded'.

Which means, side effects are executed, only the value is discarded [in
contrast to sizeof, which does not evaluate its argument expression].

> In evaluating a reference, the first thing you do is look through
> the reference (5/6). You can't evaluate an expression of incomplete type.

But 5.2.9/4 contains explicit language to skip the lvalue-to-rvalue
conversion, therefore the fact that the type is incomplete does not matter.

> So shouldn't `(void)x' behave the same regardless of whether `x' is plain
> `foobar' or `foobar &'?

Yes it should behave the same way. That's also what `static_cast<void>(x)'
does. One more test:

===============================================
struct foobar;
extern foobar y;

void bar (foobar& x)
{
  static_cast<void>(x);   // ok
  static_cast<void>(y);   // ok
  (void)x;                // error message, should be no error
  (void)y;                // error message, should be no error
  x;                      // error message, fine
  y;                      // error message, fine
}
===============================================

> What about the following?
> 
> struct foobar;
> extern foobar obj;
> extern foobar &ref; // no initialization needed here
> ...
> (void)obj; // not valid
> (void)ref; // valid or not?

Both are valid - it's the lvalue-to-rvalue conversion which is not valid
when the type is incomplete, and this lvalue-to-rvalue conversion is
explicitly turned off by 5.2.9/4.

Bruno


More information about the Gcc-bugs mailing list