Message ID | 4DBF2909.4050207@redhat.com |
---|---|
State | New |
Headers | show |
> But Diego doesn't think there was any real reason to abort on trying to > copy a STATEMENT_LIST, so it seems to me that we could revert my earlier > patch for 40975 and just add support for copying STATEMENT_LIST. So > 40975-2.patch adds that support. FWIW this assertion caught an impressive number of bugs in Ada over the years related to COND_EXPR: when they are incorrectly shared, gimplifying them on one side creates a STATEMENT_LIST and stopped the copying on the other side. I'm not sure you can copy statements if they have any side-effects; this looks quite dangerous to me. Instead statement-expressions should be wrapped up in a SAVE_EXPR/TARGET_EXPR to protect them and prevent copying.
On 05/02/2011 06:23 PM, Eric Botcazou wrote: > I'm not sure you can copy statements if they have any side-effects; this looks > quite dangerous to me. Instead statement-expressions should be wrapped up in > a SAVE_EXPR/TARGET_EXPR to protect them and prevent copying. It sounds like Ada and C++ are using copy_tree_r in very different ways. The use in C++ has to do with default arguments: we parse the expression at the point of the function declaration, but whenever we want to use the expression in a function call we need to make a deep copy of the expression. In this case, we want to copy everything. How is it used in Ada? Jason
> How is it used in Ada?
The front-end doesn't use it directly, it's only used through the gimplifier
by the unsharing phase (unshare_body). We also have statement expressions.
On 05/03/2011 03:00 AM, Eric Botcazou wrote: >> How is it used in Ada? > > The front-end doesn't use it directly, it's only used through the gimplifier > by the unsharing phase (unshare_body). We also have statement expressions. In that case you wouldn't be affected by this patch; unshare_body uses mostly_copy_tree_r, which has its own special case for STATEMENT_LIST. Jason
> In that case you wouldn't be affected by this patch; unshare_body uses > mostly_copy_tree_r, which has its own special case for STATEMENT_LIST. Right, I added it precisely to support statement expressions in Ada (instead of changing copy_tree_r) since we never want to copy them in the unsharing phase. That's why I find the change to copy_tree_r questionable.
On 05/03/2011 11:52 AM, Eric Botcazou wrote: >> In that case you wouldn't be affected by this patch; unshare_body uses >> mostly_copy_tree_r, which has its own special case for STATEMENT_LIST. > > Right, I added it precisely to support statement expressions in Ada (instead > of changing copy_tree_r) since we never want to copy them in the unsharing > phase. That's why I find the change to copy_tree_r questionable. Well, let's look at the users of copy_tree_r. cp/tree.c (bot_manip): The case I want to fix. gimplify.c (mostly_copy_tree_r): Handles STATEMENT_LIST itself. stor-layout.c (copy_self_referential_tree_r): Affected by the change. Would you like me to add a gcc_unreachable() here? tree-inline.c (copy_tree_body_r): already copies STATEMENT_LIST itself (with a copy_statement_list function which I should use instead of open-coding it again). (copy_bind_expr): subroutine of copy_tree_body_r. (unsave_r, remap_gimple_op_r): Handle STATEMENT_LIST themselves. So, looks like one place that could have an undesired change in behavior. I'll go ahead and add that assert. Jason
> Well, let's look at the users of copy_tree_r. > > cp/tree.c (bot_manip): The case I want to fix. Then I'd put the fix there. The old behaviour of copy_tree_r is IMO the most sensible one and its callers should cope, as almost all already do it seems.
On 05/04/2011 04:12 AM, Eric Botcazou wrote: >> Well, let's look at the users of copy_tree_r. >> >> cp/tree.c (bot_manip): The case I want to fix. > > Then I'd put the fix there. The old behaviour of copy_tree_r is IMO the most > sensible one and its callers should cope, as almost all already do it seems. Well, I disagree. STATEMENT_LISTs are just another kind of thing you encounter in an expression; if a caller wants special handling, they can arrange for it. This is how things used to work before, but it broke when the tree-ssa merge switched from using TREE_CHAIN on statements to a separate STATEMENT_LIST. Jason
> Well, I disagree. STATEMENT_LISTs are just another kind of thing you > encounter in an expression; if a caller wants special handling, they can > arrange for it. But you're unilaterally choosing one special handling (copying) among several ones (copying, not copying, aborting) just because of one caller, for no good reason IMO. > This is how things used to work before, but it broke when the tree-ssa > merge switched from using TREE_CHAIN on statements to a separate > STATEMENT_LIST. Well, the assertion certainly wasn't put there by accident.
On 05/04/2011 06:57 PM, Eric Botcazou wrote: > But you're unilaterally choosing one special handling (copying) among several > ones (copying, not copying, aborting) just because of one caller, for no good > reason IMO. It seems pretty straightforward to me that a function named copy_tree_r should copy everything that isn't always shared (like decls). It already copies SAVE_EXPR, after all; how is copying STATEMENT_LIST going to cause trouble in a context where copying SAVE_EXPR isn't? >> This is how things used to work before, but it broke when the tree-ssa >> merge switched from using TREE_CHAIN on statements to a separate >> STATEMENT_LIST. > > Well, the assertion certainly wasn't put there by accident. No, but the rationale isn't documented. It was added by the patch that introduced STATEMENT_LIST, http://gcc.gnu.org/ml/gcc-patches/2003-11/msg00879.html but doesn't appear in the ChangeLog entry. I notice that in that patch unsave_r copied STATEMENT_LIST, but now it doesn't. rth, do you happen to remember why you put it there? Jason
On 05/05/2011 07:09 AM, Jason Merrill wrote: > No, but the rationale isn't documented. It was added by the patch > that introduced STATEMENT_LIST, > > http://gcc.gnu.org/ml/gcc-patches/2003-11/msg00879.html > > but doesn't appear in the ChangeLog entry. I notice that in that > patch unsave_r copied STATEMENT_LIST, but now it doesn't. rth, do you > happen to remember why you put it there? No, I don't recall. I suspect that I put that in there while testing in order to determine if I needed to support copying statement lists, and it turned out that I didn't. r~
> It seems pretty straightforward to me that a function named copy_tree_r > should copy everything that isn't always shared (like decls). It > already copies SAVE_EXPR, after all; how is copying STATEMENT_LIST going > to cause trouble in a context where copying SAVE_EXPR isn't? OK, this can make sense, callers should handle special nodes like SAVE_EXPR, TARGET_EXPR, STATEMENT_LIST, etc themselves. In light of this, they need to be audited and adjusted, as you did already a few days ago. So I think I can live with your 40975-3.patch in the end. Thanks for your patience.
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 2eaa1db..fff3fbf 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -564,6 +564,7 @@ build_vec_init_expr (tree target, tree init, tree nelts, elt_init = build_vec_init_elt (type, init, complain); init = build3 (VEC_INIT_EXPR, type, slot, init, nelts); + TREE_SIDE_EFFECTS (init) = true; SET_EXPR_LOCATION (init, input_location); if (cxx_dialect >= cxx0x @@ -571,7 +572,11 @@ build_vec_init_expr (tree target, tree init, tree nelts, VEC_INIT_EXPR_IS_CONSTEXPR (init) = true; VEC_INIT_EXPR_VALUE_INIT (init) = value_init; - if (slot != target) + if (slot == target) + /* If we specified what array we're initializing, make sure + we don't override that in cp_gimplify_init_expr. */ + init = cp_build_compound_expr (init, slot, complain); + else { init = build_target_expr (slot, init, complain); TARGET_EXPR_IMPLICIT_P (init) = 1; diff --git a/gcc/testsuite/g++.dg/init/new31.C b/gcc/testsuite/g++.dg/init/new31.C new file mode 100644 index 0000000..33c94aa --- /dev/null +++ b/gcc/testsuite/g++.dg/init/new31.C @@ -0,0 +1,18 @@ +// PR c++/48834 +// { dg-options -Wuninitialized } +// { dg-do run } + +struct S +{ + S ():i (0) + { + } + int i; +}; + +int +main () +{ + S *s = new S[2]; + return 0; +}