aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/init.c')
-rw-r--r--gcc/cp/init.c106
1 files changed, 64 insertions, 42 deletions
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 39d4c57047e..9f55b7b2292 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -1,6 +1,6 @@
/* Handle initialization things in C++.
Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -47,7 +47,7 @@ static tree initializing_context PARAMS ((tree));
static void expand_cleanup_for_base PARAMS ((tree, tree));
static tree get_temp_regvar PARAMS ((tree, tree));
static tree dfs_initialize_vtbl_ptrs PARAMS ((tree, void *));
-static tree build_default_init PARAMS ((tree));
+static tree build_default_init PARAMS ((tree, tree));
static tree build_new_1 PARAMS ((tree));
static tree get_cookie_size PARAMS ((tree));
static tree build_dtor_call PARAMS ((tree, special_function_kind, int));
@@ -145,7 +145,7 @@ initialize_vtbl_ptrs (addr)
list = build_tree_list (type, addr);
/* Walk through the hierarchy, initializing the vptr in each base
- class. We do these in pre-order because can't find the virtual
+ class. We do these in pre-order because we can't find the virtual
bases for a class until we've initialized the vtbl for that
class. */
dfs_walk_real (TYPE_BINFO (type), dfs_initialize_vtbl_ptrs,
@@ -159,12 +159,14 @@ initialize_vtbl_ptrs (addr)
that T is a scalar), or a CONSTRUCTOR (in the case that T is an
aggregate). In either case, the value can be used as DECL_INITIAL
for a decl of the indicated TYPE; it is a valid static initializer.
- If STATIC_STORAGE_P is TRUE, initializers are only generated for
- entities for which zero-initialization does not simply mean filling
- the storage with zero bytes. */
+ If NELTS is non-NULL, and TYPE is an ARRAY_TYPE, NELTS is the
+ number of elements in the array. If STATIC_STORAGE_P is TRUE,
+ initializers are only generated for entities for which
+ zero-initialization does not simply mean filling the storage with
+ zero bytes. */
tree
-build_zero_init (tree type, bool static_storage_p)
+build_zero_init (tree type, tree nelts, bool static_storage_p)
{
tree init = NULL_TREE;
@@ -217,6 +219,7 @@ build_zero_init (tree type, bool static_storage_p)
if (static_storage_p && !zero_init_p (TREE_TYPE (field)))
inits = tree_cons (field,
build_zero_init (TREE_TYPE (field),
+ /*nelts=*/NULL_TREE,
static_storage_p),
inits);
@@ -236,11 +239,13 @@ build_zero_init (tree type, bool static_storage_p)
init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
/* Iterate over the array elements, building initializations. */
inits = NULL_TREE;
- for (index = size_zero_node, max_index = array_type_nelts (type);
+ max_index = nelts ? nelts : array_type_nelts (type);
+ for (index = size_zero_node;
!tree_int_cst_lt (max_index, index);
index = size_binop (PLUS_EXPR, index, size_one_node))
inits = tree_cons (index,
- build_zero_init (TREE_TYPE (type),
+ build_zero_init (TREE_TYPE (type),
+ /*nelts=*/NULL_TREE,
static_storage_p),
inits);
CONSTRUCTOR_ELTS (init) = nreverse (inits);
@@ -257,14 +262,17 @@ build_zero_init (tree type, bool static_storage_p)
return init;
}
-/* Build an expression for the default-initialization of an object
- with type T. If initialization T requires calling constructors,
- this function returns NULL_TREE; the caller is responsible for
- arranging for the constructors to be called. */
+/* Build an expression for the default-initialization of an object of
+ the indicated TYPE. If NELTS is non-NULL, and TYPE is an
+ ARRAY_TYPE, NELTS is the number of elements in the array. If
+ initialization of TYPE requires calling constructors, this function
+ returns NULL_TREE; the caller is responsible for arranging for the
+ constructors to be called. */
static tree
-build_default_init (type)
+build_default_init (type, nelts)
tree type;
+ tree nelts;
{
/* [dcl.init]:
@@ -298,7 +306,7 @@ build_default_init (type)
/* At this point, TYPE is either a POD class type, an array of POD
classes, or something even more inoccuous. */
- return build_zero_init (type, /*static_storage_p=*/false);
+ return build_zero_init (type, nelts, /*static_storage_p=*/false);
}
/* Initialize MEMBER, a FIELD_DECL, with INIT, a TREE_LIST of
@@ -352,7 +360,8 @@ perform_member_init (tree member, tree init)
&& TREE_CODE (TREE_TYPE (TREE_VALUE (init))) == ARRAY_TYPE)
{
/* Initialization of one array from another. */
- finish_expr_stmt (build_vec_init (decl, TREE_VALUE (init), 1));
+ finish_expr_stmt (build_vec_init (decl, NULL_TREE, TREE_VALUE (init),
+ /* from_array=*/1));
}
else
finish_expr_stmt (build_aggr_init (decl, init, 0));
@@ -363,7 +372,7 @@ perform_member_init (tree member, tree init)
{
if (explicit)
{
- init = build_default_init (type);
+ init = build_default_init (type, /*nelts=*/NULL_TREE);
if (TREE_CODE (type) == REFERENCE_TYPE)
warning
("default-initialization of `%#D', which has reference type",
@@ -655,6 +664,8 @@ emit_mem_initializers (tree mem_inits)
initializations should be performed. */
mem_inits = sort_mem_initializers (current_class_type, mem_inits);
+ in_base_initializer = 1;
+
/* Initialize base classes. */
while (mem_inits
&& TREE_CODE (TREE_PURPOSE (mem_inits)) != FIELD_DECL)
@@ -695,10 +706,11 @@ emit_mem_initializers (tree mem_inits)
mem_inits = TREE_CHAIN (mem_inits);
}
+ in_base_initializer = 0;
/* Initialize the vptrs. */
initialize_vtbl_ptrs (current_class_ptr);
-
+
/* Initialize the data members. */
while (mem_inits)
{
@@ -929,16 +941,15 @@ member_init_ok_or_else (field, type, member_name)
/* NAME is a FIELD_DECL, an IDENTIFIER_NODE which names a field, or it
is a _TYPE node or TYPE_DECL which names a base for that type.
- INIT is a parameter list for that field's or base's constructor.
- Check the validity of NAME, and return a TREE_LIST of the base
- _TYPE or FIELD_DECL and the INIT. If NAME is invalid, return
+ Check the validity of NAME, and return either the base _TYPE, base
+ binfo, or the FIELD_DECL of the member. If NAME is invalid, return
NULL_TREE and issue a diagnostic.
An old style unnamed direct single base construction is permitted,
where NAME is NULL. */
tree
-expand_member_init (tree name, tree init)
+expand_member_init (tree name)
{
tree basetype;
tree field;
@@ -975,14 +986,12 @@ expand_member_init (tree name, tree init)
else
basetype = NULL_TREE;
- my_friendly_assert (init != NULL_TREE, 0);
-
if (basetype)
{
tree binfo;
if (current_template_parms)
- return build_tree_list (basetype, init);
+ return basetype;
binfo = lookup_base (current_class_type, basetype,
ba_ignore, NULL);
@@ -1006,7 +1015,7 @@ expand_member_init (tree name, tree init)
}
if (binfo)
- return build_tree_list (binfo, init);
+ return binfo;
}
else
{
@@ -1016,7 +1025,7 @@ expand_member_init (tree name, tree init)
field = name;
if (member_init_ok_or_else (field, current_class_type, name))
- return build_tree_list (field, init);
+ return field;
}
return NULL_TREE;
@@ -1101,7 +1110,7 @@ build_aggr_init (exp, init, flags)
TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type);
if (itype && cp_type_quals (itype) != TYPE_UNQUALIFIED)
TREE_TYPE (init) = TYPE_MAIN_VARIANT (itype);
- stmt_expr = build_vec_init (exp, init,
+ stmt_expr = build_vec_init (exp, NULL_TREE, init,
init && same_type_p (TREE_TYPE (init),
TREE_TYPE (exp)));
TREE_READONLY (exp) = was_const;
@@ -1599,7 +1608,7 @@ build_offset_ref (type, name)
decl = maybe_dummy_object (type, &basebinfo);
- if (BASELINK_P (name))
+ if (BASELINK_P (name) || DECL_P (name))
member = name;
else
{
@@ -2138,6 +2147,7 @@ build_new_1 (exp)
tree placement, init;
tree type, true_type, size, rval, t;
tree full_type;
+ tree outer_nelts = NULL_TREE;
tree nelts = NULL_TREE;
tree alloc_call, alloc_expr, alloc_node;
tree alloc_fn;
@@ -2167,12 +2177,11 @@ build_new_1 (exp)
if (TREE_CODE (type) == ARRAY_REF)
{
has_array = 1;
- nelts = TREE_OPERAND (type, 1);
+ nelts = outer_nelts = TREE_OPERAND (type, 1);
type = TREE_OPERAND (type, 0);
- full_type = cp_build_binary_op (MINUS_EXPR, nelts, integer_one_node);
- full_type = build_index_type (full_type);
- full_type = build_cplus_array_type (type, full_type);
+ /* Use an incomplete array type to avoid VLA headaches. */
+ full_type = build_cplus_array_type (type, NULL_TREE);
}
else
full_type = type;
@@ -2357,12 +2366,16 @@ build_new_1 (exp)
init_expr = build_indirect_ref (alloc_node, NULL);
if (init == void_zero_node)
- init = build_default_init (full_type);
+ init = build_default_init (full_type, nelts);
else if (init && pedantic && has_array)
pedwarn ("ISO C++ forbids initialization in array new");
if (has_array)
- init_expr = build_vec_init (init_expr, init, 0);
+ init_expr
+ = build_vec_init (init_expr,
+ cp_build_binary_op (MINUS_EXPR, outer_nelts,
+ integer_one_node),
+ init, /*from_array=*/0);
else if (TYPE_NEEDS_CONSTRUCTING (type))
init_expr = build_special_member_call (init_expr,
complete_ctor_identifier,
@@ -2490,8 +2503,12 @@ build_new_1 (exp)
{
if (check_new)
{
- tree ifexp = cp_build_binary_op (NE_EXPR, alloc_node,
- integer_zero_node);
+ tree nullexp;
+ tree ifexp;
+
+ nullexp = convert (TREE_TYPE (alloc_node),
+ use_cookie ? cookie_size : size_zero_node);
+ ifexp = cp_build_binary_op (NE_EXPR, alloc_node, nullexp);
rval = build_conditional_expr (ifexp, rval, alloc_node);
}
@@ -2686,6 +2703,9 @@ get_temp_regvar (type, init)
initialization of a vector of aggregate types.
BASE is a reference to the vector, of ARRAY_TYPE.
+ MAXINDEX is the maximum index of the array (one less than the
+ number of elements). It is only used if
+ TYPE_DOMAIN (TREE_TYPE (BASE)) == NULL_TREE.
INIT is the (possibly NULL) initializer.
FROM_ARRAY is 0 if we should init everything with INIT
@@ -2696,8 +2716,8 @@ get_temp_regvar (type, init)
but use assignment instead of initialization. */
tree
-build_vec_init (base, init, from_array)
- tree base, init;
+build_vec_init (base, maxindex, init, from_array)
+ tree base, init, maxindex;
int from_array;
{
tree rval;
@@ -2717,9 +2737,11 @@ build_vec_init (base, init, from_array)
tree try_block = NULL_TREE;
tree try_body = NULL_TREE;
int num_initialized_elts = 0;
- tree maxindex = array_type_nelts (TREE_TYPE (base));
- if (maxindex == error_mark_node)
+ if (TYPE_DOMAIN (atype))
+ maxindex = array_type_nelts (atype);
+
+ if (maxindex == NULL_TREE || maxindex == error_mark_node)
return error_mark_node;
if (init
@@ -2909,7 +2931,7 @@ build_vec_init (base, init, from_array)
sorry
("cannot initialize multi-dimensional array with initializer");
elt_init = build_vec_init (build1 (INDIRECT_REF, type, base),
- 0, 0);
+ 0, 0, 0);
}
else
elt_init = build_aggr_init (build1 (INDIRECT_REF, type, base),