aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Mitchell <mmitchell@usa.net>1998-05-21 00:48:49 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>1998-05-21 00:48:49 +0000
commitcb96daa2dcb181abb218017a4de32838285094fa (patch)
tree7ab08ece36e47071a3f82d11d4879b0babf319a5
parentf9d94ea4d411ebc87081197daa8b53c65e50c6bd (diff)
downloadgcc-cb96daa2dcb181abb218017a4de32838285094fa.zip
gcc-cb96daa2dcb181abb218017a4de32838285094fa.tar.gz
gcc-cb96daa2dcb181abb218017a4de32838285094fa.tar.bz2
decl2.c (find_representative_member): Rename to ...
* decl2.c (find_representative_member): Rename to ... (build_anon_union_vars): New function. (finish_anon_union): Fix stupidity of previous change. From-SVN: r19920
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/decl2.c110
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/anon2.C31
3 files changed, 92 insertions, 55 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 6353d8d..b89b270 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+1998-05-21 Mark Mitchell <mmitchell@usa.net>
+
+ * decl2.c (find_representative_member): Rename to ...
+ (build_anon_union_vars): New function.
+ (finish_anon_union): Fix stupidity of previous change.
+
1998-05-20 Jason Merrill <jason@yorick.cygnus.com>
* decl.c (grokfndecl): Handle definition of specialization in
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 63b90d7..a7daa2a 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -52,7 +52,7 @@ static int is_namespace_ancestor PROTO((tree, tree));
static tree namespace_ancestor PROTO((tree, tree));
static void add_using_namespace PROTO((tree, tree, int));
static tree ambiguous_decl PROTO((tree, tree, tree));
-static tree find_representative_member PROTO((tree));
+static tree build_anon_union_vars PROTO((tree, tree*, int, int));
extern int current_class_depth;
@@ -2145,40 +2145,73 @@ get_temp_regvar (type, init)
return decl;
}
-/* Hunt through ANON_DECL, which declares an anonymous union, for a named
- member of the same size as ANON_DECL. */
+/* Hunts through the global anonymous union ANON_DECL, building
+ appropriate VAR_DECLs. Stores cleanups on the list of ELEMS, and
+ returns a VAR_DECL whose size is the same as the size of the
+ ANON_DECL, if one is available. */
-tree
-find_representative_member (anon_decl)
+tree
+build_anon_union_vars (anon_decl, elems, static_p, external_p)
tree anon_decl;
+ tree* elems;
+ int static_p;
+ int external_p;
{
- tree field;
+ tree type = TREE_TYPE (anon_decl);
tree main_decl = NULL_TREE;
+ tree field;
- for (field = TYPE_FIELDS (TREE_TYPE (anon_decl));
+ for (field = TYPE_FIELDS (type);
field != NULL_TREE;
field = TREE_CHAIN (field))
{
+ tree decl;
if (TREE_CODE (field) != FIELD_DECL)
continue;
+ if (TREE_PRIVATE (field))
+ cp_pedwarn_at ("private member `%#D' in anonymous union", field);
+ else if (TREE_PROTECTED (field))
+ cp_pedwarn_at ("protected member `%#D' in anonymous union", field);
+
+ if (DECL_NAME (field) == NULL_TREE
+ && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
+ decl = build_anon_union_vars (field, elems, static_p, external_p);
+ else
+ {
+ decl = build_decl (VAR_DECL, DECL_NAME (field), TREE_TYPE (field));
+ /* tell `pushdecl' that this is not tentative. */
+ DECL_INITIAL (decl) = error_mark_node;
+ TREE_PUBLIC (decl) = 0;
+ TREE_STATIC (decl) = static_p;
+ DECL_EXTERNAL (decl) = external_p;
+ decl = pushdecl (decl);
+ DECL_INITIAL (decl) = NULL_TREE;
+ }
+
/* Only write out one anon union element--choose the one that
can hold them all. */
if (main_decl == NULL_TREE
- && 1 == simple_cst_equal (DECL_SIZE (field),
- DECL_SIZE (anon_decl)))
- {
- if (DECL_NAME (field))
- main_decl = field;
- else if (TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
- main_decl = find_representative_member (field);
- }
- else
+ && simple_cst_equal (DECL_SIZE (decl),
+ DECL_SIZE (anon_decl)) == 1)
+ main_decl = decl;
+ else
/* ??? This causes there to be no debug info written out
about this decl. */
- TREE_ASM_WRITTEN (field) = 1;
- }
+ TREE_ASM_WRITTEN (decl) = 1;
+
+ if (DECL_NAME (field) == NULL_TREE
+ && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
+ /* The remainder of the processing was already done in the
+ recursive call. */
+ continue;
+ /* If there's a cleanup to do, it belongs in the
+ TREE_PURPOSE of the following TREE_LIST. */
+ *elems = scratch_tree_cons (NULL_TREE, decl, *elems);
+ TREE_TYPE (*elems) = type;
+ }
+
return main_decl;
}
@@ -2194,13 +2227,13 @@ finish_anon_union (anon_union_decl)
tree anon_union_decl;
{
tree type = TREE_TYPE (anon_union_decl);
- tree field = TYPE_FIELDS (type);
tree elems = NULL_TREE;
+ tree main_decl;
int public_p = TREE_PUBLIC (anon_union_decl);
int static_p = TREE_STATIC (anon_union_decl);
int external_p = DECL_EXTERNAL (anon_union_decl);
- if (field == NULL_TREE)
+ if (TYPE_FIELDS (type) == NULL_TREE)
return;
if (public_p)
@@ -2209,44 +2242,11 @@ finish_anon_union (anon_union_decl)
return;
}
- for (; field; field = TREE_CHAIN (field))
- {
- tree decl;
- if (TREE_CODE (field) != FIELD_DECL)
- continue;
-
- if (TREE_PRIVATE (field))
- cp_pedwarn_at ("private member `%#D' in anonymous union", field);
- else if (TREE_PROTECTED (field))
- cp_pedwarn_at ("protected member `%#D' in anonymous union", field);
-
- if (DECL_NAME (field) == NULL_TREE
- && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE
- && find_representative_member (field) == NULL_TREE)
- /* The member is an empty anonymous union. Don't make a
- declaration for it, as finish_file will otherwise try to
- call make_decl_rtl for it, and crash. */
- continue;
-
- decl = build_decl (VAR_DECL, DECL_NAME (field), TREE_TYPE (field));
- /* tell `pushdecl' that this is not tentative. */
- DECL_INITIAL (decl) = error_mark_node;
- TREE_PUBLIC (decl) = public_p;
- TREE_STATIC (decl) = static_p;
- DECL_EXTERNAL (decl) = external_p;
- decl = pushdecl (decl);
-
- DECL_INITIAL (decl) = NULL_TREE;
- /* If there's a cleanup to do, it belongs in the
- TREE_PURPOSE of the following TREE_LIST. */
- elems = scratch_tree_cons (NULL_TREE, decl, elems);
- TREE_TYPE (elems) = type;
- }
+ main_decl = build_anon_union_vars (anon_union_decl, &elems,
+ static_p, external_p);
if (static_p)
{
- tree main_decl = find_representative_member (anon_union_decl);
-
if (main_decl)
{
make_decl_rtl (main_decl, 0, toplevel_bindings_p ());
diff --git a/gcc/testsuite/g++.old-deja/g++.other/anon2.C b/gcc/testsuite/g++.old-deja/g++.other/anon2.C
new file mode 100644
index 0000000..49a7b2c
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.other/anon2.C
@@ -0,0 +1,31 @@
+extern "C" void abort (void);
+
+static union {
+ int x1;
+ long x2;
+ short x3;
+ long x4;
+};
+
+static union {
+ union {
+ union {
+ int z;
+ };
+ };
+ union {
+ union {
+ double d;
+ int i;
+ };
+ };
+};
+
+
+int main()
+{
+ z = 3;
+ if (i != 3)
+ abort ();
+ d = 2.5;
+}