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

View File

@ -554,7 +554,7 @@ static tree handle_warn_unused_result_attribute (tree *, tree, tree, int,
bool *);
static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
static void check_function_nonnull (tree, tree);
static void check_function_nonnull (tree, int, tree *);
static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT);
static bool nonnull_check_p (tree, unsigned HOST_WIDE_INT);
static bool get_nonnull_operand (tree, unsigned HOST_WIDE_INT *);
@ -5710,13 +5710,15 @@ handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name),
}
/* Check the argument list of a function call for null in argument slots
that are marked as requiring a non-null pointer argument. */
that are marked as requiring a non-null pointer argument. The NARGS
arguments are passed in the array ARGARRAY.
*/
static void
check_function_nonnull (tree attrs, tree params)
check_function_nonnull (tree attrs, int nargs, tree *argarray)
{
tree a, args, param;
int param_num;
tree a, args;
int i;
for (a = attrs; a; a = TREE_CHAIN (a))
{
@ -5728,85 +5730,65 @@ check_function_nonnull (tree attrs, tree params)
should check for non-null, do it. If the attribute has no args,
then every pointer argument is checked (in which case the check
for pointer type is done in check_nonnull_arg). */
for (param = params, param_num = 1; ;
param_num++, param = TREE_CHAIN (param))
for (i = 0; i < nargs; i++)
{
if (!param)
break;
if (!args || nonnull_check_p (args, param_num))
if (!args || nonnull_check_p (args, i + 1))
check_function_arguments_recurse (check_nonnull_arg, NULL,
TREE_VALUE (param),
param_num);
argarray[i],
i + 1);
}
}
}
}
/* Check that the Nth argument of a function call (counting backwards
from the end) is a (pointer)0. */
from the end) is a (pointer)0. The NARGS arguments are passed in the
array ARGARRAY. */
static void
check_function_sentinel (tree attrs, tree params, tree typelist)
check_function_sentinel (tree attrs, int nargs, tree *argarray, tree typelist)
{
tree attr = lookup_attribute ("sentinel", attrs);
if (attr)
{
int len = 0;
int pos = 0;
tree sentinel;
/* Skip over the named arguments. */
while (typelist && params)
{
typelist = TREE_CHAIN (typelist);
params = TREE_CHAIN (params);
}
if (typelist || !params)
warning (OPT_Wformat,
"not enough variable arguments to fit a sentinel");
else
while (typelist && len < nargs)
{
tree sentinel, end;
unsigned pos = 0;
if (TREE_VALUE (attr))
{
tree p = TREE_VALUE (TREE_VALUE (attr));
pos = TREE_INT_CST_LOW (p);
}
sentinel = end = params;
/* Advance `end' ahead of `sentinel' by `pos' positions. */
while (pos > 0 && TREE_CHAIN (end))
{
pos--;
end = TREE_CHAIN (end);
}
if (pos > 0)
{
warning (OPT_Wformat,
"not enough variable arguments to fit a sentinel");
return;
}
/* 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");
typelist = TREE_CHAIN (typelist);
len++;
}
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;
}
/* Check for valid arguments being passed to a function. */
/* Check for valid arguments being passed to a function.
ATTRS is a list of attributes. There are NARGS arguments in the array
ARGARRAY. TYPELIST is the list of argument types for the function.
*/
void
check_function_arguments (tree attrs, tree params, tree typelist)
check_function_arguments (tree attrs, int nargs, tree *argarray, tree typelist)
{
/* Check for null being passed in a pointer argument that must be
non-null. We also need to do this if format checking is enabled. */
if (warn_nonnull)
check_function_nonnull (attrs, params);
check_function_nonnull (attrs, nargs, argarray);
/* Check for errors in format strings. */
if (warn_format || warn_missing_format_attribute)
check_function_format (attrs, params);
check_function_format (attrs, nargs, argarray);
if (warn_format)
check_function_sentinel (attrs, params, typelist);
check_function_sentinel (attrs, nargs, argarray, typelist);
}
/* Generic argument checking recursion routine. PARAM is the argument to

View File

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

View File

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

View File

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

View File

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

View File

@ -3859,7 +3859,8 @@ extern bool check_dtor_name (tree, tree);
extern tree build_vfield_ref (tree, tree);
extern tree build_conditional_expr (tree, tree, tree);
extern tree build_addr_func (tree);
extern tree build_call (tree, tree);
extern tree build_call_a (tree, int, tree*);
extern tree build_call_n (tree, int, ...);
extern bool null_ptr_cst_p (tree);
extern bool sufficient_parms_p (tree);
extern tree type_decays_to (tree);
@ -3889,7 +3890,7 @@ extern tree strip_top_quals (tree);
extern tree perform_implicit_conversion (tree, tree);
extern tree perform_direct_initialization_if_possible (tree, tree, bool);
extern tree in_charge_arg_for_name (tree);
extern tree build_cxx_call (tree, tree);
extern tree build_cxx_call (tree, int, tree *);
#ifdef ENABLE_CHECKING
extern void validate_conversion_obstack (void);
#endif /* ENABLE_CHECKING */
@ -4174,6 +4175,7 @@ extern void synthesize_method (tree);
extern tree lazily_declare_fn (special_function_kind,
tree);
extern tree skip_artificial_parms_for (tree, tree);
extern int num_artificial_parms_for (tree);
extern tree make_alias_for (tree, tree);
/* In optimize.c */

View File

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

View File

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

View File

@ -1540,7 +1540,7 @@ static tree
build_builtin_delete_call (tree addr)
{
mark_used (global_delete_fndecl);
return build_call (global_delete_fndecl, build_tree_list (NULL_TREE, addr));
return build_call_n (global_delete_fndecl, 1, addr);
}
/* 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
{
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"

View File

@ -196,7 +196,7 @@ throw_bad_cast (void)
fn = push_throw_library_fn (fn, build_function_type (ptr_type_node,
void_list_node));
return build_cxx_call (fn, NULL_TREE);
return build_cxx_call (fn, 0, NULL);
}
/* Return an expression for "__cxa_bad_typeid()". The expression
@ -215,7 +215,7 @@ throw_bad_typeid (void)
fn = push_throw_library_fn (fn, t);
}
return build_cxx_call (fn, NULL_TREE);
return build_cxx_call (fn, 0, NULL);
}
/* 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)
{

View File

@ -60,7 +60,7 @@ static void casts_away_constness_r (tree *, tree *);
static bool casts_away_constness (tree, tree);
static void maybe_warn_about_returning_address_of_local (tree);
static tree lookup_destructor (tree, tree, tree);
static tree convert_arguments (tree, tree, tree, int);
static int convert_arguments (int, tree *, tree, tree, tree, int);
/* Do `exp = require_complete_type (exp);' to make sure exp
does not have an incomplete type. (That includes void types.)
@ -2670,10 +2670,12 @@ tree
build_function_call (tree function, tree params)
{
tree fntype, fndecl;
tree coerced_params;
tree name = NULL_TREE;
int is_method;
tree original = function;
int nargs, parm_types_len;
tree *argarray;
tree parm_types;
/* For Objective-C, convert any calls via a cast to OBJC_TYPE_REF
expressions, like those used for ObjC messenger dispatches. */
@ -2739,22 +2741,29 @@ build_function_call (tree function, tree params)
/* fntype now gets the type of function pointed to. */
fntype = TREE_TYPE (fntype);
parm_types = TYPE_ARG_TYPES (fntype);
/* Allocate storage for converted arguments. */
parm_types_len = list_length (parm_types);
nargs = list_length (params);
if (parm_types_len > nargs)
nargs = parm_types_len;
argarray = (tree *) alloca (nargs * sizeof (tree));
/* Convert the parameters to the types declared in the
function prototype, or apply default promotions. */
coerced_params = convert_arguments (TYPE_ARG_TYPES (fntype),
params, fndecl, LOOKUP_NORMAL);
if (coerced_params == error_mark_node)
nargs = convert_arguments (nargs, argarray, parm_types,
params, fndecl, LOOKUP_NORMAL);
if (nargs < 0)
return error_mark_node;
/* Check for errors in format strings and inappropriately
null parameters. */
check_function_arguments (TYPE_ATTRIBUTES (fntype), coerced_params,
TYPE_ARG_TYPES (fntype));
check_function_arguments (TYPE_ATTRIBUTES (fntype), nargs, argarray,
parm_types);
return build_cxx_call (function, coerced_params);
return build_cxx_call (function, nargs, argarray);
}
/* 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

View File

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

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_build2_initializer (enum tree_code, tree, tree, tree);
extern tree fold_build3_initializer (enum tree_code, tree, tree, tree, tree);
extern tree fold_build_call_list (tree, tree, tree);
extern tree fold_build_call_list_initializer (tree, tree, tree);
extern tree fold_build_call_array (tree, tree, int, tree *);
extern tree fold_build_call_array_initializer (tree, tree, int, tree *);
extern tree fold_convert (tree, tree);
extern tree fold_single_bit_test (enum tree_code, tree, tree, tree);
extern tree fold_ignored_result (tree);
@ -4497,8 +4497,7 @@ extern bool fold_builtin_next_arg (tree, bool);
extern enum built_in_function builtin_mathfn_code (tree);
extern tree build_function_call_expr (tree, tree);
extern tree fold_build_call_expr (tree, tree, tree, tree);
extern tree fold_builtin_call_list (tree, tree, tree);
extern tree fold_builtin_call_valist (tree, tree, int, va_list);
extern tree fold_builtin_call_array (tree, tree, int, tree *);
extern tree build_call_expr (tree, int, ...);
extern tree mathfn_built_in (tree, enum built_in_function fn);
extern tree strip_float_extensions (tree);