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 to aggregate returns


This patch does three things:

1) breaks out most of simplify_aggr_init_exprs_r into a separate function.
2) corrects the type of the return slot argument so we don't need to adjust
   it in the inliner.
3) avoids clobbering the identity of a variable initialized by an inline
   function.

These are all primarily for the benefit of tree-ssa, but are also
applicable to the trunk.

Tested x86_64-pc-linux-gnu, applied to trunk and tree-ssa.

2003-08-20  Jason Merrill  <jason@redhat.com>

	* semantics.c (simplify_aggr_init_expr): Split out from
	simplify_aggr_init_exprs_r.  Convert slot address to match
	the return type.
	* cp-tree.h: Declare it.
	* tree.c (cp_copy_res_decl_for_inlining): Don't clobber the
	DECL_NAME of a user variable.

*** cp-tree.h.~1~	Wed Aug 20 03:06:40 2003
--- cp-tree.h	Wed Aug 20 20:22:17 2003
*************** extern tree check_template_template_defa
*** 4147,4152 ****
--- 4147,4153 ----
  extern void expand_or_defer_fn			(tree);
  extern void check_accessibility_of_qualified_id (tree, tree, tree);
  extern tree finish_qualified_id_expr            (tree, tree, bool, bool);
+ extern void simplify_aggr_init_expr		(tree *);
  
  /* in tree.c */
  extern void lang_check_failed			(const char *, int,
*** semantics.c.~1~	Wed Aug 20 14:00:08 2003
--- semantics.c	Wed Aug 20 20:22:17 2003
*************** cp_expand_stmt (tree t)
*** 2713,2749 ****
  
  static tree
  simplify_aggr_init_exprs_r (tree* tp, 
!                             int* walk_subtrees ATTRIBUTE_UNUSED , 
!                             void* data ATTRIBUTE_UNUSED )
  {
-   tree aggr_init_expr;
-   tree call_expr;
-   tree fn;
-   tree args;
-   tree slot;
-   tree type;
-   enum style_t { ctor, arg, pcc } style;
- 
-   aggr_init_expr = *tp;
    /* We don't need to walk into types; there's nothing in a type that
       needs simplification.  (And, furthermore, there are places we
       actively don't want to go.  For example, we don't want to wander
       into the default arguments for a FUNCTION_DECL that appears in a
       CALL_EXPR.)  */
!   if (TYPE_P (aggr_init_expr))
      {
        *walk_subtrees = 0;
        return NULL_TREE;
      }
    /* Only AGGR_INIT_EXPRs are interesting.  */
!   else if (TREE_CODE (aggr_init_expr) != AGGR_INIT_EXPR)
      return NULL_TREE;
  
    /* Form an appropriate CALL_EXPR.  */
!   fn = TREE_OPERAND (aggr_init_expr, 0);
!   args = TREE_OPERAND (aggr_init_expr, 1);
!   slot = TREE_OPERAND (aggr_init_expr, 2);
!   type = TREE_TYPE (aggr_init_expr);
  
    if (AGGR_INIT_VIA_CTOR_P (aggr_init_expr))
      style = ctor;
--- 2713,2758 ----
  
  static tree
  simplify_aggr_init_exprs_r (tree* tp, 
!                             int* walk_subtrees,
!                             void* data ATTRIBUTE_UNUSED)
  {
    /* We don't need to walk into types; there's nothing in a type that
       needs simplification.  (And, furthermore, there are places we
       actively don't want to go.  For example, we don't want to wander
       into the default arguments for a FUNCTION_DECL that appears in a
       CALL_EXPR.)  */
!   if (TYPE_P (*tp))
      {
        *walk_subtrees = 0;
        return NULL_TREE;
      }
    /* Only AGGR_INIT_EXPRs are interesting.  */
!   else if (TREE_CODE (*tp) != AGGR_INIT_EXPR)
      return NULL_TREE;
  
+   simplify_aggr_init_expr (tp);
+ 
+   /* Keep iterating.  */
+   return NULL_TREE;
+ }
+ 
+ /* Replace the AGGR_INIT_EXPR at *TP with an equivalent CALL_EXPR.  This
+    function is broken out from the above for the benefit of the tree-ssa
+    project.  */
+ 
+ void
+ simplify_aggr_init_expr (tree *tp)
+ {
+   tree aggr_init_expr = *tp;
+ 
    /* Form an appropriate CALL_EXPR.  */
!   tree fn = TREE_OPERAND (aggr_init_expr, 0);
!   tree args = TREE_OPERAND (aggr_init_expr, 1);
!   tree slot = TREE_OPERAND (aggr_init_expr, 2);
!   tree type = TREE_TYPE (aggr_init_expr);
! 
!   tree call_expr;
!   enum style_t { ctor, arg, pcc } style;
  
    if (AGGR_INIT_VIA_CTOR_P (aggr_init_expr))
      style = ctor;
*************** simplify_aggr_init_exprs_r (tree* tp, 
*** 2762,2776 ****
      {
        /* Pass the address of the slot.  If this is a constructor, we
  	 replace the first argument; otherwise, we tack on a new one.  */
        if (style == ctor)
  	args = TREE_CHAIN (args);
  
        cxx_mark_addressable (slot);
!       args = tree_cons (NULL_TREE, 
! 			build1 (ADDR_EXPR, 
! 				build_pointer_type (TREE_TYPE (slot)),
! 				slot),
! 			args);
      }
  
    call_expr = build (CALL_EXPR, 
--- 2771,2796 ----
      {
        /* Pass the address of the slot.  If this is a constructor, we
  	 replace the first argument; otherwise, we tack on a new one.  */
+       tree addr;
+ 
        if (style == ctor)
  	args = TREE_CHAIN (args);
  
        cxx_mark_addressable (slot);
!       addr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (slot)), slot);
!       if (style == arg)
! 	{
! 	  /* The return type might have different cv-quals from the slot.  */
! 	  tree fntype = TREE_TYPE (TREE_TYPE (fn));
! #ifdef ENABLE_CHECKING
! 	  if (TREE_CODE (fntype) != FUNCTION_TYPE
! 	      && TREE_CODE (fntype) != METHOD_TYPE)
! 	    abort ();
! #endif
! 	  addr = convert (build_pointer_type (TREE_TYPE (fntype)), addr);
! 	}
! 
!       args = tree_cons (NULL_TREE, addr, args);
      }
  
    call_expr = build (CALL_EXPR, 
*************** simplify_aggr_init_exprs_r (tree* tp, 
*** 2801,2809 ****
    /* Replace the AGGR_INIT_EXPR with the CALL_EXPR.  */
    TREE_CHAIN (call_expr) = TREE_CHAIN (aggr_init_expr);
    *tp = call_expr;
- 
-   /* Keep iterating.  */
-   return NULL_TREE;
  }
  
  /* Emit all thunks to FN that should be emitted when FN is emitted.  */
--- 2821,2826 ----
*** tree.c.~1~	Sun Aug 10 11:10:35 2003
--- tree.c	Wed Aug 20 20:22:17 2003
*************** cp_copy_res_decl_for_inlining (tree resu
*** 2193,2199 ****
  	  /* We have a named return value; copy the name and source
  	     position so we can get reasonable debugging information, and
  	     register the return variable as its equivalent.  */
! 	  if (TREE_CODE (var) == VAR_DECL)
  	    {
  	      DECL_NAME (var) = DECL_NAME (nrv);
  	      DECL_SOURCE_LOCATION (var) = DECL_SOURCE_LOCATION (nrv);
--- 2193,2202 ----
  	  /* We have a named return value; copy the name and source
  	     position so we can get reasonable debugging information, and
  	     register the return variable as its equivalent.  */
! 	  if (TREE_CODE (var) == VAR_DECL
! 	      /* But not if we're initializing a variable from the
! 		 enclosing function which already has its own name.  */
! 	      && DECL_NAME (var) == NULL_TREE)
  	    {
  	      DECL_NAME (var) = DECL_NAME (nrv);
  	      DECL_SOURCE_LOCATION (var) = DECL_SOURCE_LOCATION (nrv);

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