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.  */

Reply via email to