summaryrefslogtreecommitdiff
path: root/gcc/cp/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/init.c')
-rw-r--r--gcc/cp/init.c136
1 files changed, 79 insertions, 57 deletions
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 85ad582f2d1..d796fd0822c 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -184,7 +184,7 @@ build_zero_init (tree type, tree nelts, bool static_storage_p)
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;
@@ -337,7 +337,7 @@ build_value_init_noctor (tree 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;
@@ -525,7 +525,8 @@ perform_member_init (tree member, tree init)
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, ELK_MEM_INIT);
+ 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,
@@ -562,27 +563,29 @@ build_field_list (tree t, tree list, int *uses_unions_p)
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))
@@ -708,38 +711,54 @@ sort_mem_initializers (tree t, tree mem_inits)
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
@@ -750,41 +769,48 @@ sort_mem_initializers (tree t, tree mem_inits)
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;
}
}
@@ -1005,7 +1031,7 @@ construct_virtual_base (tree vbase, tree arguments)
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);
@@ -1374,7 +1400,7 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int 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
@@ -1507,18 +1533,9 @@ build_offset_ref (tree type, tree member, bool address_p)
if (TREE_CODE (member) == TEMPLATE_DECL)
return member;
- if (dependent_type_p (type) || type_dependent_expression_p (member))
- {
- tree ref, mem_type = NULL_TREE;
- if (!dependent_scope_p (type))
- mem_type = TREE_TYPE (member);
- ref = build_qualified_name (mem_type, type, member,
+ if (dependent_scope_p (type) || type_dependent_expression_p (member))
+ return build_qualified_name (NULL_TREE, type, member,
/*template_p=*/false);
- /* Undo convert_from_reference. */
- if (TREE_CODE (ref) == INDIRECT_REF)
- ref = TREE_OPERAND (ref, 0);
- return ref;
- }
gcc_assert (TYPE_P (type));
if (! is_class_type (type, 1))
@@ -1528,6 +1545,7 @@ build_offset_ref (tree type, tree member, bool address_p)
/* Callers should call mark_used before this point. */
gcc_assert (!DECL_P (member) || TREE_USED (member));
+ 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);
@@ -1798,7 +1816,7 @@ diagnose_uninitialized_cst_or_ref_member_1 (tree type, tree origin,
if (type_has_user_provided_constructor (type))
return 0;
- for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
{
tree field_type;
@@ -2016,10 +2034,8 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
}
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))
{
@@ -2561,7 +2577,7 @@ build_java_class_ref (tree type)
/* 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);
@@ -2726,7 +2742,7 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
/* 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. */
@@ -3361,21 +3377,27 @@ push_base_cleanups (void)
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,