Commit f30efcb7 by Jason Merrill Committed by Jason Merrill

init.c (build_default_init): New fn.

        * init.c (build_default_init): New fn.
        (perform_member_init): Split out from here.
        (build_new_1): Use it.  Simplify initialization logic.
        (build_vec_init): Take an array, rather than a pointer and maxindex.
        Speed up simple initializations.  Don't clean up if we're assigning.
        * cp-tree.h: Adjust.
        * decl2.c (do_static_initialization): Remove TREE_VEC case.
        * parse.y (new_initializer): Return void_zero_node for ().
        * typeck.c (build_modify_expr): Handle getting a CONSTRUCTOR.
        * typeck2.c (digest_init): Only complain about user-written
        CONSTRUCTORs.

From-SVN: r38643
parent a412bf75
2001-01-03 Jason Merrill <jason@redhat.com>
* init.c (build_default_init): New fn.
(perform_member_init): Split out from here.
(build_new_1): Use it. Simplify initialization logic.
(build_vec_init): Take an array, rather than a pointer and maxindex.
Speed up simple initializations. Don't clean up if we're assigning.
* cp-tree.h: Adjust.
* decl2.c (do_static_initialization): Remove TREE_VEC case.
* parse.y (new_initializer): Return void_zero_node for ().
* typeck.c (build_modify_expr): Handle getting a CONSTRUCTOR.
* typeck2.c (digest_init): Only complain about user-written
CONSTRUCTORs.
2000-12-22 Mike Stump <mrs@wrs.com> 2000-12-22 Mike Stump <mrs@wrs.com>
* decl2.c: (max_tinst_depth): Increase to 50. * decl2.c: (max_tinst_depth): Increase to 50.
......
...@@ -4047,7 +4047,7 @@ extern tree build_member_call PARAMS ((tree, tree, tree)); ...@@ -4047,7 +4047,7 @@ extern tree build_member_call PARAMS ((tree, tree, tree));
extern tree build_offset_ref PARAMS ((tree, tree)); extern tree build_offset_ref PARAMS ((tree, tree));
extern tree resolve_offset_ref PARAMS ((tree)); extern tree resolve_offset_ref PARAMS ((tree));
extern tree build_new PARAMS ((tree, tree, tree, int)); extern tree build_new PARAMS ((tree, tree, tree, int));
extern tree build_vec_init PARAMS ((tree, tree, tree, tree, int)); extern tree build_vec_init PARAMS ((tree, tree, int));
extern tree build_x_delete PARAMS ((tree, int, tree)); extern tree build_x_delete PARAMS ((tree, int, tree));
extern tree build_delete PARAMS ((tree, tree, special_function_kind, int, int)); extern tree build_delete PARAMS ((tree, tree, special_function_kind, int, int));
extern tree build_vbase_delete PARAMS ((tree, tree)); extern tree build_vbase_delete PARAMS ((tree, tree));
......
...@@ -3394,10 +3394,6 @@ do_static_initialization (decl, init) ...@@ -3394,10 +3394,6 @@ do_static_initialization (decl, init)
if (IS_AGGR_TYPE (TREE_TYPE (decl)) if (IS_AGGR_TYPE (TREE_TYPE (decl))
|| TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE) || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
expr = build_aggr_init (decl, init, 0); expr = build_aggr_init (decl, init, 0);
else if (TREE_CODE (init) == TREE_VEC)
expr = build_vec_init (decl, TREE_VEC_ELT (init, 0),
TREE_VEC_ELT (init, 1),
TREE_VEC_ELT (init, 2), 0);
else else
{ {
expr = build (INIT_EXPR, TREE_TYPE (decl), decl, init); expr = build (INIT_EXPR, TREE_TYPE (decl), decl, init);
......
...@@ -49,6 +49,7 @@ static tree initializing_context PARAMS ((tree)); ...@@ -49,6 +49,7 @@ static tree initializing_context PARAMS ((tree));
static void expand_cleanup_for_base PARAMS ((tree, tree)); static void expand_cleanup_for_base PARAMS ((tree, tree));
static tree get_temp_regvar PARAMS ((tree, tree)); static tree get_temp_regvar PARAMS ((tree, tree));
static tree dfs_initialize_vtbl_ptrs PARAMS ((tree, void *)); static tree dfs_initialize_vtbl_ptrs PARAMS ((tree, void *));
static tree build_default_init PARAMS ((tree));
static tree build_new_1 PARAMS ((tree)); static tree build_new_1 PARAMS ((tree));
static tree get_cookie_size PARAMS ((tree)); static tree get_cookie_size PARAMS ((tree));
static tree build_dtor_call PARAMS ((tree, special_function_kind, int)); static tree build_dtor_call PARAMS ((tree, special_function_kind, int));
...@@ -193,6 +194,50 @@ initialize_vtbl_ptrs (addr) ...@@ -193,6 +194,50 @@ initialize_vtbl_ptrs (addr)
fixup_all_virtual_upcast_offsets (addr); fixup_all_virtual_upcast_offsets (addr);
} }
/* [dcl.init]:
To default-initialize an object of type T means:
--if T is a non-POD class type (clause _class_), the default construc-
tor for T is called (and the initialization is ill-formed if T has
no accessible default constructor);
--if T is an array type, each element is default-initialized;
--otherwise, the storage for the object is zero-initialized.
A program that calls for default-initialization of an entity of refer-
ence type is ill-formed. */
static tree
build_default_init (type)
tree type;
{
tree init = NULL_TREE;
if (TYPE_NEEDS_CONSTRUCTING (type))
/* Other code will handle running the default constructor. We can't do
anything with a CONSTRUCTOR for arrays here, as that would imply
copy-initialization. */
return NULL_TREE;
else if (AGGREGATE_TYPE_P (type))
{
/* This is a default initialization of an aggregate, but not one of
non-POD class type. We cleverly notice that the initialization
rules in such a case are the same as for initialization with an
empty brace-initialization list. */
init = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, NULL_TREE);
}
else if (TREE_CODE (type) == REFERENCE_TYPE)
/* --if T is a reference type, no initialization is performed. */
return NULL_TREE;
else
init = integer_zero_node;
init = digest_init (type, init, 0);
return init;
}
/* Subroutine of emit_base_init. */ /* Subroutine of emit_base_init. */
static void static void
...@@ -234,9 +279,7 @@ perform_member_init (member, init, explicit) ...@@ -234,9 +279,7 @@ perform_member_init (member, init, explicit)
&& TREE_CODE (TREE_TYPE (TREE_VALUE (init))) == ARRAY_TYPE) && TREE_CODE (TREE_TYPE (TREE_VALUE (init))) == ARRAY_TYPE)
{ {
/* Initialization of one array from another. */ /* Initialization of one array from another. */
finish_expr_stmt finish_expr_stmt (build_vec_init (decl, TREE_VALUE (init), 1));
(build_vec_init (TREE_OPERAND (decl, 1), decl,
array_type_nelts (type), TREE_VALUE (init), 1));
} }
else else
finish_expr_stmt (build_aggr_init (decl, init, 0)); finish_expr_stmt (build_aggr_init (decl, init, 0));
...@@ -247,28 +290,14 @@ perform_member_init (member, init, explicit) ...@@ -247,28 +290,14 @@ perform_member_init (member, init, explicit)
{ {
if (explicit) if (explicit)
{ {
/* default-initialization. */ init = build_default_init (type);
if (AGGREGATE_TYPE_P (type)) if (TREE_CODE (type) == REFERENCE_TYPE)
{ cp_warning
/* This is a default initialization of an aggregate, ("default-initialization of `%#D', which has reference type",
but not one of non-POD class type. We cleverly member);
notice that the initialization rules in such a
case are the same as for initialization with an
empty brace-initialization list. We don't want
to call build_modify_expr as that will go looking
for constructors and such. */
tree e = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
TREE_SIDE_EFFECTS (e) = 1;
finish_expr_stmt (build (INIT_EXPR, type, decl, e));
}
else if (TREE_CODE (type) == REFERENCE_TYPE)
cp_error ("default-initialization of `%#D', which has reference type",
member);
else
init = integer_zero_node;
} }
/* member traversal: note it leaves init NULL */ /* member traversal: note it leaves init NULL */
else if (TREE_CODE (TREE_TYPE (member)) == REFERENCE_TYPE) else if (TREE_CODE (type) == REFERENCE_TYPE)
cp_pedwarn ("uninitialized reference member `%D'", member); cp_pedwarn ("uninitialized reference member `%D'", member);
} }
else if (TREE_CODE (init) == TREE_LIST) else if (TREE_CODE (init) == TREE_LIST)
...@@ -1212,7 +1241,7 @@ build_aggr_init (exp, init, flags) ...@@ -1212,7 +1241,7 @@ build_aggr_init (exp, init, flags)
if (init) if (init)
TREE_TYPE (init) = TYPE_MAIN_VARIANT (itype); TREE_TYPE (init) = TYPE_MAIN_VARIANT (itype);
} }
stmt_expr = build_vec_init (exp, exp, array_type_nelts (type), init, stmt_expr = build_vec_init (exp, init,
init && same_type_p (TREE_TYPE (init), init && same_type_p (TREE_TYPE (init),
TREE_TYPE (exp))); TREE_TYPE (exp)));
TREE_READONLY (exp) = was_const; TREE_READONLY (exp) = was_const;
...@@ -2237,6 +2266,7 @@ build_new_1 (exp) ...@@ -2237,6 +2266,7 @@ build_new_1 (exp)
{ {
tree placement, init; tree placement, init;
tree type, true_type, size, rval, t; tree type, true_type, size, rval, t;
tree full_type;
tree nelts = NULL_TREE; tree nelts = NULL_TREE;
tree alloc_call, alloc_expr, alloc_node; tree alloc_call, alloc_expr, alloc_node;
tree cookie_expr, init_expr; tree cookie_expr, init_expr;
...@@ -2264,7 +2294,14 @@ build_new_1 (exp) ...@@ -2264,7 +2294,14 @@ build_new_1 (exp)
has_array = 1; has_array = 1;
nelts = TREE_OPERAND (type, 1); nelts = TREE_OPERAND (type, 1);
type = TREE_OPERAND (type, 0); 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);
} }
else
full_type = type;
true_type = type; true_type = type;
code = has_array ? VEC_NEW_EXPR : NEW_EXPR; code = has_array ? VEC_NEW_EXPR : NEW_EXPR;
...@@ -2395,7 +2432,10 @@ build_new_1 (exp) ...@@ -2395,7 +2432,10 @@ build_new_1 (exp)
/* Adjust so we're pointing to the start of the object. */ /* Adjust so we're pointing to the start of the object. */
alloc_expr = build (PLUS_EXPR, TREE_TYPE (alloc_expr), alloc_expr = build (PLUS_EXPR, TREE_TYPE (alloc_expr),
alloc_expr, cookie_size); alloc_expr, cookie_size);
alloc_expr = convert (build_pointer_type (type), alloc_expr);
/* While we're working, use a pointer to the type we've actually
allocated. */
alloc_expr = convert (build_pointer_type (full_type), alloc_expr);
/* Now save the allocation expression so we only evaluate it once. */ /* Now save the allocation expression so we only evaluate it once. */
alloc_expr = get_target_expr (alloc_expr); alloc_expr = get_target_expr (alloc_expr);
...@@ -2434,66 +2474,40 @@ build_new_1 (exp) ...@@ -2434,66 +2474,40 @@ build_new_1 (exp)
init_expr = NULL_TREE; init_expr = NULL_TREE;
if (TYPE_NEEDS_CONSTRUCTING (type) || init) if (TYPE_NEEDS_CONSTRUCTING (type) || init)
{ {
if (! TYPE_NEEDS_CONSTRUCTING (type) init_expr = build_indirect_ref (alloc_node, NULL_PTR);
&& ! IS_AGGR_TYPE (type) && ! has_array)
if (init == void_zero_node)
init = build_default_init (full_type);
else if (init && pedantic && has_array)
cp_pedwarn ("ISO C++ forbids initialization in array new");
if (has_array)
init_expr = build_vec_init (init_expr, init, 0);
else if (TYPE_NEEDS_CONSTRUCTING (type))
init_expr = build_method_call (init_expr,
complete_ctor_identifier,
init, TYPE_BINFO (true_type),
LOOKUP_NORMAL);
else
{ {
/* We are processing something like `new int (10)', which /* We are processing something like `new int (10)', which
means allocate an int, and initialize it with 10. */ means allocate an int, and initialize it with 10. */
tree deref;
tree deref_type; if (TREE_CODE (init) == TREE_LIST)
deref = build_indirect_ref (alloc_node, NULL_PTR);
/* Even for something like `new const int (10)' we must
allow the expression to be non-const while we do the
initialization. */
deref_type = TREE_TYPE (deref);
if (CP_TYPE_CONST_P (deref_type))
TREE_TYPE (deref)
= cp_build_qualified_type (deref_type,
CP_TYPE_QUALS (deref_type)
& ~TYPE_QUAL_CONST);
TREE_READONLY (deref) = 0;
if (TREE_CHAIN (init) != NULL_TREE)
pedwarn
("initializer list being treated as compound expression");
else if (TREE_CODE (init) == CONSTRUCTOR)
{ {
pedwarn if (TREE_CHAIN (init) != NULL_TREE)
("initializer list appears where operand should be used"); pedwarn
init = TREE_OPERAND (init, 1); ("initializer list being treated as compound expression");
init = build_compound_expr (init);
}
else if (TREE_CODE (init) == CONSTRUCTOR
&& TREE_TYPE (init) == NULL_TREE)
{
pedwarn ("ISO C++ forbids aggregate initializer to new");
init = digest_init (type, init, 0);
} }
init = build_compound_expr (init);
init = convert_for_initialization (deref, type, init, LOOKUP_NORMAL,
"new", NULL_TREE, 0);
init_expr = build_modify_expr (deref, NOP_EXPR, init);
}
else if (! has_array)
{
/* Constructors are never virtual. If it has an initialization, we
need to complain if we aren't allowed to use the ctor that took
that argument. */
int flags = LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_COMPLAIN;
init_expr = build_indirect_ref (alloc_node, NULL_PTR);
init_expr = build_method_call (init_expr, init_expr = build_modify_expr (init_expr, INIT_EXPR, init);
complete_ctor_identifier,
init, TYPE_BINFO (true_type), flags);
}
else
{
if (init && pedantic)
cp_pedwarn ("initialization in array new");
init_expr = convert (build_pointer_type (true_type), alloc_node);
init_expr = (build_vec_init
(NULL_TREE, init_expr,
cp_build_binary_op (MINUS_EXPR, nelts,
integer_one_node),
init, /*from_array=*/0));
} }
if (init_expr == error_mark_node) if (init_expr == error_mark_node)
...@@ -2577,16 +2591,22 @@ build_new_1 (exp) ...@@ -2577,16 +2591,22 @@ build_new_1 (exp)
if (rval == alloc_node) if (rval == alloc_node)
/* If we didn't modify anything, strip the TARGET_EXPR and return the /* If we didn't modify anything, strip the TARGET_EXPR and return the
(adjusted) call. */ (adjusted) call. */
return TREE_OPERAND (alloc_expr, 1); rval = TREE_OPERAND (alloc_expr, 1);
else
if (check_new)
{ {
tree ifexp = cp_build_binary_op (NE_EXPR, alloc_node, if (check_new)
integer_zero_node); {
rval = build_conditional_expr (ifexp, rval, alloc_node); tree ifexp = cp_build_binary_op (NE_EXPR, alloc_node,
integer_zero_node);
rval = build_conditional_expr (ifexp, rval, alloc_node);
}
rval = build (COMPOUND_EXPR, TREE_TYPE (rval), alloc_expr, rval);
} }
rval = build (COMPOUND_EXPR, TREE_TYPE (rval), alloc_expr, rval); /* Now strip the outer ARRAY_TYPE, so we return a pointer to the first
element. */
rval = convert (build_pointer_type (type), rval);
return rval; return rval;
} }
...@@ -2767,12 +2787,7 @@ get_temp_regvar (type, init) ...@@ -2767,12 +2787,7 @@ get_temp_regvar (type, init)
/* `build_vec_init' returns tree structure that performs /* `build_vec_init' returns tree structure that performs
initialization of a vector of aggregate types. initialization of a vector of aggregate types.
DECL is passed only for error reporting, and provides line number BASE is a reference to the vector, of ARRAY_TYPE.
and source file name information.
BASE is the space where the vector will be. For a vector of Ts,
the type of BASE is `T*'.
MAXINDEX is the maximum index of the array (one less than the
number of elements).
INIT is the (possibly NULL) initializer. INIT is the (possibly NULL) initializer.
FROM_ARRAY is 0 if we should init everything with INIT FROM_ARRAY is 0 if we should init everything with INIT
...@@ -2783,8 +2798,8 @@ get_temp_regvar (type, init) ...@@ -2783,8 +2798,8 @@ get_temp_regvar (type, init)
but use assignment instead of initialization. */ but use assignment instead of initialization. */
tree tree
build_vec_init (decl, base, maxindex, init, from_array) build_vec_init (base, init, from_array)
tree decl, base, maxindex, init; tree base, init;
int from_array; int from_array;
{ {
tree rval; tree rval;
...@@ -2792,8 +2807,10 @@ build_vec_init (decl, base, maxindex, init, from_array) ...@@ -2792,8 +2807,10 @@ build_vec_init (decl, base, maxindex, init, from_array)
tree size; tree size;
tree itype = NULL_TREE; tree itype = NULL_TREE;
tree iterator; tree iterator;
/* The type of the array. */
tree atype = TREE_TYPE (base);
/* The type of an element in the array. */ /* The type of an element in the array. */
tree type; tree type = TREE_TYPE (atype);
/* The type of a pointer to an element in the array. */ /* The type of a pointer to an element in the array. */
tree ptype; tree ptype;
tree stmt_expr; tree stmt_expr;
...@@ -2802,38 +2819,56 @@ build_vec_init (decl, base, maxindex, init, from_array) ...@@ -2802,38 +2819,56 @@ build_vec_init (decl, base, maxindex, init, from_array)
tree try_block = NULL_TREE; tree try_block = NULL_TREE;
tree try_body = NULL_TREE; tree try_body = NULL_TREE;
int num_initialized_elts = 0; int num_initialized_elts = 0;
tree maxindex = array_type_nelts (TREE_TYPE (base));
maxindex = cp_convert (ptrdiff_type_node, maxindex);
if (maxindex == error_mark_node) if (maxindex == error_mark_node)
return error_mark_node; return error_mark_node;
type = TREE_TYPE (TREE_TYPE (base)); /* For g++.ext/arrnew.C. */
if (init && TREE_CODE (init) == CONSTRUCTOR && TREE_TYPE (init) == NULL_TREE)
init = digest_init (atype, init, 0);
if (init && !TYPE_NEEDS_CONSTRUCTING (type)
&& ((TREE_CODE (init) == CONSTRUCTOR
/* Don't do this if the CONSTRUCTOR might contain something
that might throw and require us to clean up. */
&& (CONSTRUCTOR_ELTS (init) == NULL_TREE
|| ! TYPE_HAS_NONTRIVIAL_DESTRUCTOR (target_type (type))))
|| from_array))
{
/* Do non-default initialization of POD arrays resulting from
brace-enclosed initializers. In this case, digest_init and
store_constructor will handle the semantics for us. */
stmt_expr = build (INIT_EXPR, atype, base, init);
TREE_SIDE_EFFECTS (stmt_expr) = 1;
return stmt_expr;
}
maxindex = cp_convert (ptrdiff_type_node, maxindex);
ptype = build_pointer_type (type); ptype = build_pointer_type (type);
size = size_in_bytes (type); size = size_in_bytes (type);
if (TREE_CODE (TREE_TYPE (base)) == ARRAY_TYPE)
base = cp_convert (ptype, default_conversion (base));
/* The code we are generating looks like: /* The code we are generating looks like:
T* t1 = (T*) base; T* t1 = (T*) base;
T* rval = base; T* rval = t1;
ptrdiff_t iterator = maxindex; ptrdiff_t iterator = maxindex;
try { try {
... initializations from CONSTRUCTOR ... do {
if (iterator != -1) { ... initialize *t1 ...
do { ++t1;
... initialize *base ... } while (--iterator != -1);
++base;
} while (--iterator != -1);
}
} catch (...) { } catch (...) {
... destroy elements that were constructed ... ... destroy elements that were constructed ...
} }
return rval;
We can omit the try and catch blocks if we know that the We can omit the try and catch blocks if we know that the
initialization will never throw an exception, or if the array initialization will never throw an exception, or if the array
elements do not have destructors. If we have a CONSTRUCTOR to elements do not have destructors. We can omit the loop completely if
give us initialization information, we emit code to initialize
each of the elements before the loop in the try block, and then
iterate over fewer elements. We can omit the loop completely if
the elements of the array do not have constructors. the elements of the array do not have constructors.
We actually wrap the entire body of the above in a STMT_EXPR, for We actually wrap the entire body of the above in a STMT_EXPR, for
...@@ -2848,24 +2883,24 @@ build_vec_init (decl, base, maxindex, init, from_array) ...@@ -2848,24 +2883,24 @@ build_vec_init (decl, base, maxindex, init, from_array)
begin_init_stmts (&stmt_expr, &compound_stmt); begin_init_stmts (&stmt_expr, &compound_stmt);
destroy_temps = stmts_are_full_exprs_p (); destroy_temps = stmts_are_full_exprs_p ();
current_stmt_tree ()->stmts_are_full_exprs_p = 0; current_stmt_tree ()->stmts_are_full_exprs_p = 0;
rval = get_temp_regvar (ptype, rval = get_temp_regvar (ptype, base);
cp_convert (ptype, default_conversion (base)));
base = get_temp_regvar (ptype, rval); base = get_temp_regvar (ptype, rval);
iterator = get_temp_regvar (ptrdiff_type_node, maxindex); iterator = get_temp_regvar (ptrdiff_type_node, maxindex);
/* Protect the entire array initialization so that we can destroy /* Protect the entire array initialization so that we can destroy
the partially constructed array if an exception is thrown. */ the partially constructed array if an exception is thrown.
if (flag_exceptions && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)) But don't do this if we're assigning. */
if (flag_exceptions && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
&& from_array != 2)
{ {
try_block = begin_try_block (); try_block = begin_try_block ();
try_body = begin_compound_stmt (/*has_no_scope=*/1); try_body = begin_compound_stmt (/*has_no_scope=*/1);
} }
if (init != NULL_TREE && TREE_CODE (init) == CONSTRUCTOR if (init != NULL_TREE && TREE_CODE (init) == CONSTRUCTOR)
&& (!decl || same_type_p (TREE_TYPE (init), TREE_TYPE (decl))))
{ {
/* Do non-default initialization resulting from brace-enclosed /* Do non-default initialization of non-POD arrays resulting from
initializers. */ brace-enclosed initializers. */
tree elts; tree elts;
from_array = 0; from_array = 0;
...@@ -2883,16 +2918,8 @@ build_vec_init (decl, base, maxindex, init, from_array) ...@@ -2883,16 +2918,8 @@ build_vec_init (decl, base, maxindex, init, from_array)
finish_expr_stmt (build_modify_expr (baseref, NOP_EXPR, finish_expr_stmt (build_modify_expr (baseref, NOP_EXPR,
elt)); elt));
finish_expr_stmt (build_modify_expr finish_expr_stmt (build_unary_op (PREINCREMENT_EXPR, base, 0));
(base, finish_expr_stmt (build_unary_op (PREDECREMENT_EXPR, iterator, 0));
NOP_EXPR,
build (PLUS_EXPR, build_pointer_type (type),
base, size)));
finish_expr_stmt (build_modify_expr
(iterator,
NOP_EXPR,
build (MINUS_EXPR, ptrdiff_type_node,
iterator, integer_one_node)));
} }
/* Clear out INIT so that we don't get confused below. */ /* Clear out INIT so that we don't get confused below. */
...@@ -2903,11 +2930,6 @@ build_vec_init (decl, base, maxindex, init, from_array) ...@@ -2903,11 +2930,6 @@ build_vec_init (decl, base, maxindex, init, from_array)
/* If initializing one array from another, initialize element by /* If initializing one array from another, initialize element by
element. We rely upon the below calls the do argument element. We rely upon the below calls the do argument
checking. */ checking. */
if (decl == NULL_TREE)
{
sorry ("initialization of array from dissimilar array type");
return error_mark_node;
}
if (init) if (init)
{ {
base2 = default_conversion (init); base2 = default_conversion (init);
...@@ -2988,20 +3010,17 @@ build_vec_init (decl, base, maxindex, init, from_array) ...@@ -2988,20 +3010,17 @@ build_vec_init (decl, base, maxindex, init, from_array)
else if (TREE_CODE (type) == ARRAY_TYPE) else if (TREE_CODE (type) == ARRAY_TYPE)
{ {
if (init != 0) if (init != 0)
sorry ("cannot initialize multi-dimensional array with initializer"); sorry
elt_init = (build_vec_init ("cannot initialize multi-dimensional array with initializer");
(decl, elt_init = build_vec_init (build1 (INDIRECT_REF, type, base),
build1 (NOP_EXPR, 0, 0);
build_pointer_type (TREE_TYPE (type)),
base),
array_type_nelts (type), 0, 0));
} }
else else
elt_init = build_aggr_init (build1 (INDIRECT_REF, type, base), elt_init = build_aggr_init (build1 (INDIRECT_REF, type, base),
init, 0); init, 0);
/* The initialization of each array element is a /* The initialization of each array element is a
full-expression. */ full-expression, as per core issue 124. */
if (!building_stmt_tree ()) if (!building_stmt_tree ())
{ {
genrtl_expr_stmt (elt_init); genrtl_expr_stmt (elt_init);
...@@ -3014,25 +3033,14 @@ build_vec_init (decl, base, maxindex, init, from_array) ...@@ -3014,25 +3033,14 @@ build_vec_init (decl, base, maxindex, init, from_array)
current_stmt_tree ()->stmts_are_full_exprs_p = 0; current_stmt_tree ()->stmts_are_full_exprs_p = 0;
} }
finish_expr_stmt (build_modify_expr finish_expr_stmt (build_unary_op (PREINCREMENT_EXPR, base, 0));
(base,
NOP_EXPR,
build (PLUS_EXPR, build_pointer_type (type),
base, size)));
if (base2) if (base2)
finish_expr_stmt (build_modify_expr finish_expr_stmt (build_unary_op (PREINCREMENT_EXPR, base2, 0));
(base2,
NOP_EXPR,
build (PLUS_EXPR, build_pointer_type (type),
base2, size)));
finish_compound_stmt (/*has_no_scope=*/1, do_body); finish_compound_stmt (/*has_no_scope=*/1, do_body);
finish_do_body (do_stmt); finish_do_body (do_stmt);
finish_do_stmt (build (NE_EXPR, boolean_type_node, finish_do_stmt (build (NE_EXPR, boolean_type_node,
build (PREDECREMENT_EXPR, build_unary_op (PREDECREMENT_EXPR, iterator, 0),
ptrdiff_type_node,
iterator,
integer_one_node),
minus_one_node), minus_one_node),
do_stmt); do_stmt);
...@@ -3041,7 +3049,8 @@ build_vec_init (decl, base, maxindex, init, from_array) ...@@ -3041,7 +3049,8 @@ build_vec_init (decl, base, maxindex, init, from_array)
} }
/* Make sure to cleanup any partially constructed elements. */ /* Make sure to cleanup any partially constructed elements. */
if (flag_exceptions && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)) if (flag_exceptions && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
&& from_array != 2)
{ {
tree e; tree e;
......
...@@ -1268,7 +1268,7 @@ new_initializer: ...@@ -1268,7 +1268,7 @@ new_initializer:
'(' nonnull_exprlist ')' '(' nonnull_exprlist ')'
{ $$ = $2; } { $$ = $2; }
| LEFT_RIGHT | LEFT_RIGHT
{ $$ = NULL_TREE; } { $$ = void_zero_node; }
| '(' typespec ')' | '(' typespec ')'
{ {
cp_error ("`%T' is not a valid expression", $2.t); cp_error ("`%T' is not a valid expression", $2.t);
......
...@@ -5627,7 +5627,15 @@ build_modify_expr (lhs, modifycode, rhs) ...@@ -5627,7 +5627,15 @@ build_modify_expr (lhs, modifycode, rhs)
if (modifycode == INIT_EXPR) if (modifycode == INIT_EXPR)
{ {
if (! IS_AGGR_TYPE (lhstype)) if (TREE_CODE (rhs) == CONSTRUCTOR)
{
if (! same_type_p (TREE_TYPE (rhs), lhstype))
abort ();
result = build (INIT_EXPR, lhstype, lhs, rhs);
TREE_SIDE_EFFECTS (result) = 1;
return result;
}
else if (! IS_AGGR_TYPE (lhstype))
/* Do the default thing */; /* Do the default thing */;
else else
{ {
...@@ -5808,9 +5816,7 @@ build_modify_expr (lhs, modifycode, rhs) ...@@ -5808,9 +5816,7 @@ build_modify_expr (lhs, modifycode, rhs)
from_array = TREE_CODE (TREE_TYPE (newrhs)) == ARRAY_TYPE from_array = TREE_CODE (TREE_TYPE (newrhs)) == ARRAY_TYPE
? 1 + (modifycode != INIT_EXPR): 0; ? 1 + (modifycode != INIT_EXPR): 0;
return (build_vec_init return build_vec_init (lhs, newrhs, from_array);
(lhs, lhs, array_type_nelts (lhstype), newrhs,
from_array));
} }
if (modifycode == INIT_EXPR) if (modifycode == INIT_EXPR)
......
...@@ -581,7 +581,8 @@ digest_init (type, init, tail) ...@@ -581,7 +581,8 @@ digest_init (type, init, tail)
if (code == ARRAY_TYPE || IS_AGGR_TYPE_CODE (code)) if (code == ARRAY_TYPE || IS_AGGR_TYPE_CODE (code))
{ {
if (raw_constructor && TYPE_NON_AGGREGATE_CLASS (type)) if (raw_constructor && TYPE_NON_AGGREGATE_CLASS (type)
&& TREE_HAS_CONSTRUCTOR (init))
{ {
cp_error ("subobject of type `%T' must be initialized by constructor, not by `%E'", cp_error ("subobject of type `%T' must be initialized by constructor, not by `%E'",
type, init); type, init);
......
// Test that we properly default-initialize the new int when () is given. // Test that we properly default-initialize the new int when () is given.
// execution test - XFAIL *-*-*
#include <new> #include <new>
using namespace std; using namespace std;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment