PATCH for crash with anonymous unions

Mark Mitchell mmitchell@usa.net
Tue May 19 19:49:00 GMT 1998


Jason --

  Here's a patch for the abort on code like this:

    static union {
      union {
      };
    };

  This used to cause a crash.  OK?
  
-- 
Mark Mitchell <mmitchell@usa.net>
http://home.earthlink.net/~mbmitchell
Consulting Services Available

Tue May 19 15:48:01 1998  Mark Mitchell  <mmitchell@usa.net>

	* decl2.c (find_representative_member): New function.
	(finish_anon_union): Use it.
	
Index: decl2.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl2.c,v
retrieving revision 1.71
diff -c -p -r1.71 decl2.c
*** decl2.c	1998/05/18 23:23:05	1.71
--- decl2.c	1998/05/19 22:49:32
*************** static int is_namespace_ancestor PROTO((
*** 52,57 ****
--- 52,58 ----
  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));
  
  extern int current_class_depth;
  
*************** get_temp_regvar (type, init)
*** 2144,2149 ****
--- 2148,2186 ----
    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)))
+ 	main_decl = 
+ 	  DECL_NAME (field) ? field : 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.
     If there are static members, then all members are
     static, and must be laid out together.  If the
*************** finish_anon_union (anon_union_decl)
*** 2156,2168 ****
       tree anon_union_decl;
  {
    tree type = TREE_TYPE (anon_union_decl);
!   tree field, main_decl = NULL_TREE;
    tree elems = NULL_TREE;
    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 = TYPE_FIELDS (type)) == NULL_TREE)
      return;
  
    if (public_p)
--- 2193,2205 ----
       tree anon_union_decl;
  {
    tree type = TREE_TYPE (anon_union_decl);
!   tree field = TYPE_FIELDS (type);
    tree elems = NULL_TREE;
    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)
      return;
  
    if (public_p)
*************** finish_anon_union (anon_union_decl)
*** 2182,2187 ****
--- 2219,2231 ----
        else if (TREE_PROTECTED (field))
  	cp_pedwarn_at ("protected member `%#D' in anonymous union", field);
  
+       if (DECL_NAME (field) == NULL_TREE
+ 	  && 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;
*************** finish_anon_union (anon_union_decl)
*** 2190,2218 ****
        DECL_EXTERNAL (decl) = external_p;
        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;
        /* 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;
      }
    if (static_p)
      {
        if (main_decl)
  	{
  	  make_decl_rtl (main_decl, 0, toplevel_bindings_p ());
--- 2234,2250 ----
        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;
      }
+ 
    if (static_p)
      {
+       tree main_decl = find_representative_member (anon_union_decl);
+ 
        if (main_decl)
  	{
  	  make_decl_rtl (main_decl, 0, toplevel_bindings_p ());



More information about the Gcc-bugs mailing list