Handle anonymous unions at the tree level.
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 19 Dec 2002 17:16:26 +0000 (17:16 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 19 Dec 2002 17:16:26 +0000 (17:16 +0000)
        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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@60314 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/cp-tree.def
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/rtti.c
gcc/cp/typeck.c

index 1d7d395..b19003e 100644 (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
index 1aae797..436f840 100644 (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
index 870a13d..0209e34 100644 (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;
 }
 
index 6734301..f33ba8d 100644 (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)))
-       {
-         decl = build_anon_union_vars (field, elems, static_p, external_p);
-         if (!decl)
-           continue;
-       }
-      else if (DECL_NAME (field) == NULL_TREE)
-       continue;
-      else
+      ref = build_class_member_access_expr (object, field, NULL_TREE,
+                                           false);
+
+      if (DECL_NAME (field))
        {
-         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;
-       }
-
-      /* 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;
+      else if (ANON_AGGR_TYPE_P (TREE_TYPE (field)))
+       decl = build_anon_union_vars (ref);
 
-      /* 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);
 }
 \f
 /* Auxiliary functions to make type signatures for
index d8041ab..495e0d4 100644 (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))
index 769702b..9285ec0 100644 (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;