/* The type of the new-expression. (This type is always a pointer
type.) */
tree pointer_type;
+ tree non_const_pointer_type;
tree outer_nelts = NULL_TREE;
tree alloc_call, alloc_expr;
/* The address returned by the call to "operator new". This node is
}
/* Now use a pointer to the type we've actually allocated. */
- data_addr = fold_convert (pointer_type, data_addr);
+
+ /* But we want to operate on a non-const version to start with,
+ since we'll be modifying the elements. */
+ non_const_pointer_type = build_pointer_type
+ (cp_build_qualified_type (type, TYPE_QUALS (type) & ~TYPE_QUAL_CONST));
+
+ data_addr = fold_convert (non_const_pointer_type, data_addr);
/* Any further uses of alloc_node will want this type, too. */
- alloc_node = fold_convert (pointer_type, alloc_node);
+ alloc_node = fold_convert (non_const_pointer_type, alloc_node);
/* Now initialize the allocated object. Note that we preevaluate the
initialization expression, apart from the actual constructor call or
if (array_p)
{
- if (*init)
+ tree vecinit = NULL_TREE;
+ if (*init && VEC_length (tree, *init) == 1
+ && BRACE_ENCLOSED_INITIALIZER_P (VEC_index (tree, *init, 0))
+ && CONSTRUCTOR_IS_DIRECT_INIT (VEC_index (tree, *init, 0)))
+ {
+ tree arraytype, domain;
+ vecinit = VEC_index (tree, *init, 0);
+ if (TREE_CONSTANT (nelts))
+ domain = compute_array_index_type (NULL_TREE, nelts);
+ else
+ {
+ domain = NULL_TREE;
+ if (CONSTRUCTOR_NELTS (vecinit) > 0)
+ warning (0, "non-constant array size in new, unable to "
+ "verify length of initializer-list");
+ }
+ arraytype = build_cplus_array_type (type, domain);
+ vecinit = digest_init (arraytype, vecinit);
+ }
+ else if (*init)
{
if (complain & tf_error)
permerror (input_location, "ISO C++ forbids initialization in array new");
else
return error_mark_node;
+ vecinit = build_tree_list_vec (*init);
}
init_expr
= build_vec_init (data_addr,
MINUS_EXPR, outer_nelts,
integer_one_node,
complain),
- build_tree_list_vec (*init),
+ vecinit,
explicit_value_init_p,
/*from_array=*/0,
complain);
/* A new-expression is never an lvalue. */
gcc_assert (!lvalue_p (rval));
- return rval;
+ return convert (pointer_type, rval);
}
/* Generate a representation for a C++ "new" expression. *PLACEMENT
inner_elt_type = strip_array_types (type);
if (init
+ && TREE_CODE (atype) == ARRAY_TYPE
&& (from_array == 2
? (!CLASS_TYPE_P (inner_elt_type)
|| !TYPE_HAS_COMPLEX_ASSIGN_REF (inner_elt_type))
brace-enclosed initializers. In this case, digest_init and
store_constructor will handle the semantics for us. */
- gcc_assert (TREE_CODE (atype) == ARRAY_TYPE);
stmt_expr = build2 (INIT_EXPR, atype, base, init);
return stmt_expr;
}
{
int from_array;
- if (!same_or_base_type_p (TYPE_MAIN_VARIANT (lhstype),
- TYPE_MAIN_VARIANT (TREE_TYPE (rhs))))
+ if (BRACE_ENCLOSED_INITIALIZER_P (rhs))
+ rhs = digest_init (lhstype, rhs);
+
+ else if (!same_or_base_type_p (TYPE_MAIN_VARIANT (lhstype),
+ TYPE_MAIN_VARIANT (TREE_TYPE (rhs))))
{
if (complain & tf_error)
error ("incompatible types in assignment of %qT to %qT",
}
/* Allow array assignment in compiler-generated code. */
- if (!current_function_decl || !DECL_ARTIFICIAL (current_function_decl))
+ else if (!current_function_decl
+ || !DECL_ARTIFICIAL (current_function_decl))
{
/* This routine is used for both initialization and assignment.
Make sure the diagnostic message differentiates the context. */
/* Vectors are like simple fixed-size arrays. */
len = TYPE_VECTOR_SUBPARTS (type);
- /* There cannot be more initializers than needed as otherwise
- reshape_init would have already rejected the initializer. */
- if (!unbounded)
- gcc_assert (VEC_length (constructor_elt, v) <= len);
+ /* There must not be more initializers than needed. */
+ if (!unbounded && VEC_length (constructor_elt, v) > len)
+ error ("too many initializers for %qT", type);
for (i = 0; VEC_iterate (constructor_elt, v, i, ce); ++i)
{