diff options
Diffstat (limited to 'gcc/tree-inline.c')
-rw-r--r-- | gcc/tree-inline.c | 33 |
1 files changed, 32 insertions, 1 deletions
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 |