items with static storage duration that are not otherwise
initialized are initialized to zero. */
;
- else if (SCALAR_TYPE_P (type))
+ else if (SCALAR_TYPE_P (type)
+ || TREE_CODE (type) == COMPLEX_TYPE)
init = convert (type, integer_zero_node);
else if (CLASS_TYPE_P (type))
{
nelts, integer_one_node);
else
max_index = array_type_nelts (type);
+
+ /* If we have an error_mark here, we should just return error mark
+ as we don't know the size of the array yet. */
+ if (max_index == error_mark_node)
+ return error_mark_node;
gcc_assert (TREE_CODE (max_index) == INTEGER_CST);
/* A zero-sized array, which is accepted as an extension, will
/* Build a constructor to contain the initializations. */
init = build_constructor (type, v);
}
+ else if (TREE_CODE (type) == VECTOR_TYPE)
+ init = fold_convert (type, integer_zero_node);
else
gcc_assert (TREE_CODE (type) == REFERENCE_TYPE);
confuses the sjlj exception-handling code. Therefore, we do not
create a single conditional block, but one for each
initialization. (That way the cleanup regions always begin
- in the outer block.) We trust the back-end to figure out
+ in the outer block.) We trust the back end to figure out
that the FLAG will not change across initializations, and
avoid doing multiple tests. */
flag = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl));
return stmt_expr;
}
-/* Like build_aggr_init, but not just for aggregates. */
-
-tree
-build_init (tree decl, tree init, int flags)
-{
- tree expr;
-
- if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
- expr = build_aggr_init (decl, init, flags);
- else if (CLASS_TYPE_P (TREE_TYPE (decl)))
- expr = build_special_member_call (decl, complete_ctor_identifier,
- build_tree_list (NULL_TREE, init),
- TREE_TYPE (decl),
- LOOKUP_NORMAL|flags);
- else
- expr = build2 (INIT_EXPR, TREE_TYPE (decl), decl, init);
-
- return expr;
-}
-
static void
expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags)
{
return member;
if (dependent_type_p (type) || type_dependent_expression_p (member))
- return build_qualified_name (NULL_TREE, type, member,
+ return build_qualified_name (NULL_TREE, type, member,
/*template_p=*/false);
gcc_assert (TYPE_P (type));
}
/* Entities other than non-static members need no further
- processing. */
+ processing. */
if (TREE_CODE (member) == TYPE_DECL)
return member;
if (TREE_CODE (member) == VAR_DECL || TREE_CODE (member) == CONST_DECL)
(or any class derived from that class). */
if (address_p && DECL_P (t)
&& DECL_NONSTATIC_MEMBER_P (t))
- perform_or_defer_access_check (TYPE_BINFO (type), t);
+ perform_or_defer_access_check (TYPE_BINFO (type), t, t);
else
- perform_or_defer_access_check (basebinfo, t);
+ perform_or_defer_access_check (basebinfo, t, t);
if (DECL_STATIC_FUNCTION_P (t))
return t;
/* We need additional test besides the one in
check_accessibility_of_qualified_id in case it is
a pointer to non-static member. */
- perform_or_defer_access_check (TYPE_BINFO (type), member);
+ perform_or_defer_access_check (TYPE_BINFO (type), member, member);
if (!address_p)
{
}
error ("invalid use of non-static member function %qD",
TREE_OPERAND (member, 1));
- return member;
+ return error_mark_node;
}
else if (TREE_CODE (member) == FIELD_DECL)
{
constant_value_1 (tree decl, bool integral_p)
{
while (TREE_CODE (decl) == CONST_DECL
- || (integral_p
+ || (integral_p
? DECL_INTEGRAL_CONSTANT_VAR_P (decl)
: (TREE_CODE (decl) == VAR_DECL
&& CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (decl)))))
instantiation time. */
if (DECL_CLASS_SCOPE_P (decl)
&& CLASSTYPE_TEMPLATE_INFO (DECL_CONTEXT (decl))
- && uses_template_parms (CLASSTYPE_TI_ARGS
+ && uses_template_parms (CLASSTYPE_TI_ARGS
(DECL_CONTEXT (decl))))
{
++processing_template_decl;
init = DECL_INITIAL (decl);
}
if (init == error_mark_node)
- return error_mark_node;
+ return decl;
if (!init
|| !TREE_TYPE (init)
|| (integral_p
}
/* A more relaxed version of integral_constant_value, used by the
- common C/C++ code and by the C++ front-end for optimization
+ common C/C++ code and by the C++ front end for optimization
purposes. */
tree
decl_constant_value (tree decl)
{
- return constant_value_1 (decl,
+ return constant_value_1 (decl,
/*integral_p=*/processing_template_decl);
}
\f
int use_global_new)
{
tree new_expr;
-
- new_expr = build4 (NEW_EXPR, build_pointer_type (type), placement, type,
- nelts, init);
+
+ new_expr = build4 (NEW_EXPR, build_pointer_type (type), placement, type,
+ nelts, init);
NEW_EXPR_USE_GLOBAL (new_expr) = use_global_new;
TREE_SIDE_EFFECTS (new_expr) = 1;
static tree
build_new_1 (tree placement, tree type, tree nelts, tree init,
bool globally_qualified_p)
-
{
tree size, rval;
/* True iff this is a call to "operator new[]" instead of just
function context. Methinks that's not it's purvey. So we'll do
our own VLA layout later. */
vla_p = true;
- full_type = build_cplus_array_type (type, NULL_TREE);
index = convert (sizetype, nelts);
index = size_binop (MINUS_EXPR, index, size_one_node);
- TYPE_DOMAIN (full_type) = build_index_type (index);
+ index = build_index_type (index);
+ full_type = build_cplus_array_type (type, NULL_TREE);
+ /* We need a copy of the type as build_array_type will return a shared copy
+ of the incomplete array type. */
+ full_type = build_distinct_type_copy (full_type);
+ TYPE_DOMAIN (full_type) = index;
}
else
{
tree class_decl = build_java_class_ref (elt_type);
static const char alloc_name[] = "_Jv_AllocObject";
+ if (class_decl == error_mark_node)
+ return error_mark_node;
+
use_java_new = 1;
if (!get_global_value_if_present (get_identifier (alloc_name),
&alloc_fn))
= build_vec_init (init_expr,
cp_build_binary_op (MINUS_EXPR, outer_nelts,
integer_one_node),
- init,
- explicit_default_init_p,
+ init,
+ explicit_default_init_p,
/*from_array=*/0);
/* An array initialization is stable because the initialization
{
/* 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,
+ init = build_x_compound_expr_from_list (init,
"new initializer");
else
gcc_assert (TREE_CODE (init) != CONSTRUCTOR
|| TREE_TYPE (init) != NULL_TREE);
-
+
init_expr = build_modify_expr (init_expr, INIT_EXPR, init);
stable = stabilize_init (init_expr, &init_preeval_expr);
}
rval = build_nop (pointer_type, rval);
/* A new-expression is never an lvalue. */
- rval = rvalue (rval);
+ gcc_assert (!lvalue_p (rval));
return rval;
}
tree orig_nelts;
tree orig_init;
- if (type == error_mark_node)
+ if (placement == error_mark_node || type == error_mark_node
+ || init == error_mark_node)
return error_mark_node;
orig_placement = placement;
{
if (!build_expr_type_conversion (WANT_INT | WANT_ENUM, nelts, false))
pedwarn ("size in array new must have integral type");
- nelts = save_expr (cp_convert (sizetype, nelts));
- if (nelts == integer_zero_node)
- warning (0, "zero size array reserves no space");
+ nelts = cp_save_expr (cp_convert (sizetype, nelts));
+ /* It is valid to allocate a zero-element array:
+
+ [expr.new]
+
+ When the value of the expression in a direct-new-declarator
+ is zero, the allocation function is called to allocate an
+ array with no elements. The pointer returned by the
+ new-expression is non-null. [Note: If the library allocation
+ function is called, the pointer returned is distinct from the
+ pointer to any other object.]
+
+ However, that is not generally useful, so we issue a
+ warning. */
+ if (integer_zerop (nelts))
+ warning (0, "allocating zero-element array");
}
/* ``A reference cannot be created by the new operator. A reference
{
jclass_node = IDENTIFIER_GLOBAL_VALUE (get_identifier ("jclass"));
if (jclass_node == NULL_TREE)
- fatal_error ("call to Java constructor, while %<jclass%> undefined");
-
+ {
+ error ("call to Java constructor, while %<jclass%> undefined");
+ return error_mark_node;
+ }
jclass_node = TREE_TYPE (jclass_node);
}
break;
}
if (!field)
- internal_error ("can't find class$");
- }
+ {
+ error ("can't find %<class$%> in %qT", type);
+ return error_mark_node;
+ }
+ }
class_decl = IDENTIFIER_GLOBAL_VALUE (name);
if (class_decl == NULL_TREE)
deallocate_expr = build_op_delete_call (VEC_DELETE_EXPR,
base_tbd, virtual_size,
use_global_delete & 1,
- /*placement=*/NULL_TREE,
+ /*placement=*/NULL_TREE,
/*alloc_fn=*/NULL_TREE);
}
but use assignment instead of initialization. */
tree
-build_vec_init (tree base, tree maxindex, tree init,
+build_vec_init (tree base, tree maxindex, tree init,
bool explicit_default_init_p,
int from_array)
{
When copying from array to another, when the array elements have
only trivial copy constructors, we should use __builtin_memcpy
rather than generating a loop. That way, we could take advantage
- of whatever cleverness the back-end has for dealing with copies
+ of whatever cleverness the back end has for dealing with copies
of blocks of memory. */
is_global = begin_init_stmts (&stmt_expr, &compound_stmt);
sorry
("cannot initialize multi-dimensional array with initializer");
elt_init = build_vec_init (build1 (INDIRECT_REF, type, base),
- 0, 0,
+ 0, 0,
/*explicit_default_init_p=*/false,
0);
}
else if (!TYPE_NEEDS_CONSTRUCTING (type))
- elt_init = (build_modify_expr
+ elt_init = (build_modify_expr
(to, INIT_EXPR,
build_zero_init (type, size_one_node,
/*static_storage_p=*/false)));
if (auto_delete != sfk_deleting_destructor)
return void_zero_node;
- return build_op_delete_call (DELETE_EXPR, addr,
- cxx_sizeof_nowarn (type),
+ return build_op_delete_call (DELETE_EXPR, addr,
+ cxx_sizeof_nowarn (type),
use_global_delete,
/*placement=*/NULL_TREE,
/*alloc_fn=*/NULL_TREE);
/* Make sure we have access to the member op delete, even though
we'll actually be calling it from the destructor. */
build_op_delete_call (DELETE_EXPR, addr, cxx_sizeof_nowarn (type),
- /*global_p=*/false,
+ /*global_p=*/false,
/*placement=*/NULL_TREE,
/*alloc_fn=*/NULL_TREE);
}
for (member = TYPE_FIELDS (current_class_type); member;
member = TREE_CHAIN (member))
{
- if (TREE_CODE (member) != FIELD_DECL || DECL_ARTIFICIAL (member))
+ if (TREE_TYPE (member) == error_mark_node
+ || TREE_CODE (member) != FIELD_DECL
+ || DECL_ARTIFICIAL (member))
continue;
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (member)))
{