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
This commit is contained in:
Sandra Loosemore 2007-02-28 14:21:20 -05:00 committed by Sandra Loosemore
parent 76bf4853ce
commit 94a0dd7b59
18 changed files with 400 additions and 340 deletions

View File

@ -1,3 +1,25 @@
2007-02-28 Sandra Loosemore <sandra@codesourcery.com>
* builtins.c (fold_builtin_call_list, fold_builtin_call_valist):
Delete, and replace with...
(fold_builtin_call_array): This. Update callers to use it.
* fold-const.c (fold_build_call_list): Delete, and replace with...
(fold_build_call_array): This.
(fold_build_call_list_initializer): Delete, and replace with...
(fold_build_call_array_initializer): This.
* tree.h: Update declarations to reflect above changes.
* c-typeck.c (build_function_call): Store converted arguments
in a stack-allocated array instead of building a list.
(convert_arguments): Store arguments in the array passed in as an
argument, and return the actual number of arguments.
* c-format.c: (check_function_format): Pass arguments in an
array instead of a list.
* c-common.c (check_function_nonnull): Likewise.
(check_function_sentinel): Likewise.
(check_function_arguments): Likewise.
* c-common.h: Update declarations to reflect above changes.
2007-02-28 Jan Hubicka <jh@suse.cz> 2007-02-28 Jan Hubicka <jh@suse.cz>
* predict.def (PRED_TREE_EARLY_RETURN, PRED_CONST_RETURN, * predict.def (PRED_TREE_EARLY_RETURN, PRED_CONST_RETURN,

View File

@ -10124,56 +10124,13 @@ build_function_call_expr (tree fndecl, tree arglist)
{ {
tree fntype = TREE_TYPE (fndecl); tree fntype = TREE_TYPE (fndecl);
tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl); tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
return fold_builtin_call_list (TREE_TYPE (fntype), fn, arglist); int n = list_length (arglist);
} tree *argarray = (tree *) alloca (n * sizeof (tree));
int i;
/* Construct a CALL_EXPR with type TYPE with FN as the function expression.
ARGLIST is a TREE_LIST of arguments. */ for (i = 0; i < n; i++, arglist = TREE_CHAIN (arglist))
argarray[i] = TREE_VALUE (arglist);
tree return fold_builtin_call_array (TREE_TYPE (fntype), fn, n, argarray);
fold_builtin_call_list (tree type, tree fn, tree arglist)
{
tree ret = NULL_TREE;
if (TREE_CODE (fn) == ADDR_EXPR)
{
tree fndecl = TREE_OPERAND (fn, 0);
if (TREE_CODE (fndecl) == FUNCTION_DECL
&& DECL_BUILT_IN (fndecl))
{
/* FIXME: Don't use a list in this interface. */
if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
{
ret = targetm.fold_builtin (fndecl, arglist, false);
if (ret)
return ret;
}
else
{
tree tail = arglist;
tree args[MAX_ARGS_TO_FOLD_BUILTIN];
int nargs;
tree exp;
for (nargs = 0; nargs < MAX_ARGS_TO_FOLD_BUILTIN; nargs++)
{
if (!tail)
break;
args[nargs] = TREE_VALUE (tail);
tail = TREE_CHAIN (tail);
}
if (nargs <= MAX_ARGS_TO_FOLD_BUILTIN)
{
ret = fold_builtin_n (fndecl, args, nargs, false);
if (ret)
return ret;
}
exp = build_call_list (type, fn, arglist);
ret = fold_builtin_varargs (fndecl, exp, false);
return ret ? ret : exp;
}
}
}
return build_call_list (type, fn, arglist);
} }
/* Conveniently construct a function call expression. FNDECL names the /* Conveniently construct a function call expression. FNDECL names the
@ -10184,24 +10141,26 @@ tree
build_call_expr (tree fndecl, int n, ...) build_call_expr (tree fndecl, int n, ...)
{ {
va_list ap; va_list ap;
tree ret;
tree fntype = TREE_TYPE (fndecl); tree fntype = TREE_TYPE (fndecl);
tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl); tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
tree *argarray = (tree *) alloca (n * sizeof (tree));
int i;
va_start (ap, n); va_start (ap, n);
ret = fold_builtin_call_valist (TREE_TYPE (fntype), fn, n, ap); for (i = 0; i < n; i++)
argarray[i] = va_arg (ap, tree);
va_end (ap); va_end (ap);
return ret; return fold_builtin_call_array (TREE_TYPE (fntype), fn, n, argarray);
} }
/* Construct a CALL_EXPR with type TYPE with FN as the function expression. /* Construct a CALL_EXPR with type TYPE with FN as the function expression.
N arguments are passed in the va_list AP. */ N arguments are passed in the array ARGARRAY. */
tree tree
fold_builtin_call_valist (tree type, fold_builtin_call_array (tree type,
tree fn, tree fn,
int n, int n,
va_list ap) tree *argarray)
{ {
tree ret = NULL_TREE; tree ret = NULL_TREE;
int i; int i;
@ -10216,15 +10175,8 @@ fold_builtin_call_valist (tree type,
if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD) if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
{ {
tree arglist = NULL_TREE; tree arglist = NULL_TREE;
va_list ap0; for (i = n - 1; i >= 0; i--)
va_copy (ap0, ap); arglist = tree_cons (NULL_TREE, argarray[i], arglist);
for (i = 0; i < n; i++)
{
tree arg = va_arg (ap0, tree);
arglist = tree_cons (NULL_TREE, arg, arglist);
}
va_end (ap0);
arglist = nreverse (arglist);
ret = targetm.fold_builtin (fndecl, arglist, false); ret = targetm.fold_builtin (fndecl, arglist, false);
if (ret) if (ret)
return ret; return ret;
@ -10233,25 +10185,19 @@ fold_builtin_call_valist (tree type,
{ {
/* First try the transformations that don't require consing up /* First try the transformations that don't require consing up
an exp. */ an exp. */
tree args[MAX_ARGS_TO_FOLD_BUILTIN]; ret = fold_builtin_n (fndecl, argarray, n, false);
va_list ap0;
va_copy (ap0, ap);
for (i = 0; i < n; i++)
args[i] = va_arg (ap0, tree);
va_end (ap0);
ret = fold_builtin_n (fndecl, args, n, false);
if (ret) if (ret)
return ret; return ret;
} }
/* If we got this far, we need to build an exp. */ /* If we got this far, we need to build an exp. */
exp = build_call_valist (type, fn, n, ap); exp = build_call_array (type, fn, n, argarray);
ret = fold_builtin_varargs (fndecl, exp, false); ret = fold_builtin_varargs (fndecl, exp, false);
return ret ? ret : exp; return ret ? ret : exp;
} }
} }
return build_call_valist (type, fn, n, ap); return build_call_array (type, fn, n, argarray);
} }
/* Construct a new CALL_EXPR using the tail of the argument list of EXP /* Construct a new CALL_EXPR using the tail of the argument list of EXP

View File

@ -554,7 +554,7 @@ static tree handle_warn_unused_result_attribute (tree *, tree, tree, int,
bool *); bool *);
static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *); static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
static void check_function_nonnull (tree, tree); static void check_function_nonnull (tree, int, tree *);
static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT); static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT);
static bool nonnull_check_p (tree, unsigned HOST_WIDE_INT); static bool nonnull_check_p (tree, unsigned HOST_WIDE_INT);
static bool get_nonnull_operand (tree, unsigned HOST_WIDE_INT *); static bool get_nonnull_operand (tree, unsigned HOST_WIDE_INT *);
@ -5710,13 +5710,15 @@ handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name),
} }
/* Check the argument list of a function call for null in argument slots /* Check the argument list of a function call for null in argument slots
that are marked as requiring a non-null pointer argument. */ that are marked as requiring a non-null pointer argument. The NARGS
arguments are passed in the array ARGARRAY.
*/
static void static void
check_function_nonnull (tree attrs, tree params) check_function_nonnull (tree attrs, int nargs, tree *argarray)
{ {
tree a, args, param; tree a, args;
int param_num; int i;
for (a = attrs; a; a = TREE_CHAIN (a)) for (a = attrs; a; a = TREE_CHAIN (a))
{ {
@ -5728,85 +5730,65 @@ check_function_nonnull (tree attrs, tree params)
should check for non-null, do it. If the attribute has no args, should check for non-null, do it. If the attribute has no args,
then every pointer argument is checked (in which case the check then every pointer argument is checked (in which case the check
for pointer type is done in check_nonnull_arg). */ for pointer type is done in check_nonnull_arg). */
for (param = params, param_num = 1; ; for (i = 0; i < nargs; i++)
param_num++, param = TREE_CHAIN (param))
{ {
if (!param) if (!args || nonnull_check_p (args, i + 1))
break;
if (!args || nonnull_check_p (args, param_num))
check_function_arguments_recurse (check_nonnull_arg, NULL, check_function_arguments_recurse (check_nonnull_arg, NULL,
TREE_VALUE (param), argarray[i],
param_num); i + 1);
} }
} }
} }
} }
/* Check that the Nth argument of a function call (counting backwards /* Check that the Nth argument of a function call (counting backwards
from the end) is a (pointer)0. */ from the end) is a (pointer)0. The NARGS arguments are passed in the
array ARGARRAY. */
static void static void
check_function_sentinel (tree attrs, tree params, tree typelist) check_function_sentinel (tree attrs, int nargs, tree *argarray, tree typelist)
{ {
tree attr = lookup_attribute ("sentinel", attrs); tree attr = lookup_attribute ("sentinel", attrs);
if (attr) if (attr)
{ {
int len = 0;
int pos = 0;
tree sentinel;
/* Skip over the named arguments. */ /* Skip over the named arguments. */
while (typelist && params) while (typelist && len < nargs)
{
typelist = TREE_CHAIN (typelist);
params = TREE_CHAIN (params);
}
if (typelist || !params)
warning (OPT_Wformat,
"not enough variable arguments to fit a sentinel");
else
{ {
tree sentinel, end; typelist = TREE_CHAIN (typelist);
unsigned pos = 0; len++;
if (TREE_VALUE (attr))
{
tree p = TREE_VALUE (TREE_VALUE (attr));
pos = TREE_INT_CST_LOW (p);
}
sentinel = end = params;
/* Advance `end' ahead of `sentinel' by `pos' positions. */
while (pos > 0 && TREE_CHAIN (end))
{
pos--;
end = TREE_CHAIN (end);
}
if (pos > 0)
{
warning (OPT_Wformat,
"not enough variable arguments to fit a sentinel");
return;
}
/* Now advance both until we find the last parameter. */
while (TREE_CHAIN (end))
{
end = TREE_CHAIN (end);
sentinel = TREE_CHAIN (sentinel);
}
/* Validate the sentinel. */
if ((!POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (sentinel)))
|| !integer_zerop (TREE_VALUE (sentinel)))
/* Although __null (in C++) is only an integer we allow it
nevertheless, as we are guaranteed that it's exactly
as wide as a pointer, and we don't want to force
users to cast the NULL they have written there.
We warn with -Wstrict-null-sentinel, though. */
&& (warn_strict_null_sentinel
|| null_node != TREE_VALUE (sentinel)))
warning (OPT_Wformat, "missing sentinel in function call");
} }
if (TREE_VALUE (attr))
{
tree p = TREE_VALUE (TREE_VALUE (attr));
pos = TREE_INT_CST_LOW (p);
}
/* The sentinel must be one of the varargs, i.e.
in position >= the number of fixed arguments. */
if ((nargs - 1 - pos) < len)
{
warning (OPT_Wformat,
"not enough variable arguments to fit a sentinel");
return;
}
/* Validate the sentinel. */
sentinel = argarray[nargs - 1 - pos];
if ((!POINTER_TYPE_P (TREE_TYPE (sentinel))
|| !integer_zerop (sentinel))
/* Although __null (in C++) is only an integer we allow it
nevertheless, as we are guaranteed that it's exactly
as wide as a pointer, and we don't want to force
users to cast the NULL they have written there.
We warn with -Wstrict-null-sentinel, though. */
&& (warn_strict_null_sentinel || null_node != sentinel))
warning (OPT_Wformat, "missing sentinel in function call");
} }
} }
@ -5996,23 +5978,26 @@ handle_sentinel_attribute (tree *node, tree name, tree args,
return NULL_TREE; return NULL_TREE;
} }
/* Check for valid arguments being passed to a function. */ /* Check for valid arguments being passed to a function.
ATTRS is a list of attributes. There are NARGS arguments in the array
ARGARRAY. TYPELIST is the list of argument types for the function.
*/
void void
check_function_arguments (tree attrs, tree params, tree typelist) check_function_arguments (tree attrs, int nargs, tree *argarray, tree typelist)
{ {
/* Check for null being passed in a pointer argument that must be /* Check for null being passed in a pointer argument that must be
non-null. We also need to do this if format checking is enabled. */ non-null. We also need to do this if format checking is enabled. */
if (warn_nonnull) if (warn_nonnull)
check_function_nonnull (attrs, params); check_function_nonnull (attrs, nargs, argarray);
/* Check for errors in format strings. */ /* Check for errors in format strings. */
if (warn_format || warn_missing_format_attribute) if (warn_format || warn_missing_format_attribute)
check_function_format (attrs, params); check_function_format (attrs, nargs, argarray);
if (warn_format) if (warn_format)
check_function_sentinel (attrs, params, typelist); check_function_sentinel (attrs, nargs, argarray, typelist);
} }
/* Generic argument checking recursion routine. PARAM is the argument to /* Generic argument checking recursion routine. PARAM is the argument to

View File

@ -640,13 +640,13 @@ extern void finish_fname_decls (void);
extern const char *fname_as_string (int); extern const char *fname_as_string (int);
extern tree fname_decl (unsigned, tree); extern tree fname_decl (unsigned, tree);
extern void check_function_arguments (tree, tree, tree); extern void check_function_arguments (tree, int, tree *, tree);
extern void check_function_arguments_recurse (void (*) extern void check_function_arguments_recurse (void (*)
(void *, tree, (void *, tree,
unsigned HOST_WIDE_INT), unsigned HOST_WIDE_INT),
void *, tree, void *, tree,
unsigned HOST_WIDE_INT); unsigned HOST_WIDE_INT);
extern void check_function_format (tree, tree); extern void check_function_format (tree, int, tree *);
extern void set_Wformat (int); extern void set_Wformat (int);
extern tree handle_format_attribute (tree *, tree, tree, int, bool *); extern tree handle_format_attribute (tree *, tree, tree, int, bool *);
extern tree handle_format_arg_attribute (tree *, tree, tree, int, bool *); extern tree handle_format_arg_attribute (tree *, tree, tree, int, bool *);

View File

@ -851,13 +851,14 @@ decode_format_type (const char *s)
/* Check the argument list of a call to printf, scanf, etc. /* Check the argument list of a call to printf, scanf, etc.
ATTRS are the attributes on the function type. ATTRS are the attributes on the function type. There are NARGS argument
PARAMS is the list of argument values. Also, if -Wmissing-format-attribute, values in the array ARGARRAY.
Also, if -Wmissing-format-attribute,
warn for calls to vprintf or vscanf in functions with no such format warn for calls to vprintf or vscanf in functions with no such format
attribute themselves. */ attribute themselves. */
void void
check_function_format (tree attrs, tree params) check_function_format (tree attrs, int nargs, tree *argarray)
{ {
tree a; tree a;
@ -870,7 +871,16 @@ check_function_format (tree attrs, tree params)
function_format_info info; function_format_info info;
decode_format_attr (TREE_VALUE (a), &info, 1); decode_format_attr (TREE_VALUE (a), &info, 1);
if (warn_format) if (warn_format)
check_format_info (&info, params); {
/* FIXME: Rewrite all the internal functions in this file
to use the ARGARRAY directly instead of constructing this
temporary list. */
tree params = NULL_TREE;
int i;
for (i = nargs - 1; i >= 0; i--)
params = tree_cons (NULL_TREE, argarray[i], params);
check_format_info (&info, params);
}
if (warn_missing_format_attribute && info.first_arg_num == 0 if (warn_missing_format_attribute && info.first_arg_num == 0
&& (format_types[info.format_type].flags && (format_types[info.format_type].flags
& (int) FMT_FLAG_ARG_CONVERT)) & (int) FMT_FLAG_ARG_CONVERT))

View File

@ -83,7 +83,7 @@ static int function_types_compatible_p (tree, tree);
static int type_lists_compatible_p (tree, tree); static int type_lists_compatible_p (tree, tree);
static tree decl_constant_value_for_broken_optimization (tree); static tree decl_constant_value_for_broken_optimization (tree);
static tree lookup_field (tree, tree); static tree lookup_field (tree, tree);
static tree convert_arguments (tree, tree, tree, tree); static int convert_arguments (int, tree *, tree, tree, tree, tree);
static tree pointer_diff (tree, tree); static tree pointer_diff (tree, tree);
static tree convert_for_assignment (tree, tree, enum impl_conv, tree, tree, static tree convert_for_assignment (tree, tree, enum impl_conv, tree, tree,
int); int);
@ -2228,9 +2228,11 @@ tree
build_function_call (tree function, tree params) build_function_call (tree function, tree params)
{ {
tree fntype, fundecl = 0; tree fntype, fundecl = 0;
tree coerced_params;
tree name = NULL_TREE, result; tree name = NULL_TREE, result;
tree tem; tree tem;
int nargs;
tree *argarray;
/* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue. */ /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue. */
STRIP_TYPE_NOPS (function); STRIP_TYPE_NOPS (function);
@ -2317,30 +2319,30 @@ build_function_call (tree function, tree params)
/* Convert the parameters to the types declared in the /* Convert the parameters to the types declared in the
function prototype, or apply default promotions. */ function prototype, or apply default promotions. */
coerced_params nargs = list_length (params);
= convert_arguments (TYPE_ARG_TYPES (fntype), params, function, fundecl); argarray = (tree *) alloca (nargs * sizeof (tree));
nargs = convert_arguments (nargs, argarray, TYPE_ARG_TYPES (fntype),
if (coerced_params == error_mark_node) params, function, fundecl);
if (nargs < 0)
return error_mark_node; return error_mark_node;
/* Check that the arguments to the function are valid. */ /* Check that the arguments to the function are valid. */
check_function_arguments (TYPE_ATTRIBUTES (fntype), coerced_params, check_function_arguments (TYPE_ATTRIBUTES (fntype), nargs, argarray,
TYPE_ARG_TYPES (fntype)); TYPE_ARG_TYPES (fntype));
if (require_constant_value) if (require_constant_value)
{ {
result = fold_build_call_list_initializer (TREE_TYPE (fntype), result = fold_build_call_array_initializer (TREE_TYPE (fntype),
function, function, nargs, argarray);
coerced_params);
if (TREE_CONSTANT (result) if (TREE_CONSTANT (result)
&& (name == NULL_TREE && (name == NULL_TREE
|| strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10) != 0)) || strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10) != 0))
pedwarn_init ("initializer element is not constant"); pedwarn_init ("initializer element is not constant");
} }
else else
result = fold_build_call_list (TREE_TYPE (fntype), result = fold_build_call_array (TREE_TYPE (fntype),
function, coerced_params); function, nargs, argarray);
if (VOID_TYPE_P (TREE_TYPE (result))) if (VOID_TYPE_P (TREE_TYPE (result)))
return result; return result;
@ -2348,9 +2350,8 @@ build_function_call (tree function, tree params)
} }
/* Convert the argument expressions in the list VALUES /* Convert the argument expressions in the list VALUES
to the types in the list TYPELIST. The result is a list of converted to the types in the list TYPELIST. The resulting arguments are
argument expressions, unless there are too few arguments in which stored in the array ARGARRAY which has size NARGS.
case it is error_mark_node.
If TYPELIST is exhausted, or when an element has NULL as its type, If TYPELIST is exhausted, or when an element has NULL as its type,
perform the default conversions. perform the default conversions.
@ -2364,14 +2365,17 @@ build_function_call (tree function, tree params)
This is also where warnings about wrong number of args are generated. This is also where warnings about wrong number of args are generated.
Both VALUES and the returned value are chains of TREE_LIST nodes VALUES is a chain of TREE_LIST nodes with the elements of the list
with the elements of the list in the TREE_VALUE slots of those nodes. */ in the TREE_VALUE slots of those nodes.
static tree Returns the actual number of arguments processed (which may be less
convert_arguments (tree typelist, tree values, tree function, tree fundecl) than NARGS in some error situations), or -1 on failure. */
static int
convert_arguments (int nargs, tree *argarray,
tree typelist, tree values, tree function, tree fundecl)
{ {
tree typetail, valtail; tree typetail, valtail;
tree result = NULL;
int parmnum; int parmnum;
tree selector; tree selector;
@ -2385,7 +2389,7 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl)
selector = objc_message_selector (); selector = objc_message_selector ();
/* Scan the given expressions and types, producing individual /* Scan the given expressions and types, producing individual
converted arguments and pushing them on RESULT in reverse order. */ converted arguments and storing them in ARGARRAY. */
for (valtail = values, typetail = typelist, parmnum = 0; for (valtail = values, typetail = typelist, parmnum = 0;
valtail; valtail;
@ -2400,7 +2404,7 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl)
if (type == void_type_node) if (type == void_type_node)
{ {
error ("too many arguments to function %qE", function); error ("too many arguments to function %qE", function);
break; return parmnum;
} }
if (selector && argnum > 2) if (selector && argnum > 2)
@ -2558,35 +2562,37 @@ convert_arguments (tree typelist, tree values, tree function, tree fundecl)
&& (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))) && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
parmval = default_conversion (parmval); parmval = default_conversion (parmval);
} }
result = tree_cons (NULL_TREE, parmval, result); argarray[parmnum] = parmval;
} }
else if (TREE_CODE (TREE_TYPE (val)) == REAL_TYPE else if (TREE_CODE (TREE_TYPE (val)) == REAL_TYPE
&& (TYPE_PRECISION (TREE_TYPE (val)) && (TYPE_PRECISION (TREE_TYPE (val))
< TYPE_PRECISION (double_type_node)) < TYPE_PRECISION (double_type_node))
&& !DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (val)))) && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (val))))
/* Convert `float' to `double'. */ /* Convert `float' to `double'. */
result = tree_cons (NULL_TREE, convert (double_type_node, val), result); argarray[parmnum] = convert (double_type_node, val);
else if ((invalid_func_diag = else if ((invalid_func_diag =
targetm.calls.invalid_arg_for_unprototyped_fn (typelist, fundecl, val))) targetm.calls.invalid_arg_for_unprototyped_fn (typelist, fundecl, val)))
{ {
error (invalid_func_diag); error (invalid_func_diag);
return error_mark_node; return -1;
} }
else else
/* Convert `short' and `char' to full-size `int'. */ /* Convert `short' and `char' to full-size `int'. */
result = tree_cons (NULL_TREE, default_conversion (val), result); argarray[parmnum] = default_conversion (val);
if (typetail) if (typetail)
typetail = TREE_CHAIN (typetail); typetail = TREE_CHAIN (typetail);
} }
gcc_assert (parmnum == nargs);
if (typetail != 0 && TREE_VALUE (typetail) != void_type_node) if (typetail != 0 && TREE_VALUE (typetail) != void_type_node)
{ {
error ("too few arguments to function %qE", function); error ("too few arguments to function %qE", function);
return error_mark_node; return -1;
} }
return nreverse (result); return parmnum;
} }
/* This is the entry point used by the parser to build unary operators /* This is the entry point used by the parser to build unary operators

View File

@ -1,3 +1,30 @@
2007-02-28 Sandra Loosemore <sandra@codesourcery.com>
* typeck.c (build_function_call): Store converted arguments
in a stack-allocated array instead of building a list.
(convert_arguments): Store arguments in the array passed in as an
argument, and return the actual number of arguments.
* call.c (build_call): Delete, and replace with...
(build_call_n, build_call_a): New.
(build_op_delete_call): Rewrite to avoid constructing argument lists.
(build_over_call): Store converted arguments in a stack-allocated
array instead of building a list.
(build_cxx_call): Pass arguments in an array instead of as a list.
(build_java_interface_fn_ref): Rewrite to avoid constructing
argument lists.
* tree.h: Update declarations to reflect above changes.
* method.c (use_thunk): Use a stack-allocated array to hold
the arguments instead of a list.
* rtti.c (throw_bad_cast): Update call to cxx_call.
(throw_bad_typeid): Likewise.
(build_dynamic_cast_1): Likewise.
* init.c (build_builtin_delete_call): Use build_call_n.
* decl.c (expand_static_init): Likewise.
* except.c (cp_protect_cleanup_actions): Likewise.
* cp-gimplify.c (genericize_eh_spec_block): Likewise.
(gimplify_must_not_throw_expr): Likewise.
(cxx_omp_apply_fn): Use build_call_a.
2007-02-26 Mark Mitchell <mark@codesourcery.com> 2007-02-26 Mark Mitchell <mark@codesourcery.com>
* semantics.c (expand_or_defer_fn): Call c_record_cdtor_fn. * semantics.c (expand_or_defer_fn): Call c_record_cdtor_fn.

View File

@ -269,17 +269,38 @@ build_addr_func (tree function)
/* Build a CALL_EXPR, we can handle FUNCTION_TYPEs, METHOD_TYPEs, or /* Build a CALL_EXPR, we can handle FUNCTION_TYPEs, METHOD_TYPEs, or
POINTER_TYPE to those. Note, pointer to member function types 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 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 is_constructor = 0;
int nothrow; int nothrow;
tree tmp;
tree decl; tree decl;
tree result_type; tree result_type;
tree fntype; tree fntype;
int i;
function = build_addr_func (function); 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. for tags in STL, which are used to control overload resolution.
We don't need to handle other cases of copying empty classes. */ We don't need to handle other cases of copying empty classes. */
if (! decl || ! DECL_BUILT_IN (decl)) if (! decl || ! DECL_BUILT_IN (decl))
for (tmp = parms; tmp; tmp = TREE_CHAIN (tmp)) for (i = 0; i < n; i++)
if (is_empty_class (TREE_TYPE (TREE_VALUE (tmp))) if (is_empty_class (TREE_TYPE (argarray[i]))
&& ! TREE_ADDRESSABLE (TREE_TYPE (TREE_VALUE (tmp)))) && ! TREE_ADDRESSABLE (TREE_TYPE (argarray[i])))
{ {
tree t = build0 (EMPTY_CLASS_EXPR, TREE_TYPE (TREE_VALUE (tmp))); tree t = build0 (EMPTY_CLASS_EXPR, TREE_TYPE (argarray[i]));
TREE_VALUE (tmp) = build2 (COMPOUND_EXPR, TREE_TYPE (t), argarray[i] = build2 (COMPOUND_EXPR, TREE_TYPE (t),
TREE_VALUE (tmp), 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_HAS_CONSTRUCTOR (function) = is_constructor;
TREE_NOTHROW (function) = nothrow; TREE_NOTHROW (function) = nothrow;
@ -4005,7 +4026,7 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
tree alloc_fn) tree alloc_fn)
{ {
tree fn = NULL_TREE; tree fn = NULL_TREE;
tree fns, fnname, argtypes, args, type; tree fns, fnname, argtypes, type;
int pass; int pass;
if (addr == error_mark_node) 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) if (fns == NULL_TREE)
fns = lookup_name_nonclass (fnname); fns = lookup_name_nonclass (fnname);
/* Strip const and volatile from addr. */
addr = cp_convert (ptr_type_node, addr);
if (placement) if (placement)
{ {
/* Get the parameter types for the allocation function that is /* Get the parameter types for the allocation function that is
being called. */ being called. */
gcc_assert (alloc_fn != NULL_TREE); gcc_assert (alloc_fn != NULL_TREE);
argtypes = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (alloc_fn))); argtypes = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (alloc_fn)));
/* Also the second argument. */
args = TREE_CHAIN (TREE_OPERAND (placement, 1));
} }
else else
{ {
/* First try it without the size argument. */ /* First try it without the size argument. */
argtypes = void_list_node; 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 /* We make two tries at finding a matching `operator delete'. On
the first pass, we look for a one-operator (or placement) the first pass, we look for a one-operator (or placement)
operator delete. If we're not doing placement delete, then on 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)) if (DECL_CLASS_SCOPE_P (fn))
perform_or_defer_access_check (TYPE_BINFO (type), fn, 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) if (placement)
{ {
/* The placement args might not be suitable for overload /* The placement args might not be suitable for overload
resolution at this point, so build the call directly. */ 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); mark_used (fn);
return build_cxx_call (fn, args); return build_cxx_call (fn, nargs, argarray);
} }
else 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 /* 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]; tree fn = implicit_built_in_decls[BUILT_IN_TRAP];
gcc_assert (fn != NULL); gcc_assert (fn != NULL);
fn = build_call (fn, NULL_TREE); fn = build_call_n (fn, 0);
return fn; return fn;
} }
@ -4725,11 +4751,14 @@ build_over_call (struct z_candidate *cand, int flags)
tree args = cand->args; tree args = cand->args;
conversion **convs = cand->convs; conversion **convs = cand->convs;
conversion *conv; conversion *conv;
tree converted_args = NULL_TREE;
tree parm = TYPE_ARG_TYPES (TREE_TYPE (fn)); tree parm = TYPE_ARG_TYPES (TREE_TYPE (fn));
int parmlen;
tree arg, val; tree arg, val;
int i = 0; int i = 0;
int j = 0;
int is_method = 0; int is_method = 0;
int nargs;
tree *argarray;
/* In a template, there is no need to perform all of the work that /* 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 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); args = build_tree_list (NULL_TREE, args);
arg = 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 /* The implicit parameters to a constructor are not considered by overload
resolution, and must be of the proper type. */ resolution, and must be of the proper type. */
if (DECL_CONSTRUCTOR_P (fn)) 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); arg = TREE_CHAIN (arg);
parm = TREE_CHAIN (parm); parm = TREE_CHAIN (parm);
/* We should never try to call the abstract constructor. */ /* 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)) if (DECL_HAS_VTT_PARM_P (fn))
{ {
converted_args = tree_cons argarray[j++] = TREE_VALUE (arg);
(NULL_TREE, TREE_VALUE (arg), converted_args);
arg = TREE_CHAIN (arg); arg = TREE_CHAIN (arg);
parm = TREE_CHAIN (parm); 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, converted_arg = build_base_path (PLUS_EXPR, converted_arg,
base_binfo, 1); base_binfo, 1);
converted_args = tree_cons (NULL_TREE, converted_arg, converted_args); argarray[j++] = converted_arg;
parm = TREE_CHAIN (parm); parm = TREE_CHAIN (parm);
arg = TREE_CHAIN (arg); arg = TREE_CHAIN (arg);
++i; ++i;
@ -4875,18 +4910,14 @@ build_over_call (struct z_candidate *cand, int flags)
(conv, TREE_VALUE (arg), fn, i - is_method); (conv, TREE_VALUE (arg), fn, i - is_method);
val = convert_for_arg_passing (type, val); val = convert_for_arg_passing (type, val);
converted_args = tree_cons (NULL_TREE, val, converted_args); argarray[j++] = val;
} }
/* Default arguments */ /* Default arguments */
for (; parm && parm != void_list_node; parm = TREE_CHAIN (parm), i++) for (; parm && parm != void_list_node; parm = TREE_CHAIN (parm), i++)
converted_args argarray[j++] = convert_default_arg (TREE_VALUE (parm),
= tree_cons (NULL_TREE, TREE_PURPOSE (parm),
convert_default_arg (TREE_VALUE (parm), fn, i - is_method);
TREE_PURPOSE (parm),
fn, i - is_method),
converted_args);
/* Ellipsis */ /* Ellipsis */
for (; arg; arg = TREE_CHAIN (arg)) 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. */; /* Do no conversions for magic varargs. */;
else else
a = convert_arg_to_ellipsis (a); 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)), 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, /* Avoid actually calling copy constructors and copy assignment operators,
if possible. */ 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)) else if (cand->num_convs == 1 && DECL_COPY_CONSTRUCTOR_P (fn))
{ {
tree targ; tree targ;
arg = skip_artificial_parms_for (fn, converted_args); arg = argarray[num_artificial_parms_for (fn)];
arg = TREE_VALUE (arg);
/* Pull out the real argument, disregarding const-correctness. */ /* Pull out the real argument, disregarding const-correctness. */
targ = arg; targ = arg;
@ -4967,11 +4998,11 @@ build_over_call (struct z_candidate *cand, int flags)
&& TYPE_HAS_TRIVIAL_ASSIGN_REF (DECL_CONTEXT (fn))) && TYPE_HAS_TRIVIAL_ASSIGN_REF (DECL_CONTEXT (fn)))
{ {
tree to = stabilize_reference tree to = stabilize_reference
(build_indirect_ref (TREE_VALUE (converted_args), 0)); (build_indirect_ref (argarray[0], 0));
tree type = TREE_TYPE (to); tree type = TREE_TYPE (to);
tree as_base = CLASSTYPE_AS_BASE (type); 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))) if (tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (as_base)))
{ {
arg = build_indirect_ref (arg, 0); 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. /* We must only copy the non-tail padding parts.
Use __builtin_memcpy for the bitwise copy. */ Use __builtin_memcpy for the bitwise copy. */
tree arg0, arg1, arg2, t;
tree args, t; arg2 = TYPE_SIZE_UNIT (as_base);
arg1 = arg;
args = tree_cons (NULL, TYPE_SIZE_UNIT (as_base), NULL); arg0 = build_unary_op (ADDR_EXPR, to, 0);
args = tree_cons (NULL, arg, args);
t = build_unary_op (ADDR_EXPR, to, 0);
args = tree_cons (NULL, t, args);
t = implicit_built_in_decls[BUILT_IN_MEMCPY]; 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); 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) if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0)
{ {
tree t, *p = &TREE_VALUE (converted_args); tree t;
tree binfo = lookup_base (TREE_TYPE (TREE_TYPE (*p)), tree binfo = lookup_base (TREE_TYPE (TREE_TYPE (argarray[0])),
DECL_CONTEXT (fn), DECL_CONTEXT (fn),
ba_any, NULL); ba_any, NULL);
gcc_assert (binfo && binfo != error_mark_node); gcc_assert (binfo && binfo != error_mark_node);
*p = build_base_path (PLUS_EXPR, *p, binfo, 1); argarray[0] = build_base_path (PLUS_EXPR, argarray[0], binfo, 1);
if (TREE_SIDE_EFFECTS (*p)) if (TREE_SIDE_EFFECTS (argarray[0]))
*p = save_expr (*p); argarray[0] = save_expr (argarray[0]);
t = build_pointer_type (TREE_TYPE (fn)); t = build_pointer_type (TREE_TYPE (fn));
if (DECL_CONTEXT (fn) && TYPE_JAVA_INTERFACE (DECL_CONTEXT (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 else
fn = build_vfn_ref (*p, DECL_VINDEX (fn)); fn = build_vfn_ref (argarray[0], DECL_VINDEX (fn));
TREE_TYPE (fn) = t; TREE_TYPE (fn) = t;
} }
else if (DECL_INLINE (fn)) else if (DECL_INLINE (fn))
@ -5023,19 +5053,19 @@ build_over_call (struct z_candidate *cand, int flags)
else else
fn = build_addr_func (fn); 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 /* Build and return a call to FN, using NARGS arguments in ARGARRAY.
no overload resolution, conversion, or other high-level This function performs no overload resolution, conversion, or other
operations. */ high-level operations. */
tree tree
build_cxx_call (tree fn, tree args) build_cxx_call (tree fn, int nargs, tree *argarray)
{ {
tree fndecl; tree fndecl;
fn = build_call (fn, args); fn = build_call_a (fn, nargs, argarray);
/* If this call might throw an exception, note that fact. */ /* If this call might throw an exception, note that fact. */
fndecl = get_callee_fndecl (fn); fndecl = get_callee_fndecl (fn);
@ -5069,7 +5099,7 @@ static GTY(()) tree java_iface_lookup_fn;
static tree static tree
build_java_interface_fn_ref (tree fn, tree instance) 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; tree klass_ref, iface, iface_ref;
int i; int i;
@ -5116,13 +5146,11 @@ build_java_interface_fn_ref (tree fn, tree instance)
} }
idx = build_int_cst (NULL_TREE, i); 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, lookup_fn = build1 (ADDR_EXPR,
build_pointer_type (TREE_TYPE (java_iface_lookup_fn)), build_pointer_type (TREE_TYPE (java_iface_lookup_fn)),
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 /* Returns the value to use for the in-charge parameter when making a

View File

@ -146,9 +146,7 @@ genericize_eh_spec_block (tree *stmt_p)
{ {
tree body = EH_SPEC_STMTS (*stmt_p); tree body = EH_SPEC_STMTS (*stmt_p);
tree allowed = EH_SPEC_RAISES (*stmt_p); tree allowed = EH_SPEC_RAISES (*stmt_p);
tree failure = build_call (call_unexpected_node, tree failure = build_call_n (call_unexpected_node, 1, build_exc_ptr ());
tree_cons (NULL_TREE, build_exc_ptr (),
NULL_TREE));
gimplify_stmt (&body); gimplify_stmt (&body);
*stmt_p = gimple_build_eh_filter (body, allowed, failure); *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); gimplify_stmt (&body);
stmt = gimple_build_eh_filter (body, NULL_TREE, stmt = gimple_build_eh_filter (body, NULL_TREE,
build_call (terminate_node, NULL_TREE)); build_call_n (terminate_node, 0));
if (temp) if (temp)
{ {
@ -766,11 +764,16 @@ static tree
cxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2) cxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2)
{ {
tree defparm, parm; tree defparm, parm;
int i; int i = 0;
int nargs;
tree *argarray;
if (fn == NULL) if (fn == NULL)
return NULL; return NULL;
nargs = list_length (DECL_ARGUMENTS (fn));
argarray = (tree *) alloca (nargs * sizeof (tree));
defparm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn))); defparm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn)));
if (arg2) if (arg2)
defparm = TREE_CHAIN (defparm); 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); t = build1 (LABEL_EXPR, void_type_node, lab);
append_to_statement_list (t, &ret); append_to_statement_list (t, &ret);
t = tree_cons (NULL, p1, NULL); argarray[i++] = p1;
if (arg2) if (arg2)
t = tree_cons (NULL, p2, t); argarray[i++] = p2;
/* Handle default arguments. */ /* Handle default arguments. */
i = 1 + (arg2 != NULL); for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm), i++)
for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm)) argarray[i] = convert_default_arg (TREE_VALUE (parm),
t = tree_cons (NULL, convert_default_arg (TREE_VALUE (parm), TREE_PURPOSE (parm), fn, i);
TREE_PURPOSE (parm), t = build_call_a (fn, i, argarray);
fn, i++), t);
t = build_call (fn, nreverse (t));
append_to_statement_list (t, &ret); append_to_statement_list (t, &ret);
t = fold_convert (TREE_TYPE (p1), TYPE_SIZE_UNIT (inner_type)); 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 else
{ {
tree t = tree_cons (NULL, build_fold_addr_expr (arg1), NULL); argarray[i++] = build_fold_addr_expr (arg1);
if (arg2) if (arg2)
t = tree_cons (NULL, build_fold_addr_expr (arg2), t); argarray[i++] = build_fold_addr_expr (arg2);
/* Handle default arguments. */ /* Handle default arguments. */
i = 1 + (arg2 != NULL); for (parm = defparm; parm != void_list_node;
for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm)) parm = TREE_CHAIN (parm), i++)
t = tree_cons (NULL, convert_default_arg (TREE_VALUE (parm), argarray[i] = convert_default_arg (TREE_VALUE (parm),
TREE_PURPOSE (parm), TREE_PURPOSE (parm),
fn, i++), t); fn, i);
return build_call (fn, nreverse (t)); return build_call_a (fn, i, argarray);
} }
} }

View File

@ -3859,7 +3859,8 @@ extern bool check_dtor_name (tree, tree);
extern tree build_vfield_ref (tree, tree); extern tree build_vfield_ref (tree, tree);
extern tree build_conditional_expr (tree, tree, tree); extern tree build_conditional_expr (tree, tree, tree);
extern tree build_addr_func (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 null_ptr_cst_p (tree);
extern bool sufficient_parms_p (tree); extern bool sufficient_parms_p (tree);
extern tree type_decays_to (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_implicit_conversion (tree, tree);
extern tree perform_direct_initialization_if_possible (tree, tree, bool); extern tree perform_direct_initialization_if_possible (tree, tree, bool);
extern tree in_charge_arg_for_name (tree); 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 #ifdef ENABLE_CHECKING
extern void validate_conversion_obstack (void); extern void validate_conversion_obstack (void);
#endif /* ENABLE_CHECKING */ #endif /* ENABLE_CHECKING */
@ -4174,6 +4175,7 @@ extern void synthesize_method (tree);
extern tree lazily_declare_fn (special_function_kind, extern tree lazily_declare_fn (special_function_kind,
tree); tree);
extern tree skip_artificial_parms_for (tree, tree); extern tree skip_artificial_parms_for (tree, tree);
extern int num_artificial_parms_for (tree);
extern tree make_alias_for (tree, tree); extern tree make_alias_for (tree, tree);
/* In optimize.c */ /* In optimize.c */

View File

@ -5641,7 +5641,7 @@ expand_static_init (tree decl, tree init)
/* Emit code to perform this initialization but once. */ /* Emit code to perform this initialization but once. */
tree if_stmt = NULL_TREE, inner_if_stmt = NULL_TREE; tree if_stmt = NULL_TREE, inner_if_stmt = NULL_TREE;
tree then_clause = NULL_TREE, inner_then_clause = 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 acquire_fn, release_fn, abort_fn;
tree flag, begin; tree flag, begin;
@ -5693,7 +5693,6 @@ expand_static_init (tree decl, tree init)
if (flag_threadsafe_statics) if (flag_threadsafe_statics)
{ {
guard_addr = build_address (guard); guard_addr = build_address (guard);
guard_addr_list = build_tree_list (NULL_TREE, guard_addr);
acquire_fn = get_identifier ("__cxa_guard_acquire"); acquire_fn = get_identifier ("__cxa_guard_acquire");
release_fn = get_identifier ("__cxa_guard_release"); release_fn = get_identifier ("__cxa_guard_release");
@ -5715,7 +5714,7 @@ expand_static_init (tree decl, tree init)
} }
inner_if_stmt = begin_if_stmt (); 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_if_stmt);
inner_then_clause = begin_compound_stmt (BCS_NO_SCOPE); inner_then_clause = begin_compound_stmt (BCS_NO_SCOPE);
@ -5725,7 +5724,7 @@ expand_static_init (tree decl, tree init)
TARGET_EXPR_CLEANUP (begin) TARGET_EXPR_CLEANUP (begin)
= build3 (COND_EXPR, void_type_node, flag, = build3 (COND_EXPR, void_type_node, flag,
void_zero_node, void_zero_node,
build_call (abort_fn, guard_addr_list)); build_call_n (abort_fn, 1, guard_addr));
CLEANUP_EH_ONLY (begin) = 1; CLEANUP_EH_ONLY (begin) = 1;
/* Do the initialization itself. */ /* Do the initialization itself. */
@ -5733,7 +5732,7 @@ expand_static_init (tree decl, tree init)
init = add_stmt_to_compound init = add_stmt_to_compound
(init, build2 (MODIFY_EXPR, void_type_node, flag, boolean_true_node)); (init, build2 (MODIFY_EXPR, void_type_node, flag, boolean_true_node));
init = add_stmt_to_compound init = add_stmt_to_compound
(init, build_call (release_fn, guard_addr_list)); (init, build_call_n (release_fn, 1, guard_addr));
} }
else else
init = add_stmt_to_compound (init, set_guard (guard)); init = add_stmt_to_compound (init, set_guard (guard));

View File

@ -99,7 +99,7 @@ cp_protect_cleanup_actions (void)
When the destruction of an object during stack unwinding exits When the destruction of an object during stack unwinding exits
using an exception ... void terminate(); is called. */ using an exception ... void terminate(); is called. */
return build_call (terminate_node, NULL_TREE); return build_call_n (terminate_node, 0);
} }
static tree static tree

View File

@ -1540,7 +1540,7 @@ static tree
build_builtin_delete_call (tree addr) build_builtin_delete_call (tree addr)
{ {
mark_used (global_delete_fndecl); 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 /* Build and return a NEW_EXPR. If NELTS is non-NULL, TYPE[NELTS] is

View File

@ -452,6 +452,8 @@ use_thunk (tree thunk_fndecl, bool emit_p)
} }
else 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 /* If this is a covariant thunk, or we don't have the necessary
code for efficient thunks, generate a thunk function that code for efficient thunks, generate a thunk function that
just makes a call to the real function. Unfortunately, this 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); fixed_offset, virtual_offset);
/* Build up the call to the real function. */ /* Build up the call to the real function. */
t = tree_cons (NULL_TREE, t, NULL_TREE); argarray[0] = t;
for (a = TREE_CHAIN (a); a; a = TREE_CHAIN (a)) for (i = 1, a = TREE_CHAIN (a); a; a = TREE_CHAIN (a), i++)
t = tree_cons (NULL_TREE, a, t); argarray[i] = a;
t = nreverse (t); t = build_call_a (alias, i, argarray);
t = build_call (alias, t);
CALL_FROM_THUNK_P (t) = 1; CALL_FROM_THUNK_P (t) = 1;
if (VOID_TYPE_P (TREE_TYPE (t))) if (VOID_TYPE_P (TREE_TYPE (t)))
@ -1191,4 +1192,25 @@ skip_artificial_parms_for (tree fn, tree list)
return 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" #include "gt-cp-method.h"

View File

@ -196,7 +196,7 @@ throw_bad_cast (void)
fn = push_throw_library_fn (fn, build_function_type (ptr_type_node, fn = push_throw_library_fn (fn, build_function_type (ptr_type_node,
void_list_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 /* Return an expression for "__cxa_bad_typeid()". The expression
@ -215,7 +215,7 @@ throw_bad_typeid (void)
fn = push_throw_library_fn (fn, t); 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" /* Return an lvalue expression whose type is "const std::type_info"
@ -588,7 +588,8 @@ build_dynamic_cast_1 (tree type, tree expr)
else else
{ {
tree retval; tree retval;
tree result, td2, td3, elems; tree result, td2, td3;
tree elems[4];
tree static_type, target_type, boff; tree static_type, target_type, boff;
/* If we got here, we can't convert statically. Therefore, /* 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) if (tc == REFERENCE_TYPE)
expr1 = build_unary_op (ADDR_EXPR, expr1, 0); expr1 = build_unary_op (ADDR_EXPR, expr1, 0);
elems = tree_cons elems[0] = expr1;
(NULL_TREE, expr1, tree_cons elems[1] = td3;
(NULL_TREE, td3, tree_cons elems[2] = td2;
(NULL_TREE, td2, tree_cons elems[3] = boff;
(NULL_TREE, boff, NULL_TREE))));
dcast_fn = dynamic_cast_node; dcast_fn = dynamic_cast_node;
if (!dcast_fn) if (!dcast_fn)
@ -680,7 +680,7 @@ build_dynamic_cast_1 (tree type, tree expr)
pop_nested_namespace (ns); pop_nested_namespace (ns);
dynamic_cast_node = dcast_fn; dynamic_cast_node = dcast_fn;
} }
result = build_cxx_call (dcast_fn, elems); result = build_cxx_call (dcast_fn, 4, elems);
if (tc == REFERENCE_TYPE) if (tc == REFERENCE_TYPE)
{ {

View File

@ -60,7 +60,7 @@ static void casts_away_constness_r (tree *, tree *);
static bool casts_away_constness (tree, tree); static bool casts_away_constness (tree, tree);
static void maybe_warn_about_returning_address_of_local (tree); static void maybe_warn_about_returning_address_of_local (tree);
static tree lookup_destructor (tree, tree, 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 /* Do `exp = require_complete_type (exp);' to make sure exp
does not have an incomplete type. (That includes void types.) does not have an incomplete type. (That includes void types.)
@ -2670,10 +2670,12 @@ tree
build_function_call (tree function, tree params) build_function_call (tree function, tree params)
{ {
tree fntype, fndecl; tree fntype, fndecl;
tree coerced_params;
tree name = NULL_TREE; tree name = NULL_TREE;
int is_method; int is_method;
tree original = function; 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 /* For Objective-C, convert any calls via a cast to OBJC_TYPE_REF
expressions, like those used for ObjC messenger dispatches. */ 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 now gets the type of function pointed to. */
fntype = TREE_TYPE (fntype); 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 /* Convert the parameters to the types declared in the
function prototype, or apply default promotions. */ function prototype, or apply default promotions. */
nargs = convert_arguments (nargs, argarray, parm_types,
coerced_params = convert_arguments (TYPE_ARG_TYPES (fntype), params, fndecl, LOOKUP_NORMAL);
params, fndecl, LOOKUP_NORMAL); if (nargs < 0)
if (coerced_params == error_mark_node)
return error_mark_node; return error_mark_node;
/* Check for errors in format strings and inappropriately /* Check for errors in format strings and inappropriately
null parameters. */ null parameters. */
check_function_arguments (TYPE_ATTRIBUTES (fntype), coerced_params, check_function_arguments (TYPE_ATTRIBUTES (fntype), nargs, argarray,
TYPE_ARG_TYPES (fntype)); 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 /* 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, If parmdecls is exhausted, or when an element has NULL as its type,
perform the default conversions. 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. 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. 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 VALUES is a chain of TREE_LIST nodes with the elements of the list
with the elements of the list in the TREE_VALUE slots of those nodes. in the TREE_VALUE slots of those nodes.
In C++, unspecified trailing parameters can be filled in with their In C++, unspecified trailing parameters can be filled in with their
default arguments, if such were specified. Do so here. */ default arguments, if such were specified. Do so here. */
static tree static int
convert_arguments (tree typelist, tree values, tree fndecl, int flags) convert_arguments (int nargs, tree *argarray,
tree typelist, tree values, tree fndecl, int flags)
{ {
tree typetail, valtail; tree typetail, valtail;
tree result = NULL_TREE;
const char *called_thing = 0; const char *called_thing = 0;
int i = 0; int i = 0;
@ -2807,7 +2819,7 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags)
tree val = TREE_VALUE (valtail); tree val = TREE_VALUE (valtail);
if (val == error_mark_node || type == error_mark_node) if (val == error_mark_node || type == error_mark_node)
return error_mark_node; return -1;
if (type == void_type_node) if (type == void_type_node)
{ {
@ -2818,11 +2830,7 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags)
} }
else else
error ("too many arguments to function"); error ("too many arguments to function");
/* In case anybody wants to know if this argument return i;
list is valid. */
if (result)
TREE_TYPE (tree_last (result)) = error_mark_node;
break;
} }
/* build_c_cast puts on a NOP_EXPR to make the result not an lvalue. /* 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) if (val == error_mark_node)
return error_mark_node; return -1;
if (type != 0) if (type != 0)
{ {
@ -2866,9 +2874,9 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags)
} }
if (parmval == error_mark_node) if (parmval == error_mark_node)
return error_mark_node; return -1;
result = tree_cons (NULL_TREE, parmval, result); argarray[i] = parmval;
} }
else else
{ {
@ -2881,7 +2889,7 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags)
else else
val = convert_arg_to_ellipsis (val); val = convert_arg_to_ellipsis (val);
result = tree_cons (NULL_TREE, val, result); argarray[i] = val;
} }
if (typetail) if (typetail)
@ -2902,9 +2910,9 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags)
fndecl, i); fndecl, i);
if (parmval == error_mark_node) if (parmval == error_mark_node)
return error_mark_node; return -1;
result = tree_cons (0, parmval, result); argarray[i] = parmval;
typetail = TREE_CHAIN (typetail); typetail = TREE_CHAIN (typetail);
/* ends with `...'. */ /* ends with `...'. */
if (typetail == NULL_TREE) if (typetail == NULL_TREE)
@ -2920,11 +2928,12 @@ convert_arguments (tree typelist, tree values, tree fndecl, int flags)
} }
else else
error ("too few arguments to function"); 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 /* Build a binary-operation expression, after performing default

View File

@ -12875,13 +12875,13 @@ fold_build3_stat (enum tree_code code, tree type, tree op0, tree op1, tree op2
return tem; return tem;
} }
/* Fold a CALL_EXPR expression of type TYPE with operands FN and ARGLIST /* Fold a CALL_EXPR expression of type TYPE with operands FN and NARGS
and a null static chain. arguments in ARGARRAY, and a null static chain.
Return a folded expression if successful. Otherwise, return a CALL_EXPR Return a folded expression if successful. Otherwise, return a CALL_EXPR
of type TYPE from the given operands as constructed by build_call_list. */ of type TYPE from the given operands as constructed by build_call_array. */
tree tree
fold_build_call_list (tree type, tree fn, tree arglist) fold_build_call_array (tree type, tree fn, int nargs, tree *argarray)
{ {
tree tem; tree tem;
#ifdef ENABLE_FOLD_CHECKING #ifdef ENABLE_FOLD_CHECKING
@ -12891,6 +12891,7 @@ fold_build_call_list (tree type, tree fn, tree arglist)
checksum_after_arglist[16]; checksum_after_arglist[16];
struct md5_ctx ctx; struct md5_ctx ctx;
htab_t ht; htab_t ht;
int i;
ht = htab_create (32, htab_hash_pointer, htab_eq_pointer, NULL); ht = htab_create (32, htab_hash_pointer, htab_eq_pointer, NULL);
md5_init_ctx (&ctx); md5_init_ctx (&ctx);
@ -12899,12 +12900,13 @@ fold_build_call_list (tree type, tree fn, tree arglist)
htab_empty (ht); htab_empty (ht);
md5_init_ctx (&ctx); md5_init_ctx (&ctx);
fold_checksum_tree (arglist, &ctx, ht); for (i = 0; i < nargs; i++)
fold_checksum_tree (argarray[i], &ctx, ht);
md5_finish_ctx (&ctx, checksum_before_arglist); md5_finish_ctx (&ctx, checksum_before_arglist);
htab_empty (ht); htab_empty (ht);
#endif #endif
tem = fold_builtin_call_list (type, fn, arglist); tem = fold_builtin_call_array (type, fn, nargs, argarray);
#ifdef ENABLE_FOLD_CHECKING #ifdef ENABLE_FOLD_CHECKING
md5_init_ctx (&ctx); md5_init_ctx (&ctx);
@ -12916,12 +12918,13 @@ fold_build_call_list (tree type, tree fn, tree arglist)
fold_check_failed (fn, tem); fold_check_failed (fn, tem);
md5_init_ctx (&ctx); md5_init_ctx (&ctx);
fold_checksum_tree (arglist, &ctx, ht); for (i = 0; i < nargs; i++)
fold_checksum_tree (argarray[i], &ctx, ht);
md5_finish_ctx (&ctx, checksum_after_arglist); md5_finish_ctx (&ctx, checksum_after_arglist);
htab_delete (ht); htab_delete (ht);
if (memcmp (checksum_before_arglist, checksum_after_arglist, 16)) if (memcmp (checksum_before_arglist, checksum_after_arglist, 16))
fold_check_failed (arglist, tem); fold_check_failed (NULL_TREE, tem);
#endif #endif
return tem; return tem;
} }
@ -12987,12 +12990,13 @@ fold_build3_initializer (enum tree_code code, tree type, tree op0, tree op1,
} }
tree tree
fold_build_call_list_initializer (tree type, tree fn, tree arglist) fold_build_call_array_initializer (tree type, tree fn,
int nargs, tree *argarray)
{ {
tree result; tree result;
START_FOLD_INIT; START_FOLD_INIT;
result = fold_build_call_list (type, fn, arglist); result = fold_build_call_array (type, fn, nargs, argarray);
END_FOLD_INIT; END_FOLD_INIT;
return result; return result;

View File

@ -4397,8 +4397,8 @@ extern tree fold_build3_stat (enum tree_code, tree, tree, tree, tree MEM_STAT_DE
extern tree fold_build1_initializer (enum tree_code, tree, tree); extern tree fold_build1_initializer (enum tree_code, tree, tree);
extern tree fold_build2_initializer (enum tree_code, tree, tree, tree); extern tree fold_build2_initializer (enum tree_code, tree, tree, tree);
extern tree fold_build3_initializer (enum tree_code, tree, tree, tree, tree); extern tree fold_build3_initializer (enum tree_code, tree, tree, tree, tree);
extern tree fold_build_call_list (tree, tree, tree); extern tree fold_build_call_array (tree, tree, int, tree *);
extern tree fold_build_call_list_initializer (tree, tree, tree); extern tree fold_build_call_array_initializer (tree, tree, int, tree *);
extern tree fold_convert (tree, tree); extern tree fold_convert (tree, tree);
extern tree fold_single_bit_test (enum tree_code, tree, tree, tree); extern tree fold_single_bit_test (enum tree_code, tree, tree, tree);
extern tree fold_ignored_result (tree); extern tree fold_ignored_result (tree);
@ -4497,8 +4497,7 @@ extern bool fold_builtin_next_arg (tree, bool);
extern enum built_in_function builtin_mathfn_code (tree); extern enum built_in_function builtin_mathfn_code (tree);
extern tree build_function_call_expr (tree, tree); extern tree build_function_call_expr (tree, tree);
extern tree fold_build_call_expr (tree, tree, tree, tree); extern tree fold_build_call_expr (tree, tree, tree, tree);
extern tree fold_builtin_call_list (tree, tree, tree); extern tree fold_builtin_call_array (tree, tree, int, tree *);
extern tree fold_builtin_call_valist (tree, tree, int, va_list);
extern tree build_call_expr (tree, int, ...); extern tree build_call_expr (tree, int, ...);
extern tree mathfn_built_in (tree, enum built_in_function fn); extern tree mathfn_built_in (tree, enum built_in_function fn);
extern tree strip_float_extensions (tree); extern tree strip_float_extensions (tree);