diff options
author | Nathan Sidwell <nathan@acm.org> | 2017-05-18 18:18:04 +0000 |
---|---|---|
committer | Nathan Sidwell <nathan@gcc.gnu.org> | 2017-05-18 18:18:04 +0000 |
commit | 1bf07cc3ff38a893fd8daa248e834e9dac567b88 (patch) | |
tree | 77b3a653555adf1b37e9c52263d8229454df32f6 /gcc/cp/tree.c | |
parent | 7d2f2a6b73fd5022f9f96ffc9e2806c8d7464112 (diff) | |
download | gcc-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.c | 78 |
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 |