aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <merrill@gnu.org>1994-10-11 18:39:14 +0000
committerJason Merrill <merrill@gnu.org>1994-10-11 18:39:14 +0000
commit0171aeabee95d99ba1c6988f98210409a62b37c4 (patch)
tree2a8b84d728ba429a675a6a9f4d1ab449ec0a3632
parentfef71f9d2bc4f87bd2ea6c8874a00f76ba8b0676 (diff)
downloadgcc-0171aeabee95d99ba1c6988f98210409a62b37c4.zip
gcc-0171aeabee95d99ba1c6988f98210409a62b37c4.tar.gz
gcc-0171aeabee95d99ba1c6988f98210409a62b37c4.tar.bz2
(do_build_copy_constructor): Handle anonymous unions.
(do_build_assign_ref): Ditto. (largest_union_member): Move from lex.c. From-SVN: r8253
-rw-r--r--gcc/cp/method.c35
1 files changed, 33 insertions, 2 deletions
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index f32d005..23fffe4 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -1980,6 +1980,23 @@ build_default_constructor (fndecl)
finish_function (lineno, 0);
}
+/* For the anonymous union in TYPE, return the member that is at least as
+ large as the rest of the members, so we can copy it. */
+static tree
+largest_union_member (type)
+ tree type;
+{
+ tree f, type_size = TYPE_SIZE (type);
+
+ for (f = TYPE_FIELDS (type); f; f = TREE_CHAIN (f))
+ if (simple_cst_equal (DECL_SIZE (f), type_size))
+ return f;
+
+ /* We should always find one. */
+ my_friendly_abort (323);
+ return NULL_TREE;
+}
+
/* Generate code for default X(X&) constructor. */
void
build_copy_constructor (fndecl)
@@ -2034,7 +2051,7 @@ build_copy_constructor (fndecl)
}
for (; fields; fields = TREE_CHAIN (fields))
{
- tree name, init;
+ tree name, init, t;
if (TREE_CODE (fields) != FIELD_DECL)
continue;
if (DECL_NAME (fields))
@@ -2048,6 +2065,13 @@ build_copy_constructor (fndecl)
if (IDENTIFIER_CLASS_VALUE (DECL_NAME (fields)) != fields)
continue;
}
+ else if ((t = TREE_TYPE (fields)) != NULL_TREE
+ && TREE_CODE (t) == UNION_TYPE
+ && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))
+ && TYPE_FIELDS (t) != NULL_TREE)
+ fields = largest_union_member (t);
+ else
+ continue;
init = build (COMPONENT_REF, TREE_TYPE (fields), parm, fields);
init = build_tree_list (NULL_TREE, init);
@@ -2103,7 +2127,7 @@ build_assign_ref (fndecl)
}
for (; fields; fields = TREE_CHAIN (fields))
{
- tree comp, init;
+ tree comp, init, t;
if (TREE_CODE (fields) != FIELD_DECL)
continue;
if (DECL_NAME (fields))
@@ -2117,6 +2141,13 @@ build_assign_ref (fndecl)
if (IDENTIFIER_CLASS_VALUE (DECL_NAME (fields)) != fields)
continue;
}
+ else if ((t = TREE_TYPE (fields)) != NULL_TREE
+ && TREE_CODE (t) == UNION_TYPE
+ && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))
+ && TYPE_FIELDS (t) != NULL_TREE)
+ fields = largest_union_member (t);
+ else
+ continue;
comp = build (COMPONENT_REF, TREE_TYPE (fields), C_C_D, fields);
init = build (COMPONENT_REF, TREE_TYPE (fields), parm, fields);