On Tue, Nov 01, 2016 at 05:33:17PM -0400, Jason Merrill wrote:
> Like so?
LGTM, thanks.
> diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
> index de5e575..6899d2a 100644
> --- a/gcc/tree-inline.c
> +++ b/gcc/tree-inline.c
> @@ -1045,6 +1045,7 @@ copy_tree_body_r (tree *tp, int *walk_subtrees, void
> *data)
> copy_body_data *id = (copy_body_data *) data;
> tree fn = id->src_fn;
> tree new_block;
> + bool copied = false;
>
> /* Begin by recognizing trees that we'll completely rewrite for the
> inlining context. Our output for these trees is completely
> @@ -1241,10 +1242,40 @@ copy_tree_body_r (tree *tp, int *walk_subtrees, void
> *data)
> *walk_subtrees = 0;
> return NULL;
> }
> + else if (TREE_CODE (*tp) == COND_EXPR)
> + {
> + tree cond = TREE_OPERAND (*tp, 0);
> + walk_tree (&cond, copy_tree_body_r, data, NULL);
> + tree folded = fold (cond);
> + if (TREE_CODE (folded) == INTEGER_CST)
> + {
> + /* Only copy the taken branch; for a C++ base constructor clone
> + inherited from a virtual base, copying the other branch leads
> + to references to parameters that were optimized away. */
> + tree branch = (integer_nonzerop (folded)
> + ? TREE_OPERAND (*tp, 1)
> + : TREE_OPERAND (*tp, 2));
> + tree type = TREE_TYPE (*tp);
> + if (VOID_TYPE_P (type)
> + || type == TREE_TYPE (branch))
> + {
> + *tp = branch;
> + return copy_tree_body_r (tp, walk_subtrees, data);
> + }
> + }
> + /* Avoid copying the condition twice. */
> + copy_tree_r (tp, walk_subtrees, NULL);
> + TREE_OPERAND (*tp, 0) = cond;
> + walk_tree (&TREE_OPERAND (*tp, 1), copy_tree_body_r, data, NULL);
> + walk_tree (&TREE_OPERAND (*tp, 2), copy_tree_body_r, data, NULL);
> + *walk_subtrees = 0;
> + copied = true;
> + }
>
> /* Here is the "usual case". Copy this tree node, and then
> tweak some special cases. */
> - copy_tree_r (tp, walk_subtrees, NULL);
> + if (!copied)
> + copy_tree_r (tp, walk_subtrees, NULL);
>
> /* If EXPR has block defined, map it to newly constructed block.
> When inlining we want EXPRs without block appear in the block
Jakub