summaryrefslogtreecommitdiff
path: root/gcc/cp/init.c
diff options
context:
space:
mode:
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2009-05-21 05:58:39 +0000
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2009-05-21 05:58:39 +0000
commitf352a3fbf2100b1b9954e0132b6e5b9644956c56 (patch)
treea25b2f396979fd0a56ba8a76180aba734398019a /gcc/cp/init.c
parent2b3c93a3f3c56cb6a495f4b94d4ca09ac6f7c531 (diff)
downloadgcc-f352a3fbf2100b1b9954e0132b6e5b9644956c56.tar.gz
./:
* 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. cp/: * 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. objc/: * objc-act.c (objc_generate_cxx_ctor_or_dtor): Pass NULL rather than NULL_TREE to build_special_member_call. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@147759 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp/init.c')
-rw-r--r--gcc/cp/init.c191
1 files changed, 109 insertions, 82 deletions
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 5fa5eb84b27..fd0d587b81f 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);