decl2.c (find_representative_member): New function.

* decl2.c (find_representative_member): New function.
	(finish_anon_union): Use it.

From-SVN: r19910
This commit is contained in:
Mark Mitchell 1998-05-20 11:03:18 +00:00 committed by Mark Mitchell
parent f9c3933a4b
commit ce1b9eb9a8
3 changed files with 60 additions and 17 deletions

View File

@ -1,5 +1,8 @@
1998-05-20 Mark Mitchell <mmitchell@usa.net> 1998-05-20 Mark Mitchell <mmitchell@usa.net>
* decl2.c (find_representative_member): New function.
(finish_anon_union): Use it.
* cp-tree.h (MAIN_NAME_P): New macro. * cp-tree.h (MAIN_NAME_P): New macro.
(DECL_MAIN_P): Likwise. (DECL_MAIN_P): Likwise.
* decl.c (pushdecl): Avoid crashing on redefinitions of `main'. * decl.c (pushdecl): Avoid crashing on redefinitions of `main'.

View File

@ -52,6 +52,7 @@ static int is_namespace_ancestor PROTO((tree, tree));
static tree namespace_ancestor PROTO((tree, tree)); static tree namespace_ancestor PROTO((tree, tree));
static void add_using_namespace PROTO((tree, tree, int)); static void add_using_namespace PROTO((tree, tree, int));
static tree ambiguous_decl PROTO((tree, tree, tree)); static tree ambiguous_decl PROTO((tree, tree, tree));
static tree find_representative_member PROTO((tree));
extern int current_class_depth; extern int current_class_depth;
@ -2144,6 +2145,43 @@ get_temp_regvar (type, init)
return decl; return decl;
} }
/* Hunt through ANON_DECL, which declares an anonymous union, for a named
member of the same size as ANON_DECL. */
tree
find_representative_member (anon_decl)
tree anon_decl;
{
tree field;
tree main_decl = NULL_TREE;
for (field = TYPE_FIELDS (TREE_TYPE (anon_decl));
field != NULL_TREE;
field = TREE_CHAIN (field))
{
if (TREE_CODE (field) != FIELD_DECL)
continue;
/* 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
/* ??? This causes there to be no debug info written out
about this decl. */
TREE_ASM_WRITTEN (field) = 1;
}
return main_decl;
}
/* Finish off the processing of a UNION_TYPE structure. /* Finish off the processing of a UNION_TYPE structure.
If there are static members, then all members are If there are static members, then all members are
static, and must be laid out together. If the static, and must be laid out together. If the
@ -2156,13 +2194,13 @@ finish_anon_union (anon_union_decl)
tree anon_union_decl; tree anon_union_decl;
{ {
tree type = TREE_TYPE (anon_union_decl); tree type = TREE_TYPE (anon_union_decl);
tree field, main_decl = NULL_TREE; tree field = TYPE_FIELDS (type);
tree elems = NULL_TREE; tree elems = NULL_TREE;
int public_p = TREE_PUBLIC (anon_union_decl); int public_p = TREE_PUBLIC (anon_union_decl);
int static_p = TREE_STATIC (anon_union_decl); int static_p = TREE_STATIC (anon_union_decl);
int external_p = DECL_EXTERNAL (anon_union_decl); int external_p = DECL_EXTERNAL (anon_union_decl);
if ((field = TYPE_FIELDS (type)) == NULL_TREE) if (field == NULL_TREE)
return; return;
if (public_p) if (public_p)
@ -2182,6 +2220,14 @@ finish_anon_union (anon_union_decl)
else if (TREE_PROTECTED (field)) else if (TREE_PROTECTED (field))
cp_pedwarn_at ("protected member `%#D' in anonymous union", 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)); decl = build_decl (VAR_DECL, DECL_NAME (field), TREE_TYPE (field));
/* tell `pushdecl' that this is not tentative. */ /* tell `pushdecl' that this is not tentative. */
DECL_INITIAL (decl) = error_mark_node; DECL_INITIAL (decl) = error_mark_node;
@ -2190,29 +2236,17 @@ finish_anon_union (anon_union_decl)
DECL_EXTERNAL (decl) = external_p; DECL_EXTERNAL (decl) = external_p;
decl = pushdecl (decl); decl = pushdecl (decl);
/* 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 (decl),
DECL_SIZE (anon_union_decl)))
{
main_decl = decl;
}
else
{
/* ??? This causes there to be no debug info written out
about this decl. */
TREE_ASM_WRITTEN (decl) = 1;
}
DECL_INITIAL (decl) = NULL_TREE; DECL_INITIAL (decl) = NULL_TREE;
/* If there's a cleanup to do, it belongs in the /* If there's a cleanup to do, it belongs in the
TREE_PURPOSE of the following TREE_LIST. */ TREE_PURPOSE of the following TREE_LIST. */
elems = scratch_tree_cons (NULL_TREE, decl, elems); elems = scratch_tree_cons (NULL_TREE, decl, elems);
TREE_TYPE (elems) = type; TREE_TYPE (elems) = type;
} }
if (static_p) if (static_p)
{ {
tree main_decl = find_representative_member (anon_union_decl);
if (main_decl) if (main_decl)
{ {
make_decl_rtl (main_decl, 0, toplevel_bindings_p ()); make_decl_rtl (main_decl, 0, toplevel_bindings_p ());

View File

@ -0,0 +1,6 @@
// Build don't link:
static union {
union {
};
}; // ERROR - anonymous union with no members