summaryrefslogtreecommitdiff
path: root/gcc/cp/name-lookup.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/name-lookup.c')
-rw-r--r--gcc/cp/name-lookup.c75
1 files changed, 59 insertions, 16 deletions
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index cc8439c9ccd..22bc5e7c006 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -441,7 +441,8 @@ supplement_binding_1 (cxx_binding *binding, tree decl)
template in order to handle late matching of underlying
type on an opaque-enum-declaration followed by an
enum-specifier. */
- || (TREE_CODE (TREE_TYPE (target_decl)) == ENUMERAL_TYPE
+ || (processing_template_decl
+ && TREE_CODE (TREE_TYPE (target_decl)) == ENUMERAL_TYPE
&& TREE_CODE (TREE_TYPE (target_bval)) == ENUMERAL_TYPE
&& (dependent_type_p (ENUM_UNDERLYING_TYPE
(TREE_TYPE (target_decl)))
@@ -2420,7 +2421,15 @@ validate_nonmember_using_decl (tree decl, tree scope, tree name)
gcc_assert (DECL_P (decl));
/* Make a USING_DECL. */
- return push_using_decl (scope, name);
+ tree using_decl = push_using_decl (scope, name);
+
+ if (using_decl == NULL_TREE
+ && at_function_scope_p ()
+ && TREE_CODE (decl) == VAR_DECL)
+ /* C++11 7.3.3/10. */
+ error ("%qD is already declared in this scope", name);
+
+ return using_decl;
}
/* Process local and global using-declarations. */
@@ -4059,7 +4068,7 @@ ambiguous_decl (struct scope_binding *old, cxx_binding *new_binding, int flags)
/* If we expect types or namespaces, and not templates,
or this is not a template class. */
if ((LOOKUP_QUALIFIERS_ONLY (flags)
- && !DECL_CLASS_TEMPLATE_P (val)))
+ && !DECL_TYPE_TEMPLATE_P (val)))
val = NULL_TREE;
break;
case TYPE_DECL:
@@ -5855,23 +5864,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 +5900,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 +5937,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);
}