diff options
-rw-r--r-- | gcc/ChangeLog | 31 | ||||
-rw-r--r-- | gcc/c-common.c | 65 | ||||
-rw-r--r-- | gcc/c-common.h | 4 | ||||
-rw-r--r-- | gcc/c-parser.c | 80 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 96 | ||||
-rw-r--r-- | gcc/cp/call.c | 690 | ||||
-rw-r--r-- | gcc/cp/class.c | 17 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 40 | ||||
-rw-r--r-- | gcc/cp/cvt.c | 16 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 28 | ||||
-rw-r--r-- | gcc/cp/except.c | 11 | ||||
-rw-r--r-- | gcc/cp/init.c | 191 | ||||
-rw-r--r-- | gcc/cp/method.c | 8 | ||||
-rw-r--r-- | gcc/cp/name-lookup.c | 34 | ||||
-rw-r--r-- | gcc/cp/name-lookup.h | 7 | ||||
-rw-r--r-- | gcc/cp/parser.c | 179 | ||||
-rw-r--r-- | gcc/cp/pt.c | 300 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 80 | ||||
-rw-r--r-- | gcc/cp/tree.c | 4 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 155 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 9 | ||||
-rw-r--r-- | gcc/objc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/objc/objc-act.c | 2 | ||||
-rw-r--r-- | gcc/tree.c | 70 | ||||
-rw-r--r-- | gcc/tree.h | 10 |
25 files changed, 1408 insertions, 724 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b5afced..08543b8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,34 @@ +2009-05-20 Ian Lance Taylor <iant@google.com> + + * tree.c (build_tree_list_vec_stat): New function. + (ctor_to_vec): New function. + (build_nt_call_vec): New function. + (build_call_array): Change args to be a const pointer. + (build_call_vec): New function. + * tree.h (build_nt_call_vec): Declare. + (build_tree_list_vec_stat): Declare. + (build_tree_list_vec): Define. + (build_call_array): Update declaration. + (build_call_vec): Declare. + (ctor_to_vec): Declare. + * c-common.c (tree_vector_cache): New static variable. + (make_tree_vector): New function. + (release_tree_vector): New function. + (make_tree_vector_single): New function. + (make_tree_vector_copy): New function. + * c-common.h (tree_vector_cache, make_tree_vector): Declare. + (make_tree_vector_single, make_tree_vector_copy): Declare. + * c-parser.c (cached_expr_list_1, cached_expr_list_2): Remove. + (c_parser_expr_list): Don't manage cache here, instead call + make_tree_vector. + (c_parser_release_expr_list): Remove static function. + (c_parser_vec_to_tree_list): Remove static function. + (c_parser_attributes): Call build_tree_list_vec instead of + c_parser_vec_to_tree_list. Call release_tree_vector instead of + c_parser_release_expr_list. + (c_parser_postfix_expression_after_primary): Likewise. + (c_parser_objc_keywordexpr): Likewise. + 2009-05-20 Sandra Loosemore <sandra@codesourcery.com> * doc/tm.texi (Misc): Document TARGET_INVALID_PARAMETER_TYPE, diff --git a/gcc/c-common.c b/gcc/c-common.c index 46aacb5..45b4192 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -9132,4 +9132,69 @@ is_typedef_decl (tree x) && DECL_ORIGINAL_TYPE (x) != NULL_TREE); } +/* The C and C++ parsers both use vectors to hold function arguments. + For efficiency, we keep a cache of unused vectors. This is the + cache. */ + +typedef VEC(tree,gc)* tree_gc_vec; +DEF_VEC_P(tree_gc_vec); +DEF_VEC_ALLOC_P(tree_gc_vec,gc); +static GTY((deletable)) VEC(tree_gc_vec,gc) *tree_vector_cache; + +/* Return a new vector from the cache. If the cache is empty, + allocate a new vector. These vectors are GC'ed, so it is OK if the + pointer is not released.. */ + +VEC(tree,gc) * +make_tree_vector (void) +{ + if (!VEC_empty (tree_gc_vec, tree_vector_cache)) + return VEC_pop (tree_gc_vec, tree_vector_cache); + else + { + /* Passing 0 to VEC_alloc returns NULL, and our callers require + that we always return a non-NULL value. The vector code uses + 4 when growing a NULL vector, so we do too. */ + return VEC_alloc (tree, gc, 4); + } +} + +/* Release a vector of trees back to the cache. */ + +void +release_tree_vector (VEC(tree,gc) *vec) +{ + if (vec != NULL) + { + VEC_truncate (tree, vec, 0); + VEC_safe_push (tree_gc_vec, gc, tree_vector_cache, vec); + } +} + +/* Get a new tree vector holding a single tree. */ + +VEC(tree,gc) * +make_tree_vector_single (tree t) +{ + VEC(tree,gc) *ret = make_tree_vector (); + VEC_quick_push (tree, ret, t); + return ret; +} + +/* Get a new tree vector which is a copy of an existing one. */ + +VEC(tree,gc) * +make_tree_vector_copy (const VEC(tree,gc) *orig) +{ + VEC(tree,gc) *ret; + unsigned int ix; + tree t; + + ret = make_tree_vector (); + VEC_reserve (tree, gc, ret, VEC_length (tree, orig)); + for (ix = 0; VEC_iterate (tree, orig, ix, t); ++ix) + VEC_quick_push (tree, ret, t); + return ret; +} + #include "gt-c-common.h" diff --git a/gcc/c-common.h b/gcc/c-common.h index c4fba4d..b17020a 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -1013,6 +1013,10 @@ extern void warn_for_sign_compare (location_t, enum tree_code resultcode); extern void set_underlying_type (tree x); extern bool is_typedef_decl (tree x); +extern VEC(tree,gc) *make_tree_vector (void); +extern void release_tree_vector (VEC(tree,gc) *); +extern VEC(tree,gc) *make_tree_vector_single (tree); +extern VEC(tree,gc) *make_tree_vector_copy (const VEC(tree,gc) *); /* In c-gimplify.c */ extern void c_genericize (tree); diff --git a/gcc/c-parser.c b/gcc/c-parser.c index beda817..0320fee 100644 --- a/gcc/c-parser.c +++ b/gcc/c-parser.c @@ -921,8 +921,6 @@ static struct c_expr c_parser_expression (c_parser *); static struct c_expr c_parser_expression_conv (c_parser *); static VEC(tree,gc) *c_parser_expr_list (c_parser *, bool, bool, VEC(tree,gc) **); -static void c_parser_release_expr_list (VEC(tree,gc) *); -static tree c_parser_vec_to_tree_list (VEC(tree,gc) *); static void c_parser_omp_construct (c_parser *); static void c_parser_omp_threadprivate (c_parser *); static void c_parser_omp_barrier (c_parser *); @@ -2889,9 +2887,9 @@ c_parser_attributes (c_parser *parser) tree tree_list; c_parser_consume_token (parser); expr_list = c_parser_expr_list (parser, false, true, NULL); - tree_list = c_parser_vec_to_tree_list (expr_list); + tree_list = build_tree_list_vec (expr_list); attr_args = tree_cons (NULL_TREE, arg1, tree_list); - c_parser_release_expr_list (expr_list); + release_tree_vector (expr_list); } } else @@ -2901,8 +2899,8 @@ c_parser_attributes (c_parser *parser) else { expr_list = c_parser_expr_list (parser, false, true, NULL); - attr_args = c_parser_vec_to_tree_list (expr_list); - c_parser_release_expr_list (expr_list); + attr_args = build_tree_list_vec (expr_list); + release_tree_vector (expr_list); } } attr = build_tree_list (attr_name, attr_args); @@ -5719,8 +5717,8 @@ c_parser_postfix_expression_after_primary (c_parser *parser, expr.original_type = NULL; if (exprlist != NULL) { - c_parser_release_expr_list (exprlist); - c_parser_release_expr_list (origtypes); + release_tree_vector (exprlist); + release_tree_vector (origtypes); } break; case CPP_DOT: @@ -5853,10 +5851,6 @@ c_parser_expression_conv (c_parser *parser) nonempty-expr-list , assignment-expression */ -/* We cache two vectors, to save most allocation and deallocation. */ -static GTY((deletable)) VEC(tree,gc) *cached_expr_list_1; -static GTY((deletable)) VEC(tree,gc) *cached_expr_list_2; - static VEC(tree,gc) * c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p, VEC(tree,gc) **p_orig_types) @@ -5865,34 +5859,11 @@ c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p, VEC(tree,gc) *orig_types; struct c_expr expr; - if (cached_expr_list_1 != NULL) - { - ret = cached_expr_list_1; - cached_expr_list_1 = NULL; - VEC_truncate (tree, ret, 0); - } - else if (cached_expr_list_2 != NULL) - { - ret = cached_expr_list_2; - cached_expr_list_2 = NULL; - VEC_truncate (tree, ret, 0); - } - else - ret = VEC_alloc (tree, gc, 16); - + ret = make_tree_vector (); if (p_orig_types == NULL) orig_types = NULL; else - { - if (cached_expr_list_2 != NULL) - { - orig_types = cached_expr_list_2; - cached_expr_list_2 = NULL; - VEC_truncate (tree, orig_types, 0); - } - else - orig_types = VEC_alloc (tree, gc, 16); - } + orig_types = make_tree_vector (); expr = c_parser_expr_no_commas (parser, NULL); if (convert_p) @@ -5918,37 +5889,6 @@ c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p, *p_orig_types = orig_types; return ret; } - -/* Release a vector returned by c_parser_expr_list. */ - -static void -c_parser_release_expr_list (VEC(tree,gc) *vec) -{ - if (cached_expr_list_1 == NULL) - cached_expr_list_1 = vec; - else if (cached_expr_list_2 == NULL) - cached_expr_list_2 = vec; - else - VEC_free (tree, gc, vec); -} - -/* Convert a vector, as returned by c_parser_expr_list, to a - tree_list. */ - -static tree -c_parser_vec_to_tree_list (VEC(tree,gc) *vec) -{ - tree ret = NULL_TREE; - tree *pp = &ret; - unsigned int i; - tree t; - for (i = 0; VEC_iterate (tree, vec, i, t); ++i) - { - *pp = build_tree_list (NULL, t); - pp = &TREE_CHAIN (*pp); - } - return ret; -} /* Parse Objective-C-specific constructs. */ @@ -6830,9 +6770,9 @@ c_parser_objc_keywordexpr (c_parser *parser) else { /* We have a comma expression, we will collapse later. */ - ret = c_parser_vec_to_tree_list (expr_list); + ret = build_tree_list_vec (expr_list); } - c_parser_release_expr_list (expr_list); + release_tree_vector (expr_list); return ret; } diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 626df30..57dcb54 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,99 @@ +2009-05-20 Ian Lance Taylor <iant@google.com> + + * parser.c (cp_parser_postfix_expression): Change args to a vec. + Release it when done. + (tree_vector): Define typedef. Define VEC functions. + (cp_parser_parenthesized_expression_list): Change return type to + vec. Change all callers. + (cp_parser_new_expression): Change placement and initializer to + vecs. Release them when done. + (cp_parser_new_placement): Change return type to vec. Change all + callers. + (cp_parser_new_initializer): Likewise. + * typeck.c (build_function_call_vec): Just call + cp_build_function_call_vec. + (cp_build_function_call): Just build a vec and call + cp_build_function_call_vec. + (cp_build_function_call_vec): New function based on old + cp_build_function_call. + (convert_arguments): Remove nargs and argarray parameters. Change + values to a vec. Change caller. + (build_x_compound_expr_from_vec): New function. + (cp_build_modify_expr): Build vec to pass to + build_special_member_call. + * call.c (struct z_candidate): Add first_arg field. Change args + field to vec. + (convert_class_to_reference): Handle first argument separately. + (add_candidate): Add first_arg parameter. Change args parameter + to vec. Change all callers. + (add_function_candidate, add_conv_candidate): Likewise. + (add_template_candidate_real, add_template_candidate): Likewise. + (add_template_conv_candidate): Likewise. + (build_user_type_conversion_1): Handle first argument separately. + (resolve_args): Change return type and parameter type to vecs. + Change all callers. + (perform_overload_resolution): Change args parameter to vec. + Change all callers. + (build_new_function_call, build_operator_new_call): Likewise. + (add_candidates): Likewise. + (build_op_call): New globally visible function, built from and + replacing static function build_object_call. + (build_new_op): Don't handle CALL_EXPR. Build vec, not tree_list, + of arguments. + (build_op_delete_call): Build vec to pass to + cp_build_function_call_vec. + (build_temp): Build vec to pass to build_special_member_call. + (convert_like_real): Likewise. + (perform_direct_initialization_if_possible): Likewise. + (build_over_call): Handle first_arg field. Use build_call_array + rather than build_call_list. + (build_special_member_call): Change args parameter to vec. Change + all callers. + (build_new_method_call): Likewise. + * init.c (expand_default_init): Change parms to vec. + (build_raw_new_expr): Change placement and init to vecs. Change + all callers. + (build_new_1, build_new): Likewise. + * class.c (resolve_address_of_overloaded_function): Build array to + pass to fn_type_unification. + * pt.c (tsubst_copy_and_build): For NEW_EXPR build vecs to pass to + build_new. For CALL_EXPR create a vec rather than a tree_list; + expand a pack if necessary. + (fn_type_unification): Change args parameter to const tree *. Add + nargs parameter. Change all callers. + (type_unification_real): Likewise. + (unify): Build array to pass to type_unification_real. + (get_bindings): Build array to pass to fn_type_unification. + (any_type_dependent_arguments_p): Change args parameter to a vec. + Change all callers. + (make_args_non_dependent): Renamed from build_non_dependent_args. + Change return type to void. Change parameter type to vec. Change + all callers. + (do_auto_deduction): Pass an array to type_unification_real. + * semantics.c (perform_koenig_lookup): Change args to vec. Change + all callers. + (finish_call_expr): Change args to vec. Change all callers. Call + build_op_call instead of passing CALL_EXPR to build_new_op. + (cxx_omp_create_clause_info): Allocate vec to pass to + build_special_member_call. + * decl2.c (build_offset_ref_call_from_tree): Change args parameter + to vec. Change all callers. + * name-lookup.c (lookup_function_nonclass): Likewise. + (struct arg_lookup): Change args to vec. + (arg_assoc_namespace): Handle args as a vec. + (arg_assoc_args_vec): New static function. + (lookup_arg_dependent): Change args parameter to vec. Change all + callers. + * method.c (do_build_assign_ref): Allocate vec to pass to + build_special_member_call. + * except.c (build_throw): Likewise. + * typeck2.c (build_functional_cast): Likewise. + * cvt.c (ocp_convert): Likewise. + * tree.c (build_min_non_dep_call_vec): Change last parameter to + vec. Change all callers. + * cp-tree.h: Update declarations. + * name-lookup.h: Update declarations. + 2009-05-20 Sandra Loosemore <sandra@codesourcery.com> * typeck.c (default_conversion): Check targetm.promoted_type. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index b33e903..0d5ae6a 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -145,8 +145,7 @@ static tree convert_like_real (conversion *, tree, tree, int, int, bool, bool, tsubst_flags_t); static void op_error (enum tree_code, enum tree_code, tree, tree, tree, const char *); -static tree build_object_call (tree, tree, tsubst_flags_t); -static tree resolve_args (tree); +static VEC(tree,gc) *resolve_args (VEC(tree,gc) *); static struct z_candidate *build_user_type_conversion_1 (tree, tree, int); static void print_z_candidate (const char *, struct z_candidate *); static void print_z_candidates (struct z_candidate *); @@ -154,13 +153,14 @@ static tree build_this (tree); static struct z_candidate *splice_viable (struct z_candidate *, bool, bool *); static bool any_strictly_viable (struct z_candidate *); static struct z_candidate *add_template_candidate - (struct z_candidate **, tree, tree, tree, tree, tree, - tree, tree, int, unification_kind_t); + (struct z_candidate **, tree, tree, tree, tree, const VEC(tree,gc) *, + tree, tree, tree, int, unification_kind_t); static struct z_candidate *add_template_candidate_real - (struct z_candidate **, tree, tree, tree, tree, tree, - tree, tree, int, tree, unification_kind_t); + (struct z_candidate **, tree, tree, tree, tree, const VEC(tree,gc) *, + tree, tree, tree, int, tree, unification_kind_t); static struct z_candidate *add_template_conv_candidate - (struct z_candidate **, tree, tree, tree, tree, tree, tree); + (struct z_candidate **, tree, tree, tree, const VEC(tree,gc) *, tree, + tree, tree); static void add_builtin_candidates (struct z_candidate **, enum tree_code, enum tree_code, tree, tree *, int); @@ -172,9 +172,11 @@ static void build_builtin_candidate (struct z_candidate **, tree, tree, tree, tree *, tree *, int); static struct z_candidate *add_conv_candidate - (struct z_candidate **, tree, tree, tree, tree, tree); + (struct z_candidate **, tree, tree, tree, const VEC(tree,gc) *, tree, + tree); static struct z_candidate *add_function_candidate - (struct z_candidate **, tree, tree, tree, tree, tree, int); + (struct z_candidate **, tree, tree, tree, const VEC(tree,gc) *, tree, + tree, int); static conversion *implicit_conversion (tree, tree, tree, bool, int); static conversion *standard_conversion (tree, tree, tree, bool, int); static conversion *reference_binding (tree, tree, tree, bool, int); @@ -184,7 +186,7 @@ static bool is_subseq (conversion *, conversion *); static conversion *maybe_handle_ref_bind (conversion **); static void maybe_handle_implicit_object (conversion **); static struct z_candidate *add_candidate - (struct z_candidate **, tree, tree, size_t, + (struct z_candidate **, tree, tree, const VEC(tree,gc) *, size_t, conversion **, tree, tree, int); static tree source_type (conversion *); static void add_warning (struct z_candidate *, struct z_candidate *); @@ -197,7 +199,7 @@ static conversion *conditional_conversion (tree, tree); static char *name_as_c_string (tree, tree, bool *); static tree call_builtin_trap (void); static tree prep_operand (tree); -static void add_candidates (tree, tree, tree, bool, tree, tree, +static void add_candidates (tree, const VEC(tree,gc) *, tree, bool, tree, tree, int, struct z_candidate **); static conversion *merge_conversion_sequences (conversion *, conversion *); static bool magic_varargs_p (tree); @@ -413,8 +415,13 @@ struct z_candidate { /* The FUNCTION_DECL that will be called if this candidate is selected by overload resolution. */ tree fn; - /* The arguments to use when calling this function. */ - tree args; + /* If not NULL_TREE, the first argument to use when calling this + function. */ + tree first_arg; + /* The rest of the arguments to use when calling this function. If + there are no further arguments this may be NULL or it may be an + empty vector. */ + const VEC(tree,gc) *args; /* The implicit conversion sequences for each of the arguments to FN. */ conversion **convs; @@ -996,7 +1003,7 @@ static conversion * convert_class_to_reference (tree reference_type, tree s, tree expr, int flags) { tree conversions; - tree arglist; + tree first_arg; conversion *conv; tree t; struct z_candidate *candidates; @@ -1029,8 +1036,7 @@ convert_class_to_reference (tree reference_type, tree s, tree expr, int flags) error messages, which we should not issue now because we are just trying to find a conversion operator. Therefore, we use NULL, cast to the appropriate type. */ - arglist = build_int_cst (build_pointer_type (s), 0); - arglist = build_tree_list (NULL_TREE, arglist); + first_arg = build_int_cst (build_pointer_type (s), 0); t = TREE_TYPE (reference_type); @@ -1056,7 +1062,8 @@ convert_class_to_reference (tree reference_type, tree s, tree expr, int flags) cand = add_template_candidate (&candidates, f, s, NULL_TREE, - arglist, + first_arg, + NULL, reference_type, TYPE_BINFO (s), TREE_PURPOSE (conversions), @@ -1081,8 +1088,8 @@ convert_class_to_reference (tree reference_type, tree s, tree expr, int flags) } else if (TREE_CODE (t2) == REFERENCE_TYPE && reference_compatible_p (t, TREE_TYPE (t2))) - cand = add_function_candidate (&candidates, f, s, arglist, - TYPE_BINFO (s), + cand = add_function_candidate (&candidates, f, s, first_arg, + NULL, TYPE_BINFO (s), TREE_PURPOSE (conversions), LOOKUP_NORMAL); @@ -1119,9 +1126,9 @@ convert_class_to_reference (tree reference_type, tree s, tree expr, int flags) /* Now that we know that this is the function we're going to use fix the dummy first argument. */ - cand->args = tree_cons (NULL_TREE, - build_this (expr), - TREE_CHAIN (cand->args)); + gcc_assert (cand->first_arg == NULL_TREE + || integer_zerop (cand->first_arg)); + cand->first_arg = build_this (expr); /* Build a user-defined conversion sequence representing the conversion. */ @@ -1424,11 +1431,12 @@ implicit_conversion (tree to, tree from, tree expr, bool c_cast_p, } /* Add a new entry to the list of candidates. Used by the add_*_candidate - functions. */ + functions. ARGS will not be changed until a single candidate is + selected. */ static struct z_candidate * add_candidate (struct z_candidate **candidates, - tree fn, tree args, + tree fn, tree first_arg, const VEC(tree,gc) *args, size_t num_convs, conversion **convs, tree access_path, tree conversion_path, int viable) @@ -1437,6 +1445,7 @@ add_candidate (struct z_candidate **candidates, conversion_obstack_alloc (sizeof (struct z_candidate)); cand->fn = fn; + cand->first_arg = first_arg; cand->args = args; cand->convs = convs; cand->num_convs = num_convs; @@ -1449,24 +1458,27 @@ add_candidate (struct z_candidate **candidates, return cand; } -/* Create an overload candidate for the function or method FN called with - the argument list ARGLIST and add it to CANDIDATES. FLAGS is passed on - to implicit_conversion. +/* Create an overload candidate for the function or method FN called + with the argument list FIRST_ARG/ARGS and add it to CANDIDATES. + FLAGS is passed on to implicit_conversion. + + This does not change ARGS. CTYPE, if non-NULL, is the type we want to pretend this function comes from for purposes of overload resolution. */ static struct z_candidate * add_function_candidate (struct z_candidate **candidates, - tree fn, tree ctype, tree arglist, - tree access_path, tree conversion_path, - int flags) + tree fn, tree ctype, tree first_arg, + const VEC(tree,gc) *args, tree access_path, + tree conversion_path, int flags) { tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (fn)); int i, len; conversion **convs; - tree parmnode, argnode; - tree orig_arglist; + tree parmnode; + tree orig_first_arg = first_arg; + int skip; int viable = 1; /* At this point we should not see any functions which haven't been @@ -1479,13 +1491,17 @@ add_function_candidate (struct z_candidate **candidates, if (DECL_CONSTRUCTOR_P (fn)) { parmlist = skip_artificial_parms_for (fn, parmlist); - orig_arglist = arglist; - arglist = skip_artificial_parms_for (fn, arglist); + skip = num_artificial_parms_for (fn); + if (skip > 0 && first_arg != NULL_TREE) + { + --skip; + first_arg = NULL_TREE; + } } else - orig_arglist = arglist; + skip = 0; - len = list_length (arglist); + len = VEC_length (tree, args) - skip + (first_arg != NULL_TREE ? 1 : 0); convs = alloc_conversions (len); /* 13.3.2 - Viable functions [over.match.viable] @@ -1518,18 +1534,23 @@ add_function_candidate (struct z_candidate **candidates, to the corresponding parameter of F. */ parmnode = parmlist; - argnode = arglist; for (i = 0; i < len; ++i) { - tree arg = TREE_VALUE (argnode); - tree argtype = lvalue_type (arg); + tree arg, argtype; conversion *t; int is_this; if (parmnode == void_list_node) break; + if (i == 0 && first_arg != NULL_TREE) + arg = first_arg; + else + arg = VEC_index (tree, args, + i + skip - (first_arg != NULL_TREE ? 1 : 0)); + argtype = lvalue_type (arg); + is_this = (i == 0 && DECL_NONSTATIC_MEMBER_FUNCTION_P (fn) && ! DECL_CONSTRUCTOR_P (fn)); @@ -1591,18 +1612,18 @@ add_function_candidate (struct z_candidate **candidates, if (parmnode) parmnode = TREE_CHAIN (parmnode); - argnode = TREE_CHAIN (argnode); } out: - return add_candidate (candidates, fn, orig_arglist, len, convs, + return add_candidate (candidates, fn, orig_first_arg, args, len, convs, access_path, conversion_path, viable); } /* Create an overload candidate for the conversion function FN which will be invoked for expression OBJ, producing a pointer-to-function which - will in turn be called with the argument list ARGLIST, and add it to - CANDIDATES. FLAGS is passed on to implicit_conversion. + will in turn be called with the argument list FIRST_ARG/ARGLIST, + and add it to CANDIDATES. This does not change ARGLIST. FLAGS is + passed on to implicit_conversion. Actually, we don't really care about FN; we care about the type it converts to. There may be multiple conversion functions that will @@ -1612,21 +1633,21 @@ add_function_candidate (struct z_candidate **candidates, static struct z_candidate * add_conv_candidate (struct z_candidate **candidates, tree fn, tree obj, - tree arglist, tree access_path, tree conversion_path) + tree first_arg, const VEC(tree,gc) *arglist, + tree access_path, tree conversion_path) { tree totype = TREE_TYPE (TREE_TYPE (fn)); int i, len, viable, flags; - tree parmlist, parmnode, argnode; + tree parmlist, parmnode; conversion **convs; for (parmlist = totype; TREE_CODE (parmlist) != FUNCTION_TYPE; ) parmlist = TREE_TYPE (parmlist); parmlist = TYPE_ARG_TYPES (parmlist); - len = list_length (arglist) + 1; + len = VEC_length (tree, arglist) + (first_arg != NULL_TREE ? 1 : 0) + 1; convs = alloc_conversions (len); parmnode = parmlist; - argnode = arglist; viable = 1; flags = LOOKUP_IMPLICIT; @@ -1636,11 +1657,19 @@ add_conv_candidate (struct z_candidate **candidates, tree fn, tree obj, for (i = 0; i < len; ++i) { - tree arg = i == 0 ? obj : TREE_VALUE (argnode); - tree argtype = lvalue_type (arg); + tree arg, argtype; conversion *t; if (i == 0) + arg = obj; + else if (i == 1 && first_arg != NULL_TREE) + arg = first_arg; + else + arg = VEC_index (tree, arglist, + i - (first_arg != NULL_TREE ? 1 : 0) - 1); + argtype = lvalue_type (arg); + + if (i == 0) t = implicit_conversion (totype, argtype, arg, /*c_cast_p=*/false, flags); else if (parmnode == void_list_node) @@ -1666,7 +1695,6 @@ add_conv_candidate (struct z_candidate **candidates, tree fn, tree obj, if (parmnode) parmnode = TREE_CHAIN (parmnode); - argnode = TREE_CHAIN (argnode); } if (i < len) @@ -1675,7 +1703,7 @@ add_conv_candidate (struct z_candidate **candidates, tree fn, tree obj, if (!sufficient_parms_p (parmnode)) viable = 0; - return add_candidate (candidates, totype, arglist, len, convs, + return add_candidate (candidates, totype, first_arg, arglist, len, convs, access_path, conversion_path, viable); } @@ -1728,7 +1756,7 @@ build_builtin_candidate (struct z_candidate **candidates, tree fnname, viable = 0; } - add_candidate (candidates, fnname, /*args=*/NULL_TREE, + add_candidate (candidates, fnname, /*first_arg=*/NULL_TREE, /*args=*/NULL, num_convs, convs, /*access_path=*/NULL_TREE, /*conversion_path=*/NULL_TREE, @@ -2349,37 +2377,79 @@ add_builtin_candidates (struct z_candidate **candidates, enum tree_code code, TMPL is the template. EXPLICIT_TARGS are any explicit template arguments. ARGLIST is the arguments provided at the call-site. - The RETURN_TYPE is the desired type for conversion operators. If - OBJ is NULL_TREE, FLAGS and CTYPE are as for add_function_candidate. - If an OBJ is supplied, FLAGS and CTYPE are ignored, and OBJ is as for - add_conv_candidate. */ + This does not change ARGLIST. The RETURN_TYPE is the desired type + for conversion operators. If OBJ is NULL_TREE, FLAGS and CTYPE are + as for add_function_candidate. If an OBJ is supplied, FLAGS and + CTYPE are ignored, and OBJ is as for add_conv_candidate. */ static struct z_candidate* add_template_candidate_real (struct z_candidate **candidates, tree tmpl, - tree ctype, tree explicit_targs, tree arglist, - tree return_type, tree access_path, - tree conversion_path, int flags, tree obj, - unification_kind_t strict) + tree ctype, tree explicit_targs, tree first_arg, + const VEC(tree,gc) *arglist, tree return_type, + tree access_path, tree conversion_path, + int flags, tree obj, unification_kind_t strict) { int ntparms = DECL_NTPARMS (tmpl); tree targs = make_tree_vec (ntparms); - tree args_without_in_chrg = arglist; + unsigned int nargs; + int skip_without_in_chrg; + tree first_arg_without_in_chrg; + tree *args_without_in_chrg; + unsigned int nargs_without_in_chrg; + unsigned int ia, ix; + tree arg; struct z_candidate *cand; int i; tree fn; + nargs = (first_arg == NULL_TREE ? 0 : 1) + VEC_length (tree, arglist); + + skip_without_in_chrg = 0; + + first_arg_without_in_chrg = first_arg; + /* We don't do deduction on the in-charge parameter, the VTT parameter or 'this'. */ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (tmpl)) - args_without_in_chrg = TREE_CHAIN (args_without_in_chrg); + { + if (first_arg_without_in_chrg != NULL_TREE) + first_arg_without_in_chrg = NULL_TREE; + else + ++skip_without_in_chrg; + } if ((DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (tmpl) || DECL_BASE_CONSTRUCTOR_P (tmpl)) && CLASSTYPE_VBASECLASSES (DECL_CONTEXT (tmpl))) - args_without_in_chrg = TREE_CHAIN (args_without_in_chrg); + { + if (first_arg_without_in_chrg != NULL_TREE) + first_arg_without_in_chrg = NULL_TREE; + else + ++skip_without_in_chrg; + } + + nargs_without_in_chrg = ((first_arg_without_in_chrg != NULL_TREE ? 1 : 0) + + (VEC_length (tree, arglist) + - skip_without_in_chrg)); + args_without_in_chrg = XALLOCAVEC (tree, nargs_without_in_chrg); + ia = 0; + if (first_arg_without_in_chrg != NULL_TREE) + { + args_without_in_chrg[ia] = first_arg_without_in_chrg; + ++ia; + } + for (ix = skip_without_in_chrg; + VEC_iterate (tree, arglist, ix, arg); + ++ix) + { + args_without_in_chrg[ia] = arg; + ++ia; + } + gcc_assert (ia == nargs_without_in_chrg); i = fn_type_unification (tmpl, explicit_targs, targs, args_without_in_chrg, + nargs_without_in_chrg, return_type, strict, flags); if (i != 0) @@ -2411,7 +2481,7 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl, class type, and a logical interpretation is that the intent was to forbid the instantiation of member templates which would then have that form. */ - if (DECL_CONSTRUCTOR_P (fn) && list_length (arglist) == 2) + if (DECL_CONSTRUCTOR_P (fn) && nargs == 2) { tree arg_types = FUNCTION_FIRST_USER_PARMTYPE (fn); if (arg_types && same_type_p (TYPE_MAIN_VARIANT (TREE_VALUE (arg_types)), @@ -2421,11 +2491,11 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl, if (obj != NULL_TREE) /* Aha, this is a conversion function. */ - cand = add_conv_candidate (candidates, fn, obj, access_path, - conversion_path, arglist); + cand = add_conv_candidate (candidates, fn, obj, first_arg, arglist, + access_path, conversion_path); else cand = add_function_candidate (candidates, fn, ctype, - arglist, access_path, + first_arg, arglist, access_path, conversion_path, flags); if (DECL_TI_TEMPLATE (fn) != tmpl) /* This situation can occur if a member template of a template @@ -2455,26 +2525,29 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl, static struct z_candidate * add_template_candidate (struct z_candidate **candidates, tree tmpl, tree ctype, - tree explicit_targs, tree arglist, tree return_type, + tree explicit_targs, tree first_arg, + const VEC(tree,gc) *arglist, tree return_type, tree access_path, tree conversion_path, int flags, unification_kind_t strict) { return add_template_candidate_real (candidates, tmpl, ctype, - explicit_targs, arglist, return_type, - access_path, conversion_path, + explicit_targs, first_arg, arglist, + return_type, access_path, conversion_path, flags, NULL_TREE, strict); } static struct z_candidate * add_template_conv_candidate (struct z_candidate **candidates, tree tmpl, - tree obj, tree arglist, tree return_type, - tree access_path, tree conversion_path) + tree obj, tree first_arg, + const VEC(tree,gc) *arglist, + tree return_type, tree access_path, + tree conversion_path) { return add_template_candidate_real (candidates, tmpl, NULL_TREE, NULL_TREE, - arglist, return_type, access_path, + first_arg, arglist, return_type, access_path, conversion_path, 0, obj, DEDUCE_CONV); } @@ -2681,7 +2754,8 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags) tree ctors = NULL_TREE; tree conv_fns = NULL_TREE; conversion *conv = NULL; - tree args = NULL_TREE; + tree first_arg = NULL_TREE; + VEC(tree,gc) *args = NULL; bool any_viable_p; int convflags; @@ -2721,15 +2795,13 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags) if (ctors) { - tree t; - ctors = BASELINK_FUNCTIONS (ctors); - t = build_int_cst (build_pointer_type (totype), 0); + first_arg = build_int_cst (build_pointer_type (totype), 0); if (BRACE_ENCLOSED_INITIALIZER_P (expr) && !TYPE_HAS_LIST_CTOR (totype)) { - args = ctor_to_list (expr); + args = ctor_to_vec (expr); /* We still allow more conversions within an init-list. */ flags = ((flags & ~LOOKUP_NO_CONVERSION) /* But not for the copy ctor. */ @@ -2737,12 +2809,12 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags) |LOOKUP_NO_NARROWING); } else - args = build_tree_list (NULL_TREE, expr); + args = make_tree_vector_single (expr); + /* We should never try to call the abstract or base constructor from here. */ gcc_assert (!DECL_HAS_IN_CHARGE_PARM_P (OVL_CURRENT (ctors)) && !DECL_HAS_VTT_PARM_P (OVL_CURRENT (ctors))); - args = tree_cons (NULL_TREE, t, args); } for (; ctors; ctors = OVL_NEXT (ctors)) { @@ -2753,14 +2825,14 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags) if (TREE_CODE (ctor) == TEMPLATE_DECL) cand = add_template_candidate (&candidates, ctor, totype, - NULL_TREE, args, NULL_TREE, + NULL_TREE, first_arg, args, NULL_TREE, TYPE_BINFO (totype), TYPE_BINFO (totype), flags, DEDUCE_CALL); else cand = add_function_candidate (&candidates, ctor, totype, - args, TYPE_BINFO (totype), + first_arg, args, TYPE_BINFO (totype), TYPE_BINFO (totype), flags); @@ -2784,7 +2856,7 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags) } if (conv_fns) - args = build_tree_list (NULL_TREE, build_this (expr)); + first_arg = build_this (expr); for (; conv_fns; conv_fns = TREE_CHAIN (conv_fns)) { @@ -2816,14 +2888,14 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags) if (TREE_CODE (fn) == TEMPLATE_DECL) cand = add_template_candidate (&candidates, fn, fromtype, NULL_TREE, - args, totype, + first_arg, NULL, totype, TYPE_BINFO (fromtype), conversion_path, flags, DEDUCE_CONV); else cand = add_function_candidate (&candidates, fn, fromtype, - args, + first_arg, NULL, TYPE_BINFO (fromtype), conversion_path, flags); @@ -2926,23 +2998,23 @@ build_user_type_conversion (tree totype, tree expr, int flags) /* Do any initial processing on the arguments to a function call. */ -static tree -resolve_args (tree args) +static VEC(tree,gc) * +resolve_args (VEC(tree,gc) *args) { - tree t; - for (t = args; t; t = TREE_CHAIN (t)) - { - tree arg = TREE_VALUE (t); + unsigned int ix; + tree arg; + for (ix = 0; VEC_iterate (tree, args, ix, arg); ++ix) + { if (error_operand_p (arg)) - return error_mark_node; + return NULL; else if (VOID_TYPE_P (TREE_TYPE (arg))) { error ("invalid use of void expression"); - return error_mark_node; + return NULL; } else if (invalid_nonstatic_memfn_p (arg, tf_warning_or_error)) - return error_mark_node; + return NULL; } return args; } @@ -2961,7 +3033,7 @@ resolve_args (tree args) static struct z_candidate * perform_overload_resolution (tree fn, - tree args, + const VEC(tree,gc) *args, struct z_candidate **candidates, bool *any_viable_p) { @@ -2972,12 +3044,11 @@ perform_overload_resolution (tree fn, *candidates = NULL; *any_viable_p = true; - /* Check FN and ARGS. */ + /* Check FN. */ gcc_assert (TREE_CODE (fn) == FUNCTION_DECL || TREE_CODE (fn) == TEMPLATE_DECL || TREE_CODE (fn) == OVERLOAD || TREE_CODE (fn) == TEMPLATE_ID_EXPR); - gcc_assert (!args || TREE_CODE (args) == TREE_LIST); if (TREE_CODE (fn) == TEMPLATE_ID_EXPR) { @@ -3002,10 +3073,11 @@ perform_overload_resolution (tree fn, } /* Return an expression for a call to FN (a namespace-scope function, - or a static member function) with the ARGS. */ + or a static member function) with the ARGS. This may change + ARGS. */ tree -build_new_function_call (tree fn, tree args, bool koenig_p, +build_new_function_call (tree fn, VEC(tree,gc) **args, bool koenig_p, tsubst_flags_t complain) { struct z_candidate *candidates, *cand; @@ -3013,9 +3085,12 @@ build_new_function_call (tree fn, tree args, bool koenig_p, void *p; tree result; - args = resolve_args (args); - if (args == error_mark_node) - return error_mark_node; + if (args != NULL && *args != NULL) + { + *args = resolve_args (*args); + if (*args == NULL) + return error_mark_node; + } /* If this function was found without using argument dependent lookup, then we want to ignore any undeclared friend @@ -3029,7 +3104,8 @@ build_new_function_call (tree fn, tree args, bool koenig_p, { if (complain & tf_error) error ("no matching function for call to %<%D(%A)%>", - DECL_NAME (OVL_CURRENT (orig_fn)), args); + DECL_NAME (OVL_CURRENT (orig_fn)), + build_tree_list_vec (*args)); return error_mark_node; } } @@ -3037,22 +3113,22 @@ build_new_function_call (tree fn, tree args, bool koenig_p, /* Get the high-water mark for the CONVERSION_OBSTACK. */ p = conversion_obstack_alloc (0); - cand = perform_overload_resolution (fn, args, &candidates, &any_viable_p); + cand = perform_overload_resolution (fn, *args, &candidates, &any_viable_p); if (!cand) { if (complain & tf_error) { if (!any_viable_p && candidates && ! candidates->next) - return cp_build_function_call (candidates->fn, args, complain); + return cp_build_function_call_vec (candidates->fn, args, complain); if (TREE_CODE (fn) == TEMPLATE_ID_EXPR) fn = TREE_OPERAND (fn, 0); if (!any_viable_p) error ("no matching function for call to %<%D(%A)%>", - DECL_NAME (OVL_CURRENT (fn)), args); + DECL_NAME (OVL_CURRENT (fn)), build_tree_list_vec (*args)); else error ("call of overloaded %<%D(%A)%> is ambiguous", - DECL_NAME (OVL_CURRENT (fn)), args); + DECL_NAME (OVL_CURRENT (fn)), build_tree_list_vec (*args)); if (candidates) print_z_candidates (candidates); } @@ -3069,15 +3145,16 @@ build_new_function_call (tree fn, tree args, bool koenig_p, /* Build a call to a global operator new. FNNAME is the name of the operator (either "operator new" or "operator new[]") and ARGS are - the arguments provided. *SIZE points to the total number of bytes - required by the allocation, and is updated if that is changed here. - *COOKIE_SIZE is non-NULL if a cookie should be used. If this - function determines that no cookie should be used, after all, - *COOKIE_SIZE is set to NULL_TREE. If FN is non-NULL, it will be - set, upon return, to the allocation function called. */ + the arguments provided. This may change ARGS. *SIZE points to the + total number of bytes required by the allocation, and is updated if + that is changed here. *COOKIE_SIZE is non-NULL if a cookie should + be used. If this function determines that no cookie should be + used, after all, *COOKIE_SIZE is set to NULL_TREE. If FN is + non-NULL, it will be set, upon return, to the allocation function + called. */ tree -build_operator_new_call (tree fnname, tree args, +build_operator_new_call (tree fnname, VEC(tree,gc) **args, tree *size, tree *cookie_size, tree *fn) { @@ -3088,10 +3165,10 @@ build_operator_new_call (tree fnname, tree args, if (fn) *fn = NULL_TREE; - args = tree_cons (NULL_TREE, *size, args); - args = resolve_args (args); - if (args == error_mark_node) - return args; + VEC_safe_insert (tree, gc, *args, 0, *size); + *args = resolve_args (*args); + if (*args == NULL) + return error_mark_node; /* Based on: @@ -3102,10 +3179,10 @@ build_operator_new_call (tree fnname, tree args, up in the global scope. we disregard block-scope declarations of "operator new". */ - fns = lookup_function_nonclass (fnname, args, /*block_p=*/false); + fns = lookup_function_nonclass (fnname, *args, /*block_p=*/false); /* Figure out what function is being called. */ - cand = perform_overload_resolution (fns, args, &candidates, &any_viable_p); + cand = perform_overload_resolution (fns, *args, &candidates, &any_viable_p); /* If no suitable function could be found, issue an error message and give up. */ @@ -3113,10 +3190,10 @@ build_operator_new_call (tree fnname, tree args, { if (!any_viable_p) error ("no matching function for call to %<%D(%A)%>", - DECL_NAME (OVL_CURRENT (fns)), args); + DECL_NAME (OVL_CURRENT (fns)), build_tree_list_vec (*args)); else error ("call of overloaded %<%D(%A)%> is ambiguous", - DECL_NAME (OVL_CURRENT (fns)), args); + DECL_NAME (OVL_CURRENT (fns)), build_tree_list_vec (*args)); if (candidates) print_z_candidates (candidates); return error_mark_node; @@ -3130,12 +3207,11 @@ build_operator_new_call (tree fnname, tree args, bool use_cookie = true; if (!abi_version_at_least (2)) { - tree placement = TREE_CHAIN (args); /* In G++ 3.2, the check was implemented incorrectly; it looked at the placement expression, rather than the type of the function. */ - if (placement && !TREE_CHAIN (placement) - && same_type_p (TREE_TYPE (TREE_VALUE (placement)), + if (VEC_length (tree, *args) == 2 + && same_type_p (TREE_TYPE (VEC_index (tree, *args, 1)), ptr_type_node)) use_cookie = false; } @@ -3159,7 +3235,7 @@ build_operator_new_call (tree fnname, tree args, /* Update the total size. */ *size = size_binop (PLUS_EXPR, *size, *cookie_size); /* Update the argument list to reflect the adjusted size. */ - TREE_VALUE (args) = *size; + VEC_replace (tree, *args, 0, *size); } else *cookie_size = NULL_TREE; @@ -3173,16 +3249,23 @@ build_operator_new_call (tree fnname, tree args, return build_over_call (cand, LOOKUP_NORMAL, tf_warning_or_error); } -static tree -build_object_call (tree obj, tree args, tsubst_flags_t complain) +/* Build a new call to operator(). This may change ARGS. */ + +tree +build_op_call (tree obj, VEC(tree,gc) **args, tsubst_flags_t complain) { struct z_candidate *candidates = 0, *cand; - tree fns, convs, mem_args = NULL_TREE; + tree fns, convs, first_mem_arg = NULL_TREE; tree type = TREE_TYPE (obj); bool any_viable_p; tree result = NULL_TREE; void *p; + if (error_operand_p (obj)) + return error_mark_node; + + obj = prep_operand (obj); + if (TYPE_PTRMEMFUNC_P (type)) { if (complain & tf_error) @@ -3201,10 +3284,12 @@ build_object_call (tree obj, tree args, tsubst_flags_t complain) else fns = NULL_TREE; - args = resolve_args (args); - - if (args == error_mark_node) - return error_mark_node; + if (args != NULL && *args != NULL) + { + *args = resolve_args (*args); + if (*args == NULL) + return error_mark_node; + } /* Get the high-water mark for the CONVERSION_OBSTACK. */ p = conversion_obstack_alloc (0); @@ -3212,20 +3297,20 @@ build_object_call (tree obj, tree args, tsubst_flags_t complain) if (fns) { tree base = BINFO_TYPE (BASELINK_BINFO (fns)); - mem_args = tree_cons (NULL_TREE, build_this (obj), args); + first_mem_arg = build_this (obj); for (fns = BASELINK_FUNCTIONS (fns); fns; fns = OVL_NEXT (fns)) { tree fn = OVL_CURRENT (fns); if (TREE_CODE (fn) == TEMPLATE_DECL) add_template_candidate (&candidates, fn, base, NULL_TREE, - mem_args, NULL_TREE, + first_mem_arg, *args, NULL_TREE, TYPE_BINFO (type), TYPE_BINFO (type), LOOKUP_NORMAL, DEDUCE_CALL); else add_function_candidate - (&candidates, fn, base, mem_args, TYPE_BINFO (type), + (&candidates, fn, base, first_mem_arg, *args, TYPE_BINFO (type), TYPE_BINFO (type), LOOKUP_NORMAL); } } @@ -3253,12 +3338,12 @@ build_object_call (tree obj, tree args, tsubst_flags_t complain) if (TREE_CODE (fn) == TEMPLATE_DECL) add_template_conv_candidate - (&candidates, fn, obj, args, totype, + (&candidates, fn, obj, NULL_TREE, *args, totype, /*access_path=*/NULL_TREE, /*conversion_path=*/NULL_TREE); else - add_conv_candidate (&candidates, fn, obj, args, - /*conversion_path=*/NULL_TREE, + add_conv_candidate (&candidates, fn, obj, NULL_TREE, + *args, /*conversion_path=*/NULL_TREE, /*access_path=*/NULL_TREE); } } @@ -3268,7 +3353,8 @@ build_object_call (tree obj, tree args, tsubst_flags_t complain) { if (complain & tf_error) { - error ("no match for call to %<(%T) (%A)%>", TREE_TYPE (obj), args); + error ("no match for call to %<(%T) (%A)%>", TREE_TYPE (obj), + build_tree_list_vec (*args)); print_z_candidates (candidates); } result = error_mark_node; @@ -3281,7 +3367,7 @@ build_object_call (tree obj, tree args, tsubst_flags_t complain) if (complain & tf_error) { error ("call of %<(%T) (%A)%> is ambiguous", - TREE_TYPE (obj), args); + TREE_TYPE (obj), build_tree_list_vec (*args)); print_z_candidates (candidates); } result = error_mark_node; @@ -3297,7 +3383,7 @@ build_object_call (tree obj, tree args, tsubst_flags_t complain) obj = convert_like_with_context (cand->convs[0], obj, cand->fn, -1, complain); obj = convert_from_reference (obj); - result = cp_build_function_call (obj, args, complain); + result = cp_build_function_call_vec (obj, args, complain); } } @@ -3849,29 +3935,33 @@ prep_operand (tree operand) /* Add each of the viable functions in FNS (a FUNCTION_DECL or OVERLOAD) to the CANDIDATES, returning an updated list of CANDIDATES. The ARGS are the arguments provided to the call, - without any implicit object parameter. The EXPLICIT_TARGS are - explicit template arguments provided. TEMPLATE_ONLY is true if - only template functions should be considered. CONVERSION_PATH, - ACCESS_PATH, and FLAGS are as for add_function_candidate. */ + without any implicit object parameter. This may change ARGS. The + EXPLICIT_TARGS are explicit template arguments provided. + TEMPLATE_ONLY is true if only template functions should be + considered. CONVERSION_PATH, ACCESS_PATH, and FLAGS are as for + add_function_candidate. */ static void -add_candidates (tree fns, tree args, +add_candidates (tree fns, const VEC(tree,gc) *args, tree explicit_targs, bool template_only, tree conversion_path, tree access_path, int flags, struct z_candidate **candidates) { tree ctype; - tree non_static_args; + VEC(tree,gc) *non_static_args; + tree first_arg; ctype = conversion_path ? BINFO_TYPE (conversion_path) : NULL_TREE; /* Delay creating the implicit this parameter until it is needed. */ - non_static_args = NULL_TREE; + non_static_args = NULL; + first_arg = NULL_TREE; while (fns) { tree fn; - tree fn_args; + tree fn_first_arg; + const VEC(tree,gc) *fn_args; fn = OVL_CURRENT (fns); /* Figure out which set of arguments to use. */ @@ -3879,21 +3969,34 @@ add_candidates (tree fns, tree args, { /* If this function is a non-static member, prepend the implicit object parameter. */ - if (!non_static_args) - non_static_args = tree_cons (NULL_TREE, - build_this (TREE_VALUE (args)), - TREE_CHAIN (args)); + if (non_static_args == NULL) + { + unsigned int ix; + tree arg; + + non_static_args = VEC_alloc (tree, gc, + VEC_length (tree, args) - 1); + for (ix = 1; VEC_iterate (tree, args, ix, arg); ++ix) + VEC_quick_push (tree, non_static_args, arg); + } + if (first_arg == NULL_TREE) + first_arg = build_this (VEC_index (tree, args, 0)); + fn_first_arg = first_arg; fn_args = non_static_args; } else - /* Otherwise, just use the list of arguments provided. */ - fn_args = args; + { + /* Otherwise, just use the list of arguments provided. */ + fn_first_arg = NULL_TREE; + fn_args = args; + } if (TREE_CODE (fn) == TEMPLATE_DECL) add_template_candidate (candidates, fn, ctype, explicit_targs, + fn_first_arg, fn_args, NULL_TREE, access_path, @@ -3904,6 +4007,7 @@ add_candidates (tree fns, tree args, add_function_candidate (candidates, fn, ctype, + fn_first_arg, fn_args, access_path, conversion_path, @@ -3917,7 +4021,8 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3, bool *overloaded_p, tsubst_flags_t complain) { struct z_candidate *candidates = 0, *cand; - tree arglist, fnname; + VEC(tree,gc) *arglist; + tree fnname; tree args[3]; tree result = NULL_TREE; bool result_valid_p = false; @@ -3955,7 +4060,8 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3, gcc_unreachable (); case CALL_EXPR: - return build_object_call (arg1, arg2, complain); + /* Use build_op_call instead. */ + gcc_unreachable (); case TRUTH_ORIF_EXPR: case TRUTH_ANDIF_EXPR: @@ -3988,12 +4094,12 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3, if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR) arg2 = integer_zero_node; - arglist = NULL_TREE; - if (arg3) - arglist = tree_cons (NULL_TREE, arg3, arglist); - if (arg2) - arglist = tree_cons (NULL_TREE, arg2, arglist); - arglist = tree_cons (NULL_TREE, arg1, arglist); + arglist = VEC_alloc (tree, gc, 3); + VEC_quick_push (tree, arglist, arg1); + if (arg2 != NULL_TREE) + VEC_quick_push (tree, arglist, arg2); + if (arg3 != NULL_TREE) + VEC_quick_push (tree, arglist, arg3); /* Get the high-water mark for the CONVERSION_OBSTACK. */ p = conversion_obstack_alloc (0); @@ -4133,7 +4239,7 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3, if (overloaded_p) *overloaded_p = true; - if (resolve_args (arglist) == error_mark_node) + if (resolve_args (arglist) == NULL) result = error_mark_node; else result = build_over_call (cand, LOOKUP_NORMAL, complain); @@ -4434,13 +4540,14 @@ build_op_delete_call (enum tree_code code, tree addr, tree size, } else { - 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 cp_build_function_call (fn, args, tf_warning_or_error); + tree ret; + VEC(tree,gc) *args = VEC_alloc (tree, gc, 2); + VEC_quick_push (tree, args, addr); + if (pass != 0) + VEC_quick_push (tree, args, size); + ret = cp_build_function_call_vec (fn, &args, tf_warning_or_error); + VEC_free (tree, gc, args); + return ret; } } @@ -4498,12 +4605,13 @@ build_temp (tree expr, tree type, int flags, diagnostic_t *diagnostic_kind) { int savew, savee; + VEC(tree,gc) *args; savew = warningcount, savee = errorcount; - expr = build_special_member_call (NULL_TREE, - complete_ctor_identifier, - build_tree_list (NULL_TREE, expr), - type, flags, tf_warning_or_error); + args = make_tree_vector_single (expr); + expr = build_special_member_call (NULL_TREE, complete_ctor_identifier, + &args, type, flags, tf_warning_or_error); + release_tree_vector (args); if (warningcount > savew) *diagnostic_kind = DK_WARNING; else if (errorcount > savee) @@ -4665,7 +4773,8 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, tree elttype = TREE_VEC_ELT (CLASSTYPE_TI_ARGS (totype), 0); tree new_ctor = build_constructor (init_list_type_node, NULL); unsigned len = CONSTRUCTOR_NELTS (expr); - tree array, parms, val; + tree array, val; + VEC(tree,gc) *parms; unsigned ix; /* Convert all the elements. */ @@ -4684,12 +4793,14 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, array = build_array_of_n_type (elttype, len); array = finish_compound_literal (array, new_ctor); - parms = build_tree_list (NULL_TREE, size_int (len)); - parms = tree_cons (NULL_TREE, decay_conversion (array), parms); + parms = make_tree_vector (); + VEC_safe_push (tree, gc, parms, decay_conversion (array)); + VEC_safe_push (tree, gc, parms, size_int (len)); /* Call the private constructor. */ push_deferring_access_checks (dk_no_check); new_ctor = build_special_member_call - (NULL_TREE, complete_ctor_identifier, parms, totype, 0, complain); + (NULL_TREE, complete_ctor_identifier, &parms, totype, 0, complain); + release_tree_vector (parms); pop_deferring_access_checks (); return build_cplus_new (totype, new_ctor); } @@ -5146,14 +5257,16 @@ static tree build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) { tree fn = cand->fn; - tree args = cand->args; + const VEC(tree,gc) *args = cand->args; + tree first_arg = cand->first_arg; conversion **convs = cand->convs; conversion *conv; tree parm = TYPE_ARG_TYPES (TREE_TYPE (fn)); int parmlen; - tree arg, val; + tree val; int i = 0; int j = 0; + unsigned int arg_index = 0; int is_method = 0; int nargs; tree *argarray; @@ -5167,8 +5280,28 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) { tree expr; tree return_type; + const tree *argarray; + unsigned int nargs; + return_type = TREE_TYPE (TREE_TYPE (fn)); - expr = build_call_list (return_type, build_addr_func (fn), args); + nargs = VEC_length (tree, args); + if (first_arg == NULL_TREE) + argarray = VEC_address (tree, CONST_CAST (VEC(tree,gc) *, args)); + else + { + tree *alcarray; + unsigned int ix; + tree arg; + + ++nargs; + alcarray = XALLOCAVEC (tree, nargs); + alcarray[0] = first_arg; + for (ix = 0; VEC_iterate (tree, args, ix, arg); ++ix) + alcarray[ix + 1] = arg; + argarray = alcarray; + } + expr = build_call_array (return_type, build_addr_func (fn), nargs, + argarray); if (TREE_THIS_VOLATILE (fn) && cfun) current_function_returns_abnormally = 1; if (!VOID_TYPE_P (return_type)) @@ -5223,13 +5356,9 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) perform_or_defer_access_check (cand->access_path, fn, fn); } - if (args && TREE_CODE (args) != TREE_LIST) - 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); + nargs = VEC_length (tree, args) + (first_arg != NULL_TREE ? 1 : 0); if (parmlen > nargs) nargs = parmlen; argarray = (tree *) alloca (nargs * sizeof (tree)); @@ -5238,16 +5367,24 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) resolution, and must be of the proper type. */ if (DECL_CONSTRUCTOR_P (fn)) { - argarray[j++] = TREE_VALUE (arg); - arg = TREE_CHAIN (arg); + if (first_arg != NULL_TREE) + { + argarray[j++] = first_arg; + first_arg = NULL_TREE; + } + else + { + argarray[j++] = VEC_index (tree, args, arg_index); + ++arg_index; + } parm = TREE_CHAIN (parm); /* We should never try to call the abstract constructor. */ gcc_assert (!DECL_HAS_IN_CHARGE_PARM_P (fn)); if (DECL_HAS_VTT_PARM_P (fn)) { - argarray[j++] = TREE_VALUE (arg); - arg = TREE_CHAIN (arg); + argarray[j++] = VEC_index (tree, args, arg_index); + ++arg_index; parm = TREE_CHAIN (parm); } } @@ -5255,7 +5392,10 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) else if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE) { tree parmtype = TREE_VALUE (parm); - tree argtype = TREE_TYPE (TREE_VALUE (arg)); + tree arg = (first_arg != NULL_TREE + ? first_arg + : VEC_index (tree, args, arg_index)); + tree argtype = TREE_TYPE (arg); tree converted_arg; tree base_binfo; @@ -5278,7 +5418,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) /* Convert to the base in which the function was declared. */ gcc_assert (cand->conversion_path != NULL_TREE); converted_arg = build_base_path (PLUS_EXPR, - TREE_VALUE (arg), + arg, cand->conversion_path, 1); /* Check that the base class is accessible. */ @@ -5297,13 +5437,17 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) argarray[j++] = converted_arg; parm = TREE_CHAIN (parm); - arg = TREE_CHAIN (arg); + if (first_arg != NULL_TREE) + first_arg = NULL_TREE; + else + ++arg_index; ++i; is_method = 1; } - for (; arg && parm; - parm = TREE_CHAIN (parm), arg = TREE_CHAIN (arg), ++i) + gcc_assert (first_arg == NULL_TREE); + for (; arg_index < VEC_length (tree, args) && parm; + parm = TREE_CHAIN (parm), ++arg_index, ++i) { tree type = TREE_VALUE (parm); @@ -5316,7 +5460,8 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) conv = conv->u.next; val = convert_like_with_context - (conv, TREE_VALUE (arg), fn, i - is_method, complain); + (conv, VEC_index (tree, args, arg_index), fn, i - is_method, + complain); val = convert_for_arg_passing (type, val); if (val == error_mark_node) @@ -5331,9 +5476,9 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) TREE_PURPOSE (parm), fn, i - is_method); /* Ellipsis */ - for (; arg; arg = TREE_CHAIN (arg)) + for (; arg_index < VEC_length (tree, args); ++arg_index) { - tree a = TREE_VALUE (arg); + tree a = VEC_index (tree, args, arg_index); if (magic_varargs_p (fn)) /* Do no conversions for magic varargs. */; else @@ -5357,7 +5502,8 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) || DECL_MOVE_CONSTRUCTOR_P (fn))) { tree targ; - arg = argarray[num_artificial_parms_for (fn)]; + tree arg = argarray[num_artificial_parms_for (fn)]; + tree fa; /* Pull out the real argument, disregarding const-correctness. */ targ = arg; @@ -5398,7 +5544,10 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) INIT_EXPR to collapse the temp into our target. Otherwise, if the ctor is trivial, do a bitwise copy with a simple TARGET_EXPR for a temp or an INIT_EXPR otherwise. */ - if (integer_zerop (TREE_VALUE (args))) + fa = (cand->first_arg != NULL_TREE + ? cand->first_arg + : VEC_index (tree, args, 0)); + if (integer_zerop (fa)) { if (TREE_CODE (arg) == TARGET_EXPR) return arg; @@ -5409,8 +5558,8 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) || (TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)) && !move_fn_p (fn))) { - tree to = stabilize_reference - (cp_build_indirect_ref (TREE_VALUE (args), 0, complain)); + tree to = stabilize_reference (cp_build_indirect_ref (fa, 0, + complain)); val = build2 (INIT_EXPR, DECL_CONTEXT (fn), to, arg); return val; @@ -5424,8 +5573,8 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) (cp_build_indirect_ref (argarray[0], 0, complain)); tree type = TREE_TYPE (to); tree as_base = CLASSTYPE_AS_BASE (type); + tree arg = argarray[1]; - arg = argarray[1]; if (tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (as_base))) { arg = cp_build_indirect_ref (arg, 0, complain); @@ -5631,9 +5780,10 @@ in_charge_arg_for_name (tree name) /* Build a call to a constructor, destructor, or an assignment operator for INSTANCE, an expression with class type. NAME - indicates the special member function to call; ARGS are the - arguments. BINFO indicates the base of INSTANCE that is to be - passed as the `this' parameter to the member function called. + indicates the special member function to call; *ARGS are the + arguments. ARGS may be NULL. This may change ARGS. BINFO + indicates the base of INSTANCE that is to be passed as the `this' + parameter to the member function called. FLAGS are the LOOKUP_* flags to use when processing the call. @@ -5642,12 +5792,14 @@ in_charge_arg_for_name (tree name) store the newly constructed object into a VAR_DECL. */ tree -build_special_member_call (tree instance, tree name, tree args, +build_special_member_call (tree instance, tree name, VEC(tree,gc) **args, tree binfo, int flags, tsubst_flags_t complain) { tree fns; /* The type of the subobject to be constructed or destroyed. */ tree class_type; + VEC(tree,gc) *allocated = NULL; + tree ret; gcc_assert (name == complete_ctor_identifier || name == base_ctor_identifier @@ -5679,7 +5831,7 @@ build_special_member_call (tree instance, tree name, tree args, if (name == complete_dtor_identifier || name == base_dtor_identifier || name == deleting_dtor_identifier) - gcc_assert (args == NULL_TREE); + gcc_assert (args == NULL || VEC_empty (tree, *args)); /* Convert to the base class, if necessary. */ if (!same_type_ignoring_top_level_qualifiers_p @@ -5728,13 +5880,24 @@ build_special_member_call (tree instance, tree name, tree args, sub_vtt = build2 (POINTER_PLUS_EXPR, TREE_TYPE (vtt), vtt, BINFO_SUBVTT_INDEX (binfo)); - args = tree_cons (NULL_TREE, sub_vtt, args); + if (args == NULL) + { + allocated = make_tree_vector (); + args = &allocated; + } + + VEC_safe_insert (tree, gc, *args, 0, sub_vtt); } - return build_new_method_call (instance, fns, args, - TYPE_BINFO (BINFO_TYPE (binfo)), - flags, /*fn=*/NULL, - complain); + ret = build_new_method_call (instance, fns, args, + TYPE_BINFO (BINFO_TYPE (binfo)), + flags, /*fn=*/NULL, + complain); + + if (allocated != NULL) + release_tree_vector (allocated); + + return ret; } /* Return the NAME, as a C string. The NAME indicates a function that @@ -5783,10 +5946,11 @@ name_as_c_string (tree name, tree type, bool *free_p) } /* Build a call to "INSTANCE.FN (ARGS)". If FN_P is non-NULL, it will - be set, upon return, to the function called. */ + be set, upon return, to the function called. ARGS may be NULL. + This may change ARGS. */ tree -build_new_method_call (tree instance, tree fns, tree args, +build_new_method_call (tree instance, tree fns, VEC(tree,gc) **args, tree conversion_path, int flags, tree *fn_p, tsubst_flags_t complain) { @@ -5795,9 +5959,11 @@ build_new_method_call (tree instance, tree fns, tree args, tree basetype = NULL_TREE; tree access_binfo; tree optype; - tree mem_args = NULL_TREE, instance_ptr; + tree first_mem_arg = NULL_TREE; + tree instance_ptr; tree name; - tree user_args; + bool skip_first_for_error; + VEC(tree,gc) *user_args; tree call; tree fn; tree class_type; @@ -5805,7 +5971,7 @@ build_new_method_call (tree instance, tree fns, tree args, bool any_viable_p; tree orig_instance; tree orig_fns; - tree orig_args; + VEC(tree,gc) *orig_args = NULL; void *p; gcc_assert (instance != NULL_TREE); @@ -5815,8 +5981,7 @@ build_new_method_call (tree instance, tree fns, tree args, *fn_p = NULL_TREE; if (error_operand_p (instance) - || error_operand_p (fns) - || args == error_mark_node) + || error_operand_p (fns)) return error_mark_node; if (!BASELINK_P (fns)) @@ -5828,7 +5993,6 @@ build_new_method_call (tree instance, tree fns, tree args, orig_instance = instance; orig_fns = fns; - orig_args = args; /* Dismantle the baselink to collect all the information we need. */ if (!conversion_path) @@ -5853,16 +6017,20 @@ build_new_method_call (tree instance, tree fns, tree args, if (processing_template_decl) { + orig_args = args == NULL ? NULL : make_tree_vector_copy (*args); instance = build_non_dependent_expr (instance); - args = build_non_dependent_args (orig_args); - } - - /* The USER_ARGS are the arguments we will display to users if an - error occurs. The USER_ARGS should not include any - compiler-generated arguments. The "this" pointer hasn't been - added yet. However, we must remove the VTT pointer if this is a - call to a base-class constructor or destructor. */ - user_args = args; + if (args != NULL) + make_args_non_dependent (*args); + } + + /* Figure out whether to skip the first argument for the error + message we will display to users if an error occurs. We don't + want to display any compiler-generated arguments. The "this" + pointer hasn't been added yet. However, we must remove the VTT + pointer if this is a call to a base-class constructor or + destructor. */ + skip_first_for_error = false; + user_args = args == NULL ? NULL : *args; if (IDENTIFIER_CTOR_OR_DTOR_P (name)) { /* Callers should explicitly indicate whether they want to construct @@ -5873,13 +6041,16 @@ build_new_method_call (tree instance, tree fns, tree args, /* Remove the VTT pointer, if present. */ if ((name == base_ctor_identifier || name == base_dtor_identifier) && CLASSTYPE_VBASECLASSES (basetype)) - user_args = TREE_CHAIN (user_args); + skip_first_for_error = true; } /* Process the argument list. */ - args = resolve_args (args); - if (args == error_mark_node) - return error_mark_node; + if (args != NULL && *args != NULL) + { + *args = resolve_args (*args); + if (*args == NULL) + return error_mark_node; + } instance_ptr = build_this (instance); @@ -5899,17 +6070,17 @@ build_new_method_call (tree instance, tree fns, tree args, /* If CONSTRUCTOR_IS_DIRECT_INIT is set, this was a T{ } form initializer, not T({ }). If the type doesn't have a list ctor, break apart the list into separate ctor args. */ - if (DECL_CONSTRUCTOR_P (fn) && args - && BRACE_ENCLOSED_INITIALIZER_P (TREE_VALUE (args)) - && CONSTRUCTOR_IS_DIRECT_INIT (TREE_VALUE (args)) + if (DECL_CONSTRUCTOR_P (fn) && args != NULL && !VEC_empty (tree, *args) + && BRACE_ENCLOSED_INITIALIZER_P (VEC_index (tree, *args, 0)) + && CONSTRUCTOR_IS_DIRECT_INIT (VEC_index (tree, *args, 0)) && !TYPE_HAS_LIST_CTOR (basetype)) { - gcc_assert (TREE_CHAIN (args) == NULL_TREE); - args = ctor_to_list (TREE_VALUE (args)); + gcc_assert (VEC_length (tree, *args) == 1); + *args = ctor_to_vec (VEC_index (tree, *args, 0)); } class_type = (conversion_path ? BINFO_TYPE (conversion_path) : NULL_TREE); - mem_args = tree_cons (NULL_TREE, instance_ptr, args); + first_mem_arg = instance_ptr; /* Get the high-water mark for the CONVERSION_OBSTACK. */ p = conversion_obstack_alloc (0); @@ -5917,7 +6088,7 @@ build_new_method_call (tree instance, tree fns, tree args, for (fn = fns; fn; fn = OVL_NEXT (fn)) { tree t = OVL_CURRENT (fn); - tree this_arglist; + tree this_first_arg; /* We can end up here for copy-init of same or base class. */ if ((flags & LOOKUP_ONLYCONVERTING) @@ -5925,16 +6096,18 @@ build_new_method_call (tree instance, tree fns, tree args, continue; if (DECL_NONSTATIC_MEMBER_FUNCTION_P (t)) - this_arglist = mem_args; + this_first_arg = first_mem_arg; else - this_arglist = args; + this_first_arg = NULL_TREE; if (TREE_CODE (t) == TEMPLATE_DECL) /* A member template. */ add_template_candidate (&candidates, t, class_type, explicit_targs, - this_arglist, optype, + this_first_arg, + args == NULL ? NULL : *args, + optype, access_binfo, conversion_path, flags, @@ -5942,7 +6115,8 @@ build_new_method_call (tree instance, tree fns, tree args, else if (! template_only) add_function_candidate (&candidates, t, class_type, - this_arglist, + this_first_arg, + args == NULL ? NULL : *args, access_binfo, conversion_path, flags); @@ -5959,10 +6133,14 @@ build_new_method_call (tree instance, tree fns, tree args, { char *pretty_name; bool free_p; + tree arglist; pretty_name = name_as_c_string (name, basetype, &free_p); + arglist = build_tree_list_vec (user_args); + if (skip_first_for_error) + arglist = TREE_CHAIN (arglist); error ("no matching function for call to %<%T::%s(%A)%#V%>", - basetype, pretty_name, user_args, + basetype, pretty_name, arglist, TREE_TYPE (TREE_TYPE (instance_ptr))); if (free_p) free (pretty_name); @@ -5978,12 +6156,16 @@ build_new_method_call (tree instance, tree fns, tree args, { char *pretty_name; bool free_p; + tree arglist; if (complain & tf_error) { pretty_name = name_as_c_string (name, basetype, &free_p); + arglist = build_tree_list_vec (user_args); + if (skip_first_for_error) + arglist = TREE_CHAIN (arglist); error ("call of overloaded %<%s(%A)%> is ambiguous", pretty_name, - user_args); + arglist); print_z_candidates (candidates); if (free_p) free (pretty_name); @@ -6064,7 +6246,7 @@ build_new_method_call (tree instance, tree fns, tree args, } if (TREE_CODE (call) == INDIRECT_REF) call = TREE_OPERAND (call, 0); - call = (build_min_non_dep_call_list + call = (build_min_non_dep_call_vec (call, build_min (COMPONENT_REF, TREE_TYPE (CALL_EXPR_FN (call)), orig_instance, orig_fns, NULL_TREE), @@ -6077,6 +6259,9 @@ build_new_method_call (tree instance, tree fns, tree args, /* Free all the conversions we allocated. */ obstack_free (&conversion_obstack, p); + if (orig_args != NULL) + release_tree_vector (orig_args); + return call; } @@ -7132,9 +7317,10 @@ perform_direct_initialization_if_possible (tree type, ill-formed. */ if (CLASS_TYPE_P (type)) { + VEC(tree,gc) *args = make_tree_vector_single (expr); expr = build_special_member_call (NULL_TREE, complete_ctor_identifier, - build_tree_list (NULL_TREE, expr), - type, LOOKUP_NORMAL, complain); + &args, type, LOOKUP_NORMAL, complain); + release_tree_vector (args); return build_cplus_new (type, expr); } diff --git a/gcc/cp/class.c b/gcc/cp/class.c index ad50a4e..049e980 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -6072,6 +6072,9 @@ resolve_address_of_overloaded_function (tree target_type, tree target_arg_types; tree target_ret_type; tree fns; + tree *args; + unsigned int nargs, ia; + tree arg; if (is_ptrmem) target_fn_type @@ -6085,6 +6088,14 @@ resolve_address_of_overloaded_function (tree target_type, if (TREE_CODE (target_fn_type) == METHOD_TYPE) target_arg_types = TREE_CHAIN (target_arg_types); + nargs = list_length (target_arg_types); + args = XALLOCAVEC (tree, nargs); + for (arg = target_arg_types, ia = 0; + arg != NULL_TREE && arg != void_list_node; + arg = TREE_CHAIN (arg), ++ia) + args[ia] = TREE_VALUE (arg); + nargs = ia; + for (fns = overload; fns; fns = OVL_NEXT (fns)) { tree fn = OVL_CURRENT (fns); @@ -6104,9 +6115,9 @@ resolve_address_of_overloaded_function (tree target_type, /* Try to do argument deduction. */ targs = make_tree_vec (DECL_NTPARMS (fn)); - if (fn_type_unification (fn, explicit_targs, targs, - target_arg_types, target_ret_type, - DEDUCE_EXACT, LOOKUP_NORMAL)) + if (fn_type_unification (fn, explicit_targs, targs, args, nargs, + target_ret_type, DEDUCE_EXACT, + LOOKUP_NORMAL)) /* Argument deduction failed. */ continue; diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 3dfd482..5a32a90b 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4176,17 +4176,20 @@ extern bool null_ptr_cst_p (tree); extern bool sufficient_parms_p (const_tree); extern tree type_decays_to (tree); extern tree build_user_type_conversion (tree, tree, int); -extern tree build_new_function_call (tree, tree, bool, +extern tree build_new_function_call (tree, VEC(tree,gc) **, bool, tsubst_flags_t); -extern tree build_operator_new_call (tree, tree, tree *, tree *, - tree *); -extern tree build_new_method_call (tree, tree, tree, tree, int, - tree *, tsubst_flags_t); -extern tree build_special_member_call (tree, tree, tree, tree, int, - tsubst_flags_t); +extern tree build_operator_new_call (tree, VEC(tree,gc) **, tree *, + tree *, tree *); +extern tree build_new_method_call (tree, tree, VEC(tree,gc) **, + tree, int, tree *, + tsubst_flags_t); +extern tree build_special_member_call (tree, tree, VEC(tree,gc) **, + tree, int, tsubst_flags_t); extern tree build_new_op (enum tree_code, int, tree, tree, tree, bool *, tsubst_flags_t); +extern tree build_op_call (tree, VEC(tree,gc) **, + tsubst_flags_t); extern tree build_op_delete_call (enum tree_code, tree, tree, bool, tree, tree); extern bool can_convert (tree, tree); extern bool can_convert_arg (tree, tree, tree, int); @@ -4408,7 +4411,7 @@ extern void determine_visibility (tree); extern void constrain_class_visibility (tree); extern void import_export_decl (tree); extern tree build_cleanup (tree); -extern tree build_offset_ref_call_from_tree (tree, tree); +extern tree build_offset_ref_call_from_tree (tree, VEC(tree,gc) **); extern void check_default_args (tree); extern void mark_used (tree); extern void finish_static_data_member_decl (tree, tree, bool, tree, int); @@ -4472,7 +4475,8 @@ extern tree build_zero_init (tree, tree, bool); extern tree build_value_init (tree); extern tree build_value_init_noctor (tree); extern tree build_offset_ref (tree, tree, bool); -extern tree build_new (tree, tree, tree, tree, int, +extern tree build_new (VEC(tree,gc) **, tree, tree, + VEC(tree,gc) **, int, tsubst_flags_t); extern tree build_vec_init (tree, tree, tree, bool, int, tsubst_flags_t); @@ -4554,7 +4558,8 @@ extern int uses_template_parms (tree); extern int uses_template_parms_level (tree, int); extern tree instantiate_class_template (tree); extern tree instantiate_template (tree, tree, tsubst_flags_t); -extern int fn_type_unification (tree, tree, tree, tree, +extern int fn_type_unification (tree, tree, tree, + const tree *, unsigned int, tree, unification_kind_t, int); extern void mark_decl_instantiated (tree, int); extern int more_specialized_fn (tree, tree, int); @@ -4592,7 +4597,7 @@ extern bool any_dependent_template_arguments_p (const_tree); extern bool dependent_template_p (tree); extern bool dependent_template_id_p (tree, tree); extern bool type_dependent_expression_p (tree); -extern bool any_type_dependent_arguments_p (const_tree); +extern bool any_type_dependent_arguments_p (const VEC(tree,gc) *); extern bool type_dependent_expression_p_push (tree); extern bool value_dependent_expression_p (tree); extern bool any_value_dependent_elements_p (const_tree); @@ -4600,7 +4605,7 @@ extern bool dependent_omp_for_p (tree, tree, tree, tree); extern tree resolve_typename_type (tree, bool); extern tree template_for_substitution (tree); extern tree build_non_dependent_expr (tree); -extern tree build_non_dependent_args (tree); +extern void make_args_non_dependent (VEC(tree,gc) *); extern bool reregister_specialization (tree, tree, tree); extern tree fold_non_dependent_expr (tree); extern bool explicit_class_specialization_p (tree); @@ -4748,9 +4753,9 @@ extern tree begin_stmt_expr (void); extern tree finish_stmt_expr_expr (tree, tree); extern tree finish_stmt_expr (tree, bool); extern tree stmt_expr_value_expr (tree); -extern tree perform_koenig_lookup (tree, tree); -extern tree finish_call_expr (tree, tree, bool, bool, - tsubst_flags_t); +extern tree perform_koenig_lookup (tree, VEC(tree,gc) *); +extern tree finish_call_expr (tree, VEC(tree,gc) **, bool, + bool, tsubst_flags_t); extern tree finish_increment_expr (tree, enum tree_code); extern tree finish_this_expr (void); extern tree finish_pseudo_destructor_expr (tree, tree, tree); @@ -4832,7 +4837,7 @@ extern bool builtin_valid_in_constant_expr_p (const_tree); extern tree build_min (enum tree_code, tree, ...); extern tree build_min_nt (enum tree_code, ...); extern tree build_min_non_dep (enum tree_code, tree, ...); -extern tree build_min_non_dep_call_list (tree, tree, tree); +extern tree build_min_non_dep_call_vec (tree, tree, VEC(tree,gc) *); extern tree build_cplus_new (tree, tree); extern tree build_aggr_init_expr (tree, tree); extern tree get_target_expr (tree); @@ -4932,6 +4937,8 @@ extern tree cp_build_indirect_ref (tree, const char *, extern tree build_array_ref (tree, tree, location_t); extern tree get_member_function_from_ptrfunc (tree *, tree); extern tree cp_build_function_call (tree, tree, tsubst_flags_t); +extern tree cp_build_function_call_vec (tree, VEC(tree,gc) **, + tsubst_flags_t); extern tree build_x_binary_op (enum tree_code, tree, enum tree_code, tree, enum tree_code, bool *, @@ -4945,6 +4952,7 @@ extern tree unary_complex_lvalue (enum tree_code, tree); extern tree build_x_conditional_expr (tree, tree, tree, tsubst_flags_t); extern tree build_x_compound_expr_from_list (tree, const char *); +extern tree build_x_compound_expr_from_vec (VEC(tree,gc) *, const char *); extern tree build_x_compound_expr (tree, tree, tsubst_flags_t); extern tree build_compound_expr (tree, tree); extern tree cp_build_compound_expr (tree, tree, tsubst_flags_t); diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index daf145f..3220fe6 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -1,6 +1,6 @@ /* Language-level data type conversion for GNU C++. Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) @@ -755,11 +755,15 @@ ocp_convert (tree type, tree expr, int convtype, int flags) the target with the temp (see [dcl.init]). */ ctor = build_user_type_conversion (type, ctor, flags); else - ctor = build_special_member_call (NULL_TREE, - complete_ctor_identifier, - build_tree_list (NULL_TREE, ctor), - type, flags, - tf_warning_or_error); + { + VEC(tree,gc) *ctor_vec = make_tree_vector_single (ctor); + ctor = build_special_member_call (NULL_TREE, + complete_ctor_identifier, + &ctor_vec, + type, flags, + tf_warning_or_error); + release_tree_vector (ctor_vec); + } if (ctor) return build_cplus_new (type, ctor); } diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 0e050dd..3f753d1 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -3680,18 +3680,18 @@ cp_write_global_declarations (void) /* FN is an OFFSET_REF, DOTSTAR_EXPR or MEMBER_REF indicating the function to call in parse-tree form; it has not yet been semantically analyzed. ARGS are the arguments to the function. - They have already been semantically analyzed. */ + They have already been semantically analyzed. This may change + ARGS. */ tree -build_offset_ref_call_from_tree (tree fn, tree args) +build_offset_ref_call_from_tree (tree fn, VEC(tree,gc) **args) { tree orig_fn; - tree orig_args; + VEC(tree,gc) *orig_args = NULL; tree expr; tree object; orig_fn = fn; - orig_args = args; object = TREE_OPERAND (fn, 0); if (processing_template_decl) @@ -3699,17 +3699,19 @@ build_offset_ref_call_from_tree (tree fn, tree args) gcc_assert (TREE_CODE (fn) == DOTSTAR_EXPR || TREE_CODE (fn) == MEMBER_REF); if (type_dependent_expression_p (fn) - || any_type_dependent_arguments_p (args)) - return build_nt_call_list (fn, args); + || any_type_dependent_arguments_p (*args)) + return build_nt_call_vec (fn, *args); + + orig_args = make_tree_vector_copy (*args); /* Transform the arguments and add the implicit "this" parameter. That must be done before the FN is transformed because we depend on the form of FN. */ - args = build_non_dependent_args (args); + make_args_non_dependent (*args); object = build_non_dependent_expr (object); if (TREE_CODE (fn) == DOTSTAR_EXPR) object = cp_build_unary_op (ADDR_EXPR, object, 0, tf_warning_or_error); - args = tree_cons (NULL_TREE, object, args); + VEC_safe_insert (tree, gc, *args, 0, object); /* Now that the arguments are done, transform FN. */ fn = build_non_dependent_expr (fn); } @@ -3726,12 +3728,16 @@ build_offset_ref_call_from_tree (tree fn, tree args) tf_warning_or_error); fn = TREE_OPERAND (fn, 1); fn = get_member_function_from_ptrfunc (&object_addr, fn); - args = tree_cons (NULL_TREE, object_addr, args); + VEC_safe_insert (tree, gc, *args, 0, object_addr); } - expr = cp_build_function_call (fn, args, tf_warning_or_error); + expr = cp_build_function_call_vec (fn, args, tf_warning_or_error); if (processing_template_decl && expr != error_mark_node) - return build_min_non_dep_call_list (expr, orig_fn, orig_args); + expr = build_min_non_dep_call_vec (expr, orig_fn, orig_args); + + if (orig_args != NULL) + release_tree_vector (orig_args); + return expr; } diff --git a/gcc/cp/except.c b/gcc/cp/except.c index 2638ccc..99c7036 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -1,6 +1,6 @@ /* Handle exceptional things in C++. Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008 + 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc. Contributed by Michael Tiemann <tiemann@cygnus.com> Rewritten by Mike Stump <mrs@cygnus.com>, based upon an @@ -736,6 +736,7 @@ build_throw (tree exp) if (CLASS_TYPE_P (temp_type)) { int flags = LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING; + VEC(tree,gc) *exp_vec; /* Under C++0x [12.8/16 class.copy], a thrown lvalue is sometimes treated as an rvalue for the purposes of overload resolution @@ -749,11 +750,11 @@ build_throw (tree exp) flags = flags | LOOKUP_PREFER_RVALUE; /* Call the copy constructor. */ + exp_vec = make_tree_vector_single (exp); exp = (build_special_member_call - (object, complete_ctor_identifier, - build_tree_list (NULL_TREE, exp), - TREE_TYPE (object), - flags, tf_warning_or_error)); + (object, complete_ctor_identifier, &exp_vec, + TREE_TYPE (object), flags, tf_warning_or_error)); + release_tree_vector (exp_vec); if (exp == error_mark_node) { error (" in thrown expression"); diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 5fa5eb8..fd0d587 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -302,7 +302,7 @@ build_value_init (tree type) return build_aggr_init_expr (type, build_special_member_call (NULL_TREE, complete_ctor_identifier, - NULL_TREE, type, LOOKUP_NORMAL, + NULL, type, LOOKUP_NORMAL, tf_warning_or_error)); else if (TREE_CODE (type) != UNION_TYPE && TYPE_NEEDS_CONSTRUCTING (type)) { @@ -312,7 +312,7 @@ build_value_init (tree type) This will be handled in simplify_aggr_init_expr. */ tree ctor = build_special_member_call (NULL_TREE, complete_ctor_identifier, - NULL_TREE, type, LOOKUP_NORMAL, tf_warning_or_error); + NULL, type, LOOKUP_NORMAL, tf_warning_or_error); ctor = build_aggr_init_expr (type, ctor); AGGR_INIT_ZERO_FIRST (ctor) = 1; @@ -951,7 +951,7 @@ expand_cleanup_for_base (tree binfo, tree flag) /* Call the destructor. */ expr = build_special_member_call (current_class_ref, base_dtor_identifier, - NULL_TREE, + NULL, binfo, LOOKUP_NORMAL | LOOKUP_NONVIRTUAL, tf_warning_or_error); @@ -1285,7 +1285,7 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, followed by initialization by X. If neither of these work out, then look hard. */ tree rval; - tree parms; + VEC(tree,gc) *parms; if (init && TREE_CODE (init) != TREE_LIST && (flags & LOOKUP_ONLYCONVERTING)) @@ -1325,23 +1325,28 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, return; } - if (init == NULL_TREE - || (TREE_CODE (init) == TREE_LIST && ! TREE_TYPE (init))) + if (init == NULL_TREE) + parms = NULL; + else if (TREE_CODE (init) == TREE_LIST && !TREE_TYPE (init)) { - parms = init; - if (parms) - init = TREE_VALUE (parms); + parms = make_tree_vector (); + for (; init != NULL_TREE; init = TREE_CHAIN (init)) + VEC_safe_push (tree, gc, parms, TREE_VALUE (init)); } else - parms = build_tree_list (NULL_TREE, init); + parms = make_tree_vector_single (init); if (true_exp == exp) ctor_name = complete_ctor_identifier; else ctor_name = base_ctor_identifier; - rval = build_special_member_call (exp, ctor_name, parms, binfo, flags, + rval = build_special_member_call (exp, ctor_name, &parms, binfo, flags, complain); + + if (parms != NULL) + release_tree_vector (parms); + if (TREE_SIDE_EFFECTS (rval)) finish_expr_stmt (convert_to_void (rval, NULL, complain)); } @@ -1706,18 +1711,31 @@ build_builtin_delete_call (tree addr) the type of the object being allocated; otherwise, it's just TYPE. INIT is the initializer, if any. USE_GLOBAL_NEW is true if the user explicitly wrote "::operator new". PLACEMENT, if non-NULL, is - the TREE_LIST of arguments to be provided as arguments to a - placement new operator. This routine performs no semantic checks; - it just creates and returns a NEW_EXPR. */ + a vector of arguments to be provided as arguments to a placement + new operator. This routine performs no semantic checks; it just + creates and returns a NEW_EXPR. */ static tree -build_raw_new_expr (tree placement, tree type, tree nelts, tree init, - int use_global_new) +build_raw_new_expr (VEC(tree,gc) *placement, tree type, tree nelts, + VEC(tree,gc) *init, int use_global_new) { + tree init_list; tree new_expr; - new_expr = build4 (NEW_EXPR, build_pointer_type (type), placement, type, - nelts, init); + /* If INIT is NULL, the we want to store NULL_TREE in the NEW_EXPR. + If INIT is not NULL, then we want to store VOID_ZERO_NODE. This + permits us to distinguish the case of a missing initializer "new + int" from an empty initializer "new int()". */ + if (init == NULL) + init_list = NULL_TREE; + else if (VEC_empty (tree, init)) + init_list = void_zero_node; + else + init_list = build_tree_list_vec (init); + + new_expr = build4 (NEW_EXPR, build_pointer_type (type), + build_tree_list_vec (placement), type, nelts, + init_list); NEW_EXPR_USE_GLOBAL (new_expr) = use_global_new; TREE_SIDE_EFFECTS (new_expr) = 1; @@ -1776,11 +1794,12 @@ avoid_placement_new_aliasing (tree t, tree placement) /* Generate code for a new-expression, including calling the "operator new" function, initializing the object, and, if an exception occurs during construction, cleaning up. The arguments are as for - build_raw_new_expr. */ + build_raw_new_expr. This may change PLACEMENT and INIT. */ static tree -build_new_1 (tree placement, tree type, tree nelts, tree init, - bool globally_qualified_p, tsubst_flags_t complain) +build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, + VEC(tree,gc) **init, bool globally_qualified_p, + tsubst_flags_t complain) { tree size, rval; /* True iff this is a call to "operator new[]" instead of just @@ -1807,11 +1826,12 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, beginning of the storage allocated for an array-new expression in order to store the number of elements. */ tree cookie_size = NULL_TREE; + bool have_placement; + tree placement_first; tree placement_expr = NULL_TREE; /* True if the function we are calling is a placement allocation function. */ bool placement_allocation_fn_p; - tree args = NULL_TREE; /* True if the storage must be initialized, either by a constructor or due to an explicit new-initializer. */ bool is_initialized; @@ -1855,9 +1875,9 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, if (abstract_virtuals_error (NULL_TREE, elt_type)) return error_mark_node; - is_initialized = (TYPE_NEEDS_CONSTRUCTING (elt_type) || init); + is_initialized = (TYPE_NEEDS_CONSTRUCTING (elt_type) || *init != NULL); - if (CP_TYPE_CONST_P (elt_type) && !init + if (CP_TYPE_CONST_P (elt_type) && *init == NULL && !type_has_user_provided_default_constructor (elt_type)) { if (complain & tf_error) @@ -1871,8 +1891,18 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, alloc_fn = NULL_TREE; + /* If PLACEMENT is a single simple pointer type not passed by + reference, prepare to capture it in a temporary variable. Do + this now, since PLACEMENT will change in the calls below. */ + have_placement = !VEC_empty (tree, *placement); + placement_first = NULL_TREE; + if (VEC_length (tree, *placement) == 1 + && (TREE_CODE (TREE_TYPE (VEC_index (tree, *placement, 0))) + == POINTER_TYPE)) + placement_first = VEC_index (tree, *placement, 0); + /* Allocate the object. */ - if (! placement && TYPE_FOR_JAVA (elt_type)) + if (VEC_empty (tree, *placement) && TYPE_FOR_JAVA (elt_type)) { tree class_addr; tree class_decl = build_java_class_ref (elt_type); @@ -1928,7 +1958,7 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, size = size_binop (PLUS_EXPR, size, cookie_size); } /* Create the argument list. */ - args = tree_cons (NULL_TREE, size, placement); + VEC_safe_insert (tree, gc, *placement, 0, size); /* Do name-lookup to find the appropriate operator. */ fns = lookup_fnfields (elt_type, fnname, /*protect=*/2); if (fns == NULL_TREE) @@ -1947,7 +1977,7 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, return error_mark_node; } alloc_call = build_new_method_call (build_dummy_object (elt_type), - fns, args, + fns, placement, /*conversion_path=*/NULL_TREE, LOOKUP_NORMAL, &alloc_fn, @@ -1973,12 +2003,10 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, gcc_assert (alloc_fn != NULL_TREE); - /* If PLACEMENT is a simple pointer type and is not passed by reference, - then copy it into PLACEMENT_EXPR. */ + /* If we found a simple case of PLACEMENT_EXPR above, then copy it + into a temporary variable. */ if (!processing_template_decl - && placement != NULL_TREE - && TREE_CHAIN (placement) == NULL_TREE - && TREE_CODE (TREE_TYPE (TREE_VALUE (placement))) == POINTER_TYPE + && placement_first != NULL_TREE && TREE_CODE (alloc_call) == CALL_EXPR && call_expr_nargs (alloc_call) == 2 && TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (alloc_call, 0))) == INTEGER_TYPE @@ -1989,7 +2017,7 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (placement_arg))) || VOID_TYPE_P (TREE_TYPE (TREE_TYPE (placement_arg)))) { - placement_expr = get_target_expr (TREE_VALUE (placement)); + placement_expr = get_target_expr (placement_first); CALL_EXPR_ARG (alloc_call, 1) = convert (TREE_TYPE (placement_arg), placement_expr); } @@ -2000,7 +2028,7 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, if (!cookie_size && !is_initialized) { rval = build_nop (pointer_type, alloc_call); - if (placement != NULL) + if (have_placement) rval = avoid_placement_new_aliasing (rval, placement_expr); return rval; } @@ -2109,15 +2137,15 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, bool stable; bool explicit_value_init_p = false; - if (init == void_zero_node) + if (*init != NULL && VEC_empty (tree, *init)) { - init = NULL_TREE; + *init = NULL; explicit_value_init_p = true; } if (array_p) { - if (init) + if (*init) { if (complain & tf_error) permerror (input_location, "ISO C++ forbids initialization in array new"); @@ -2130,7 +2158,7 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, MINUS_EXPR, outer_nelts, integer_one_node, complain), - init, + build_tree_list_vec (*init), explicit_value_init_p, /*from_array=*/0, complain); @@ -2160,17 +2188,13 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, } else { + tree ie; + /* We are processing something like `new int (10)', which means allocate an int, and initialize it with 10. */ - if (TREE_CODE (init) == TREE_LIST) - init = build_x_compound_expr_from_list (init, - "new initializer"); - else - gcc_assert (TREE_CODE (init) != CONSTRUCTOR - || TREE_TYPE (init) != NULL_TREE); - - init_expr = cp_build_modify_expr (init_expr, INIT_EXPR, init, + ie = build_x_compound_expr_from_vec (*init, "new initializer"); + init_expr = cp_build_modify_expr (init_expr, INIT_EXPR, ie, complain); } stable = stabilize_init (init_expr, &init_preeval_expr); @@ -2283,60 +2307,58 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, /* A new-expression is never an lvalue. */ gcc_assert (!lvalue_p (rval)); - if (placement != NULL) + if (have_placement) rval = avoid_placement_new_aliasing (rval, placement_expr); return rval; } -/* Generate a representation for a C++ "new" expression. PLACEMENT is - a TREE_LIST of placement-new arguments (or NULL_TREE if none). If - NELTS is NULL, TYPE is the type of the storage to be allocated. If - NELTS is not NULL, then this is an array-new allocation; TYPE is - the type of the elements in the array and NELTS is the number of - elements in the array. INIT, if non-NULL, is the initializer for - the new object, or void_zero_node to indicate an initializer of - "()". If USE_GLOBAL_NEW is true, then the user explicitly wrote - "::new" rather than just "new". */ +/* Generate a representation for a C++ "new" expression. *PLACEMENT + is a vector of placement-new arguments (or NULL if none). If NELTS + is NULL, TYPE is the type of the storage to be allocated. If NELTS + is not NULL, then this is an array-new allocation; TYPE is the type + of the elements in the array and NELTS is the number of elements in + the array. *INIT, if non-NULL, is the initializer for the new + object, or an empty vector to indicate an initializer of "()". If + USE_GLOBAL_NEW is true, then the user explicitly wrote "::new" + rather than just "new". This may change PLACEMENT and INIT. */ tree -build_new (tree placement, tree type, tree nelts, tree init, - int use_global_new, tsubst_flags_t complain) +build_new (VEC(tree,gc) **placement, tree type, tree nelts, + VEC(tree,gc) **init, int use_global_new, tsubst_flags_t complain) { tree rval; - tree orig_placement; - tree orig_nelts; - tree orig_init; + VEC(tree,gc) *orig_placement = NULL; + tree orig_nelts = NULL_TREE; + VEC(tree,gc) *orig_init = NULL; - if (placement == error_mark_node || type == error_mark_node - || init == error_mark_node) + if (type == error_mark_node) return error_mark_node; - orig_placement = placement; - orig_nelts = nelts; - orig_init = init; - - if (nelts == NULL_TREE && init != void_zero_node && list_length (init) == 1) + if (nelts == NULL_TREE && VEC_length (tree, *init) == 1) { tree auto_node = type_uses_auto (type); - if (auto_node && describable_type (TREE_VALUE (init))) - type = do_auto_deduction (type, TREE_VALUE (init), auto_node); + if (auto_node && describable_type (VEC_index (tree, *init, 0))) + type = do_auto_deduction (type, VEC_index (tree, *init, 0), auto_node); } if (processing_template_decl) { if (dependent_type_p (type) - || any_type_dependent_arguments_p (placement) + || any_type_dependent_arguments_p (*placement) || (nelts && type_dependent_expression_p (nelts)) - || (init != void_zero_node - && any_type_dependent_arguments_p (init))) - return build_raw_new_expr (placement, type, nelts, init, + || any_type_dependent_arguments_p (*init)) + return build_raw_new_expr (*placement, type, nelts, *init, use_global_new); - placement = build_non_dependent_args (placement); + + orig_placement = make_tree_vector_copy (*placement); + orig_nelts = nelts; + orig_init = make_tree_vector_copy (*init); + + make_args_non_dependent (*placement); if (nelts) nelts = build_non_dependent_expr (nelts); - if (init != void_zero_node) - init = build_non_dependent_args (init); + make_args_non_dependent (*init); } if (nelts) @@ -2381,8 +2403,13 @@ build_new (tree placement, tree type, tree nelts, tree init, return error_mark_node; if (processing_template_decl) - return build_raw_new_expr (orig_placement, type, orig_nelts, orig_init, - use_global_new); + { + tree ret = build_raw_new_expr (orig_placement, type, orig_nelts, + orig_init, use_global_new); + release_tree_vector (orig_placement); + release_tree_vector (orig_init); + return ret; + } /* Wrap it in a NOP_EXPR so warn_if_unused_value doesn't complain. */ rval = build1 (NOP_EXPR, TREE_TYPE (rval), rval); @@ -2954,7 +2981,7 @@ build_dtor_call (tree exp, special_function_kind dtor_kind, int flags) } fn = lookup_fnfields (TREE_TYPE (exp), name, /*protect=*/2); return build_new_method_call (exp, fn, - /*args=*/NULL_TREE, + /*args=*/NULL, /*conversion_path=*/NULL_TREE, flags, /*fn_p=*/NULL, @@ -3172,7 +3199,7 @@ push_base_cleanups (void) { expr = build_special_member_call (current_class_ref, base_dtor_identifier, - NULL_TREE, + NULL, base_binfo, (LOOKUP_NORMAL | LOOKUP_NONVIRTUAL), @@ -3194,7 +3221,7 @@ push_base_cleanups (void) expr = build_special_member_call (current_class_ref, base_dtor_identifier, - NULL_TREE, base_binfo, + NULL, base_binfo, LOOKUP_NORMAL | LOOKUP_NONVIRTUAL, tf_warning_or_error); finish_decl_cleanup (NULL_TREE, expr); diff --git a/gcc/cp/method.c b/gcc/cp/method.c index e632fe0..410503d 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -1,7 +1,7 @@ /* Handle the hair of processing (but not expanding) inline functions. Also manage function and variable name overloading. Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) @@ -661,19 +661,21 @@ do_build_assign_ref (tree fndecl) BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) { tree converted_parm; + VEC(tree,gc) *parmvec; /* We must convert PARM directly to the base class explicitly since the base class may be ambiguous. */ converted_parm = build_base_path (PLUS_EXPR, parm, base_binfo, 1); /* Call the base class assignment operator. */ + parmvec = make_tree_vector_single (converted_parm); finish_expr_stmt (build_special_member_call (current_class_ref, ansi_assopname (NOP_EXPR), - build_tree_list (NULL_TREE, - converted_parm), + &parmvec, base_binfo, LOOKUP_NORMAL | LOOKUP_NONVIRTUAL, tf_warning_or_error)); + release_tree_vector (parmvec); } /* Assign to each of the non-static data members. */ diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index e499ede..215750f 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -4235,7 +4235,7 @@ lookup_name_nonclass (tree name) } tree -lookup_function_nonclass (tree name, tree args, bool block_p) +lookup_function_nonclass (tree name, VEC(tree,gc) *args, bool block_p) { return lookup_arg_dependent (name, @@ -4427,7 +4427,7 @@ lookup_type_current_level (tree name) struct arg_lookup { tree name; - tree args; + VEC(tree,gc) *args; tree namespaces; tree classes; tree functions; @@ -4435,6 +4435,7 @@ struct arg_lookup static bool arg_assoc (struct arg_lookup*, tree); static bool arg_assoc_args (struct arg_lookup*, tree); +static bool arg_assoc_args_vec (struct arg_lookup*, VEC(tree,gc) *); static bool arg_assoc_type (struct arg_lookup*, tree); static bool add_function (struct arg_lookup *, tree); static bool arg_assoc_namespace (struct arg_lookup *, tree); @@ -4589,13 +4590,13 @@ arg_assoc_namespace (struct arg_lookup *k, tree scope) classes. */ if (hidden_name_p (OVL_CURRENT (value))) { - tree args; + unsigned int ix; + tree arg; - for (args = k->args; args; args = TREE_CHAIN (args)) - if (friend_of_associated_class_p (TREE_VALUE (args), - OVL_CURRENT (value))) + for (ix = 0; VEC_iterate (tree, k->args, ix, arg); ++ix) + if (friend_of_associated_class_p (arg, OVL_CURRENT (value))) break; - if (!args) + if (ix >= VEC_length (tree, k->args)) continue; } @@ -4805,6 +4806,21 @@ arg_assoc_args (struct arg_lookup *k, tree args) return false; } +/* Adds everything associated with an argument vector. Returns true + on error. */ + +static bool +arg_assoc_args_vec (struct arg_lookup *k, VEC(tree,gc) *args) +{ + unsigned int ix; + tree arg; + + for (ix = 0; VEC_iterate (tree, args, ix, arg); ++ix) + if (arg_assoc (k, arg)) + return true; + return false; +} + /* Adds everything associated with a given tree_node. Returns 1 on error. */ static bool @@ -4884,7 +4900,7 @@ arg_assoc (struct arg_lookup *k, tree n) are the functions found in normal lookup. */ tree -lookup_arg_dependent (tree name, tree fns, tree args) +lookup_arg_dependent (tree name, tree fns, VEC(tree,gc) *args) { struct arg_lookup k; @@ -4907,7 +4923,7 @@ lookup_arg_dependent (tree name, tree fns, tree args) picking up later definitions) in the second stage. */ k.namespaces = NULL_TREE; - arg_assoc_args (&k, args); + arg_assoc_args_vec (&k, args); fns = k.functions; diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h index 6de4cfa..2203a84 100644 --- a/gcc/cp/name-lookup.h +++ b/gcc/cp/name-lookup.h @@ -1,5 +1,6 @@ /* Declarations for C++ name lookup routines. - Copyright (C) 2003, 2004, 2005, 2007, 2008 Free Software Foundation, Inc. + Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009 + Free Software Foundation, Inc. Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net> This file is part of GCC. @@ -317,7 +318,7 @@ extern tree remove_hidden_names (tree); extern tree lookup_qualified_name (tree, tree, bool, bool); extern tree lookup_name_nonclass (tree); extern tree lookup_name_innermost_nonclass_level (tree); -extern tree lookup_function_nonclass (tree, tree, bool); +extern tree lookup_function_nonclass (tree, VEC(tree,gc) *, bool); extern void push_local_binding (tree, tree, int); extern bool pushdecl_class_level (tree); extern tree pushdecl_namespace_level (tree, bool); @@ -332,7 +333,7 @@ extern void do_toplevel_using_decl (tree, tree, tree); extern void do_local_using_decl (tree, tree, tree); extern tree do_class_using_decl (tree, tree); extern void do_using_directive (tree); -extern tree lookup_arg_dependent (tree, tree, tree); +extern tree lookup_arg_dependent (tree, tree, VEC(tree,gc) *); extern bool is_associated_namespace (tree, tree); extern void parse_using_directive (tree, tree); extern tree innermost_non_namespace_value (tree); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 6954ef0..e7d2e7d 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -1584,7 +1584,7 @@ static tree cp_parser_postfix_open_square_expression (cp_parser *, tree, bool); static tree cp_parser_postfix_dot_deref_expression (cp_parser *, enum cpp_ttype, tree, bool, cp_id_kind *, location_t); -static tree cp_parser_parenthesized_expression_list +static VEC(tree,gc) *cp_parser_parenthesized_expression_list (cp_parser *, bool, bool, bool, bool *); static void cp_parser_pseudo_destructor_name (cp_parser *, tree *, tree *); @@ -1594,7 +1594,7 @@ static enum tree_code cp_parser_unary_operator (cp_token *); static tree cp_parser_new_expression (cp_parser *); -static tree cp_parser_new_placement +static VEC(tree,gc) *cp_parser_new_placement (cp_parser *); static tree cp_parser_new_type_id (cp_parser *, tree *); @@ -1602,7 +1602,7 @@ static cp_declarator *cp_parser_new_declarator_opt (cp_parser *); static cp_declarator *cp_parser_direct_new_declarator (cp_parser *); -static tree cp_parser_new_initializer +static VEC(tree,gc) *cp_parser_new_initializer (cp_parser *); static tree cp_parser_delete_expression (cp_parser *); @@ -4685,7 +4685,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, bool is_builtin_constant_p; bool saved_integral_constant_expression_p = false; bool saved_non_integral_constant_expression_p = false; - tree args; + VEC(tree,gc) *args; is_member_access = false; @@ -4713,7 +4713,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, = saved_non_integral_constant_expression_p; } - if (args == error_mark_node) + if (args == NULL) { postfix_expression = error_mark_node; break; @@ -4726,6 +4726,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, "a function call")) { postfix_expression = error_mark_node; + release_tree_vector (args); break; } @@ -4735,7 +4736,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, { if (TREE_CODE (postfix_expression) == IDENTIFIER_NODE) { - if (args) + if (!VEC_empty (tree, args)) { koenig_p = true; if (!any_type_dependent_arguments_p (args)) @@ -4749,7 +4750,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, /* We do not perform argument-dependent lookup if normal lookup finds a non-function, in accordance with the expected resolution of DR 218. */ - else if (args && is_overloaded_fn (postfix_expression)) + else if (!VEC_empty (tree, args) + && is_overloaded_fn (postfix_expression)) { tree fn = get_first_fn (postfix_expression); @@ -4782,7 +4784,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, || any_type_dependent_arguments_p (args))) { postfix_expression - = build_nt_call_list (postfix_expression, args); + = build_nt_call_vec (postfix_expression, args); + release_tree_vector (args); break; } @@ -4790,7 +4793,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, { postfix_expression = (build_new_method_call - (instance, fn, args, NULL_TREE, + (instance, fn, &args, NULL_TREE, (idk == CP_ID_KIND_QUALIFIED ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL), /*fn_p=*/NULL, @@ -4798,7 +4801,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, } else postfix_expression - = finish_call_expr (postfix_expression, args, + = finish_call_expr (postfix_expression, &args, /*disallow_virtual=*/false, /*koenig_p=*/false, tf_warning_or_error); @@ -4807,25 +4810,27 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, || TREE_CODE (postfix_expression) == MEMBER_REF || TREE_CODE (postfix_expression) == DOTSTAR_EXPR) postfix_expression = (build_offset_ref_call_from_tree - (postfix_expression, args)); + (postfix_expression, &args)); else if (idk == CP_ID_KIND_QUALIFIED) /* A call to a static class member, or a namespace-scope function. */ postfix_expression - = finish_call_expr (postfix_expression, args, + = finish_call_expr (postfix_expression, &args, /*disallow_virtual=*/true, koenig_p, tf_warning_or_error); else /* All other function calls. */ postfix_expression - = finish_call_expr (postfix_expression, args, + = finish_call_expr (postfix_expression, &args, /*disallow_virtual=*/false, koenig_p, tf_warning_or_error); /* The POSTFIX_EXPRESSION is certainly no longer an id. */ idk = CP_ID_KIND_NONE; + + release_tree_vector (args); } break; @@ -5132,24 +5137,22 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser, ALLOW_EXPANSION_P is true if this expression allows expansion of an argument pack. - Returns a TREE_LIST. The TREE_VALUE of each node is a - representation of an assignment-expression. Note that a TREE_LIST - is returned even if there is only a single expression in the list. - error_mark_node is returned if the ( and or ) are - missing. NULL_TREE is returned on no expressions. The parentheses - are eaten. IS_ATTRIBUTE_LIST is true if this is really an attribute - list being parsed. If NON_CONSTANT_P is non-NULL, *NON_CONSTANT_P - indicates whether or not all of the expressions in the list were - constant. */ + Returns a vector of trees. Each element is a representation of an + assignment-expression. NULL is returned if the ( and or ) are + missing. An empty, but allocated, vector is returned on no + expressions. The parentheses are eaten. IS_ATTRIBUTE_LIST is true + if this is really an attribute list being parsed. If + NON_CONSTANT_P is non-NULL, *NON_CONSTANT_P indicates whether or + not all of the expressions in the list were constant. */ -static tree +static VEC(tree,gc) * cp_parser_parenthesized_expression_list (cp_parser* parser, bool is_attribute_list, bool cast_p, bool allow_expansion_p, bool *non_constant_p) { - tree expression_list = NULL_TREE; + VEC(tree,gc) *expression_list; bool fold_expr_p = is_attribute_list; tree identifier = NULL_TREE; bool saved_greater_than_is_operator_p; @@ -5159,7 +5162,9 @@ cp_parser_parenthesized_expression_list (cp_parser* parser, *non_constant_p = false; if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>")) - return error_mark_node; + return NULL; + + expression_list = make_tree_vector (); /* Within a parenthesized expression, a `>' token is always the greater-than operator. */ @@ -5228,7 +5233,7 @@ cp_parser_parenthesized_expression_list (cp_parser* parser, expressions to the list, so that we can still tell if the correct form for a parenthesized expression-list is found. That gives better errors. */ - expression_list = tree_cons (NULL_TREE, expr, expression_list); + VEC_safe_push (tree, gc, expression_list, expr); if (expr == error_mark_node) goto skip_comma; @@ -5264,17 +5269,15 @@ cp_parser_parenthesized_expression_list (cp_parser* parser, { parser->greater_than_is_operator_p = saved_greater_than_is_operator_p; - return error_mark_node; + return NULL; } } parser->greater_than_is_operator_p = saved_greater_than_is_operator_p; - /* We built up the list in reverse order so we must reverse it now. */ - expression_list = nreverse (expression_list); if (identifier) - expression_list = tree_cons (NULL_TREE, identifier, expression_list); + VEC_safe_insert (tree, gc, expression_list, 0, identifier); return expression_list; } @@ -5618,10 +5621,11 @@ static tree cp_parser_new_expression (cp_parser* parser) { bool global_scope_p; - tree placement; + VEC(tree,gc) *placement; tree type; - tree initializer; + VEC(tree,gc) *initializer; tree nelts; + tree ret; /* Look for the optional `::' operator. */ global_scope_p @@ -5637,7 +5641,11 @@ cp_parser_new_expression (cp_parser* parser) placement = cp_parser_new_placement (parser); /* If that didn't work out, there's no new-placement. */ if (!cp_parser_parse_definitely (parser)) - placement = NULL_TREE; + { + if (placement != NULL) + release_tree_vector (placement); + placement = NULL; + } /* If the next token is a `(', then we have a parenthesized type-id. */ @@ -5673,16 +5681,25 @@ cp_parser_new_expression (cp_parser* parser) || cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) initializer = cp_parser_new_initializer (parser); else - initializer = NULL_TREE; + initializer = NULL; /* A new-expression may not appear in an integral constant expression. */ if (cp_parser_non_integral_constant_expression (parser, "%<new%>")) - return error_mark_node; + ret = error_mark_node; + else + { + /* Create a representation of the new-expression. */ + ret = build_new (&placement, type, nelts, &initializer, global_scope_p, + tf_warning_or_error); + } - /* Create a representation of the new-expression. */ - return build_new (placement, type, nelts, initializer, global_scope_p, - tf_warning_or_error); + if (placement != NULL) + release_tree_vector (placement); + if (initializer != NULL) + release_tree_vector (initializer); + + return ret; } /* Parse a new-placement. @@ -5692,10 +5709,10 @@ cp_parser_new_expression (cp_parser* parser) Returns the same representation as for an expression-list. */ -static tree +static VEC(tree,gc) * cp_parser_new_placement (cp_parser* parser) { - tree expression_list; + VEC(tree,gc) *expression_list; /* Parse the expression-list. */ expression_list = (cp_parser_parenthesized_expression_list @@ -5885,28 +5902,26 @@ cp_parser_direct_new_declarator (cp_parser* parser) ( expression-list [opt] ) braced-init-list - Returns a representation of the expression-list. If there is no - expression-list, VOID_ZERO_NODE is returned. */ + Returns a representation of the expression-list. */ -static tree +static VEC(tree,gc) * cp_parser_new_initializer (cp_parser* parser) { - tree expression_list; + VEC(tree,gc) *expression_list; if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) { + tree t; bool expr_non_constant_p; maybe_warn_cpp0x ("extended initializer lists"); - expression_list = cp_parser_braced_list (parser, &expr_non_constant_p); - CONSTRUCTOR_IS_DIRECT_INIT (expression_list) = 1; - expression_list = build_tree_list (NULL_TREE, expression_list); + t = cp_parser_braced_list (parser, &expr_non_constant_p); + CONSTRUCTOR_IS_DIRECT_INIT (t) = 1; + expression_list = make_tree_vector_single (t); } else expression_list = (cp_parser_parenthesized_expression_list (parser, false, /*cast_p=*/false, /*allow_expansion_p=*/true, /*non_constant_p=*/NULL)); - if (!expression_list) - expression_list = void_zero_node; return expression_list; } @@ -9225,11 +9240,18 @@ cp_parser_mem_initializer (cp_parser* parser) expression_list = build_tree_list (NULL_TREE, expression_list); } else - expression_list - = cp_parser_parenthesized_expression_list (parser, false, - /*cast_p=*/false, - /*allow_expansion_p=*/true, - /*non_constant_p=*/NULL); + { + VEC(tree,gc)* vec; + vec = cp_parser_parenthesized_expression_list (parser, false, + /*cast_p=*/false, + /*allow_expansion_p=*/true, + /*non_constant_p=*/NULL); + if (vec == NULL) + return error_mark_node; + expression_list = build_tree_list_vec (vec); + release_tree_vector (vec); + } + if (expression_list == error_mark_node) return error_mark_node; if (!expression_list) @@ -14585,10 +14607,17 @@ cp_parser_initializer (cp_parser* parser, bool* is_direct_init, init = cp_parser_initializer_clause (parser, non_constant_p); } else if (token->type == CPP_OPEN_PAREN) - init = cp_parser_parenthesized_expression_list (parser, false, - /*cast_p=*/false, - /*allow_expansion_p=*/true, - non_constant_p); + { + VEC(tree,gc) *vec; + vec = cp_parser_parenthesized_expression_list (parser, false, + /*cast_p=*/false, + /*allow_expansion_p=*/true, + non_constant_p); + if (vec == NULL) + return error_mark_node; + init = build_tree_list_vec (vec); + release_tree_vector (vec); + } else if (token->type == CPP_OPEN_BRACE) { maybe_warn_cpp0x ("extended initializer lists"); @@ -16850,10 +16879,18 @@ cp_parser_attribute_list (cp_parser* parser) /* If it's an `(', then parse the attribute arguments. */ if (token->type == CPP_OPEN_PAREN) { - arguments = cp_parser_parenthesized_expression_list - (parser, true, /*cast_p=*/false, - /*allow_expansion_p=*/false, - /*non_constant_p=*/NULL); + VEC(tree,gc) *vec; + vec = cp_parser_parenthesized_expression_list + (parser, true, /*cast_p=*/false, + /*allow_expansion_p=*/false, + /*non_constant_p=*/NULL); + if (vec == NULL) + arguments = error_mark_node; + else + { + arguments = build_tree_list_vec (vec); + release_tree_vector (vec); + } /* Save the arguments away. */ TREE_VALUE (attribute) = arguments; } @@ -17981,6 +18018,7 @@ cp_parser_simple_cast_expression (cp_parser *parser) static tree cp_parser_functional_cast (cp_parser* parser, tree type) { + VEC(tree,gc) *vec; tree expression_list; tree cast; bool nonconst_p; @@ -17995,11 +18033,18 @@ cp_parser_functional_cast (cp_parser* parser, tree type) return finish_compound_literal (type, expression_list); } - expression_list - = cp_parser_parenthesized_expression_list (parser, false, - /*cast_p=*/true, - /*allow_expansion_p=*/true, - /*non_constant_p=*/NULL); + + vec = cp_parser_parenthesized_expression_list (parser, false, + /*cast_p=*/true, + /*allow_expansion_p=*/true, + /*non_constant_p=*/NULL); + if (vec == NULL) + expression_list = error_mark_node; + else + { + expression_list = build_tree_list_vec (vec); + release_tree_vector (vec); + } cast = build_functional_cast (type, expression_list, tf_warning_or_error); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 2ca28d6..ed6b031 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -118,8 +118,8 @@ static tree add_outermost_template_args (tree, tree); static bool check_instantiated_args (tree, tree, tsubst_flags_t); static int maybe_adjust_types_for_deduction (unification_kind_t, tree*, tree*, tree); -static int type_unification_real (tree, tree, tree, tree, - int, unification_kind_t, int); +static int type_unification_real (tree, tree, tree, const tree *, + unsigned int, int, unification_kind_t, int); static void note_template_header (int); static tree convert_nontype_argument_function (tree, tree); static tree convert_nontype_argument (tree, tree); @@ -11430,24 +11430,54 @@ tsubst_copy_and_build (tree t, case NEW_EXPR: { + tree placement = RECUR (TREE_OPERAND (t, 0)); tree init = RECUR (TREE_OPERAND (t, 3)); + VEC(tree,gc) *placement_vec; + VEC(tree,gc) *init_vec; + tree ret; - if (TREE_OPERAND (t, 3) && !init) - /* If there was an initializer in the original tree, but - it instantiated to an empty list, then we should pass on - VOID_ZERO_NODE to tell build_new that it was an empty - initializer () rather than no initializer. This can only - happen when the initializer is a pack expansion whose - parameter packs are of length zero. */ - init = void_zero_node; + if (placement == NULL_TREE) + placement_vec = NULL; + else + { + placement_vec = make_tree_vector (); + for (; placement != NULL_TREE; placement = TREE_CHAIN (placement)) + VEC_safe_push (tree, gc, placement_vec, TREE_VALUE (placement)); + } - return build_new - (RECUR (TREE_OPERAND (t, 0)), - RECUR (TREE_OPERAND (t, 1)), - RECUR (TREE_OPERAND (t, 2)), - init, - NEW_EXPR_USE_GLOBAL (t), - complain); + /* If there was an initializer in the original tree, but it + instantiated to an empty list, then we should pass a + non-NULL empty vector to tell build_new that it was an + empty initializer() rather than no initializer. This can + only happen when the initializer is a pack expansion whose + parameter packs are of length zero. */ + if (init == NULL_TREE && TREE_OPERAND (t, 3) == NULL_TREE) + init_vec = NULL; + else + { + init_vec = make_tree_vector (); + if (init == void_zero_node) + gcc_assert (init_vec != NULL); + else + { + for (; init != NULL_TREE; init = TREE_CHAIN (init)) + VEC_safe_push (tree, gc, init_vec, TREE_VALUE (init)); + } + } + + ret = build_new (&placement_vec, + RECUR (TREE_OPERAND (t, 1)), + RECUR (TREE_OPERAND (t, 2)), + &init_vec, + NEW_EXPR_USE_GLOBAL (t), + complain); + + if (placement_vec != NULL) + release_tree_vector (placement_vec); + if (init_vec != NULL) + release_tree_vector (init_vec); + + return ret; } case DELETE_EXPR: @@ -11465,9 +11495,11 @@ tsubst_copy_and_build (tree t, case CALL_EXPR: { tree function; - tree call_args; + VEC(tree,gc) *call_args; + unsigned int nargs, i; bool qualified_p; bool koenig_p; + tree ret; function = CALL_EXPR_FN (t); /* When we parsed the expression, we determined whether or @@ -11502,8 +11534,40 @@ tsubst_copy_and_build (tree t, qualified_p = true; } - /* FIXME: Rewrite this so as not to construct an arglist. */ - call_args = RECUR (CALL_EXPR_ARGS (t)); + nargs = call_expr_nargs (t); + call_args = make_tree_vector (); + for (i = 0; i < nargs; ++i) + { + tree arg = CALL_EXPR_ARG (t, i); + + if (!PACK_EXPANSION_P (arg)) + VEC_safe_push (tree, gc, call_args, + RECUR (CALL_EXPR_ARG (t, i))); + else + { + /* Expand the pack expansion and push each entry onto + CALL_ARGS. */ + arg = tsubst_pack_expansion (arg, args, complain, in_decl); + if (TREE_CODE (arg) == TREE_VEC) + { + unsigned int len, j; + + len = TREE_VEC_LENGTH (arg); + for (j = 0; j < len; ++j) + { + tree value = TREE_VEC_ELT (arg, j); + if (value != NULL_TREE) + value = convert_from_reference (value); + VEC_safe_push (tree, gc, call_args, value); + } + } + else + { + /* A partial substitution. Add one entry. */ + VEC_safe_push (tree, gc, call_args, arg); + } + } + } /* We do not perform argument-dependent lookup if normal lookup finds a non-function, in accordance with the @@ -11524,6 +11588,7 @@ tsubst_copy_and_build (tree t, if (TREE_CODE (function) == IDENTIFIER_NODE) { unqualified_name_lookup_error (function); + release_tree_vector (call_args); return error_mark_node; } @@ -11532,27 +11597,32 @@ tsubst_copy_and_build (tree t, mark_used (function); if (TREE_CODE (function) == OFFSET_REF) - return build_offset_ref_call_from_tree (function, call_args); - if (TREE_CODE (function) == COMPONENT_REF) + ret = build_offset_ref_call_from_tree (function, &call_args); + else if (TREE_CODE (function) == COMPONENT_REF) { if (!BASELINK_P (TREE_OPERAND (function, 1))) - return finish_call_expr (function, call_args, + ret = finish_call_expr (function, &call_args, /*disallow_virtual=*/false, /*koenig_p=*/false, complain); else - return (build_new_method_call + ret = (build_new_method_call (TREE_OPERAND (function, 0), TREE_OPERAND (function, 1), - call_args, NULL_TREE, + &call_args, NULL_TREE, qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL, /*fn_p=*/NULL, complain)); } - return finish_call_expr (function, call_args, - /*disallow_virtual=*/qualified_p, - koenig_p, - complain); + else + ret = finish_call_expr (function, &call_args, + /*disallow_virtual=*/qualified_p, + koenig_p, + complain); + + release_tree_vector (call_args); + + return ret; } case COND_EXPR: @@ -12112,9 +12182,10 @@ instantiate_template (tree tmpl, tree targ_ptr, tsubst_flags_t complain) return fndecl; } -/* The FN is a TEMPLATE_DECL for a function. The ARGS are the - arguments that are being used when calling it. TARGS is a vector - into which the deduced template arguments are placed. +/* The FN is a TEMPLATE_DECL for a function. ARGS is an array with + NARGS elements of the arguments that are being used when calling + it. TARGS is a vector into which the deduced template arguments + are placed. Return zero for success, 2 for an incomplete match that doesn't resolve all the types, and 1 for complete failure. An error message will be @@ -12146,7 +12217,8 @@ int fn_type_unification (tree fn, tree explicit_targs, tree targs, - tree args, + const tree *args, + unsigned int nargs, tree return_type, unification_kind_t strict, int flags) @@ -12263,8 +12335,14 @@ fn_type_unification (tree fn, if (return_type) { + tree *new_args; + parms = tree_cons (NULL_TREE, TREE_TYPE (fntype), parms); - args = tree_cons (NULL_TREE, return_type, args); + new_args = XALLOCAVEC (tree, nargs + 1); + new_args[0] = return_type; + memcpy (new_args + 1, args, nargs * sizeof (tree)); + args = new_args; + ++nargs; } /* We allow incomplete unification without an error message here @@ -12272,7 +12350,7 @@ fn_type_unification (tree fn, callers must be ready to deal with unification failures in any event. */ result = type_unification_real (DECL_INNERMOST_TEMPLATE_PARMS (fn), - targs, parms, args, /*subr=*/0, + targs, parms, args, nargs, /*subr=*/0, strict, flags); if (result == 0 && incomplete_argument_packs_p) @@ -12337,14 +12415,14 @@ fn_type_unification (tree fn, parameters are used in non-deduced contexts. */ if (strict == DEDUCE_EXACT) { + unsigned int i; + tree sarg = skip_artificial_parms_for (fn, TYPE_ARG_TYPES (substed)); - tree arg = args; if (return_type) sarg = tree_cons (NULL_TREE, TREE_TYPE (substed), sarg); - for (; arg && sarg; - arg = TREE_CHAIN (arg), sarg = TREE_CHAIN (sarg)) - if (!same_type_p (TREE_VALUE (arg), TREE_VALUE (sarg))) + for (i = 0; i < nargs && sarg; ++i, sarg = TREE_CHAIN (sarg)) + if (!same_type_p (args[i], TREE_VALUE (sarg))) return 1; } } @@ -12459,7 +12537,8 @@ static int type_unification_real (tree tparms, tree targs, tree xparms, - tree xargs, + const tree *xargs, + unsigned int xnargs, int subr, unification_kind_t strict, int flags) @@ -12469,11 +12548,13 @@ type_unification_real (tree tparms, int ntparms = TREE_VEC_LENGTH (tparms); int sub_strict; int saw_undeduced = 0; - tree parms, args; + tree parms; + const tree *args; + unsigned int nargs; + unsigned int ia; gcc_assert (TREE_CODE (tparms) == TREE_VEC); gcc_assert (xparms == NULL_TREE || TREE_CODE (xparms) == TREE_LIST); - gcc_assert (!xargs || TREE_CODE (xargs) == TREE_LIST); gcc_assert (ntparms > 0); switch (strict) @@ -12498,17 +12579,19 @@ type_unification_real (tree tparms, again: parms = xparms; args = xargs; + nargs = xnargs; + ia = 0; while (parms && parms != void_list_node - && args && args != void_list_node) + && ia < nargs) { if (TREE_CODE (TREE_VALUE (parms)) == TYPE_PACK_EXPANSION) break; parm = TREE_VALUE (parms); parms = TREE_CHAIN (parms); - arg = TREE_VALUE (args); - args = TREE_CHAIN (args); + arg = args[ia]; + ++ia; arg_expr = NULL; if (arg == error_mark_node) @@ -12587,20 +12670,11 @@ type_unification_real (tree tparms, /* Unify the remaining arguments with the pack expansion type. */ tree argvec; tree parmvec = make_tree_vec (1); - int len = 0; - tree t; - /* Count the number of arguments that remain. */ - for (t = args; t && t != void_list_node; t = TREE_CHAIN (t)) - len++; - /* Allocate a TREE_VEC and copy in all of the arguments */ - argvec = make_tree_vec (len); - for (i = 0; args && args != void_list_node; args = TREE_CHAIN (args)) - { - TREE_VEC_ELT (argvec, i) = TREE_VALUE (args); - ++i; - } + argvec = make_tree_vec (nargs - ia); + for (i = 0; ia < nargs; ++ia, ++i) + TREE_VEC_ELT (argvec, i) = args[ia]; /* Copy the parameter into parmvec. */ TREE_VEC_ELT (parmvec, 0) = TREE_VALUE (parms); @@ -12614,7 +12688,7 @@ type_unification_real (tree tparms, /* Fail if we've reached the end of the parm list, and more args are present, and the parm list isn't variadic. */ - if (args && args != void_list_node && parms == void_list_node) + if (ia < nargs && parms == void_list_node) return 1; /* Fail if parms are left and they don't have default values. */ if (parms && parms != void_list_node @@ -13896,26 +13970,42 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict) case METHOD_TYPE: case FUNCTION_TYPE: - if (TREE_CODE (arg) != TREE_CODE (parm)) - return 1; + { + unsigned int nargs; + tree *args; + tree a; + unsigned int i; - /* CV qualifications for methods can never be deduced, they must - match exactly. We need to check them explicitly here, - because type_unification_real treats them as any other - cv-qualified parameter. */ - if (TREE_CODE (parm) == METHOD_TYPE - && (!check_cv_quals_for_unify - (UNIFY_ALLOW_NONE, - TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (arg))), - TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (parm)))))) - return 1; + if (TREE_CODE (arg) != TREE_CODE (parm)) + return 1; - if (unify (tparms, targs, TREE_TYPE (parm), - TREE_TYPE (arg), UNIFY_ALLOW_NONE)) - return 1; - return type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm), - TYPE_ARG_TYPES (arg), 1, DEDUCE_EXACT, - LOOKUP_NORMAL); + /* CV qualifications for methods can never be deduced, they must + match exactly. We need to check them explicitly here, + because type_unification_real treats them as any other + cv-qualified parameter. */ + if (TREE_CODE (parm) == METHOD_TYPE + && (!check_cv_quals_for_unify + (UNIFY_ALLOW_NONE, + TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (arg))), + TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (parm)))))) + return 1; + + if (unify (tparms, targs, TREE_TYPE (parm), + TREE_TYPE (arg), UNIFY_ALLOW_NONE)) + return 1; + + nargs = list_length (TYPE_ARG_TYPES (arg)); + args = XALLOCAVEC (tree, nargs); + for (a = TYPE_ARG_TYPES (arg), i = 0; + a != NULL_TREE && a != void_list_node; + a = TREE_CHAIN (a), ++i) + args[i] = TREE_VALUE (a); + nargs = i; + + return type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm), + args, nargs, 1, DEDUCE_EXACT, + LOOKUP_NORMAL); + } case OFFSET_TYPE: /* Unify a pointer to member with a pointer to member function, which @@ -14469,6 +14559,9 @@ get_bindings (tree fn, tree decl, tree explicit_args, bool check_rettype) tree targs = make_tree_vec (ntparms); tree decl_type; tree decl_arg_types; + tree *args; + unsigned int nargs, ix; + tree arg; /* Substitute the explicit template arguments into the type of DECL. The call to fn_type_unification will handle substitution into the @@ -14503,8 +14596,15 @@ get_bindings (tree fn, tree decl, tree explicit_args, bool check_rettype) decl_arg_types = skip_artificial_parms_for (decl, TYPE_ARG_TYPES (decl_type)); + nargs = list_length (decl_arg_types); + args = XALLOCAVEC (tree, nargs); + for (arg = decl_arg_types, ix = 0; + arg != NULL_TREE && arg != void_list_node; + arg = TREE_CHAIN (arg), ++ix) + args[ix] = TREE_VALUE (arg); + if (fn_type_unification (fn, explicit_args, targs, - decl_arg_types, + args, ix, (check_rettype || DECL_CONV_FN_P (fn) ? TREE_TYPE (decl_type) : NULL_TREE), DEDUCE_EXACT, LOOKUP_NORMAL)) @@ -16580,19 +16680,18 @@ type_dependent_expression_p_push (tree expr) return b; } -/* Returns TRUE if ARGS (a TREE_LIST of arguments to a function call) - contains a type-dependent expression. */ +/* Returns TRUE if ARGS contains a type-dependent expression. */ bool -any_type_dependent_arguments_p (const_tree args) +any_type_dependent_arguments_p (const VEC(tree,gc) *args) { - while (args) - { - tree arg = TREE_VALUE (args); + unsigned int i; + tree arg; + for (i = 0; VEC_iterate (tree, args, i, arg); ++i) + { if (type_dependent_expression_p (arg)) return true; - args = TREE_CHAIN (args); } return false; } @@ -17012,22 +17111,22 @@ build_non_dependent_expr (tree expr) return build1 (NON_DEPENDENT_EXPR, non_reference (TREE_TYPE (expr)), expr); } -/* ARGS is a TREE_LIST of expressions as arguments to a function call. - Return a new TREE_LIST with the various arguments replaced with - equivalent non-dependent expressions. */ +/* ARGS is a vector of expressions as arguments to a function call. + Replace the arguments with equivalent non-dependent expressions. + This modifies ARGS in place. */ -tree -build_non_dependent_args (tree args) +void +make_args_non_dependent (VEC(tree,gc) *args) { - tree a; - tree new_args; + unsigned int ix; + tree arg; - new_args = NULL_TREE; - for (a = args; a; a = TREE_CHAIN (a)) - new_args = tree_cons (NULL_TREE, - build_non_dependent_expr (TREE_VALUE (a)), - new_args); - return nreverse (new_args); + for (ix = 0; VEC_iterate (tree, args, ix, arg); ++ix) + { + tree newarg = build_non_dependent_expr (arg); + if (newarg != arg) + VEC_replace (tree, args, ix, newarg); + } } /* Returns a type which represents 'auto'. We use a TEMPLATE_TYPE_PARM @@ -17084,7 +17183,8 @@ listify_autos (tree type, tree auto_node) tree do_auto_deduction (tree type, tree init, tree auto_node) { - tree parms, args, tparms, targs; + tree parms, tparms, targs; + tree args[1]; int val; /* [dcl.spec.auto]: Obtain P from T by replacing the occurrences of auto @@ -17095,12 +17195,12 @@ do_auto_deduction (tree type, tree init, tree auto_node) type = listify_autos (type, auto_node); parms = build_tree_list (NULL_TREE, type); - args = build_tree_list (NULL_TREE, init); + args[0] = init; tparms = make_tree_vec (1); targs = make_tree_vec (1); TREE_VEC_ELT (tparms, 0) = build_tree_list (NULL_TREE, TYPE_NAME (auto_node)); - val = type_unification_real (tparms, targs, parms, args, 0, + val = type_unification_real (tparms, targs, parms, args, 1, 0, DEDUCE_CALL, LOOKUP_NORMAL); if (val > 0) { diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 18aa051..2b12448 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -1820,7 +1820,7 @@ stmt_expr_value_expr (tree stmt_expr) resolution. */ tree -perform_koenig_lookup (tree fn, tree args) +perform_koenig_lookup (tree fn, VEC(tree,gc) *args) { tree identifier = NULL_TREE; tree functions = NULL_TREE; @@ -1865,7 +1865,8 @@ perform_koenig_lookup (tree fn, tree args) return fn; } -/* Generate an expression for `FN (ARGS)'. +/* Generate an expression for `FN (ARGS)'. This may change the + contents of ARGS. If DISALLOW_VIRTUAL is true, the call to FN will be not generated as a virtual call, even if FN is virtual. (This flag is set when @@ -1876,29 +1877,26 @@ perform_koenig_lookup (tree fn, tree args) Returns code for the call. */ tree -finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p, - tsubst_flags_t complain) +finish_call_expr (tree fn, VEC(tree,gc) **args, bool disallow_virtual, + bool koenig_p, tsubst_flags_t complain) { tree result; tree orig_fn; - tree orig_args; + VEC(tree,gc) *orig_args = NULL; - if (fn == error_mark_node || args == error_mark_node) + if (fn == error_mark_node) return error_mark_node; - /* ARGS should be a list of arguments. */ - gcc_assert (!args || TREE_CODE (args) == TREE_LIST); gcc_assert (!TYPE_P (fn)); orig_fn = fn; - orig_args = args; if (processing_template_decl) { if (type_dependent_expression_p (fn) - || any_type_dependent_arguments_p (args)) + || any_type_dependent_arguments_p (*args)) { - result = build_nt_call_list (fn, args); + result = build_nt_call_vec (fn, *args); KOENIG_LOOKUP_P (result) = koenig_p; if (cfun) { @@ -1916,11 +1914,12 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p, } return result; } + orig_args = make_tree_vector_copy (*args); if (!BASELINK_P (fn) && TREE_CODE (fn) != PSEUDO_DTOR_EXPR && TREE_TYPE (fn) != unknown_type_node) fn = build_non_dependent_expr (fn); - args = build_non_dependent_args (orig_args); + make_args_non_dependent (*args); } if (is_overloaded_fn (fn)) @@ -1969,7 +1968,11 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p, if (processing_template_decl) { if (type_dependent_expression_p (object)) - return build_nt_call_list (orig_fn, orig_args); + { + tree ret = build_nt_call_vec (orig_fn, orig_args); + release_tree_vector (orig_args); + return ret; + } object = build_non_dependent_expr (object); } @@ -1985,15 +1988,7 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p, if (TREE_CODE (fn) == FUNCTION_DECL && (DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL || DECL_BUILT_IN_CLASS (fn) == BUILT_IN_MD)) - { - VEC(tree,gc)* vec = VEC_alloc (tree, gc, list_length (args)); - tree p; - - for (p = args; p != NULL_TREE; p = TREE_CHAIN (p)) - VEC_quick_push (tree, vec, TREE_VALUE (p)); - result = resolve_overloaded_builtin (fn, vec); - VEC_free (tree, gc, vec); - } + result = resolve_overloaded_builtin (fn, *args); if (!result) /* A call to a namespace-scope function. */ @@ -2001,7 +1996,7 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p, } else if (TREE_CODE (fn) == PSEUDO_DTOR_EXPR) { - if (args) + if (!VEC_empty (tree, *args)) error ("arguments to destructor are not allowed"); /* Mark the pseudo-destructor call as having side-effects so that we do not issue warnings about its use. */ @@ -2013,18 +2008,19 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p, else if (CLASS_TYPE_P (TREE_TYPE (fn))) /* If the "function" is really an object of class type, it might have an overloaded `operator ()'. */ - result = build_new_op (CALL_EXPR, LOOKUP_NORMAL, fn, args, NULL_TREE, - /*overloaded_p=*/NULL, complain); + result = build_op_call (fn, args, complain); if (!result) /* A call where the function is unknown. */ - result = cp_build_function_call (fn, args, complain); + result = cp_build_function_call_vec (fn, args, complain); if (processing_template_decl) { - result = build_call_list (TREE_TYPE (result), orig_fn, orig_args); + result = build_call_vec (TREE_TYPE (result), orig_fn, orig_args); KOENIG_LOOKUP_P (result) = koenig_p; + release_tree_vector (orig_args); } + return result; } @@ -3423,18 +3419,23 @@ cxx_omp_create_clause_info (tree c, tree type, bool need_default_ctor, if (need_default_ctor || (need_copy_ctor && !TYPE_HAS_TRIVIAL_INIT_REF (type))) { + VEC(tree,gc) *vec; + if (need_default_ctor) - t = NULL; + vec = NULL; else { t = build_int_cst (build_pointer_type (type), 0); t = build1 (INDIRECT_REF, type, t); - t = build_tree_list (NULL, t); + vec = make_tree_vector_single (t); } t = build_special_member_call (NULL_TREE, complete_ctor_identifier, - t, type, LOOKUP_NORMAL, + &vec, type, LOOKUP_NORMAL, tf_warning_or_error); + if (vec != NULL) + release_tree_vector (vec); + if (targetm.cxx.cdtor_returns_this () || errorcount) /* Because constructors and destructors return this, the call will have been cast to "void". Remove the @@ -3472,12 +3473,15 @@ cxx_omp_create_clause_info (tree c, tree type, bool need_default_ctor, if (need_copy_assignment && !TYPE_HAS_TRIVIAL_ASSIGN_REF (type)) { + VEC(tree,gc) *vec; + t = build_int_cst (build_pointer_type (type), 0); t = build1 (INDIRECT_REF, type, t); + vec = make_tree_vector_single (t); t = build_special_member_call (t, ansi_assopname (NOP_EXPR), - build_tree_list (NULL, t), - type, LOOKUP_NORMAL, + &vec, type, LOOKUP_NORMAL, tf_warning_or_error); + release_tree_vector (vec); /* We'll have called convert_from_reference on the call, which may well have added an indirect_ref. It's unneeded here, @@ -4433,7 +4437,9 @@ void finish_omp_barrier (void) { tree fn = built_in_decls[BUILT_IN_GOMP_BARRIER]; - tree stmt = finish_call_expr (fn, NULL, false, false, tf_warning_or_error); + VEC(tree,gc) *vec = make_tree_vector (); + tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error); + release_tree_vector (vec); finish_expr_stmt (stmt); } @@ -4441,7 +4447,9 @@ void finish_omp_flush (void) { tree fn = built_in_decls[BUILT_IN_SYNCHRONIZE]; - tree stmt = finish_call_expr (fn, NULL, false, false, tf_warning_or_error); + VEC(tree,gc) *vec = make_tree_vector (); + tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error); + release_tree_vector (vec); finish_expr_stmt (stmt); } @@ -4449,7 +4457,9 @@ void finish_omp_taskwait (void) { tree fn = built_in_decls[BUILT_IN_GOMP_TASKWAIT]; - tree stmt = finish_call_expr (fn, NULL, false, false, tf_warning_or_error); + VEC(tree,gc) *vec = make_tree_vector (); + tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error); + release_tree_vector (vec); finish_expr_stmt (stmt); } diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index f1868f5..8c51e0b 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -1719,9 +1719,9 @@ build_min_non_dep (enum tree_code code, tree non_dep, ...) built. */ tree -build_min_non_dep_call_list (tree non_dep, tree fn, tree arglist) +build_min_non_dep_call_vec (tree non_dep, tree fn, VEC(tree,gc) *argvec) { - tree t = build_nt_call_list (fn, arglist); + tree t = build_nt_call_vec (fn, argvec); TREE_TYPE (t) = TREE_TYPE (non_dep); TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (non_dep); return t; diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 87138bd..074d619 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -61,7 +61,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 int convert_arguments (int, tree *, tree, tree, tree, int, +static int convert_arguments (tree, VEC(tree,gc) **, tree, int, tsubst_flags_t); /* Do `exp = require_complete_type (exp);' to make sure exp @@ -2866,38 +2866,57 @@ tree build_function_call_vec (tree function, VEC(tree,gc) *params, VEC(tree,gc) *origtypes ATTRIBUTE_UNUSED) { - tree p; - tree *pp; - unsigned int i; - tree t; + VEC(tree,gc) *orig_params = params; + tree ret = cp_build_function_call_vec (function, ¶ms, + tf_warning_or_error); - /* FIXME: Should just change cp_build_function_call to use a - VEC. */ - p = NULL_TREE; - pp = &p; - for (i = 0; VEC_iterate (tree, params, i, t); ++i) - { - *pp = build_tree_list (NULL, t); - pp = &TREE_CHAIN (*pp); - } - return cp_build_function_call (function, p, tf_warning_or_error); + /* cp_build_function_call_vec can reallocate PARAMS by adding + default arguments. That should never happen here. Verify + that. */ + gcc_assert (params == orig_params); + + return ret; } +/* Build a function call using a tree list of arguments. */ + tree cp_build_function_call (tree function, tree params, tsubst_flags_t complain) { + VEC(tree,gc) *vec; + tree ret; + + vec = make_tree_vector (); + for (; params != NULL_TREE; params = TREE_CHAIN (params)) + VEC_safe_push (tree, gc, vec, TREE_VALUE (params)); + ret = cp_build_function_call_vec (function, &vec, complain); + release_tree_vector (vec); + return ret; +} + +/* Build a function call using a vector of arguments. PARAMS may be + NULL if there are no parameters. This changes the contents of + PARAMS. */ + +tree +cp_build_function_call_vec (tree function, VEC(tree,gc) **params, + tsubst_flags_t complain) +{ tree fntype, fndecl; tree name = NULL_TREE; int is_method; tree original = function; - int nargs, parm_types_len; + int nargs; tree *argarray; tree parm_types; + VEC(tree,gc) *allocated = NULL; + tree ret; /* For Objective-C, convert any calls via a cast to OBJC_TYPE_REF expressions, like those used for ObjC messenger dispatches. */ - if (params != NULL_TREE) - function = objc_rewrite_function_call (function, TREE_VALUE (params)); + if (params != NULL && !VEC_empty (tree, *params)) + function = objc_rewrite_function_call (function, + VEC_index (tree, *params, 0)); /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue. Strip such NOP_EXPRs, since FUNCTION is used in non-lvalue context. */ @@ -2957,57 +2976,55 @@ cp_build_function_call (tree function, tree params, tsubst_flags_t complain) 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. */ - nargs = convert_arguments (nargs, argarray, parm_types, - params, fndecl, LOOKUP_NORMAL, - complain); + if (params == NULL) + { + allocated = make_tree_vector (); + params = &allocated; + } + + nargs = convert_arguments (parm_types, params, fndecl, LOOKUP_NORMAL, + complain); if (nargs < 0) return error_mark_node; + argarray = VEC_address (tree, *params); + /* Check for errors in format strings and inappropriately null parameters. */ check_function_arguments (TYPE_ATTRIBUTES (fntype), nargs, argarray, parm_types); - return build_cxx_call (function, nargs, argarray); + ret = build_cxx_call (function, nargs, argarray); + + if (allocated != NULL) + release_tree_vector (allocated); + + return ret; } -/* Convert the actual parameter expressions in the list VALUES - to the types in the list TYPELIST. +/* Convert the actual parameter expressions in the list VALUES to the + types in the list TYPELIST. The converted expressions are stored + back in the VALUES vector. 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. Returns the actual number of arguments processed (which might be less - than NARGS), or -1 on error. - - VALUES is a chain of TREE_LIST nodes with the elements of the list - in the TREE_VALUE slots of those nodes. + than the length of the vector), or -1 on error. In C++, unspecified trailing parameters can be filled in with their default arguments, if such were specified. Do so here. */ static int -convert_arguments (int nargs, tree *argarray, - tree typelist, tree values, tree fndecl, int flags, - tsubst_flags_t complain) +convert_arguments (tree typelist, VEC(tree,gc) **values, tree fndecl, + int flags, tsubst_flags_t complain) { - tree typetail, valtail; + tree typetail; const char *called_thing = 0; - int i = 0; + unsigned int i; /* Argument passing is always copy-initialization. */ flags |= LOOKUP_ONLYCONVERTING; @@ -3026,12 +3043,12 @@ convert_arguments (int nargs, tree *argarray, called_thing = "function"; } - for (valtail = values, typetail = typelist; - valtail; - valtail = TREE_CHAIN (valtail), i++) + for (i = 0, typetail = typelist; + i < VEC_length (tree, *values); + i++) { tree type = typetail ? TREE_VALUE (typetail) : 0; - tree val = TREE_VALUE (valtail); + tree val = VEC_index (tree, *values, i); if (val == error_mark_node || type == error_mark_node) return -1; @@ -3100,7 +3117,7 @@ convert_arguments (int nargs, tree *argarray, if (parmval == error_mark_node) return -1; - argarray[i] = parmval; + VEC_replace (tree, *values, i, parmval); } else { @@ -3113,7 +3130,7 @@ convert_arguments (int nargs, tree *argarray, else val = convert_arg_to_ellipsis (val); - argarray[i] = val; + VEC_replace (tree, *values, i, val); } if (typetail) @@ -3142,7 +3159,7 @@ convert_arguments (int nargs, tree *argarray, if (parmval == error_mark_node) return -1; - argarray[i] = parmval; + VEC_safe_push (tree, gc, *values, parmval); typetail = TREE_CHAIN (typetail); /* ends with `...'. */ if (typetail == NULL_TREE) @@ -3166,8 +3183,7 @@ convert_arguments (int nargs, tree *argarray, } } - gcc_assert (i <= nargs); - return i; + return (int) i; } /* Build a binary-operation expression, after performing default @@ -4994,6 +5010,34 @@ tree build_x_compound_expr_from_list (tree list, const char *msg) return expr; } +/* Like build_x_compound_expr_from_list, but using a VEC. */ + +tree +build_x_compound_expr_from_vec (VEC(tree,gc) *vec, const char *msg) +{ + if (VEC_empty (tree, vec)) + return NULL_TREE; + else if (VEC_length (tree, vec) == 1) + return VEC_index (tree, vec, 0); + else + { + tree expr; + unsigned int ix; + tree t; + + if (msg != NULL) + permerror (input_location, + "%s expression list treated as compound expression", + msg); + + expr = VEC_index (tree, vec, 0); + for (ix = 1; VEC_iterate (tree, vec, ix, t); ++ix) + expr = build_x_compound_expr (expr, t, tf_warning_or_error); + + return expr; + } +} + /* Handle overloading of the ',' operator when needed. */ tree @@ -6038,10 +6082,11 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs, /* Do the default thing. */; else { + VEC(tree,gc) *rhs_vec = make_tree_vector_single (rhs); result = build_special_member_call (lhs, complete_ctor_identifier, - build_tree_list (NULL_TREE, rhs), - lhstype, LOOKUP_NORMAL, + &rhs_vec, lhstype, LOOKUP_NORMAL, complain); + release_tree_vector (rhs_vec); if (result == NULL_TREE) return error_mark_node; return result; diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 5783f67..e668427 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -1442,6 +1442,7 @@ build_functional_cast (tree exp, tree parms, tsubst_flags_t complain) /* The type to which we are casting. */ tree type; + VEC(tree,gc) *parmvec; if (exp == error_mark_node || parms == error_mark_node) return error_mark_node; @@ -1512,8 +1513,12 @@ build_functional_cast (tree exp, tree parms, tsubst_flags_t complain) } /* Call the constructor. */ - exp = build_special_member_call (NULL_TREE, complete_ctor_identifier, parms, - type, LOOKUP_NORMAL, complain); + parmvec = make_tree_vector (); + for (; parms != NULL_TREE; parms = TREE_CHAIN (parms)) + VEC_safe_push (tree, gc, parmvec, TREE_VALUE (parms)); + exp = build_special_member_call (NULL_TREE, complete_ctor_identifier, + &parmvec, type, LOOKUP_NORMAL, complain); + release_tree_vector (parmvec); if (exp == error_mark_node) return error_mark_node; diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog index a1f0f24..f65fa96 100644 --- a/gcc/objc/ChangeLog +++ b/gcc/objc/ChangeLog @@ -1,3 +1,8 @@ +2009-05-20 Ian Lance Taylor <iant@google.com> + + * objc-act.c (objc_generate_cxx_ctor_or_dtor): Pass NULL rather + than NULL_TREE to build_special_member_call. + 2009-05-10 Ian Lance Taylor <iant@google.com> * objc-act.c (objc_building_struct): New static variable. diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index 9bf7d3f..d4624bb 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -4538,7 +4538,7 @@ objc_generate_cxx_ctor_or_dtor (bool dtor) (build_special_member_call (build_ivar_reference (DECL_NAME (ivar)), dtor ? complete_dtor_identifier : complete_ctor_identifier, - NULL_TREE, type, LOOKUP_NORMAL, tf_warning_or_error)); + NULL, type, LOOKUP_NORMAL, tf_warning_or_error)); } } @@ -1827,6 +1827,23 @@ build_tree_list_stat (tree parm, tree value MEM_STAT_DECL) return t; } +/* Build a chain of TREE_LIST nodes from a vector. */ + +tree +build_tree_list_vec_stat (const VEC(tree,gc) *vec MEM_STAT_DECL) +{ + tree ret = NULL_TREE; + tree *pp = &ret; + unsigned int i; + tree t; + for (i = 0; VEC_iterate (tree, vec, i, t); ++i) + { + *pp = build_tree_list_stat (NULL, t PASS_MEM_STAT); + pp = &TREE_CHAIN (*pp); + } + return ret; +} + /* Return a newly created TREE_LIST node whose purpose and value fields are PURPOSE and VALUE and whose TREE_CHAIN is CHAIN. */ @@ -1870,6 +1887,22 @@ ctor_to_list (tree ctor) return list; } + +/* Return the values of the elements of a CONSTRUCTOR as a vector of + trees. */ + +VEC(tree,gc) * +ctor_to_vec (tree ctor) +{ + VEC(tree, gc) *vec = VEC_alloc (tree, gc, CONSTRUCTOR_NELTS (ctor)); + unsigned int ix; + tree val; + + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (ctor), ix, val) + VEC_quick_push (tree, vec, val); + + return vec; +} /* Return the size nominally occupied by an object of type TYPE when it resides in memory. The value is measured in units of bytes, @@ -3483,6 +3516,23 @@ build_nt_call_list (tree fn, tree arglist) CALL_EXPR_ARG (t, i) = TREE_VALUE (arglist); return t; } + +/* Similar to build_nt, but for creating a CALL_EXPR object with a + tree VEC. */ + +tree +build_nt_call_vec (tree fn, VEC(tree,gc) *args) +{ + tree ret, t; + unsigned int ix; + + ret = build_vl_exp (CALL_EXPR, VEC_length (tree, args) + 3); + CALL_EXPR_FN (ret) = fn; + CALL_EXPR_STATIC_CHAIN (ret) = NULL_TREE; + for (ix = 0; VEC_iterate (tree, args, ix, t); ++ix) + CALL_EXPR_ARG (ret, ix) = t; + return ret; +} /* Create a DECL_... node of code CODE, name NAME and data type TYPE. We do NOT enter this node in any sort of symbol table. @@ -8240,7 +8290,7 @@ build_call_valist (tree return_type, tree fn, int nargs, va_list args) which are specified as a tree array ARGS. */ tree -build_call_array (tree return_type, tree fn, int nargs, tree *args) +build_call_array (tree return_type, tree fn, int nargs, const tree *args) { tree t; int i; @@ -8255,6 +8305,24 @@ build_call_array (tree return_type, tree fn, int nargs, tree *args) return t; } +/* Like build_call_array, but takes a VEC. */ + +tree +build_call_vec (tree return_type, tree fn, VEC(tree,gc) *args) +{ + tree ret, t; + unsigned int ix; + + ret = build_vl_exp (CALL_EXPR, VEC_length (tree, args) + 3); + TREE_TYPE (ret) = return_type; + CALL_EXPR_FN (ret) = fn; + CALL_EXPR_STATIC_CHAIN (ret) = NULL_TREE; + for (ix = 0; VEC_iterate (tree, args, ix, t); ++ix) + CALL_EXPR_ARG (ret, ix) = t; + process_call_operands (ret); + return ret; +} + /* Returns true if it is possible to prove that the index of an array access REF (an ARRAY_REF expression) falls into the @@ -3833,6 +3833,7 @@ extern tree maybe_get_identifier (const char *); extern tree build_nt (enum tree_code, ...); extern tree build_nt_call_list (tree, tree); +extern tree build_nt_call_vec (tree, VEC(tree,gc) *); extern tree build0_stat (enum tree_code, tree MEM_STAT_DECL); #define build0(c,t) build0_stat (c,t MEM_STAT_INFO) @@ -3870,6 +3871,8 @@ extern tree build_one_cst (tree); extern tree build_string (int, const char *); extern tree build_tree_list_stat (tree, tree MEM_STAT_DECL); #define build_tree_list(t,q) build_tree_list_stat(t,q MEM_STAT_INFO) +extern tree build_tree_list_vec_stat (const VEC(tree,gc) * MEM_STAT_DECL); +#define build_tree_list_vec(v) build_tree_list_vec_stat (v MEM_STAT_INFO) extern tree build_decl_stat (enum tree_code, tree, tree MEM_STAT_DECL); extern tree build_fn_decl (const char *, tree); #define build_decl(c,t,q) build_decl_stat (c,t,q MEM_STAT_INFO) @@ -3883,7 +3886,8 @@ extern tree build_vl_exp_stat (enum tree_code, int MEM_STAT_DECL); extern tree build_call_list (tree, tree, tree); extern tree build_call_nary (tree, tree, int, ...); extern tree build_call_valist (tree, tree, int, va_list); -extern tree build_call_array (tree, tree, int, tree*); +extern tree build_call_array (tree, tree, int, const tree *); +extern tree build_call_vec (tree, tree, VEC(tree,gc) *); /* Construct various nodes representing data types. */ @@ -4310,6 +4314,10 @@ extern bool initializer_zerop (const_tree); extern tree ctor_to_list (tree); +/* Given a CONSTRUCTOR CTOR, return the element values as a vector. */ + +extern VEC(tree,gc) *ctor_to_vec (tree); + /* Examine CTOR to discover: * how many scalar fields are set to nonzero values, and place it in *P_NZ_ELTS; |