Commit ce1b9eb9 by Mark Mitchell Committed by Mark Mitchell

decl2.c (find_representative_member): New function.

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

From-SVN: r19910
parent f9c3933a
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'.
......
...@@ -52,6 +52,7 @@ static int is_namespace_ancestor PROTO((tree, tree)); ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 ());
......
// Build don't link:
static union {
union {
};
}; // ERROR - anonymous union with no members
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment