// g++ 1.37.1 bug 900428_01

// g++ fails to issue error messages for cases where an incomplete type
// object must be evaluated if the value of such an evaluation is not
// actually used in the given context.

// In the case where such an object is volatile, it is obvious that this
// could be a problem, however I believe that errors should be issued
// for such cases regardless of whether or not such values are volatile
// because the abstract semantics seem to require the evaluation of such
// values whether they are volatile or not.

// [expr.static.cast/4, stmt.expr/1, expr.comma/1] show that expressions do
// not under go lvalue to rvalue decay, unless the value is actually used.
// This can be surprising when the object is volatile. We interpret a
// dereference of pointer to volatile to be a read.

// keywords: incomplete types, evaluation, volatile qualifier
// Build don't link: 

int *ip_fn ();
int &ir_fn ();
volatile int *vip_fn ();
volatile int &vir_fn ();

void int_test (int i, int *p, volatile int *vp, int &r, volatile int &vr)
{
  int j;
  volatile int vj;
  
  *p;				// ok, no warning
  (void)*p;			// ok, no warning
  (void)(i ? j : *p);	        // ok, no warning
  (void)(i ? *p : j);	        // ok, no warning
  (void)((void)1, *p);	        // ok, no warning

  *vp;				// ok, no warning
  (void)*vp;			// ok, no warning
  (void)(i ? vj : *vp);	        // ok, no warning
  (void)(i ? *vp : vj);	        // ok, no warning
  (void)((void)1, *vp);         // ok, no warning

  r;				// ok, no warning
  (void)r;			// ok, no warning
  (void)(i ? j : r);	        // ok, no warning
  (void)(i ? r : j);	        // ok, no warning
  (void)((void)1, r);	        // ok, no warning

  vr;				// WARNING - reference not accessed
  (void)vr;			// WARNING - reference not accessed
  (void)(i ? vj : vr);	        // WARNING - reference not accessed
  (void)(i ? vr : vj);	        // WARNING - reference not accessed
  (void)((void)1, vr);          // WARNING - reference not accessed
  
  *ip_fn ();			// ok, no warning
  *vip_fn ();			// ok, no warning
  ir_fn ();			// ok, no warning
  vir_fn ();			// WARNING - reference not accessed
}

struct S;
S *sp_fn ();
S &sr_fn ();
volatile S *vsp_fn ();
volatile S &vsr_fn ();

void incomplete_test (int i, S *p, volatile S *vp, S &r, volatile S &vr)
{
  extern S j;
  extern volatile S vj;
  
  *p;				// ok, no warning
  (void)*p;			// ok, no warning
  (void)(i ? j : *p);	        // ok, no warning
  (void)(i ? *p : j);	        // ok, no warning
  (void)((void)1, *p);	        // ok, no warning

  *vp;				// WARNING - incomplete not accessed
  (void)*vp;			// WARNING - incomplete not accessed
  (void)(i ? vj : *vp);	        // WARNING - incomplete not accessed
  (void)(i ? *vp : vj);	        // WARNING - incomplete not accessed
  (void)((void)1, *vp);         // WARNING - incomplete not accessed

  r;				// ok, no warning
  (void)r;			// ok, no warning
  (void)(i ? j : r);	        // ok, no warning
  (void)(i ? r : j);	        // ok, no warning
  (void)((void)1, r);	        // ok, no warning

  vr;				// WARNING - reference not accessed
  (void)vr;			// WARNING - reference not accessed
  (void)(i ? vj : vr);	        // WARNING - reference not accessed
  (void)(i ? vr : vj);	        // WARNING - reference not accessed
  (void)((void)1, vr);          // WARNING - reference not accessed
  
  *sp_fn ();			// ok, no warning
  *vsp_fn ();			// WARNING - incomplete not accessed
  sr_fn ();			// ok, no warning
  vsr_fn ();			// WARNING - reference not accessed
}

struct T {int m;};
T *tp_fn ();
T &tr_fn ();
volatile T *vtp_fn ();
volatile T &vtr_fn ();

void complete_test (int i, T *p, volatile T *vp, T &r, volatile T &vr)
{
  T j;
  volatile T vj;
  
  *p;				// ok, no warning
  (void)*p;			// ok, no warning
  (void)(i ? j : *p);	        // ok, no warning
  (void)(i ? *p : j);	        // ok, no warning
  (void)((void)1, *p);	        // ok, no warning

  *vp;				// ok, no warning
  (void)*vp;			// ok, no warning
  (void)(i ? vj : *vp);	        // ok, no warning
  (void)(i ? *vp : vj);	        // ok, no warning
  (void)((void)1, *vp);         // ok, no warning

  r;				// ok, no warning
  (void)r;			// ok, no warning
  (void)(i ? j : r);	        // ok, no warning
  (void)(i ? r : j);	        // ok, no warning
  (void)((void)1, r);	        // ok, no warning

  vr;				// WARNING - reference not accessed
  (void)vr;			// WARNING - reference not accessed
  (void)(i ? vj : vr);	        // WARNING - reference not accessed
  (void)(i ? vr : vj);	        // WARNING - reference not accessed
  (void)((void)1, vr);          // WARNING - reference not accessed
  
  *tp_fn ();			// ok, no warning
  *vtp_fn ();			// ok, no warning
  tr_fn ();			// ok, no warning
  vtr_fn ();			// ok, no warningWARNING - reference not accessed
}

void extern_test ()
{
  extern S es;
  extern volatile S ves;
  extern T et;
  extern volatile T vet;
  
  extern S &esr;
  extern volatile S &vesr;
  extern T &etr;
  extern volatile T &vetr;
  
  es;				// ok, no warning
  ves;				// WARNING - incomplete not accessed
  et;				// ok, no warning
  vet;				// ok, no warning
  
  esr;				// ok, no warning
  vesr;				// WARNING - incomplete not accessed
  etr;				// ok, no warning
  vetr;				// WARNING - reference not accessed
}
