/* Handle initialization things in C++.
Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
-#include "rtl.h"
-#include "expr.h"
#include "cp-tree.h"
#include "flags.h"
#include "output.h"
-#include "except.h"
#include "toplev.h"
#include "target.h"
static tree build_dtor_call (tree, special_function_kind, int);
static tree build_field_list (tree, tree, int *);
static tree build_vtbl_address (tree);
+static int diagnose_uninitialized_cst_or_ref_member_1 (tree, tree, bool, bool);
/* We are about to generate some complex initialization code.
Conceptually, it is all a single expression. However, we may want
VEC(constructor_elt,gc) *v = NULL;
/* Iterate over the fields, building initializations. */
- for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
{
if (TREE_CODE (field) != FIELD_DECL)
continue;
/* Iterate over the array elements, building initializations. */
if (nelts)
- max_index = fold_build2 (MINUS_EXPR, TREE_TYPE (nelts),
+ max_index = fold_build2_loc (input_location,
+ MINUS_EXPR, TREE_TYPE (nelts),
nelts, integer_one_node);
else
max_index = array_type_nelts (type);
TYPE, as described in [dcl.init]. */
tree
-build_value_init (tree type)
+build_value_init (tree type, tsubst_flags_t complain)
{
/* [dcl.init]
(type,
build_special_member_call (NULL_TREE, complete_ctor_identifier,
NULL, type, LOOKUP_NORMAL,
- tf_warning_or_error));
+ complain));
else if (TREE_CODE (type) != UNION_TYPE && TYPE_NEEDS_CONSTRUCTING (type))
{
/* This is a class that needs constructing, but doesn't have
This will be handled in simplify_aggr_init_expr. */
tree ctor = build_special_member_call
(NULL_TREE, complete_ctor_identifier,
- NULL, type, LOOKUP_NORMAL, tf_warning_or_error);
+ NULL, type, LOOKUP_NORMAL, complain);
ctor = build_aggr_init_expr (type, ctor);
AGGR_INIT_ZERO_FIRST (ctor) = 1;
return ctor;
}
}
- return build_value_init_noctor (type);
+ return build_value_init_noctor (type, complain);
}
/* Like build_value_init, but don't call the constructor for TYPE. Used
for base initializers. */
tree
-build_value_init_noctor (tree type)
+build_value_init_noctor (tree type, tsubst_flags_t complain)
{
if (CLASS_TYPE_P (type))
{
VEC(constructor_elt,gc) *v = NULL;
/* Iterate over the fields, building initializations. */
- for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
{
tree ftype, value;
ftype = TREE_TYPE (field);
if (TREE_CODE (ftype) == REFERENCE_TYPE)
- error ("value-initialization of reference");
+ {
+ if (complain & tf_error)
+ error ("value-initialization of reference");
+ else
+ return error_mark_node;
+ }
/* We could skip vfields and fields of types with
user-defined constructors, but I think that won't improve
corresponding to base classes as well. Thus, iterating
over TYPE_FIELDs will result in correct initialization of
all of the subobjects. */
- value = build_value_init (ftype);
+ value = build_value_init (ftype, complain);
if (value)
CONSTRUCTOR_APPEND_ELT(v, field, value);
/* 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;
+ {
+ error ("cannot value-initialize array of unknown bound %qT", type);
+ return error_mark_node;
+ }
gcc_assert (TREE_CODE (max_index) == INTEGER_CST);
/* A zero-sized array, which is accepted as an extension, will
ce->index = build2 (RANGE_EXPR, sizetype, size_zero_node,
max_index);
- ce->value = build_value_init (TREE_TYPE (type));
+ ce->value = build_value_init (TREE_TYPE (type), complain);
/* The gimplifier can't deal with a RANGE_EXPR of TARGET_EXPRs. */
gcc_assert (TREE_CODE (ce->value) != TARGET_EXPR
member);
else
{
- init = build2 (INIT_EXPR, type, decl, build_value_init (type));
+ init = build2 (INIT_EXPR, type, decl,
+ build_value_init (type, tf_warning_or_error));
finish_expr_stmt (init);
}
}
{
if (init == NULL_TREE)
{
+ tree core_type;
/* member traversal: note it leaves init NULL */
if (TREE_CODE (type) == REFERENCE_TYPE)
permerror (DECL_SOURCE_LOCATION (current_function_decl),
permerror (DECL_SOURCE_LOCATION (current_function_decl),
"uninitialized member %qD with %<const%> type %qT",
member, type);
+
+ core_type = strip_array_types (type);
+ if (CLASS_TYPE_P (core_type)
+ && (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type)
+ || CLASSTYPE_REF_FIELDS_NEED_INIT (core_type)))
+ diagnose_uninitialized_cst_or_ref_member (core_type,
+ /*using_new=*/false,
+ /*complain=*/true);
}
else if (TREE_CODE (init) == TREE_LIST)
/* There was an explicit member initialization. Do some work
in that case. */
- init = build_x_compound_expr_from_list (init, "member initializer");
+ init = build_x_compound_expr_from_list (init, ELK_MEM_INIT,
+ tf_warning_or_error);
if (init)
finish_expr_stmt (cp_build_modify_expr (decl, INIT_EXPR, init,
if (TREE_CODE (t) == UNION_TYPE)
*uses_unions_p = 1;
- for (fields = TYPE_FIELDS (t); fields; fields = TREE_CHAIN (fields))
+ for (fields = TYPE_FIELDS (t); fields; fields = DECL_CHAIN (fields))
{
+ tree fieldtype;
+
/* Skip CONST_DECLs for enumeration constants and so forth. */
if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
continue;
+ fieldtype = TREE_TYPE (fields);
/* Keep track of whether or not any fields are unions. */
- if (TREE_CODE (TREE_TYPE (fields)) == UNION_TYPE)
+ if (TREE_CODE (fieldtype) == UNION_TYPE)
*uses_unions_p = 1;
/* For an anonymous struct or union, we must recursively
consider the fields of the anonymous type. They can be
directly initialized from the constructor. */
- if (ANON_AGGR_TYPE_P (TREE_TYPE (fields)))
+ if (ANON_AGGR_TYPE_P (fieldtype))
{
/* Add this field itself. Synthesized copy constructors
initialize the entire aggregate. */
list = tree_cons (fields, NULL_TREE, list);
/* And now add the fields in the anonymous aggregate. */
- list = build_field_list (TREE_TYPE (fields), list,
- uses_unions_p);
+ list = build_field_list (fieldtype, list, uses_unions_p);
}
/* Add this field. */
else if (DECL_NAME (fields))
If a ctor-initializer specifies more than one mem-initializer for
multiple members of the same union (including members of
- anonymous unions), the ctor-initializer is ill-formed. */
+ anonymous unions), the ctor-initializer is ill-formed.
+
+ Here we also splice out uninitialized union members. */
if (uses_unions_p)
{
tree last_field = NULL_TREE;
- for (init = sorted_inits; init; init = TREE_CHAIN (init))
+ tree *p;
+ for (p = &sorted_inits; *p; )
{
tree field;
- tree field_type;
+ tree ctx;
int done;
- /* Skip uninitialized members and base classes. */
- if (!TREE_VALUE (init)
- || TREE_CODE (TREE_PURPOSE (init)) != FIELD_DECL)
- continue;
+ init = *p;
+
+ field = TREE_PURPOSE (init);
+
+ /* Skip base classes. */
+ if (TREE_CODE (field) != FIELD_DECL)
+ goto next;
+
+ /* If this is an anonymous union with no explicit initializer,
+ splice it out. */
+ if (!TREE_VALUE (init) && ANON_UNION_TYPE_P (TREE_TYPE (field)))
+ goto splice;
+
/* See if this field is a member of a union, or a member of a
structure contained in a union, etc. */
- field = TREE_PURPOSE (init);
- for (field_type = DECL_CONTEXT (field);
- !same_type_p (field_type, t);
- field_type = TYPE_CONTEXT (field_type))
- if (TREE_CODE (field_type) == UNION_TYPE)
+ for (ctx = DECL_CONTEXT (field);
+ !same_type_p (ctx, t);
+ ctx = TYPE_CONTEXT (ctx))
+ if (TREE_CODE (ctx) == UNION_TYPE)
break;
/* If this field is not a member of a union, skip it. */
- if (TREE_CODE (field_type) != UNION_TYPE)
- continue;
+ if (TREE_CODE (ctx) != UNION_TYPE)
+ goto next;
+
+ /* If this union member has no explicit initializer, splice
+ it out. */
+ if (!TREE_VALUE (init))
+ goto splice;
/* It's only an error if we have two initializers for the same
union type. */
if (!last_field)
{
last_field = field;
- continue;
+ goto next;
}
/* See if LAST_FIELD and the field initialized by INIT are
union { struct { int i; int j; }; };
initializing both `i' and `j' makes sense. */
- field_type = DECL_CONTEXT (field);
+ ctx = DECL_CONTEXT (field);
done = 0;
do
{
- tree last_field_type;
+ tree last_ctx;
- last_field_type = DECL_CONTEXT (last_field);
+ last_ctx = DECL_CONTEXT (last_field);
while (1)
{
- if (same_type_p (last_field_type, field_type))
+ if (same_type_p (last_ctx, ctx))
{
- if (TREE_CODE (field_type) == UNION_TYPE)
+ if (TREE_CODE (ctx) == UNION_TYPE)
error_at (DECL_SOURCE_LOCATION (current_function_decl),
"initializations for multiple members of %qT",
- last_field_type);
+ last_ctx);
done = 1;
break;
}
- if (same_type_p (last_field_type, t))
+ if (same_type_p (last_ctx, t))
break;
- last_field_type = TYPE_CONTEXT (last_field_type);
+ last_ctx = TYPE_CONTEXT (last_ctx);
}
/* If we've reached the outermost class, then we're
done. */
- if (same_type_p (field_type, t))
+ if (same_type_p (ctx, t))
break;
- field_type = TYPE_CONTEXT (field_type);
+ ctx = TYPE_CONTEXT (ctx);
}
while (!done);
last_field = field;
+
+ next:
+ p = &TREE_CHAIN (*p);
+ continue;
+ splice:
+ *p = TREE_CHAIN (*p);
+ continue;
}
}
base_addr = build_base_path (PLUS_EXPR, current_class_ptr,
subobject, 1);
expand_aggr_init_1 (subobject, NULL_TREE,
- cp_build_indirect_ref (base_addr, NULL,
+ cp_build_indirect_ref (base_addr, RO_NULL,
tf_warning_or_error),
arguments,
LOOKUP_NORMAL,
TREE_TYPE (vtt_parm),
vtt_parm,
vtt_index);
- vtbl2 = cp_build_indirect_ref (vtbl2, NULL, tf_warning_or_error);
+ vtbl2 = cp_build_indirect_ref (vtbl2, RO_NULL, tf_warning_or_error);
vtbl2 = convert (TREE_TYPE (vtbl), vtbl2);
/* The actual initializer is the VTT value only in the subobject
}
/* Compute the location of the vtpr. */
- vtbl_ptr = build_vfield_ref (cp_build_indirect_ref (decl, NULL,
+ vtbl_ptr = build_vfield_ref (cp_build_indirect_ref (decl, RO_NULL,
tf_warning_or_error),
TREE_TYPE (binfo));
gcc_assert (vtbl_ptr != error_mark_node);
LOOKUP_NORMAL | LOOKUP_NONVIRTUAL,
tf_warning_or_error);
if (flag)
- expr = fold_build3 (COND_EXPR, void_type_node,
+ expr = fold_build3_loc (input_location,
+ COND_EXPR, void_type_node,
c_common_truthvalue_conversion (input_location, flag),
expr, integer_zero_node);
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));
+ flag = DECL_CHAIN (DECL_ARGUMENTS (current_function_decl));
inner_if_stmt = begin_if_stmt ();
finish_if_stmt_cond (flag, inner_if_stmt);
TREE_READONLY (exp) = 0;
TREE_THIS_VOLATILE (exp) = 0;
- if (init && TREE_CODE (init) != TREE_LIST)
+ if (init && TREE_CODE (init) != TREE_LIST
+ && !(BRACE_ENCLOSED_INITIALIZER_P (init)
+ && CONSTRUCTOR_IS_DIRECT_INIT (init)))
flags |= LOOKUP_ONLYCONVERTING;
if (TREE_CODE (type) == ARRAY_TYPE)
/* Must arrange to initialize each element of EXP
from elements of INIT. */
itype = init ? TREE_TYPE (init) : NULL_TREE;
- if (cp_type_quals (type) != TYPE_UNQUALIFIED)
- TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type);
- if (itype && cp_type_quals (itype) != TYPE_UNQUALIFIED)
- itype = TREE_TYPE (init) = TYPE_MAIN_VARIANT (itype);
+ if (cv_qualified_p (type))
+ TREE_TYPE (exp) = cv_unqualified (type);
+ if (itype && cv_qualified_p (itype))
+ TREE_TYPE (init) = cv_unqualified (itype);
stmt_expr = build_vec_init (exp, NULL_TREE, init,
/*explicit_value_init_p=*/false,
- itype && same_type_p (itype,
+ itype && same_type_p (TREE_TYPE (init),
TREE_TYPE (exp)),
complain);
TREE_READONLY (exp) = was_const;
tree rval;
VEC(tree,gc) *parms;
+ if (init && BRACE_ENCLOSED_INITIALIZER_P (init)
+ && CP_AGGREGATE_TYPE_P (type))
+ {
+ /* A brace-enclosed initializer for an aggregate. In C++0x this can
+ happen for direct-initialization, too. */
+ init = digest_init (type, init);
+ init = build2 (INIT_EXPR, TREE_TYPE (exp), exp, init);
+ TREE_SIDE_EFFECTS (init) = 1;
+ finish_expr_stmt (init);
+ return;
+ }
+
if (init && TREE_CODE (init) != TREE_LIST
&& (flags & LOOKUP_ONLYCONVERTING))
{
to run a new constructor; and catching an exception, where we
have already built up the constructor call so we could wrap it
in an exception region. */;
- else if (BRACE_ENCLOSED_INITIALIZER_P (init)
- && CP_AGGREGATE_TYPE_P (type))
- {
- /* A brace-enclosed initializer for an aggregate. */
- init = digest_init (type, init);
- }
else
init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
release_tree_vector (parms);
if (TREE_SIDE_EFFECTS (rval))
- finish_expr_stmt (convert_to_void (rval, NULL, complain));
+ finish_expr_stmt (convert_to_void (rval, ICV_CAST, complain));
}
/* This function is responsible for initializing EXP with INIT
then just zero out the object and we're done. */
else
{
- init = build2 (INIT_EXPR, type, exp, build_value_init_noctor (type));
+ init = build2 (INIT_EXPR, type, exp,
+ build_value_init_noctor (type, complain));
finish_expr_stmt (init);
return;
}
if (TREE_CODE (member) == TEMPLATE_DECL)
return member;
- if (dependent_type_p (type) || type_dependent_expression_p (member))
+ if (dependent_scope_p (type) || type_dependent_expression_p (member))
return build_qualified_name (NULL_TREE, type, member,
- /*template_p=*/false);
+ /*template_p=*/false);
gcc_assert (TYPE_P (type));
if (! is_class_type (type, 1))
/* Callers should call mark_used before this point. */
gcc_assert (!DECL_P (member) || TREE_USED (member));
- if (!COMPLETE_TYPE_P (complete_type (type))
- && !TYPE_BEING_DEFINED (type))
+ type = TYPE_MAIN_VARIANT (type);
+ if (!COMPLETE_OR_OPEN_TYPE_P (complete_type (type)))
{
error ("incomplete type %qT does not have member %qD", type, member);
return error_mark_node;
init = DECL_INITIAL (decl);
}
if (init == error_mark_node)
- return decl;
+ {
+ if (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl))
+ /* Treat the error as a constant to avoid cascading errors on
+ excessively recursive template instantiation (c++/9335). */
+ return init;
+ else
+ return decl;
+ }
/* Initializers in templates are generally expanded during
instantiation, so before that for const int i(2)
INIT is a TREE_LIST with the actual initializer as
return new_expr;
}
+/* Diagnose uninitialized const members or reference members of type
+ TYPE. USING_NEW is used to disambiguate the diagnostic between a
+ new expression without a new-initializer and a declaration. Returns
+ the error count. */
+
+static int
+diagnose_uninitialized_cst_or_ref_member_1 (tree type, tree origin,
+ bool using_new, bool complain)
+{
+ tree field;
+ int error_count = 0;
+
+ if (type_has_user_provided_constructor (type))
+ return 0;
+
+ for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
+ {
+ tree field_type;
+
+ if (TREE_CODE (field) != FIELD_DECL)
+ continue;
+
+ field_type = strip_array_types (TREE_TYPE (field));
+
+ if (TREE_CODE (field_type) == REFERENCE_TYPE)
+ {
+ ++ error_count;
+ if (complain)
+ {
+ if (using_new)
+ error ("uninitialized reference member in %q#T "
+ "using %<new%> without new-initializer", origin);
+ else
+ error ("uninitialized reference member in %q#T", origin);
+ inform (DECL_SOURCE_LOCATION (field),
+ "%qD should be initialized", field);
+ }
+ }
+
+ if (CP_TYPE_CONST_P (field_type))
+ {
+ ++ error_count;
+ if (complain)
+ {
+ if (using_new)
+ error ("uninitialized const member in %q#T "
+ "using %<new%> without new-initializer", origin);
+ else
+ error ("uninitialized const member in %q#T", origin);
+ inform (DECL_SOURCE_LOCATION (field),
+ "%qD should be initialized", field);
+ }
+ }
+
+ if (CLASS_TYPE_P (field_type))
+ error_count
+ += diagnose_uninitialized_cst_or_ref_member_1 (field_type, origin,
+ using_new, complain);
+ }
+ return error_count;
+}
+
+int
+diagnose_uninitialized_cst_or_ref_member (tree type, bool using_new, bool complain)
+{
+ return diagnose_uninitialized_cst_or_ref_member_1 (type, type, using_new, complain);
+}
+
/* 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
/* 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
is_initialized = (TYPE_NEEDS_CONSTRUCTING (elt_type) || *init != NULL);
+ if (*init == NULL)
+ {
+ bool maybe_uninitialized_error = false;
+ /* A program that calls for default-initialization [...] of an
+ entity of reference type is ill-formed. */
+ if (CLASSTYPE_REF_FIELDS_NEED_INIT (elt_type))
+ maybe_uninitialized_error = true;
+
+ /* A new-expression that creates an object of type T initializes
+ that object as follows:
+ - If the new-initializer is omitted:
+ -- If T is a (possibly cv-qualified) non-POD class type
+ (or array thereof), the object is default-initialized (8.5).
+ [...]
+ -- Otherwise, the object created has indeterminate
+ value. If T is a const-qualified type, or a (possibly
+ cv-qualified) POD class type (or array thereof)
+ containing (directly or indirectly) a member of
+ const-qualified type, the program is ill-formed; */
+
+ if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (elt_type))
+ maybe_uninitialized_error = true;
+
+ if (maybe_uninitialized_error
+ && diagnose_uninitialized_cst_or_ref_member (elt_type,
+ /*using_new=*/true,
+ complain & tf_error))
+ return error_mark_node;
+ }
+
if (CP_TYPE_CONST_P (elt_type) && *init == NULL
&& !type_has_user_provided_default_constructor (elt_type))
{
}
alloc_fn = OVL_CURRENT (alloc_fn);
class_addr = build1 (ADDR_EXPR, jclass_node, class_decl);
- alloc_call = (cp_build_function_call
- (alloc_fn,
- build_tree_list (NULL_TREE, class_addr),
- complain));
+ alloc_call = cp_build_function_call_nary (alloc_fn, complain,
+ class_addr, NULL_TREE);
}
else if (TYPE_FOR_JAVA (elt_type) && MAYBE_CLASS_TYPE_P (elt_type))
{
many elements to destroy later. We use the last sizeof
(size_t) bytes to store the number of elements. */
cookie_ptr = size_binop (MINUS_EXPR, cookie_size, size_in_bytes (sizetype));
- cookie_ptr = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (alloc_node),
+ cookie_ptr = fold_build2_loc (input_location,
+ POINTER_PLUS_EXPR, TREE_TYPE (alloc_node),
alloc_node, cookie_ptr);
size_ptr_type = build_pointer_type (sizetype);
cookie_ptr = fold_convert (size_ptr_type, cookie_ptr);
- cookie = cp_build_indirect_ref (cookie_ptr, NULL, complain);
+ cookie = cp_build_indirect_ref (cookie_ptr, RO_NULL, complain);
cookie_expr = build2 (MODIFY_EXPR, sizetype, cookie, nelts);
{
/* Also store the element size. */
cookie_ptr = build2 (POINTER_PLUS_EXPR, size_ptr_type, cookie_ptr,
- fold_build1 (NEGATE_EXPR, sizetype,
+ fold_build1_loc (input_location,
+ NEGATE_EXPR, sizetype,
size_in_bytes (sizetype)));
- cookie = cp_build_indirect_ref (cookie_ptr, NULL, complain);
+ cookie = cp_build_indirect_ref (cookie_ptr, RO_NULL, complain);
cookie = build2 (MODIFY_EXPR, sizetype, cookie,
size_in_bytes (elt_type));
cookie_expr = build2 (COMPOUND_EXPR, TREE_TYPE (cookie_expr),
}
/* 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, cp_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);
}
else
{
- init_expr = cp_build_indirect_ref (data_addr, NULL, complain);
+ init_expr = cp_build_indirect_ref (data_addr, RO_NULL, complain);
if (TYPE_NEEDS_CONSTRUCTING (type) && !explicit_value_init_p)
{
else if (explicit_value_init_p)
{
/* Something like `new int()'. */
- init_expr = build2 (INIT_EXPR, type,
- init_expr, build_value_init (type));
+ tree val = build_value_init (type, complain);
+ if (val == error_mark_node)
+ return error_mark_node;
+ init_expr = build2 (INIT_EXPR, type, init_expr, val);
}
else
{
else if (stable)
/* This is much simpler if we were able to preevaluate all of
the arguments to the constructor call. */
- init_expr = build2 (TRY_CATCH_EXPR, void_type_node,
- init_expr, cleanup);
+ {
+ /* CLEANUP is compiler-generated, so no diagnostics. */
+ TREE_NO_WARNING (cleanup) = true;
+ init_expr = build2 (TRY_CATCH_EXPR, void_type_node,
+ init_expr, cleanup);
+ /* Likewise, this try-catch is compiler-generated. */
+ TREE_NO_WARNING (init_expr) = true;
+ }
else
/* Ack! First we allocate the memory. Then we set our sentry
variable to true, and expand a cleanup that deletes the
sentry = TARGET_EXPR_SLOT (begin);
+ /* CLEANUP is compiler-generated, so no diagnostics. */
+ TREE_NO_WARNING (cleanup) = true;
+
TARGET_EXPR_CLEANUP (begin)
= build3 (COND_EXPR, void_type_node, sentry,
cleanup, void_zero_node);
= build2 (COMPOUND_EXPR, void_type_node, begin,
build2 (COMPOUND_EXPR, void_type_node, init_expr,
end));
+ /* Likewise, this is compiler-generated. */
+ TREE_NO_WARNING (init_expr) = true;
}
-
}
}
else
/* 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
else
return error_mark_node;
}
+ nelts = mark_rvalue_use (nelts);
nelts = cp_save_expr (cp_convert (sizetype, nelts));
}
/* The type allocated must be complete. If the new-type-id was
"T[N]" then we are just checking that "T" is complete here, but
that is equivalent, since the value of "N" doesn't matter. */
- if (!complete_type_or_else (type, NULL_TREE))
+ if (!complete_type_or_maybe_complain (type, NULL_TREE, complain))
return error_mark_node;
rval = build_new_1 (placement, type, nelts, init, use_global_new, complain);
/* Mangle the class$ field. */
{
tree field;
- for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
if (DECL_NAME (field) == CL_suffix)
{
mangle_decl (field);
tbase = create_temporary_var (ptype);
tbase_init = cp_build_modify_expr (tbase, NOP_EXPR,
- fold_build2 (POINTER_PLUS_EXPR, ptype,
+ fold_build2_loc (input_location,
+ POINTER_PLUS_EXPR, ptype,
fold_convert (ptype, base),
virtual_size),
tf_warning_or_error);
- DECL_REGISTER (tbase) = 1;
controller = build3 (BIND_EXPR, void_type_node, tbase,
NULL_TREE, NULL_TREE);
TREE_SIDE_EFFECTS (controller) = 1;
body = build1 (EXIT_EXPR, void_type_node,
build2 (EQ_EXPR, boolean_type_node, tbase,
fold_convert (ptype, base)));
- tmp = fold_build1 (NEGATE_EXPR, sizetype, size_exp);
+ tmp = fold_build1_loc (input_location, NEGATE_EXPR, sizetype, size_exp);
body = build_compound_expr
(input_location,
body, cp_build_modify_expr (tbase, NOP_EXPR,
body = integer_zero_node;
/* Outermost wrapper: If pointer is null, punt. */
- body = fold_build3 (COND_EXPR, void_type_node,
- fold_build2 (NE_EXPR, boolean_type_node, base,
+ body = fold_build3_loc (input_location, COND_EXPR, void_type_node,
+ fold_build2_loc (input_location,
+ NE_EXPR, boolean_type_node, base,
convert (TREE_TYPE (base),
integer_zero_node)),
body, integer_zero_node);
/* Pre-evaluate the SAVE_EXPR outside of the BIND_EXPR. */
body = build2 (COMPOUND_EXPR, void_type_node, base, body);
- return convert_to_void (body, /*implicit=*/NULL, tf_warning_or_error);
+ return convert_to_void (body, ICV_CAST, tf_warning_or_error);
}
/* Create an unnamed variable of the indicated TYPE. */
{
tree rval;
tree base2 = NULL_TREE;
- tree size;
tree itype = NULL_TREE;
tree iterator;
/* The type of BASE. */
gcc_assert (!init);
inner_elt_type = strip_array_types (type);
+
+ /* Look through the TARGET_EXPR around a compound literal. */
+ if (init && TREE_CODE (init) == TARGET_EXPR
+ && TREE_CODE (TARGET_EXPR_INITIAL (init)) == CONSTRUCTOR
+ && from_array != 2)
+ init = TARGET_EXPR_INITIAL (init);
+
if (init
+ && TREE_CODE (atype) == ARRAY_TYPE
&& (from_array == 2
? (!CLASS_TYPE_P (inner_elt_type)
- || !TYPE_HAS_COMPLEX_ASSIGN_REF (inner_elt_type))
+ || !TYPE_HAS_COMPLEX_COPY_ASSIGN (inner_elt_type))
: !TYPE_NEEDS_CONSTRUCTING (type))
&& ((TREE_CODE (init) == CONSTRUCTOR
/* Don't do this if the CONSTRUCTOR might contain something
|| ! TYPE_HAS_NONTRIVIAL_DESTRUCTOR (inner_elt_type)))
|| from_array))
{
- /* Do non-default initialization of POD arrays resulting from
+ /* Do non-default initialization of trivial arrays resulting from
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;
}
maxindex = cp_convert (ptrdiff_type_node, maxindex);
- size = size_in_bytes (type);
if (TREE_CODE (atype) == ARRAY_TYPE)
{
ptype = build_pointer_type (type);
base = get_temp_regvar (ptype, rval);
iterator = get_temp_regvar (ptrdiff_type_node, maxindex);
+ /* If initializing one array from another, initialize element by
+ element. We rely upon the below calls to do the argument
+ checking. Evaluate the initializer before entering the try block. */
+ if (from_array && init && TREE_CODE (init) != CONSTRUCTOR)
+ {
+ base2 = decay_conversion (init);
+ itype = TREE_TYPE (base2);
+ base2 = get_temp_regvar (itype, base2);
+ itype = TREE_TYPE (itype);
+ }
+
/* Protect the entire array initialization so that we can destroy
the partially constructed array if an exception is thrown.
But don't do this if we're assigning. */
if (init != NULL_TREE && TREE_CODE (init) == CONSTRUCTOR)
{
- /* Do non-default initialization of non-POD arrays resulting from
+ /* Do non-default initialization of non-trivial arrays resulting from
brace-enclosed initializers. */
unsigned HOST_WIDE_INT idx;
tree elt;
}
else if (from_array)
{
- /* If initializing one array from another, initialize element by
- element. We rely upon the below calls the do argument
- checking. */
if (init)
- {
- base2 = decay_conversion (init);
- itype = TREE_TYPE (base2);
- base2 = get_temp_regvar (itype, base2);
- itype = TREE_TYPE (itype);
- }
+ /* OK, we set base2 above. */;
else if (TYPE_LANG_SPECIFIC (type)
&& TYPE_NEEDS_CONSTRUCTING (type)
&& ! TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
0, complain);
}
else if (explicit_value_init_p)
- elt_init = build2 (INIT_EXPR, type, to,
- build_value_init (type));
+ {
+ elt_init = build_value_init (type, complain);
+ if (elt_init == error_mark_node)
+ return error_mark_node;
+ else
+ elt_init = build2 (INIT_EXPR, type, to, elt_init);
+ }
else
{
gcc_assert (TYPE_NEEDS_CONSTRUCTING (type));
{
atype = build_pointer_type (atype);
stmt_expr = build1 (NOP_EXPR, atype, stmt_expr);
- stmt_expr = cp_build_indirect_ref (stmt_expr, NULL, complain);
+ stmt_expr = cp_build_indirect_ref (stmt_expr, RO_NULL, complain);
TREE_NO_WARNING (stmt_expr) = 1;
}
type = TYPE_MAIN_VARIANT (type);
+ addr = mark_rvalue_use (addr);
+
if (TREE_CODE (type) == POINTER_TYPE)
{
bool complete_p = true;
/*alloc_fn=*/NULL_TREE);
}
- expr = build_dtor_call (cp_build_indirect_ref (addr, NULL,
+ expr = build_dtor_call (cp_build_indirect_ref (addr, RO_NULL,
tf_warning_or_error),
auto_delete, flags);
if (do_delete)
finish_decl_cleanup (NULL_TREE, expr);
}
+ /* Don't automatically destroy union members. */
+ if (TREE_CODE (current_class_type) == UNION_TYPE)
+ return;
+
for (member = TYPE_FIELDS (current_class_type); member;
- member = TREE_CHAIN (member))
+ member = DECL_CHAIN (member))
{
- if (TREE_TYPE (member) == error_mark_node
+ tree this_type = TREE_TYPE (member);
+ if (this_type == error_mark_node
|| TREE_CODE (member) != FIELD_DECL
|| DECL_ARTIFICIAL (member))
continue;
- if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (member)))
+ if (ANON_UNION_TYPE_P (this_type))
+ continue;
+ if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (this_type))
{
tree this_member = (build_class_member_access_expr
(current_class_ref, member,
/*access_path=*/NULL_TREE,
/*preserve_reference=*/false,
tf_warning_or_error));
- tree this_type = TREE_TYPE (member);
expr = build_delete (this_type, this_member,
sfk_complete_destructor,
LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL,
base = TARGET_EXPR_SLOT (base_init);
}
type = strip_array_types (TREE_TYPE (type));
- cookie_addr = fold_build1 (NEGATE_EXPR, sizetype, TYPE_SIZE_UNIT (sizetype));
+ cookie_addr = fold_build1_loc (input_location, NEGATE_EXPR,
+ sizetype, TYPE_SIZE_UNIT (sizetype));
cookie_addr = build2 (POINTER_PLUS_EXPR,
size_ptr_type,
fold_convert (size_ptr_type, base),
cookie_addr);
- maxindex = cp_build_indirect_ref (cookie_addr, NULL, tf_warning_or_error);
+ maxindex = cp_build_indirect_ref (cookie_addr, RO_NULL, tf_warning_or_error);
}
else if (TREE_CODE (type) == ARRAY_TYPE)
{