diff options
author | Jason Merrill <jason@redhat.com> | 2010-07-14 13:00:51 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2010-07-14 13:00:51 -0400 |
commit | 57ece2583335d663e2787df4f6fe3804ec921ea9 (patch) | |
tree | 152c38c98a68f7f49ca34046d6b08f92764dea84 /gcc/cp/init.c | |
parent | a9c5db803f4921a59f8a97307df66bd0f546ff42 (diff) | |
download | gcc-57ece2583335d663e2787df4f6fe3804ec921ea9.zip gcc-57ece2583335d663e2787df4f6fe3804ec921ea9.tar.gz gcc-57ece2583335d663e2787df4f6fe3804ec921ea9.tar.bz2 |
Implement C++0x unrestricted unions (N2544)
Implement C++0x unrestricted unions (N2544)
* class.c (check_field_decl): Loosen union handling in C++0x.
* method.c (walk_field_subobs): Split out from...
(synthesized_method_walk): ...here. Set msg before loops.
(process_subob_fn): Check for triviality in union members.
* init.c (sort_mem_initializers): Splice out uninitialized
anonymous unions and union members.
(push_base_cleanups): Don't automatically destroy anonymous unions
and union members.
From-SVN: r162187
Diffstat (limited to 'gcc/cp/init.c')
-rw-r--r-- | gcc/cp/init.c | 53 |
1 files changed, 41 insertions, 12 deletions
diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 20f921d..4e7cab3 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -708,23 +708,34 @@ 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; 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)) @@ -732,14 +743,19 @@ sort_mem_initializers (tree t, tree mem_inits) break; /* If this field is not a member of a union, skip it. */ if (TREE_CODE (field_type) != UNION_TYPE) - continue; + 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 @@ -785,6 +801,13 @@ sort_mem_initializers (tree t, tree mem_inits) while (!done); last_field = field; + + next: + p = &TREE_CHAIN (*p); + continue; + splice: + *p = TREE_CHAIN (*p); + continue; } } @@ -3353,21 +3376,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)) { - 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, |