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