aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/tree.c
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@acm.org>2017-05-18 18:18:04 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2017-05-18 18:18:04 +0000
commit1bf07cc3ff38a893fd8daa248e834e9dac567b88 (patch)
tree77b3a653555adf1b37e9c52263d8229454df32f6 /gcc/cp/tree.c
parent7d2f2a6b73fd5022f9f96ffc9e2806c8d7464112 (diff)
downloadgcc-1bf07cc3ff38a893fd8daa248e834e9dac567b88.zip
gcc-1bf07cc3ff38a893fd8daa248e834e9dac567b88.tar.gz
gcc-1bf07cc3ff38a893fd8daa248e834e9dac567b88.tar.bz2
cp-tree.h (OVL_ARG_DEPENDENT): Delete.
* cp-tree.h (OVL_ARG_DEPENDENT): Delete. (OVL_USED_P): New. (lookup_keep): Declare. * name-lookup.c (add_function): Don't set OVL_ARG_DEPENDENT. * pt.c (tsubst_copy): Assert lookup is persistent. * semantics.c (finish_call_expr): Use lkp_iterator, call lookup_keep. * tree.c (ovl_copy): New. (ovl_insert, ovl_iterator::remove_node): Copy immutable nodes. (lookup_keep): New. From-SVN: r248250
Diffstat (limited to 'gcc/cp/tree.c')
-rw-r--r--gcc/cp/tree.c78
1 files changed, 75 insertions, 3 deletions
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 61254c0..e2d0225 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -2124,6 +2124,30 @@ ovl_make (tree fn, tree next)
return result;
}
+static tree
+ovl_copy (tree ovl)
+{
+ tree result = ovl_cache;
+
+ if (result)
+ {
+ ovl_cache = OVL_FUNCTION (result);
+ /* Zap the flags. */
+ memset (result, 0, sizeof (tree_base));
+ TREE_SET_CODE (result, OVERLOAD);
+ }
+ else
+ result = make_node (OVERLOAD);
+
+ gcc_assert (!OVL_NESTED_P (ovl) && !OVL_LOOKUP_P (ovl));
+ TREE_TYPE (result) = TREE_TYPE (ovl);
+ OVL_FUNCTION (result) = OVL_FUNCTION (ovl);
+ OVL_CHAIN (result) = OVL_CHAIN (ovl);
+ OVL_USING_P (ovl) = OVL_USING_P (ovl);
+
+ return result;
+}
+
/* Add FN to the (potentially NULL) overload set OVL. USING_P is
true, if FN is via a using declaration. Overloads are ordered as
using, regular. */
@@ -2131,6 +2155,7 @@ ovl_make (tree fn, tree next)
tree
ovl_insert (tree fn, tree maybe_ovl, bool using_p)
{
+ bool copying = false; /* Checking use only. */
int weight = using_p;
tree result = NULL_TREE;
@@ -2140,6 +2165,15 @@ ovl_insert (tree fn, tree maybe_ovl, bool using_p)
while (maybe_ovl && TREE_CODE (maybe_ovl) == OVERLOAD
&& (weight < OVL_USING_P (maybe_ovl)))
{
+ gcc_checking_assert (!OVL_LOOKUP_P (maybe_ovl)
+ && (!OVL_USED_P (maybe_ovl) || !copying));
+ if (OVL_USED_P (maybe_ovl))
+ {
+ copying = true;
+ maybe_ovl = ovl_copy (maybe_ovl);
+ if (insert_after)
+ OVL_CHAIN (insert_after) = maybe_ovl;
+ }
if (!result)
result = maybe_ovl;
insert_after = maybe_ovl;
@@ -2156,7 +2190,7 @@ ovl_insert (tree fn, tree maybe_ovl, bool using_p)
if (insert_after)
{
- TREE_CHAIN (insert_after) = trail;
+ OVL_CHAIN (insert_after) = trail;
TREE_TYPE (insert_after) = unknown_type_node;
}
else
@@ -2165,14 +2199,32 @@ ovl_insert (tree fn, tree maybe_ovl, bool using_p)
return result;
}
-/* NODE is on the overloads of OVL. Remove it. */
+/* NODE is on the overloads of OVL. Remove it. If a predecessor is
+ OVL_USED_P we must copy OVL nodes, because those are immutable.
+ The removed node is unaltered and may continue to be iterated
+ from (i.e. it is safe to remove a node from an overload one is
+ currently iterating over). */
tree
ovl_iterator::remove_node (tree overload, tree node)
{
+ bool copying = false; /* Checking use only. */
+
tree *slot = &overload;
while (*slot != node)
- slot = &OVL_CHAIN (*slot);
+ {
+ tree probe = *slot;
+ gcc_checking_assert (!OVL_LOOKUP_P (probe)
+ && (!OVL_USED_P (probe) || !copying));
+ if (OVL_USED_P (probe))
+ {
+ copying = true;
+ probe = ovl_copy (probe);
+ *slot = probe;
+ }
+
+ slot = &OVL_CHAIN (probe);
+ }
/* Stitch out NODE. We don't have to worry about now making a
singleton overload (and consequently maybe setting its type),
@@ -2199,6 +2251,26 @@ lookup_add (tree fns, tree lookup)
return lookup;
}
+/* If KEEP is true, preserve the contents of a lookup so that it is
+ available for a later instantiation. Otherwise release the LOOKUP
+ nodes for reuse. */
+
+void
+lookup_keep (tree lookup, bool keep)
+{
+ for (;
+ lookup && TREE_CODE (lookup) == OVERLOAD
+ && OVL_LOOKUP_P (lookup) && !OVL_USED_P (lookup);
+ lookup = OVL_CHAIN (lookup))
+ if (keep)
+ OVL_USED_P (lookup) = true;
+ else
+ {
+ OVL_FUNCTION (lookup) = ovl_cache;
+ ovl_cache = lookup;
+ }
+}
+
/* Returns nonzero if X is an expression for a (possibly overloaded)
function. If "f" is a function or function template, "f", "c->f",
"c.f", "C::f", and "f<int>" will all be considered possibly