aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorSandra Loosemore <sandra@codesourcery.com>2007-02-28 14:21:20 -0500
committerSandra Loosemore <sandra@gcc.gnu.org>2007-02-28 14:21:20 -0500
commit94a0dd7b599e1d83b81f007258af2b16e7cbc4c5 (patch)
tree34dad42b40269284ec633fd80ce8a06342ba7ea3 /gcc/cp
parent76bf4853ce24034b8489b3b5ba56d1de50203ea5 (diff)
downloadgcc-94a0dd7b599e1d83b81f007258af2b16e7cbc4c5.zip
gcc-94a0dd7b599e1d83b81f007258af2b16e7cbc4c5.tar.gz
gcc-94a0dd7b599e1d83b81f007258af2b16e7cbc4c5.tar.bz2
builtins.c (fold_builtin_call_list, [...]): Delete, and replace with...
2007-02-28 Sandra Loosemore <sandra@codesourcery.com> * gcc/builtins.c (fold_builtin_call_list, fold_builtin_call_valist): Delete, and replace with... (fold_builtin_call_array): This. Update callers to use it. * gcc/fold-const.c (fold_build_call_list): Delete, and replace with... (fold_build_call_array): This. (fold_build_call_list_initializer): Delete, and replace with... (fold_build_call_array_initializer): This. * gcc/tree.h: Update declarations to reflect above changes. * gcc/c-typeck.c (build_function_call): Store converted arguments in a stack-allocated array instead of building a list. (convert_arguments): Store arguments in the array passed in as an argument, and return the actual number of arguments. * gcc/c-format.c: (check_function_format): Pass arguments in an array instead of a list. * gcc/c-common.c (check_function_nonnull): Likewise. (check_function_sentinel): Likewise. (check_function_arguments): Likewise. * gcc/c-common.h: Update declarations to reflect above changes. * gcc/cp/typeck.c (build_function_call): Store converted arguments in a stack-allocated array instead of building a list. (convert_arguments): Store arguments in the array passed in as an argument, and return the actual number of arguments. * gcc/cp/call.c (build_call): Delete, and replace with... (build_call_n, build_call_a): New. (build_op_delete_call): Rewrite to avoid constructing argument lists. (build_over_call): Store converted arguments in a stack-allocated array instead of building a list. (build_cxx_call): Pass arguments in an array instead of as a list. (build_java_interface_fn_ref): Rewrite to avoid constructing argument lists. * gcc/cp/tree.h: Update declarations to reflect above changes. * gcc/cp/method.c (use_thunk): Use a stack-allocated array to hold the arguments instead of a list. * gcc/cp/rtti.c (throw_bad_cast): Update call to cxx_call. (throw_bad_typeid): Likewise. (build_dynamic_cast_1): Likewise. * gcc/cp/init.c (build_builtin_delete_call): Use build_call_n. * gcc/cp/decl.c (expand_static_init): Likewise. * gcc/cp/except.c (cp_protect_cleanup_actions): Likewise. * gcc/cp/cp-gimplify.c (genericize_eh_spec_block): Likewise. (gimplify_must_not_throw_expr): Likewise. (cxx_omp_apply_fn): Use build_call_a. From-SVN: r122411
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog27
-rw-r--r--gcc/cp/call.c172
-rw-r--r--gcc/cp/cp-gimplify.c43
-rw-r--r--gcc/cp/cp-tree.h6
-rw-r--r--gcc/cp/decl.c9
-rw-r--r--gcc/cp/except.c2
-rw-r--r--gcc/cp/init.c2
-rw-r--r--gcc/cp/method.c32
-rw-r--r--gcc/cp/rtti.c18
-rw-r--r--gcc/cp/typeck.c67
10 files changed, 233 insertions, 145 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 2bf12bd..f675607 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,30 @@
+2007-02-28 Sandra Loosemore <sandra@codesourcery.com>
+
+ * typeck.c (build_function_call): Store converted arguments
+ in a stack-allocated array instead of building a list.
+ (convert_arguments): Store arguments in the array passed in as an
+ argument, and return the actual number of arguments.
+ * call.c (build_call): Delete, and replace with...
+ (build_call_n, build_call_a): New.
+ (build_op_delete_call): Rewrite to avoid constructing argument lists.
+ (build_over_call): Store converted arguments in a stack-allocated
+ array instead of building a list.
+ (build_cxx_call): Pass arguments in an array instead of as a list.
+ (build_java_interface_fn_ref): Rewrite to avoid constructing
+ argument lists.
+ * tree.h: Update declarations to reflect above changes.
+ * method.c (use_thunk): Use a stack-allocated array to hold
+ the arguments instead of a list.
+ * rtti.c (throw_bad_cast): Update call to cxx_call.
+ (throw_bad_typeid): Likewise.
+ (build_dynamic_cast_1): Likewise.
+ * init.c (build_builtin_delete_call): Use build_call_n.
+ * decl.c (expand_static_init): Likewise.
+ * except.c (cp_protect_cleanup_actions): Likewise.
+ * cp-gimplify.c (genericize_eh_spec_block): Likewise.
+ (gimplify_must_not_throw_expr): Likewise.
+ (cxx_omp_apply_fn): Use build_call_a.
+
2007-02-26 Mark Mitchell <mark@codesourcery.com>
* semantics.c (expand_or_defer_fn): Call c_record_cdtor_fn.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index f60c592..3514e62 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -269,17 +269,38 @@ build_addr_func (tree function)
/* Build a CALL_EXPR, we can handle FUNCTION_TYPEs, METHOD_TYPEs, or
POINTER_TYPE to those. Note, pointer to member function types
- (TYPE_PTRMEMFUNC_P) must be handled by our callers. */
+ (TYPE_PTRMEMFUNC_P) must be handled by our callers. There are
+ two variants. build_call_a is the primitive taking an array of
+ arguments, while build_call_n is a wrapper that handles varargs. */
tree
-build_call (tree function, tree parms)
+build_call_n (tree function, int n, ...)
+{
+ if (n == 0)
+ return build_call_a (function, 0, NULL);
+ else
+ {
+ tree *argarray = (tree *) alloca (n * sizeof (tree));
+ va_list ap;
+ int i;
+
+ va_start (ap, n);
+ for (i = 0; i < n; i++)
+ argarray[i] = va_arg (ap, tree);
+ va_end (ap);
+ return build_call_a (function, n, argarray);
+ }
+}
+
+tree
+build_call_a (tree function, int n, tree *argarray)
{
int is_constructor = 0;
int nothrow;
- tree tmp;
tree decl;
tree result_type;
tree fntype;
+ int i;
function = build_addr_func (function);
@@ -327,16 +348,16 @@ build_call (tree function, tree parms)
for tags in STL, which are used to control overload resolution.
We don't need to handle other cases of copying empty classes. */
if (! decl || ! DECL_BUILT_IN (decl))
- for (tmp = parms; tmp; tmp = TREE_CHAIN (tmp))
- if (is_empty_class (TREE_TYPE (TREE_VALUE (tmp)))
- && ! TREE_ADDRESSABLE (TREE_TYPE (TREE_VALUE (tmp))))
+ for (i = 0; i < n; i++)
+ if (is_empty_class (TREE_TYPE (argarray[i]))
+ && ! TREE_ADDRESSABLE (TREE_TYPE (argarray[i])))
{
- tree t = build0 (EMPTY_CLASS_EXPR, TREE_TYPE (TREE_VALUE (tmp)));
- TREE_VALUE (tmp) = build2 (COMPOUND_EXPR, TREE_TYPE (t),
- TREE_VALUE (tmp), t);
+ tree t = build0 (EMPTY_CLASS_EXPR, TREE_TYPE (argarray[i]));
+ argarray[i] = build2 (COMPOUND_EXPR, TREE_TYPE (t),
+ argarray[i], t);
}
- function = build_call_list (result_type, function, parms);
+ function = build_call_array (result_type, function, n, argarray);
TREE_HAS_CONSTRUCTOR (function) = is_constructor;
TREE_NOTHROW (function) = nothrow;
@@ -4005,7 +4026,7 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
tree alloc_fn)
{
tree fn = NULL_TREE;
- tree fns, fnname, argtypes, args, type;
+ tree fns, fnname, argtypes, type;
int pass;
if (addr == error_mark_node)
@@ -4036,25 +4057,22 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
if (fns == NULL_TREE)
fns = lookup_name_nonclass (fnname);
+ /* Strip const and volatile from addr. */
+ addr = cp_convert (ptr_type_node, addr);
+
if (placement)
{
/* Get the parameter types for the allocation function that is
being called. */
gcc_assert (alloc_fn != NULL_TREE);
argtypes = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (alloc_fn)));
- /* Also the second argument. */
- args = TREE_CHAIN (TREE_OPERAND (placement, 1));
}
else
{
/* First try it without the size argument. */
argtypes = void_list_node;
- args = NULL_TREE;
}
- /* Strip const and volatile from addr. */
- addr = cp_convert (ptr_type_node, addr);
-
/* We make two tries at finding a matching `operator delete'. On
the first pass, we look for a one-operator (or placement)
operator delete. If we're not doing placement delete, then on
@@ -4113,21 +4131,29 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
if (DECL_CLASS_SCOPE_P (fn))
perform_or_defer_access_check (TYPE_BINFO (type), fn, fn);
- if (pass == 0)
- args = tree_cons (NULL_TREE, addr, args);
- else
- args = tree_cons (NULL_TREE, addr,
- build_tree_list (NULL_TREE, size));
-
if (placement)
{
/* The placement args might not be suitable for overload
resolution at this point, so build the call directly. */
+ int nargs = call_expr_nargs (placement);
+ tree *argarray = (tree *) alloca (nargs * sizeof (tree));
+ int i;
+ argarray[0] = addr;
+ for (i = 1; i < nargs; i++)
+ argarray[i] = CALL_EXPR_ARG (placement, i);
mark_used (fn);
- return build_cxx_call (fn, args);
+ return build_cxx_call (fn, nargs, argarray);
}
else
- return build_function_call (fn, args);
+ {
+ tree args;
+ if (pass == 0)
+ args = tree_cons (NULL_TREE, addr, NULL_TREE);
+ else
+ args = tree_cons (NULL_TREE, addr,
+ build_tree_list (NULL_TREE, size));
+ return build_function_call (fn, args);
+ }
}
/* If we are doing placement delete we do nothing if we don't find a
@@ -4494,7 +4520,7 @@ call_builtin_trap (void)
tree fn = implicit_built_in_decls[BUILT_IN_TRAP];
gcc_assert (fn != NULL);
- fn = build_call (fn, NULL_TREE);
+ fn = build_call_n (fn, 0);
return fn;
}
@@ -4725,11 +4751,14 @@ build_over_call (struct z_candidate *cand, int flags)
tree args = cand->args;
conversion **convs = cand->convs;
conversion *conv;
- tree converted_args = NULL_TREE;
tree parm = TYPE_ARG_TYPES (TREE_TYPE (fn));
+ int parmlen;
tree arg, val;
int i = 0;
+ int j = 0;
int is_method = 0;
+ int nargs;
+ tree *argarray;
/* In a template, there is no need to perform all of the work that
is normally done. We are only interested in the type of the call
@@ -4795,11 +4824,18 @@ build_over_call (struct z_candidate *cand, int flags)
args = build_tree_list (NULL_TREE, args);
arg = args;
+ /* Find maximum size of vector to hold converted arguments. */
+ parmlen = list_length (parm);
+ nargs = list_length (args);
+ if (parmlen > nargs)
+ nargs = parmlen;
+ argarray = (tree *) alloca (nargs * sizeof (tree));
+
/* The implicit parameters to a constructor are not considered by overload
resolution, and must be of the proper type. */
if (DECL_CONSTRUCTOR_P (fn))
{
- converted_args = tree_cons (NULL_TREE, TREE_VALUE (arg), converted_args);
+ argarray[j++] = TREE_VALUE (arg);
arg = TREE_CHAIN (arg);
parm = TREE_CHAIN (parm);
/* We should never try to call the abstract constructor. */
@@ -4807,8 +4843,7 @@ build_over_call (struct z_candidate *cand, int flags)
if (DECL_HAS_VTT_PARM_P (fn))
{
- converted_args = tree_cons
- (NULL_TREE, TREE_VALUE (arg), converted_args);
+ argarray[j++] = TREE_VALUE (arg);
arg = TREE_CHAIN (arg);
parm = TREE_CHAIN (parm);
}
@@ -4852,7 +4887,7 @@ build_over_call (struct z_candidate *cand, int flags)
converted_arg = build_base_path (PLUS_EXPR, converted_arg,
base_binfo, 1);
- converted_args = tree_cons (NULL_TREE, converted_arg, converted_args);
+ argarray[j++] = converted_arg;
parm = TREE_CHAIN (parm);
arg = TREE_CHAIN (arg);
++i;
@@ -4875,18 +4910,14 @@ build_over_call (struct z_candidate *cand, int flags)
(conv, TREE_VALUE (arg), fn, i - is_method);
val = convert_for_arg_passing (type, val);
- converted_args = tree_cons (NULL_TREE, val, converted_args);
+ argarray[j++] = val;
}
/* Default arguments */
for (; parm && parm != void_list_node; parm = TREE_CHAIN (parm), i++)
- converted_args
- = tree_cons (NULL_TREE,
- convert_default_arg (TREE_VALUE (parm),
- TREE_PURPOSE (parm),
- fn, i - is_method),
- converted_args);
-
+ argarray[j++] = convert_default_arg (TREE_VALUE (parm),
+ TREE_PURPOSE (parm),
+ fn, i - is_method);
/* Ellipsis */
for (; arg; arg = TREE_CHAIN (arg))
{
@@ -4895,13 +4926,14 @@ build_over_call (struct z_candidate *cand, int flags)
/* Do no conversions for magic varargs. */;
else
a = convert_arg_to_ellipsis (a);
- converted_args = tree_cons (NULL_TREE, a, converted_args);
+ argarray[j++] = a;
}
- converted_args = nreverse (converted_args);
+ gcc_assert (j <= nargs);
+ nargs = j;
check_function_arguments (TYPE_ATTRIBUTES (TREE_TYPE (fn)),
- converted_args, TYPE_ARG_TYPES (TREE_TYPE (fn)));
+ nargs, argarray, TYPE_ARG_TYPES (TREE_TYPE (fn)));
/* Avoid actually calling copy constructors and copy assignment operators,
if possible. */
@@ -4911,8 +4943,7 @@ build_over_call (struct z_candidate *cand, int flags)
else if (cand->num_convs == 1 && DECL_COPY_CONSTRUCTOR_P (fn))
{
tree targ;
- arg = skip_artificial_parms_for (fn, converted_args);
- arg = TREE_VALUE (arg);
+ arg = argarray[num_artificial_parms_for (fn)];
/* Pull out the real argument, disregarding const-correctness. */
targ = arg;
@@ -4967,11 +4998,11 @@ build_over_call (struct z_candidate *cand, int flags)
&& TYPE_HAS_TRIVIAL_ASSIGN_REF (DECL_CONTEXT (fn)))
{
tree to = stabilize_reference
- (build_indirect_ref (TREE_VALUE (converted_args), 0));
+ (build_indirect_ref (argarray[0], 0));
tree type = TREE_TYPE (to);
tree as_base = CLASSTYPE_AS_BASE (type);
- arg = TREE_VALUE (TREE_CHAIN (converted_args));
+ arg = argarray[1];
if (tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (as_base)))
{
arg = build_indirect_ref (arg, 0);
@@ -4981,17 +5012,16 @@ build_over_call (struct z_candidate *cand, int flags)
{
/* We must only copy the non-tail padding parts.
Use __builtin_memcpy for the bitwise copy. */
+
+ tree arg0, arg1, arg2, t;
- tree args, t;
-
- args = tree_cons (NULL, TYPE_SIZE_UNIT (as_base), NULL);
- args = tree_cons (NULL, arg, args);
- t = build_unary_op (ADDR_EXPR, to, 0);
- args = tree_cons (NULL, t, args);
+ arg2 = TYPE_SIZE_UNIT (as_base);
+ arg1 = arg;
+ arg0 = build_unary_op (ADDR_EXPR, to, 0);
t = implicit_built_in_decls[BUILT_IN_MEMCPY];
- t = build_call (t, args);
+ t = build_call_n (t, 3, arg0, arg1, arg2);
- t = convert (TREE_TYPE (TREE_VALUE (args)), t);
+ t = convert (TREE_TYPE (arg0), t);
val = build_indirect_ref (t, 0);
}
@@ -5002,20 +5032,20 @@ build_over_call (struct z_candidate *cand, int flags)
if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0)
{
- tree t, *p = &TREE_VALUE (converted_args);
- tree binfo = lookup_base (TREE_TYPE (TREE_TYPE (*p)),
+ tree t;
+ tree binfo = lookup_base (TREE_TYPE (TREE_TYPE (argarray[0])),
DECL_CONTEXT (fn),
ba_any, NULL);
gcc_assert (binfo && binfo != error_mark_node);
- *p = build_base_path (PLUS_EXPR, *p, binfo, 1);
- if (TREE_SIDE_EFFECTS (*p))
- *p = save_expr (*p);
+ argarray[0] = build_base_path (PLUS_EXPR, argarray[0], binfo, 1);
+ if (TREE_SIDE_EFFECTS (argarray[0]))
+ argarray[0] = save_expr (argarray[0]);
t = build_pointer_type (TREE_TYPE (fn));
if (DECL_CONTEXT (fn) && TYPE_JAVA_INTERFACE (DECL_CONTEXT (fn)))
- fn = build_java_interface_fn_ref (fn, *p);
+ fn = build_java_interface_fn_ref (fn, argarray[0]);
else
- fn = build_vfn_ref (*p, DECL_VINDEX (fn));
+ fn = build_vfn_ref (argarray[0], DECL_VINDEX (fn));
TREE_TYPE (fn) = t;
}
else if (DECL_INLINE (fn))
@@ -5023,19 +5053,19 @@ build_over_call (struct z_candidate *cand, int flags)
else
fn = build_addr_func (fn);
- return build_cxx_call (fn, converted_args);
+ return build_cxx_call (fn, nargs, argarray);
}
-/* Build and return a call to FN, using ARGS. This function performs
- no overload resolution, conversion, or other high-level
- operations. */
+/* Build and return a call to FN, using NARGS arguments in ARGARRAY.
+ This function performs no overload resolution, conversion, or other
+ high-level operations. */
tree
-build_cxx_call (tree fn, tree args)
+build_cxx_call (tree fn, int nargs, tree *argarray)
{
tree fndecl;
- fn = build_call (fn, args);
+ fn = build_call_a (fn, nargs, argarray);
/* If this call might throw an exception, note that fact. */
fndecl = get_callee_fndecl (fn);
@@ -5069,7 +5099,7 @@ static GTY(()) tree java_iface_lookup_fn;
static tree
build_java_interface_fn_ref (tree fn, tree instance)
{
- tree lookup_args, lookup_fn, method, idx;
+ tree lookup_fn, method, idx;
tree klass_ref, iface, iface_ref;
int i;
@@ -5116,13 +5146,11 @@ build_java_interface_fn_ref (tree fn, tree instance)
}
idx = build_int_cst (NULL_TREE, i);
- lookup_args = tree_cons (NULL_TREE, klass_ref,
- tree_cons (NULL_TREE, iface_ref,
- build_tree_list (NULL_TREE, idx)));
lookup_fn = build1 (ADDR_EXPR,
build_pointer_type (TREE_TYPE (java_iface_lookup_fn)),
java_iface_lookup_fn);
- return build_call_list (ptr_type_node, lookup_fn, lookup_args);
+ return build_call_nary (ptr_type_node, lookup_fn,
+ 3, klass_ref, iface_ref, idx);
}
/* Returns the value to use for the in-charge parameter when making a
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index aa1b0ed..bd67ad1 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -146,9 +146,7 @@ genericize_eh_spec_block (tree *stmt_p)
{
tree body = EH_SPEC_STMTS (*stmt_p);
tree allowed = EH_SPEC_RAISES (*stmt_p);
- tree failure = build_call (call_unexpected_node,
- tree_cons (NULL_TREE, build_exc_ptr (),
- NULL_TREE));
+ tree failure = build_call_n (call_unexpected_node, 1, build_exc_ptr ());
gimplify_stmt (&body);
*stmt_p = gimple_build_eh_filter (body, allowed, failure);
@@ -432,7 +430,7 @@ gimplify_must_not_throw_expr (tree *expr_p, tree *pre_p)
gimplify_stmt (&body);
stmt = gimple_build_eh_filter (body, NULL_TREE,
- build_call (terminate_node, NULL_TREE));
+ build_call_n (terminate_node, 0));
if (temp)
{
@@ -766,11 +764,16 @@ static tree
cxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2)
{
tree defparm, parm;
- int i;
+ int i = 0;
+ int nargs;
+ tree *argarray;
if (fn == NULL)
return NULL;
+ nargs = list_length (DECL_ARGUMENTS (fn));
+ argarray = (tree *) alloca (nargs * sizeof (tree));
+
defparm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn)));
if (arg2)
defparm = TREE_CHAIN (defparm);
@@ -817,16 +820,14 @@ cxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2)
t = build1 (LABEL_EXPR, void_type_node, lab);
append_to_statement_list (t, &ret);
- t = tree_cons (NULL, p1, NULL);
+ argarray[i++] = p1;
if (arg2)
- t = tree_cons (NULL, p2, t);
+ argarray[i++] = p2;
/* Handle default arguments. */
- i = 1 + (arg2 != NULL);
- for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm))
- t = tree_cons (NULL, convert_default_arg (TREE_VALUE (parm),
- TREE_PURPOSE (parm),
- fn, i++), t);
- t = build_call (fn, nreverse (t));
+ for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm), i++)
+ argarray[i] = convert_default_arg (TREE_VALUE (parm),
+ TREE_PURPOSE (parm), fn, i);
+ t = build_call_a (fn, i, argarray);
append_to_statement_list (t, &ret);
t = fold_convert (TREE_TYPE (p1), TYPE_SIZE_UNIT (inner_type));
@@ -850,16 +851,16 @@ cxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2)
}
else
{
- tree t = tree_cons (NULL, build_fold_addr_expr (arg1), NULL);
+ argarray[i++] = build_fold_addr_expr (arg1);
if (arg2)
- t = tree_cons (NULL, build_fold_addr_expr (arg2), t);
+ argarray[i++] = build_fold_addr_expr (arg2);
/* Handle default arguments. */
- i = 1 + (arg2 != NULL);
- for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm))
- t = tree_cons (NULL, convert_default_arg (TREE_VALUE (parm),
- TREE_PURPOSE (parm),
- fn, i++), t);
- return build_call (fn, nreverse (t));
+ for (parm = defparm; parm != void_list_node;
+ parm = TREE_CHAIN (parm), i++)
+ argarray[i] = convert_default_arg (TREE_VALUE (parm),
+ TREE_PURPOSE (parm),
+ fn, i);
+ return build_call_a (fn, i, argarray);
}
}
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index e03003e..6c4d7ee 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -3859,7 +3859,8 @@ extern bool check_dtor_name (tree, tree);
extern tree build_vfield_ref (tree, tree);
extern tree build_conditional_expr (tree, tree, tree);
extern tree build_addr_func (tree);
-extern tree build_call (tree, tree);
+extern tree build_call_a (tree, int, tree*);
+extern tree build_call_n (tree, int, ...);
extern bool null_ptr_cst_p (tree);
extern bool sufficient_parms_p (tree);
extern tree type_decays_to (tree);
@@ -3889,7 +3890,7 @@ extern tree strip_top_quals (tree);
extern tree perform_implicit_conversion (tree, tree);
extern tree perform_direct_initialization_if_possible (tree, tree, bool);
extern tree in_charge_arg_for_name (tree);
-extern tree build_cxx_call (tree, tree);
+extern tree build_cxx_call (tree, int, tree *);
#ifdef ENABLE_CHECKING
extern void validate_conversion_obstack (void);
#endif /* ENABLE_CHECKING */
@@ -4174,6 +4175,7 @@ extern void synthesize_method (tree);
extern tree lazily_declare_fn (special_function_kind,
tree);
extern tree skip_artificial_parms_for (tree, tree);
+extern int num_artificial_parms_for (tree);
extern tree make_alias_for (tree, tree);
/* In optimize.c */
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 9ad9e3a..3aaa8df 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -5641,7 +5641,7 @@ expand_static_init (tree decl, tree init)
/* Emit code to perform this initialization but once. */
tree if_stmt = NULL_TREE, inner_if_stmt = NULL_TREE;
tree then_clause = NULL_TREE, inner_then_clause = NULL_TREE;
- tree guard, guard_addr, guard_addr_list;
+ tree guard, guard_addr;
tree acquire_fn, release_fn, abort_fn;
tree flag, begin;
@@ -5693,7 +5693,6 @@ expand_static_init (tree decl, tree init)
if (flag_threadsafe_statics)
{
guard_addr = build_address (guard);
- guard_addr_list = build_tree_list (NULL_TREE, guard_addr);
acquire_fn = get_identifier ("__cxa_guard_acquire");
release_fn = get_identifier ("__cxa_guard_release");
@@ -5715,7 +5714,7 @@ expand_static_init (tree decl, tree init)
}
inner_if_stmt = begin_if_stmt ();
- finish_if_stmt_cond (build_call (acquire_fn, guard_addr_list),
+ finish_if_stmt_cond (build_call_n (acquire_fn, 1, guard_addr),
inner_if_stmt);
inner_then_clause = begin_compound_stmt (BCS_NO_SCOPE);
@@ -5725,7 +5724,7 @@ expand_static_init (tree decl, tree init)
TARGET_EXPR_CLEANUP (begin)
= build3 (COND_EXPR, void_type_node, flag,
void_zero_node,
- build_call (abort_fn, guard_addr_list));
+ build_call_n (abort_fn, 1, guard_addr));
CLEANUP_EH_ONLY (begin) = 1;
/* Do the initialization itself. */
@@ -5733,7 +5732,7 @@ expand_static_init (tree decl, tree init)
init = add_stmt_to_compound
(init, build2 (MODIFY_EXPR, void_type_node, flag, boolean_true_node));
init = add_stmt_to_compound
- (init, build_call (release_fn, guard_addr_list));
+ (init, build_call_n (release_fn, 1, guard_addr));
}
else
init = add_stmt_to_compound (init, set_guard (guard));
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index f97ab06..f500437 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -99,7 +99,7 @@ cp_protect_cleanup_actions (void)
When the destruction of an object during stack unwinding exits
using an exception ... void terminate(); is called. */
- return build_call (terminate_node, NULL_TREE);
+ return build_call_n (terminate_node, 0);
}
static tree
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 1ca0798..679be20 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -1540,7 +1540,7 @@ static tree
build_builtin_delete_call (tree addr)
{
mark_used (global_delete_fndecl);
- return build_call (global_delete_fndecl, build_tree_list (NULL_TREE, addr));
+ return build_call_n (global_delete_fndecl, 1, addr);
}
/* Build and return a NEW_EXPR. If NELTS is non-NULL, TYPE[NELTS] is
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 7d5c4e8..4dff5b9 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -452,6 +452,8 @@ use_thunk (tree thunk_fndecl, bool emit_p)
}
else
{
+ int i;
+ tree *argarray = (tree *) alloca (list_length (a) * sizeof (tree));
/* If this is a covariant thunk, or we don't have the necessary
code for efficient thunks, generate a thunk function that
just makes a call to the real function. Unfortunately, this
@@ -475,11 +477,10 @@ use_thunk (tree thunk_fndecl, bool emit_p)
fixed_offset, virtual_offset);
/* Build up the call to the real function. */
- t = tree_cons (NULL_TREE, t, NULL_TREE);
- for (a = TREE_CHAIN (a); a; a = TREE_CHAIN (a))
- t = tree_cons (NULL_TREE, a, t);
- t = nreverse (t);
- t = build_call (alias, t);
+ argarray[0] = t;
+ for (i = 1, a = TREE_CHAIN (a); a; a = TREE_CHAIN (a), i++)
+ argarray[i] = a;
+ t = build_call_a (alias, i, argarray);
CALL_FROM_THUNK_P (t) = 1;
if (VOID_TYPE_P (TREE_TYPE (t)))
@@ -1191,4 +1192,25 @@ skip_artificial_parms_for (tree fn, tree list)
return list;
}
+/* Given a FUNCTION_DECL FN and a chain LIST, return the number of
+ artificial parms in FN. */
+
+int
+num_artificial_parms_for (tree fn)
+{
+ int count = 0;
+
+ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
+ count++;
+ else
+ return 0;
+
+ if (DECL_HAS_IN_CHARGE_PARM_P (fn))
+ count++;
+ if (DECL_HAS_VTT_PARM_P (fn))
+ count++;
+ return count;
+}
+
+
#include "gt-cp-method.h"
diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c
index 8549ec0..121699f 100644
--- a/gcc/cp/rtti.c
+++ b/gcc/cp/rtti.c
@@ -196,7 +196,7 @@ throw_bad_cast (void)
fn = push_throw_library_fn (fn, build_function_type (ptr_type_node,
void_list_node));
- return build_cxx_call (fn, NULL_TREE);
+ return build_cxx_call (fn, 0, NULL);
}
/* Return an expression for "__cxa_bad_typeid()". The expression
@@ -215,7 +215,7 @@ throw_bad_typeid (void)
fn = push_throw_library_fn (fn, t);
}
- return build_cxx_call (fn, NULL_TREE);
+ return build_cxx_call (fn, 0, NULL);
}
/* Return an lvalue expression whose type is "const std::type_info"
@@ -588,7 +588,8 @@ build_dynamic_cast_1 (tree type, tree expr)
else
{
tree retval;
- tree result, td2, td3, elems;
+ tree result, td2, td3;
+ tree elems[4];
tree static_type, target_type, boff;
/* If we got here, we can't convert statically. Therefore,
@@ -646,11 +647,10 @@ build_dynamic_cast_1 (tree type, tree expr)
if (tc == REFERENCE_TYPE)
expr1 = build_unary_op (ADDR_EXPR, expr1, 0);
- elems = tree_cons
- (NULL_TREE, expr1, tree_cons
- (NULL_TREE, td3, tree_cons
- (NULL_TREE, td2, tree_cons
- (NULL_TREE, boff, NULL_TREE))));
+ elems[0] = expr1;
+ elems[1] = td3;
+ elems[2] = td2;
+ elems[3] = boff;
dcast_fn = dynamic_cast_node;
if (!dcast_fn)
@@ -680,7 +680,7 @@ build_dynamic_cast_1 (tree type, tree expr)
pop_nested_namespace (ns);
dynamic_cast_node = dcast_fn;
}
- result = build_cxx_call (dcast_fn, elems);
+ result = build_cxx_call (dcast_fn, 4, elems);
if (tc == REFERENCE_TYPE)
{
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 63f03cc..b8ae880 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -60,7 +60,7 @@ static void casts_away_constness_r (tree *, tree *);
static bool casts_away_constness (tree, tree);
static void maybe_warn_about_returning_address_of_local (tree);
static tree lookup_destructor (tree, tree, tree);
-static tree convert_arguments (tree, tree, tree, int);
+static int convert_arguments (int, tree *, tree, tree, tree, int);
/* Do `exp = require_complete_type (exp);' to make sure exp
does not have an incomplete type. (That includes void types.)
@@ -2670,10 +2670,12 @@ tree
build_function_call (tree function, tree params)
{
tree fntype, fndecl;
- tree coerced_params;
tree name = NULL_TREE;
int is_method;
tree original = function;
+ int nargs, parm_types_len;
+ tree *argarray;
+ tree parm_types;
/* For Objective-C, convert any calls via a cast to OBJC_TYPE_REF
expressions, like those used for ObjC messenger dispatches. */
@@ -2739,22 +2741,29 @@ build_function_call (tree function, tree params)
/* fntype now gets the type of function pointed to. */
fntype = TREE_TYPE (fntype);
+ parm_types = TYPE_ARG_TYPES (fntype);
+
+ /* Allocate storage for converted arguments. */
+ parm_types_len = list_length (parm_types);
+ nargs = list_length (params);
+ if (parm_types_len > nargs)
+ nargs = parm_types_len;
+ argarray = (tree *) alloca (nargs * sizeof (tree));
/* Convert the parameters to the types declared in the
function prototype, or apply default promotions. */
-
- coerced_params = convert_arguments (TYPE_ARG_TYPES (fntype),
- params, fndecl, LOOKUP_NORMAL);
- if (coerced_params == error_mark_node)
+ nargs = convert_arguments (nargs, argarray, parm_types,
+ params, fndecl, LOOKUP_NORMAL);
+ if (nargs < 0)
return error_mark_node;
/* Check for errors in format strings and inappropriately
null parameters. */
- check_function_arguments (TYPE_ATTRIBUTES (fntype), coerced_params,
- TYPE_ARG_TYPES (fntype));
+ check_function_arguments (TYPE_ATTRIBUTES (fntype), nargs, argarray,
+ parm_types);
- return build_cxx_call (function, coerced_params);
+ return build_cxx_call (function, nargs, argarray);
}
/* Convert the actual parameter expressions in the list VALUES
@@ -2762,23 +2771,26 @@ build_function_call (tree function, tree params)
If parmdecls is exhausted, or when an element has NULL as its type,
perform the default conversions.
+ Store the converted arguments in ARGARRAY. NARGS is the size of this array.
+
NAME is an IDENTIFIER_NODE or 0. It is used only for error messages.
This is also where warnings about wrong number of args are generated.
- Return a list of expressions for the parameters as converted.
+ Returns the actual number of arguments processed (which might be less
+ than NARGS), or -1 on error.
- Both VALUES and the returned value are chains of TREE_LIST nodes
- with the elements of the list in the TREE_VALUE slots of those nodes.
+ VALUES is a chain of TREE_LIST nodes with the elements of the list
+ in the TREE_VALUE slots of those nodes.
In C++, unspecified trailing parameters can be filled in with their
default arguments, if such were specified. Do so here. */
-static tree
-convert_arguments (tree typelist, tree values, tree fndecl, int flags)
+static int
+convert_arguments (int nargs, tree *argarray,
+ tree typelist, tree values, tree fndecl, int flags)
{
tree typetail, valtail;
- tree result = NULL_TREE;
const char *called_thing = 0;
int i = 0;
@@ -2807,7 +2819,7 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags)
tree val = TREE_VALUE (valtail);
if (val == error_mark_node || type == error_mark_node)
- return error_mark_node;
+ return -1;
if (type == void_type_node)
{
@@ -2818,11 +2830,7 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags)
}
else
error ("too many arguments to function");
- /* In case anybody wants to know if this argument
- list is valid. */
- if (result)
- TREE_TYPE (tree_last (result)) = error_mark_node;
- break;
+ return i;
}
/* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
@@ -2841,7 +2849,7 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags)
}
if (val == error_mark_node)
- return error_mark_node;
+ return -1;
if (type != 0)
{
@@ -2866,9 +2874,9 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags)
}
if (parmval == error_mark_node)
- return error_mark_node;
+ return -1;
- result = tree_cons (NULL_TREE, parmval, result);
+ argarray[i] = parmval;
}
else
{
@@ -2881,7 +2889,7 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags)
else
val = convert_arg_to_ellipsis (val);
- result = tree_cons (NULL_TREE, val, result);
+ argarray[i] = val;
}
if (typetail)
@@ -2902,9 +2910,9 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags)
fndecl, i);
if (parmval == error_mark_node)
- return error_mark_node;
+ return -1;
- result = tree_cons (0, parmval, result);
+ argarray[i] = parmval;
typetail = TREE_CHAIN (typetail);
/* ends with `...'. */
if (typetail == NULL_TREE)
@@ -2920,11 +2928,12 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags)
}
else
error ("too few arguments to function");
- return error_mark_node;
+ return -1;
}
}
- return nreverse (result);
+ gcc_assert (i <= nargs);
+ return i;
}
/* Build a binary-operation expression, after performing default