This adds quick_emplace_push and safe_emplace_push to vec.
These are like std::vector's emplace_back so you don't need an extra
copy of the struct around.

Since we require C++11 and also support partial non-PODs for vec, these 
functions
can be added.

I will be using them to cleanup some code and even improving how some places
use vec.

Bootstrapped and tested on x86_64-linux-gnu.

gcc/ChangeLog:

        * vec.h (vec<T,vl_embed>::quick_emplace_push): New function.
        (vec<T,vl_ptr>::quick_emplace_push): New function.
        (vec<T,vl_ptr>::safe_emplace_push): New function.
        * vec.cc (test_init): Add test for safe_emplace_push.
        (test_quick_emplace_push): New function.
        (test_safe_emplace_push): New function.
        (vec_cc_tests): Call test_quick_emplace_push and
        test_safe_emplace_push.

Signed-off-by: Andrew Pinski <quic_apin...@quicinc.com>
---
 gcc/vec.cc | 41 +++++++++++++++++++++++++++++++++++++++++
 gcc/vec.h  | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 87 insertions(+)

diff --git a/gcc/vec.cc b/gcc/vec.cc
index ba963b96c6a..cd7cd3c156b 100644
--- a/gcc/vec.cc
+++ b/gcc/vec.cc
@@ -304,6 +304,10 @@ test_init ()
 
     ASSERT_EQ (2, v1.length ());
     ASSERT_EQ (2, v2.length ());
+    v2.safe_emplace_push (1);
+
+    ASSERT_EQ (3, v1.length ());
+    ASSERT_EQ (3, v2.length ());
     v1.release ();
   }
 }
@@ -327,6 +331,25 @@ test_quick_push ()
   ASSERT_EQ (7, v[2]);
 }
 
+/* Verify that vec::quick_emplace_push works correctly.  */
+
+static void
+test_quick_emplace_push ()
+{
+  auto_vec <std::pair<int,int>> v;
+  ASSERT_EQ (0, v.length ());
+  v.reserve (3);
+  ASSERT_EQ (0, v.length ());
+  ASSERT_TRUE (v.space (3));
+  v.quick_emplace_push (5, 5);
+  v.quick_emplace_push (6, 6);
+  v.quick_emplace_push (7, 7);
+  ASSERT_EQ (3, v.length ());
+  ASSERT_EQ (std::make_pair(5,5), v[0]);
+  ASSERT_EQ (std::make_pair(6,6), v[1]);
+  ASSERT_EQ (std::make_pair(7,7), v[2]);
+}
+
 /* Verify that vec::safe_push works correctly.  */
 
 static void
@@ -343,6 +366,22 @@ test_safe_push ()
   ASSERT_EQ (7, v[2]);
 }
 
+/* Verify that vec::safe_emplace_push works correctly.  */
+
+static void
+test_safe_emplace_push ()
+{
+  auto_vec <std::pair<int,int>> v;
+  ASSERT_EQ (0, v.length ());
+  v.safe_emplace_push (5, 5);
+  v.safe_emplace_push (6, 6);
+  v.safe_emplace_push (7, 7);
+  ASSERT_EQ (3, v.length ());
+  ASSERT_EQ (std::make_pair(5,5), v[0]);
+  ASSERT_EQ (std::make_pair(6,6), v[1]);
+  ASSERT_EQ (std::make_pair(7,7), v[2]);
+}
+
 /* Verify that vec::truncate works correctly.  */
 
 static void
@@ -591,7 +630,9 @@ vec_cc_tests ()
 {
   test_init ();
   test_quick_push ();
+  test_quick_emplace_push ();
   test_safe_push ();
+  test_safe_emplace_push ();
   test_truncate ();
   test_safe_grow_cleared ();
   test_pop ();
diff --git a/gcc/vec.h b/gcc/vec.h
index b13c4716428..8277d156f05 100644
--- a/gcc/vec.h
+++ b/gcc/vec.h
@@ -619,6 +619,8 @@ public:
   void splice (const vec &);
   void splice (const vec *src);
   T *quick_push (const T &);
+  template <typename ...Args>
+  T *quick_emplace_push (Args&&... args);
   using pop_ret_type
     = typename std::conditional <std::is_trivially_destructible <T>::value,
                                 T &, void>::type;
@@ -1044,6 +1046,21 @@ vec<T, A, vl_embed>::quick_push (const T &obj)
   return slot;
 }
 
+/* Push T(ARGS) (a new element) onto the end of the vector.  There must be
+   sufficient space in the vector.  Return a pointer to the slot
+   where T(ARGS) was inserted.  */
+
+template<typename T, typename A>
+template<typename ...Args>
+inline T *
+vec<T, A, vl_embed>::quick_emplace_push (Args&&... args)
+{
+  gcc_checking_assert (space (1));
+  T *slot = &address ()[m_vecpfx.m_num++];
+  ::new (static_cast<void*>(slot)) T (std::forward<Args>(args)...);
+  return slot;
+}
+
 
 /* Pop and return a reference to the last element off the end of the
    vector.  If T has non-trivial destructor, this method just pops
@@ -1612,7 +1629,11 @@ public:
   void splice (const vec &);
   void safe_splice (const vec & CXX_MEM_STAT_INFO);
   T *quick_push (const T &);
+  template <typename ...Args>
+  T *quick_emplace_push (Args&&... args);
   T *safe_push (const T &CXX_MEM_STAT_INFO);
+  template <typename ...Args>
+  T *safe_emplace_push (Args&&... args CXX_MEM_STAT_INFO);
   using pop_ret_type
     = typename std::conditional <std::is_trivially_destructible <T>::value,
                                 T &, void>::type;
@@ -2070,6 +2091,18 @@ vec<T, va_heap, vl_ptr>::quick_push (const T &obj)
   return m_vec->quick_push (obj);
 }
 
+/* Push OBJ (a new element) onto the end of the vector.  There must be
+   sufficient space in the vector.  Return a pointer to the slot
+   where OBJ was inserted.  */
+
+template<typename T>
+template <typename ...Args>
+inline T *
+vec<T, va_heap, vl_ptr>::quick_emplace_push (Args&& ... args)
+{
+  return m_vec->quick_emplace_push (std::forward<Args>(args)...);
+}
+
 
 /* Push a new element OBJ onto the end of this vector.  Reallocates
    the embedded vector, if needed.  Return a pointer to the slot where
@@ -2083,6 +2116,19 @@ vec<T, va_heap, vl_ptr>::safe_push (const T &obj 
MEM_STAT_DECL)
   return quick_push (obj);
 }
 
+/* Push a new element T(ARGS) onto the end of this vector.  Reallocates
+   the embedded vector, if needed.  Return a pointer to the slot where
+   OBJ was inserted.  */
+
+template<typename T>
+template <typename ...Args>
+inline T *
+vec<T, va_heap, vl_ptr>::safe_emplace_push (Args&&... args MEM_STAT_DECL)
+{
+  reserve (1, false PASS_MEM_STAT);
+  return quick_emplace_push (std::forward<Args>(args)...);
+}
+
 
 /* Pop and return a reference to the last element off the end of the
    vector.  If T has non-trivial destructor, this method just pops
-- 
2.43.0

Reply via email to