This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c++/35548] g++ 4.3.{0,1} miscompile this simple program
- From: "varg at theor dot jinr dot ru" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 13 Mar 2008 06:42:57 -0000
- Subject: [Bug c++/35548] g++ 4.3.{0,1} miscompile this simple program
- References: <bug-35548-12910@http.gcc.gnu.org/bugzilla/>
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
------- Comment #2 from varg at theor dot jinr dot ru 2008-03-13 06:42 -------
Richard Guenther wrote:
> the object compare is invoked on is not properly initialized (its _vptr is
> NULL).
Not exactly. The object (or rather, the pointer managed by that objects) gets
deleted too early.
> Please try to simplify the test program.
template <class T> class ptr
{
T* p;
public:
ptr(T* t) throw() : p(t)
{
p->set_refcount(1);
}
explicit ptr(T& t) throw() : p(&t)
{
p->add_reference();
}
ptr(const ptr& other) throw() : p(other.p)
{
p->add_reference();
}
~ptr()
{
if (p->remove_reference() == 0)
delete p;
}
ptr& operator=(const ptr& other)
{
T* otherp = other.p;
otherp->add_reference();
if (p->remove_reference() == 0)
delete p;
p = otherp;
return *this;
}
T& operator*() const throw()
{
return *p;
}
T* operator->() const throw()
{
return p;
}
};
class refcounted
{
public:
refcounted() throw() : refcount(0) { }
unsigned add_reference() throw()
{
return ++refcount;
}
unsigned remove_reference() throw()
{
return --refcount;
}
unsigned get_refcount() const throw()
{
return refcount;
}
void set_refcount(unsigned r) throw()
{
refcount = r;
}
private:
unsigned refcount;
};
class ex;
enum status_flags {
dynallocated = 1,
evaluated = 2
};
class basic : public refcounted
{
public:
basic() : flags(0) { }
basic(const basic& other) : flags(other.flags & ~dynallocated) { }
virtual basic* duplicate() const
{
return new basic(*this);
}
virtual ex eval() const;
const basic& hold() const
{
flags |= evaluated;
return *this;
}
virtual ~basic() { }
protected:
mutable unsigned flags;
private:
friend class ex;
};
class ex {
private:
mutable ptr<basic> bp;
static ptr<basic> construct_from_basic(const basic& other)
{
if (!(other.flags & evaluated)) {
const ex& tmpex = other.eval();
if ((other.get_refcount() == 0) && (other.flags &
dynallocated))
delete &other;
return tmpex.bp;
} else {
if (other.flags & dynallocated) {
return ptr<basic>(const_cast<basic &>(other));
} else {
basic* bp = other.duplicate();
bp->flags |= dynallocated;
return bp;
}
}
}
public:
ex(const basic& other) : bp(construct_from_basic(other)) { }
ex eval() const
{
return bp->eval();
}
};
ex basic::eval() const
{
return hold();
}
class oops : public basic
{
public:
oops() { }
oops* duplicate() const
{
return new oops(*this);
}
ex eval() const
{
return oops().hold();
}
};
int main(int argc, char** argv)
{
const ex e = oops().hold();
const ex& f = argc > 1 ? e : e.eval();
const ex& g = f.eval();
return 0;
}
--
varg at theor dot jinr dot ru changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |varg at theor dot jinr dot
| |ru
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35548