mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-01 20:21:12 +08:00
libcc1: use variadic templates for "call"
This changes libcc1 to use variadic templates for the "call" functions. The primary benefit is that this simplifies the code. libcc1 * rpc.hh (call): Use variadic template. Remove overloads. * marshall.hh (marshall): Add base overload. Use variadic template.
This commit is contained in:
parent
c10a3b13fe
commit
dc6be7c022
@ -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
|
||||
|
168
libcc1/rpc.hh
168
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)>
|
||||
|
Loading…
x
Reference in New Issue
Block a user