https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113476
--- Comment #8 from Aldy Hernandez <aldyh at gcc dot gnu.org> --- (In reply to Richard Biener from comment #5) > (In reply to Martin Jambor from comment #4) > > The right place where to free stuff in lattices post-IPA would be in > > ipa_node_params::~ipa_node_params() where we should iterate over lattices > > and deinitialize them or perhaps destruct the array because since > > ipcp_vr_lattice directly contains Value_Range which AFAIU directly contains > > int_range_max which has a virtual destructor... does not look like a POD > > anymore. This has escaped me when I was looking at the IPA-VR changes but > > hopefully it should not be too difficult to deal with. > > OK, that might work for the IPA side. > > It's quite unusual to introduce a virtual DTOR in the middle of the class > hierarchy though. Grepping I do see quite some direct uses of 'irange' > and also 'vrange' which do not have the DTOR visible but 'irange' already > exposes and uses 'maybe_resize'. I think those should only be introduced > in the class exposing the virtual DTOR (but why virtual?!). > > Would be nice to have a picture of the range class hierarchies with > pointers on which types to use in which circumstances ... For reference, you should always use the most base class you can. If you can get the work done with the vrange API, use that. If you're dealing with an integer, use irange. The int_range<> derived class should only be used for defining a variable, so: int_range<123> foobar; // Defined with storage. if (is_a <irange>) { irange &p = as_a <irange> (foobar); ... } // Use an irange reference here, not an int_range reference. void somefunc (const irange &r) { } Also, the reason irange does not have a destructor is because it has no storage. Only int_range<> has storage associated with it, so it is the only one able to see if the range grew: template<unsigned N, bool RESIZABLE> inline int_range<N, RESIZABLE>::~int_range () { if (RESIZABLE && m_base != m_ranges) delete[] m_base; } The irange superclass does not have storage, just the m_base pointer. OTOH, m_ranges[] lives in int_range<>: template<unsigned N, bool RESIZABLE = false> class int_range : public irange { ... private: wide_int m_ranges[N*2]; }; This shouldn't be a problem because you should never be putting a raw irange pointer in a container that you allocate/deallocate. Does this help? If so, I could definitely document it in value-range.h.