[v2,05/21] libcc1: use variadic templates for "call"

Message ID 20210428010119.806184-6-tom@tromey.com
State New
Headers show
Series
  • C++11-based improvements for libcc1
Related show

Commit Message

Tom Tromey April 28, 2021, 1:01 a.m.
This changes libcc1 to use variadic templates for the "call"
functions.  The primary benefit is that this simplifies the code.

libcc1/ChangeLog
2021-04-27  Tom Tromey  <tom@tromey.com>

	* rpc.hh (call): Use variadic template.  Remove overloads.
	* marshall.hh (marshall): Add base overload.  Use variadic
	template.
---
 libcc1/ChangeLog   |   6 ++
 libcc1/marshall.hh |  16 +++++
 libcc1/rpc.hh      | 168 +++------------------------------------------
 3 files changed, 31 insertions(+), 159 deletions(-)

-- 
2.26.2

Comments

Martin Sebor via Gcc-patches April 28, 2021, 6:28 p.m. | #1
On 4/27/2021 7:01 PM, Tom Tromey wrote:
> This changes libcc1 to use variadic templates for the "call"

> functions.  The primary benefit is that this simplifies the code.

>

> libcc1/ChangeLog

> 2021-04-27  Tom Tromey  <tom@tromey.com>

>

> 	* rpc.hh (call): Use variadic template.  Remove overloads.

> 	* marshall.hh (marshall): Add base overload.  Use variadic

> 	template.


OK

jeff

Patch

diff --git a/libcc1/marshall.hh b/libcc1/marshall.hh
index 8d890eb9b6c7..4a28a8fe4ae2 100644
--- a/libcc1/marshall.hh
+++ b/libcc1/marshall.hh
@@ -52,6 +52,14 @@  namespace cc1_plugin
   status unmarshall_array_start (connection *, char, size_t *);
   status unmarshall_array_elmts (connection *, size_t, void *);
 
+  // An "empty" marshall call -- used to handle the base case for some
+  // variadic templates.
+  static inline
+  status marshall (connection *)
+  {
+    return OK;
+  }
+
   // A template function that can handle marshalling various integer
   // objects to the connection.
   template<typename T>
@@ -103,6 +111,14 @@  namespace cc1_plugin
   // resulting array must be freed by the caller, using 'delete[]' on
   // the elements, and 'delete' on the array object itself.
   status unmarshall (connection *, struct gcc_type_array **);
+
+  template<typename T1, typename T2, typename... Arg>
+  status marshall (connection *c, T1 arg1, T2 arg2, Arg... rest)
+  {
+    if (!marshall (c, arg1))
+      return FAIL;
+    return marshall (c, arg2, rest...);
+  }
 };
 
 #endif // CC1_PLUGIN_MARSHALL_HH
diff --git a/libcc1/rpc.hh b/libcc1/rpc.hh
index 429aeb3c1278..a3631cb5d7e2 100644
--- a/libcc1/rpc.hh
+++ b/libcc1/rpc.hh
@@ -232,10 +232,10 @@  namespace cc1_plugin
 #endif /* GCC_CP_INTERFACE_H */
 
   // There are two kinds of template functions here: "call" and
-  // "callback".  They are each repeated multiple times to handle
-  // different numbers of arguments.  (This would be improved with
-  // C++11, though applying a call is still tricky until C++14 can be
-  // used.)
+  // "callback".  "call" is implemented with variadic templates, but
+  // "callback" is repeated multiple times to handle different numbers
+  // of arguments.  (This could be improved with C++17 and
+  // std::apply.)
 
   // The "call" template is used for making a remote procedure call.
   // It starts a query ('Q') packet, marshalls its arguments, waits
@@ -248,15 +248,17 @@  namespace cc1_plugin
   // arguments, passes them to the wrapped function, and finally
   // marshalls a reply packet.
 
-  template<typename R>
+  template<typename R, typename... Arg>
   status
-  call (connection *conn, const char *method, R *result)
+  call (connection *conn, const char *method, R *result, Arg... args)
   {
     if (!conn->send ('Q'))
       return FAIL;
     if (!marshall (conn, method))
       return FAIL;
-    if (!marshall (conn, 0))
+    if (!marshall (conn, (int) sizeof... (Arg)))
+      return FAIL;
+    if (!marshall (conn, args...))
       return FAIL;
     if (!conn->wait_for_result ())
       return FAIL;
@@ -279,25 +281,6 @@  namespace cc1_plugin
     return marshall (conn, result);
   }
 
-  template<typename R, typename A>
-  status
-  call (connection *conn, const char *method, R *result, A arg)
-  {
-    if (!conn->send ('Q'))
-      return FAIL;
-    if (!marshall (conn, method))
-      return FAIL;
-    if (!marshall (conn, 1))
-      return FAIL;
-    if (!marshall (conn, arg))
-      return FAIL;
-    if (!conn->wait_for_result ())
-      return FAIL;
-    if (!unmarshall (conn, result))
-      return FAIL;
-    return OK;
-  }
-
   template<typename R, typename A, R (*func) (connection *, A)>
   status
   callback (connection *conn)
@@ -315,27 +298,6 @@  namespace cc1_plugin
     return marshall (conn, result);
   }
 
-  template<typename R, typename A1, typename A2>
-  status
-  call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2)
-  {
-    if (!conn->send ('Q'))
-      return FAIL;
-    if (!marshall (conn, method))
-      return FAIL;
-    if (!marshall (conn, 2))
-      return FAIL;
-    if (!marshall (conn, arg1))
-      return FAIL;
-    if (!marshall (conn, arg2))
-      return FAIL;
-    if (!conn->wait_for_result ())
-      return FAIL;
-    if (!unmarshall (conn, result))
-      return FAIL;
-    return OK;
-  }
-
   template<typename R, typename A1, typename A2, R (*func) (connection *,
 							    A1, A2)>
   status
@@ -357,30 +319,6 @@  namespace cc1_plugin
     return marshall (conn, result);
   }
 
-  template<typename R, typename A1, typename A2, typename A3>
-  status
-  call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2,
-	A3 arg3)
-  {
-    if (!conn->send ('Q'))
-      return FAIL;
-    if (!marshall (conn, method))
-      return FAIL;
-    if (!marshall (conn, 3))
-      return FAIL;
-    if (!marshall (conn, arg1))
-      return FAIL;
-    if (!marshall (conn, arg2))
-      return FAIL;
-    if (!marshall (conn, arg3))
-      return FAIL;
-    if (!conn->wait_for_result ())
-      return FAIL;
-    if (!unmarshall (conn, result))
-      return FAIL;
-    return OK;
-  }
-
   template<typename R, typename A1, typename A2, typename A3,
 	   R (*func) (connection *, A1, A2, A3)>
   status
@@ -405,32 +343,6 @@  namespace cc1_plugin
     return marshall (conn, result);
   }
 
-  template<typename R, typename A1, typename A2, typename A3, typename A4>
-  status
-  call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2,
-	A3 arg3, A4 arg4)
-  {
-    if (!conn->send ('Q'))
-      return FAIL;
-    if (!marshall (conn, method))
-      return FAIL;
-    if (!marshall (conn, 4))
-      return FAIL;
-    if (!marshall (conn, arg1))
-      return FAIL;
-    if (!marshall (conn, arg2))
-      return FAIL;
-    if (!marshall (conn, arg3))
-      return FAIL;
-    if (!marshall (conn, arg4))
-      return FAIL;
-    if (!conn->wait_for_result ())
-      return FAIL;
-    if (!unmarshall (conn, result))
-      return FAIL;
-    return OK;
-  }
-
   template<typename R, typename A1, typename A2, typename A3, typename A4,
 	   R (*func) (connection *, A1, A2, A3, A4)>
   status
@@ -458,35 +370,6 @@  namespace cc1_plugin
     return marshall (conn, result);
   }
 
-  template<typename R, typename A1, typename A2, typename A3, typename A4,
-	   typename A5>
-  status
-  call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2,
-	A3 arg3, A4 arg4, A5 arg5)
-  {
-    if (!conn->send ('Q'))
-      return FAIL;
-    if (!marshall (conn, method))
-      return FAIL;
-    if (!marshall (conn, 5))
-      return FAIL;
-    if (!marshall (conn, arg1))
-      return FAIL;
-    if (!marshall (conn, arg2))
-      return FAIL;
-    if (!marshall (conn, arg3))
-      return FAIL;
-    if (!marshall (conn, arg4))
-      return FAIL;
-    if (!marshall (conn, arg5))
-      return FAIL;
-    if (!conn->wait_for_result ())
-      return FAIL;
-    if (!unmarshall (conn, result))
-      return FAIL;
-    return OK;
-  }
-
   template<typename R, typename A1, typename A2, typename A3, typename A4,
 	   typename A5, R (*func) (connection *, A1, A2, A3, A4, A5)>
   status
@@ -517,39 +400,6 @@  namespace cc1_plugin
     return marshall (conn, result);
   }
 
-  template<typename R, typename A1, typename A2, typename A3, typename A4,
-	   typename A5, typename A6, typename A7>
-  status
-  call (connection *conn, const char *method, R *result, A1 arg1, A2 arg2,
-	A3 arg3, A4 arg4, A5 arg5, A6 arg6, A7 arg7)
-  {
-    if (!conn->send ('Q'))
-      return FAIL;
-    if (!marshall (conn, method))
-      return FAIL;
-    if (!marshall (conn, 7))
-      return FAIL;
-    if (!marshall (conn, arg1))
-      return FAIL;
-    if (!marshall (conn, arg2))
-      return FAIL;
-    if (!marshall (conn, arg3))
-      return FAIL;
-    if (!marshall (conn, arg4))
-      return FAIL;
-    if (!marshall (conn, arg5))
-      return FAIL;
-    if (!marshall (conn, arg6))
-      return FAIL;
-    if (!marshall (conn, arg7))
-      return FAIL;
-    if (!conn->wait_for_result ())
-      return FAIL;
-    if (!unmarshall (conn, result))
-      return FAIL;
-    return OK;
-  }
-
   template<typename R, typename A1, typename A2, typename A3, typename A4,
 	   typename A5, typename A6, typename A7,
 	   R (*func) (connection *, A1, A2, A3, A4, A5, A6, A7)>