]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
builtins.c (fold_builtin_call_list, [...]): Delete, and replace with...
authorSandra Loosemore <sandra@codesourcery.com>
Wed, 28 Feb 2007 19:21:20 +0000 (14:21 -0500)
committerSandra Loosemore <sandra@gcc.gnu.org>
Wed, 28 Feb 2007 19:21:20 +0000 (14:21 -0500)
2007-02-28  Sandra Loosemore  <sandra@codesourcery.com>

* gcc/builtins.c (fold_builtin_call_list, fold_builtin_call_valist):
Delete, and replace with...
(fold_builtin_call_array): This.  Update callers to use it.
* gcc/fold-const.c (fold_build_call_list): Delete, and replace with...
(fold_build_call_array): This.
(fold_build_call_list_initializer): Delete, and replace with...
(fold_build_call_array_initializer): This.
* gcc/tree.h: Update declarations to reflect above changes.

* gcc/c-typeck.c (build_function_call): Store converted arguments
in a stack-allocated array instead of building a list.
(convert_arguments): Store arguments in the array passed in as an
argument, and return the actual number of arguments.
* gcc/c-format.c: (check_function_format): Pass arguments in an
array instead of a list.
* gcc/c-common.c (check_function_nonnull): Likewise.
(check_function_sentinel): Likewise.
(check_function_arguments): Likewise.
* gcc/c-common.h: Update declarations to reflect above changes.

* gcc/cp/typeck.c (build_function_call): Store converted arguments
in a stack-allocated array instead of building a list.
(convert_arguments): Store arguments in the array passed in as an
argument, and return the actual number of arguments.
* gcc/cp/call.c (build_call): Delete, and replace with...
(build_call_n, build_call_a): New.
(build_op_delete_call): Rewrite to avoid constructing argument lists.
(build_over_call): Store converted arguments in a stack-allocated
array instead of building a list.
(build_cxx_call): Pass arguments in an array instead of as a list.
(build_java_interface_fn_ref): Rewrite to avoid constructing
argument lists.
* gcc/cp/tree.h: Update declarations to reflect above changes.
* gcc/cp/method.c (use_thunk): Use a stack-allocated array to hold
the arguments instead of a list.
* gcc/cp/rtti.c (throw_bad_cast): Update call to cxx_call.
(throw_bad_typeid): Likewise.
(build_dynamic_cast_1): Likewise.
* gcc/cp/init.c (build_builtin_delete_call): Use build_call_n.
* gcc/cp/decl.c (expand_static_init): Likewise.
* gcc/cp/except.c (cp_protect_cleanup_actions): Likewise.
* gcc/cp/cp-gimplify.c (genericize_eh_spec_block): Likewise.
(gimplify_must_not_throw_expr): Likewise.
(cxx_omp_apply_fn): Use build_call_a.

From-SVN: r122411

18 files changed:
gcc/ChangeLog
gcc/builtins.c
gcc/c-common.c
gcc/c-common.h
gcc/c-format.c
gcc/c-typeck.c
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-gimplify.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/except.c
gcc/cp/init.c
gcc/cp/method.c
gcc/cp/rtti.c
gcc/cp/typeck.c
gcc/fold-const.c
gcc/tree.h

index e1c941fc19019a01e3042006853d3efb79334a44..2974266dc25bdfef5a2437287aadf78f1c86e16d 100644 (file)
@@ -1,3 +1,25 @@
+2007-02-28  Sandra Loosemore  <sandra@codesourcery.com>
+
+       * builtins.c (fold_builtin_call_list, fold_builtin_call_valist):
+       Delete, and replace with...
+       (fold_builtin_call_array): This.  Update callers to use it.
+       * fold-const.c (fold_build_call_list): Delete, and replace with...
+       (fold_build_call_array): This.
+       (fold_build_call_list_initializer): Delete, and replace with...
+       (fold_build_call_array_initializer): This.
+       * tree.h: Update declarations to reflect above changes.
+
+       * c-typeck.c (build_function_call): Store converted arguments
+       in a stack-allocated array instead of building a list.
+       (convert_arguments): Store arguments in the array passed in as an
+       argument, and return the actual number of arguments.
+       * c-format.c: (check_function_format): Pass arguments in an
+       array instead of a list.
+       * c-common.c (check_function_nonnull): Likewise.
+       (check_function_sentinel): Likewise.
+       (check_function_arguments): Likewise.
+       * c-common.h: Update declarations to reflect above changes.
+
 2007-02-28  Jan Hubicka  <jh@suse.cz>
 
        * predict.def (PRED_TREE_EARLY_RETURN, PRED_CONST_RETURN,
index 3e1ab59a9765f00d2fb38fd85d9331fb68367088..676b9caba663da58246480cf2c9303013b000dc8 100644 (file)
@@ -10124,56 +10124,13 @@ build_function_call_expr (tree fndecl, tree arglist)
 {
   tree fntype = TREE_TYPE (fndecl);
   tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
-  return fold_builtin_call_list (TREE_TYPE (fntype), fn, arglist);
-}
-
-/* Construct a CALL_EXPR with type TYPE with FN as the function expression.
-   ARGLIST is a TREE_LIST of arguments.  */
-
-tree
-fold_builtin_call_list (tree type, tree fn, tree arglist)
-{
-  tree ret = NULL_TREE;
-  if (TREE_CODE (fn) == ADDR_EXPR)
-    {
-      tree fndecl = TREE_OPERAND (fn, 0);
-      if (TREE_CODE (fndecl) == FUNCTION_DECL
-         && DECL_BUILT_IN (fndecl))
-       {
-         /* FIXME: Don't use a list in this interface.  */
-         if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
-           {
-             ret = targetm.fold_builtin (fndecl, arglist, false);
-             if (ret)
-               return ret;
-           }
-         else
-           {
-             tree tail = arglist;
-             tree args[MAX_ARGS_TO_FOLD_BUILTIN];
-             int nargs;
-             tree exp;
-
-             for (nargs = 0; nargs < MAX_ARGS_TO_FOLD_BUILTIN; nargs++)
-               {
-                 if (!tail)
-                   break;
-                 args[nargs] = TREE_VALUE (tail);
-                 tail = TREE_CHAIN (tail);
-               }
-             if (nargs <= MAX_ARGS_TO_FOLD_BUILTIN)
-               {
-                 ret = fold_builtin_n (fndecl, args, nargs, false);
-                 if (ret)
-                   return ret;
-               }
-             exp = build_call_list (type, fn, arglist);
-             ret = fold_builtin_varargs (fndecl, exp, false);
-             return ret ? ret : exp;
-           }
-       }
-    }
-  return build_call_list (type, fn, arglist);
+  int n = list_length (arglist);
+  tree *argarray = (tree *) alloca (n * sizeof (tree));
+  int i;
+  
+  for (i = 0; i < n; i++, arglist = TREE_CHAIN (arglist))
+    argarray[i] = TREE_VALUE (arglist);
+  return fold_builtin_call_array (TREE_TYPE (fntype), fn, n, argarray);
 }
 
 /* Conveniently construct a function call expression.  FNDECL names the
@@ -10184,24 +10141,26 @@ tree
 build_call_expr (tree fndecl, int n, ...)
 {
   va_list ap;
-  tree ret;
   tree fntype = TREE_TYPE (fndecl);
   tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
+  tree *argarray = (tree *) alloca (n * sizeof (tree));
+  int i;
 
   va_start (ap, n);
-  ret = fold_builtin_call_valist (TREE_TYPE (fntype), fn, n, ap);
+  for (i = 0; i < n; i++)
+    argarray[i] = va_arg (ap, tree);
   va_end (ap);
-  return ret;
+  return fold_builtin_call_array (TREE_TYPE (fntype), fn, n, argarray);
 }
 
 /* Construct a CALL_EXPR with type TYPE with FN as the function expression.
-   N arguments are passed in the va_list AP.  */
+   N arguments are passed in the array ARGARRAY.  */
 
 tree
-fold_builtin_call_valist (tree type,
-                         tree fn,
-                         int n,
-                         va_list ap)
+fold_builtin_call_array (tree type,
+                        tree fn,
+                        int n,
+                        tree *argarray)
 {
   tree ret = NULL_TREE;
   int i;
@@ -10216,15 +10175,8 @@ fold_builtin_call_valist (tree type,
         if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
           {
             tree arglist = NULL_TREE;
-            va_list ap0;
-            va_copy (ap0, ap);
-            for (i = 0; i < n; i++)
-              {
-                tree arg = va_arg (ap0, tree);
-                arglist = tree_cons (NULL_TREE, arg, arglist);
-              }
-            va_end (ap0);
-            arglist = nreverse (arglist);
+           for (i = n - 1; i >= 0; i--)
+             arglist = tree_cons (NULL_TREE, argarray[i], arglist);
             ret = targetm.fold_builtin (fndecl, arglist, false);
             if (ret)
               return ret;
@@ -10233,25 +10185,19 @@ fold_builtin_call_valist (tree type,
           {
             /* First try the transformations that don't require consing up
                an exp.  */
-            tree args[MAX_ARGS_TO_FOLD_BUILTIN];
-            va_list ap0;
-            va_copy (ap0, ap);
-            for (i = 0; i < n; i++)
-              args[i] = va_arg (ap0, tree);
-            va_end (ap0);
-            ret = fold_builtin_n (fndecl, args, n, false);
+            ret = fold_builtin_n (fndecl, argarray, n, false);
             if (ret)
               return ret;
           }
 
         /* If we got this far, we need to build an exp.  */
-        exp = build_call_valist (type, fn, n, ap);
+        exp = build_call_array (type, fn, n, argarray);
         ret = fold_builtin_varargs (fndecl, exp, false);
         return ret ? ret : exp;
       }
   }
 
-  return build_call_valist (type, fn, n, ap);
+  return build_call_array (type, fn, n, argarray);
 }
 
 /* Construct a new CALL_EXPR using the tail of the argument list of EXP
index 8d321a292f5e066a1778b010d692ccedd39f4f34..6ea3800be8db98cdc6848cf2146c873440f1516d 100644 (file)
@@ -554,7 +554,7 @@ static tree handle_warn_unused_result_attribute (tree *, tree, tree, int,
                                                 bool *);
 static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
 
-static void check_function_nonnull (tree, tree);
+static void check_function_nonnull (tree, int, tree *);
 static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT);
 static bool nonnull_check_p (tree, unsigned HOST_WIDE_INT);
 static bool get_nonnull_operand (tree, unsigned HOST_WIDE_INT *);
@@ -5710,13 +5710,15 @@ handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name),
 }
 
 /* Check the argument list of a function call for null in argument slots
-   that are marked as requiring a non-null pointer argument.  */
+   that are marked as requiring a non-null pointer argument.  The NARGS
+   arguments are passed in the array ARGARRAY.
+*/
 
 static void
-check_function_nonnull (tree attrs, tree params)
+check_function_nonnull (tree attrs, int nargs, tree *argarray)
 {
-  tree a, args, param;
-  int param_num;
+  tree a, args;
+  int i;
 
   for (a = attrs; a; a = TREE_CHAIN (a))
     {
@@ -5728,85 +5730,65 @@ check_function_nonnull (tree attrs, tree params)
             should check for non-null, do it.  If the attribute has no args,
             then every pointer argument is checked (in which case the check
             for pointer type is done in check_nonnull_arg).  */
-         for (param = params, param_num = 1; ;
-              param_num++, param = TREE_CHAIN (param))
+         for (i = 0; i < nargs; i++)
            {
-             if (!param)
-               break;
-             if (!args || nonnull_check_p (args, param_num))
+             if (!args || nonnull_check_p (args, i + 1))
                check_function_arguments_recurse (check_nonnull_arg, NULL,
-                                                 TREE_VALUE (param),
-                                                 param_num);
+                                                 argarray[i],
+                                                 i + 1);
            }
        }
     }
 }
 
 /* Check that the Nth argument of a function call (counting backwards
-   from the end) is a (pointer)0.  */
+   from the end) is a (pointer)0.  The NARGS arguments are passed in the
+   array ARGARRAY.  */
 
 static void
-check_function_sentinel (tree attrs, tree params, tree typelist)
+check_function_sentinel (tree attrs, int nargs, tree *argarray, tree typelist)
 {
   tree attr = lookup_attribute ("sentinel", attrs);
 
   if (attr)
     {
-      /* Skip over the named arguments.  */
-      while (typelist && params)
-      {
-       typelist = TREE_CHAIN (typelist);
-       params = TREE_CHAIN (params);
-      }
+      int len = 0;
+      int pos = 0;
+      tree sentinel;
 
-      if (typelist || !params)
-       warning (OPT_Wformat,
-                "not enough variable arguments to fit a sentinel");
-      else
+      /* Skip over the named arguments.  */
+      while (typelist && len < nargs)
        {
-         tree sentinel, end;
-         unsigned pos = 0;
-
-         if (TREE_VALUE (attr))
-           {
-             tree p = TREE_VALUE (TREE_VALUE (attr));
-             pos = TREE_INT_CST_LOW (p);
-           }
-
-         sentinel = end = params;
-
-         /* Advance `end' ahead of `sentinel' by `pos' positions.  */
-         while (pos > 0 && TREE_CHAIN (end))
-           {
-             pos--;
-             end = TREE_CHAIN (end);
-           }
-         if (pos > 0)
-           {
-             warning (OPT_Wformat,
-                      "not enough variable arguments to fit a sentinel");
-             return;
-           }
+         typelist = TREE_CHAIN (typelist);
+         len++;
+       }
 
-         /* Now advance both until we find the last parameter.  */
-         while (TREE_CHAIN (end))
-           {
-             end = TREE_CHAIN (end);
-             sentinel = TREE_CHAIN (sentinel);
-           }
+      if (TREE_VALUE (attr))
+       {
+         tree p = TREE_VALUE (TREE_VALUE (attr));
+         pos = TREE_INT_CST_LOW (p);
+       }
 
-         /* Validate the sentinel.  */
-         if ((!POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (sentinel)))
-              || !integer_zerop (TREE_VALUE (sentinel)))
-             /* Although __null (in C++) is only an integer we allow it
-                nevertheless, as we are guaranteed that it's exactly
-                as wide as a pointer, and we don't want to force
-                users to cast the NULL they have written there.
-                We warn with -Wstrict-null-sentinel, though.  */
-             && (warn_strict_null_sentinel
-                 || null_node != TREE_VALUE (sentinel)))
-           warning (OPT_Wformat, "missing sentinel in function call");
+      /* The sentinel must be one of the varargs, i.e.
+        in position >= the number of fixed arguments.  */
+      if ((nargs - 1 - pos) < len)
+       {
+         warning (OPT_Wformat,
+                  "not enough variable arguments to fit a sentinel");
+         return;
        }
+
+      /* Validate the sentinel.  */
+      sentinel = argarray[nargs - 1 - pos];
+      if ((!POINTER_TYPE_P (TREE_TYPE (sentinel))
+          || !integer_zerop (sentinel))
+         /* Although __null (in C++) is only an integer we allow it
+            nevertheless, as we are guaranteed that it's exactly
+            as wide as a pointer, and we don't want to force
+            users to cast the NULL they have written there.
+            We warn with -Wstrict-null-sentinel, though.  */
+         && (warn_strict_null_sentinel || null_node != sentinel))
+       warning (OPT_Wformat, "missing sentinel in function call");
     }
 }
 
@@ -5996,23 +5978,26 @@ handle_sentinel_attribute (tree *node, tree name, tree args,
   return NULL_TREE;
 }
 \f
-/* Check for valid arguments being passed to a function.  */
+/* Check for valid arguments being passed to a function.
+   ATTRS is a list of attributes.  There are NARGS arguments in the array
+   ARGARRAY.  TYPELIST is the list of argument types for the function.
+ */
 void
-check_function_arguments (tree attrs, tree params, tree typelist)
+check_function_arguments (tree attrs, int nargs, tree *argarray, tree typelist)
 {
   /* Check for null being passed in a pointer argument that must be
      non-null.  We also need to do this if format checking is enabled.  */
 
   if (warn_nonnull)
-    check_function_nonnull (attrs, params);
+    check_function_nonnull (attrs, nargs, argarray);
 
   /* Check for errors in format strings.  */
 
   if (warn_format || warn_missing_format_attribute)
-      check_function_format (attrs, params);
+    check_function_format (attrs, nargs, argarray);
 
   if (warn_format)
-    check_function_sentinel (attrs, params, typelist);
+    check_function_sentinel (attrs, nargs, argarray, typelist);
 }
 
 /* Generic argument checking recursion routine.  PARAM is the argument to
index e52b83208af56458534ce1a96ab0d99f6c12b20d..2eedf79d29d6e706e16301f62aae91fadbdab5c8 100644 (file)
@@ -640,13 +640,13 @@ extern void finish_fname_decls (void);
 extern const char *fname_as_string (int);
 extern tree fname_decl (unsigned, tree);
 
-extern void check_function_arguments (tree, tree, tree);
+extern void check_function_arguments (tree, int, tree *, tree);
 extern void check_function_arguments_recurse (void (*)
                                              (void *, tree,
                                               unsigned HOST_WIDE_INT),
                                              void *, tree,
                                              unsigned HOST_WIDE_INT);
-extern void check_function_format (tree, tree);
+extern void check_function_format (tree, int, tree *);
 extern void set_Wformat (int);
 extern tree handle_format_attribute (tree *, tree, tree, int, bool *);
 extern tree handle_format_arg_attribute (tree *, tree, tree, int, bool *);
index 403724e5e110931d5f0c4e4a354e52bb55ba6756..4a0a41e3a54bd1fe39737bebca458d39a8a2c401 100644 (file)
@@ -851,13 +851,14 @@ decode_format_type (const char *s)
 
 \f
 /* Check the argument list of a call to printf, scanf, etc.
-   ATTRS are the attributes on the function type.
-   PARAMS is the list of argument values.  Also, if -Wmissing-format-attribute,
+   ATTRS are the attributes on the function type.  There are NARGS argument
+   values in the array ARGARRAY.
+   Also, if -Wmissing-format-attribute,
    warn for calls to vprintf or vscanf in functions with no such format
    attribute themselves.  */
 
 void
-check_function_format (tree attrs, tree params)
+check_function_format (tree attrs, int nargs, tree *argarray)
 {
   tree a;
 
@@ -870,7 +871,16 @@ check_function_format (tree attrs, tree params)
          function_format_info info;
          decode_format_attr (TREE_VALUE (a), &info, 1);
          if (warn_format)
-           check_format_info (&info, params);
+           {
+             /* FIXME: Rewrite all the internal functions in this file
+                to use the ARGARRAY directly instead of constructing this
+                temporary list.  */
+             tree params = NULL_TREE;
+             int i;
+             for (i = nargs - 1; i >= 0; i--)
+               params = tree_cons (NULL_TREE, argarray[i], params);
+             check_format_info (&info, params);
+           }
          if (warn_missing_format_attribute && info.first_arg_num == 0
              && (format_types[info.format_type].flags
                  & (int) FMT_FLAG_ARG_CONVERT))
index d3495a9f71dec39cf0a94330f94941246781c05e..8afc2c757ebf30295ddcb62436750c51c4976117 100644 (file)
@@ -83,7 +83,7 @@ static int function_types_compatible_p (tree, tree);
 static int type_lists_compatible_p (tree, tree);
 static tree decl_constant_value_for_broken_optimization (tree);
 static tree lookup_field (tree, tree);
-static tree convert_arguments (tree, tree, tree, tree);
+static int convert_arguments (int, tree *, tree, tree, tree, tree);
 static tree pointer_diff (tree, tree);
 static tree convert_for_assignment (tree, tree, enum impl_conv, tree, tree,
                                    int);
@@ -2228,9 +2228,11 @@ tree
 build_function_call (tree function, tree params)
 {
   tree fntype, fundecl = 0;
-  tree coerced_params;
   tree name = NULL_TREE, result;
   tree tem;
+  int nargs;
+  tree *argarray;
+  
 
   /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue.  */
   STRIP_TYPE_NOPS (function);
@@ -2317,30 +2319,30 @@ build_function_call (tree function, tree params)
   /* Convert the parameters to the types declared in the
      function prototype, or apply default promotions.  */
 
-  coerced_params
-    = convert_arguments (TYPE_ARG_TYPES (fntype), params, function, fundecl);
-
-  if (coerced_params == error_mark_node)
+  nargs = list_length (params);
+  argarray = (tree *) alloca (nargs * sizeof (tree));
+  nargs = convert_arguments (nargs, argarray, TYPE_ARG_TYPES (fntype), 
+                            params, function, fundecl);
+  if (nargs < 0)
     return error_mark_node;
 
   /* Check that the arguments to the function are valid.  */
 
-  check_function_arguments (TYPE_ATTRIBUTES (fntype), coerced_params,
+  check_function_arguments (TYPE_ATTRIBUTES (fntype), nargs, argarray,
                            TYPE_ARG_TYPES (fntype));
 
   if (require_constant_value)
     {
-      result = fold_build_call_list_initializer (TREE_TYPE (fntype),
-                                                function,
-                                                coerced_params);
+      result = fold_build_call_array_initializer (TREE_TYPE (fntype),
+                                                 function, nargs, argarray);
       if (TREE_CONSTANT (result)
          && (name == NULL_TREE
              || strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10) != 0))
        pedwarn_init ("initializer element is not constant");
     }
   else
-    result = fold_build_call_list (TREE_TYPE (fntype),
-                                  function, coerced_params);
+    result = fold_build_call_array (TREE_TYPE (fntype),
+                                   function, nargs, argarray);
 
   if (VOID_TYPE_P (TREE_TYPE (result)))
     return result;
@@ -2348,9 +2350,8 @@ build_function_call (tree function, tree params)
 }
 \f
 /* Convert the argument expressions in the list VALUES
-   to the types in the list TYPELIST.  The result is a list of converted
-   argument expressions, unless there are too few arguments in which
-   case it is error_mark_node.
+   to the types in the list TYPELIST.  The resulting arguments are
+   stored in the array ARGARRAY which has size NARGS.
 
    If TYPELIST is exhausted, or when an element has NULL as its type,
    perform the default conversions.
@@ -2364,14 +2365,17 @@ build_function_call (tree function, tree params)
 
    This is also where warnings about wrong number of args are generated.
 
-   Both VALUES and the returned value are chains of TREE_LIST nodes
-   with the elements of the list in the TREE_VALUE slots of those nodes.  */
+   VALUES is a chain of TREE_LIST nodes with the elements of the list
+   in the TREE_VALUE slots of those nodes.
 
-static tree
-convert_arguments (tree typelist, tree values, tree function, tree fundecl)
+   Returns the actual number of arguments processed (which may be less
+   than NARGS in some error situations), or -1 on failure.  */
+
+static int
+convert_arguments (int nargs, tree *argarray,
+                  tree typelist, tree values, tree function, tree fundecl)
 {
   tree typetail, valtail;
-  tree result = NULL;
   int parmnum;
   tree selector;
 
@@ -2385,7 +2389,7 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl)
   selector = objc_message_selector ();
 
   /* Scan the given expressions and types, producing individual
-     converted arguments and pushing them on RESULT in reverse order.  */
+     converted arguments and storing them in ARGARRAY.  */
 
   for (valtail = values, typetail = typelist, parmnum = 0;
        valtail;
@@ -2400,7 +2404,7 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl)
       if (type == void_type_node)
        {
          error ("too many arguments to function %qE", function);
-         break;
+         return parmnum;
        }
 
       if (selector && argnum > 2)
@@ -2558,35 +2562,37 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl)
                  && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
                parmval = default_conversion (parmval);
            }
-         result = tree_cons (NULL_TREE, parmval, result);
+         argarray[parmnum] = parmval;
        }
       else if (TREE_CODE (TREE_TYPE (val)) == REAL_TYPE
               && (TYPE_PRECISION (TREE_TYPE (val))
                   < TYPE_PRECISION (double_type_node))
               && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (val))))
        /* Convert `float' to `double'.  */
-       result = tree_cons (NULL_TREE, convert (double_type_node, val), result);
+       argarray[parmnum] = convert (double_type_node, val);
       else if ((invalid_func_diag =
                targetm.calls.invalid_arg_for_unprototyped_fn (typelist, fundecl, val)))
        {
          error (invalid_func_diag);
-         return error_mark_node;
+         return -1;
        }
       else
        /* Convert `short' and `char' to full-size `int'.  */
-       result = tree_cons (NULL_TREE, default_conversion (val), result);
+       argarray[parmnum] = default_conversion (val);
 
       if (typetail)
        typetail = TREE_CHAIN (typetail);
     }
 
+  gcc_assert (parmnum == nargs);
+
   if (typetail != 0 && TREE_VALUE (typetail) != void_type_node)
     {
       error ("too few arguments to function %qE", function);
-      return error_mark_node;
+      return -1;
     }
 
-  return nreverse (result);
+  return parmnum;
 }
 \f
 /* This is the entry point used by the parser to build unary operators
index 2bf12bd923034b5f05fde9aee55676b9b34149c4..f6756070895dd46bb3085d2682cee85bde84e75d 100644 (file)
@@ -1,3 +1,30 @@
+2007-02-28  Sandra Loosemore  <sandra@codesourcery.com>
+
+       * typeck.c (build_function_call): Store converted arguments
+       in a stack-allocated array instead of building a list.
+       (convert_arguments): Store arguments in the array passed in as an
+       argument, and return the actual number of arguments.
+       * call.c (build_call): Delete, and replace with...
+       (build_call_n, build_call_a): New.
+       (build_op_delete_call): Rewrite to avoid constructing argument lists.
+       (build_over_call): Store converted arguments in a stack-allocated
+       array instead of building a list.
+       (build_cxx_call): Pass arguments in an array instead of as a list.
+       (build_java_interface_fn_ref): Rewrite to avoid constructing
+       argument lists.
+       * tree.h: Update declarations to reflect above changes.
+       * method.c (use_thunk): Use a stack-allocated array to hold
+       the arguments instead of a list.
+       * rtti.c (throw_bad_cast): Update call to cxx_call.
+       (throw_bad_typeid): Likewise.
+       (build_dynamic_cast_1): Likewise.
+       * init.c (build_builtin_delete_call): Use build_call_n.
+       * decl.c (expand_static_init): Likewise.
+       * except.c (cp_protect_cleanup_actions): Likewise.
+       * cp-gimplify.c (genericize_eh_spec_block): Likewise.
+       (gimplify_must_not_throw_expr): Likewise.
+       (cxx_omp_apply_fn): Use build_call_a.
+
 2007-02-26  Mark Mitchell  <mark@codesourcery.com>
 
        * semantics.c (expand_or_defer_fn): Call c_record_cdtor_fn.
index f60c59260fd8b72b04eeef1ddd3ef50cd153a392..3514e62324be44fc7e2bc76ac4bc09f29fe1aec6 100644 (file)
@@ -269,17 +269,38 @@ build_addr_func (tree function)
 
 /* Build a CALL_EXPR, we can handle FUNCTION_TYPEs, METHOD_TYPEs, or
    POINTER_TYPE to those.  Note, pointer to member function types
-   (TYPE_PTRMEMFUNC_P) must be handled by our callers.  */
+   (TYPE_PTRMEMFUNC_P) must be handled by our callers.  There are
+   two variants.  build_call_a is the primitive taking an array of
+   arguments, while build_call_n is a wrapper that handles varargs.  */
 
 tree
-build_call (tree function, tree parms)
+build_call_n (tree function, int n, ...)
+{
+  if (n == 0)
+    return build_call_a (function, 0, NULL);
+  else
+    {
+      tree *argarray = (tree *) alloca (n * sizeof (tree));
+      va_list ap;
+      int i;
+
+      va_start (ap, n);
+      for (i = 0; i < n; i++)
+       argarray[i] = va_arg (ap, tree);
+      va_end (ap);
+      return build_call_a (function, n, argarray);
+    }
+}
+
+tree
+build_call_a (tree function, int n, tree *argarray)
 {
   int is_constructor = 0;
   int nothrow;
-  tree tmp;
   tree decl;
   tree result_type;
   tree fntype;
+  int i;
 
   function = build_addr_func (function);
 
@@ -327,16 +348,16 @@ build_call (tree function, tree parms)
      for tags in STL, which are used to control overload resolution.
      We don't need to handle other cases of copying empty classes.  */
   if (! decl || ! DECL_BUILT_IN (decl))
-    for (tmp = parms; tmp; tmp = TREE_CHAIN (tmp))
-      if (is_empty_class (TREE_TYPE (TREE_VALUE (tmp)))
-         && ! TREE_ADDRESSABLE (TREE_TYPE (TREE_VALUE (tmp))))
+    for (i = 0; i < n; i++)
+      if (is_empty_class (TREE_TYPE (argarray[i]))
+         && ! TREE_ADDRESSABLE (TREE_TYPE (argarray[i])))
        {
-         tree t = build0 (EMPTY_CLASS_EXPR, TREE_TYPE (TREE_VALUE (tmp)));
-         TREE_VALUE (tmp) = build2 (COMPOUND_EXPR, TREE_TYPE (t),
-                                    TREE_VALUE (tmp), t);
+         tree t = build0 (EMPTY_CLASS_EXPR, TREE_TYPE (argarray[i]));
+         argarray[i] = build2 (COMPOUND_EXPR, TREE_TYPE (t),
+                               argarray[i], t);
        }
 
-  function = build_call_list (result_type, function, parms);
+  function = build_call_array (result_type, function, n, argarray);
   TREE_HAS_CONSTRUCTOR (function) = is_constructor;
   TREE_NOTHROW (function) = nothrow;
 
@@ -4005,7 +4026,7 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
                      tree alloc_fn)
 {
   tree fn = NULL_TREE;
-  tree fns, fnname, argtypes, args, type;
+  tree fns, fnname, argtypes, type;
   int pass;
 
   if (addr == error_mark_node)
@@ -4036,25 +4057,22 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
   if (fns == NULL_TREE)
     fns = lookup_name_nonclass (fnname);
 
+  /* Strip const and volatile from addr.  */
+  addr = cp_convert (ptr_type_node, addr);
+
   if (placement)
     {
       /* Get the parameter types for the allocation function that is
         being called.  */
       gcc_assert (alloc_fn != NULL_TREE);
       argtypes = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (alloc_fn)));
-      /* Also the second argument.  */
-      args = TREE_CHAIN (TREE_OPERAND (placement, 1));
     }
   else
     {
       /* First try it without the size argument.  */
       argtypes = void_list_node;
-      args = NULL_TREE;
     }
 
-  /* Strip const and volatile from addr.  */
-  addr = cp_convert (ptr_type_node, addr);
-
   /* We make two tries at finding a matching `operator delete'.  On
      the first pass, we look for a one-operator (or placement)
      operator delete.  If we're not doing placement delete, then on
@@ -4113,21 +4131,29 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
       if (DECL_CLASS_SCOPE_P (fn))
        perform_or_defer_access_check (TYPE_BINFO (type), fn, fn);
 
-      if (pass == 0)
-       args = tree_cons (NULL_TREE, addr, args);
-      else
-       args = tree_cons (NULL_TREE, addr,
-                         build_tree_list (NULL_TREE, size));
-
       if (placement)
        {
          /* The placement args might not be suitable for overload
             resolution at this point, so build the call directly.  */
+         int nargs = call_expr_nargs (placement);
+         tree *argarray = (tree *) alloca (nargs * sizeof (tree));
+         int i;
+         argarray[0] = addr;
+         for (i = 1; i < nargs; i++)
+           argarray[i] = CALL_EXPR_ARG (placement, i);
          mark_used (fn);
-         return build_cxx_call (fn, args);
+         return build_cxx_call (fn, nargs, argarray);
        }
       else
-       return build_function_call (fn, args);
+       {
+         tree args;
+         if (pass == 0)
+           args = tree_cons (NULL_TREE, addr, NULL_TREE);
+         else
+           args = tree_cons (NULL_TREE, addr,
+                             build_tree_list (NULL_TREE, size));
+         return build_function_call (fn, args);
+       }
     }
 
   /* If we are doing placement delete we do nothing if we don't find a
@@ -4494,7 +4520,7 @@ call_builtin_trap (void)
   tree fn = implicit_built_in_decls[BUILT_IN_TRAP];
 
   gcc_assert (fn != NULL);
-  fn = build_call (fn, NULL_TREE);
+  fn = build_call_n (fn, 0);
   return fn;
 }
 
@@ -4725,11 +4751,14 @@ build_over_call (struct z_candidate *cand, int flags)
   tree args = cand->args;
   conversion **convs = cand->convs;
   conversion *conv;
-  tree converted_args = NULL_TREE;
   tree parm = TYPE_ARG_TYPES (TREE_TYPE (fn));
+  int parmlen;
   tree arg, val;
   int i = 0;
+  int j = 0;
   int is_method = 0;
+  int nargs;
+  tree *argarray;
 
   /* In a template, there is no need to perform all of the work that
      is normally done.  We are only interested in the type of the call
@@ -4795,11 +4824,18 @@ build_over_call (struct z_candidate *cand, int flags)
     args = build_tree_list (NULL_TREE, args);
   arg = args;
 
+  /* Find maximum size of vector to hold converted arguments.  */
+  parmlen = list_length (parm);
+  nargs = list_length (args);
+  if (parmlen > nargs)
+    nargs = parmlen;
+  argarray = (tree *) alloca (nargs * sizeof (tree));
+
   /* The implicit parameters to a constructor are not considered by overload
      resolution, and must be of the proper type.  */
   if (DECL_CONSTRUCTOR_P (fn))
     {
-      converted_args = tree_cons (NULL_TREE, TREE_VALUE (arg), converted_args);
+      argarray[j++] = TREE_VALUE (arg);
       arg = TREE_CHAIN (arg);
       parm = TREE_CHAIN (parm);
       /* We should never try to call the abstract constructor.  */
@@ -4807,8 +4843,7 @@ build_over_call (struct z_candidate *cand, int flags)
 
       if (DECL_HAS_VTT_PARM_P (fn))
        {
-         converted_args = tree_cons
-           (NULL_TREE, TREE_VALUE (arg), converted_args);
+         argarray[j++] = TREE_VALUE (arg);
          arg = TREE_CHAIN (arg);
          parm = TREE_CHAIN (parm);
        }
@@ -4852,7 +4887,7 @@ build_over_call (struct z_candidate *cand, int flags)
       converted_arg = build_base_path (PLUS_EXPR, converted_arg,
                                       base_binfo, 1);
 
-      converted_args = tree_cons (NULL_TREE, converted_arg, converted_args);
+      argarray[j++] = converted_arg;
       parm = TREE_CHAIN (parm);
       arg = TREE_CHAIN (arg);
       ++i;
@@ -4875,18 +4910,14 @@ build_over_call (struct z_candidate *cand, int flags)
        (conv, TREE_VALUE (arg), fn, i - is_method);
 
       val = convert_for_arg_passing (type, val);
-      converted_args = tree_cons (NULL_TREE, val, converted_args);
+      argarray[j++] = val;
     }
 
   /* Default arguments */
   for (; parm && parm != void_list_node; parm = TREE_CHAIN (parm), i++)
-    converted_args
-      = tree_cons (NULL_TREE,
-                  convert_default_arg (TREE_VALUE (parm),
-                                       TREE_PURPOSE (parm),
-                                       fn, i - is_method),
-                  converted_args);
-
+    argarray[j++] = convert_default_arg (TREE_VALUE (parm),
+                                        TREE_PURPOSE (parm),
+                                        fn, i - is_method);
   /* Ellipsis */
   for (; arg; arg = TREE_CHAIN (arg))
     {
@@ -4895,13 +4926,14 @@ build_over_call (struct z_candidate *cand, int flags)
        /* Do no conversions for magic varargs.  */;
       else
        a = convert_arg_to_ellipsis (a);
-      converted_args = tree_cons (NULL_TREE, a, converted_args);
+      argarray[j++] = a;
     }
 
-  converted_args = nreverse (converted_args);
+  gcc_assert (j <= nargs);
+  nargs = j;
 
   check_function_arguments (TYPE_ATTRIBUTES (TREE_TYPE (fn)),
-                           converted_args, TYPE_ARG_TYPES (TREE_TYPE (fn)));
+                           nargs, argarray, TYPE_ARG_TYPES (TREE_TYPE (fn)));
 
   /* Avoid actually calling copy constructors and copy assignment operators,
      if possible.  */
@@ -4911,8 +4943,7 @@ build_over_call (struct z_candidate *cand, int flags)
   else if (cand->num_convs == 1 && DECL_COPY_CONSTRUCTOR_P (fn))
     {
       tree targ;
-      arg = skip_artificial_parms_for (fn, converted_args);
-      arg = TREE_VALUE (arg);
+      arg = argarray[num_artificial_parms_for (fn)];
 
       /* Pull out the real argument, disregarding const-correctness.  */
       targ = arg;
@@ -4967,11 +4998,11 @@ build_over_call (struct z_candidate *cand, int flags)
           && TYPE_HAS_TRIVIAL_ASSIGN_REF (DECL_CONTEXT (fn)))
     {
       tree to = stabilize_reference
-       (build_indirect_ref (TREE_VALUE (converted_args), 0));
+       (build_indirect_ref (argarray[0], 0));
       tree type = TREE_TYPE (to);
       tree as_base = CLASSTYPE_AS_BASE (type);
 
-      arg = TREE_VALUE (TREE_CHAIN (converted_args));
+      arg = argarray[1];
       if (tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (as_base)))
        {
          arg = build_indirect_ref (arg, 0);
@@ -4981,17 +5012,16 @@ build_over_call (struct z_candidate *cand, int flags)
        {
          /* We must only copy the non-tail padding parts.
             Use __builtin_memcpy for the bitwise copy.  */
+       
+         tree arg0, arg1, arg2, t;
 
-         tree args, t;
-
-         args = tree_cons (NULL, TYPE_SIZE_UNIT (as_base), NULL);
-         args = tree_cons (NULL, arg, args);
-         t = build_unary_op (ADDR_EXPR, to, 0);
-         args = tree_cons (NULL, t, args);
+         arg2 = TYPE_SIZE_UNIT (as_base);
+         arg1 = arg;
+         arg0 = build_unary_op (ADDR_EXPR, to, 0);
          t = implicit_built_in_decls[BUILT_IN_MEMCPY];
-         t = build_call (t, args);
+         t = build_call_n (t, 3, arg0, arg1, arg2);
 
-         t = convert (TREE_TYPE (TREE_VALUE (args)), t);
+         t = convert (TREE_TYPE (arg0), t);
          val = build_indirect_ref (t, 0);
        }
 
@@ -5002,20 +5032,20 @@ build_over_call (struct z_candidate *cand, int flags)
 
   if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0)
     {
-      tree t, *p = &TREE_VALUE (converted_args);
-      tree binfo = lookup_base (TREE_TYPE (TREE_TYPE (*p)),
+      tree t;
+      tree binfo = lookup_base (TREE_TYPE (TREE_TYPE (argarray[0])),
                                DECL_CONTEXT (fn),
                                ba_any, NULL);
       gcc_assert (binfo && binfo != error_mark_node);
 
-      *p = build_base_path (PLUS_EXPR, *p, binfo, 1);
-      if (TREE_SIDE_EFFECTS (*p))
-       *p = save_expr (*p);
+      argarray[0] = build_base_path (PLUS_EXPR, argarray[0], binfo, 1);
+      if (TREE_SIDE_EFFECTS (argarray[0]))
+       argarray[0] = save_expr (argarray[0]);
       t = build_pointer_type (TREE_TYPE (fn));
       if (DECL_CONTEXT (fn) && TYPE_JAVA_INTERFACE (DECL_CONTEXT (fn)))
-       fn = build_java_interface_fn_ref (fn, *p);
+       fn = build_java_interface_fn_ref (fn, argarray[0]);
       else
-       fn = build_vfn_ref (*p, DECL_VINDEX (fn));
+       fn = build_vfn_ref (argarray[0], DECL_VINDEX (fn));
       TREE_TYPE (fn) = t;
     }
   else if (DECL_INLINE (fn))
@@ -5023,19 +5053,19 @@ build_over_call (struct z_candidate *cand, int flags)
   else
     fn = build_addr_func (fn);
 
-  return build_cxx_call (fn, converted_args);
+  return build_cxx_call (fn, nargs, argarray);
 }
 
-/* Build and return a call to FN, using ARGS.  This function performs
-   no overload resolution, conversion, or other high-level
-   operations.  */
+/* Build and return a call to FN, using NARGS arguments in ARGARRAY.
+   This function performs no overload resolution, conversion, or other
+   high-level operations.  */
 
 tree
-build_cxx_call (tree fn, tree args)
+build_cxx_call (tree fn, int nargs, tree *argarray)
 {
   tree fndecl;
 
-  fn = build_call (fn, args);
+  fn = build_call_a (fn, nargs, argarray);
 
   /* If this call might throw an exception, note that fact.  */
   fndecl = get_callee_fndecl (fn);
@@ -5069,7 +5099,7 @@ static GTY(()) tree java_iface_lookup_fn;
 static tree
 build_java_interface_fn_ref (tree fn, tree instance)
 {
-  tree lookup_args, lookup_fn, method, idx;
+  tree lookup_fn, method, idx;
   tree klass_ref, iface, iface_ref;
   int i;
 
@@ -5116,13 +5146,11 @@ build_java_interface_fn_ref (tree fn, tree instance)
     }
   idx = build_int_cst (NULL_TREE, i);
 
-  lookup_args = tree_cons (NULL_TREE, klass_ref,
-                          tree_cons (NULL_TREE, iface_ref,
-                                     build_tree_list (NULL_TREE, idx)));
   lookup_fn = build1 (ADDR_EXPR,
                      build_pointer_type (TREE_TYPE (java_iface_lookup_fn)),
                      java_iface_lookup_fn);
-  return build_call_list (ptr_type_node, lookup_fn, lookup_args);
+  return build_call_nary (ptr_type_node, lookup_fn,
+                         3, klass_ref, iface_ref, idx);
 }
 
 /* Returns the value to use for the in-charge parameter when making a
index aa1b0ed73c9f7d65088dd06418b382d33132ff90..bd67ad1b819e11d232c25a0ba164d045e4e0eb42 100644 (file)
@@ -146,9 +146,7 @@ genericize_eh_spec_block (tree *stmt_p)
 {
   tree body = EH_SPEC_STMTS (*stmt_p);
   tree allowed = EH_SPEC_RAISES (*stmt_p);
-  tree failure = build_call (call_unexpected_node,
-                            tree_cons (NULL_TREE, build_exc_ptr (),
-                                       NULL_TREE));
+  tree failure = build_call_n (call_unexpected_node, 1, build_exc_ptr ());
   gimplify_stmt (&body);
 
   *stmt_p = gimple_build_eh_filter (body, allowed, failure);
@@ -432,7 +430,7 @@ gimplify_must_not_throw_expr (tree *expr_p, tree *pre_p)
   gimplify_stmt (&body);
 
   stmt = gimple_build_eh_filter (body, NULL_TREE,
-                                build_call (terminate_node, NULL_TREE));
+                                build_call_n (terminate_node, 0));
 
   if (temp)
     {
@@ -766,11 +764,16 @@ static tree
 cxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2)
 {
   tree defparm, parm;
-  int i;
+  int i = 0;
+  int nargs;
+  tree *argarray;
 
   if (fn == NULL)
     return NULL;
 
+  nargs = list_length (DECL_ARGUMENTS (fn));
+  argarray = (tree *) alloca (nargs * sizeof (tree));
+
   defparm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn)));
   if (arg2)
     defparm = TREE_CHAIN (defparm);
@@ -817,16 +820,14 @@ cxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2)
       t = build1 (LABEL_EXPR, void_type_node, lab);
       append_to_statement_list (t, &ret);
 
-      t = tree_cons (NULL, p1, NULL);
+      argarray[i++] = p1;
       if (arg2)
-       t = tree_cons (NULL, p2, t);
+       argarray[i++] = p2;
       /* Handle default arguments.  */
-      i = 1 + (arg2 != NULL);
-      for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm))
-       t = tree_cons (NULL, convert_default_arg (TREE_VALUE (parm),
-                                                 TREE_PURPOSE (parm),
-                                                 fn, i++), t);
-      t = build_call (fn, nreverse (t));
+      for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm), i++)
+       argarray[i] = convert_default_arg (TREE_VALUE (parm),
+                                          TREE_PURPOSE (parm), fn, i);
+      t = build_call_a (fn, i, argarray);
       append_to_statement_list (t, &ret);
 
       t = fold_convert (TREE_TYPE (p1), TYPE_SIZE_UNIT (inner_type));
@@ -850,16 +851,16 @@ cxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2)
     }
   else
     {
-      tree t = tree_cons (NULL, build_fold_addr_expr (arg1), NULL);
+      argarray[i++] = build_fold_addr_expr (arg1);
       if (arg2)
-       t = tree_cons (NULL, build_fold_addr_expr (arg2), t);
+       argarray[i++] = build_fold_addr_expr (arg2);
       /* Handle default arguments.  */
-      i = 1 + (arg2 != NULL);
-      for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm))
-       t = tree_cons (NULL, convert_default_arg (TREE_VALUE (parm),
-                                                 TREE_PURPOSE (parm),
-                                                 fn, i++), t);
-      return build_call (fn, nreverse (t));
+      for (parm = defparm; parm != void_list_node;
+          parm = TREE_CHAIN (parm), i++)
+       argarray[i] = convert_default_arg (TREE_VALUE (parm),
+                                          TREE_PURPOSE (parm),
+                                          fn, i);
+      return build_call_a (fn, i, argarray);
     }
 }
 
index e03003e12107d0b53b7c8ff71ca61f428cee1f02..6c4d7ee7fa532c8e3f496400655014e89a77a078 100644 (file)
@@ -3859,7 +3859,8 @@ extern bool check_dtor_name                       (tree, tree);
 extern tree build_vfield_ref                   (tree, tree);
 extern tree build_conditional_expr             (tree, tree, tree);
 extern tree build_addr_func                    (tree);
-extern tree build_call                         (tree, tree);
+extern tree build_call_a                       (tree, int, tree*);
+extern tree build_call_n                       (tree, int, ...);
 extern bool null_ptr_cst_p                     (tree);
 extern bool sufficient_parms_p                 (tree);
 extern tree type_decays_to                     (tree);
@@ -3889,7 +3890,7 @@ extern tree strip_top_quals                       (tree);
 extern tree perform_implicit_conversion                (tree, tree);
 extern tree perform_direct_initialization_if_possible (tree, tree, bool);
 extern tree in_charge_arg_for_name             (tree);
-extern tree build_cxx_call                     (tree, tree);
+extern tree build_cxx_call                     (tree, int, tree *);
 #ifdef ENABLE_CHECKING
 extern void validate_conversion_obstack                (void);
 #endif /* ENABLE_CHECKING */
@@ -4174,6 +4175,7 @@ extern void synthesize_method                     (tree);
 extern tree lazily_declare_fn                  (special_function_kind,
                                                 tree);
 extern tree skip_artificial_parms_for          (tree, tree);
+extern int num_artificial_parms_for            (tree);
 extern tree make_alias_for                     (tree, tree);
 
 /* In optimize.c */
index 9ad9e3a0ee2292d331fdc57c8658bcaa575ba657..3aaa8df7dc5bad07bf62c9522cd8c9609340a966 100644 (file)
@@ -5641,7 +5641,7 @@ expand_static_init (tree decl, tree init)
       /* Emit code to perform this initialization but once.  */
       tree if_stmt = NULL_TREE, inner_if_stmt = NULL_TREE;
       tree then_clause = NULL_TREE, inner_then_clause = NULL_TREE;
-      tree guard, guard_addr, guard_addr_list;
+      tree guard, guard_addr;
       tree acquire_fn, release_fn, abort_fn;
       tree flag, begin;
 
@@ -5693,7 +5693,6 @@ expand_static_init (tree decl, tree init)
       if (flag_threadsafe_statics)
        {
          guard_addr = build_address (guard);
-         guard_addr_list = build_tree_list (NULL_TREE, guard_addr);
 
          acquire_fn = get_identifier ("__cxa_guard_acquire");
          release_fn = get_identifier ("__cxa_guard_release");
@@ -5715,7 +5714,7 @@ expand_static_init (tree decl, tree init)
            }
 
          inner_if_stmt = begin_if_stmt ();
-         finish_if_stmt_cond (build_call (acquire_fn, guard_addr_list),
+         finish_if_stmt_cond (build_call_n (acquire_fn, 1, guard_addr),
                               inner_if_stmt);
 
          inner_then_clause = begin_compound_stmt (BCS_NO_SCOPE);
@@ -5725,7 +5724,7 @@ expand_static_init (tree decl, tree init)
          TARGET_EXPR_CLEANUP (begin)
            = build3 (COND_EXPR, void_type_node, flag,
                      void_zero_node,
-                     build_call (abort_fn, guard_addr_list));
+                     build_call_n (abort_fn, 1, guard_addr));
          CLEANUP_EH_ONLY (begin) = 1;
 
          /* Do the initialization itself.  */
@@ -5733,7 +5732,7 @@ expand_static_init (tree decl, tree init)
          init = add_stmt_to_compound
            (init, build2 (MODIFY_EXPR, void_type_node, flag, boolean_true_node));
          init = add_stmt_to_compound
-           (init, build_call (release_fn, guard_addr_list));
+           (init, build_call_n (release_fn, 1, guard_addr));
        }
       else
        init = add_stmt_to_compound (init, set_guard (guard));
index f97ab063dde5f383f09ef990d84acb0eed8e592c..f500437e97011aac5ce82351c994d9acd2ad6108 100644 (file)
@@ -99,7 +99,7 @@ cp_protect_cleanup_actions (void)
 
      When the destruction of an object during stack unwinding exits
      using an exception ... void terminate(); is called.  */
-  return build_call (terminate_node, NULL_TREE);
+  return build_call_n (terminate_node, 0);
 }
 
 static tree
index 1ca07989babfc20edf0b9ada34acd7300affd632..679be2067e67108e60a22b49139a0e60e354c123 100644 (file)
@@ -1540,7 +1540,7 @@ static tree
 build_builtin_delete_call (tree addr)
 {
   mark_used (global_delete_fndecl);
-  return build_call (global_delete_fndecl, build_tree_list (NULL_TREE, addr));
+  return build_call_n (global_delete_fndecl, 1, addr);
 }
 \f
 /* Build and return a NEW_EXPR.  If NELTS is non-NULL, TYPE[NELTS] is
index 7d5c4e8f680f96f60c2fce20f9ef690691d7b6f9..4dff5b9026aaea04d4164eae21beaf9ba7c39266 100644 (file)
@@ -452,6 +452,8 @@ use_thunk (tree thunk_fndecl, bool emit_p)
     }
   else
     {
+      int i;
+      tree *argarray = (tree *) alloca (list_length (a) * sizeof (tree));
       /* If this is a covariant thunk, or we don't have the necessary
         code for efficient thunks, generate a thunk function that
         just makes a call to the real function.  Unfortunately, this
@@ -475,11 +477,10 @@ use_thunk (tree thunk_fndecl, bool emit_p)
                          fixed_offset, virtual_offset);
 
       /* Build up the call to the real function.  */
-      t = tree_cons (NULL_TREE, t, NULL_TREE);
-      for (a = TREE_CHAIN (a); a; a = TREE_CHAIN (a))
-       t = tree_cons (NULL_TREE, a, t);
-      t = nreverse (t);
-      t = build_call (alias, t);
+      argarray[0] = t;
+      for (i = 1, a = TREE_CHAIN (a); a; a = TREE_CHAIN (a), i++)
+       argarray[i] = a;
+      t = build_call_a (alias, i, argarray);
       CALL_FROM_THUNK_P (t) = 1;
 
       if (VOID_TYPE_P (TREE_TYPE (t)))
@@ -1191,4 +1192,25 @@ skip_artificial_parms_for (tree fn, tree list)
   return list;
 }
 
+/* Given a FUNCTION_DECL FN and a chain LIST, return the number of
+   artificial parms in FN.  */
+
+int
+num_artificial_parms_for (tree fn)
+{
+  int count = 0;
+
+  if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
+    count++;
+  else
+    return 0;
+
+  if (DECL_HAS_IN_CHARGE_PARM_P (fn))
+    count++;
+  if (DECL_HAS_VTT_PARM_P (fn))
+    count++;
+  return count;
+}
+
+
 #include "gt-cp-method.h"
index 8549ec07f11700b12b9779ee5e41cbf20fca1eb8..121699f669d7afa6550ecc574afbc6054a08b834 100644 (file)
@@ -196,7 +196,7 @@ throw_bad_cast (void)
     fn = push_throw_library_fn (fn, build_function_type (ptr_type_node,
                                                         void_list_node));
 
-  return build_cxx_call (fn, NULL_TREE);
+  return build_cxx_call (fn, 0, NULL);
 }
 
 /* Return an expression for "__cxa_bad_typeid()".  The expression
@@ -215,7 +215,7 @@ throw_bad_typeid (void)
       fn = push_throw_library_fn (fn, t);
     }
 
-  return build_cxx_call (fn, NULL_TREE);
+  return build_cxx_call (fn, 0, NULL);
 }
 \f
 /* Return an lvalue expression whose type is "const std::type_info"
@@ -588,7 +588,8 @@ build_dynamic_cast_1 (tree type, tree expr)
       else
        {
          tree retval;
-         tree result, td2, td3, elems;
+         tree result, td2, td3;
+         tree elems[4];
          tree static_type, target_type, boff;
 
          /* If we got here, we can't convert statically.  Therefore,
@@ -646,11 +647,10 @@ build_dynamic_cast_1 (tree type, tree expr)
          if (tc == REFERENCE_TYPE)
            expr1 = build_unary_op (ADDR_EXPR, expr1, 0);
 
-         elems = tree_cons
-           (NULL_TREE, expr1, tree_cons
-            (NULL_TREE, td3, tree_cons
-             (NULL_TREE, td2, tree_cons
-              (NULL_TREE, boff, NULL_TREE))));
+         elems[0] = expr1;
+         elems[1] = td3;
+         elems[2] = td2;
+         elems[3] = boff;
 
          dcast_fn = dynamic_cast_node;
          if (!dcast_fn)
@@ -680,7 +680,7 @@ build_dynamic_cast_1 (tree type, tree expr)
              pop_nested_namespace (ns);
              dynamic_cast_node = dcast_fn;
            }
-         result = build_cxx_call (dcast_fn, elems);
+         result = build_cxx_call (dcast_fn, 4, elems);
 
          if (tc == REFERENCE_TYPE)
            {
index 63f03ccecded297fa015a33f4844c0d1a43b1939..b8ae880440dfdfc05963ef31efea85f61f724f27 100644 (file)
@@ -60,7 +60,7 @@ static void casts_away_constness_r (tree *, tree *);
 static bool casts_away_constness (tree, tree);
 static void maybe_warn_about_returning_address_of_local (tree);
 static tree lookup_destructor (tree, tree, tree);
-static tree convert_arguments (tree, tree, tree, int);
+static int convert_arguments (int, tree *, tree, tree, tree, int);
 
 /* Do `exp = require_complete_type (exp);' to make sure exp
    does not have an incomplete type.  (That includes void types.)
@@ -2670,10 +2670,12 @@ tree
 build_function_call (tree function, tree params)
 {
   tree fntype, fndecl;
-  tree coerced_params;
   tree name = NULL_TREE;
   int is_method;
   tree original = function;
+  int nargs, parm_types_len;
+  tree *argarray;
+  tree parm_types;
 
   /* For Objective-C, convert any calls via a cast to OBJC_TYPE_REF
      expressions, like those used for ObjC messenger dispatches.  */
@@ -2739,22 +2741,29 @@ build_function_call (tree function, tree params)
 
   /* fntype now gets the type of function pointed to.  */
   fntype = TREE_TYPE (fntype);
+  parm_types = TYPE_ARG_TYPES (fntype);
+
+  /* Allocate storage for converted arguments.  */
+  parm_types_len = list_length (parm_types);
+  nargs = list_length (params);
+  if (parm_types_len > nargs)
+    nargs = parm_types_len;
+  argarray = (tree *) alloca (nargs * sizeof (tree));
 
   /* Convert the parameters to the types declared in the
      function prototype, or apply default promotions.  */
-
-  coerced_params = convert_arguments (TYPE_ARG_TYPES (fntype),
-                                     params, fndecl, LOOKUP_NORMAL);
-  if (coerced_params == error_mark_node)
+  nargs = convert_arguments (nargs, argarray, parm_types,
+                            params, fndecl, LOOKUP_NORMAL);
+  if (nargs < 0)
     return error_mark_node;
 
   /* Check for errors in format strings and inappropriately
      null parameters.  */
 
-  check_function_arguments (TYPE_ATTRIBUTES (fntype), coerced_params,
-                           TYPE_ARG_TYPES (fntype));
+  check_function_arguments (TYPE_ATTRIBUTES (fntype), nargs, argarray,
+                           parm_types);
 
-  return build_cxx_call (function, coerced_params);
+  return build_cxx_call (function, nargs, argarray);
 }
 \f
 /* Convert the actual parameter expressions in the list VALUES
@@ -2762,23 +2771,26 @@ build_function_call (tree function, tree params)
    If parmdecls is exhausted, or when an element has NULL as its type,
    perform the default conversions.
 
+   Store the converted arguments in ARGARRAY.  NARGS is the size of this array.
+
    NAME is an IDENTIFIER_NODE or 0.  It is used only for error messages.
 
    This is also where warnings about wrong number of args are generated.
 
-   Return a list of expressions for the parameters as converted.
+   Returns the actual number of arguments processed (which might be less
+   than NARGS), or -1 on error.
 
-   Both VALUES and the returned value are chains of TREE_LIST nodes
-   with the elements of the list in the TREE_VALUE slots of those nodes.
+   VALUES is a chain of TREE_LIST nodes with the elements of the list
+   in the TREE_VALUE slots of those nodes.
 
    In C++, unspecified trailing parameters can be filled in with their
    default arguments, if such were specified.  Do so here.  */
 
-static tree
-convert_arguments (tree typelist, tree values, tree fndecl, int flags)
+static int
+convert_arguments (int nargs, tree *argarray,
+                  tree typelist, tree values, tree fndecl, int flags)
 {
   tree typetail, valtail;
-  tree result = NULL_TREE;
   const char *called_thing = 0;
   int i = 0;
 
@@ -2807,7 +2819,7 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags)
       tree val = TREE_VALUE (valtail);
 
       if (val == error_mark_node || type == error_mark_node)
-       return error_mark_node;
+       return -1;
 
       if (type == void_type_node)
        {
@@ -2818,11 +2830,7 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags)
            }
          else
            error ("too many arguments to function");
-         /* In case anybody wants to know if this argument
-            list is valid.  */
-         if (result)
-           TREE_TYPE (tree_last (result)) = error_mark_node;
-         break;
+         return i;
        }
 
       /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
@@ -2841,7 +2849,7 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags)
        }
 
       if (val == error_mark_node)
-       return error_mark_node;
+       return -1;
 
       if (type != 0)
        {
@@ -2866,9 +2874,9 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags)
            }
 
          if (parmval == error_mark_node)
-           return error_mark_node;
+           return -1;
 
-         result = tree_cons (NULL_TREE, parmval, result);
+         argarray[i] = parmval;
        }
       else
        {
@@ -2881,7 +2889,7 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags)
          else
            val = convert_arg_to_ellipsis (val);
 
-         result = tree_cons (NULL_TREE, val, result);
+         argarray[i] = val;
        }
 
       if (typetail)
@@ -2902,9 +2910,9 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags)
                                       fndecl, i);
 
              if (parmval == error_mark_node)
-               return error_mark_node;
+               return -1;
 
-             result = tree_cons (0, parmval, result);
+             argarray[i] = parmval;
              typetail = TREE_CHAIN (typetail);
              /* ends with `...'.  */
              if (typetail == NULL_TREE)
@@ -2920,11 +2928,12 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags)
            }
          else
            error ("too few arguments to function");
-         return error_mark_node;
+         return -1;
        }
     }
 
-  return nreverse (result);
+  gcc_assert (i <= nargs);
+  return i;
 }
 \f
 /* Build a binary-operation expression, after performing default
index 80c3c41ecff8b20b533241d194c330d3a0babf99..f1f4c2cb296a1a58167d81acd18e41a9274a64fe 100644 (file)
@@ -12875,13 +12875,13 @@ fold_build3_stat (enum tree_code code, tree type, tree op0, tree op1, tree op2
   return tem;
 }
 
-/* Fold a CALL_EXPR expression of type TYPE with operands FN and ARGLIST
-   and a null static chain.
+/* Fold a CALL_EXPR expression of type TYPE with operands FN and NARGS
+   arguments in ARGARRAY, and a null static chain.
    Return a folded expression if successful.  Otherwise, return a CALL_EXPR
-   of type TYPE from the given operands as constructed by build_call_list.  */
+   of type TYPE from the given operands as constructed by build_call_array.  */
 
 tree
-fold_build_call_list (tree type, tree fn, tree arglist)
+fold_build_call_array (tree type, tree fn, int nargs, tree *argarray)
 {
   tree tem;
 #ifdef ENABLE_FOLD_CHECKING
@@ -12891,6 +12891,7 @@ fold_build_call_list (tree type, tree fn, tree arglist)
                checksum_after_arglist[16];
   struct md5_ctx ctx;
   htab_t ht;
+  int i;
 
   ht = htab_create (32, htab_hash_pointer, htab_eq_pointer, NULL);
   md5_init_ctx (&ctx);
@@ -12899,12 +12900,13 @@ fold_build_call_list (tree type, tree fn, tree arglist)
   htab_empty (ht);
 
   md5_init_ctx (&ctx);
-  fold_checksum_tree (arglist, &ctx, ht);
+  for (i = 0; i < nargs; i++)
+    fold_checksum_tree (argarray[i], &ctx, ht);
   md5_finish_ctx (&ctx, checksum_before_arglist);
   htab_empty (ht);
 #endif
 
-  tem = fold_builtin_call_list (type, fn, arglist);
+  tem = fold_builtin_call_array (type, fn, nargs, argarray);
       
 #ifdef ENABLE_FOLD_CHECKING
   md5_init_ctx (&ctx);
@@ -12916,12 +12918,13 @@ fold_build_call_list (tree type, tree fn, tree arglist)
     fold_check_failed (fn, tem);
   
   md5_init_ctx (&ctx);
-  fold_checksum_tree (arglist, &ctx, ht);
+  for (i = 0; i < nargs; i++)
+    fold_checksum_tree (argarray[i], &ctx, ht);
   md5_finish_ctx (&ctx, checksum_after_arglist);
   htab_delete (ht);
 
   if (memcmp (checksum_before_arglist, checksum_after_arglist, 16))
-    fold_check_failed (arglist, tem);
+    fold_check_failed (NULL_TREE, tem);
 #endif
   return tem;
 }
@@ -12987,12 +12990,13 @@ fold_build3_initializer (enum tree_code code, tree type, tree op0, tree op1,
 }
 
 tree
-fold_build_call_list_initializer (tree type, tree fn, tree arglist)
+fold_build_call_array_initializer (tree type, tree fn,
+                                  int nargs, tree *argarray)
 {
   tree result;
   START_FOLD_INIT;
 
-  result = fold_build_call_list (type, fn, arglist);
+  result = fold_build_call_array (type, fn, nargs, argarray);
 
   END_FOLD_INIT;
   return result;
index 1e2ecd070ef8b84c232937520cb4bf4bb73761cb..69690ee3550e3bfab9645a648590a849f2423e05 100644 (file)
@@ -4397,8 +4397,8 @@ extern tree fold_build3_stat (enum tree_code, tree, tree, tree, tree MEM_STAT_DE
 extern tree fold_build1_initializer (enum tree_code, tree, tree);
 extern tree fold_build2_initializer (enum tree_code, tree, tree, tree);
 extern tree fold_build3_initializer (enum tree_code, tree, tree, tree, tree);
-extern tree fold_build_call_list (tree, tree, tree);
-extern tree fold_build_call_list_initializer (tree, tree, tree);
+extern tree fold_build_call_array (tree, tree, int, tree *);
+extern tree fold_build_call_array_initializer (tree, tree, int, tree *);
 extern tree fold_convert (tree, tree);
 extern tree fold_single_bit_test (enum tree_code, tree, tree, tree);
 extern tree fold_ignored_result (tree);
@@ -4497,8 +4497,7 @@ extern bool fold_builtin_next_arg (tree, bool);
 extern enum built_in_function builtin_mathfn_code (tree);
 extern tree build_function_call_expr (tree, tree);
 extern tree fold_build_call_expr (tree, tree, tree, tree);
-extern tree fold_builtin_call_list (tree, tree, tree);
-extern tree fold_builtin_call_valist (tree, tree, int, va_list);
+extern tree fold_builtin_call_array (tree, tree, int, tree *);
 extern tree build_call_expr (tree, int, ...);
 extern tree mathfn_built_in (tree, enum built_in_function fn);
 extern tree strip_float_extensions (tree);