While debugging locations I noticed the semi_embedded_vec template in line-map.h doesn't declare a copy ctor or copy assignment, but is being copied in a couple of places in the C++ parser (via gcc_rich_location). It gets away with it most likely because it never grows beyond the embedded buffer.
The attached patch defines the copy ctor and also copy assignment and adds the corresponding move functions. Tested on x86_64-linux. Martin
libcpp/ChangeLog: * include/line-map.h (class semi_embedded_vec): Add copy ctor and assignment, move ctor and move assignment. diff --git a/libcpp/include/line-map.h b/libcpp/include/line-map.h index 7d964172469..1d6fb0d6b00 100644 --- a/libcpp/include/line-map.h +++ b/libcpp/include/line-map.h @@ -1376,6 +1376,12 @@ class semi_embedded_vec semi_embedded_vec (); ~semi_embedded_vec (); + semi_embedded_vec (const semi_embedded_vec &); + semi_embedded_vec (semi_embedded_vec &&); + + semi_embedded_vec& operator= (const semi_embedded_vec &); + semi_embedded_vec& operator= (semi_embedded_vec &&); + unsigned int count () const { return m_num; } T& operator[] (int idx); const T& operator[] (int idx) const; @@ -1395,8 +1401,89 @@ class semi_embedded_vec template <typename T, int NUM_EMBEDDED> semi_embedded_vec<T, NUM_EMBEDDED>::semi_embedded_vec () -: m_num (0), m_alloc (0), m_extra (NULL) + : m_num (0), m_alloc (0), m_extra (NULL) +{ +} + +/* Copy ctor. */ + +template <typename T, int NUM_EMBEDDED> +semi_embedded_vec<T, NUM_EMBEDDED>:: +semi_embedded_vec (const semi_embedded_vec &rhs) + : m_num (rhs.m_num), m_alloc (rhs.m_alloc) { + int nemb = rhs.m_num < NUM_EMBEDDED ? rhs.m_num : NUM_EMBEDDED; + memcpy (m_embedded, rhs.m_embedded, nemb * sizeof (T)); + + if (!m_extra) + { + m_extra = NULL; + return; + } + + m_extra = XNEWVEC (T, m_alloc); + memcpy (m_extra, rhs.m_extra, m_alloc * sizeof (T)); +} + +/* Move ctor. */ + +template <typename T, int NUM_EMBEDDED> +semi_embedded_vec<T, NUM_EMBEDDED>:: +semi_embedded_vec (semi_embedded_vec &&rhs) + : m_num (rhs.m_num), m_alloc (rhs.m_alloc) +{ + int nemb = rhs.m_num < NUM_EMBEDDED ? rhs.m_num : NUM_EMBEDDED; + memcpy (m_embedded, rhs.m_embedded, nemb * sizeof (T)); + + m_extra = rhs.m_extra; + rhs.m_extra = NULL; +} + +/* Copy assignment. */ + +template <typename T, int NUM_EMBEDDED> +semi_embedded_vec<T, NUM_EMBEDDED>& +semi_embedded_vec<T, NUM_EMBEDDED>::operator= (const semi_embedded_vec &rhs) +{ + int nemb = rhs.m_num < NUM_EMBEDDED ? rhs.m_num : NUM_EMBEDDED; + memcpy (m_embedded, rhs.m_embedded, nemb * sizeof (T)); + + m_num = rhs.m_num; + + if (!rhs.m_extra) + /* Don't release already allocated memory. */ + return *this; + + if (m_alloc < rhs.m_alloc) + { + m_extra = XRESIZEVEC (T, m_extra, rhs.m_alloc); + m_alloc = rhs.m_alloc; + } + + memcpy (m_extra, rhs.m_extra, m_alloc * sizeof (T)); + return *this; +} + +/* Move assignment. */ + +template <typename T, int NUM_EMBEDDED> +semi_embedded_vec<T, NUM_EMBEDDED>& +semi_embedded_vec<T, NUM_EMBEDDED>::operator= (semi_embedded_vec &&rhs) +{ + int nemb = rhs.m_num < NUM_EMBEDDED ? rhs.m_num : NUM_EMBEDDED; + memcpy (m_embedded, rhs.m_embedded, nemb * sizeof (T)); + + m_num = rhs.m_num; + + if (!rhs.m_extra) + /* Don't release already allocated memory. */ + return *this; + + m_extra = rhs.m_extra; + m_alloc = rhs.m_alloc; + + rhs.m_extra = NULL; + return *this; } /* semi_embedded_vec's dtor. Release any dynamically-allocated memory. */