This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: PATCH RFA: Use vectors in the C++ frontend


Here is a new version of the patch to use vectors to hold function
arguments in the C++ frontend.  This one adds some more generic
functions, and uses the same caching approach for both the C and C++
frontends.  This patch does a bit better on reclaiming unused vectors,
and gets a 1.8% reduction in total allocated memory when compiling
tramp3d.

Ian


gcc/ChangeLog:

2009-04-28  Ian Lance Taylor  <iant@google.com>

	* tree.c (build_tree_list_vec_stat): New function.
	(ctor_to_vec): New function.
	(build_nt_call_vec): New function.
	(build_call_array): Change args to be a const pointer.
	(build_call_vec): New function.
	* tree.h (build_nt_call_vec): Declare.
	(build_tree_list_vec_stat): Declare.
	(build_tree_list_vec): Define.
	(build_call_array): Update declaration.
	(build_call_vec): Declare.
	(ctor_to_vec): Declare.
	* c-common.c (tree_vector_cache): New static variable.
	(make_tree_vector): New function.
	(release_tree_vector): New function.
	(make_tree_vector_single): New function.
	(make_tree_vector_copy): New function.
	* c-common.h (tree_vector_cache, make_tree_vector): Declare.
	(make_tree_vector_single, make_tree_vector_copy): Declare.
	* c-parser.c (cached_expr_list_1, cached_expr_list_2): Remove.
	(c_parser_expr_list): Don't manage cache here, instead call
	make_tree_vector.
	(c_parser_release_expr_list): Remove static function.
	(c_parser_vec_to_tree_list): Remove static function.
	(c_parser_attributes): Call build_tree_list_vec instead of
	c_parser_vec_to_tree_list.  Call release_tree_vector instead of
	c_parser_release_expr_list.
	(c_parser_postfix_expression_after_primary): Likewise.
	(c_parser_objc_keywordexpr): Likewise.

gcc/cp/ChangeLog:

2009-04-28  Ian Lance Taylor  <iant@google.com>

	* parser.c (cp_parser_postfix_expression): Change args to a vec.
	Release it when done.
	(tree_vector): Define typedef.  Define VEC functions.
	(cp_parser_parenthesized_expression_list): Change return type to
	vec.  Change all callers.
	(cp_parser_new_expression): Change placement and initializer to
	vecs.  Release them when done.
	(cp_parser_new_placement): Change return type to vec.  Change all
	callers.
	(cp_parser_new_initializer): Likewise.
	* typeck.c (build_function_call_vec): Just call
	cp_build_function_call_vec.
	(cp_build_function_call): Just build a vec and call
	cp_build_function_call_vec.
	(cp_build_function_call_vec): New function based on old
	cp_build_function_call.
	(convert_arguments): Remove nargs and argarray parameters.  Change
	values to a vec.  Change caller.
	(build_x_compound_expr_from_vec): New function.
	(cp_build_modify_expr): Build vec to pass to
	build_special_member_call.
	* call.c (struct z_candidate): Add first_arg field.  Change args
	field to vec.
	(convert_class_to_reference): Handle first argument separately.
	(add_candidate): Add first_arg parameter.  Change args parameter
	to vec.  Change all callers.
	(add_function_candidate, add_conv_candidate): Likewise.
	(add_template_candidate_real, add_template_candidate): Likewise.
	(add_template_conv_candidate): Likewise.
	(build_user_type_conversion_1): Handle first argument separately.
	(resolve_args): Change return type and parameter type to vecs.
	Change all callers.
	(perform_overload_resolution): Change args parameter to vec.
	Change all callers.
	(build_new_function_call, build_operator_new_call): Likewise.
	(add_candidates): Likewise.
	(build_op_call): New globally visible function, built from and
	replacing static function build_object_call.
	(build_new_op): Don't handle CALL_EXPR.  Build vec, not tree_list,
	of arguments.
	(build_op_delete_call): Build vec to pass to
	cp_build_function_call_vec.
	(build_temp): Build vec to pass to build_special_member_call.
	(convert_like_real): Likewise.
	(perform_direct_initialization_if_possible): Likewise.
	(build_over_call): Handle first_arg field.  Use build_call_array
	rather than build_call_list.
	(build_special_member_call): Change args parameter to vec.  Change
	all callers.
	(build_new_method_call): Likewise.
	* init.c (expand_default_init): Change parms to vec.
	(build_raw_new_expr): Change placement and init to vecs.  Change
	all callers.
	(build_new_1, build_new): Likewise.
	* class.c (resolve_address_of_overloaded_function): Build array to
	pass to fn_type_unification.
	* pt.c (tsubst_copy_and_build): For NEW_EXPR build vecs to pass to
	build_new.  For CALL_EXPR create a vec rather than a tree_list;
	expand a pack if necessary.
	(fn_type_unification): Change args parameter to const tree *.  Add
	nargs parameter.  Change all callers.
	(type_unification_real): Likewise.
	(unify): Build array to pass to type_unification_real.
	(get_bindings): Build array to pass to fn_type_unification.
	(any_type_dependent_arguments_p): Change args parameter to a vec.
	Change all callers.
	(make_args_non_dependent): Renamed from build_non_dependent_args.
	Change return type to void.  Change parameter type to vec.  Change
	all callers.
	(do_auto_deduction): Pass an array to type_unification_real.
	* semantics.c (perform_koenig_lookup): Change args to vec.  Change
	all callers.
	(finish_call_expr): Change args to vec.  Change all callers.  Call
	build_op_call instead of passing CALL_EXPR to build_new_op.
	(cxx_omp_create_clause_info): Allocate vec to pass to
	build_special_member_call.
	* decl2.c (build_offset_ref_call_from_tree): Change args parameter
	to vec.  Change all callers.
	* name-lookup.c (lookup_function_nonclass): Likewise.
	(struct arg_lookup): Change args to vec.
	(arg_assoc_namespace): Handle args as a vec.
	(arg_assoc_args_vec): New static function.
	(lookup_arg_dependent): Change args parameter to vec.  Change all
	callers.
	* method.c (do_build_assign_ref): Allocate vec to pass to
	build_special_member_call.
	* except.c (build_throw): Likewise.
	* typeck2.c (build_functional_cast): Likewise.
	* cvt.c (ocp_convert): Likewise.
	* tree.c (build_min_non_dep_call_vec): Change last parameter to
	vec.  Change all callers.
	* cp-tree.h: Update declarations.
	* name-lookup.h: Update declarations.

gcc/objc/ChangeLog:

2009-04-28  Ian Lance Taylor  <iant@google.com>

	* objc-act.c (objc_generate_cxx_ctor_or_dtor): Pass NULL rather
	than NULL_TREE to build_special_member_call.


Index: tree.c
===================================================================
--- tree.c	(revision 146793)
+++ tree.c	(working copy)
@@ -1827,6 +1827,23 @@ build_tree_list_stat (tree parm, tree va
   return t;
 }
 
+/* Build a chain of TREE_LIST nodes from a vector.  */
+
+tree
+build_tree_list_vec_stat (const VEC(tree,gc) *vec MEM_STAT_DECL)
+{
+  tree ret = NULL_TREE;
+  tree *pp = &ret;
+  unsigned int i;
+  tree t;
+  for (i = 0; VEC_iterate (tree, vec, i, t); ++i)
+    {
+      *pp = build_tree_list_stat (NULL, t PASS_MEM_STAT);
+      pp = &TREE_CHAIN (*pp);
+    }
+  return ret;
+}
+
 /* Return a newly created TREE_LIST node whose
    purpose and value fields are PURPOSE and VALUE
    and whose TREE_CHAIN is CHAIN.  */
@@ -1870,6 +1887,22 @@ ctor_to_list (tree ctor)
 
   return list;
 }
+
+/* Return the values of the elements of a CONSTRUCTOR as a vector of
+   trees.  */
+
+VEC(tree,gc) *
+ctor_to_vec (tree ctor)
+{
+  VEC(tree, gc) *vec = VEC_alloc (tree, gc, CONSTRUCTOR_NELTS (ctor));
+  unsigned int ix;
+  tree val;
+
+  FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (ctor), ix, val)
+    VEC_quick_push (tree, vec, val);
+
+  return vec;
+}
 
 /* Return the size nominally occupied by an object of type TYPE
    when it resides in memory.  The value is measured in units of bytes,
@@ -3483,6 +3516,23 @@ build_nt_call_list (tree fn, tree arglis
     CALL_EXPR_ARG (t, i) = TREE_VALUE (arglist);
   return t;
 }
+
+/* Similar to build_nt, but for creating a CALL_EXPR object with a
+   tree VEC.  */
+
+tree
+build_nt_call_vec (tree fn, VEC(tree,gc) *args)
+{
+  tree ret, t;
+  unsigned int ix;
+
+  ret = build_vl_exp (CALL_EXPR, VEC_length (tree, args) + 3);
+  CALL_EXPR_FN (ret) = fn;
+  CALL_EXPR_STATIC_CHAIN (ret) = NULL_TREE;
+  for (ix = 0; VEC_iterate (tree, args, ix, t); ++ix)
+    CALL_EXPR_ARG (ret, ix) = t;
+  return ret;
+}
 
 /* Create a DECL_... node of code CODE, name NAME and data type TYPE.
    We do NOT enter this node in any sort of symbol table.
@@ -8208,7 +8258,7 @@ build_call_valist (tree return_type, tre
    which are specified as a tree array ARGS.  */
 
 tree
-build_call_array (tree return_type, tree fn, int nargs, tree *args)
+build_call_array (tree return_type, tree fn, int nargs, const tree *args)
 {
   tree t;
   int i;
@@ -8223,6 +8273,24 @@ build_call_array (tree return_type, tree
   return t;
 }
 
+/* Like build_call_array, but takes a VEC.  */
+
+tree
+build_call_vec (tree return_type, tree fn, VEC(tree,gc) *args)
+{
+  tree ret, t;
+  unsigned int ix;
+
+  ret = build_vl_exp (CALL_EXPR, VEC_length (tree, args) + 3);
+  TREE_TYPE (ret) = return_type;
+  CALL_EXPR_FN (ret) = fn;
+  CALL_EXPR_STATIC_CHAIN (ret) = NULL_TREE;
+  for (ix = 0; VEC_iterate (tree, args, ix, t); ++ix)
+    CALL_EXPR_ARG (ret, ix) = t;
+  process_call_operands (ret);
+  return ret;
+}
+
 
 /* Returns true if it is possible to prove that the index of
    an array access REF (an ARRAY_REF expression) falls into the
Index: tree.h
===================================================================
--- tree.h	(revision 146793)
+++ tree.h	(working copy)
@@ -3841,6 +3841,7 @@ extern tree maybe_get_identifier (const 
 
 extern tree build_nt (enum tree_code, ...);
 extern tree build_nt_call_list (tree, tree);
+extern tree build_nt_call_vec (tree, VEC(tree,gc) *);
 
 extern tree build0_stat (enum tree_code, tree MEM_STAT_DECL);
 #define build0(c,t) build0_stat (c,t MEM_STAT_INFO)
@@ -3878,6 +3879,8 @@ extern tree build_one_cst (tree);
 extern tree build_string (int, const char *);
 extern tree build_tree_list_stat (tree, tree MEM_STAT_DECL);
 #define build_tree_list(t,q) build_tree_list_stat(t,q MEM_STAT_INFO)
+extern tree build_tree_list_vec_stat (const VEC(tree,gc) * MEM_STAT_DECL);
+#define build_tree_list_vec(v) build_tree_list_vec_stat (v MEM_STAT_INFO)
 extern tree build_decl_stat (enum tree_code, tree, tree MEM_STAT_DECL);
 extern tree build_fn_decl (const char *, tree);
 #define build_decl(c,t,q) build_decl_stat (c,t,q MEM_STAT_INFO)
@@ -3891,7 +3894,8 @@ extern tree build_vl_exp_stat (enum tree
 extern tree build_call_list (tree, tree, tree);
 extern tree build_call_nary (tree, tree, int, ...);
 extern tree build_call_valist (tree, tree, int, va_list);
-extern tree build_call_array (tree, tree, int, tree*);
+extern tree build_call_array (tree, tree, int, const tree *);
+extern tree build_call_vec (tree, tree, VEC(tree,gc) *);
 
 /* Construct various nodes representing data types.  */
 
@@ -4318,6 +4322,10 @@ extern bool initializer_zerop (const_tre
 
 extern tree ctor_to_list (tree);
 
+/* Given a CONSTRUCTOR CTOR, return the element values as a vector.  */
+
+extern VEC(tree,gc) *ctor_to_vec (tree);
+
 /* Examine CTOR to discover:
    * how many scalar fields are set to nonzero values,
      and place it in *P_NZ_ELTS;
Index: objc/objc-act.c
===================================================================
--- objc/objc-act.c	(revision 146793)
+++ objc/objc-act.c	(working copy)
@@ -4512,7 +4512,7 @@ objc_generate_cxx_ctor_or_dtor (bool dto
 	     (build_special_member_call
 	      (build_ivar_reference (DECL_NAME (ivar)),
 	       dtor ? complete_dtor_identifier : complete_ctor_identifier,
-	       NULL_TREE, type, LOOKUP_NORMAL, tf_warning_or_error));
+	       NULL, type, LOOKUP_NORMAL, tf_warning_or_error));
 	}
     }
 
Index: cp/typeck.c
===================================================================
--- cp/typeck.c	(revision 146793)
+++ cp/typeck.c	(working copy)
@@ -61,7 +61,7 @@ static void casts_away_constness_r (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 int convert_arguments (int, tree *, tree, tree, tree, int,
+static int convert_arguments (tree, VEC(tree,gc) **, tree, int,
                               tsubst_flags_t);
 
 /* Do `exp = require_complete_type (exp);' to make sure exp
@@ -2862,38 +2862,57 @@ tree
 build_function_call_vec (tree function, VEC(tree,gc) *params,
 			 VEC(tree,gc) *origtypes ATTRIBUTE_UNUSED)
 {
-  tree p;
-  tree *pp;
-  unsigned int i;
-  tree t;
+  VEC(tree,gc) *orig_params = params;
+  tree ret = cp_build_function_call_vec (function, &params,
+					 tf_warning_or_error);
 
-  /* FIXME: Should just change cp_build_function_call to use a
-     VEC.  */
-  p = NULL_TREE;
-  pp = &p;
-  for (i = 0; VEC_iterate (tree, params, i, t); ++i)
-    {
-      *pp = build_tree_list (NULL, t);
-      pp = &TREE_CHAIN (*pp);
-    }
-  return cp_build_function_call (function, p, tf_warning_or_error);
+  /* cp_build_function_call_vec can reallocate PARAMS by adding
+     default arguments.  That should never happen here.  Verify
+     that.  */
+  gcc_assert (params == orig_params);
+
+  return ret;
 }
 
+/* Build a function call using a tree list of arguments.  */
+
 tree
 cp_build_function_call (tree function, tree params, tsubst_flags_t complain)
 {
+  VEC(tree,gc) *vec;
+  tree ret;
+
+  vec = make_tree_vector ();
+  for (; params != NULL_TREE; params = TREE_CHAIN (params))
+    VEC_safe_push (tree, gc, vec, TREE_VALUE (params));
+  ret = cp_build_function_call_vec (function, &vec, complain);
+  release_tree_vector (vec);
+  return ret;
+}
+
+/* Build a function call using a vector of arguments.  PARAMS may be
+   NULL if there are no parameters.  This changes the contents of
+   PARAMS.  */
+
+tree
+cp_build_function_call_vec (tree function, VEC(tree,gc) **params,
+			    tsubst_flags_t complain)
+{
   tree fntype, fndecl;
   tree name = NULL_TREE;
   int is_method;
   tree original = function;
-  int nargs, parm_types_len;
+  int nargs;
   tree *argarray;
   tree parm_types;
+  VEC(tree,gc) *allocated = NULL;
+  tree ret;
 
   /* For Objective-C, convert any calls via a cast to OBJC_TYPE_REF
      expressions, like those used for ObjC messenger dispatches.  */
-  if (params != NULL_TREE)
-    function = objc_rewrite_function_call (function, TREE_VALUE (params));
+  if (params != NULL && !VEC_empty (tree, *params))
+    function = objc_rewrite_function_call (function,
+					   VEC_index (tree, *params, 0));
 
   /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
      Strip such NOP_EXPRs, since FUNCTION is used in non-lvalue context.  */
@@ -2953,57 +2972,55 @@ cp_build_function_call (tree function, t
   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.  */
-  nargs = convert_arguments (nargs, argarray, parm_types,
-			     params, fndecl, LOOKUP_NORMAL,
-                             complain);
+  if (params == NULL)
+    {
+      allocated = make_tree_vector ();
+      params = &allocated;
+    }
+
+  nargs = convert_arguments (parm_types, params, fndecl, LOOKUP_NORMAL,
+			     complain);
   if (nargs < 0)
     return error_mark_node;
 
+  argarray = VEC_address (tree, *params);
+
   /* Check for errors in format strings and inappropriately
      null parameters.  */
   check_function_arguments (TYPE_ATTRIBUTES (fntype), nargs, argarray,
 			    parm_types);
 
-  return build_cxx_call (function, nargs, argarray);
+  ret = build_cxx_call (function, nargs, argarray);
+
+  if (allocated != NULL)
+    release_tree_vector (allocated);
+
+  return ret;
 }
 
-/* Convert the actual parameter expressions in the list VALUES
-   to the types in the list TYPELIST.
+/* Convert the actual parameter expressions in the list VALUES to the
+   types in the list TYPELIST.  The converted expressions are stored
+   back in the VALUES vector.
    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.
 
    Returns the actual number of arguments processed (which might be less
-   than NARGS), or -1 on error.
-
-   VALUES is a chain of TREE_LIST nodes with the elements of the list
-   in the TREE_VALUE slots of those nodes.
+   than the length of the vector), or -1 on error.
 
    In C++, unspecified trailing parameters can be filled in with their
    default arguments, if such were specified.  Do so here.  */
 
 static int
-convert_arguments (int nargs, tree *argarray,
-		   tree typelist, tree values, tree fndecl, int flags,
-                   tsubst_flags_t complain)
+convert_arguments (tree typelist, VEC(tree,gc) **values, tree fndecl,
+		   int flags, tsubst_flags_t complain)
 {
-  tree typetail, valtail;
+  tree typetail;
   const char *called_thing = 0;
-  int i = 0;
+  unsigned int i;
 
   /* Argument passing is always copy-initialization.  */
   flags |= LOOKUP_ONLYCONVERTING;
@@ -3022,12 +3039,12 @@ convert_arguments (int nargs, tree *arga
 	called_thing = "function";
     }
 
-  for (valtail = values, typetail = typelist;
-       valtail;
-       valtail = TREE_CHAIN (valtail), i++)
+  for (i = 0, typetail = typelist;
+       i < VEC_length (tree, *values);
+       i++)
     {
       tree type = typetail ? TREE_VALUE (typetail) : 0;
-      tree val = TREE_VALUE (valtail);
+      tree val = VEC_index (tree, *values, i);
 
       if (val == error_mark_node || type == error_mark_node)
 	return -1;
@@ -3096,7 +3113,7 @@ convert_arguments (int nargs, tree *arga
 	  if (parmval == error_mark_node)
 	    return -1;
 
-	  argarray[i] = parmval;
+	  VEC_replace (tree, *values, i, parmval);
 	}
       else
 	{
@@ -3109,7 +3126,7 @@ convert_arguments (int nargs, tree *arga
 	  else
 	    val = convert_arg_to_ellipsis (val);
 
-	  argarray[i] = val;
+	  VEC_replace (tree, *values, i, val);
 	}
 
       if (typetail)
@@ -3138,7 +3155,7 @@ convert_arguments (int nargs, tree *arga
 	      if (parmval == error_mark_node)
 		return -1;
 
-	      argarray[i] = parmval;
+	      VEC_safe_push (tree, gc, *values, parmval);
 	      typetail = TREE_CHAIN (typetail);
 	      /* ends with `...'.  */
 	      if (typetail == NULL_TREE)
@@ -3162,8 +3179,7 @@ convert_arguments (int nargs, tree *arga
 	}
     }
 
-  gcc_assert (i <= nargs);
-  return i;
+  return (int) i;
 }
 
 /* Build a binary-operation expression, after performing default
@@ -4974,6 +4990,34 @@ tree build_x_compound_expr_from_list (tr
   return expr;
 }
 
+/* Like build_x_compound_expr_from_list, but using a VEC.  */
+
+tree
+build_x_compound_expr_from_vec (VEC(tree,gc) *vec, const char *msg)
+{
+  if (VEC_empty (tree, vec))
+    return NULL_TREE;
+  else if (VEC_length (tree, vec) == 1)
+    return VEC_index (tree, vec, 0);
+  else
+    {
+      tree expr;
+      unsigned int ix;
+      tree t;
+
+      if (msg != NULL)
+	permerror (input_location,
+		   "%s expression list treated as compound expression",
+		   msg);
+
+      expr = VEC_index (tree, vec, 0);
+      for (ix = 1; VEC_iterate (tree, vec, ix, t); ++ix)
+	expr = build_x_compound_expr (expr, t, tf_warning_or_error);
+
+      return expr;
+    }
+}
+
 /* Handle overloading of the ',' operator when needed.  */
 
 tree
@@ -6012,10 +6056,11 @@ cp_build_modify_expr (tree lhs, enum tre
 	/* Do the default thing.  */;
       else
 	{
+	  VEC(tree,gc) *rhs_vec = make_tree_vector_single (rhs);
 	  result = build_special_member_call (lhs, complete_ctor_identifier,
-					      build_tree_list (NULL_TREE, rhs),
-					      lhstype, LOOKUP_NORMAL,
+					      &rhs_vec, lhstype, LOOKUP_NORMAL,
                                               complain);
+	  release_tree_vector (rhs_vec);
 	  if (result == NULL_TREE)
 	    return error_mark_node;
 	  return result;
Index: cp/init.c
===================================================================
--- cp/init.c	(revision 146793)
+++ cp/init.c	(working copy)
@@ -302,7 +302,7 @@ build_value_init (tree type)
 	return build_aggr_init_expr
 	  (type,
 	   build_special_member_call (NULL_TREE, complete_ctor_identifier,
-				      NULL_TREE, type, LOOKUP_NORMAL,
+				      NULL, type, LOOKUP_NORMAL,
 				      tf_warning_or_error));
       else if (TREE_CODE (type) != UNION_TYPE && TYPE_NEEDS_CONSTRUCTING (type))
 	{
@@ -312,7 +312,7 @@ build_value_init (tree type)
 	     This will be handled in simplify_aggr_init_expr.  */
 	  tree ctor = build_special_member_call
 	    (NULL_TREE, complete_ctor_identifier,
-	     NULL_TREE, type, LOOKUP_NORMAL, tf_warning_or_error);
+	     NULL, type, LOOKUP_NORMAL, tf_warning_or_error);
 
 	  ctor = build_aggr_init_expr (type, ctor);
 	  AGGR_INIT_ZERO_FIRST (ctor) = 1;
@@ -951,7 +951,7 @@ expand_cleanup_for_base (tree binfo, tre
   /* Call the destructor.  */
   expr = build_special_member_call (current_class_ref,
 				    base_dtor_identifier,
-				    NULL_TREE,
+				    NULL,
 				    binfo,
 				    LOOKUP_NORMAL | LOOKUP_NONVIRTUAL,
                                     tf_warning_or_error);
@@ -1285,7 +1285,7 @@ expand_default_init (tree binfo, tree tr
      followed by initialization by X.  If neither of these work
      out, then look hard.  */
   tree rval;
-  tree parms;
+  VEC(tree,gc) *parms;
 
   if (init && TREE_CODE (init) != TREE_LIST
       && (flags & LOOKUP_ONLYCONVERTING))
@@ -1325,23 +1325,28 @@ expand_default_init (tree binfo, tree tr
       return;
     }
 
-  if (init == NULL_TREE
-      || (TREE_CODE (init) == TREE_LIST && ! TREE_TYPE (init)))
-    {
-      parms = init;
-      if (parms)
-	init = TREE_VALUE (parms);
+  if (init == NULL_TREE)
+    parms = NULL;
+  else if (TREE_CODE (init) == TREE_LIST && !TREE_TYPE (init))
+    {
+      parms = make_tree_vector ();
+      for (; init != NULL_TREE; init = TREE_CHAIN (init))
+	VEC_safe_push (tree, gc, parms, TREE_VALUE (init));
     }
   else
-    parms = build_tree_list (NULL_TREE, init);
+    parms = make_tree_vector_single (init);
 
   if (true_exp == exp)
     ctor_name = complete_ctor_identifier;
   else
     ctor_name = base_ctor_identifier;
 
-  rval = build_special_member_call (exp, ctor_name, parms, binfo, flags,
+  rval = build_special_member_call (exp, ctor_name, &parms, binfo, flags,
                                     complain);
+
+  if (parms != NULL)
+    release_tree_vector (parms);
+
   if (TREE_SIDE_EFFECTS (rval))
     finish_expr_stmt (convert_to_void (rval, NULL, complain));
 }
@@ -1706,18 +1711,31 @@ build_builtin_delete_call (tree addr)
    the type of the object being allocated; otherwise, it's just TYPE.
    INIT is the initializer, if any.  USE_GLOBAL_NEW is true if the
    user explicitly wrote "::operator new".  PLACEMENT, if non-NULL, is
-   the TREE_LIST of arguments to be provided as arguments to a
-   placement new operator.  This routine performs no semantic checks;
-   it just creates and returns a NEW_EXPR.  */
+   a vector of arguments to be provided as arguments to a placement
+   new operator.  This routine performs no semantic checks; it just
+   creates and returns a NEW_EXPR.  */
 
 static tree
-build_raw_new_expr (tree placement, tree type, tree nelts, tree init,
-		    int use_global_new)
+build_raw_new_expr (VEC(tree,gc) *placement, tree type, tree nelts,
+		    VEC(tree,gc) *init, int use_global_new)
 {
+  tree init_list;
   tree new_expr;
 
-  new_expr = build4 (NEW_EXPR, build_pointer_type (type), placement, type,
-		     nelts, init);
+  /* If INIT is NULL, the we want to store NULL_TREE in the NEW_EXPR.
+     If INIT is not NULL, then we want to store VOID_ZERO_NODE.  This
+     permits us to distinguish the case of a missing initializer "new
+     int" from an empty initializer "new int()".  */
+  if (init == NULL)
+    init_list = NULL_TREE;
+  else if (VEC_empty (tree, init))
+    init_list = void_zero_node;
+  else
+    init_list = build_tree_list_vec (init);
+
+  new_expr = build4 (NEW_EXPR, build_pointer_type (type),
+		     build_tree_list_vec (placement), type, nelts,
+		     init_list);
   NEW_EXPR_USE_GLOBAL (new_expr) = use_global_new;
   TREE_SIDE_EFFECTS (new_expr) = 1;
 
@@ -1776,11 +1794,12 @@ avoid_placement_new_aliasing (tree t, tr
 /* Generate code for a new-expression, including calling the "operator
    new" function, initializing the object, and, if an exception occurs
    during construction, cleaning up.  The arguments are as for
-   build_raw_new_expr.  */
+   build_raw_new_expr.  This may change PLACEMENT and INIT.  */
 
 static tree
-build_new_1 (tree placement, tree type, tree nelts, tree init,
-	     bool globally_qualified_p, tsubst_flags_t complain)
+build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
+	     VEC(tree,gc) **init, bool globally_qualified_p,
+	     tsubst_flags_t complain)
 {
   tree size, rval;
   /* True iff this is a call to "operator new[]" instead of just
@@ -1807,11 +1826,12 @@ build_new_1 (tree placement, tree type, 
      beginning of the storage allocated for an array-new expression in
      order to store the number of elements.  */
   tree cookie_size = NULL_TREE;
+  bool have_placement;
+  tree placement_first;
   tree placement_expr = NULL_TREE;
   /* True if the function we are calling is a placement allocation
      function.  */
   bool placement_allocation_fn_p;
-  tree args = NULL_TREE;
   /* True if the storage must be initialized, either by a constructor
      or due to an explicit new-initializer.  */
   bool is_initialized;
@@ -1855,9 +1875,9 @@ build_new_1 (tree placement, tree type, 
   if (abstract_virtuals_error (NULL_TREE, elt_type))
     return error_mark_node;
 
-  is_initialized = (TYPE_NEEDS_CONSTRUCTING (elt_type) || init);
+  is_initialized = (TYPE_NEEDS_CONSTRUCTING (elt_type) || *init != NULL);
 
-  if (CP_TYPE_CONST_P (elt_type) && !init
+  if (CP_TYPE_CONST_P (elt_type) && *init == NULL
       && !type_has_user_provided_default_constructor (elt_type))
     {
       if (complain & tf_error)
@@ -1871,8 +1891,18 @@ build_new_1 (tree placement, tree type, 
 
   alloc_fn = NULL_TREE;
 
+  /* If PLACEMENT is a single simple pointer type not passed by
+     reference, prepare to capture it in a temporary variable.  Do
+     this now, since PLACEMENT will change in the calls below.  */
+  have_placement = !VEC_empty (tree, *placement);
+  placement_first = NULL_TREE;
+  if (VEC_length (tree, *placement) == 1
+      && (TREE_CODE (TREE_TYPE (VEC_index (tree, *placement, 0)))
+	  == POINTER_TYPE))
+    placement_first = VEC_index (tree, *placement, 0);
+
   /* Allocate the object.  */
-  if (! placement && TYPE_FOR_JAVA (elt_type))
+  if (VEC_empty (tree, *placement) && TYPE_FOR_JAVA (elt_type))
     {
       tree class_addr;
       tree class_decl = build_java_class_ref (elt_type);
@@ -1928,7 +1958,7 @@ build_new_1 (tree placement, tree type, 
 	      size = size_binop (PLUS_EXPR, size, cookie_size);
 	    }
 	  /* Create the argument list.  */
-	  args = tree_cons (NULL_TREE, size, placement);
+	  VEC_safe_insert (tree, gc, *placement, 0, size);
 	  /* Do name-lookup to find the appropriate operator.  */
 	  fns = lookup_fnfields (elt_type, fnname, /*protect=*/2);
 	  if (fns == NULL_TREE)
@@ -1947,7 +1977,7 @@ build_new_1 (tree placement, tree type, 
 	      return error_mark_node;
 	    }
 	  alloc_call = build_new_method_call (build_dummy_object (elt_type),
-					      fns, args,
+					      fns, placement,
 					      /*conversion_path=*/NULL_TREE,
 					      LOOKUP_NORMAL,
 					      &alloc_fn,
@@ -1973,12 +2003,10 @@ build_new_1 (tree placement, tree type, 
 
   gcc_assert (alloc_fn != NULL_TREE);
 
-  /* If PLACEMENT is a simple pointer type and is not passed by reference,
-     then copy it into PLACEMENT_EXPR.  */
+  /* If we found a simple case of PLACEMENT_EXPR above, then copy it
+     into a temporary variable.  */
   if (!processing_template_decl
-      && placement != NULL_TREE
-      && TREE_CHAIN (placement) == NULL_TREE
-      && TREE_CODE (TREE_TYPE (TREE_VALUE (placement))) == POINTER_TYPE
+      && placement_first != NULL_TREE
       && TREE_CODE (alloc_call) == CALL_EXPR
       && call_expr_nargs (alloc_call) == 2
       && TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (alloc_call, 0))) == INTEGER_TYPE
@@ -1989,7 +2017,7 @@ build_new_1 (tree placement, tree type, 
       if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (placement_arg)))
 	  || VOID_TYPE_P (TREE_TYPE (TREE_TYPE (placement_arg))))
 	{
-	  placement_expr = get_target_expr (TREE_VALUE (placement));
+	  placement_expr = get_target_expr (placement_first);
 	  CALL_EXPR_ARG (alloc_call, 1)
 	    = convert (TREE_TYPE (placement_arg), placement_expr);
 	}
@@ -2000,7 +2028,7 @@ build_new_1 (tree placement, tree type, 
   if (!cookie_size && !is_initialized)
     {
       rval = build_nop (pointer_type, alloc_call);
-      if (placement != NULL)
+      if (have_placement)
 	rval = avoid_placement_new_aliasing (rval, placement_expr);
       return rval;
     }
@@ -2109,15 +2137,15 @@ build_new_1 (tree placement, tree type, 
       bool stable;
       bool explicit_value_init_p = false;
 
-      if (init == void_zero_node)
+      if (*init != NULL && VEC_empty (tree, *init))
 	{
-	  init = NULL_TREE;
+	  *init = NULL;
 	  explicit_value_init_p = true;
 	}
 
       if (array_p)
 	{
-	  if (init)
+	  if (*init)
             {
               if (complain & tf_error)
                 permerror (input_location, "ISO C++ forbids initialization in array new");
@@ -2130,7 +2158,7 @@ build_new_1 (tree placement, tree type, 
 						  MINUS_EXPR, outer_nelts,
 						  integer_one_node,
 						  complain),
-			      init,
+			      build_tree_list_vec (*init),
 			      explicit_value_init_p,
 			      /*from_array=*/0,
                               complain);
@@ -2160,17 +2188,13 @@ build_new_1 (tree placement, tree type, 
 	    }
 	  else
 	    {
+	      tree ie;
+
 	      /* We are processing something like `new int (10)', which
 		 means allocate an int, and initialize it with 10.  */
 
-	      if (TREE_CODE (init) == TREE_LIST)
-		init = build_x_compound_expr_from_list (init,
-							"new initializer");
-	      else
-		gcc_assert (TREE_CODE (init) != CONSTRUCTOR
-			    || TREE_TYPE (init) != NULL_TREE);
-
-	      init_expr = cp_build_modify_expr (init_expr, INIT_EXPR, init,
+	      ie = build_x_compound_expr_from_vec (*init, "new initializer");
+	      init_expr = cp_build_modify_expr (init_expr, INIT_EXPR, ie,
 						complain);
 	    }
 	  stable = stabilize_init (init_expr, &init_preeval_expr);
@@ -2283,60 +2307,58 @@ build_new_1 (tree placement, tree type, 
   /* A new-expression is never an lvalue.  */
   gcc_assert (!lvalue_p (rval));
 
-  if (placement != NULL)
+  if (have_placement)
     rval = avoid_placement_new_aliasing (rval, placement_expr);
 
   return rval;
 }
 
-/* Generate a representation for a C++ "new" expression.  PLACEMENT is
-   a TREE_LIST of placement-new arguments (or NULL_TREE if none).  If
-   NELTS is NULL, TYPE is the type of the storage to be allocated.  If
-   NELTS is not NULL, then this is an array-new allocation; TYPE is
-   the type of the elements in the array and NELTS is the number of
-   elements in the array.  INIT, if non-NULL, is the initializer for
-   the new object, or void_zero_node to indicate an initializer of
-   "()".  If USE_GLOBAL_NEW is true, then the user explicitly wrote
-   "::new" rather than just "new".  */
+/* Generate a representation for a C++ "new" expression.  *PLACEMENT
+   is a vector of placement-new arguments (or NULL if none).  If NELTS
+   is NULL, TYPE is the type of the storage to be allocated.  If NELTS
+   is not NULL, then this is an array-new allocation; TYPE is the type
+   of the elements in the array and NELTS is the number of elements in
+   the array.  *INIT, if non-NULL, is the initializer for the new
+   object, or an empty vector to indicate an initializer of "()".  If
+   USE_GLOBAL_NEW is true, then the user explicitly wrote "::new"
+   rather than just "new".  This may change PLACEMENT and INIT.  */
 
 tree
-build_new (tree placement, tree type, tree nelts, tree init,
-	   int use_global_new, tsubst_flags_t complain)
+build_new (VEC(tree,gc) **placement, tree type, tree nelts,
+	   VEC(tree,gc) **init, int use_global_new, tsubst_flags_t complain)
 {
   tree rval;
-  tree orig_placement;
-  tree orig_nelts;
-  tree orig_init;
+  VEC(tree,gc) *orig_placement = NULL;
+  tree orig_nelts = NULL_TREE;
+  VEC(tree,gc) *orig_init = NULL;
 
-  if (placement == error_mark_node || type == error_mark_node
-      || init == error_mark_node)
+  if (type == error_mark_node)
     return error_mark_node;
 
-  orig_placement = placement;
-  orig_nelts = nelts;
-  orig_init = init;
-
-  if (nelts == NULL_TREE && init != void_zero_node && list_length (init) == 1)
+  if (nelts == NULL_TREE && VEC_length (tree, *init) == 1)
     {
       tree auto_node = type_uses_auto (type);
-      if (auto_node && describable_type (TREE_VALUE (init)))
-	type = do_auto_deduction (type, TREE_VALUE (init), auto_node);
+      if (auto_node && describable_type (VEC_index (tree, *init, 0)))
+	type = do_auto_deduction (type, VEC_index (tree, *init, 0), auto_node);
     }
 
   if (processing_template_decl)
     {
       if (dependent_type_p (type)
-	  || any_type_dependent_arguments_p (placement)
+	  || any_type_dependent_arguments_p (*placement)
 	  || (nelts && type_dependent_expression_p (nelts))
-	  || (init != void_zero_node
-	      && any_type_dependent_arguments_p (init)))
-	return build_raw_new_expr (placement, type, nelts, init,
+	  || any_type_dependent_arguments_p (*init))
+	return build_raw_new_expr (*placement, type, nelts, *init,
 				   use_global_new);
-      placement = build_non_dependent_args (placement);
+
+      orig_placement = make_tree_vector_copy (*placement);
+      orig_nelts = nelts;
+      orig_init = make_tree_vector_copy (*init);
+
+      make_args_non_dependent (*placement);
       if (nelts)
 	nelts = build_non_dependent_expr (nelts);
-      if (init != void_zero_node)
-	init = build_non_dependent_args (init);
+      make_args_non_dependent (*init);
     }
 
   if (nelts)
@@ -2381,8 +2403,13 @@ build_new (tree placement, tree type, tr
     return error_mark_node;
 
   if (processing_template_decl)
-    return build_raw_new_expr (orig_placement, type, orig_nelts, orig_init,
-			       use_global_new);
+    {
+      tree ret = build_raw_new_expr (orig_placement, type, orig_nelts,
+				     orig_init, use_global_new);
+      release_tree_vector (orig_placement);
+      release_tree_vector (orig_init);
+      return ret;
+    }
 
   /* Wrap it in a NOP_EXPR so warn_if_unused_value doesn't complain.  */
   rval = build1 (NOP_EXPR, TREE_TYPE (rval), rval);
@@ -2954,7 +2981,7 @@ build_dtor_call (tree exp, special_funct
     }
   fn = lookup_fnfields (TREE_TYPE (exp), name, /*protect=*/2);
   return build_new_method_call (exp, fn,
-				/*args=*/NULL_TREE,
+				/*args=*/NULL,
 				/*conversion_path=*/NULL_TREE,
 				flags,
 				/*fn_p=*/NULL,
@@ -3172,7 +3199,7 @@ push_base_cleanups (void)
 	    {
 	      expr = build_special_member_call (current_class_ref,
 						base_dtor_identifier,
-						NULL_TREE,
+						NULL,
 						base_binfo,
 						(LOOKUP_NORMAL
 						 | LOOKUP_NONVIRTUAL),
@@ -3194,7 +3221,7 @@ push_base_cleanups (void)
 
       expr = build_special_member_call (current_class_ref,
 					base_dtor_identifier,
-					NULL_TREE, base_binfo,
+					NULL, base_binfo,
 					LOOKUP_NORMAL | LOOKUP_NONVIRTUAL,
                                         tf_warning_or_error);
       finish_decl_cleanup (NULL_TREE, expr);
Index: cp/class.c
===================================================================
--- cp/class.c	(revision 146793)
+++ cp/class.c	(working copy)
@@ -6072,6 +6072,9 @@ resolve_address_of_overloaded_function (
       tree target_arg_types;
       tree target_ret_type;
       tree fns;
+      tree *args;
+      unsigned int nargs, ia;
+      tree arg;
 
       if (is_ptrmem)
 	target_fn_type
@@ -6085,6 +6088,14 @@ resolve_address_of_overloaded_function (
       if (TREE_CODE (target_fn_type) == METHOD_TYPE)
 	target_arg_types = TREE_CHAIN (target_arg_types);
 
+      nargs = list_length (target_arg_types);
+      args = XALLOCAVEC (tree, nargs);
+      for (arg = target_arg_types, ia = 0;
+	   arg != NULL_TREE && arg != void_list_node;
+	   arg = TREE_CHAIN (arg), ++ia)
+	args[ia] = TREE_VALUE (arg);
+      nargs = ia;
+
       for (fns = overload; fns; fns = OVL_NEXT (fns))
 	{
 	  tree fn = OVL_CURRENT (fns);
@@ -6104,9 +6115,9 @@ resolve_address_of_overloaded_function (
 
 	  /* Try to do argument deduction.  */
 	  targs = make_tree_vec (DECL_NTPARMS (fn));
-	  if (fn_type_unification (fn, explicit_targs, targs,
-				   target_arg_types, target_ret_type,
-				   DEDUCE_EXACT, LOOKUP_NORMAL))
+	  if (fn_type_unification (fn, explicit_targs, targs, args, nargs,
+				   target_ret_type, DEDUCE_EXACT,
+				   LOOKUP_NORMAL))
 	    /* Argument deduction failed.  */
 	    continue;
 
Index: cp/method.c
===================================================================
--- cp/method.c	(revision 146793)
+++ cp/method.c	(working copy)
@@ -1,7 +1,7 @@
 /* Handle the hair of processing (but not expanding) inline functions.
    Also manage function and variable name overloading.
    Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
    Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com)
 
@@ -661,19 +661,21 @@ do_build_assign_ref (tree fndecl)
 	   BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
 	{
 	  tree converted_parm;
+	  VEC(tree,gc) *parmvec;
 
 	  /* We must convert PARM directly to the base class
 	     explicitly since the base class may be ambiguous.  */
 	  converted_parm = build_base_path (PLUS_EXPR, parm, base_binfo, 1);
 	  /* Call the base class assignment operator.  */
+	  parmvec = make_tree_vector_single (converted_parm);
 	  finish_expr_stmt
 	    (build_special_member_call (current_class_ref,
 					ansi_assopname (NOP_EXPR),
-					build_tree_list (NULL_TREE,
-							 converted_parm),
+					&parmvec,
 					base_binfo,
 					LOOKUP_NORMAL | LOOKUP_NONVIRTUAL,
                                         tf_warning_or_error));
+	  release_tree_vector (parmvec);
 	}
 
       /* Assign to each of the non-static data members.  */
Index: cp/except.c
===================================================================
--- cp/except.c	(revision 146793)
+++ cp/except.c	(working copy)
@@ -1,6 +1,6 @@
 /* Handle exceptional things in C++.
    Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
+   2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
    Free Software Foundation, Inc.
    Contributed by Michael Tiemann <tiemann@cygnus.com>
    Rewritten by Mike Stump <mrs@cygnus.com>, based upon an
@@ -736,6 +736,7 @@ build_throw (tree exp)
       if (CLASS_TYPE_P (temp_type))
 	{
 	  int flags = LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING;
+	  VEC(tree,gc) *exp_vec;
 
 	  /* Under C++0x [12.8/16 class.copy], a thrown lvalue is sometimes
 	     treated as an rvalue for the purposes of overload resolution
@@ -749,11 +750,11 @@ build_throw (tree exp)
 	    flags = flags | LOOKUP_PREFER_RVALUE;
 
 	  /* Call the copy constructor.  */
+	  exp_vec = make_tree_vector_single (exp);
 	  exp = (build_special_member_call
-		 (object, complete_ctor_identifier,
-		  build_tree_list (NULL_TREE, exp),
-		  TREE_TYPE (object),
-		  flags, tf_warning_or_error));
+		 (object, complete_ctor_identifier, &exp_vec,
+		  TREE_TYPE (object), flags, tf_warning_or_error));
+	  release_tree_vector (exp_vec);
 	  if (exp == error_mark_node)
 	    {
 	      error ("  in thrown expression");
Index: cp/tree.c
===================================================================
--- cp/tree.c	(revision 146793)
+++ cp/tree.c	(working copy)
@@ -1699,9 +1699,9 @@ build_min_non_dep (enum tree_code code, 
    built.  */
 
 tree
-build_min_non_dep_call_list (tree non_dep, tree fn, tree arglist)
+build_min_non_dep_call_vec (tree non_dep, tree fn, VEC(tree,gc) *argvec)
 {
-  tree t = build_nt_call_list (fn, arglist);
+  tree t = build_nt_call_vec (fn, argvec);
   TREE_TYPE (t) = TREE_TYPE (non_dep);
   TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (non_dep);
   return t;
Index: cp/typeck2.c
===================================================================
--- cp/typeck2.c	(revision 146793)
+++ cp/typeck2.c	(working copy)
@@ -1436,6 +1436,7 @@ build_functional_cast (tree exp, tree pa
 
   /* The type to which we are casting.  */
   tree type;
+  VEC(tree,gc) *parmvec;
 
   if (exp == error_mark_node || parms == error_mark_node)
     return error_mark_node;
@@ -1506,8 +1507,12 @@ build_functional_cast (tree exp, tree pa
     }
 
   /* Call the constructor.  */
-  exp = build_special_member_call (NULL_TREE, complete_ctor_identifier, parms,
-				   type, LOOKUP_NORMAL, complain);
+  parmvec = make_tree_vector ();
+  for (; parms != NULL_TREE; parms = TREE_CHAIN (parms))
+    VEC_safe_push (tree, gc, parmvec, TREE_VALUE (parms));
+  exp = build_special_member_call (NULL_TREE, complete_ctor_identifier,
+				   &parmvec, type, LOOKUP_NORMAL, complain);
+  release_tree_vector (parmvec);
 
   if (exp == error_mark_node)
     return error_mark_node;
Index: cp/pt.c
===================================================================
--- cp/pt.c	(revision 146793)
+++ cp/pt.c	(working copy)
@@ -118,8 +118,8 @@ static tree add_outermost_template_args 
 static bool check_instantiated_args (tree, tree, tsubst_flags_t);
 static int maybe_adjust_types_for_deduction (unification_kind_t, tree*, tree*,
 					     tree);
-static int  type_unification_real (tree, tree, tree, tree,
-				   int, unification_kind_t, int);
+static int type_unification_real (tree, tree, tree, const tree *,
+				  unsigned int, int, unification_kind_t, int);
 static void note_template_header (int);
 static tree convert_nontype_argument_function (tree, tree);
 static tree convert_nontype_argument (tree, tree);
@@ -11405,24 +11405,54 @@ tsubst_copy_and_build (tree t,
 
     case NEW_EXPR:
       {
+	tree placement = RECUR (TREE_OPERAND (t, 0));
 	tree init = RECUR (TREE_OPERAND (t, 3));
+	VEC(tree,gc) *placement_vec;
+	VEC(tree,gc) *init_vec;
+	tree ret;
 
-	if (TREE_OPERAND (t, 3) && !init)
-	  /* If there was an initializer in the original tree, but
-	     it instantiated to an empty list, then we should pass on
-	     VOID_ZERO_NODE to tell build_new that it was an empty
-	     initializer () rather than no initializer.  This can only
-	     happen when the initializer is a pack expansion whose
-	     parameter packs are of length zero.  */
-	  init = void_zero_node;
+	if (placement == NULL_TREE)
+	  placement_vec = NULL;
+	else
+	  {
+	    placement_vec = make_tree_vector ();
+	    for (; placement != NULL_TREE; placement = TREE_CHAIN (placement))
+	      VEC_safe_push (tree, gc, placement_vec, TREE_VALUE (placement));
+	  }
 
-	return build_new
-	  (RECUR (TREE_OPERAND (t, 0)),
-	   RECUR (TREE_OPERAND (t, 1)),
-	   RECUR (TREE_OPERAND (t, 2)),
-	   init,
-	   NEW_EXPR_USE_GLOBAL (t),
-           complain);
+	/* If there was an initializer in the original tree, but it
+	   instantiated to an empty list, then we should pass a
+	   non-NULL empty vector to tell build_new that it was an
+	   empty initializer() rather than no initializer.  This can
+	   only happen when the initializer is a pack expansion whose
+	   parameter packs are of length zero.  */
+	if (init == NULL_TREE && TREE_OPERAND (t, 3) == NULL_TREE)
+	  init_vec = NULL;
+	else
+	  {
+	    init_vec = make_tree_vector ();
+	    if (init == void_zero_node)
+	      gcc_assert (init_vec != NULL);
+	    else
+	      {
+		for (; init != NULL_TREE; init = TREE_CHAIN (init))
+		  VEC_safe_push (tree, gc, init_vec, TREE_VALUE (init));
+	      }
+	  }
+
+	ret = build_new (&placement_vec,
+			 RECUR (TREE_OPERAND (t, 1)),
+			 RECUR (TREE_OPERAND (t, 2)),
+			 &init_vec,
+			 NEW_EXPR_USE_GLOBAL (t),
+			 complain);
+
+	if (placement_vec != NULL)
+	  release_tree_vector (placement_vec);
+	if (init_vec != NULL)
+	  release_tree_vector (init_vec);
+
+	return ret;
       }
 
     case DELETE_EXPR:
@@ -11440,9 +11470,11 @@ tsubst_copy_and_build (tree t,
     case CALL_EXPR:
       {
 	tree function;
-	tree call_args;
+	VEC(tree,gc) *call_args;
+	unsigned int nargs, i;
 	bool qualified_p;
 	bool koenig_p;
+	tree ret;
 
 	function = CALL_EXPR_FN (t);
 	/* When we parsed the expression,  we determined whether or
@@ -11477,8 +11509,40 @@ tsubst_copy_and_build (tree t,
 	      qualified_p = true;
 	  }
 
-	/* FIXME:  Rewrite this so as not to construct an arglist.  */
-	call_args = RECUR (CALL_EXPR_ARGS (t));
+	nargs = call_expr_nargs (t);
+	call_args = make_tree_vector ();
+	for (i = 0; i < nargs; ++i)
+	  {
+	    tree arg = CALL_EXPR_ARG (t, i);
+
+	    if (!PACK_EXPANSION_P (arg))
+	      VEC_safe_push (tree, gc, call_args,
+			     RECUR (CALL_EXPR_ARG (t, i)));
+	    else
+	      {
+		/* Expand the pack expansion and push each entry onto
+		   CALL_ARGS.  */
+		arg = tsubst_pack_expansion (arg, args, complain, in_decl);
+		if (TREE_CODE (arg) == TREE_VEC)
+		  {
+		    unsigned int len, j;
+
+		    len = TREE_VEC_LENGTH (arg);
+		    for (j = 0; j < len; ++j)
+		      {
+			tree value = TREE_VEC_ELT (arg, j);
+			if (value != NULL_TREE)
+			  value = convert_from_reference (value);
+			VEC_safe_push (tree, gc, call_args, value);
+		      }
+		  }
+		else
+		  {
+		    /* A partial substitution.  Add one entry.  */
+		    VEC_safe_push (tree, gc, call_args, arg);
+		  }
+	      }
+	  }
 
 	/* We do not perform argument-dependent lookup if normal
 	   lookup finds a non-function, in accordance with the
@@ -11499,6 +11563,7 @@ tsubst_copy_and_build (tree t,
 	if (TREE_CODE (function) == IDENTIFIER_NODE)
 	  {
 	    unqualified_name_lookup_error (function);
+	    release_tree_vector (call_args);
 	    return error_mark_node;
 	  }
 
@@ -11507,27 +11572,32 @@ tsubst_copy_and_build (tree t,
 	  mark_used (function);
 
 	if (TREE_CODE (function) == OFFSET_REF)
-	  return build_offset_ref_call_from_tree (function, call_args);
-	if (TREE_CODE (function) == COMPONENT_REF)
+	  ret = build_offset_ref_call_from_tree (function, &call_args);
+	else if (TREE_CODE (function) == COMPONENT_REF)
 	  {
 	    if (!BASELINK_P (TREE_OPERAND (function, 1)))
-	      return finish_call_expr (function, call_args,
+	      ret = finish_call_expr (function, &call_args,
 				       /*disallow_virtual=*/false,
 				       /*koenig_p=*/false,
 				       complain);
 	    else
-	      return (build_new_method_call
+	      ret = (build_new_method_call
 		      (TREE_OPERAND (function, 0),
 		       TREE_OPERAND (function, 1),
-		       call_args, NULL_TREE,
+		       &call_args, NULL_TREE,
 		       qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL,
 		       /*fn_p=*/NULL,
 		       complain));
 	  }
-	return finish_call_expr (function, call_args,
-				 /*disallow_virtual=*/qualified_p,
-				 koenig_p,
-				 complain);
+	else
+	  ret = finish_call_expr (function, &call_args,
+				  /*disallow_virtual=*/qualified_p,
+				  koenig_p,
+				  complain);
+
+	release_tree_vector (call_args);
+
+	return ret;
       }
 
     case COND_EXPR:
@@ -12087,9 +12157,10 @@ instantiate_template (tree tmpl, tree ta
   return fndecl;
 }
 
-/* The FN is a TEMPLATE_DECL for a function.  The ARGS are the
-   arguments that are being used when calling it.  TARGS is a vector
-   into which the deduced template arguments are placed.
+/* The FN is a TEMPLATE_DECL for a function.  ARGS is an array with
+   NARGS elements of the arguments that are being used when calling
+   it.  TARGS is a vector into which the deduced template arguments
+   are placed.
 
    Return zero for success, 2 for an incomplete match that doesn't resolve
    all the types, and 1 for complete failure.  An error message will be
@@ -12121,7 +12192,8 @@ int
 fn_type_unification (tree fn,
 		     tree explicit_targs,
 		     tree targs,
-		     tree args,
+		     const tree *args,
+		     unsigned int nargs,
 		     tree return_type,
 		     unification_kind_t strict,
 		     int flags)
@@ -12238,8 +12310,14 @@ fn_type_unification (tree fn,
 
   if (return_type)
     {
+      tree *new_args;
+
       parms = tree_cons (NULL_TREE, TREE_TYPE (fntype), parms);
-      args = tree_cons (NULL_TREE, return_type, args);
+      new_args = XALLOCAVEC (tree, nargs + 1);
+      new_args[0] = return_type;
+      memcpy (new_args + 1, args, nargs * sizeof (tree));
+      args = new_args;
+      ++nargs;
     }
 
   /* We allow incomplete unification without an error message here
@@ -12247,7 +12325,7 @@ fn_type_unification (tree fn,
      callers must be ready to deal with unification failures in any
      event.  */
   result = type_unification_real (DECL_INNERMOST_TEMPLATE_PARMS (fn),
-				  targs, parms, args, /*subr=*/0,
+				  targs, parms, args, nargs, /*subr=*/0,
 				  strict, flags);
 
   if (result == 0 && incomplete_argument_packs_p)
@@ -12312,14 +12390,14 @@ fn_type_unification (tree fn,
 	 parameters are used in non-deduced contexts.  */
       if (strict == DEDUCE_EXACT)
 	{
+	  unsigned int i;
+
 	  tree sarg
 	    = skip_artificial_parms_for (fn, TYPE_ARG_TYPES (substed));
-	  tree arg = args;
 	  if (return_type)
 	    sarg = tree_cons (NULL_TREE, TREE_TYPE (substed), sarg);
-	  for (; arg && sarg;
-	       arg = TREE_CHAIN (arg), sarg = TREE_CHAIN (sarg))
-	    if (!same_type_p (TREE_VALUE (arg), TREE_VALUE (sarg)))
+	  for (i = 0; i < nargs && sarg; ++i, sarg = TREE_CHAIN (sarg))
+	    if (!same_type_p (args[i], TREE_VALUE (sarg)))
 	      return 1;
 	}
     }
@@ -12434,7 +12512,8 @@ static int
 type_unification_real (tree tparms,
 		       tree targs,
 		       tree xparms,
-		       tree xargs,
+		       const tree *xargs,
+		       unsigned int xnargs,
 		       int subr,
 		       unification_kind_t strict,
 		       int flags)
@@ -12444,11 +12523,13 @@ type_unification_real (tree tparms,
   int ntparms = TREE_VEC_LENGTH (tparms);
   int sub_strict;
   int saw_undeduced = 0;
-  tree parms, args;
+  tree parms;
+  const tree *args;
+  unsigned int nargs;
+  unsigned int ia;
 
   gcc_assert (TREE_CODE (tparms) == TREE_VEC);
   gcc_assert (xparms == NULL_TREE || TREE_CODE (xparms) == TREE_LIST);
-  gcc_assert (!xargs || TREE_CODE (xargs) == TREE_LIST);
   gcc_assert (ntparms > 0);
 
   switch (strict)
@@ -12473,17 +12554,19 @@ type_unification_real (tree tparms,
  again:
   parms = xparms;
   args = xargs;
+  nargs = xnargs;
 
+  ia = 0;
   while (parms && parms != void_list_node
-	 && args && args != void_list_node)
+	 && ia < nargs)
     {
       if (TREE_CODE (TREE_VALUE (parms)) == TYPE_PACK_EXPANSION)
         break;
 
       parm = TREE_VALUE (parms);
       parms = TREE_CHAIN (parms);
-      arg = TREE_VALUE (args);
-      args = TREE_CHAIN (args);
+      arg = args[ia];
+      ++ia;
       arg_expr = NULL;
 
       if (arg == error_mark_node)
@@ -12562,20 +12645,11 @@ type_unification_real (tree tparms,
       /* Unify the remaining arguments with the pack expansion type.  */
       tree argvec;
       tree parmvec = make_tree_vec (1);
-      int len = 0;
-      tree t;
 
-      /* Count the number of arguments that remain.  */
-      for (t = args; t && t != void_list_node; t = TREE_CHAIN (t))
-        len++;
-        
       /* Allocate a TREE_VEC and copy in all of the arguments */ 
-      argvec = make_tree_vec (len);
-      for (i = 0; args && args != void_list_node; args = TREE_CHAIN (args))
-        {
-          TREE_VEC_ELT (argvec, i) = TREE_VALUE (args);
-          ++i;
-        }
+      argvec = make_tree_vec (nargs - ia);
+      for (i = 0; ia < nargs; ++ia, ++i)
+	TREE_VEC_ELT (argvec, i) = args[ia];
 
       /* Copy the parameter into parmvec.  */
       TREE_VEC_ELT (parmvec, 0) = TREE_VALUE (parms);
@@ -12589,7 +12663,7 @@ type_unification_real (tree tparms,
 
   /* Fail if we've reached the end of the parm list, and more args
      are present, and the parm list isn't variadic.  */
-  if (args && args != void_list_node && parms == void_list_node)
+  if (ia < nargs && parms == void_list_node)
     return 1;
   /* Fail if parms are left and they don't have default values.  */
   if (parms && parms != void_list_node
@@ -13871,26 +13945,42 @@ unify (tree tparms, tree targs, tree par
 
     case METHOD_TYPE:
     case FUNCTION_TYPE:
-      if (TREE_CODE (arg) != TREE_CODE (parm))
-	return 1;
+      {
+	unsigned int nargs;
+	tree *args;
+	tree a;
+	unsigned int i;
 
-      /* CV qualifications for methods can never be deduced, they must
-	 match exactly.  We need to check them explicitly here,
-	 because type_unification_real treats them as any other
-	 cv-qualified parameter.  */
-      if (TREE_CODE (parm) == METHOD_TYPE
-	  && (!check_cv_quals_for_unify
-	      (UNIFY_ALLOW_NONE,
-	       TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (arg))),
-	       TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (parm))))))
-	return 1;
+	if (TREE_CODE (arg) != TREE_CODE (parm))
+	  return 1;
 
-      if (unify (tparms, targs, TREE_TYPE (parm),
-		 TREE_TYPE (arg), UNIFY_ALLOW_NONE))
-	return 1;
-      return type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm),
-				    TYPE_ARG_TYPES (arg), 1, DEDUCE_EXACT,
-				    LOOKUP_NORMAL);
+	/* CV qualifications for methods can never be deduced, they must
+	   match exactly.  We need to check them explicitly here,
+	   because type_unification_real treats them as any other
+	   cv-qualified parameter.  */
+	if (TREE_CODE (parm) == METHOD_TYPE
+	    && (!check_cv_quals_for_unify
+		(UNIFY_ALLOW_NONE,
+		 TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (arg))),
+		 TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (parm))))))
+	  return 1;
+
+	if (unify (tparms, targs, TREE_TYPE (parm),
+		   TREE_TYPE (arg), UNIFY_ALLOW_NONE))
+	  return 1;
+
+	nargs = list_length (TYPE_ARG_TYPES (arg));
+	args = XALLOCAVEC (tree, nargs);
+	for (a = TYPE_ARG_TYPES (arg), i = 0;
+	     a != NULL_TREE && a != void_list_node;
+	     a = TREE_CHAIN (a), ++i)
+	  args[i] = TREE_VALUE (a);
+	nargs = i;
+
+	return type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm),
+				      args, nargs, 1, DEDUCE_EXACT,
+				      LOOKUP_NORMAL);
+      }
 
     case OFFSET_TYPE:
       /* Unify a pointer to member with a pointer to member function, which
@@ -14444,6 +14534,9 @@ get_bindings (tree fn, tree decl, tree e
   tree targs = make_tree_vec (ntparms);
   tree decl_type;
   tree decl_arg_types;
+  tree *args;
+  unsigned int nargs, ix;
+  tree arg;
 
   /* Substitute the explicit template arguments into the type of DECL.
      The call to fn_type_unification will handle substitution into the
@@ -14478,8 +14571,15 @@ get_bindings (tree fn, tree decl, tree e
   decl_arg_types = skip_artificial_parms_for (decl, 
 					      TYPE_ARG_TYPES (decl_type));
 
+  nargs = list_length (decl_arg_types);
+  args = XALLOCAVEC (tree, nargs);
+  for (arg = decl_arg_types, ix = 0;
+       arg != NULL_TREE && arg != void_list_node;
+       arg = TREE_CHAIN (arg), ++ix)
+    args[ix] = TREE_VALUE (arg);
+
   if (fn_type_unification (fn, explicit_args, targs,
-			   decl_arg_types,
+			   args, ix,
 			   (check_rettype || DECL_CONV_FN_P (fn)
 			    ? TREE_TYPE (decl_type) : NULL_TREE),
 			   DEDUCE_EXACT, LOOKUP_NORMAL))
@@ -16555,19 +16655,18 @@ type_dependent_expression_p_push (tree e
   return b;
 }
 
-/* Returns TRUE if ARGS (a TREE_LIST of arguments to a function call)
-   contains a type-dependent expression.  */
+/* Returns TRUE if ARGS contains a type-dependent expression.  */
 
 bool
-any_type_dependent_arguments_p (const_tree args)
+any_type_dependent_arguments_p (const VEC(tree,gc) *args)
 {
-  while (args)
-    {
-      tree arg = TREE_VALUE (args);
+  unsigned int i;
+  tree arg;
 
+  for (i = 0; VEC_iterate (tree, args, i, arg); ++i)
+    {
       if (type_dependent_expression_p (arg))
 	return true;
-      args = TREE_CHAIN (args);
     }
   return false;
 }
@@ -16987,22 +17086,22 @@ build_non_dependent_expr (tree expr)
   return build1 (NON_DEPENDENT_EXPR, non_reference (TREE_TYPE (expr)), expr);
 }
 
-/* ARGS is a TREE_LIST of expressions as arguments to a function call.
-   Return a new TREE_LIST with the various arguments replaced with
-   equivalent non-dependent expressions.  */
+/* ARGS is a vector of expressions as arguments to a function call.
+   Replace the arguments with equivalent non-dependent expressions.
+   This modifies ARGS in place.  */
 
-tree
-build_non_dependent_args (tree args)
+void
+make_args_non_dependent (VEC(tree,gc) *args)
 {
-  tree a;
-  tree new_args;
+  unsigned int ix;
+  tree arg;
 
-  new_args = NULL_TREE;
-  for (a = args; a; a = TREE_CHAIN (a))
-    new_args = tree_cons (NULL_TREE,
-			  build_non_dependent_expr (TREE_VALUE (a)),
-			  new_args);
-  return nreverse (new_args);
+  for (ix = 0; VEC_iterate (tree, args, ix, arg); ++ix)
+    {
+      tree newarg = build_non_dependent_expr (arg);
+      if (newarg != arg)
+	VEC_replace (tree, args, ix, newarg);
+    }
 }
 
 /* Returns a type which represents 'auto'.  We use a TEMPLATE_TYPE_PARM
@@ -17059,7 +17158,8 @@ listify_autos (tree type, tree auto_node
 tree
 do_auto_deduction (tree type, tree init, tree auto_node)
 {
-  tree parms, args, tparms, targs;
+  tree parms, tparms, targs;
+  tree args[1];
   int val;
 
   /* [dcl.spec.auto]: Obtain P from T by replacing the occurrences of auto
@@ -17070,12 +17170,12 @@ do_auto_deduction (tree type, tree init,
     type = listify_autos (type, auto_node);
 
   parms = build_tree_list (NULL_TREE, type);
-  args = build_tree_list (NULL_TREE, init);
+  args[0] = init;
   tparms = make_tree_vec (1);
   targs = make_tree_vec (1);
   TREE_VEC_ELT (tparms, 0)
     = build_tree_list (NULL_TREE, TYPE_NAME (auto_node));
-  val = type_unification_real (tparms, targs, parms, args, 0,
+  val = type_unification_real (tparms, targs, parms, args, 1, 0,
 			       DEDUCE_CALL, LOOKUP_NORMAL);
   if (val > 0)
     {
Index: cp/semantics.c
===================================================================
--- cp/semantics.c	(revision 146793)
+++ cp/semantics.c	(working copy)
@@ -1821,7 +1821,7 @@ stmt_expr_value_expr (tree stmt_expr)
    resolution.  */
 
 tree
-perform_koenig_lookup (tree fn, tree args)
+perform_koenig_lookup (tree fn, VEC(tree,gc) *args)
 {
   tree identifier = NULL_TREE;
   tree functions = NULL_TREE;
@@ -1866,7 +1866,8 @@ perform_koenig_lookup (tree fn, tree arg
   return fn;
 }
 
-/* Generate an expression for `FN (ARGS)'.
+/* Generate an expression for `FN (ARGS)'.  This may change the
+   contents of ARGS.
 
    If DISALLOW_VIRTUAL is true, the call to FN will be not generated
    as a virtual call, even if FN is virtual.  (This flag is set when
@@ -1877,29 +1878,26 @@ perform_koenig_lookup (tree fn, tree arg
    Returns code for the call.  */
 
 tree
-finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p,
-		  tsubst_flags_t complain)
+finish_call_expr (tree fn, VEC(tree,gc) **args, bool disallow_virtual,
+		  bool koenig_p, tsubst_flags_t complain)
 {
   tree result;
   tree orig_fn;
-  tree orig_args;
+  VEC(tree,gc) *orig_args = NULL;
 
-  if (fn == error_mark_node || args == error_mark_node)
+  if (fn == error_mark_node)
     return error_mark_node;
 
-  /* ARGS should be a list of arguments.  */
-  gcc_assert (!args || TREE_CODE (args) == TREE_LIST);
   gcc_assert (!TYPE_P (fn));
 
   orig_fn = fn;
-  orig_args = args;
 
   if (processing_template_decl)
     {
       if (type_dependent_expression_p (fn)
-	  || any_type_dependent_arguments_p (args))
+	  || any_type_dependent_arguments_p (*args))
 	{
-	  result = build_nt_call_list (fn, args);
+	  result = build_nt_call_vec (fn, *args);
 	  KOENIG_LOOKUP_P (result) = koenig_p;
 	  if (cfun)
 	    {
@@ -1917,11 +1915,12 @@ finish_call_expr (tree fn, tree args, bo
 	    }
 	  return result;
 	}
+      orig_args = make_tree_vector_copy (*args);
       if (!BASELINK_P (fn)
 	  && TREE_CODE (fn) != PSEUDO_DTOR_EXPR
 	  && TREE_TYPE (fn) != unknown_type_node)
 	fn = build_non_dependent_expr (fn);
-      args = build_non_dependent_args (orig_args);
+      make_args_non_dependent (*args);
     }
 
   if (is_overloaded_fn (fn))
@@ -1970,7 +1969,11 @@ finish_call_expr (tree fn, tree args, bo
       if (processing_template_decl)
 	{
 	  if (type_dependent_expression_p (object))
-	    return build_nt_call_list (orig_fn, orig_args);
+	    {
+	      tree ret = build_nt_call_vec (orig_fn, orig_args);
+	      release_tree_vector (orig_args);
+	      return ret;
+	    }
 	  object = build_non_dependent_expr (object);
 	}
 
@@ -1986,15 +1989,7 @@ finish_call_expr (tree fn, tree args, bo
       if (TREE_CODE (fn) == FUNCTION_DECL
 	  && (DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL
 	      || DECL_BUILT_IN_CLASS (fn) == BUILT_IN_MD))
-	{
-	  VEC(tree,gc)* vec = VEC_alloc (tree, gc, list_length (args));
-	  tree p;
-
-	  for (p = args; p != NULL_TREE; p = TREE_CHAIN (p))
-	    VEC_quick_push (tree, vec, TREE_VALUE (p));
-	  result = resolve_overloaded_builtin (fn, vec);
-	  VEC_free (tree, gc, vec);
-	}
+	result = resolve_overloaded_builtin (fn, *args);
 
       if (!result)
 	/* A call to a namespace-scope function.  */
@@ -2002,7 +1997,7 @@ finish_call_expr (tree fn, tree args, bo
     }
   else if (TREE_CODE (fn) == PSEUDO_DTOR_EXPR)
     {
-      if (args)
+      if (!VEC_empty (tree, *args))
 	error ("arguments to destructor are not allowed");
       /* Mark the pseudo-destructor call as having side-effects so
 	 that we do not issue warnings about its use.  */
@@ -2014,18 +2009,19 @@ finish_call_expr (tree fn, tree args, bo
   else if (CLASS_TYPE_P (TREE_TYPE (fn)))
     /* If the "function" is really an object of class type, it might
        have an overloaded `operator ()'.  */
-    result = build_new_op (CALL_EXPR, LOOKUP_NORMAL, fn, args, NULL_TREE,
-			   /*overloaded_p=*/NULL, complain);
+    result = build_op_call (fn, args, complain);
 
   if (!result)
     /* A call where the function is unknown.  */
-    result = cp_build_function_call (fn, args, complain);
+    result = cp_build_function_call_vec (fn, args, complain);
 
   if (processing_template_decl)
     {
-      result = build_call_list (TREE_TYPE (result), orig_fn, orig_args);
+      result = build_call_vec (TREE_TYPE (result), orig_fn, orig_args);
       KOENIG_LOOKUP_P (result) = koenig_p;
+      release_tree_vector (orig_args);
     }
+
   return result;
 }
 
@@ -3424,18 +3420,23 @@ cxx_omp_create_clause_info (tree c, tree
   if (need_default_ctor
       || (need_copy_ctor && !TYPE_HAS_TRIVIAL_INIT_REF (type)))
     {
+      VEC(tree,gc) *vec;
+
       if (need_default_ctor)
-	t = NULL;
+	vec = NULL;
       else
 	{
 	  t = build_int_cst (build_pointer_type (type), 0);
 	  t = build1 (INDIRECT_REF, type, t);
-	  t = build_tree_list (NULL, t);
+	  vec = make_tree_vector_single (t);
 	}
       t = build_special_member_call (NULL_TREE, complete_ctor_identifier,
-				     t, type, LOOKUP_NORMAL,
+				     &vec, type, LOOKUP_NORMAL,
 				     tf_warning_or_error);
 
+      if (vec != NULL)
+	release_tree_vector (vec);
+
       if (targetm.cxx.cdtor_returns_this () || errorcount)
 	/* Because constructors and destructors return this,
 	   the call will have been cast to "void".  Remove the
@@ -3473,12 +3474,15 @@ cxx_omp_create_clause_info (tree c, tree
 
   if (need_copy_assignment && !TYPE_HAS_TRIVIAL_ASSIGN_REF (type))
     {
+      VEC(tree,gc) *vec;
+
       t = build_int_cst (build_pointer_type (type), 0);
       t = build1 (INDIRECT_REF, type, t);
+      vec = make_tree_vector_single (t);
       t = build_special_member_call (t, ansi_assopname (NOP_EXPR),
-				     build_tree_list (NULL, t),
-				     type, LOOKUP_NORMAL,
+				     &vec, type, LOOKUP_NORMAL,
 				     tf_warning_or_error);
+      release_tree_vector (vec);
 
       /* We'll have called convert_from_reference on the call, which
 	 may well have added an indirect_ref.  It's unneeded here,
@@ -4434,7 +4438,9 @@ void
 finish_omp_barrier (void)
 {
   tree fn = built_in_decls[BUILT_IN_GOMP_BARRIER];
-  tree stmt = finish_call_expr (fn, NULL, false, false, tf_warning_or_error);
+  VEC(tree,gc) *vec = make_tree_vector ();
+  tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
+  release_tree_vector (vec);
   finish_expr_stmt (stmt);
 }
 
@@ -4442,7 +4448,9 @@ void
 finish_omp_flush (void)
 {
   tree fn = built_in_decls[BUILT_IN_SYNCHRONIZE];
-  tree stmt = finish_call_expr (fn, NULL, false, false, tf_warning_or_error);
+  VEC(tree,gc) *vec = make_tree_vector ();
+  tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
+  release_tree_vector (vec);
   finish_expr_stmt (stmt);
 }
 
@@ -4450,7 +4458,9 @@ void
 finish_omp_taskwait (void)
 {
   tree fn = built_in_decls[BUILT_IN_GOMP_TASKWAIT];
-  tree stmt = finish_call_expr (fn, NULL, false, false, tf_warning_or_error);
+  VEC(tree,gc) *vec = make_tree_vector ();
+  tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
+  release_tree_vector (vec);
   finish_expr_stmt (stmt);
 }
 
Index: cp/decl2.c
===================================================================
--- cp/decl2.c	(revision 146793)
+++ cp/decl2.c	(working copy)
@@ -3680,18 +3680,18 @@ cp_write_global_declarations (void)
 /* FN is an OFFSET_REF, DOTSTAR_EXPR or MEMBER_REF indicating the
    function to call in parse-tree form; it has not yet been
    semantically analyzed.  ARGS are the arguments to the function.
-   They have already been semantically analyzed.  */
+   They have already been semantically analyzed.  This may change
+   ARGS.  */
 
 tree
-build_offset_ref_call_from_tree (tree fn, tree args)
+build_offset_ref_call_from_tree (tree fn, VEC(tree,gc) **args)
 {
   tree orig_fn;
-  tree orig_args;
+  VEC(tree,gc) *orig_args = NULL;
   tree expr;
   tree object;
 
   orig_fn = fn;
-  orig_args = args;
   object = TREE_OPERAND (fn, 0);
 
   if (processing_template_decl)
@@ -3699,17 +3699,19 @@ build_offset_ref_call_from_tree (tree fn
       gcc_assert (TREE_CODE (fn) == DOTSTAR_EXPR
 		  || TREE_CODE (fn) == MEMBER_REF);
       if (type_dependent_expression_p (fn)
-	  || any_type_dependent_arguments_p (args))
-	return build_nt_call_list (fn, args);
+	  || any_type_dependent_arguments_p (*args))
+	return build_nt_call_vec (fn, *args);
+
+      orig_args = make_tree_vector_copy (*args);
 
       /* Transform the arguments and add the implicit "this"
 	 parameter.  That must be done before the FN is transformed
 	 because we depend on the form of FN.  */
-      args = build_non_dependent_args (args);
+      make_args_non_dependent (*args);
       object = build_non_dependent_expr (object);
       if (TREE_CODE (fn) == DOTSTAR_EXPR)
 	object = cp_build_unary_op (ADDR_EXPR, object, 0, tf_warning_or_error);
-      args = tree_cons (NULL_TREE, object, args);
+      VEC_safe_insert (tree, gc, *args, 0, object);
       /* Now that the arguments are done, transform FN.  */
       fn = build_non_dependent_expr (fn);
     }
@@ -3726,12 +3728,16 @@ build_offset_ref_call_from_tree (tree fn
                                          tf_warning_or_error);
       fn = TREE_OPERAND (fn, 1);
       fn = get_member_function_from_ptrfunc (&object_addr, fn);
-      args = tree_cons (NULL_TREE, object_addr, args);
+      VEC_safe_insert (tree, gc, *args, 0, object_addr);
     }
 
-  expr = cp_build_function_call (fn, args, tf_warning_or_error);
+  expr = cp_build_function_call_vec (fn, args, tf_warning_or_error);
   if (processing_template_decl && expr != error_mark_node)
-    return build_min_non_dep_call_list (expr, orig_fn, orig_args);
+    expr = build_min_non_dep_call_vec (expr, orig_fn, orig_args);
+
+  if (orig_args != NULL)
+    release_tree_vector (orig_args);
+
   return expr;
 }
 
Index: cp/parser.c
===================================================================
--- cp/parser.c	(revision 146793)
+++ cp/parser.c	(working copy)
@@ -1589,7 +1589,7 @@ static tree cp_parser_postfix_open_squar
   (cp_parser *, tree, bool);
 static tree cp_parser_postfix_dot_deref_expression
   (cp_parser *, enum cpp_ttype, tree, bool, cp_id_kind *, location_t);
-static tree cp_parser_parenthesized_expression_list
+static VEC(tree,gc) *cp_parser_parenthesized_expression_list
   (cp_parser *, bool, bool, bool, bool *);
 static void cp_parser_pseudo_destructor_name
   (cp_parser *, tree *, tree *);
@@ -1599,7 +1599,7 @@ static enum tree_code cp_parser_unary_op
   (cp_token *);
 static tree cp_parser_new_expression
   (cp_parser *);
-static tree cp_parser_new_placement
+static VEC(tree,gc) *cp_parser_new_placement
   (cp_parser *);
 static tree cp_parser_new_type_id
   (cp_parser *, tree *);
@@ -1607,7 +1607,7 @@ static cp_declarator *cp_parser_new_decl
   (cp_parser *);
 static cp_declarator *cp_parser_direct_new_declarator
   (cp_parser *);
-static tree cp_parser_new_initializer
+static VEC(tree,gc) *cp_parser_new_initializer
   (cp_parser *);
 static tree cp_parser_delete_expression
   (cp_parser *);
@@ -4690,7 +4690,7 @@ cp_parser_postfix_expression (cp_parser 
 	    bool is_builtin_constant_p;
 	    bool saved_integral_constant_expression_p = false;
 	    bool saved_non_integral_constant_expression_p = false;
-	    tree args;
+	    VEC(tree,gc) *args;
 
             is_member_access = false;
 
@@ -4718,7 +4718,7 @@ cp_parser_postfix_expression (cp_parser 
 		  = saved_non_integral_constant_expression_p;
 	      }
 
-	    if (args == error_mark_node)
+	    if (args == NULL)
 	      {
 		postfix_expression = error_mark_node;
 		break;
@@ -4731,6 +4731,7 @@ cp_parser_postfix_expression (cp_parser 
 							       "a function call"))
 	      {
 		postfix_expression = error_mark_node;
+		release_tree_vector (args);
 		break;
 	      }
 
@@ -4740,7 +4741,7 @@ cp_parser_postfix_expression (cp_parser 
 	      {
 		if (TREE_CODE (postfix_expression) == IDENTIFIER_NODE)
 		  {
-		    if (args)
+		    if (!VEC_empty (tree, args))
 		      {
 			koenig_p = true;
 			if (!any_type_dependent_arguments_p (args))
@@ -4754,7 +4755,8 @@ cp_parser_postfix_expression (cp_parser 
 		/* We do not perform argument-dependent lookup if
 		   normal lookup finds a non-function, in accordance
 		   with the expected resolution of DR 218.  */
-		else if (args && is_overloaded_fn (postfix_expression))
+		else if (!VEC_empty (tree, args)
+			 && is_overloaded_fn (postfix_expression))
 		  {
 		    tree fn = get_first_fn (postfix_expression);
 
@@ -4787,7 +4789,8 @@ cp_parser_postfix_expression (cp_parser 
 			|| any_type_dependent_arguments_p (args)))
 		  {
 		    postfix_expression
-		      = build_nt_call_list (postfix_expression, args);
+		      = build_nt_call_vec (postfix_expression, args);
+		    release_tree_vector (args);
 		    break;
 		  }
 
@@ -4795,7 +4798,7 @@ cp_parser_postfix_expression (cp_parser 
 		  {
 		  postfix_expression
 		    = (build_new_method_call
-		       (instance, fn, args, NULL_TREE,
+		       (instance, fn, &args, NULL_TREE,
 			(idk == CP_ID_KIND_QUALIFIED
 			 ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL),
 			/*fn_p=*/NULL,
@@ -4803,7 +4806,7 @@ cp_parser_postfix_expression (cp_parser 
 		  }
 		else
 		  postfix_expression
-		    = finish_call_expr (postfix_expression, args,
+		    = finish_call_expr (postfix_expression, &args,
 					/*disallow_virtual=*/false,
 					/*koenig_p=*/false,
 					tf_warning_or_error);
@@ -4812,25 +4815,27 @@ cp_parser_postfix_expression (cp_parser 
 		     || TREE_CODE (postfix_expression) == MEMBER_REF
 		     || TREE_CODE (postfix_expression) == DOTSTAR_EXPR)
 	      postfix_expression = (build_offset_ref_call_from_tree
-				    (postfix_expression, args));
+				    (postfix_expression, &args));
 	    else if (idk == CP_ID_KIND_QUALIFIED)
 	      /* A call to a static class member, or a namespace-scope
 		 function.  */
 	      postfix_expression
-		= finish_call_expr (postfix_expression, args,
+		= finish_call_expr (postfix_expression, &args,
 				    /*disallow_virtual=*/true,
 				    koenig_p,
 				    tf_warning_or_error);
 	    else
 	      /* All other function calls.  */
 	      postfix_expression
-		= finish_call_expr (postfix_expression, args,
+		= finish_call_expr (postfix_expression, &args,
 				    /*disallow_virtual=*/false,
 				    koenig_p,
 				    tf_warning_or_error);
 
 	    /* The POSTFIX_EXPRESSION is certainly no longer an id.  */
 	    idk = CP_ID_KIND_NONE;
+
+	    release_tree_vector (args);
 	  }
 	  break;
 
@@ -5137,24 +5142,22 @@ cp_parser_postfix_dot_deref_expression (
    ALLOW_EXPANSION_P is true if this expression allows expansion of an
    argument pack.
 
-   Returns a TREE_LIST.  The TREE_VALUE of each node is a
-   representation of an assignment-expression.  Note that a TREE_LIST
-   is returned even if there is only a single expression in the list.
-   error_mark_node is returned if the ( and or ) are
-   missing. NULL_TREE is returned on no expressions. The parentheses
-   are eaten. IS_ATTRIBUTE_LIST is true if this is really an attribute
-   list being parsed.  If NON_CONSTANT_P is non-NULL, *NON_CONSTANT_P
-   indicates whether or not all of the expressions in the list were
-   constant.  */
+   Returns a vector of trees.  Each element is a representation of an
+   assignment-expression.  NULL is returned if the ( and or ) are
+   missing.  An empty, but allocated, vector is returned on no
+   expressions.  The parentheses are eaten.  IS_ATTRIBUTE_LIST is true
+   if this is really an attribute list being parsed.  If
+   NON_CONSTANT_P is non-NULL, *NON_CONSTANT_P indicates whether or
+   not all of the expressions in the list were constant.  */
 
-static tree
+static VEC(tree,gc) *
 cp_parser_parenthesized_expression_list (cp_parser* parser,
 					 bool is_attribute_list,
 					 bool cast_p,
                                          bool allow_expansion_p,
 					 bool *non_constant_p)
 {
-  tree expression_list = NULL_TREE;
+  VEC(tree,gc) *expression_list;
   bool fold_expr_p = is_attribute_list;
   tree identifier = NULL_TREE;
   bool saved_greater_than_is_operator_p;
@@ -5164,7 +5167,9 @@ cp_parser_parenthesized_expression_list 
     *non_constant_p = false;
 
   if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
-    return error_mark_node;
+    return NULL;
+
+  expression_list = make_tree_vector ();
 
   /* Within a parenthesized expression, a `>' token is always
      the greater-than operator.  */
@@ -5233,7 +5238,7 @@ cp_parser_parenthesized_expression_list 
 		expressions to the list, so that we can still tell if
 		the correct form for a parenthesized expression-list
 		is found. That gives better errors.  */
-	    expression_list = tree_cons (NULL_TREE, expr, expression_list);
+	    VEC_safe_push (tree, gc, expression_list, expr);
 
 	    if (expr == error_mark_node)
 	      goto skip_comma;
@@ -5269,17 +5274,15 @@ cp_parser_parenthesized_expression_list 
 	{
 	  parser->greater_than_is_operator_p
 	    = saved_greater_than_is_operator_p;
-	  return error_mark_node;
+	  return NULL;
 	}
     }
 
   parser->greater_than_is_operator_p
     = saved_greater_than_is_operator_p;
 
-  /* We built up the list in reverse order so we must reverse it now.  */
-  expression_list = nreverse (expression_list);
   if (identifier)
-    expression_list = tree_cons (NULL_TREE, identifier, expression_list);
+    VEC_safe_insert (tree, gc, expression_list, 0, identifier);
 
   return expression_list;
 }
@@ -5623,10 +5626,11 @@ static tree
 cp_parser_new_expression (cp_parser* parser)
 {
   bool global_scope_p;
-  tree placement;
+  VEC(tree,gc) *placement;
   tree type;
-  tree initializer;
+  VEC(tree,gc) *initializer;
   tree nelts;
+  tree ret;
 
   /* Look for the optional `::' operator.  */
   global_scope_p
@@ -5642,7 +5646,11 @@ cp_parser_new_expression (cp_parser* par
   placement = cp_parser_new_placement (parser);
   /* If that didn't work out, there's no new-placement.  */
   if (!cp_parser_parse_definitely (parser))
-    placement = NULL_TREE;
+    {
+      if (placement != NULL)
+	release_tree_vector (placement);
+      placement = NULL;
+    }
 
   /* If the next token is a `(', then we have a parenthesized
      type-id.  */
@@ -5678,16 +5686,25 @@ cp_parser_new_expression (cp_parser* par
       || cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
     initializer = cp_parser_new_initializer (parser);
   else
-    initializer = NULL_TREE;
+    initializer = NULL;
 
   /* A new-expression may not appear in an integral constant
      expression.  */
   if (cp_parser_non_integral_constant_expression (parser, "%<new%>"))
-    return error_mark_node;
+    ret = error_mark_node;
+  else
+    {
+      /* Create a representation of the new-expression.  */
+      ret = build_new (&placement, type, nelts, &initializer, global_scope_p,
+		       tf_warning_or_error);
+    }
 
-  /* Create a representation of the new-expression.  */
-  return build_new (placement, type, nelts, initializer, global_scope_p,
-                    tf_warning_or_error);
+  if (placement != NULL)
+    release_tree_vector (placement);
+  if (initializer != NULL)
+    release_tree_vector (initializer);
+
+  return ret;
 }
 
 /* Parse a new-placement.
@@ -5697,10 +5714,10 @@ cp_parser_new_expression (cp_parser* par
 
    Returns the same representation as for an expression-list.  */
 
-static tree
+static VEC(tree,gc) *
 cp_parser_new_placement (cp_parser* parser)
 {
-  tree expression_list;
+  VEC(tree,gc) *expression_list;
 
   /* Parse the expression-list.  */
   expression_list = (cp_parser_parenthesized_expression_list
@@ -5890,28 +5907,26 @@ cp_parser_direct_new_declarator (cp_pars
      ( expression-list [opt] )
      braced-init-list
 
-   Returns a representation of the expression-list.  If there is no
-   expression-list, VOID_ZERO_NODE is returned.  */
+   Returns a representation of the expression-list.  */
 
-static tree
+static VEC(tree,gc) *
 cp_parser_new_initializer (cp_parser* parser)
 {
-  tree expression_list;
+  VEC(tree,gc) *expression_list;
 
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
     {
+      tree t;
       bool expr_non_constant_p;
       maybe_warn_cpp0x ("extended initializer lists");
-      expression_list = cp_parser_braced_list (parser, &expr_non_constant_p);
-      CONSTRUCTOR_IS_DIRECT_INIT (expression_list) = 1;
-      expression_list = build_tree_list (NULL_TREE, expression_list);
+      t = cp_parser_braced_list (parser, &expr_non_constant_p);
+      CONSTRUCTOR_IS_DIRECT_INIT (t) = 1;
+      expression_list = make_tree_vector_single (t);
     }
   else
     expression_list = (cp_parser_parenthesized_expression_list
 		       (parser, false, /*cast_p=*/false, /*allow_expansion_p=*/true,
 			/*non_constant_p=*/NULL));
-  if (!expression_list)
-    expression_list = void_zero_node;
 
   return expression_list;
 }
@@ -9230,11 +9245,18 @@ cp_parser_mem_initializer (cp_parser* pa
       expression_list = build_tree_list (NULL_TREE, expression_list);
     }
   else
-    expression_list
-      = cp_parser_parenthesized_expression_list (parser, false,
-						 /*cast_p=*/false,
-						 /*allow_expansion_p=*/true,
-						 /*non_constant_p=*/NULL);
+    {
+      VEC(tree,gc)* vec;
+      vec = cp_parser_parenthesized_expression_list (parser, false,
+						     /*cast_p=*/false,
+						     /*allow_expansion_p=*/true,
+						     /*non_constant_p=*/NULL);
+      if (vec == NULL)
+	return error_mark_node;
+      expression_list = build_tree_list_vec (vec);
+      release_tree_vector (vec);
+    }
+
   if (expression_list == error_mark_node)
     return error_mark_node;
   if (!expression_list)
@@ -14590,10 +14612,17 @@ cp_parser_initializer (cp_parser* parser
       init = cp_parser_initializer_clause (parser, non_constant_p);
     }
   else if (token->type == CPP_OPEN_PAREN)
-    init = cp_parser_parenthesized_expression_list (parser, false,
-						    /*cast_p=*/false,
-                                                    /*allow_expansion_p=*/true,
-						    non_constant_p);
+    {
+      VEC(tree,gc) *vec;
+      vec = cp_parser_parenthesized_expression_list (parser, false,
+						     /*cast_p=*/false,
+						     /*allow_expansion_p=*/true,
+						     non_constant_p);
+      if (vec == NULL)
+	return error_mark_node;
+      init = build_tree_list_vec (vec);
+      release_tree_vector (vec);
+    }
   else if (token->type == CPP_OPEN_BRACE)
     {
       maybe_warn_cpp0x ("extended initializer lists");
@@ -16850,10 +16879,18 @@ cp_parser_attribute_list (cp_parser* par
 	  /* If it's an `(', then parse the attribute arguments.  */
 	  if (token->type == CPP_OPEN_PAREN)
 	    {
-	      arguments = cp_parser_parenthesized_expression_list
-			  (parser, true, /*cast_p=*/false,
-                           /*allow_expansion_p=*/false,
-			   /*non_constant_p=*/NULL);
+	      VEC(tree,gc) *vec;
+	      vec = cp_parser_parenthesized_expression_list
+		    (parser, true, /*cast_p=*/false,
+		     /*allow_expansion_p=*/false,
+		     /*non_constant_p=*/NULL);
+	      if (vec == NULL)
+		arguments = error_mark_node;
+	      else
+		{
+		  arguments = build_tree_list_vec (vec);
+		  release_tree_vector (vec);
+		}
 	      /* Save the arguments away.  */
 	      TREE_VALUE (attribute) = arguments;
 	    }
@@ -17981,6 +18018,7 @@ cp_parser_simple_cast_expression (cp_par
 static tree
 cp_parser_functional_cast (cp_parser* parser, tree type)
 {
+  VEC(tree,gc) *vec;
   tree expression_list;
   tree cast;
   bool nonconst_p;
@@ -17995,11 +18033,18 @@ cp_parser_functional_cast (cp_parser* pa
       return finish_compound_literal (type, expression_list);
     }
 
-  expression_list
-    = cp_parser_parenthesized_expression_list (parser, false,
-					       /*cast_p=*/true,
-					       /*allow_expansion_p=*/true,
-					       /*non_constant_p=*/NULL);
+
+  vec = cp_parser_parenthesized_expression_list (parser, false,
+						 /*cast_p=*/true,
+						 /*allow_expansion_p=*/true,
+						 /*non_constant_p=*/NULL);
+  if (vec == NULL)
+    expression_list = error_mark_node;
+  else
+    {
+      expression_list = build_tree_list_vec (vec);
+      release_tree_vector (vec);
+    }
 
   cast = build_functional_cast (type, expression_list,
                                 tf_warning_or_error);
Index: cp/call.c
===================================================================
--- cp/call.c	(revision 146793)
+++ cp/call.c	(working copy)
@@ -145,8 +145,7 @@ static tree convert_like_real (conversio
 			       bool, tsubst_flags_t);
 static void op_error (enum tree_code, enum tree_code, tree, tree,
 		      tree, const char *);
-static tree build_object_call (tree, tree, tsubst_flags_t);
-static tree resolve_args (tree);
+static VEC(tree,gc) *resolve_args (VEC(tree,gc) *);
 static struct z_candidate *build_user_type_conversion_1 (tree, tree, int);
 static void print_z_candidate (const char *, struct z_candidate *);
 static void print_z_candidates (struct z_candidate *);
@@ -154,13 +153,14 @@ static tree build_this (tree);
 static struct z_candidate *splice_viable (struct z_candidate *, bool, bool *);
 static bool any_strictly_viable (struct z_candidate *);
 static struct z_candidate *add_template_candidate
-	(struct z_candidate **, tree, tree, tree, tree, tree,
-	 tree, tree, int, unification_kind_t);
+	(struct z_candidate **, tree, tree, tree, tree, const VEC(tree,gc) *,
+	 tree, tree, tree, int, unification_kind_t);
 static struct z_candidate *add_template_candidate_real
-	(struct z_candidate **, tree, tree, tree, tree, tree,
-	 tree, tree, int, tree, unification_kind_t);
+	(struct z_candidate **, tree, tree, tree, tree, const VEC(tree,gc) *,
+	 tree, tree, tree, int, tree, unification_kind_t);
 static struct z_candidate *add_template_conv_candidate
-	(struct z_candidate **, tree, tree, tree, tree, tree, tree);
+	(struct z_candidate **, tree, tree, tree, const VEC(tree,gc) *, tree,
+	 tree, tree);
 static void add_builtin_candidates
 	(struct z_candidate **, enum tree_code, enum tree_code,
 	 tree, tree *, int);
@@ -172,9 +172,11 @@ static void build_builtin_candidate
 	(struct z_candidate **, tree, tree, tree, tree *, tree *,
 	 int);
 static struct z_candidate *add_conv_candidate
-	(struct z_candidate **, tree, tree, tree, tree, tree);
+	(struct z_candidate **, tree, tree, tree, const VEC(tree,gc) *, tree,
+	 tree);
 static struct z_candidate *add_function_candidate
-	(struct z_candidate **, tree, tree, tree, tree, tree, int);
+	(struct z_candidate **, tree, tree, tree, const VEC(tree,gc) *, tree,
+	 tree, int);
 static conversion *implicit_conversion (tree, tree, tree, bool, int);
 static conversion *standard_conversion (tree, tree, tree, bool, int);
 static conversion *reference_binding (tree, tree, tree, bool, int);
@@ -184,7 +186,7 @@ static bool is_subseq (conversion *, con
 static conversion *maybe_handle_ref_bind (conversion **);
 static void maybe_handle_implicit_object (conversion **);
 static struct z_candidate *add_candidate
-	(struct z_candidate **, tree, tree, size_t,
+	(struct z_candidate **, tree, tree, const VEC(tree,gc) *, size_t,
 	 conversion **, tree, tree, int);
 static tree source_type (conversion *);
 static void add_warning (struct z_candidate *, struct z_candidate *);
@@ -197,7 +199,7 @@ static conversion *conditional_conversio
 static char *name_as_c_string (tree, tree, bool *);
 static tree call_builtin_trap (void);
 static tree prep_operand (tree);
-static void add_candidates (tree, tree, tree, bool, tree, tree,
+static void add_candidates (tree, const VEC(tree,gc) *, tree, bool, tree, tree,
 			    int, struct z_candidate **);
 static conversion *merge_conversion_sequences (conversion *, conversion *);
 static bool magic_varargs_p (tree);
@@ -413,8 +415,13 @@ struct z_candidate {
   /* The FUNCTION_DECL that will be called if this candidate is
      selected by overload resolution.  */
   tree fn;
-  /* The arguments to use when calling this function.  */
-  tree args;
+  /* If not NULL_TREE, the first argument to use when calling this
+     function.  */
+  tree first_arg;
+  /* The rest of the arguments to use when calling this function.  If
+     there are no further arguments this may be NULL or it may be an
+     empty vector.  */
+  const VEC(tree,gc) *args;
   /* The implicit conversion sequences for each of the arguments to
      FN.  */
   conversion **convs;
@@ -996,7 +1003,7 @@ static conversion *
 convert_class_to_reference (tree reference_type, tree s, tree expr)
 {
   tree conversions;
-  tree arglist;
+  tree first_arg;
   conversion *conv;
   tree t;
   struct z_candidate *candidates;
@@ -1029,8 +1036,7 @@ convert_class_to_reference (tree referen
      error messages, which we should not issue now because we are just
      trying to find a conversion operator.  Therefore, we use NULL,
      cast to the appropriate type.  */
-  arglist = build_int_cst (build_pointer_type (s), 0);
-  arglist = build_tree_list (NULL_TREE, arglist);
+  first_arg = build_int_cst (build_pointer_type (s), 0);
 
   t = TREE_TYPE (reference_type);
 
@@ -1052,7 +1058,8 @@ convert_class_to_reference (tree referen
 	      cand = add_template_candidate (&candidates,
 					     f, s,
 					     NULL_TREE,
-					     arglist,
+					     first_arg,
+					     NULL,
 					     reference_type,
 					     TYPE_BINFO (s),
 					     TREE_PURPOSE (conversions),
@@ -1077,8 +1084,8 @@ convert_class_to_reference (tree referen
 	    }
 	  else if (TREE_CODE (t2) == REFERENCE_TYPE
 		   && reference_compatible_p (t, TREE_TYPE (t2)))
-	    cand = add_function_candidate (&candidates, f, s, arglist,
-					   TYPE_BINFO (s),
+	    cand = add_function_candidate (&candidates, f, s, first_arg,
+					   NULL, TYPE_BINFO (s),
 					   TREE_PURPOSE (conversions),
 					   LOOKUP_NORMAL);
 
@@ -1116,9 +1123,9 @@ convert_class_to_reference (tree referen
 
   /* Now that we know that this is the function we're going to use fix
      the dummy first argument.  */
-  cand->args = tree_cons (NULL_TREE,
-			  build_this (expr),
-			  TREE_CHAIN (cand->args));
+  gcc_assert (cand->first_arg == NULL_TREE
+	      || integer_zerop (cand->first_arg));
+  cand->first_arg = build_this (expr);
 
   /* Build a user-defined conversion sequence representing the
      conversion.  */
@@ -1416,11 +1423,12 @@ implicit_conversion (tree to, tree from,
 }
 
 /* Add a new entry to the list of candidates.  Used by the add_*_candidate
-   functions.  */
+   functions.  ARGS will not be changed until a single candidate is
+   selected.  */
 
 static struct z_candidate *
 add_candidate (struct z_candidate **candidates,
-	       tree fn, tree args,
+	       tree fn, tree first_arg, const VEC(tree,gc) *args,
 	       size_t num_convs, conversion **convs,
 	       tree access_path, tree conversion_path,
 	       int viable)
@@ -1429,6 +1437,7 @@ add_candidate (struct z_candidate **cand
     conversion_obstack_alloc (sizeof (struct z_candidate));
 
   cand->fn = fn;
+  cand->first_arg = first_arg;
   cand->args = args;
   cand->convs = convs;
   cand->num_convs = num_convs;
@@ -1441,24 +1450,27 @@ add_candidate (struct z_candidate **cand
   return cand;
 }
 
-/* Create an overload candidate for the function or method FN called with
-   the argument list ARGLIST and add it to CANDIDATES.  FLAGS is passed on
-   to implicit_conversion.
+/* Create an overload candidate for the function or method FN called
+   with the argument list FIRST_ARG/ARGS and add it to CANDIDATES.
+   FLAGS is passed on to implicit_conversion.
+
+   This does not change ARGS.
 
    CTYPE, if non-NULL, is the type we want to pretend this function
    comes from for purposes of overload resolution.  */
 
 static struct z_candidate *
 add_function_candidate (struct z_candidate **candidates,
-			tree fn, tree ctype, tree arglist,
-			tree access_path, tree conversion_path,
-			int flags)
+			tree fn, tree ctype, tree first_arg,
+			const VEC(tree,gc) *args, tree access_path,
+			tree conversion_path, int flags)
 {
   tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (fn));
   int i, len;
   conversion **convs;
-  tree parmnode, argnode;
-  tree orig_arglist;
+  tree parmnode;
+  tree orig_first_arg = first_arg;
+  int skip;
   int viable = 1;
 
   /* At this point we should not see any functions which haven't been
@@ -1471,13 +1483,17 @@ add_function_candidate (struct z_candida
   if (DECL_CONSTRUCTOR_P (fn))
     {
       parmlist = skip_artificial_parms_for (fn, parmlist);
-      orig_arglist = arglist;
-      arglist = skip_artificial_parms_for (fn, arglist);
+      skip = num_artificial_parms_for (fn);
+      if (skip > 0 && first_arg != NULL_TREE)
+	{
+	  --skip;
+	  first_arg = NULL_TREE;
+	}
     }
   else
-    orig_arglist = arglist;
+    skip = 0;
 
-  len = list_length (arglist);
+  len = VEC_length (tree, args) - skip + (first_arg != NULL_TREE ? 1 : 0);
   convs = alloc_conversions (len);
 
   /* 13.3.2 - Viable functions [over.match.viable]
@@ -1510,18 +1526,23 @@ add_function_candidate (struct z_candida
      to the corresponding parameter of F.  */
 
   parmnode = parmlist;
-  argnode = arglist;
 
   for (i = 0; i < len; ++i)
     {
-      tree arg = TREE_VALUE (argnode);
-      tree argtype = lvalue_type (arg);
+      tree arg, argtype;
       conversion *t;
       int is_this;
 
       if (parmnode == void_list_node)
 	break;
 
+      if (i == 0 && first_arg != NULL_TREE)
+	arg = first_arg;
+      else
+	arg = VEC_index (tree, args,
+			 i + skip - (first_arg != NULL_TREE ? 1 : 0));
+      argtype = lvalue_type (arg);
+
       is_this = (i == 0 && DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
 		 && ! DECL_CONSTRUCTOR_P (fn));
 
@@ -1575,18 +1596,18 @@ add_function_candidate (struct z_candida
 
       if (parmnode)
 	parmnode = TREE_CHAIN (parmnode);
-      argnode = TREE_CHAIN (argnode);
     }
 
  out:
-  return add_candidate (candidates, fn, orig_arglist, len, convs,
+  return add_candidate (candidates, fn, orig_first_arg, args, len, convs,
 			access_path, conversion_path, viable);
 }
 
 /* Create an overload candidate for the conversion function FN which will
    be invoked for expression OBJ, producing a pointer-to-function which
-   will in turn be called with the argument list ARGLIST, and add it to
-   CANDIDATES.  FLAGS is passed on to implicit_conversion.
+   will in turn be called with the argument list FIRST_ARG/ARGLIST,
+   and add it to CANDIDATES.  This does not change ARGLIST.  FLAGS is
+   passed on to implicit_conversion.
 
    Actually, we don't really care about FN; we care about the type it
    converts to.  There may be multiple conversion functions that will
@@ -1596,21 +1617,21 @@ add_function_candidate (struct z_candida
 
 static struct z_candidate *
 add_conv_candidate (struct z_candidate **candidates, tree fn, tree obj,
-		    tree arglist, tree access_path, tree conversion_path)
+		    tree first_arg, const VEC(tree,gc) *arglist,
+		    tree access_path, tree conversion_path)
 {
   tree totype = TREE_TYPE (TREE_TYPE (fn));
   int i, len, viable, flags;
-  tree parmlist, parmnode, argnode;
+  tree parmlist, parmnode;
   conversion **convs;
 
   for (parmlist = totype; TREE_CODE (parmlist) != FUNCTION_TYPE; )
     parmlist = TREE_TYPE (parmlist);
   parmlist = TYPE_ARG_TYPES (parmlist);
 
-  len = list_length (arglist) + 1;
+  len = VEC_length (tree, arglist) + (first_arg != NULL_TREE ? 1 : 0) + 1;
   convs = alloc_conversions (len);
   parmnode = parmlist;
-  argnode = arglist;
   viable = 1;
   flags = LOOKUP_NORMAL;
 
@@ -1620,11 +1641,19 @@ add_conv_candidate (struct z_candidate *
 
   for (i = 0; i < len; ++i)
     {
-      tree arg = i == 0 ? obj : TREE_VALUE (argnode);
-      tree argtype = lvalue_type (arg);
+      tree arg, argtype;
       conversion *t;
 
       if (i == 0)
+	arg = obj;
+      else if (i == 1 && first_arg != NULL_TREE)
+	arg = first_arg;
+      else
+	arg = VEC_index (tree, arglist,
+			 i - (first_arg != NULL_TREE ? 1 : 0) - 1);
+      argtype = lvalue_type (arg);
+
+      if (i == 0)
 	t = implicit_conversion (totype, argtype, arg, /*c_cast_p=*/false,
 				 flags);
       else if (parmnode == void_list_node)
@@ -1650,7 +1679,6 @@ add_conv_candidate (struct z_candidate *
 
       if (parmnode)
 	parmnode = TREE_CHAIN (parmnode);
-      argnode = TREE_CHAIN (argnode);
     }
 
   if (i < len)
@@ -1659,7 +1687,7 @@ add_conv_candidate (struct z_candidate *
   if (!sufficient_parms_p (parmnode))
     viable = 0;
 
-  return add_candidate (candidates, totype, arglist, len, convs,
+  return add_candidate (candidates, totype, first_arg, arglist, len, convs,
 			access_path, conversion_path, viable);
 }
 
@@ -1711,7 +1739,7 @@ build_builtin_candidate (struct z_candid
 	viable = 0;
     }
 
-  add_candidate (candidates, fnname, /*args=*/NULL_TREE,
+  add_candidate (candidates, fnname, /*first_arg=*/NULL_TREE, /*args=*/NULL,
 		 num_convs, convs,
 		 /*access_path=*/NULL_TREE,
 		 /*conversion_path=*/NULL_TREE,
@@ -2332,37 +2360,79 @@ add_builtin_candidates (struct z_candida
 
    TMPL is the template.  EXPLICIT_TARGS are any explicit template
    arguments.  ARGLIST is the arguments provided at the call-site.
-   The RETURN_TYPE is the desired type for conversion operators.  If
-   OBJ is NULL_TREE, FLAGS and CTYPE are as for add_function_candidate.
-   If an OBJ is supplied, FLAGS and CTYPE are ignored, and OBJ is as for
-   add_conv_candidate.  */
+   This does not change ARGLIST.  The RETURN_TYPE is the desired type
+   for conversion operators.  If OBJ is NULL_TREE, FLAGS and CTYPE are
+   as for add_function_candidate.  If an OBJ is supplied, FLAGS and
+   CTYPE are ignored, and OBJ is as for add_conv_candidate.  */
 
 static struct z_candidate*
 add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
-			     tree ctype, tree explicit_targs, tree arglist,
-			     tree return_type, tree access_path,
-			     tree conversion_path, int flags, tree obj,
-			     unification_kind_t strict)
+			     tree ctype, tree explicit_targs, tree first_arg,
+			     const VEC(tree,gc) *arglist, tree return_type,
+			     tree access_path, tree conversion_path,
+			     int flags, tree obj, unification_kind_t strict)
 {
   int ntparms = DECL_NTPARMS (tmpl);
   tree targs = make_tree_vec (ntparms);
-  tree args_without_in_chrg = arglist;
+  unsigned int nargs;
+  int skip_without_in_chrg;
+  tree first_arg_without_in_chrg;
+  tree *args_without_in_chrg;
+  unsigned int nargs_without_in_chrg;
+  unsigned int ia, ix;
+  tree arg;
   struct z_candidate *cand;
   int i;
   tree fn;
 
+  nargs = (first_arg == NULL_TREE ? 0 : 1) + VEC_length (tree, arglist);
+
+  skip_without_in_chrg = 0;
+
+  first_arg_without_in_chrg = first_arg;
+
   /* We don't do deduction on the in-charge parameter, the VTT
      parameter or 'this'.  */
   if (DECL_NONSTATIC_MEMBER_FUNCTION_P (tmpl))
-    args_without_in_chrg = TREE_CHAIN (args_without_in_chrg);
+    {
+      if (first_arg_without_in_chrg != NULL_TREE)
+	first_arg_without_in_chrg = NULL_TREE;
+      else
+	++skip_without_in_chrg;
+    }
 
   if ((DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (tmpl)
        || DECL_BASE_CONSTRUCTOR_P (tmpl))
       && CLASSTYPE_VBASECLASSES (DECL_CONTEXT (tmpl)))
-    args_without_in_chrg = TREE_CHAIN (args_without_in_chrg);
+    {
+      if (first_arg_without_in_chrg != NULL_TREE)
+	first_arg_without_in_chrg = NULL_TREE;
+      else
+	++skip_without_in_chrg;
+    }
+
+  nargs_without_in_chrg = ((first_arg_without_in_chrg != NULL_TREE ? 1 : 0)
+			   + (VEC_length (tree, arglist)
+			      - skip_without_in_chrg));
+  args_without_in_chrg = XALLOCAVEC (tree, nargs_without_in_chrg);
+  ia = 0;
+  if (first_arg_without_in_chrg != NULL_TREE)
+    {
+      args_without_in_chrg[ia] = first_arg_without_in_chrg;
+      ++ia;
+    }
+  for (ix = skip_without_in_chrg;
+       VEC_iterate (tree, arglist, ix, arg);
+       ++ix)
+    {
+      args_without_in_chrg[ia] = arg;
+      ++ia;
+    }
+  gcc_assert (ia == nargs_without_in_chrg);
 
   i = fn_type_unification (tmpl, explicit_targs, targs,
 			   args_without_in_chrg,
+			   nargs_without_in_chrg,
 			   return_type, strict, flags);
 
   if (i != 0)
@@ -2394,7 +2464,7 @@ add_template_candidate_real (struct z_ca
      class type, and a logical interpretation is that the intent was
      to forbid the instantiation of member templates which would then
      have that form.  */
-  if (DECL_CONSTRUCTOR_P (fn) && list_length (arglist) == 2)
+  if (DECL_CONSTRUCTOR_P (fn) && nargs == 2)
     {
       tree arg_types = FUNCTION_FIRST_USER_PARMTYPE (fn);
       if (arg_types && same_type_p (TYPE_MAIN_VARIANT (TREE_VALUE (arg_types)),
@@ -2404,11 +2474,11 @@ add_template_candidate_real (struct z_ca
 
   if (obj != NULL_TREE)
     /* Aha, this is a conversion function.  */
-    cand = add_conv_candidate (candidates, fn, obj, access_path,
-			       conversion_path, arglist);
+    cand = add_conv_candidate (candidates, fn, obj, first_arg, arglist,
+			       access_path, conversion_path);
   else
     cand = add_function_candidate (candidates, fn, ctype,
-				   arglist, access_path,
+				   first_arg, arglist, access_path,
 				   conversion_path, flags);
   if (DECL_TI_TEMPLATE (fn) != tmpl)
     /* This situation can occur if a member template of a template
@@ -2438,26 +2508,29 @@ add_template_candidate_real (struct z_ca
 
 static struct z_candidate *
 add_template_candidate (struct z_candidate **candidates, tree tmpl, tree ctype,
-			tree explicit_targs, tree arglist, tree return_type,
+			tree explicit_targs, tree first_arg,
+			const VEC(tree,gc) *arglist, tree return_type,
 			tree access_path, tree conversion_path, int flags,
 			unification_kind_t strict)
 {
   return
     add_template_candidate_real (candidates, tmpl, ctype,
-				 explicit_targs, arglist, return_type,
-				 access_path, conversion_path,
+				 explicit_targs, first_arg, arglist,
+				 return_type, access_path, conversion_path,
 				 flags, NULL_TREE, strict);
 }
 
 
 static struct z_candidate *
 add_template_conv_candidate (struct z_candidate **candidates, tree tmpl,
-			     tree obj, tree arglist, tree return_type,
-			     tree access_path, tree conversion_path)
+			     tree obj, tree first_arg,
+			     const VEC(tree,gc) *arglist,
+			     tree return_type, tree access_path,
+			     tree conversion_path)
 {
   return
     add_template_candidate_real (candidates, tmpl, NULL_TREE, NULL_TREE,
-				 arglist, return_type, access_path,
+				 first_arg, arglist, return_type, access_path,
 				 conversion_path, 0, obj, DEDUCE_CONV);
 }
 
@@ -2664,7 +2737,8 @@ build_user_type_conversion_1 (tree totyp
   tree ctors = NULL_TREE;
   tree conv_fns = NULL_TREE;
   conversion *conv = NULL;
-  tree args = NULL_TREE;
+  tree first_arg = NULL_TREE;
+  VEC(tree,gc) *args = NULL;
   bool any_viable_p;
   int convflags;
 
@@ -2704,15 +2778,13 @@ build_user_type_conversion_1 (tree totyp
 
   if (ctors)
     {
-      tree t;
-
       ctors = BASELINK_FUNCTIONS (ctors);
 
-      t = build_int_cst (build_pointer_type (totype), 0);
+      first_arg = build_int_cst (build_pointer_type (totype), 0);
       if (BRACE_ENCLOSED_INITIALIZER_P (expr)
 	  && !TYPE_HAS_LIST_CTOR (totype))
 	{
-	  args = ctor_to_list (expr);
+	  args = ctor_to_vec (expr);
 	  /* We still allow more conversions within an init-list.  */
 	  flags = ((flags & ~LOOKUP_NO_CONVERSION)
 		   /* But not for the copy ctor.  */
@@ -2720,12 +2792,12 @@ build_user_type_conversion_1 (tree totyp
 		   |LOOKUP_NO_NARROWING);
 	}
       else
-	args = build_tree_list (NULL_TREE, expr);
+	args = make_tree_vector_single (expr);
+
       /* We should never try to call the abstract or base constructor
 	 from here.  */
       gcc_assert (!DECL_HAS_IN_CHARGE_PARM_P (OVL_CURRENT (ctors))
 		  && !DECL_HAS_VTT_PARM_P (OVL_CURRENT (ctors)));
-      args = tree_cons (NULL_TREE, t, args);
     }
   for (; ctors; ctors = OVL_NEXT (ctors))
     {
@@ -2736,14 +2808,14 @@ build_user_type_conversion_1 (tree totyp
 
       if (TREE_CODE (ctor) == TEMPLATE_DECL)
 	cand = add_template_candidate (&candidates, ctor, totype,
-				       NULL_TREE, args, NULL_TREE,
+				       NULL_TREE, first_arg, args, NULL_TREE,
 				       TYPE_BINFO (totype),
 				       TYPE_BINFO (totype),
 				       flags,
 				       DEDUCE_CALL);
       else
 	cand = add_function_candidate (&candidates, ctor, totype,
-				       args, TYPE_BINFO (totype),
+				       first_arg, args, TYPE_BINFO (totype),
 				       TYPE_BINFO (totype),
 				       flags);
 
@@ -2767,7 +2839,7 @@ build_user_type_conversion_1 (tree totyp
     }
 
   if (conv_fns)
-    args = build_tree_list (NULL_TREE, build_this (expr));
+    first_arg = build_this (expr);
 
   for (; conv_fns; conv_fns = TREE_CHAIN (conv_fns))
     {
@@ -2795,14 +2867,14 @@ build_user_type_conversion_1 (tree totyp
 	  if (TREE_CODE (fn) == TEMPLATE_DECL)
 	    cand = add_template_candidate (&candidates, fn, fromtype,
 					   NULL_TREE,
-					   args, totype,
+					   first_arg, NULL, totype,
 					   TYPE_BINFO (fromtype),
 					   conversion_path,
 					   flags,
 					   DEDUCE_CONV);
 	  else
 	    cand = add_function_candidate (&candidates, fn, fromtype,
-					   args,
+					   first_arg, NULL,
 					   TYPE_BINFO (fromtype),
 					   conversion_path,
 					   flags);
@@ -2905,23 +2977,23 @@ build_user_type_conversion (tree totype,
 
 /* Do any initial processing on the arguments to a function call.  */
 
-static tree
-resolve_args (tree args)
+static VEC(tree,gc) *
+resolve_args (VEC(tree,gc) *args)
 {
-  tree t;
-  for (t = args; t; t = TREE_CHAIN (t))
-    {
-      tree arg = TREE_VALUE (t);
+  unsigned int ix;
+  tree arg;
 
+  for (ix = 0; VEC_iterate (tree, args, ix, arg); ++ix)
+    {
       if (error_operand_p (arg))
-	return error_mark_node;
+	return NULL;
       else if (VOID_TYPE_P (TREE_TYPE (arg)))
 	{
 	  error ("invalid use of void expression");
-	  return error_mark_node;
+	  return NULL;
 	}
       else if (invalid_nonstatic_memfn_p (arg, tf_warning_or_error))
-	return error_mark_node;
+	return NULL;
     }
   return args;
 }
@@ -2940,7 +3012,7 @@ resolve_args (tree args)
 
 static struct z_candidate *
 perform_overload_resolution (tree fn,
-			     tree args,
+			     const VEC(tree,gc) *args,
 			     struct z_candidate **candidates,
 			     bool *any_viable_p)
 {
@@ -2951,12 +3023,11 @@ perform_overload_resolution (tree fn,
   *candidates = NULL;
   *any_viable_p = true;
 
-  /* Check FN and ARGS.  */
+  /* Check FN.  */
   gcc_assert (TREE_CODE (fn) == FUNCTION_DECL
 	      || TREE_CODE (fn) == TEMPLATE_DECL
 	      || TREE_CODE (fn) == OVERLOAD
 	      || TREE_CODE (fn) == TEMPLATE_ID_EXPR);
-  gcc_assert (!args || TREE_CODE (args) == TREE_LIST);
 
   if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
     {
@@ -2981,10 +3052,11 @@ perform_overload_resolution (tree fn,
 }
 
 /* Return an expression for a call to FN (a namespace-scope function,
-   or a static member function) with the ARGS.  */
+   or a static member function) with the ARGS.  This may change
+   ARGS.  */
 
 tree
-build_new_function_call (tree fn, tree args, bool koenig_p, 
+build_new_function_call (tree fn, VEC(tree,gc) **args, bool koenig_p, 
 			 tsubst_flags_t complain)
 {
   struct z_candidate *candidates, *cand;
@@ -2992,9 +3064,12 @@ build_new_function_call (tree fn, tree a
   void *p;
   tree result;
 
-  args = resolve_args (args);
-  if (args == error_mark_node)
-    return error_mark_node;
+  if (args != NULL && *args != NULL)
+    {
+      *args = resolve_args (*args);
+      if (*args == NULL)
+	return error_mark_node;
+    }
 
   /* If this function was found without using argument dependent
      lookup, then we want to ignore any undeclared friend
@@ -3008,7 +3083,8 @@ build_new_function_call (tree fn, tree a
 	{
 	  if (complain & tf_error)
 	    error ("no matching function for call to %<%D(%A)%>",
-		   DECL_NAME (OVL_CURRENT (orig_fn)), args);
+		   DECL_NAME (OVL_CURRENT (orig_fn)),
+		   build_tree_list_vec (*args));
 	  return error_mark_node;
 	}
     }
@@ -3016,22 +3092,22 @@ build_new_function_call (tree fn, tree a
   /* Get the high-water mark for the CONVERSION_OBSTACK.  */
   p = conversion_obstack_alloc (0);
 
-  cand = perform_overload_resolution (fn, args, &candidates, &any_viable_p);
+  cand = perform_overload_resolution (fn, *args, &candidates, &any_viable_p);
 
   if (!cand)
     {
       if (complain & tf_error)
 	{
 	  if (!any_viable_p && candidates && ! candidates->next)
-	    return cp_build_function_call (candidates->fn, args, complain);
+	    return cp_build_function_call_vec (candidates->fn, args, complain);
 	  if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
 	    fn = TREE_OPERAND (fn, 0);
 	  if (!any_viable_p)
 	    error ("no matching function for call to %<%D(%A)%>",
-		   DECL_NAME (OVL_CURRENT (fn)), args);
+		   DECL_NAME (OVL_CURRENT (fn)), build_tree_list_vec (*args));
 	  else
 	    error ("call of overloaded %<%D(%A)%> is ambiguous",
-		   DECL_NAME (OVL_CURRENT (fn)), args);
+		   DECL_NAME (OVL_CURRENT (fn)), build_tree_list_vec (*args));
 	  if (candidates)
 	    print_z_candidates (candidates);
 	}
@@ -3048,15 +3124,16 @@ build_new_function_call (tree fn, tree a
 
 /* Build a call to a global operator new.  FNNAME is the name of the
    operator (either "operator new" or "operator new[]") and ARGS are
-   the arguments provided.  *SIZE points to the total number of bytes
-   required by the allocation, and is updated if that is changed here.
-   *COOKIE_SIZE is non-NULL if a cookie should be used.  If this
-   function determines that no cookie should be used, after all,
-   *COOKIE_SIZE is set to NULL_TREE.  If FN is non-NULL, it will be
-   set, upon return, to the allocation function called.  */
+   the arguments provided.  This may change ARGS.  *SIZE points to the
+   total number of bytes required by the allocation, and is updated if
+   that is changed here.  *COOKIE_SIZE is non-NULL if a cookie should
+   be used.  If this function determines that no cookie should be
+   used, after all, *COOKIE_SIZE is set to NULL_TREE.  If FN is
+   non-NULL, it will be set, upon return, to the allocation function
+   called.  */
 
 tree
-build_operator_new_call (tree fnname, tree args,
+build_operator_new_call (tree fnname, VEC(tree,gc) **args,
 			 tree *size, tree *cookie_size,
 			 tree *fn)
 {
@@ -3067,10 +3144,10 @@ build_operator_new_call (tree fnname, tr
 
   if (fn)
     *fn = NULL_TREE;
-  args = tree_cons (NULL_TREE, *size, args);
-  args = resolve_args (args);
-  if (args == error_mark_node)
-    return args;
+  VEC_safe_insert (tree, gc, *args, 0, *size);
+  *args = resolve_args (*args);
+  if (*args == NULL)
+    return error_mark_node;
 
   /* Based on:
 
@@ -3081,10 +3158,10 @@ build_operator_new_call (tree fnname, tr
        up in the global scope.
 
      we disregard block-scope declarations of "operator new".  */
-  fns = lookup_function_nonclass (fnname, args, /*block_p=*/false);
+  fns = lookup_function_nonclass (fnname, *args, /*block_p=*/false);
 
   /* Figure out what function is being called.  */
-  cand = perform_overload_resolution (fns, args, &candidates, &any_viable_p);
+  cand = perform_overload_resolution (fns, *args, &candidates, &any_viable_p);
 
   /* If no suitable function could be found, issue an error message
      and give up.  */
@@ -3092,10 +3169,10 @@ build_operator_new_call (tree fnname, tr
     {
       if (!any_viable_p)
 	error ("no matching function for call to %<%D(%A)%>",
-	       DECL_NAME (OVL_CURRENT (fns)), args);
+	       DECL_NAME (OVL_CURRENT (fns)), build_tree_list_vec (*args));
       else
 	error ("call of overloaded %<%D(%A)%> is ambiguous",
-	       DECL_NAME (OVL_CURRENT (fns)), args);
+	       DECL_NAME (OVL_CURRENT (fns)), build_tree_list_vec (*args));
       if (candidates)
 	print_z_candidates (candidates);
       return error_mark_node;
@@ -3109,12 +3186,11 @@ build_operator_new_call (tree fnname, tr
        bool use_cookie = true;
        if (!abi_version_at_least (2))
 	 {
-	   tree placement = TREE_CHAIN (args);
 	   /* In G++ 3.2, the check was implemented incorrectly; it
 	      looked at the placement expression, rather than the
 	      type of the function.  */
-	   if (placement && !TREE_CHAIN (placement)
-	       && same_type_p (TREE_TYPE (TREE_VALUE (placement)),
+	   if (VEC_length (tree, *args) == 2
+	       && same_type_p (TREE_TYPE (VEC_index (tree, *args, 1)),
 			       ptr_type_node))
 	     use_cookie = false;
 	 }
@@ -3138,7 +3214,7 @@ build_operator_new_call (tree fnname, tr
 	   /* Update the total size.  */
 	   *size = size_binop (PLUS_EXPR, *size, *cookie_size);
 	   /* Update the argument list to reflect the adjusted size.  */
-	   TREE_VALUE (args) = *size;
+	   VEC_replace (tree, *args, 0, *size);
 	 }
        else
 	 *cookie_size = NULL_TREE;
@@ -3152,16 +3228,23 @@ build_operator_new_call (tree fnname, tr
    return build_over_call (cand, LOOKUP_NORMAL, tf_warning_or_error);
 }
 
-static tree
-build_object_call (tree obj, tree args, tsubst_flags_t complain)
+/* Build a new call to operator().  This may change ARGS.  */
+
+tree
+build_op_call (tree obj, VEC(tree,gc) **args, tsubst_flags_t complain)
 {
   struct z_candidate *candidates = 0, *cand;
-  tree fns, convs, mem_args = NULL_TREE;
+  tree fns, convs, first_mem_arg = NULL_TREE;
   tree type = TREE_TYPE (obj);
   bool any_viable_p;
   tree result = NULL_TREE;
   void *p;
 
+  if (error_operand_p (obj))
+    return error_mark_node;
+
+  obj = prep_operand (obj);
+
   if (TYPE_PTRMEMFUNC_P (type))
     {
       if (complain & tf_error)
@@ -3180,10 +3263,12 @@ build_object_call (tree obj, tree args, 
   else
     fns = NULL_TREE;
 
-  args = resolve_args (args);
-
-  if (args == error_mark_node)
-    return error_mark_node;
+  if (args != NULL && *args != NULL)
+    {
+      *args = resolve_args (*args);
+      if (*args == NULL)
+	return error_mark_node;
+    }
 
   /* Get the high-water mark for the CONVERSION_OBSTACK.  */
   p = conversion_obstack_alloc (0);
@@ -3191,20 +3276,20 @@ build_object_call (tree obj, tree args, 
   if (fns)
     {
       tree base = BINFO_TYPE (BASELINK_BINFO (fns));
-      mem_args = tree_cons (NULL_TREE, build_this (obj), args);
+      first_mem_arg = build_this (obj);
 
       for (fns = BASELINK_FUNCTIONS (fns); fns; fns = OVL_NEXT (fns))
 	{
 	  tree fn = OVL_CURRENT (fns);
 	  if (TREE_CODE (fn) == TEMPLATE_DECL)
 	    add_template_candidate (&candidates, fn, base, NULL_TREE,
-				    mem_args, NULL_TREE,
+				    first_mem_arg, *args, NULL_TREE,
 				    TYPE_BINFO (type),
 				    TYPE_BINFO (type),
 				    LOOKUP_NORMAL, DEDUCE_CALL);
 	  else
 	    add_function_candidate
-	      (&candidates, fn, base, mem_args, TYPE_BINFO (type),
+	      (&candidates, fn, base, first_mem_arg, *args, TYPE_BINFO (type),
 	       TYPE_BINFO (type), LOOKUP_NORMAL);
 	}
     }
@@ -3228,12 +3313,12 @@ build_object_call (tree obj, tree args, 
 	    tree fn = OVL_CURRENT (fns);
 	    if (TREE_CODE (fn) == TEMPLATE_DECL)
 	      add_template_conv_candidate
-		(&candidates, fn, obj, args, totype,
+		(&candidates, fn, obj, NULL_TREE, *args, totype,
 		 /*access_path=*/NULL_TREE,
 		 /*conversion_path=*/NULL_TREE);
 	    else
-	      add_conv_candidate (&candidates, fn, obj, args,
-				  /*conversion_path=*/NULL_TREE,
+	      add_conv_candidate (&candidates, fn, obj, NULL_TREE,
+				  *args, /*conversion_path=*/NULL_TREE,
 				  /*access_path=*/NULL_TREE);
 	  }
     }
@@ -3243,7 +3328,8 @@ build_object_call (tree obj, tree args, 
     {
       if (complain & tf_error)
         {
-          error ("no match for call to %<(%T) (%A)%>", TREE_TYPE (obj), args);
+          error ("no match for call to %<(%T) (%A)%>", TREE_TYPE (obj),
+		 build_tree_list_vec (*args));
           print_z_candidates (candidates);
         }
       result = error_mark_node;
@@ -3256,7 +3342,7 @@ build_object_call (tree obj, tree args, 
           if (complain & tf_error)
             {
               error ("call of %<(%T) (%A)%> is ambiguous", 
-                     TREE_TYPE (obj), args);
+                     TREE_TYPE (obj), build_tree_list_vec (*args));
               print_z_candidates (candidates);
             }
 	  result = error_mark_node;
@@ -3272,7 +3358,7 @@ build_object_call (tree obj, tree args, 
 	  obj = convert_like_with_context (cand->convs[0], obj, cand->fn, -1,
 					   complain);
 	  obj = convert_from_reference (obj);
-	  result = cp_build_function_call (obj, args, complain);
+	  result = cp_build_function_call_vec (obj, args, complain);
 	}
     }
 
@@ -3824,29 +3910,33 @@ prep_operand (tree operand)
 /* Add each of the viable functions in FNS (a FUNCTION_DECL or
    OVERLOAD) to the CANDIDATES, returning an updated list of
    CANDIDATES.  The ARGS are the arguments provided to the call,
-   without any implicit object parameter.  The EXPLICIT_TARGS are
-   explicit template arguments provided.  TEMPLATE_ONLY is true if
-   only template functions should be considered.  CONVERSION_PATH,
-   ACCESS_PATH, and FLAGS are as for add_function_candidate.  */
+   without any implicit object parameter.  This may change ARGS.  The
+   EXPLICIT_TARGS are explicit template arguments provided.
+   TEMPLATE_ONLY is true if only template functions should be
+   considered.  CONVERSION_PATH, ACCESS_PATH, and FLAGS are as for
+   add_function_candidate.  */
 
 static void
-add_candidates (tree fns, tree args,
+add_candidates (tree fns, const VEC(tree,gc) *args,
 		tree explicit_targs, bool template_only,
 		tree conversion_path, tree access_path,
 		int flags,
 		struct z_candidate **candidates)
 {
   tree ctype;
-  tree non_static_args;
+  VEC(tree,gc) *non_static_args;
+  tree first_arg;
 
   ctype = conversion_path ? BINFO_TYPE (conversion_path) : NULL_TREE;
   /* Delay creating the implicit this parameter until it is needed.  */
-  non_static_args = NULL_TREE;
+  non_static_args = NULL;
+  first_arg = NULL_TREE;
 
   while (fns)
     {
       tree fn;
-      tree fn_args;
+      tree fn_first_arg;
+      const VEC(tree,gc) *fn_args;
 
       fn = OVL_CURRENT (fns);
       /* Figure out which set of arguments to use.  */
@@ -3854,21 +3944,34 @@ add_candidates (tree fns, tree args,
 	{
 	  /* If this function is a non-static member, prepend the implicit
 	     object parameter.  */
-	  if (!non_static_args)
-	    non_static_args = tree_cons (NULL_TREE,
-					 build_this (TREE_VALUE (args)),
-					 TREE_CHAIN (args));
+	  if (non_static_args == NULL)
+	    {
+	      unsigned int ix;
+	      tree arg;
+
+	      non_static_args = VEC_alloc (tree, gc,
+					   VEC_length (tree, args) - 1);
+	      for (ix = 1; VEC_iterate (tree, args, ix, arg); ++ix)
+		VEC_quick_push (tree, non_static_args, arg);
+	    }
+	  if (first_arg == NULL_TREE)
+	    first_arg = build_this (VEC_index (tree, args, 0));
+	  fn_first_arg = first_arg;
 	  fn_args = non_static_args;
 	}
       else
-	/* Otherwise, just use the list of arguments provided.  */
-	fn_args = args;
+	{
+	  /* Otherwise, just use the list of arguments provided.  */
+	  fn_first_arg = NULL_TREE;
+	  fn_args = args;
+	}
 
       if (TREE_CODE (fn) == TEMPLATE_DECL)
 	add_template_candidate (candidates,
 				fn,
 				ctype,
 				explicit_targs,
+				fn_first_arg, 
 				fn_args,
 				NULL_TREE,
 				access_path,
@@ -3879,6 +3982,7 @@ add_candidates (tree fns, tree args,
 	add_function_candidate (candidates,
 				fn,
 				ctype,
+				fn_first_arg,
 				fn_args,
 				access_path,
 				conversion_path,
@@ -3892,7 +3996,8 @@ build_new_op (enum tree_code code, int f
 	      bool *overloaded_p, tsubst_flags_t complain)
 {
   struct z_candidate *candidates = 0, *cand;
-  tree arglist, fnname;
+  VEC(tree,gc) *arglist;
+  tree fnname;
   tree args[3];
   tree result = NULL_TREE;
   bool result_valid_p = false;
@@ -3930,7 +4035,8 @@ build_new_op (enum tree_code code, int f
       gcc_unreachable ();
 
     case CALL_EXPR:
-      return build_object_call (arg1, arg2, complain);
+      /* Use build_op_call instead.  */
+      gcc_unreachable ();
 
     case TRUTH_ORIF_EXPR:
     case TRUTH_ANDIF_EXPR:
@@ -3963,12 +4069,12 @@ build_new_op (enum tree_code code, int f
   if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR)
     arg2 = integer_zero_node;
 
-  arglist = NULL_TREE;
-  if (arg3)
-    arglist = tree_cons (NULL_TREE, arg3, arglist);
-  if (arg2)
-    arglist = tree_cons (NULL_TREE, arg2, arglist);
-  arglist = tree_cons (NULL_TREE, arg1, arglist);
+  arglist = VEC_alloc (tree, gc, 3);
+  VEC_quick_push (tree, arglist, arg1);
+  if (arg2 != NULL_TREE)
+    VEC_quick_push (tree, arglist, arg2);
+  if (arg3 != NULL_TREE)
+    VEC_quick_push (tree, arglist, arg3);
 
   /* Get the high-water mark for the CONVERSION_OBSTACK.  */
   p = conversion_obstack_alloc (0);
@@ -4108,7 +4214,7 @@ build_new_op (enum tree_code code, int f
 	  if (overloaded_p)
 	    *overloaded_p = true;
 
-	  if (resolve_args (arglist) == error_mark_node)
+	  if (resolve_args (arglist) == NULL)
 	    result = error_mark_node;
 	  else
 	    result = build_over_call (cand, LOOKUP_NORMAL, complain);
@@ -4409,13 +4515,14 @@ build_op_delete_call (enum tree_code cod
 	}
       else
 	{
-	  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 cp_build_function_call (fn, args, tf_warning_or_error);
+	  tree ret;
+	  VEC(tree,gc) *args = VEC_alloc (tree, gc, 2);
+	  VEC_quick_push (tree, args, addr);
+	  if (pass != 0)
+	    VEC_quick_push (tree, args, size);
+	  ret = cp_build_function_call_vec (fn, &args, tf_warning_or_error);
+	  VEC_free (tree, gc, args);
+	  return ret;
 	}
     }
 
@@ -4473,12 +4580,13 @@ build_temp (tree expr, tree type, int fl
 	    diagnostic_t *diagnostic_kind)
 {
   int savew, savee;
+  VEC(tree,gc) *args;
 
   savew = warningcount, savee = errorcount;
-  expr = build_special_member_call (NULL_TREE,
-				    complete_ctor_identifier,
-				    build_tree_list (NULL_TREE, expr),
-				    type, flags, tf_warning_or_error);
+  args = make_tree_vector_single (expr);
+  expr = build_special_member_call (NULL_TREE, complete_ctor_identifier,
+				    &args, type, flags, tf_warning_or_error);
+  release_tree_vector (args);
   if (warningcount > savew)
     *diagnostic_kind = DK_WARNING;
   else if (errorcount > savee)
@@ -4640,7 +4748,8 @@ convert_like_real (conversion *convs, tr
 	tree elttype = TREE_VEC_ELT (CLASSTYPE_TI_ARGS (totype), 0);
 	tree new_ctor = build_constructor (init_list_type_node, NULL);
 	unsigned len = CONSTRUCTOR_NELTS (expr);
-	tree array, parms, val;
+	tree array, val;
+	VEC(tree,gc) *parms;
 	unsigned ix;
 
 	/* Convert all the elements.  */
@@ -4659,12 +4768,14 @@ convert_like_real (conversion *convs, tr
 	array = build_array_of_n_type (elttype, len);
 	array = finish_compound_literal (array, new_ctor);
 
-	parms = build_tree_list (NULL_TREE, size_int (len));
-	parms = tree_cons (NULL_TREE, decay_conversion (array), parms);
+	parms = make_tree_vector ();
+	VEC_safe_push (tree, gc, parms, decay_conversion (array));
+	VEC_safe_push (tree, gc, parms, size_int (len));
 	/* Call the private constructor.  */
 	push_deferring_access_checks (dk_no_check);
 	new_ctor = build_special_member_call
-	  (NULL_TREE, complete_ctor_identifier, parms, totype, 0, complain);
+	  (NULL_TREE, complete_ctor_identifier, &parms, totype, 0, complain);
+	release_tree_vector (parms);
 	pop_deferring_access_checks ();
 	return build_cplus_new (totype, new_ctor);
       }
@@ -5121,14 +5232,16 @@ static tree
 build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
 {
   tree fn = cand->fn;
-  tree args = cand->args;
+  const VEC(tree,gc) *args = cand->args;
+  tree first_arg = cand->first_arg;
   conversion **convs = cand->convs;
   conversion *conv;
   tree parm = TYPE_ARG_TYPES (TREE_TYPE (fn));
   int parmlen;
-  tree arg, val;
+  tree val;
   int i = 0;
   int j = 0;
+  unsigned int arg_index = 0;
   int is_method = 0;
   int nargs;
   tree *argarray;
@@ -5142,8 +5255,28 @@ build_over_call (struct z_candidate *can
     {
       tree expr;
       tree return_type;
+      const tree *argarray;
+      unsigned int nargs;
+
       return_type = TREE_TYPE (TREE_TYPE (fn));
-      expr = build_call_list (return_type, build_addr_func (fn), args);
+      nargs = VEC_length (tree, args);
+      if (first_arg == NULL_TREE)
+	argarray = VEC_address (tree, CONST_CAST (VEC(tree,gc) *, args));
+      else
+	{
+	  tree *alcarray;
+	  unsigned int ix;
+	  tree arg;
+
+	  ++nargs;
+	  alcarray = XALLOCAVEC (tree, nargs);
+	  alcarray[0] = first_arg;
+	  for (ix = 0; VEC_iterate (tree, args, ix, arg); ++ix)
+	    alcarray[ix + 1] = arg;
+	  argarray = alcarray;
+	}
+      expr = build_call_array (return_type, build_addr_func (fn), nargs,
+			       argarray);
       if (TREE_THIS_VOLATILE (fn) && cfun)
 	current_function_returns_abnormally = 1;
       if (!VOID_TYPE_P (return_type))
@@ -5198,13 +5331,9 @@ build_over_call (struct z_candidate *can
 	perform_or_defer_access_check (cand->access_path, fn, fn);
     }
 
-  if (args && TREE_CODE (args) != TREE_LIST)
-    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);
+  nargs = VEC_length (tree, args) + (first_arg != NULL_TREE ? 1 : 0);
   if (parmlen > nargs)
     nargs = parmlen;
   argarray = (tree *) alloca (nargs * sizeof (tree));
@@ -5213,16 +5342,24 @@ build_over_call (struct z_candidate *can
      resolution, and must be of the proper type.  */
   if (DECL_CONSTRUCTOR_P (fn))
     {
-      argarray[j++] = TREE_VALUE (arg);
-      arg = TREE_CHAIN (arg);
+      if (first_arg != NULL_TREE)
+	{
+	  argarray[j++] = first_arg;
+	  first_arg = NULL_TREE;
+	}
+      else
+	{
+	  argarray[j++] = VEC_index (tree, args, arg_index);
+	  ++arg_index;
+	}
       parm = TREE_CHAIN (parm);
       /* We should never try to call the abstract constructor.  */
       gcc_assert (!DECL_HAS_IN_CHARGE_PARM_P (fn));
 
       if (DECL_HAS_VTT_PARM_P (fn))
 	{
-	  argarray[j++] = TREE_VALUE (arg);
-	  arg = TREE_CHAIN (arg);
+	  argarray[j++] = VEC_index (tree, args, arg_index);
+	  ++arg_index;
 	  parm = TREE_CHAIN (parm);
 	}
     }
@@ -5230,7 +5367,10 @@ build_over_call (struct z_candidate *can
   else if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
     {
       tree parmtype = TREE_VALUE (parm);
-      tree argtype = TREE_TYPE (TREE_VALUE (arg));
+      tree arg = (first_arg != NULL_TREE
+		  ? first_arg
+		  : VEC_index (tree, args, arg_index));
+      tree argtype = TREE_TYPE (arg);
       tree converted_arg;
       tree base_binfo;
 
@@ -5253,7 +5393,7 @@ build_over_call (struct z_candidate *can
       /* Convert to the base in which the function was declared.  */
       gcc_assert (cand->conversion_path != NULL_TREE);
       converted_arg = build_base_path (PLUS_EXPR,
-				       TREE_VALUE (arg),
+				       arg,
 				       cand->conversion_path,
 				       1);
       /* Check that the base class is accessible.  */
@@ -5272,13 +5412,17 @@ build_over_call (struct z_candidate *can
 
       argarray[j++] = converted_arg;
       parm = TREE_CHAIN (parm);
-      arg = TREE_CHAIN (arg);
+      if (first_arg != NULL_TREE)
+	first_arg = NULL_TREE;
+      else
+	++arg_index;
       ++i;
       is_method = 1;
     }
 
-  for (; arg && parm;
-       parm = TREE_CHAIN (parm), arg = TREE_CHAIN (arg), ++i)
+  gcc_assert (first_arg == NULL_TREE);
+  for (; arg_index < VEC_length (tree, args) && parm;
+       parm = TREE_CHAIN (parm), ++arg_index, ++i)
     {
       tree type = TREE_VALUE (parm);
 
@@ -5291,7 +5435,8 @@ build_over_call (struct z_candidate *can
 	conv = conv->u.next;
 
       val = convert_like_with_context
-	(conv, TREE_VALUE (arg), fn, i - is_method, complain);
+	(conv, VEC_index (tree, args, arg_index), fn, i - is_method,
+	 complain);
 
       val = convert_for_arg_passing (type, val);
       if (val == error_mark_node)
@@ -5306,9 +5451,9 @@ build_over_call (struct z_candidate *can
 					 TREE_PURPOSE (parm),
 					 fn, i - is_method);
   /* Ellipsis */
-  for (; arg; arg = TREE_CHAIN (arg))
+  for (; arg_index < VEC_length (tree, args); ++arg_index)
     {
-      tree a = TREE_VALUE (arg);
+      tree a = VEC_index (tree, args, arg_index);
       if (magic_varargs_p (fn))
 	/* Do no conversions for magic varargs.  */;
       else
@@ -5332,7 +5477,8 @@ build_over_call (struct z_candidate *can
                || DECL_MOVE_CONSTRUCTOR_P (fn)))
     {
       tree targ;
-      arg = argarray[num_artificial_parms_for (fn)];
+      tree arg = argarray[num_artificial_parms_for (fn)];
+      tree fa;
 
       /* Pull out the real argument, disregarding const-correctness.  */
       targ = arg;
@@ -5373,7 +5519,10 @@ build_over_call (struct z_candidate *can
 	 INIT_EXPR to collapse the temp into our target.  Otherwise, if the
 	 ctor is trivial, do a bitwise copy with a simple TARGET_EXPR for a
 	 temp or an INIT_EXPR otherwise.  */
-      if (integer_zerop (TREE_VALUE (args)))
+      fa = (cand->first_arg != NULL_TREE
+	    ? cand->first_arg
+	    : VEC_index (tree, args, 0));
+      if (integer_zerop (fa))
 	{
 	  if (TREE_CODE (arg) == TARGET_EXPR)
 	    return arg;
@@ -5384,8 +5533,8 @@ build_over_call (struct z_candidate *can
 	       || (TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn))
 		   && !move_fn_p (fn)))
 	{
-	  tree to = stabilize_reference
-	    (cp_build_indirect_ref (TREE_VALUE (args), 0, complain));
+	  tree to = stabilize_reference (cp_build_indirect_ref (fa, 0,
+								complain));
 
 	  val = build2 (INIT_EXPR, DECL_CONTEXT (fn), to, arg);
 	  return val;
@@ -5399,8 +5548,8 @@ build_over_call (struct z_candidate *can
 	(cp_build_indirect_ref (argarray[0], 0, complain));
       tree type = TREE_TYPE (to);
       tree as_base = CLASSTYPE_AS_BASE (type);
+      tree arg = argarray[1];
 
-      arg = argarray[1];
       if (tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (as_base)))
 	{
 	  arg = cp_build_indirect_ref (arg, 0, complain);
@@ -5606,9 +5755,10 @@ in_charge_arg_for_name (tree name)
 
 /* Build a call to a constructor, destructor, or an assignment
    operator for INSTANCE, an expression with class type.  NAME
-   indicates the special member function to call; ARGS are the
-   arguments.  BINFO indicates the base of INSTANCE that is to be
-   passed as the `this' parameter to the member function called.
+   indicates the special member function to call; *ARGS are the
+   arguments.  ARGS may be NULL.  This may change ARGS.  BINFO
+   indicates the base of INSTANCE that is to be passed as the `this'
+   parameter to the member function called.
 
    FLAGS are the LOOKUP_* flags to use when processing the call.
 
@@ -5617,12 +5767,14 @@ in_charge_arg_for_name (tree name)
    store the newly constructed object into a VAR_DECL.  */
 
 tree
-build_special_member_call (tree instance, tree name, tree args,
+build_special_member_call (tree instance, tree name, VEC(tree,gc) **args,
 			   tree binfo, int flags, tsubst_flags_t complain)
 {
   tree fns;
   /* The type of the subobject to be constructed or destroyed.  */
   tree class_type;
+  VEC(tree,gc) *allocated = NULL;
+  tree ret;
 
   gcc_assert (name == complete_ctor_identifier
 	      || name == base_ctor_identifier
@@ -5654,7 +5806,7 @@ build_special_member_call (tree instance
       if (name == complete_dtor_identifier
 	  || name == base_dtor_identifier
 	  || name == deleting_dtor_identifier)
-	gcc_assert (args == NULL_TREE);
+	gcc_assert (args == NULL || VEC_empty (tree, *args));
 
       /* Convert to the base class, if necessary.  */
       if (!same_type_ignoring_top_level_qualifiers_p
@@ -5703,13 +5855,24 @@ build_special_member_call (tree instance
       sub_vtt = build2 (POINTER_PLUS_EXPR, TREE_TYPE (vtt), vtt,
 			BINFO_SUBVTT_INDEX (binfo));
 
-      args = tree_cons (NULL_TREE, sub_vtt, args);
+      if (args == NULL)
+	{
+	  allocated = make_tree_vector ();
+	  args = &allocated;
+	}
+
+      VEC_safe_insert (tree, gc, *args, 0, sub_vtt);
     }
 
-  return build_new_method_call (instance, fns, args,
-				TYPE_BINFO (BINFO_TYPE (binfo)),
-				flags, /*fn=*/NULL,
-				complain);
+  ret = build_new_method_call (instance, fns, args,
+			       TYPE_BINFO (BINFO_TYPE (binfo)),
+			       flags, /*fn=*/NULL,
+			       complain);
+
+  if (allocated != NULL)
+    release_tree_vector (allocated);
+
+  return ret;
 }
 
 /* Return the NAME, as a C string.  The NAME indicates a function that
@@ -5758,10 +5921,11 @@ name_as_c_string (tree name, tree type, 
 }
 
 /* Build a call to "INSTANCE.FN (ARGS)".  If FN_P is non-NULL, it will
-   be set, upon return, to the function called.  */
+   be set, upon return, to the function called.  ARGS may be NULL.
+   This may change ARGS.  */
 
 tree
-build_new_method_call (tree instance, tree fns, tree args,
+build_new_method_call (tree instance, tree fns, VEC(tree,gc) **args,
 		       tree conversion_path, int flags,
 		       tree *fn_p, tsubst_flags_t complain)
 {
@@ -5770,9 +5934,11 @@ build_new_method_call (tree instance, tr
   tree basetype = NULL_TREE;
   tree access_binfo;
   tree optype;
-  tree mem_args = NULL_TREE, instance_ptr;
+  tree first_mem_arg = NULL_TREE;
+  tree instance_ptr;
   tree name;
-  tree user_args;
+  bool skip_first_for_error;
+  VEC(tree,gc) *user_args;
   tree call;
   tree fn;
   tree class_type;
@@ -5780,7 +5946,7 @@ build_new_method_call (tree instance, tr
   bool any_viable_p;
   tree orig_instance;
   tree orig_fns;
-  tree orig_args;
+  VEC(tree,gc) *orig_args = NULL;
   void *p;
 
   gcc_assert (instance != NULL_TREE);
@@ -5790,8 +5956,7 @@ build_new_method_call (tree instance, tr
     *fn_p = NULL_TREE;
 
   if (error_operand_p (instance)
-      || error_operand_p (fns)
-      || args == error_mark_node)
+      || error_operand_p (fns))
     return error_mark_node;
 
   if (!BASELINK_P (fns))
@@ -5803,7 +5968,6 @@ build_new_method_call (tree instance, tr
 
   orig_instance = instance;
   orig_fns = fns;
-  orig_args = args;
 
   /* Dismantle the baselink to collect all the information we need.  */
   if (!conversion_path)
@@ -5828,16 +5992,20 @@ build_new_method_call (tree instance, tr
 
   if (processing_template_decl)
     {
+      orig_args = args == NULL ? NULL : make_tree_vector_copy (*args);
       instance = build_non_dependent_expr (instance);
-      args = build_non_dependent_args (orig_args);
+      if (args != NULL)
+	make_args_non_dependent (*args);
     }
 
-  /* The USER_ARGS are the arguments we will display to users if an
-     error occurs.  The USER_ARGS should not include any
-     compiler-generated arguments.  The "this" pointer hasn't been
-     added yet.  However, we must remove the VTT pointer if this is a
-     call to a base-class constructor or destructor.  */
-  user_args = args;
+  /* Figure out whether to skip the first argument for the error
+     message we will display to users if an error occurs.  We don't
+     want to display any compiler-generated arguments.  The "this"
+     pointer hasn't been added yet.  However, we must remove the VTT
+     pointer if this is a call to a base-class constructor or
+     destructor.  */
+  skip_first_for_error = false;
+  user_args = args == NULL ? NULL : *args;
   if (IDENTIFIER_CTOR_OR_DTOR_P (name))
     {
       /* Callers should explicitly indicate whether they want to construct
@@ -5848,13 +6016,16 @@ build_new_method_call (tree instance, tr
       /* Remove the VTT pointer, if present.  */
       if ((name == base_ctor_identifier || name == base_dtor_identifier)
 	  && CLASSTYPE_VBASECLASSES (basetype))
-	user_args = TREE_CHAIN (user_args);
+	skip_first_for_error = true;
     }
 
   /* Process the argument list.  */
-  args = resolve_args (args);
-  if (args == error_mark_node)
-    return error_mark_node;
+  if (args != NULL && *args != NULL)
+    {
+      *args = resolve_args (*args);
+      if (*args == NULL)
+	return error_mark_node;
+    }
 
   instance_ptr = build_this (instance);
 
@@ -5874,17 +6045,17 @@ build_new_method_call (tree instance, tr
   /* If CONSTRUCTOR_IS_DIRECT_INIT is set, this was a T{ } form
      initializer, not T({ }).  If the type doesn't have a list ctor,
      break apart the list into separate ctor args.  */
-  if (DECL_CONSTRUCTOR_P (fn) && args
-      && BRACE_ENCLOSED_INITIALIZER_P (TREE_VALUE (args))
-      && CONSTRUCTOR_IS_DIRECT_INIT (TREE_VALUE (args))
+  if (DECL_CONSTRUCTOR_P (fn) && args != NULL && !VEC_empty (tree, *args)
+      && BRACE_ENCLOSED_INITIALIZER_P (VEC_index (tree, *args, 0))
+      && CONSTRUCTOR_IS_DIRECT_INIT (VEC_index (tree, *args, 0))
       && !TYPE_HAS_LIST_CTOR (basetype))
     {
-      gcc_assert (TREE_CHAIN (args) == NULL_TREE);
-      args = ctor_to_list (TREE_VALUE (args));
+      gcc_assert (VEC_length (tree, *args) == 1);
+      *args = ctor_to_vec (VEC_index (tree, *args, 0));
     }
 
   class_type = (conversion_path ? BINFO_TYPE (conversion_path) : NULL_TREE);
-  mem_args = tree_cons (NULL_TREE, instance_ptr, args);
+  first_mem_arg = instance_ptr;
 
   /* Get the high-water mark for the CONVERSION_OBSTACK.  */
   p = conversion_obstack_alloc (0);
@@ -5892,7 +6063,7 @@ build_new_method_call (tree instance, tr
   for (fn = fns; fn; fn = OVL_NEXT (fn))
     {
       tree t = OVL_CURRENT (fn);
-      tree this_arglist;
+      tree this_first_arg;
 
       /* We can end up here for copy-init of same or base class.  */
       if ((flags & LOOKUP_ONLYCONVERTING)
@@ -5900,16 +6071,18 @@ build_new_method_call (tree instance, tr
 	continue;
 
       if (DECL_NONSTATIC_MEMBER_FUNCTION_P (t))
-	this_arglist = mem_args;
+	this_first_arg = first_mem_arg;
       else
-	this_arglist = args;
+	this_first_arg = NULL_TREE;
 
       if (TREE_CODE (t) == TEMPLATE_DECL)
 	/* A member template.  */
 	add_template_candidate (&candidates, t,
 				class_type,
 				explicit_targs,
-				this_arglist, optype,
+				this_first_arg,
+				args == NULL ? NULL : *args,
+				optype,
 				access_binfo,
 				conversion_path,
 				flags,
@@ -5917,7 +6090,8 @@ build_new_method_call (tree instance, tr
       else if (! template_only)
 	add_function_candidate (&candidates, t,
 				class_type,
-				this_arglist,
+				this_first_arg,
+				args == NULL ? NULL : *args,
 				access_binfo,
 				conversion_path,
 				flags);
@@ -5934,10 +6108,14 @@ build_new_method_call (tree instance, tr
 	    {
 	      char *pretty_name;
 	      bool free_p;
+	      tree arglist;
 
 	      pretty_name = name_as_c_string (name, basetype, &free_p);
+	      arglist = build_tree_list_vec (user_args);
+	      if (skip_first_for_error)
+		arglist = TREE_CHAIN (arglist);
 	      error ("no matching function for call to %<%T::%s(%A)%#V%>",
-		     basetype, pretty_name, user_args,
+		     basetype, pretty_name, arglist,
 		     TREE_TYPE (TREE_TYPE (instance_ptr)));
 	      if (free_p)
 		free (pretty_name);
@@ -5953,12 +6131,16 @@ build_new_method_call (tree instance, tr
 	{
 	  char *pretty_name;
 	  bool free_p;
+	  tree arglist;
 
 	  if (complain & tf_error)
 	    {
 	      pretty_name = name_as_c_string (name, basetype, &free_p);
+	      arglist = build_tree_list_vec (user_args);
+	      if (skip_first_for_error)
+		arglist = TREE_CHAIN (arglist);
 	      error ("call of overloaded %<%s(%A)%> is ambiguous", pretty_name,
-		     user_args);
+		     arglist);
 	      print_z_candidates (candidates);
 	      if (free_p)
 		free (pretty_name);
@@ -6039,7 +6221,7 @@ build_new_method_call (tree instance, tr
 	}
       if (TREE_CODE (call) == INDIRECT_REF)
 	call = TREE_OPERAND (call, 0);
-      call = (build_min_non_dep_call_list
+      call = (build_min_non_dep_call_vec
 	      (call,
 	       build_min (COMPONENT_REF, TREE_TYPE (CALL_EXPR_FN (call)),
 			  orig_instance, orig_fns, NULL_TREE),
@@ -6052,6 +6234,9 @@ build_new_method_call (tree instance, tr
  /* Free all the conversions we allocated.  */
   obstack_free (&conversion_obstack, p);
 
+  if (orig_args != NULL)
+    release_tree_vector (orig_args);
+
   return call;
 }
 
@@ -7091,9 +7276,10 @@ perform_direct_initialization_if_possibl
      ill-formed.  */
   if (CLASS_TYPE_P (type))
     {
+      VEC(tree,gc) *args = make_tree_vector_single (expr);
       expr = build_special_member_call (NULL_TREE, complete_ctor_identifier,
-					build_tree_list (NULL_TREE, expr),
-					type, LOOKUP_NORMAL, complain);
+					&args, type, LOOKUP_NORMAL, complain);
+      release_tree_vector (args);
       return build_cplus_new (type, expr);
     }
 
Index: cp/cvt.c
===================================================================
--- cp/cvt.c	(revision 146793)
+++ cp/cvt.c	(working copy)
@@ -1,6 +1,6 @@
 /* Language-level data type conversion for GNU C++.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
    Hacked by Michael Tiemann (tiemann@cygnus.com)
 
@@ -750,11 +750,15 @@ ocp_convert (tree type, tree expr, int c
 	   the target with the temp (see [dcl.init]).  */
 	ctor = build_user_type_conversion (type, ctor, flags);
       else
-	ctor = build_special_member_call (NULL_TREE,
-					  complete_ctor_identifier,
-					  build_tree_list (NULL_TREE, ctor),
-					  type, flags,
-                                          tf_warning_or_error);
+	{
+	  VEC(tree,gc) *ctor_vec = make_tree_vector_single (ctor);
+	  ctor = build_special_member_call (NULL_TREE,
+					    complete_ctor_identifier,
+					    &ctor_vec,
+					    type, flags,
+					    tf_warning_or_error);
+	  release_tree_vector (ctor_vec);
+	}
       if (ctor)
 	return build_cplus_new (type, ctor);
     }
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h	(revision 146793)
+++ cp/cp-tree.h	(working copy)
@@ -4178,17 +4178,20 @@ extern bool null_ptr_cst_p			(tree);
 extern bool sufficient_parms_p			(const_tree);
 extern tree type_decays_to			(tree);
 extern tree build_user_type_conversion		(tree, tree, int);
-extern tree build_new_function_call		(tree, tree, bool, 
+extern tree build_new_function_call		(tree, VEC(tree,gc) **, bool, 
 						 tsubst_flags_t);
-extern tree build_operator_new_call		(tree, tree, tree *, tree *,
-						 tree *);
-extern tree build_new_method_call		(tree, tree, tree, tree, int,
-						 tree *, tsubst_flags_t);
-extern tree build_special_member_call		(tree, tree, tree, tree, int,
-                                                 tsubst_flags_t);
+extern tree build_operator_new_call		(tree, VEC(tree,gc) **, tree *,
+						 tree *, tree *);
+extern tree build_new_method_call		(tree, tree, VEC(tree,gc) **,
+						 tree, int, tree *,
+						 tsubst_flags_t);
+extern tree build_special_member_call		(tree, tree, VEC(tree,gc) **,
+						 tree, int, tsubst_flags_t);
 extern tree build_new_op			(enum tree_code, int, tree, 
 						 tree, tree, bool *,
 						 tsubst_flags_t);
+extern tree build_op_call			(tree, VEC(tree,gc) **,
+						 tsubst_flags_t);
 extern tree build_op_delete_call		(enum tree_code, tree, tree, bool, tree, tree);
 extern bool can_convert				(tree, tree);
 extern bool can_convert_arg			(tree, tree, tree, int);
@@ -4416,7 +4419,7 @@ extern void constrain_class_visibility		
 extern void update_member_visibility		(tree);
 extern void import_export_decl			(tree);
 extern tree build_cleanup			(tree);
-extern tree build_offset_ref_call_from_tree	(tree, tree);
+extern tree build_offset_ref_call_from_tree	(tree, VEC(tree,gc) **);
 extern void check_default_args			(tree);
 extern void mark_used				(tree);
 extern void finish_static_data_member_decl	(tree, tree, bool, tree, int);
@@ -4476,7 +4479,8 @@ extern tree build_zero_init			(tree, tre
 extern tree build_value_init			(tree);
 extern tree build_value_init_noctor		(tree);
 extern tree build_offset_ref			(tree, tree, bool);
-extern tree build_new				(tree, tree, tree, tree, int,
+extern tree build_new				(VEC(tree,gc) **, tree, tree,
+						 VEC(tree,gc) **, int,
                                                  tsubst_flags_t);
 extern tree build_vec_init			(tree, tree, tree, bool, int,
                                                  tsubst_flags_t);
@@ -4560,7 +4564,8 @@ extern int uses_template_parms			(tree);
 extern int uses_template_parms_level		(tree, int);
 extern tree instantiate_class_template		(tree);
 extern tree instantiate_template		(tree, tree, tsubst_flags_t);
-extern int fn_type_unification			(tree, tree, tree, tree,
+extern int fn_type_unification			(tree, tree, tree,
+						 const tree *, unsigned int,
 						 tree, unification_kind_t, int);
 extern void mark_decl_instantiated		(tree, int);
 extern int more_specialized_fn			(tree, tree, int);
@@ -4598,7 +4603,7 @@ extern bool any_dependent_template_argum
 extern bool dependent_template_p		(tree);
 extern bool dependent_template_id_p		(tree, tree);
 extern bool type_dependent_expression_p		(tree);
-extern bool any_type_dependent_arguments_p      (const_tree);
+extern bool any_type_dependent_arguments_p      (const VEC(tree,gc) *);
 extern bool type_dependent_expression_p_push	(tree);
 extern bool value_dependent_expression_p	(tree);
 extern bool any_value_dependent_elements_p      (const_tree);
@@ -4606,7 +4611,7 @@ extern bool dependent_omp_for_p			(tree,
 extern tree resolve_typename_type		(tree, bool);
 extern tree template_for_substitution		(tree);
 extern tree build_non_dependent_expr		(tree);
-extern tree build_non_dependent_args		(tree);
+extern void make_args_non_dependent		(VEC(tree,gc) *);
 extern bool reregister_specialization		(tree, tree, tree);
 extern tree fold_non_dependent_expr		(tree);
 extern bool explicit_class_specialization_p     (tree);
@@ -4757,9 +4762,9 @@ extern tree begin_stmt_expr			(void);
 extern tree finish_stmt_expr_expr		(tree, tree);
 extern tree finish_stmt_expr			(tree, bool);
 extern tree stmt_expr_value_expr		(tree);
-extern tree perform_koenig_lookup		(tree, tree);
-extern tree finish_call_expr			(tree, tree, bool, bool, 
-						 tsubst_flags_t);
+extern tree perform_koenig_lookup		(tree, VEC(tree,gc) *);
+extern tree finish_call_expr			(tree, VEC(tree,gc) **, bool,
+						 bool, tsubst_flags_t);
 extern tree finish_increment_expr		(tree, enum tree_code);
 extern tree finish_this_expr			(void);
 extern tree finish_pseudo_destructor_expr       (tree, tree, tree);
@@ -4848,7 +4853,7 @@ extern bool builtin_valid_in_constant_ex
 extern tree build_min				(enum tree_code, tree, ...);
 extern tree build_min_nt			(enum tree_code, ...);
 extern tree build_min_non_dep			(enum tree_code, tree, ...);
-extern tree build_min_non_dep_call_list		(tree, tree, tree);
+extern tree build_min_non_dep_call_vec		(tree, tree, VEC(tree,gc) *);
 extern tree build_cplus_new			(tree, tree);
 extern tree build_aggr_init_expr		(tree, tree);
 extern tree get_target_expr			(tree);
@@ -4935,6 +4940,8 @@ extern tree cp_build_indirect_ref		(tree
 extern tree build_array_ref			(tree, tree, location_t);
 extern tree get_member_function_from_ptrfunc	(tree *, tree);
 extern tree cp_build_function_call              (tree, tree, tsubst_flags_t);
+extern tree cp_build_function_call_vec		(tree, VEC(tree,gc) **,
+						 tsubst_flags_t);
 extern tree build_x_binary_op			(enum tree_code, tree,
 						 enum tree_code, tree,
 						 enum tree_code, bool *,
@@ -4948,6 +4955,7 @@ extern tree unary_complex_lvalue		(enum 
 extern tree build_x_conditional_expr		(tree, tree, tree, 
                                                  tsubst_flags_t);
 extern tree build_x_compound_expr_from_list	(tree, const char *);
+extern tree build_x_compound_expr_from_vec	(VEC(tree,gc) *, const char *);
 extern tree build_x_compound_expr		(tree, tree, tsubst_flags_t);
 extern tree build_compound_expr                 (tree, tree);
 extern tree cp_build_compound_expr		(tree, tree, tsubst_flags_t);
Index: cp/name-lookup.c
===================================================================
--- cp/name-lookup.c	(revision 146793)
+++ cp/name-lookup.c	(working copy)
@@ -4235,7 +4235,7 @@ lookup_name_nonclass (tree name)
 }
 
 tree
-lookup_function_nonclass (tree name, tree args, bool block_p)
+lookup_function_nonclass (tree name, VEC(tree,gc) *args, bool block_p)
 {
   return
     lookup_arg_dependent (name,
@@ -4427,7 +4427,7 @@ lookup_type_current_level (tree name)
 struct arg_lookup
 {
   tree name;
-  tree args;
+  VEC(tree,gc) *args;
   tree namespaces;
   tree classes;
   tree functions;
@@ -4435,6 +4435,7 @@ struct arg_lookup
 
 static bool arg_assoc (struct arg_lookup*, tree);
 static bool arg_assoc_args (struct arg_lookup*, tree);
+static bool arg_assoc_args_vec (struct arg_lookup*, VEC(tree,gc) *);
 static bool arg_assoc_type (struct arg_lookup*, tree);
 static bool add_function (struct arg_lookup *, tree);
 static bool arg_assoc_namespace (struct arg_lookup *, tree);
@@ -4589,13 +4590,13 @@ arg_assoc_namespace (struct arg_lookup *
 	 classes.  */
       if (hidden_name_p (OVL_CURRENT (value)))
 	{
-	  tree args;
+	  unsigned int ix;
+	  tree arg;
 
-	  for (args = k->args; args; args = TREE_CHAIN (args))
-	    if (friend_of_associated_class_p (TREE_VALUE (args),
-					      OVL_CURRENT (value)))
+	  for (ix = 0; VEC_iterate (tree, k->args, ix, arg); ++ix)
+	    if (friend_of_associated_class_p (arg, OVL_CURRENT (value)))
 	      break;
-	  if (!args)
+	  if (ix >= VEC_length (tree, k->args))
 	    continue;
 	}
 
@@ -4805,6 +4806,21 @@ arg_assoc_args (struct arg_lookup *k, tr
   return false;
 }
 
+/* Adds everything associated with an argument vector.  Returns true
+   on error.  */
+
+static bool
+arg_assoc_args_vec (struct arg_lookup *k, VEC(tree,gc) *args)
+{
+  unsigned int ix;
+  tree arg;
+
+  for (ix = 0; VEC_iterate (tree, args, ix, arg); ++ix)
+    if (arg_assoc (k, arg))
+      return true;
+  return false;
+}
+
 /* Adds everything associated with a given tree_node.  Returns 1 on error.  */
 
 static bool
@@ -4884,7 +4900,7 @@ arg_assoc (struct arg_lookup *k, tree n)
    are the functions found in normal lookup.  */
 
 tree
-lookup_arg_dependent (tree name, tree fns, tree args)
+lookup_arg_dependent (tree name, tree fns, VEC(tree,gc) *args)
 {
   struct arg_lookup k;
 
@@ -4907,7 +4923,7 @@ lookup_arg_dependent (tree name, tree fn
      picking up later definitions) in the second stage. */
   k.namespaces = NULL_TREE;
 
-  arg_assoc_args (&k, args);
+  arg_assoc_args_vec (&k, args);
 
   fns = k.functions;
   
Index: cp/name-lookup.h
===================================================================
--- cp/name-lookup.h	(revision 146793)
+++ cp/name-lookup.h	(working copy)
@@ -1,5 +1,6 @@
 /* Declarations for C++ name lookup routines.
-   Copyright (C) 2003, 2004, 2005, 2007, 2008  Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009
+   Free Software Foundation, Inc.
    Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net>
 
 This file is part of GCC.
@@ -317,7 +318,7 @@ extern tree remove_hidden_names (tree);
 extern tree lookup_qualified_name (tree, tree, bool, bool);
 extern tree lookup_name_nonclass (tree);
 extern tree lookup_name_innermost_nonclass_level (tree);
-extern tree lookup_function_nonclass (tree, tree, bool);
+extern tree lookup_function_nonclass (tree, VEC(tree,gc) *, bool);
 extern void push_local_binding (tree, tree, int);
 extern bool pushdecl_class_level (tree);
 extern tree pushdecl_namespace_level (tree, bool);
@@ -332,7 +333,7 @@ extern void do_toplevel_using_decl (tree
 extern void do_local_using_decl (tree, tree, tree);
 extern tree do_class_using_decl (tree, tree);
 extern void do_using_directive (tree);
-extern tree lookup_arg_dependent (tree, tree, tree);
+extern tree lookup_arg_dependent (tree, tree, VEC(tree,gc) *);
 extern bool is_associated_namespace (tree, tree);
 extern void parse_using_directive (tree, tree);
 extern tree innermost_non_namespace_value (tree);
Index: c-common.c
===================================================================
--- c-common.c	(revision 146793)
+++ c-common.c	(working copy)
@@ -9267,4 +9267,69 @@ is_typedef_decl (tree x)
           && DECL_ORIGINAL_TYPE (x) != NULL_TREE);
 }
 
+/* The C and C++ parsers both use vectors to hold function arguments.
+   For efficiency, we keep a cache of unused vectors.  This is the
+   cache.  */
+
+typedef VEC(tree,gc)* tree_vector;
+DEF_VEC_P(tree_vector);
+DEF_VEC_ALLOC_P(tree_vector,gc);
+static GTY((deletable)) VEC(tree_vector,gc) *tree_vector_cache;
+
+/* Return a new vector from the cache.  If the cache is empty,
+   allocate a new vector.  These vectors are GC'ed, so it is OK if the
+   pointer is not released..  */
+
+VEC(tree,gc) *
+make_tree_vector (void)
+{
+  if (!VEC_empty (tree_vector, tree_vector_cache))
+    return VEC_pop (tree_vector, tree_vector_cache);
+  else
+    {
+      /* Passing 0 to VEC_alloc returns NULL, and our callers require
+	 that we always return a non-NULL value.  The vector code uses
+	 4 when growing a NULL vector, so we do too.  */
+      return VEC_alloc (tree, gc, 4);
+    }
+}
+
+/* Release a vector of trees back to the cache.  */
+
+void
+release_tree_vector (VEC(tree,gc) *vec)
+{
+  if (vec != NULL)
+    {
+      VEC_truncate (tree, vec, 0);
+      VEC_safe_push (tree_vector, gc, tree_vector_cache, vec);
+    }
+}
+
+/* Get a new tree vector holding a single tree.  */
+
+VEC(tree,gc) *
+make_tree_vector_single (tree t)
+{
+  VEC(tree,gc) *ret = make_tree_vector ();
+  VEC_quick_push (tree, ret, t);
+  return ret;
+}
+
+/* Get a new tree vector which is a copy of an existing one.  */
+
+VEC(tree,gc) *
+make_tree_vector_copy (const VEC(tree,gc) *orig)
+{
+  VEC(tree,gc) *ret;
+  unsigned int ix;
+  tree t;
+
+  ret = make_tree_vector ();
+  VEC_reserve (tree, gc, ret, VEC_length (tree, orig));
+  for (ix = 0; VEC_iterate (tree, orig, ix, t); ++ix)
+    VEC_quick_push (tree, ret, t);
+  return ret;
+}
+
 #include "gt-c-common.h"
Index: c-common.h
===================================================================
--- c-common.h	(revision 146793)
+++ c-common.h	(working copy)
@@ -1004,6 +1004,10 @@ extern void warn_for_sign_compare (locat
 				   enum tree_code resultcode);
 extern void set_underlying_type (tree x);
 extern bool is_typedef_decl (tree x);
+extern VEC(tree,gc) *make_tree_vector (void);
+extern void release_tree_vector (VEC(tree,gc) *);
+extern VEC(tree,gc) *make_tree_vector_single (tree);
+extern VEC(tree,gc) *make_tree_vector_copy (const VEC(tree,gc) *);
 
 /* In c-gimplify.c  */
 extern void c_genericize (tree);
Index: c-parser.c
===================================================================
--- c-parser.c	(revision 146793)
+++ c-parser.c	(working copy)
@@ -917,8 +917,6 @@ static struct c_expr c_parser_expression
 static struct c_expr c_parser_expression_conv (c_parser *);
 static VEC(tree,gc) *c_parser_expr_list (c_parser *, bool, bool,
 					 VEC(tree,gc) **);
-static void c_parser_release_expr_list (VEC(tree,gc) *);
-static tree c_parser_vec_to_tree_list (VEC(tree,gc) *);
 static void c_parser_omp_construct (c_parser *);
 static void c_parser_omp_threadprivate (c_parser *);
 static void c_parser_omp_barrier (c_parser *);
@@ -2870,9 +2868,9 @@ c_parser_attributes (c_parser *parser)
 		  tree tree_list;
 		  c_parser_consume_token (parser);
 		  expr_list = c_parser_expr_list (parser, false, true, NULL);
-		  tree_list = c_parser_vec_to_tree_list (expr_list);
+		  tree_list = build_tree_list_vec (expr_list);
 		  attr_args = tree_cons (NULL_TREE, arg1, tree_list);
-		  c_parser_release_expr_list (expr_list);
+		  release_tree_vector (expr_list);
 		}
 	    }
 	  else
@@ -2882,8 +2880,8 @@ c_parser_attributes (c_parser *parser)
 	      else
 		{
 		  expr_list = c_parser_expr_list (parser, false, true, NULL);
-		  attr_args = c_parser_vec_to_tree_list (expr_list);
-		  c_parser_release_expr_list (expr_list);
+		  attr_args = build_tree_list_vec (expr_list);
+		  release_tree_vector (expr_list);
 		}
 	    }
 	  attr = build_tree_list (attr_name, attr_args);
@@ -5675,8 +5673,8 @@ c_parser_postfix_expression_after_primar
 	  expr.original_type = NULL;
 	  if (exprlist != NULL)
 	    {
-	      c_parser_release_expr_list (exprlist);
-	      c_parser_release_expr_list (origtypes);
+	      release_tree_vector (exprlist);
+	      release_tree_vector (origtypes);
 	    }
 	  break;
 	case CPP_DOT:
@@ -5809,10 +5807,6 @@ c_parser_expression_conv (c_parser *pars
      nonempty-expr-list , assignment-expression
 */
 
-/* We cache two vectors, to save most allocation and deallocation.  */
-static GTY((deletable)) VEC(tree,gc) *cached_expr_list_1;
-static GTY((deletable)) VEC(tree,gc) *cached_expr_list_2;
-
 static VEC(tree,gc) *
 c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
 		    VEC(tree,gc) **p_orig_types)
@@ -5821,34 +5815,11 @@ c_parser_expr_list (c_parser *parser, bo
   VEC(tree,gc) *orig_types;
   struct c_expr expr;
 
-  if (cached_expr_list_1 != NULL)
-    {
-      ret = cached_expr_list_1;
-      cached_expr_list_1 = NULL;
-      VEC_truncate (tree, ret, 0);
-    }
-  else if (cached_expr_list_2 != NULL)
-    {
-      ret = cached_expr_list_2;
-      cached_expr_list_2 = NULL;
-      VEC_truncate (tree, ret, 0);
-    }
-  else
-    ret = VEC_alloc (tree, gc, 16);
-
+  ret = make_tree_vector ();
   if (p_orig_types == NULL)
     orig_types = NULL;
   else
-    {
-      if (cached_expr_list_2 != NULL)
-	{
-	  orig_types = cached_expr_list_2;
-	  cached_expr_list_2 = NULL;
-	  VEC_truncate (tree, orig_types, 0);
-	}
-      else
-	orig_types = VEC_alloc (tree, gc, 16);
-    }
+    orig_types = make_tree_vector ();
 
   expr = c_parser_expr_no_commas (parser, NULL);
   if (convert_p)
@@ -5874,37 +5845,6 @@ c_parser_expr_list (c_parser *parser, bo
     *p_orig_types = orig_types;
   return ret;
 }
-
-/* Release a vector returned by c_parser_expr_list.  */
-
-static void
-c_parser_release_expr_list (VEC(tree,gc) *vec)
-{
-  if (cached_expr_list_1 == NULL)
-    cached_expr_list_1 = vec;
-  else if (cached_expr_list_2 == NULL)
-    cached_expr_list_2 = vec;
-  else
-    VEC_free (tree, gc, vec);
-}
-
-/* Convert a vector, as returned by c_parser_expr_list, to a
-   tree_list.  */
-
-static tree
-c_parser_vec_to_tree_list (VEC(tree,gc) *vec)
-{
-  tree ret = NULL_TREE;
-  tree *pp = &ret;
-  unsigned int i;
-  tree t;
-  for (i = 0; VEC_iterate (tree, vec, i, t); ++i)
-    {
-      *pp = build_tree_list (NULL, t);
-      pp = &TREE_CHAIN (*pp);
-    }
-  return ret;
-}
 
 /* Parse Objective-C-specific constructs.  */
 
@@ -6786,9 +6726,9 @@ c_parser_objc_keywordexpr (c_parser *par
   else
     {
       /* We have a comma expression, we will collapse later.  */
-      ret = c_parser_vec_to_tree_list (expr_list);
+      ret = build_tree_list_vec (expr_list);
     }
-  c_parser_release_expr_list (expr_list);
+  release_tree_vector (expr_list);
   return ret;
 }
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]