Handle anonymous unions at the tree level.

C++ ABI change: Mangle anonymous unions using the name of their
        first named field (by depth-first search).  Should not cause
        binary compatibility problems, though, as the compiler previously
        didn't emit anything for affected unions.
        * cp-tree.def (ALIAS_DECL): New tree code.
        * decl2.c (build_anon_union_vars): Build ALIAS_DECLs.  Return the
        first field, not the largest.
        (finish_anon_union): Don't mess with RTL.  Do set DECL_ASSEMBLER_NAME,
        push the decl, and write it out at namespace scope.
        * decl.c (lookup_name_real): See through an ALIAS_DECL.
        (pushdecl): Add namespace bindings for ALIAS_DECLs.
        * rtti.c (unemitted_tinfo_decl_p): Don't try to look at the name
        of a decl which doesn't have one.
        * typeck.c (build_class_member_access_expr): Don't recurse if
        we already have the type we want.

From-SVN: r60314
This commit is contained in:
Jason Merrill 2002-12-19 12:16:26 -05:00 committed by Jason Merrill
parent e54b4cae03
commit 0ca7178c84
6 changed files with 70 additions and 79 deletions

View File

@ -1,3 +1,22 @@
2002-12-18 Jason Merrill <jason@redhat.com>
Handle anonymous unions at the tree level.
C++ ABI change: Mangle anonymous unions using the name of their
first named field (by depth-first search). Should not cause
binary compatibility problems, though, as the compiler previously
didn't emit anything for affected unions.
* cp-tree.def (ALIAS_DECL): New tree code.
* decl2.c (build_anon_union_vars): Build ALIAS_DECLs. Return the
first field, not the largest.
(finish_anon_union): Don't mess with RTL. Do set DECL_ASSEMBLER_NAME,
push the decl, and write it out at namespace scope.
* decl.c (lookup_name_real): See through an ALIAS_DECL.
(pushdecl): Add namespace bindings for ALIAS_DECLs.
* rtti.c (unemitted_tinfo_decl_p): Don't try to look at the name
of a decl which doesn't have one.
* typeck.c (build_class_member_access_expr): Don't recurse if
we already have the type we want.
2002-12-18 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
PR c++/8099

View File

@ -89,6 +89,10 @@ DEFTREECODE (THROW_EXPR, "throw_expr", 'e', 1)
these to avoid actually creating instances of the empty classes. */
DEFTREECODE (EMPTY_CLASS_EXPR, "empty_class_expr", 'e', 0)
/* A DECL which is really just a placeholder for an expression. Used to
implement non-class scope anonymous unions. */
DEFTREECODE (ALIAS_DECL, "alias_decl", 'd', 0)
/* A reference to a member function or member functions from a base
class. BASELINK_FUNCTIONS gives the FUNCTION_DECL,
TEMPLATE_DECL, OVERLOAD, or TEMPLATE_ID_EXPR corresponding to the

View File

@ -4051,6 +4051,7 @@ pushdecl (x)
&& t != NULL_TREE)
&& (TREE_CODE (x) == TYPE_DECL
|| TREE_CODE (x) == VAR_DECL
|| TREE_CODE (x) == ALIAS_DECL
|| TREE_CODE (x) == NAMESPACE_DECL
|| TREE_CODE (x) == CONST_DECL
|| TREE_CODE (x) == TEMPLATE_DECL))
@ -6228,6 +6229,9 @@ does not match lookup in the current scope (`%#D')",
else if (from_obj)
val = from_obj;
if (val && TREE_CODE (val) == ALIAS_DECL)
val = DECL_INITIAL (val);
return val;
}

View File

@ -66,7 +66,7 @@ static int maybe_emit_vtables (tree);
static int is_namespace_ancestor PARAMS ((tree, tree));
static void add_using_namespace PARAMS ((tree, tree, int));
static tree ambiguous_decl PARAMS ((tree, tree, tree,int));
static tree build_anon_union_vars PARAMS ((tree, tree*, int, int));
static tree build_anon_union_vars PARAMS ((tree));
static int acceptable_java_type PARAMS ((tree));
static void output_vtable_inherit PARAMS ((tree));
static tree start_objects PARAMS ((int, int));
@ -1269,22 +1269,15 @@ defer_fn (fn)
VARRAY_PUSH_TREE (deferred_fns, fn);
}
/* 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.
/* Walks through the namespace- or function-scope anonymous union OBJECT,
building appropriate ALIAS_DECLs. Returns one of the fields for use in
the mangled name. */
FIXME: we should really handle anonymous unions by binding the names
of the members to COMPONENT_REFs rather than this kludge. */
static tree
build_anon_union_vars (anon_decl, elems, static_p, external_p)
tree anon_decl;
tree* elems;
int static_p;
int external_p;
static tree
build_anon_union_vars (object)
tree object;
{
tree type = TREE_TYPE (anon_decl);
tree type = TREE_TYPE (object);
tree main_decl = NULL_TREE;
tree field;
@ -1298,12 +1291,14 @@ build_anon_union_vars (anon_decl, elems, static_p, external_p)
field = TREE_CHAIN (field))
{
tree decl;
tree ref;
if (DECL_ARTIFICIAL (field))
continue;
if (TREE_CODE (field) != FIELD_DECL)
{
cp_pedwarn_at ("`%#D' invalid; an anonymous union can only have non-static data members",
cp_pedwarn_at ("\
`%#D' invalid; an anonymous union can only have non-static data members",
field);
continue;
}
@ -1313,55 +1308,25 @@ build_anon_union_vars (anon_decl, elems, static_p, external_p)
else if (TREE_PROTECTED (field))
cp_pedwarn_at ("protected member `%#D' in anonymous union", field);
if (DECL_NAME (field) == NULL_TREE
&& ANON_AGGR_TYPE_P (TREE_TYPE (field)))
ref = build_class_member_access_expr (object, field, NULL_TREE,
false);
if (DECL_NAME (field))
{
decl = build_anon_union_vars (field, elems, static_p, external_p);
if (!decl)
continue;
}
else if (DECL_NAME (field) == NULL_TREE)
continue;
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;
decl = build_decl (ALIAS_DECL, DECL_NAME (field), TREE_TYPE (field));
DECL_INITIAL (decl) = ref;
TREE_PUBLIC (decl) = 0;
TREE_STATIC (decl) = static_p;
DECL_EXTERNAL (decl) = external_p;
TREE_STATIC (decl) = 0;
DECL_EXTERNAL (decl) = 1;
decl = pushdecl (decl);
DECL_INITIAL (decl) = NULL_TREE;
}
else if (ANON_AGGR_TYPE_P (TREE_TYPE (field)))
decl = build_anon_union_vars (ref);
/* Only write out one anon union element--choose the largest
one. We used to try to find one the same size as the union,
but that fails if the ABI forces us to align the union more
strictly. */
if (main_decl == NULL_TREE
|| tree_int_cst_lt (DECL_SIZE (main_decl), DECL_SIZE (decl)))
{
if (main_decl)
TREE_ASM_WRITTEN (main_decl) = 1;
main_decl = decl;
}
else
/* ??? This causes there to be no debug info written out
about this decl. */
TREE_ASM_WRITTEN (decl) = 1;
if (DECL_NAME (field) == NULL_TREE
&& ANON_AGGR_TYPE_P (TREE_TYPE (field)))
/* 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 = tree_cons (NULL_TREE, decl, *elems);
TREE_TYPE (*elems) = type;
if (main_decl == NULL_TREE)
main_decl = decl;
}
return main_decl;
}
@ -1376,8 +1341,6 @@ finish_anon_union (anon_union_decl)
tree type = TREE_TYPE (anon_union_decl);
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);
/* The VAR_DECL's context is the same as the TYPE's context. */
DECL_CONTEXT (anon_union_decl) = DECL_CONTEXT (TYPE_NAME (type));
@ -1393,29 +1356,27 @@ finish_anon_union (anon_union_decl)
if (!processing_template_decl)
{
main_decl
= build_anon_union_vars (anon_union_decl,
&DECL_ANON_UNION_ELEMS (anon_union_decl),
static_p, external_p);
main_decl = build_anon_union_vars (anon_union_decl);
if (main_decl == NULL_TREE)
{
warning ("anonymous aggregate with no members");
warning ("anonymous union with no members");
return;
}
if (static_p)
{
make_decl_rtl (main_decl, 0);
COPY_DECL_RTL (main_decl, anon_union_decl);
expand_anon_union_decl (anon_union_decl,
NULL_TREE,
DECL_ANON_UNION_ELEMS (anon_union_decl));
return;
}
/* Use main_decl to set the mangled name. */
DECL_NAME (anon_union_decl) = DECL_NAME (main_decl);
mangle_decl (anon_union_decl);
DECL_NAME (anon_union_decl) = NULL_TREE;
}
add_decl_stmt (anon_union_decl);
pushdecl (anon_union_decl);
if (building_stmt_tree ()
&& at_function_scope_p ())
add_decl_stmt (anon_union_decl);
else if (!processing_template_decl)
rest_of_decl_compilation (anon_union_decl, NULL,
toplevel_bindings_p (), at_eof);
}
/* Auxiliary functions to make type signatures for

View File

@ -1444,7 +1444,9 @@ unemitted_tinfo_decl_p (t, data)
{
if (/* It's a var decl */
TREE_CODE (t) == VAR_DECL
/* whos name points back to itself */
/* which has a name */
&& DECL_NAME (t)
/* whose name points back to itself */
&& IDENTIFIER_GLOBAL_VALUE (DECL_NAME (t)) == t
/* whose name's type is non-null */
&& TREE_TYPE (DECL_NAME (t))

View File

@ -1987,7 +1987,8 @@ build_class_member_access_expr (tree object, tree member,
OBJECT so that it refers to the class containing the
anonymous union. Generate a reference to the anonymous union
itself, and recur to find MEMBER. */
if (ANON_AGGR_TYPE_P (DECL_CONTEXT (member)))
if (ANON_AGGR_TYPE_P (DECL_CONTEXT (member))
&& !same_type_p (object_type, DECL_CONTEXT (member)))
{
tree anonymous_union;