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