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