This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH][C++] Fix PR40799
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sat, 18 Jul 2009 21:29:48 +0200 (CEST)
- Subject: [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;
+ }