This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH: PR 7754


This PR deals with anonymous unions in template functions.  This feature
never really worked correctly, but we have made it much more visibly
broken in G++ 3.2.  This should fix it so that they really work.

Tested on i686-pc-linux-gnu, applied on the mainline and the branch.

Applied on the mainline and on the branch.

--
Mark Mitchell                mark@codesourcery.com
CodeSourcery, LLC            http://www.codesourcery.com
	PR c++/7754
	* g++.dg/template/union1.C: New test.

	PR c++/7754
	* decl2.c (finish_anon_union): Do not expand anonymous unions when
	procesing template functions.
	* pt.c (tsubst_decl, case VAR_DECL): Try to complete the variable
	type. Call layout_decl.
	(tsubst_expr, case DECL_STMT): Handle anonymous unions.

Index: cp/decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.563
diff -c -5 -p -r1.563 decl2.c
*** cp/decl2.c	21 Sep 2002 12:51:54 -0000	1.563
--- cp/decl2.c	4 Oct 2002 03:48:02 -0000
*************** finish_anon_union (anon_union_decl)
*** 1380,1409 ****
     {
       error ("namespace-scope anonymous aggregates must be static");
       return;
     }

!   main_decl = build_anon_union_vars (anon_union_decl,
! 				     &DECL_ANON_UNION_ELEMS (anon_union_decl),
! 				     static_p, external_p);
!
!   if (main_decl == NULL_TREE)
     {
!       warning ("anonymous aggregate 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));
     }
!   else
!     add_decl_stmt (anon_union_decl);
 }

 /* Finish processing a builtin type TYPE.  It's name is NAME,
    its fields are in the array FIELDS.  LEN is the number of elements
    in FIELDS minus one, or put another way, it is the maximum subscript
--- 1380,1414 ----
     {
       error ("namespace-scope anonymous aggregates must be static");
       return;
     }

!   if (!processing_template_decl)
     {
!       main_decl
! 	= build_anon_union_vars (anon_union_decl,
! 				 &DECL_ANON_UNION_ELEMS (anon_union_decl),
! 				 static_p, external_p);
!
!       if (main_decl == NULL_TREE)
! 	{
! 	  warning ("anonymous aggregate 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;
! 	}
     }
!
!   add_decl_stmt (anon_union_decl);
 }

 /* Finish processing a builtin type TYPE.  It's name is NAME,
    its fields are in the array FIELDS.  LEN is the number of elements
    in FIELDS minus one, or put another way, it is the maximum subscript
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.620
diff -c -5 -p -r1.620 pt.c
*** cp/pt.c	2 Oct 2002 20:01:36 -0000	1.620
--- cp/pt.c	4 Oct 2002 03:48:34 -0000
*************** tsubst_decl (t, args, type, complain)
*** 6123,6133 ****
 	    r = spec;
 	    break;
 	  }

 	r = copy_decl (t);
! 	TREE_TYPE (r) = type;
 	c_apply_type_quals_to_decl (cp_type_quals (type), r);
 	DECL_CONTEXT (r) = ctx;
 	/* Clear out the mangled name and RTL for the instantiation.  */
 	SET_DECL_ASSEMBLER_NAME (r, NULL_TREE);
 	SET_DECL_RTL (r, NULL_RTX);
--- 6132,6142 ----
 	    r = spec;
 	    break;
 	  }

 	r = copy_decl (t);
! 	TREE_TYPE (r) = complete_type (type);
 	c_apply_type_quals_to_decl (cp_type_quals (type), r);
 	DECL_CONTEXT (r) = ctx;
 	/* Clear out the mangled name and RTL for the instantiation.  */
 	SET_DECL_ASSEMBLER_NAME (r, NULL_TREE);
 	SET_DECL_RTL (r, NULL_RTX);
*************** tsubst_decl (t, args, type, complain)
*** 6162,6171 ****
--- 6171,6182 ----
 	  register_local_specialization (r, t);

 	TREE_CHAIN (r) = NULL_TREE;
 	if (TREE_CODE (r) == VAR_DECL && VOID_TYPE_P (type))
 	  cp_error_at ("instantiation of `%D' as type `%T'", r, type);
+ 	/* Compute the size, alignment, etc. of R.  */
+ 	layout_decl (r, 0);
       }
       break;

     default:
       abort ();
*************** tsubst_expr (t, args, complain, in_decl)
*** 7413,7447 ****
 	  {
 	    init = DECL_INITIAL (decl);
 	    decl = tsubst (decl, args, complain, in_decl);
 	    if (decl != error_mark_node)
 	      {
-                 if (TREE_CODE (decl) != TYPE_DECL)
-                   /* Make sure the type is instantiated now.  */
-                   complete_type (TREE_TYPE (decl));
 	        if (init)
 	          DECL_INITIAL (decl) = error_mark_node;
 	        /* By marking the declaration as instantiated, we avoid
 	           trying to instantiate it.  Since instantiate_decl can't
 	           handle local variables, and since we've already done
 	           all that needs to be done, that's the right thing to
 	           do.  */
 	        if (TREE_CODE (decl) == VAR_DECL)
 	          DECL_TEMPLATE_INSTANTIATED (decl) = 1;
! 	        maybe_push_decl (decl);
! 		if (DECL_PRETTY_FUNCTION_P (decl))
 		  {
! 		    /* For __PRETTY_FUNCTION__ we have to adjust the
! 		       initializer.  */
! 		    const char *const name
! 		      = cxx_printable_name (current_function_decl, 2);
! 		    init = cp_fname_init (name);
! 		    TREE_TYPE (decl) = TREE_TYPE (init);
 		  }
- 		else
- 		  init = tsubst_expr (init, args, complain, in_decl);
- 	        cp_finish_decl (decl, init, NULL_TREE, 0);
 	      }
 	  }

 	/* A DECL_STMT can also be used as an expression, in the condition
 	   clause of an if/for/while construct.  If we aren't followed by
--- 7424,7462 ----
 	  {
 	    init = DECL_INITIAL (decl);
 	    decl = tsubst (decl, args, complain, in_decl);
 	    if (decl != error_mark_node)
 	      {
 	        if (init)
 	          DECL_INITIAL (decl) = error_mark_node;
 	        /* By marking the declaration as instantiated, we avoid
 	           trying to instantiate it.  Since instantiate_decl can't
 	           handle local variables, and since we've already done
 	           all that needs to be done, that's the right thing to
 	           do.  */
 	        if (TREE_CODE (decl) == VAR_DECL)
 	          DECL_TEMPLATE_INSTANTIATED (decl) = 1;
! 		if (TREE_CODE (decl) == VAR_DECL
! 		    && ANON_AGGR_TYPE_P (TREE_TYPE (decl)))
! 		  /* Anonymous aggregates are a special case.  */
! 		  finish_anon_union (decl);
! 		else
 		  {
! 		    maybe_push_decl (decl);
! 		    if (DECL_PRETTY_FUNCTION_P (decl))
! 		      {
! 			/* For __PRETTY_FUNCTION__ we have to adjust the
! 			   initializer.  */
! 			const char *const name
! 			  = cxx_printable_name (current_function_decl, 2);
! 			init = cp_fname_init (name);
! 			TREE_TYPE (decl) = TREE_TYPE (init);
! 		      }
! 		    else
! 		      init = tsubst_expr (init, args, complain, in_decl);
! 		    cp_finish_decl (decl, init, NULL_TREE, 0);
 		  }
 	      }
 	  }

 	/* A DECL_STMT can also be used as an expression, in the condition
 	   clause of an if/for/while construct.  If we aren't followed by
Index: testsuite/g++.dg/template/union1.C
===================================================================
RCS file: testsuite/g++.dg/template/union1.C
diff -N testsuite/g++.dg/template/union1.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/union1.C	4 Oct 2002 03:48:40 -0000
***************
*** 0 ****
--- 1,29 ----
+ // { dg-do run }
+
+ extern "C" void abort ();
+
+ void g (char c)
+ {
+   if (c != 'a')
+     abort ();
+ }
+
+ void h (int i)
+ {
+   if (i != 3)
+     abort ();
+ }
+
+ template <typename T> void f(T const &t)
+ {
+     union { char c; T t_; };
+
+     c = 'a';
+     g (c);
+     t_ = 3;
+     h (t_);
+ }
+
+ int main () {
+   f (3);
+ }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]