------- 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

Reply via email to