diff options
-rw-r--r-- | gcc/cp/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/cp/name-lookup.c | 60 |
2 files changed, 56 insertions, 13 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e64bbdf..b596155 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2012-08-20 Richard Guenther <rguenther@suse.de> + + * name-lookup.c (store_binding_p): New predicate, split out from ... + (store_binding): ... here. Always store binding and require + target vector with enough space. + (store_bindings): Collect to store bindings and reserve space + for them, then store them. + (store_class_bindings): Likewise. + 2012-08-19 Mikael Morin <mikael@gcc.gnu.org> * Make-lang.in: Fix typo. diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 97581d9..f8dbfa1 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -5855,23 +5855,33 @@ pushtag (tree name, tree type, tag_scope scope) scope isn't enough, because more binding levels may be pushed. */ struct saved_scope *scope_chain; -/* If ID has not already been marked, add an appropriate binding to - *OLD_BINDINGS. */ +/* Return true if ID has not already been marked. */ + +static inline bool +store_binding_p (tree id) +{ + if (!id || !IDENTIFIER_BINDING (id)) + return false; + + if (IDENTIFIER_MARKED (id)) + return false; + + return true; +} + +/* Add an appropriate binding to *OLD_BINDINGS which needs to already + have enough space reserved. */ static void store_binding (tree id, VEC(cxx_saved_binding,gc) **old_bindings) { cxx_saved_binding *saved; - if (!id || !IDENTIFIER_BINDING (id)) - return; - - if (IDENTIFIER_MARKED (id)) - return; + gcc_checking_assert (store_binding_p (id)); IDENTIFIER_MARKED (id) = 1; - saved = VEC_safe_push (cxx_saved_binding, gc, *old_bindings, NULL); + saved = VEC_quick_push (cxx_saved_binding, *old_bindings, NULL); saved->identifier = id; saved->binding = IDENTIFIER_BINDING (id); saved->real_type_value = REAL_IDENTIFIER_TYPE_VALUE (id); @@ -5881,19 +5891,32 @@ store_binding (tree id, VEC(cxx_saved_binding,gc) **old_bindings) static void store_bindings (tree names, VEC(cxx_saved_binding,gc) **old_bindings) { - tree t; + static VEC(tree,heap) *bindings_need_stored = NULL; + tree t, id; + size_t i; bool subtime = timevar_cond_start (TV_NAME_LOOKUP); for (t = names; t; t = TREE_CHAIN (t)) { - tree id; - if (TREE_CODE (t) == TREE_LIST) id = TREE_PURPOSE (t); else id = DECL_NAME (t); - store_binding (id, old_bindings); + if (store_binding_p (id)) + VEC_safe_push(tree, heap, bindings_need_stored, id); + } + if (!VEC_empty (tree, bindings_need_stored)) + { + VEC_reserve_exact (cxx_saved_binding, gc, *old_bindings, + VEC_length (tree, bindings_need_stored)); + for (i = 0; VEC_iterate(tree, bindings_need_stored, i, id); ++i) + { + /* We can appearantly have duplicates in NAMES. */ + if (store_binding_p (id)) + store_binding (id, old_bindings); + } + VEC_truncate (tree, bindings_need_stored, 0); } timevar_cond_stop (TV_NAME_LOOKUP, subtime); } @@ -5905,12 +5928,23 @@ static void store_class_bindings (VEC(cp_class_binding,gc) *names, VEC(cxx_saved_binding,gc) **old_bindings) { + static VEC(tree,heap) *bindings_need_stored = NULL; size_t i; cp_class_binding *cb; bool subtime = timevar_cond_start (TV_NAME_LOOKUP); for (i = 0; VEC_iterate(cp_class_binding, names, i, cb); ++i) - store_binding (cb->identifier, old_bindings); + if (store_binding_p (cb->identifier)) + VEC_safe_push (tree, heap, bindings_need_stored, cb->identifier); + if (!VEC_empty (tree, bindings_need_stored)) + { + tree id; + VEC_reserve_exact (cxx_saved_binding, gc, *old_bindings, + VEC_length (tree, bindings_need_stored)); + for (i = 0; VEC_iterate(tree, bindings_need_stored, i, id); ++i) + store_binding (id, old_bindings); + VEC_truncate (tree, bindings_need_stored, 0); + } timevar_cond_stop (TV_NAME_LOOKUP, subtime); } |