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]

[PATCH][C++] Fix PR40799


This fixes a fallout from the gimplification unit-at-a-time patch.
The issue is that not all of C++ GENERIC (well, what is GENERIC
anyway ...) is handled by the tree copying routines in tree-inline.c
In particular they are confused by USING_DECLs which do not have
types in their TREE_TYPE field which causes the testcase to ICE.

My fix is to move the C++ specific gimplification of these to
the C++ specific genericization.  I'm somewhat confused as of
what is supposed to be GENERIC or done during genericization
vs. gimplification (which also handles arbitrary trees via the
langhook...).

Anyway - I will try to work again on one of my followup patches
to the unit-at-a-time gimplification which will move the actual
cloning to the middle-end using the inliner.

In the meantime this should fix the immediate fallout.

Bootstrapped and tested on x86_64-unknown-linux-gnu, ok for trunk?

Thanks,
Richard.

2009-07-18  Richard Guenther  <rguenther@suse.de>

	PR c++/40799
	* cp-gimplify.c (cp_gimplify_expr): Move handling of using
	related exprs to ...
	(cp_genericize_r): ... genericization stage.
	(cp_genericize): Adjust.

	* g++.dg/lookup/using21.C: New testcase.

Index: gcc/cp/cp-gimplify.c
===================================================================
*** gcc/cp/cp-gimplify.c	(revision 149777)
--- gcc/cp/cp-gimplify.c	(working copy)
*************** cp_gimplify_expr (tree *expr_p, gimple_s
*** 503,510 ****
    int saved_stmts_are_full_exprs_p = 0;
    enum tree_code code = TREE_CODE (*expr_p);
    enum gimplify_status ret;
-   tree block = NULL;
-   VEC(gimple, heap) *bind_expr_stack = NULL;
  
    if (STATEMENT_CODE_P (code))
      {
--- 503,508 ----
*************** cp_gimplify_expr (tree *expr_p, gimple_s
*** 571,607 ****
        break;
  
      case USING_STMT:
!       /* Get the innermost inclosing GIMPLE_BIND that has a non NULL
!          BLOCK, and append an IMPORTED_DECL to its
! 	 BLOCK_VARS chained list.  */
! 
!       bind_expr_stack = gimple_bind_expr_stack ();
!       if (bind_expr_stack)
! 	{
! 	  int i;
! 	  for (i = VEC_length (gimple, bind_expr_stack) - 1; i >= 0; i--)
! 	    if ((block = gimple_bind_block (VEC_index (gimple,
! 						       bind_expr_stack,
! 						       i))))
! 	      break;
! 	}
!       if (block)
! 	{
! 	  tree using_directive;
! 	  gcc_assert (TREE_OPERAND (*expr_p, 0));
! 
! 	  using_directive = make_node (IMPORTED_DECL);
! 	  TREE_TYPE (using_directive) = void_type_node;
! 
! 	  IMPORTED_DECL_ASSOCIATED_DECL (using_directive)
! 	    = TREE_OPERAND (*expr_p, 0);
! 	  TREE_CHAIN (using_directive) = BLOCK_VARS (block);
! 	  BLOCK_VARS (block) = using_directive;
! 	}
!       /* The USING_STMT won't appear in GIMPLE.  */
!       *expr_p = NULL;
!       ret = GS_ALL_DONE;
!       break;
  
      case FOR_STMT:
        gimplify_for_stmt (expr_p, pre_p);
--- 569,575 ----
        break;
  
      case USING_STMT:
!       gcc_unreachable ();
  
      case FOR_STMT:
        gimplify_for_stmt (expr_p, pre_p);
*************** cxx_int_tree_map_hash (const void *item)
*** 693,698 ****
--- 661,672 ----
    return ((const struct cxx_int_tree_map *)item)->uid;
  }
  
+ struct cp_genericize_data
+ {
+   struct pointer_set_t *p_set;
+   VEC (tree, heap) *bind_expr_stack;
+ };
+ 
  /* Perform any pre-gimplification lowering of C++ front end trees to
     GENERIC.  */
  
*************** static tree
*** 700,706 ****
  cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
  {
    tree stmt = *stmt_p;
!   struct pointer_set_t *p_set = (struct pointer_set_t*) data;
  
    if (is_invisiref_parm (stmt)
        /* Don't dereference parms in a thunk, pass the references through. */
--- 674,681 ----
  cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
  {
    tree stmt = *stmt_p;
!   struct cp_genericize_data *wtd = (struct cp_genericize_data *) data;
!   struct pointer_set_t *p_set = wtd->p_set;
  
    if (is_invisiref_parm (stmt)
        /* Don't dereference parms in a thunk, pass the references through. */
*************** cp_genericize_r (tree *stmt_p, int *walk
*** 759,765 ****
  	    *walk_subtrees = 0;
  	    if (OMP_CLAUSE_LASTPRIVATE_STMT (stmt))
  	      cp_walk_tree (&OMP_CLAUSE_LASTPRIVATE_STMT (stmt),
! 			    cp_genericize_r, p_set, NULL);
  	  }
  	break;
        case OMP_CLAUSE_PRIVATE:
--- 734,740 ----
  	    *walk_subtrees = 0;
  	    if (OMP_CLAUSE_LASTPRIVATE_STMT (stmt))
  	      cp_walk_tree (&OMP_CLAUSE_LASTPRIVATE_STMT (stmt),
! 			    cp_genericize_r, data, NULL);
  	  }
  	break;
        case OMP_CLAUSE_PRIVATE:
*************** cp_genericize_r (tree *stmt_p, int *walk
*** 829,834 ****
--- 804,859 ----
  	}
      }
  
+   else if (TREE_CODE (stmt) == BIND_EXPR)
+     {
+       VEC_safe_push (tree, heap, wtd->bind_expr_stack, stmt);
+       cp_walk_tree (&BIND_EXPR_BODY (stmt),
+ 		    cp_genericize_r, data, NULL);
+       VEC_pop (tree, wtd->bind_expr_stack);
+       *walk_subtrees = 0;
+     }
+ 
+   else if (TREE_CODE (stmt) == USING_STMT)
+     {
+       tree block = NULL_TREE;
+ 
+       /* Get the innermost inclosing GIMPLE_BIND that has a non NULL
+          BLOCK, and append an IMPORTED_DECL to its
+ 	 BLOCK_VARS chained list.  */
+       if (wtd->bind_expr_stack)
+ 	{
+ 	  int i;
+ 	  for (i = VEC_length (tree, wtd->bind_expr_stack) - 1; i >= 0; i--)
+ 	    if ((block = BIND_EXPR_BLOCK (VEC_index (tree,
+ 						     wtd->bind_expr_stack, i))))
+ 	      break;
+ 	}
+       if (block)
+ 	{
+ 	  tree using_directive;
+ 	  gcc_assert (TREE_OPERAND (stmt, 0));
+ 
+ 	  using_directive = make_node (IMPORTED_DECL);
+ 	  TREE_TYPE (using_directive) = void_type_node;
+ 
+ 	  IMPORTED_DECL_ASSOCIATED_DECL (using_directive)
+ 	    = TREE_OPERAND (stmt, 0);
+ 	  TREE_CHAIN (using_directive) = BLOCK_VARS (block);
+ 	  BLOCK_VARS (block) = using_directive;
+ 	}
+       /* The USING_STMT won't appear in GENERIC.  */
+       *stmt_p = build1 (NOP_EXPR, void_type_node, integer_zero_node);
+       *walk_subtrees = 0;
+     }
+ 
+   else if (TREE_CODE (stmt) == DECL_EXPR
+ 	   && TREE_CODE (DECL_EXPR_DECL (stmt)) == USING_DECL)
+     {
+       /* Using decls inside DECL_EXPRs are just dropped on the floor.  */
+       *stmt_p = build1 (NOP_EXPR, void_type_node, integer_zero_node);
+       *walk_subtrees = 0;
+     }
+ 
    pointer_set_insert (p_set, *stmt_p);
  
    return NULL;
*************** void
*** 838,844 ****
  cp_genericize (tree fndecl)
  {
    tree t;
!   struct pointer_set_t *p_set;
  
    /* Fix up the types of parms passed by invisible reference.  */
    for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t))
--- 863,869 ----
  cp_genericize (tree fndecl)
  {
    tree t;
!   struct cp_genericize_data wtd;
  
    /* Fix up the types of parms passed by invisible reference.  */
    for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t))
*************** cp_genericize (tree fndecl)
*** 872,880 ****
  
    /* We do want to see every occurrence of the parms, so we can't just use
       walk_tree's hash functionality.  */
!   p_set = pointer_set_create ();
!   cp_walk_tree (&DECL_SAVED_TREE (fndecl), cp_genericize_r, p_set, NULL);
!   pointer_set_destroy (p_set);
  
    /* Do everything else.  */
    c_genericize (fndecl);
--- 897,907 ----
  
    /* We do want to see every occurrence of the parms, so we can't just use
       walk_tree's hash functionality.  */
!   wtd.p_set = pointer_set_create ();
!   wtd.bind_expr_stack = NULL;
!   cp_walk_tree (&DECL_SAVED_TREE (fndecl), cp_genericize_r, &wtd, NULL);
!   pointer_set_destroy (wtd.p_set);
!   VEC_free (tree, heap, wtd.bind_expr_stack);
  
    /* Do everything else.  */
    c_genericize (fndecl);
Index: gcc/testsuite/g++.dg/lookup/using21.C
===================================================================
*** gcc/testsuite/g++.dg/lookup/using21.C	(revision 0)
--- gcc/testsuite/g++.dg/lookup/using21.C	(revision 0)
***************
*** 0 ****
--- 1,13 ----
+ // PR c++/40799
+ 
+ namespace Bar {
+   typedef int A;
+ }
+ class CollectionDeleteGuard {
+ public:
+   CollectionDeleteGuard(int);
+ };
+ CollectionDeleteGuard::CollectionDeleteGuard(int)
+ {
+   using Bar::A;
+ }


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