Instead of a va_list here we can create a std::initializer_list that contains 
the
arguments and pass that.
This is just one quick version of what was mentioned during the Reviewing 
refactoring
goals and acceptable abstractions.
The generated code should be similar or slightly better. Plus there is extra 
checking
of bounds of the std::initializer_list.

I didn't remove the n argument from build_call_nary at this stage as I didn't 
want to change
the calls to build_call_nary but I added a gcc_checking_assert to make sure the 
number passed
is the number of arguments.

gcc/ChangeLog:

        * tree.cc (build_call_nary): Remove decl.
        Add template definition that uses std::initializer_list<tree>
        and call build_call.
        (build_call): New declaration.
        * tree.h (build_call_nary): Remove.
        (build_call): New function.

Signed-off-by: Andrew Pinski <[email protected]>
---
 gcc/tree.cc | 26 ++++++++++++++------------
 gcc/tree.h  | 15 ++++++++++++++-
 2 files changed, 28 insertions(+), 13 deletions(-)

diff --git a/gcc/tree.cc b/gcc/tree.cc
index 446261a8a8c..fdd8dd6492e 100644
--- a/gcc/tree.cc
+++ b/gcc/tree.cc
@@ -11013,32 +11013,34 @@ build_call_1 (tree return_type, tree fn, int nargs)
 
 /* Build a CALL_EXPR of class tcc_vl_exp with the indicated RETURN_TYPE and
    FN and a null static chain slot.  NARGS is the number of call arguments
-   which are specified as "..." arguments.  */
+   which are specified as a va_list ARGS.  */
 
 tree
-build_call_nary (tree return_type, tree fn, int nargs, ...)
+build_call_valist (tree return_type, tree fn, int nargs, va_list args)
 {
-  tree ret;
-  va_list args;
-  va_start (args, nargs);
-  ret = build_call_valist (return_type, fn, nargs, args);
-  va_end (args);
-  return ret;
+  tree t;
+  int i;
+
+  t = build_call_1 (return_type, fn, nargs);
+  for (i = 0; i < nargs; i++)
+    CALL_EXPR_ARG (t, i) = va_arg (args, tree);
+  process_call_operands (t);
+  return t;
 }
 
 /* Build a CALL_EXPR of class tcc_vl_exp with the indicated RETURN_TYPE and
-   FN and a null static chain slot.  NARGS is the number of call arguments
-   which are specified as a va_list ARGS.  */
+   FN and a null static chain slot.  ARGS specifies the call arguments.  */
 
 tree
-build_call_valist (tree return_type, tree fn, int nargs, va_list args)
+build_call (tree return_type, tree fn, std::initializer_list<tree> args)
 {
   tree t;
   int i;
+  int nargs = args.size();
 
   t = build_call_1 (return_type, fn, nargs);
   for (i = 0; i < nargs; i++)
-    CALL_EXPR_ARG (t, i) = va_arg (args, tree);
+    CALL_EXPR_ARG (t, i) = args.data()[i];
   process_call_operands (t);
   return t;
 }
diff --git a/gcc/tree.h b/gcc/tree.h
index 4a4b8ef7f0a..d4453245c4a 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -4974,8 +4974,21 @@ extern tree build_omp_clause (location_t, enum 
omp_clause_code);
 
 extern tree build_vl_exp (enum tree_code, int CXX_MEM_STAT_INFO);
 
-extern tree build_call_nary (tree, tree, int, ...);
 extern tree build_call_valist (tree, tree, int, va_list);
+extern tree build_call (tree, tree, std::initializer_list<tree>);
+
+
+/* Build a CALL_EXPR of class tcc_vl_exp with the indicated RETURN_TYPE and
+   FN and a null static chain slot.  NARGS is the number of call arguments
+   which are specified as "..." arguments.  */
+
+template <typename ...T>
+inline tree build_call_nary (tree return_type, tree fn, int nargs, T... args)
+{
+  std::initializer_list<tree> args_ = {args...};
+  gcc_checking_assert (sizeof...(args) == nargs);
+  return build_call (return_type, fn, args_);
+}
 #define build_call_array(T1,T2,N,T3)\
    build_call_array_loc (UNKNOWN_LOCATION, T1, T2, N, T3)
 extern tree build_call_array_loc (location_t, tree, tree, int, const tree *);
-- 
2.43.0

Reply via email to