We use unshare_expr in many places now outside of gimple
even. So it makes sense to move the decl to tree.h.
A few sources can now even not need to include gimplify.h;
I have not checked all of them just a few which seemed
like including gimplify.h didn't make sense.

This also moves the implementations of unshare_expr,
unshare_expr_without_location and copy_if_shared from gimplify.cc
to tree.cc to keep the headers "clean".

Bootstrapped and tested on x86_64-linux-gnu.

Changes since v1:
 * v2: Move implementation too.

gcc/ChangeLog:

        * cfgrtl.cc: Don't include gimplify.h or gimplify-me.h.
        * cgraphbuild.cc: Likewise.
        * emit-rtl.cc: Likewie.
        * tree-ssa-dom.cc: Likewise.
        * tree-ssa-dse.cc: Likewise.
        * tree-ssa-loop-im.cc: Likewise.
        * tree-ssa-loop-niter.cc: Likewise.
        * tree-ssa-loop-unswitch.cc: Likewise.
        * tree-ssa-math-opts.cc: Likewise.
        * tree-ssa-phiopt.cc: Likewise.
        * tree-ssa-phiprop.cc: Likewise.
        * tree-ssa-pre.cc: Likewise.
        * tree-ssa-propagate.cc: Likewise.
        * tree-ssa-sccvn.cc: Likewise.
        * gimplify.h (unshare_expr): Remove.
        (unshare_expr_without_location): Remove.
        (copy_if_shared): Remove.
        * tree.h (unshare_expr): New decl.
        (unshare_expr_without_location): Likewise.
        (copy_if_shared): Likewise.
        * gimplify.cc (mostly_copy_tree_r): Moved to tree.cc.
        (copy_if_shared_r): Likewise.
        (copy_if_shared): Likewise.
        (unshare_expr): Likewise.
        (prune_expr_location): Likewise.
        (unshare_expr_without_location): Likewise.
        * tree.cc (mostly_copy_tree_r): Moved from gimplify.cc
        (copy_if_shared_r): Likewise.
        (copy_if_shared): Likewise.
        (unshare_expr): Likewise.
        (prune_expr_location): Likewise.
        (unshare_expr_without_location): Likewise.

Signed-off-by: Andrew Pinski <[email protected]>
---
 gcc/cfgrtl.cc                 |   1 -
 gcc/cgraphbuild.cc            |   1 -
 gcc/emit-rtl.cc               |   1 -
 gcc/gimplify.cc               | 160 ----------------------------------
 gcc/gimplify.h                |   3 -
 gcc/tree-ssa-dom.cc           |   1 -
 gcc/tree-ssa-dse.cc           |   1 -
 gcc/tree-ssa-loop-im.cc       |   1 -
 gcc/tree-ssa-loop-niter.cc    |   1 -
 gcc/tree-ssa-loop-unswitch.cc |   1 -
 gcc/tree-ssa-math-opts.cc     |   2 -
 gcc/tree-ssa-phiopt.cc        |   2 -
 gcc/tree-ssa-phiprop.cc       |   1 -
 gcc/tree-ssa-pre.cc           |   1 -
 gcc/tree-ssa-propagate.cc     |   1 -
 gcc/tree-ssa-sccvn.cc         |   1 -
 gcc/tree.cc                   | 159 +++++++++++++++++++++++++++++++++
 gcc/tree.h                    |   9 ++
 18 files changed, 168 insertions(+), 179 deletions(-)

diff --git a/gcc/cfgrtl.cc b/gcc/cfgrtl.cc
index 7714e5548c2..0ec72f08fa8 100644
--- a/gcc/cfgrtl.cc
+++ b/gcc/cfgrtl.cc
@@ -62,7 +62,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-pass.h"
 #include "print-rtl.h"
 #include "rtl-iter.h"
-#include "gimplify.h"
 #include "profile.h"
 #include "sreal.h"
 
diff --git a/gcc/cgraphbuild.cc b/gcc/cgraphbuild.cc
index e33a414310b..3faf8395db5 100644
--- a/gcc/cgraphbuild.cc
+++ b/gcc/cgraphbuild.cc
@@ -31,7 +31,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-walk.h"
 #include "ipa-utils.h"
 #include "except.h"
-#include "gimplify.h"
 
 /* Context of record_reference.  */
 struct record_reference_ctx
diff --git a/gcc/emit-rtl.cc b/gcc/emit-rtl.cc
index e41ec2283b8..7f5d267341a 100644
--- a/gcc/emit-rtl.cc
+++ b/gcc/emit-rtl.cc
@@ -63,7 +63,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "rtx-vector-builder.h"
 #include "gimple.h"
 #include "gimple-ssa.h"
-#include "gimplify.h"
 #include "bbitmap.h"
 
 struct target_rtl default_target_rtl;
diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index e4db4b1d9bd..cdd039eb2bd 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -896,131 +896,6 @@ gimple_add_tmp_var (tree tmp)
     }
 }
 
-
-
-/* This page contains routines to unshare tree nodes, i.e. to duplicate tree
-   nodes that are referenced more than once in GENERIC functions.  This is
-   necessary because gimplification (translation into GIMPLE) is performed
-   by modifying tree nodes in-place, so gimplification of a shared node in a
-   first context could generate an invalid GIMPLE form in a second context.
-
-   This is achieved with a simple mark/copy/unmark algorithm that walks the
-   GENERIC representation top-down, marks nodes with TREE_VISITED the first
-   time it encounters them, duplicates them if they already have TREE_VISITED
-   set, and finally removes the TREE_VISITED marks it has set.
-
-   The algorithm works only at the function level, i.e. it generates a GENERIC
-   representation of a function with no nodes shared within the function when
-   passed a GENERIC function (except for nodes that are allowed to be shared).
-
-   At the global level, it is also necessary to unshare tree nodes that are
-   referenced in more than one function, for the same aforementioned reason.
-   This requires some cooperation from the front-end.  There are 2 strategies:
-
-     1. Manual unsharing.  The front-end needs to call unshare_expr on every
-        expression that might end up being shared across functions.
-
-     2. Deep unsharing.  This is an extension of regular unsharing.  Instead
-        of calling unshare_expr on expressions that might be shared across
-        functions, the front-end pre-marks them with TREE_VISITED.  This will
-        ensure that they are unshared on the first reference within functions
-        when the regular unsharing algorithm runs.  The counterpart is that
-        this algorithm must look deeper than for manual unsharing, which is
-        specified by LANG_HOOKS_DEEP_UNSHARING.
-
-  If there are only few specific cases of node sharing across functions, it is
-  probably easier for a front-end to unshare the expressions manually.  On the
-  contrary, if the expressions generated at the global level are as widespread
-  as expressions generated within functions, deep unsharing is very likely the
-  way to go.  */
-
-/* Similar to copy_tree_r but do not copy SAVE_EXPR or TARGET_EXPR nodes.
-   These nodes model computations that must be done once.  If we were to
-   unshare something like SAVE_EXPR(i++), the gimplification process would
-   create wrong code.  However, if DATA is non-null, it must hold a pointer
-   set that is used to unshare the subtrees of these nodes.  */
-
-static tree
-mostly_copy_tree_r (tree *tp, int *walk_subtrees, void *data)
-{
-  tree t = *tp;
-  enum tree_code code = TREE_CODE (t);
-
-  /* Do not copy SAVE_EXPR, TARGET_EXPR or BIND_EXPR nodes themselves, but
-     copy their subtrees if we can make sure to do it only once.  */
-  if (code == SAVE_EXPR || code == TARGET_EXPR || code == BIND_EXPR)
-    {
-      if (data && !((hash_set<tree> *)data)->add (t))
-       ;
-      else
-       *walk_subtrees = 0;
-    }
-
-  /* Stop at types, decls, constants like copy_tree_r.  */
-  else if (TREE_CODE_CLASS (code) == tcc_type
-          || TREE_CODE_CLASS (code) == tcc_declaration
-          || TREE_CODE_CLASS (code) == tcc_constant)
-    *walk_subtrees = 0;
-
-  /* Cope with the statement expression extension.  */
-  else if (code == STATEMENT_LIST)
-    ;
-
-  /* Leave the bulk of the work to copy_tree_r itself.  */
-  else
-    copy_tree_r (tp, walk_subtrees, NULL);
-
-  return NULL_TREE;
-}
-
-/* Callback for walk_tree to unshare most of the shared trees rooted at *TP.
-   If *TP has been visited already, then *TP is deeply copied by calling
-   mostly_copy_tree_r.  DATA is passed to mostly_copy_tree_r unmodified.  */
-
-static tree
-copy_if_shared_r (tree *tp, int *walk_subtrees, void *data)
-{
-  tree t = *tp;
-  enum tree_code code = TREE_CODE (t);
-
-  /* Skip types, decls, and constants.  But we do want to look at their
-     types and the bounds of types.  Mark them as visited so we properly
-     unmark their subtrees on the unmark pass.  If we've already seen them,
-     don't look down further.  */
-  if (TREE_CODE_CLASS (code) == tcc_type
-      || TREE_CODE_CLASS (code) == tcc_declaration
-      || TREE_CODE_CLASS (code) == tcc_constant)
-    {
-      if (TREE_VISITED (t))
-       *walk_subtrees = 0;
-      else
-       TREE_VISITED (t) = 1;
-    }
-
-  /* If this node has been visited already, unshare it and don't look
-     any deeper.  */
-  else if (TREE_VISITED (t))
-    {
-      walk_tree (tp, mostly_copy_tree_r, data, NULL);
-      *walk_subtrees = 0;
-    }
-
-  /* Otherwise, mark the node as visited and keep looking.  */
-  else
-    TREE_VISITED (t) = 1;
-
-  return NULL_TREE;
-}
-
-/* Unshare most of the shared trees rooted at *TP.  DATA is passed to the
-   copy_if_shared_r callback unmodified.  */
-
-void
-copy_if_shared (tree *tp, void *data)
-{
-  walk_tree (tp, copy_if_shared_r, data, NULL);
-}
-
 /* Unshare all the trees in the body of FNDECL, as well as in the bodies of
    any nested functions.  */
 
@@ -1089,41 +964,6 @@ unvisit_body (tree fndecl)
       unvisit_body (cgn->decl);
 }
 
-/* Unconditionally make an unshared copy of EXPR.  This is used when using
-   stored expressions which span multiple functions, such as BINFO_VTABLE,
-   as the normal unsharing process can't tell that they're shared.  */
-
-tree
-unshare_expr (tree expr)
-{
-  walk_tree (&expr, mostly_copy_tree_r, NULL, NULL);
-  return expr;
-}
-
-/* Worker for unshare_expr_without_location.  */
-
-static tree
-prune_expr_location (tree *tp, int *walk_subtrees, void *)
-{
-  if (EXPR_P (*tp))
-    SET_EXPR_LOCATION (*tp, UNKNOWN_LOCATION);
-  else
-    *walk_subtrees = 0;
-  return NULL_TREE;
-}
-
-/* Similar to unshare_expr but also prune all expression locations
-   from EXPR.  */
-
-tree
-unshare_expr_without_location (tree expr)
-{
-  walk_tree (&expr, mostly_copy_tree_r, NULL, NULL);
-  if (EXPR_P (expr))
-    walk_tree (&expr, prune_expr_location, NULL, NULL);
-  return expr;
-}
-
 /* Return the EXPR_LOCATION of EXPR, if it (maybe recursively) has
    one, OR_ELSE otherwise.  The location of a STATEMENT_LISTs
    comprising at least one DEBUG_BEGIN_STMT followed by exactly one
diff --git a/gcc/gimplify.h b/gcc/gimplify.h
index caa35b426bd..18c7514c9a3 100644
--- a/gcc/gimplify.h
+++ b/gcc/gimplify.h
@@ -62,9 +62,6 @@ extern tree get_initialized_tmp_var (tree, gimple_seq *, 
gimple_seq * = NULL,
 extern void declare_vars (tree, gimple *, bool);
 extern void gimple_add_tmp_var (tree);
 extern void gimple_add_tmp_var_fn (struct function *, tree);
-extern void copy_if_shared (tree *, void * = NULL);
-extern tree unshare_expr (tree);
-extern tree unshare_expr_without_location (tree);
 extern tree voidify_wrapper_expr (tree, tree);
 extern tree build_and_jump (tree *);
 extern enum gimplify_status gimplify_self_mod_expr (tree *, gimple_seq *,
diff --git a/gcc/tree-ssa-dom.cc b/gcc/tree-ssa-dom.cc
index 3be7979f528..37a29697319 100644
--- a/gcc/tree-ssa-dom.cc
+++ b/gcc/tree-ssa-dom.cc
@@ -42,7 +42,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-ssa-scopedtables.h"
 #include "tree-ssa-threadedge.h"
 #include "tree-ssa-dom.h"
-#include "gimplify.h"
 #include "tree-cfgcleanup.h"
 #include "dbgcnt.h"
 #include "alloc-pool.h"
diff --git a/gcc/tree-ssa-dse.cc b/gcc/tree-ssa-dse.cc
index 58cfa9ec129..2f97d6d1a1a 100644
--- a/gcc/tree-ssa-dse.cc
+++ b/gcc/tree-ssa-dse.cc
@@ -37,7 +37,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-ssa-dse.h"
 #include "builtins.h"
 #include "gimple-fold.h"
-#include "gimplify.h"
 #include "tree-eh.h"
 #include "cfganal.h"
 #include "cgraph.h"
diff --git a/gcc/tree-ssa-loop-im.cc b/gcc/tree-ssa-loop-im.cc
index 4f7401e2d5d..2651e3919e3 100644
--- a/gcc/tree-ssa-loop-im.cc
+++ b/gcc/tree-ssa-loop-im.cc
@@ -30,7 +30,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "fold-const.h"
 #include "cfganal.h"
 #include "tree-eh.h"
-#include "gimplify.h"
 #include "gimple-iterator.h"
 #include "tree-cfg.h"
 #include "tree-ssa-loop-manip.h"
diff --git a/gcc/tree-ssa-loop-niter.cc b/gcc/tree-ssa-loop-niter.cc
index c39401147ae..f179be1ffc7 100644
--- a/gcc/tree-ssa-loop-niter.cc
+++ b/gcc/tree-ssa-loop-niter.cc
@@ -32,7 +32,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "fold-const.h"
 #include "calls.h"
 #include "intl.h"
-#include "gimplify.h"
 #include "gimple-iterator.h"
 #include "tree-cfg.h"
 #include "tree-ssa-loop-ivopts.h"
diff --git a/gcc/tree-ssa-loop-unswitch.cc b/gcc/tree-ssa-loop-unswitch.cc
index 96680bc64ea..a18c9ccfffa 100644
--- a/gcc/tree-ssa-loop-unswitch.cc
+++ b/gcc/tree-ssa-loop-unswitch.cc
@@ -26,7 +26,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-pass.h"
 #include "ssa.h"
 #include "fold-const.h"
-#include "gimplify.h"
 #include "tree-cfg.h"
 #include "tree-ssa.h"
 #include "tree-ssa-loop-niter.h"
diff --git a/gcc/tree-ssa-math-opts.cc b/gcc/tree-ssa-math-opts.cc
index cd3fd2fc8fb..72f6dbd1a99 100644
--- a/gcc/tree-ssa-math-opts.cc
+++ b/gcc/tree-ssa-math-opts.cc
@@ -102,8 +102,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "fold-const.h"
 #include "gimple-iterator.h"
 #include "gimple-fold.h"
-#include "gimplify.h"
-#include "gimplify-me.h"
 #include "stor-layout.h"
 #include "tree-cfg.h"
 #include "tree-dfa.h"
diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc
index e654e823636..18b5f284eee 100644
--- a/gcc/tree-ssa-phiopt.cc
+++ b/gcc/tree-ssa-phiopt.cc
@@ -35,9 +35,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "fold-const.h"
 #include "stor-layout.h"
 #include "cfganal.h"
-#include "gimplify.h"
 #include "gimple-iterator.h"
-#include "gimplify-me.h"
 #include "tree-cfg.h"
 #include "tree-dfa.h"
 #include "domwalk.h"
diff --git a/gcc/tree-ssa-phiprop.cc b/gcc/tree-ssa-phiprop.cc
index 54f3ad8d9f8..7e7a4534eb2 100644
--- a/gcc/tree-ssa-phiprop.cc
+++ b/gcc/tree-ssa-phiprop.cc
@@ -29,7 +29,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-pretty-print.h"
 #include "fold-const.h"
 #include "tree-eh.h"
-#include "gimplify.h"
 #include "gimple-iterator.h"
 #include "stor-layout.h"
 #include "tree-ssa-loop.h"
diff --git a/gcc/tree-ssa-pre.cc b/gcc/tree-ssa-pre.cc
index 0e5eaf86bc7..5ded68443dd 100644
--- a/gcc/tree-ssa-pre.cc
+++ b/gcc/tree-ssa-pre.cc
@@ -37,7 +37,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-iterator.h"
 #include "gimple-fold.h"
 #include "tree-eh.h"
-#include "gimplify.h"
 #include "tree-cfg.h"
 #include "tree-into-ssa.h"
 #include "tree-dfa.h"
diff --git a/gcc/tree-ssa-propagate.cc b/gcc/tree-ssa-propagate.cc
index a87c45d3a12..992b4243670 100644
--- a/gcc/tree-ssa-propagate.cc
+++ b/gcc/tree-ssa-propagate.cc
@@ -30,7 +30,6 @@
 #include "gimple-iterator.h"
 #include "gimple-fold.h"
 #include "tree-eh.h"
-#include "gimplify.h"
 #include "tree-cfg.h"
 #include "tree-ssa.h"
 #include "tree-ssa-propagate.h"
diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc
index e19beb439d2..79b6b465294 100644
--- a/gcc/tree-ssa-sccvn.cc
+++ b/gcc/tree-ssa-sccvn.cc
@@ -42,7 +42,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-iterator.h"
 #include "gimple-fold.h"
 #include "tree-eh.h"
-#include "gimplify.h"
 #include "flags.h"
 #include "dojump.h"
 #include "explow.h"
diff --git a/gcc/tree.cc b/gcc/tree.cc
index 8479ffab584..e3df004be97 100644
--- a/gcc/tree.cc
+++ b/gcc/tree.cc
@@ -15847,6 +15847,165 @@ diagnose_versioned_decls (tree old_decl, tree 
new_decl)
            (old_target_attr, old_decl, new_target_attr, new_decl);
 }
 
+
+/* This page contains routines to unshare tree nodes, i.e. to duplicate tree
+   nodes that are referenced more than once in GENERIC functions.  This is
+   necessary because gimplification (translation into GIMPLE) is performed
+   by modifying tree nodes in-place, so gimplification of a shared node in a
+   first context could generate an invalid GIMPLE form in a second context.
+
+   This is achieved with a simple mark/copy/unmark algorithm that walks the
+   GENERIC representation top-down, marks nodes with TREE_VISITED the first
+   time it encounters them, duplicates them if they already have TREE_VISITED
+   set, and finally removes the TREE_VISITED marks it has set.
+
+   The algorithm works only at the function level, i.e. it generates a GENERIC
+   representation of a function with no nodes shared within the function when
+   passed a GENERIC function (except for nodes that are allowed to be shared).
+
+   At the global level, it is also necessary to unshare tree nodes that are
+   referenced in more than one function, for the same aforementioned reason.
+   This requires some cooperation from the front-end.  There are 2 strategies:
+
+     1. Manual unsharing.  The front-end needs to call unshare_expr on every
+        expression that might end up being shared across functions.
+
+     2. Deep unsharing.  This is an extension of regular unsharing.  Instead
+        of calling unshare_expr on expressions that might be shared across
+        functions, the front-end pre-marks them with TREE_VISITED.  This will
+        ensure that they are unshared on the first reference within functions
+        when the regular unsharing algorithm runs.  The counterpart is that
+        this algorithm must look deeper than for manual unsharing, which is
+        specified by LANG_HOOKS_DEEP_UNSHARING.
+
+  If there are only few specific cases of node sharing across functions, it is
+  probably easier for a front-end to unshare the expressions manually.  On the
+  contrary, if the expressions generated at the global level are as widespread
+  as expressions generated within functions, deep unsharing is very likely the
+  way to go.  */
+
+/* Similar to copy_tree_r but do not copy SAVE_EXPR or TARGET_EXPR nodes.
+   These nodes model computations that must be done once.  If we were to
+   unshare something like SAVE_EXPR(i++), the gimplification process would
+   create wrong code.  However, if DATA is non-null, it must hold a pointer
+   set that is used to unshare the subtrees of these nodes.  */
+
+static tree
+mostly_copy_tree_r (tree *tp, int *walk_subtrees, void *data)
+{
+  tree t = *tp;
+  enum tree_code code = TREE_CODE (t);
+
+  /* Do not copy SAVE_EXPR, TARGET_EXPR or BIND_EXPR nodes themselves, but
+     copy their subtrees if we can make sure to do it only once.  */
+  if (code == SAVE_EXPR || code == TARGET_EXPR || code == BIND_EXPR)
+    {
+      if (data && !((hash_set<tree> *)data)->add (t))
+       ;
+      else
+       *walk_subtrees = 0;
+    }
+
+  /* Stop at types, decls, constants like copy_tree_r.  */
+  else if (TREE_CODE_CLASS (code) == tcc_type
+          || TREE_CODE_CLASS (code) == tcc_declaration
+          || TREE_CODE_CLASS (code) == tcc_constant)
+    *walk_subtrees = 0;
+
+  /* Cope with the statement expression extension.  */
+  else if (code == STATEMENT_LIST)
+    ;
+
+  /* Leave the bulk of the work to copy_tree_r itself.  */
+  else
+    copy_tree_r (tp, walk_subtrees, NULL);
+
+  return NULL_TREE;
+}
+
+/* Callback for walk_tree to unshare most of the shared trees rooted at *TP.
+   If *TP has been visited already, then *TP is deeply copied by calling
+   mostly_copy_tree_r.  DATA is passed to mostly_copy_tree_r unmodified.  */
+
+static tree
+copy_if_shared_r (tree *tp, int *walk_subtrees, void *data)
+{
+  tree t = *tp;
+  enum tree_code code = TREE_CODE (t);
+
+  /* Skip types, decls, and constants.  But we do want to look at their
+     types and the bounds of types.  Mark them as visited so we properly
+     unmark their subtrees on the unmark pass.  If we've already seen them,
+     don't look down further.  */
+  if (TREE_CODE_CLASS (code) == tcc_type
+      || TREE_CODE_CLASS (code) == tcc_declaration
+      || TREE_CODE_CLASS (code) == tcc_constant)
+    {
+      if (TREE_VISITED (t))
+       *walk_subtrees = 0;
+      else
+       TREE_VISITED (t) = 1;
+    }
+
+  /* If this node has been visited already, unshare it and don't look
+     any deeper.  */
+  else if (TREE_VISITED (t))
+    {
+      walk_tree (tp, mostly_copy_tree_r, data, NULL);
+      *walk_subtrees = 0;
+    }
+
+  /* Otherwise, mark the node as visited and keep looking.  */
+  else
+    TREE_VISITED (t) = 1;
+
+  return NULL_TREE;
+}
+
+/* Unshare most of the shared trees rooted at *TP.  DATA is passed to the
+   copy_if_shared_r callback unmodified.  */
+
+void
+copy_if_shared (tree *tp, void *data)
+{
+  walk_tree (tp, copy_if_shared_r, data, NULL);
+}
+
+/* Unconditionally make an unshared copy of EXPR.  This is used when using
+   stored expressions which span multiple functions, such as BINFO_VTABLE,
+   as the normal unsharing process can't tell that they're shared.  */
+
+tree
+unshare_expr (tree expr)
+{
+  walk_tree (&expr, mostly_copy_tree_r, NULL, NULL);
+  return expr;
+}
+
+/* Worker for unshare_expr_without_location.  */
+
+static tree
+prune_expr_location (tree *tp, int *walk_subtrees, void *)
+{
+  if (EXPR_P (*tp))
+    SET_EXPR_LOCATION (*tp, UNKNOWN_LOCATION);
+  else
+    *walk_subtrees = 0;
+  return NULL_TREE;
+}
+
+/* Similar to unshare_expr but also prune all expression locations
+   from EXPR.  */
+
+tree
+unshare_expr_without_location (tree expr)
+{
+  walk_tree (&expr, mostly_copy_tree_r, NULL, NULL);
+  if (EXPR_P (expr))
+    walk_tree (&expr, prune_expr_location, NULL, NULL);
+  return expr;
+}
+
 void
 tree_cc_finalize (void)
 {
diff --git a/gcc/tree.h b/gcc/tree.h
index 3b012d0fd6a..05400ada20b 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -7204,4 +7204,13 @@ extern bool disjoint_version_decls (tree, tree);
 /* Checks if two overlapping decls are not mergeable.  */
 extern bool diagnose_versioned_decls (tree, tree);
 
+/* Unshare tree if needed.  */
+extern tree unshare_expr (tree);
+
+/* Unshare tree if needed.
+   Removing the locations if an expr.  */
+extern tree unshare_expr_without_location (tree);
+
+extern void copy_if_shared (tree *, void * = NULL);
+
 #endif  /* GCC_TREE_H  */
-- 
2.43.0

Reply via email to