+ BIND_EXPR_VARS (*tp) = remap_decls (BIND_EXPR_VARS (*tp), NULL, id);
+}
+
+
+/* Create a new gimple_seq by remapping all the statements in BODY
+ using the inlining information in ID. */
+
+gimple_seq
+remap_gimple_seq (gimple_seq body, copy_body_data *id)
+{
+ gimple_stmt_iterator si;
+ gimple_seq new_body = NULL;
+
+ for (si = gsi_start (body); !gsi_end_p (si); gsi_next (&si))
+ {
+ gimple new_stmt = remap_gimple_stmt (gsi_stmt (si), id);
+ gimple_seq_add_stmt (&new_body, new_stmt);
+ }
+
+ return new_body;
+}
+
+
+/* Copy a GIMPLE_BIND statement STMT, remapping all the symbols in its
+ block using the mapping information in ID. */
+
+static gimple
+copy_gimple_bind (gimple stmt, copy_body_data *id)
+{
+ gimple new_bind;
+ tree new_block, new_vars;
+ gimple_seq body, new_body;
+
+ /* Copy the statement. Note that we purposely don't use copy_stmt
+ here because we need to remap statements as we copy. */
+ body = gimple_bind_body (stmt);
+ new_body = remap_gimple_seq (body, id);
+
+ new_block = gimple_bind_block (stmt);
+ if (new_block)
+ remap_block (&new_block, id);
+
+ /* This will remap a lot of the same decls again, but this should be
+ harmless. */
+ new_vars = gimple_bind_vars (stmt);
+ if (new_vars)
+ new_vars = remap_decls (new_vars, NULL, id);
+
+ new_bind = gimple_build_bind (new_vars, new_body, new_block);
+
+ return new_bind;
+}
+
+
+/* Remap the GIMPLE operand pointed to by *TP. DATA is really a
+ 'struct walk_stmt_info *'. DATA->INFO is a 'copy_body_data *'.
+ WALK_SUBTREES is used to indicate walk_gimple_op whether to keep
+ recursing into the children nodes of *TP. */
+
+static tree
+remap_gimple_op_r (tree *tp, int *walk_subtrees, void *data)
+{
+ struct walk_stmt_info *wi_p = (struct walk_stmt_info *) data;
+ copy_body_data *id = (copy_body_data *) wi_p->info;
+ tree fn = id->src_fn;
+
+ if (TREE_CODE (*tp) == SSA_NAME)
+ {
+ *tp = remap_ssa_name (*tp, id);
+ *walk_subtrees = 0;
+ return NULL;
+ }
+ else if (auto_var_in_fn_p (*tp, fn))
+ {
+ /* Local variables and labels need to be replaced by equivalent
+ variables. We don't want to copy static variables; there's
+ only one of those, no matter how many times we inline the
+ containing function. Similarly for globals from an outer
+ function. */
+ tree new_decl;
+
+ /* Remap the declaration. */
+ new_decl = remap_decl (*tp, id);
+ gcc_assert (new_decl);
+ /* Replace this variable with the copy. */
+ STRIP_TYPE_NOPS (new_decl);
+ /* ??? The C++ frontend uses void * pointer zero to initialize
+ any other type. This confuses the middle-end type verification.
+ As cloned bodies do not go through gimplification again the fixup
+ there doesn't trigger. */
+ if (TREE_CODE (new_decl) == INTEGER_CST
+ && !useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (new_decl)))
+ new_decl = fold_convert (TREE_TYPE (*tp), new_decl);
+ *tp = new_decl;
+ *walk_subtrees = 0;
+ }
+ else if (TREE_CODE (*tp) == STATEMENT_LIST)
+ gcc_unreachable ();
+ else if (TREE_CODE (*tp) == SAVE_EXPR)
+ gcc_unreachable ();
+ else if (TREE_CODE (*tp) == LABEL_DECL
+ && (!DECL_CONTEXT (*tp)
+ || decl_function_context (*tp) == id->src_fn))
+ /* These may need to be remapped for EH handling. */
+ *tp = remap_decl (*tp, id);
+ else if (TYPE_P (*tp))
+ /* Types may need remapping as well. */
+ *tp = remap_type (*tp, id);
+ else if (CONSTANT_CLASS_P (*tp))
+ {
+ /* If this is a constant, we have to copy the node iff the type
+ will be remapped. copy_tree_r will not copy a constant. */
+ tree new_type = remap_type (TREE_TYPE (*tp), id);
+
+ if (new_type == TREE_TYPE (*tp))
+ *walk_subtrees = 0;
+
+ else if (TREE_CODE (*tp) == INTEGER_CST)
+ *tp = build_int_cst_wide (new_type, TREE_INT_CST_LOW (*tp),
+ TREE_INT_CST_HIGH (*tp));
+ else
+ {
+ *tp = copy_node (*tp);
+ TREE_TYPE (*tp) = new_type;
+ }
+ }
+ else
+ {
+ /* Otherwise, just copy the node. Note that copy_tree_r already
+ knows not to copy VAR_DECLs, etc., so this is safe. */
+ if (TREE_CODE (*tp) == INDIRECT_REF)
+ {
+ /* Get rid of *& from inline substitutions that can happen when a
+ pointer argument is an ADDR_EXPR. */
+ tree decl = TREE_OPERAND (*tp, 0);
+ tree *n;
+
+ n = (tree *) pointer_map_contains (id->decl_map, decl);
+ if (n)
+ {
+ tree type, new_tree, old;
+
+ /* If we happen to get an ADDR_EXPR in n->value, strip
+ it manually here as we'll eventually get ADDR_EXPRs
+ which lie about their types pointed to. In this case
+ build_fold_indirect_ref wouldn't strip the
+ INDIRECT_REF, but we absolutely rely on that. As
+ fold_indirect_ref does other useful transformations,
+ try that first, though. */
+ type = TREE_TYPE (TREE_TYPE (*n));
+ new_tree = unshare_expr (*n);
+ old = *tp;
+ *tp = gimple_fold_indirect_ref (new_tree);
+ if (!*tp)
+ {
+ if (TREE_CODE (new_tree) == ADDR_EXPR)
+ {
+ *tp = fold_indirect_ref_1 (EXPR_LOCATION (new_tree),
+ type, new_tree);
+ /* ??? We should either assert here or build
+ a VIEW_CONVERT_EXPR instead of blindly leaking
+ incompatible types to our IL. */
+ if (! *tp)
+ *tp = TREE_OPERAND (new_tree, 0);
+ }
+ else
+ {
+ *tp = build1 (INDIRECT_REF, type, new_tree);
+ TREE_THIS_VOLATILE (*tp) = TREE_THIS_VOLATILE (old);
+ TREE_NO_WARNING (*tp) = TREE_NO_WARNING (old);
+ }
+ }
+ *walk_subtrees = 0;
+ return NULL;
+ }
+ }
+
+ /* Here is the "usual case". Copy this tree node, and then
+ tweak some special cases. */
+ copy_tree_r (tp, walk_subtrees, NULL);
+
+ /* Global variables we haven't seen yet need to go into referenced
+ vars. If not referenced from types only. */
+ if (gimple_in_ssa_p (cfun)
+ && TREE_CODE (*tp) == VAR_DECL
+ && id->remapping_type_depth == 0)
+ add_referenced_var (*tp);
+
+ /* We should never have TREE_BLOCK set on non-statements. */
+ if (EXPR_P (*tp))
+ gcc_assert (!TREE_BLOCK (*tp));
+
+ if (TREE_CODE (*tp) != OMP_CLAUSE)
+ TREE_TYPE (*tp) = remap_type (TREE_TYPE (*tp), id);
+
+ if (TREE_CODE (*tp) == TARGET_EXPR && TREE_OPERAND (*tp, 3))
+ {
+ /* The copied TARGET_EXPR has never been expanded, even if the
+ original node was expanded already. */
+ TREE_OPERAND (*tp, 1) = TREE_OPERAND (*tp, 3);
+ TREE_OPERAND (*tp, 3) = NULL_TREE;
+ }
+ else if (TREE_CODE (*tp) == ADDR_EXPR)
+ {
+ /* Variable substitution need not be simple. In particular,
+ the INDIRECT_REF substitution above. Make sure that
+ TREE_CONSTANT and friends are up-to-date. But make sure
+ to not improperly set TREE_BLOCK on some sub-expressions. */
+ int invariant = is_gimple_min_invariant (*tp);
+ tree block = id->block;
+ id->block = NULL_TREE;
+ walk_tree (&TREE_OPERAND (*tp, 0), copy_tree_body_r, id, NULL);
+ id->block = block;
+
+ /* Handle the case where we substituted an INDIRECT_REF
+ into the operand of the ADDR_EXPR. */
+ if (TREE_CODE (TREE_OPERAND (*tp, 0)) == INDIRECT_REF)
+ *tp = TREE_OPERAND (TREE_OPERAND (*tp, 0), 0);
+ else
+ recompute_tree_invariant_for_addr_expr (*tp);
+
+ /* If this used to be invariant, but is not any longer,
+ then regimplification is probably needed. */
+ if (invariant && !is_gimple_min_invariant (*tp))
+ id->regimplify = true;
+
+ *walk_subtrees = 0;
+ }
+ }
+
+ /* Keep iterating. */
+ return NULL_TREE;