Scarry warning: "this might be used uninitialized"

David Mazieres dm@reeducation-labor.lcs.mit.edu
Sun Sep 20 15:29:00 GMT 1998


Egcs 1.1 (and also egcs-current as of two weeks ago) have a bug that
causes them to report that "this" is uninitialized.

Unfortunately, the bug is kind of finicky.  I can only trigger it
using both an object with an __attribute__ ((noreturn)) destructor and
some nested templates.  The example code to trigger the bug is
therefore somewhat large (~100 lines).  However, I have appended it.
When you compile the attached program, it gives:

% c++ -Wall -Werror -O2 -c this_uninit.C
cc1plus: warnings being treated as errors
this_uninit.C: In function `void getres(int)':
this_uninit.C:71: warning: `struct refcounted<callback0_0<int> > * this' might be used uninitialized in this function
this_uninit.C:17: warning: `class callback0_0<int> * this' might be used uninitialized in this function
this_uninit.C:61: warning: `class callback<int> * this' might be used uninitialized in this function
this_uninit.C:61: warning: `class callback<int> * this' might be used uninitialized in this function
this_uninit.C:17: warning: `class callback0_0<int> * this' might be used uninitialized in this function
this_uninit.C:17: warning: `class callback<int> * this' might be used uninitialized in this function

That error seems to indicate that something is going horribly wrong in
the compiler.

Thanks,
David


===

struct refcount {
  int cnt;
  void refcount_inc () { cnt++; }
  void refcount_dec () { if (!--cnt) delete this; }
  refcount () : cnt (0) {}
  virtual ~refcount () {}
};

template<class T>
struct refcounted
  : virtual public refcount, public T
{
  refcounted () {}
  template<class A1>
  refcounted (const A1 &a1)
    : T (a1) {}
};

template<class T>
struct ptr {
  refcount *c;
  T *p;

  void refcount_inc () const { if (c) c->refcount_inc (); }
  void refcount_dec () const { if (c) c->refcount_dec (); }

  ptr () { c = 0; p = 0; }
  ptr (const ptr &r)
    : c (r), p (r) { refcount_inc (); }
  template<class U> ptr (refcounted<U> *rcp) {
    if (rcp) { c = rcp; p = rcp; refcount_inc (); }
    else { c = 0; p = 0; }
  }
  const ptr &operator= (const ptr &r)
    { r.refcount_inc (); refcount_dec (); c = r.c; p = r.p; return *this; }

  operator T *() const { return p; }
  T *operator-> () const { return p; }
  T &operator* () const { return *p; }
};


template<class R>
class callback {
public:
  typedef ptr<callback<R> > ptr;

  virtual R operator() () = 0;
  virtual ~callback () {}
};

template<class R>
class callback0_0
  : public callback<R> {
  typedef R (*cb_t) ();
  cb_t f;
  callback0_0 ();
public:
  callback0_0 (cb_t ff)
    : f (ff) {}
  R operator() () {
    return f ();
  }
};

template<class R>
static inline refcounted<callback0_0<R> > *
wrap (R (*f) ())
{
  return new (refcounted<callback0_0<R> >) (f);
}


struct dumbobj {
  dumbobj ();
  ~dumbobj ();
};

struct abortobj : dumbobj {
  abortobj () {}
  ~abortobj () __attribute__ ((noreturn));
};

callback<int>::ptr cb;

static int
f ()
{
  return 0;
}

void
getres (int stat)
{
  if (stat)
    abortobj ();
  cb = wrap (&f);
}

abortobj::~abortobj ()
{
  abort ();
}



More information about the Gcc-bugs mailing list