diff options
author | Mark Mitchell <mmitchell@usa.net> | 1998-05-21 00:48:49 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 1998-05-21 00:48:49 +0000 |
commit | cb96daa2dcb181abb218017a4de32838285094fa (patch) | |
tree | 7ab08ece36e47071a3f82d11d4879b0babf319a5 | |
parent | f9d94ea4d411ebc87081197daa8b53c65e50c6bd (diff) | |
download | gcc-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/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 110 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.other/anon2.C | 31 |
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; +} |