From 9d029ddfdadd3a469a8069ff498a29df8cdb5393 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Tue, 23 May 2017 10:58:57 +0000 Subject: [PATCH] cp-tree.h (OVL_P): New. gcc/cp * cp-tree.h (OVL_P): New. * name-lookup.h (push_local_binding): Delete. (do_toplevel_using_decl, do_local_using_decl): Rename to ... (finish_namespace_using_decl, finish_local_using_decl): ... here * name-lookup.c (add_decl_to_level): Swap args. (pop_bindings_and_leave_scope): Look inside TREE_LIST. (diagnose_name_conflict): Check contexts are same for redecl. (update_local_overload): New. (compparms_for_decl_and_using): Rename to ... (matching_fn_p): ... here. (pushdecl_maybe_friend_1): Adjust add_decl_to_level, push_local_bindings call. (push_local_binding): Make static, replace FLAGS arg with IS_USING. (validate_nonmember_using_decl): Use OVL_FIRST. (do_nonmember_using_decl): Use in/out parameters. Use lkp_iterator and simplify. (do_toplevel_using_decl, do_local_using_decl): Rename to ... (finish_namespace_using_decl, finish_local_using_decl): ... here. Adjust. (lookup_type_current_level): Delete. * parser.c (cp_parser_using_declaration): Adjust. * pt.c (tsubst_expr): Adjust. libcc1/ * libcp1plugin.cc (plugin_add_using_decl): Call finish_namespace_using_decl. Use assert not unreachable. gcc/testsuite/ * g++.dg/lookup/using13.C: Adjust expected error. From-SVN: r248364 --- gcc/cp/ChangeLog | 26 ++ gcc/cp/cp-tree.h | 5 + gcc/cp/name-lookup.c | 451 ++++++++++++++++------------------ gcc/cp/name-lookup.h | 5 +- gcc/cp/parser.c | 4 +- gcc/cp/pt.c | 2 +- gcc/testsuite/ChangeLog | 4 + gcc/testsuite/g++.dg/lookup/using13.C | 2 +- libcc1/ChangeLog | 5 + libcc1/libcp1plugin.cc | 9 +- 10 files changed, 266 insertions(+), 247 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ba03324..aaf39c2 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,29 @@ +2017-05-23 Nathan Sidwell + + * cp-tree.h (OVL_P): New. + * name-lookup.h (push_local_binding): Delete. + (do_toplevel_using_decl, do_local_using_decl): Rename to ... + (finish_namespace_using_decl, finish_local_using_decl): ... here + * name-lookup.c (add_decl_to_level): Swap args. + (pop_bindings_and_leave_scope): Look inside TREE_LIST. + (diagnose_name_conflict): Check contexts are same for redecl. + (update_local_overload): New. + (compparms_for_decl_and_using): Rename to ... + (matching_fn_p): ... here. + (pushdecl_maybe_friend_1): Adjust add_decl_to_level, + push_local_bindings call. + (push_local_binding): Make static, replace FLAGS arg with + IS_USING. + (validate_nonmember_using_decl): Use OVL_FIRST. + (do_nonmember_using_decl): Use in/out parameters. Use + lkp_iterator and simplify. + (do_toplevel_using_decl, do_local_using_decl): Rename to ... + (finish_namespace_using_decl, finish_local_using_decl): ... here. + Adjust. + (lookup_type_current_level): Delete. + * parser.c (cp_parser_using_declaration): Adjust. + * pt.c (tsubst_expr): Adjust. + 2017-05-22 Nathan Sidwell * name-lookup.h (parse_using_directive): Replace with ... diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 0064222..8e8e560 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -671,6 +671,11 @@ typedef struct ptrmem_cst * ptrmem_cst_t; /* The name of the overload set. */ #define OVL_NAME(NODE) DECL_NAME (OVL_FIRST (NODE)) +/* Whether this is a set of overloaded functions. TEMPLATE_DECLS are + always wrapped in an OVERLOAD, so we don't need to check them + here. */ +#define OVL_P(NODE) \ + (TREE_CODE (NODE) == FUNCTION_DECL || TREE_CODE (NODE) == OVERLOAD) /* Whether this is a single member overload. */ #define OVL_SINGLE_P(NODE) \ (TREE_CODE (NODE) != OVERLOAD || !OVL_CHAIN (NODE)) diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 7178932..c79ded3 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -38,6 +38,7 @@ static cp_binding_level *innermost_nonclass_level (void); static void set_identifier_type_value_with_scope (tree id, tree decl, cp_binding_level *b); static void set_namespace_binding (tree scope, tree name, tree val); +static void push_local_binding (tree, tree, bool); /* The bindings for a particular name in a particular scope. */ @@ -58,14 +59,13 @@ static void consider_binding_level (tree name, cp_binding_level *lvl, bool look_within_fields, enum lookup_name_fuzzy_kind kind); -static tree lookup_type_current_level (tree); static tree push_using_directive (tree); static void diagnose_name_conflict (tree, tree); /* Add DECL to the list of things declared in B. */ static void -add_decl_to_level (tree decl, cp_binding_level *b) +add_decl_to_level (cp_binding_level *b, tree decl) { /* We used to record virtual tables as if they were ordinary variables, but no longer do so. */ @@ -995,7 +995,13 @@ void pop_bindings_and_leave_scope (void) { for (tree t = get_local_decls (); t; t = DECL_CHAIN (t)) - pop_local_binding (DECL_NAME (t), t); + { + tree decl = TREE_CODE (t) == TREE_LIST ? TREE_VALUE (t) : t; + tree name = OVL_NAME (decl); + + pop_local_binding (name, decl); + } + leave_scope (); } @@ -1179,7 +1185,8 @@ diagnose_name_conflict (tree decl, tree bval) && (TREE_CODE (decl) != TYPE_DECL || (DECL_ARTIFICIAL (decl) && DECL_ARTIFICIAL (bval)) || (!DECL_ARTIFICIAL (decl) && !DECL_ARTIFICIAL (bval))) - && !is_overloaded_fn (decl)) + && !DECL_DECLARES_FUNCTION_P (decl) + && CP_DECL_CONTEXT (decl) == CP_DECL_CONTEXT (bval)) error ("redeclaration of %q#D", decl); else error ("%q#D conflicts with a previous declaration", decl); @@ -1199,6 +1206,56 @@ supplement_binding (cxx_binding *binding, tree decl) return ret; } +/* Replace BINDING's current value on its scope's name list with + NEWVAL. */ + +static void +update_local_overload (cxx_binding *binding, tree newval) +{ + tree *d; + + for (d = &binding->scope->names; ; d = &TREE_CHAIN (*d)) + if (*d == binding->value) + { + /* Stitch new list node in. */ + *d = tree_cons (NULL_TREE, NULL_TREE, TREE_CHAIN (*d)); + break; + } + else if (TREE_CODE (*d) == TREE_LIST && TREE_VALUE (*d) == binding->value) + break; + + TREE_VALUE (*d) = newval; +} + +/* Compares the parameter-type-lists of ONE and TWO and + returns false if they are different. If the DECLs are template + functions, the return types and the template parameter lists are + compared too (DR 565). */ + +static bool +matching_fn_p (tree one, tree two) +{ + if (!compparms (TYPE_ARG_TYPES (TREE_TYPE (one)), + TYPE_ARG_TYPES (TREE_TYPE (two)))) + return false; + + if (TREE_CODE (one) == TEMPLATE_DECL + && TREE_CODE (two) == TEMPLATE_DECL) + { + /* Compare template parms. */ + if (!comp_template_parms (DECL_TEMPLATE_PARMS (one), + DECL_TEMPLATE_PARMS (two))) + return false; + + /* And return type. */ + if (!same_type_p (TREE_TYPE (TREE_TYPE (one)), + TREE_TYPE (TREE_TYPE (two)))) + return false; + } + + return true; +} + /* Map of identifiers to extern C functions (or LISTS thereof). */ static GTY(()) hash_map *extern_c_fns; @@ -1699,7 +1756,7 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend) { t = push_overloaded_decl (x, PUSH_GLOBAL, is_friend); if (t == x) - add_decl_to_level (x, NAMESPACE_LEVEL (CP_DECL_CONTEXT (t))); + add_decl_to_level (NAMESPACE_LEVEL (CP_DECL_CONTEXT (t)), x); } if (DECL_DECLARES_FUNCTION_P (t)) @@ -1814,7 +1871,7 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend) if (need_new_binding) { - push_local_binding (name, x, 0); + push_local_binding (name, x, false); /* Because push_local_binding will hook X on to the current_binding_level's name list, we don't want to do that again below. */ @@ -1881,10 +1938,9 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend) } if (need_new_binding) - add_decl_to_level (x, - DECL_NAMESPACE_SCOPE_P (x) + add_decl_to_level (DECL_NAMESPACE_SCOPE_P (x) ? NAMESPACE_LEVEL (CP_DECL_CONTEXT (x)) - : current_binding_level); + : current_binding_level, x); return x; } @@ -1932,12 +1988,11 @@ maybe_push_decl (tree decl) } /* Bind DECL to ID in the current_binding_level, assumed to be a local - binding level. If PUSH_USING is set in FLAGS, we know that DECL - doesn't really belong to this binding level, that it got here - through a using-declaration. */ + binding level. If IS_USING is true, DECL got here through a + using-declaration. */ -void -push_local_binding (tree id, tree decl, int flags) +static void +push_local_binding (tree id, tree decl, bool is_using) { cp_binding_level *b; @@ -1958,15 +2013,14 @@ push_local_binding (tree id, tree decl, int flags) /* Create a new binding. */ push_binding (id, decl, b); - if (TREE_CODE (decl) == OVERLOAD || (flags & PUSH_USING)) - /* We must put the OVERLOAD into a TREE_LIST since the - TREE_CHAIN of an OVERLOAD is already used. Similarly for - decls that got here through a using-declaration. */ + if (TREE_CODE (decl) == OVERLOAD || is_using) + /* We must put the OVERLOAD or using into a TREE_LIST since we + cannot use the decl's chain itself. */ decl = build_tree_list (NULL_TREE, decl); /* And put DECL on the list of things declared by the current binding level. */ - add_decl_to_level (decl, b); + add_decl_to_level (b, decl); } /* Check to see whether or not DECL is a variable that would have been @@ -2840,28 +2894,6 @@ pushdecl_outermost_localscope (tree x) return ret; } -/* Helper function for push_overloaded_decl_1 and do_nonmember_using_decl. - Compares the parameter-type-lists of DECL1 and DECL2 and returns false - if they are different. If the DECLs are template functions, the return - types and the template parameter lists are compared too (DR 565). */ - -static bool -compparms_for_decl_and_using_decl (tree decl1, tree decl2) -{ - if (!compparms (TYPE_ARG_TYPES (TREE_TYPE (decl1)), - TYPE_ARG_TYPES (TREE_TYPE (decl2)))) - return false; - - if (! DECL_FUNCTION_TEMPLATE_P (decl1) - || ! DECL_FUNCTION_TEMPLATE_P (decl2)) - return true; - - return (comp_template_parms (DECL_TEMPLATE_PARMS (decl1), - DECL_TEMPLATE_PARMS (decl2)) - && same_type_p (TREE_TYPE (TREE_TYPE (decl1)), - TREE_TYPE (TREE_TYPE (decl2)))); -} - /* DECL is a FUNCTION_DECL for a non-member function, which may have other definitions already in place. We get around this by making the value of the identifier point to a list of all the things that @@ -2918,7 +2950,7 @@ push_overloaded_decl_1 (tree decl, int flags, bool is_friend) if (TREE_CODE (tmp) == OVERLOAD && OVL_USING_P (tmp) && !(flags & PUSH_USING) - && compparms_for_decl_and_using_decl (fn, decl) + && matching_fn_p (fn, decl) && ! decls_match (fn, decl)) diagnose_name_conflict (decl, fn); @@ -3047,10 +3079,7 @@ validate_nonmember_using_decl (tree decl, tree scope, tree name) return NULL_TREE; } - if (is_overloaded_fn (decl)) - decl = get_first_fn (decl); - - gcc_assert (DECL_P (decl)); + decl = OVL_FIRST (decl); /* Make a USING_DECL. */ tree using_decl = push_using_decl (scope, name); @@ -3064,60 +3093,64 @@ validate_nonmember_using_decl (tree decl, tree scope, tree name) return using_decl; } -/* Process local and global using-declarations. */ +/* Process a local-scope or namespace-scope using declaration. SCOPE + is the nominated scope to search for NAME. VALUE_P and TYPE_P + point to the binding for NAME in the current scope and are + updated. */ static void -do_nonmember_using_decl (tree scope, tree name, tree oldval, tree oldtype, - tree *newval, tree *newtype) +do_nonmember_using_decl (tree scope, tree name, tree *value_p, tree *type_p) { - struct scope_binding decls = EMPTY_SCOPE_BINDING; + struct scope_binding lookup = EMPTY_SCOPE_BINDING; - *newval = *newtype = NULL_TREE; - if (!qualified_lookup_using_namespace (name, scope, &decls, 0)) + if (!qualified_lookup_using_namespace (name, scope, &lookup, 0)) /* Lookup error */ return; - if (!decls.value && !decls.type) + if (!lookup.value) { error ("%qD not declared", name); return; } + else if (TREE_CODE (lookup.value) == TREE_LIST) + { + error ("reference to %qD is ambiguous", name); + print_candidates (lookup.value); + lookup.value = NULL_TREE; + } + + if (lookup.type && TREE_CODE (lookup.type) == TREE_LIST) + { + error ("reference to %qD is ambiguous", name); + print_candidates (lookup.type); + lookup.type = NULL_TREE; + } + + tree value = *value_p; + tree type = *type_p; /* Shift the old and new bindings around so we're comparing class and enumeration names to each other. */ - if (oldval && DECL_IMPLICIT_TYPEDEF_P (oldval)) + if (value && DECL_IMPLICIT_TYPEDEF_P (value)) { - oldtype = oldval; - oldval = NULL_TREE; + type = value; + value = NULL_TREE; } - if (decls.value && DECL_IMPLICIT_TYPEDEF_P (decls.value)) + if (lookup.value && DECL_IMPLICIT_TYPEDEF_P (lookup.value)) { - decls.type = decls.value; - decls.value = NULL_TREE; + lookup.type = lookup.value; + lookup.value = NULL_TREE; } - if (decls.value) + if (lookup.value && lookup.value != value) { /* Check for using functions. */ - if (is_overloaded_fn (decls.value)) + if (OVL_P (lookup.value) && (!value || OVL_P (value))) { - tree tmp, tmp1; - - if (oldval && !is_overloaded_fn (oldval)) + for (lkp_iterator usings (lookup.value); usings; ++usings) { - error ("%qD is already declared in this scope", name); - oldval = NULL_TREE; - } - - *newval = oldval; - for (tmp = decls.value; tmp; tmp = OVL_NEXT (tmp)) - { - tree new_fn = OVL_CURRENT (tmp); - - /* Don't import functions that haven't been declared. */ - if (DECL_ANTICIPATED (new_fn)) - continue; + tree new_fn = *usings; /* [namespace.udecl] @@ -3125,138 +3158,67 @@ do_nonmember_using_decl (tree scope, tree name, tree oldval, tree oldtype, scope has the same name and the same parameter types as a function introduced by a using declaration the program is ill-formed. */ - for (tmp1 = oldval; tmp1; tmp1 = OVL_NEXT (tmp1)) + bool found = false; + for (ovl_iterator old (value); !found && old; ++old) { - tree old_fn = OVL_CURRENT (tmp1); + tree old_fn = *old; if (new_fn == old_fn) - /* The function already exists in the current namespace. */ - break; - else if (TREE_CODE (tmp1) == OVERLOAD && OVL_USING_P (tmp1)) - continue; /* this is a using decl */ - else if (compparms_for_decl_and_using_decl (new_fn, old_fn)) + /* The function already exists in the current + namespace. */ + found = true; + else if (old.using_p ()) + continue; /* This is a using decl. */ + else if (DECL_ANTICIPATED (old_fn) + && !DECL_HIDDEN_FRIEND_P (old_fn)) + continue; /* This is an anticipated builtin. */ + else if (!matching_fn_p (new_fn, old_fn)) + continue; /* Parameters do not match. */ + else if (decls_match (new_fn, old_fn)) + found = true; + else { - /* There was already a non-using declaration in - this scope with the same parameter types. If both - are the same extern "C" functions, that's ok. */ - if (DECL_ANTICIPATED (old_fn) - && !DECL_HIDDEN_FRIEND_P (old_fn)) - /* Ignore anticipated built-ins. */; - else if (decls_match (new_fn, old_fn)) - break; - else - { - diagnose_name_conflict (new_fn, old_fn); - break; - } + diagnose_name_conflict (new_fn, old_fn); + found = true; } } - /* If we broke out of the loop, there's no reason to add - this function to the using declarations for this - scope. */ - if (tmp1) - continue; - - /* If we are adding to an existing OVERLOAD, then we no - longer know the type of the set of functions. */ - if (*newval && TREE_CODE (*newval) == OVERLOAD) - TREE_TYPE (*newval) = unknown_type_node; - /* Add this new function to the set. */ - *newval = ovl_insert (OVL_CURRENT (tmp), *newval, true); + if (!found) + /* Unlike the overload case we don't drop anticipated + builtins here. They don't cause a problem, and + we'd like to match them with a future + declaration. */ + value = ovl_insert (new_fn, value, true); } } + else if (value + /* Ignore anticipated builtins. */ + && !(TREE_CODE (value) == FUNCTION_DECL + && DECL_ANTICIPATED (value) + && !DECL_HIDDEN_FRIEND_P (value)) + && !decls_match (lookup.value, value)) + diagnose_name_conflict (lookup.value, value); else - { - /* If we're declaring a non-function and OLDVAL is an anticipated - built-in, just pretend it isn't there. */ - if (oldval - && TREE_CODE (oldval) == FUNCTION_DECL - && DECL_ANTICIPATED (oldval) - && !DECL_HIDDEN_FRIEND_P (oldval)) - oldval = NULL_TREE; - - *newval = decls.value; - if (oldval && !decls_match (*newval, oldval)) - error ("%qD is already declared in this scope", name); - } + value = lookup.value; } - else - *newval = oldval; - if (decls.type && TREE_CODE (decls.type) == TREE_LIST) + if (lookup.type && lookup.type != type) { - error ("reference to %qD is ambiguous", name); - print_candidates (decls.type); - } - else - { - *newtype = decls.type; - if (oldtype && *newtype && !decls_match (oldtype, *newtype)) - error ("%qD is already declared in this scope", name); - } - - /* If *newval is empty, shift any class or enumeration name down. */ - if (!*newval) - { - *newval = *newtype; - *newtype = NULL_TREE; - } -} - -/* Process a using-declaration at function scope. */ - -void -do_local_using_decl (tree decl, tree scope, tree name) -{ - tree oldval, oldtype, newval, newtype; - tree orig_decl = decl; - - decl = validate_nonmember_using_decl (decl, scope, name); - if (decl == NULL_TREE) - return; - - if (building_stmt_list_p () - && at_function_scope_p ()) - add_decl_expr (decl); - - oldval = lookup_name_innermost_nonclass_level (name); - oldtype = lookup_type_current_level (name); - - do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype); - - if (newval) - { - if (is_overloaded_fn (newval)) - { - tree fn, term; - - /* We only need to push declarations for those functions - that were not already bound in the current level. - The old value might be NULL_TREE, it might be a single - function, or an OVERLOAD. */ - if (oldval && TREE_CODE (oldval) == OVERLOAD) - term = OVL_FUNCTION (oldval); - else - term = oldval; - for (fn = newval; fn && OVL_CURRENT (fn) != term; - fn = OVL_NEXT (fn)) - push_overloaded_decl (OVL_CURRENT (fn), - PUSH_LOCAL | PUSH_USING, - false); - } + if (type && !decls_match (lookup.type, type)) + diagnose_name_conflict (lookup.type, type); else - push_local_binding (name, newval, PUSH_USING); + type = lookup.type; } - if (newtype) + + /* If bind->value is empty, shift any class or enumeration name back. */ + if (!value) { - push_local_binding (name, newtype, PUSH_USING); - set_identifier_type_value (name, newtype); + value = type; + type = NULL_TREE; } - /* Emit debug info. */ - if (!processing_template_decl) - cp_emit_debug_info_for_using (orig_decl, current_scope()); + *value_p = value; + *type_p = type; } /* Returns true if ANCESTOR encloses DESCENDANT, including matching. @@ -4337,35 +4299,86 @@ pushdecl_namespace_level (tree x, bool is_friend) return t; } -/* Process a using-declaration not appearing in class or local scope. */ +/* Process a using-declaration appearing in namespace scope. */ void -do_toplevel_using_decl (tree decl, tree scope, tree name) +finish_namespace_using_decl (tree decl, tree scope, tree name) { - tree oldval, oldtype, newval, newtype; tree orig_decl = decl; - cxx_binding *binding; + gcc_checking_assert (current_binding_level->kind == sk_namespace); decl = validate_nonmember_using_decl (decl, scope, name); if (decl == NULL_TREE) return; - binding = binding_for_name (NAMESPACE_LEVEL (current_namespace), name); + cxx_binding *binding + = binding_for_name (NAMESPACE_LEVEL (current_namespace), name); + + tree value = binding->value; + tree type = binding->type; - oldval = binding->value; - oldtype = binding->type; + do_nonmember_using_decl (scope, name, &value, &type); - do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype); + /* Copy declarations found. */ + binding->value = value; + binding->type = type; /* Emit debug info. */ + gcc_assert (!processing_template_decl); if (!processing_template_decl) cp_emit_debug_info_for_using (orig_decl, current_namespace); +} - /* Copy declarations found. */ - if (newval) - binding->value = newval; - if (newtype) - binding->type = newtype; +/* Process a using-declaration at local scope. */ + +void +finish_local_using_decl (tree decl, tree scope, tree name) +{ + tree orig_decl = decl; + + gcc_checking_assert (current_binding_level->kind != sk_class + && current_binding_level->kind != sk_namespace); + decl = validate_nonmember_using_decl (decl, scope, name); + if (decl == NULL_TREE) + return; + + gcc_assert (building_stmt_list_p ()); + if (building_stmt_list_p () + && at_function_scope_p ()) + add_decl_expr (decl); + + cxx_binding *binding = find_local_binding (current_binding_level, name); + tree value = binding ? binding->value : NULL_TREE; + tree type = binding ? binding->type : NULL_TREE; + + do_nonmember_using_decl (scope, name, &value, &type); + + if (!value) + ; + else if (binding && value == binding->value) + ; + else if (binding && binding->value && TREE_CODE (value) == OVERLOAD) + { + update_local_overload (IDENTIFIER_BINDING (name), value); + IDENTIFIER_BINDING (name)->value = value; + } + else + /* Install the new binding. */ + push_local_binding (name, value, true); + + if (!type) + ; + else if (binding && type == binding->type) + ; + else + { + push_local_binding (name, type, true); + set_identifier_type_value (name, type); + } + + /* Emit debug info. */ + if (!processing_template_decl) + cp_emit_debug_info_for_using (orig_decl, current_scope ()); } /* Combines two sets of overloaded functions into an OVERLOAD chain, removing @@ -5651,38 +5664,6 @@ is_local_extern (tree decl) return false; } -/* Like lookup_name_innermost_nonclass_level, but for types. */ - -static tree -lookup_type_current_level (tree name) -{ - tree t = NULL_TREE; - - timevar_start (TV_NAME_LOOKUP); - gcc_assert (current_binding_level->kind != sk_namespace); - - if (REAL_IDENTIFIER_TYPE_VALUE (name) != NULL_TREE - && REAL_IDENTIFIER_TYPE_VALUE (name) != global_type_node) - { - cp_binding_level *b = current_binding_level; - while (1) - { - if (purpose_member (name, b->type_shadowed)) - { - t = REAL_IDENTIFIER_TYPE_VALUE (name); - break; - } - if (b->kind == sk_cleanup) - b = b->level_chain; - else - break; - } - } - - timevar_stop (TV_NAME_LOOKUP); - return t; -} - /* Add namespace to using_directives. Return NULL_TREE if nothing was changed (i.e. there was already a directive), or the fresh TREE_LIST otherwise. */ diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h index 84ab206..85a5b69 100644 --- a/gcc/cp/name-lookup.h +++ b/gcc/cp/name-lookup.h @@ -315,7 +315,6 @@ extern tree lookup_name_nonclass (tree); extern tree lookup_name_innermost_nonclass_level (tree); extern bool is_local_extern (tree); extern tree lookup_function_nonclass (tree, vec *, bool); -extern void push_local_binding (tree, tree, int); extern bool pushdecl_class_level (tree); extern tree pushdecl_namespace_level (tree, bool); extern bool push_class_level_binding (tree, tree); @@ -326,8 +325,6 @@ extern void set_decl_namespace (tree, tree, bool); extern void push_decl_namespace (tree); extern void pop_decl_namespace (void); extern void do_namespace_alias (tree, tree); -extern void do_toplevel_using_decl (tree, tree, tree); -extern void do_local_using_decl (tree, tree, tree); extern tree do_class_using_decl (tree, tree); extern void do_using_directive (tree); extern cp_expr lookup_arg_dependent (tree, tree, vec *); @@ -336,6 +333,8 @@ extern tree innermost_non_namespace_value (tree); extern cxx_binding *outer_binding (tree, cxx_binding *, bool); extern void cp_emit_debug_info_for_using (tree, tree); +extern void finish_namespace_using_decl (tree, tree, tree); +extern void finish_local_using_decl (tree, tree, tree); extern void finish_namespace_using_directive (tree, tree); extern void finish_local_using_directive (tree, tree); extern tree pushdecl_outermost_localscope (tree); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index cdde7a0..23d979c 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -18499,9 +18499,9 @@ cp_parser_using_declaration (cp_parser* parser, return false; } else if (!at_namespace_scope_p ()) - do_local_using_decl (decl, qscope, identifier); + finish_local_using_decl (decl, qscope, identifier); else - do_toplevel_using_decl (decl, qscope, identifier); + finish_namespace_using_decl (decl, qscope, identifier); } } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index f9980fe..10cac4a 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -15696,7 +15696,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, if (decl == error_mark_node || TREE_CODE (decl) == TREE_LIST) qualified_name_lookup_error (scope, name, decl, input_location); else - do_local_using_decl (decl, scope, name); + finish_local_using_decl (decl, scope, name); } else if (DECL_PACK_P (decl)) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5b6b82f..7b42abc 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2017-05-23 Nathan Sidwell + + * g++.dg/lookup/using13.C: Adjust expected error. + 2017-05-23 Senthil Kumar Selvaraj * gcc.dg/tree-ssa/builtin-snprintf-warn-3.c: Require ptr32plus. diff --git a/gcc/testsuite/g++.dg/lookup/using13.C b/gcc/testsuite/g++.dg/lookup/using13.C index c102fdc..26b703d 100644 --- a/gcc/testsuite/g++.dg/lookup/using13.C +++ b/gcc/testsuite/g++.dg/lookup/using13.C @@ -8,5 +8,5 @@ namespace A { int a; } namespace C{ int a; - using A::a; // { dg-error "already declared" } + using A::a; // { dg-error "conflicts with a previous" } } diff --git a/libcc1/ChangeLog b/libcc1/ChangeLog index 0a66c21..1969873 100644 --- a/libcc1/ChangeLog +++ b/libcc1/ChangeLog @@ -1,3 +1,8 @@ +2017-05-23 Nathan Sidwell + + * libcp1plugin.cc (plugin_add_using_decl): Call + finish_namespace_using_decl. Use assert not unreachable. + 2017-05-11 Nathan Sidwell * libcp1plugin.cc (safe_pushdecl_maybe_friend): Call pushdecl. diff --git a/libcc1/libcp1plugin.cc b/libcc1/libcp1plugin.cc index 7e30862..7db74c7 100644 --- a/libcc1/libcp1plugin.cc +++ b/libcc1/libcp1plugin.cc @@ -1030,13 +1030,12 @@ plugin_add_using_decl (cc1_plugin::connection *, finish_member_declaration (decl); } - else if (!at_namespace_scope_p ()) + else { - gcc_unreachable (); - do_local_using_decl (target, tcontext, identifier); + /* We can't be at local scope. */ + gcc_assert (at_namespace_scope_p ()); + finish_namespace_using_decl (target, tcontext, identifier); } - else - do_toplevel_using_decl (target, tcontext, identifier); return 1; } -- 2.7.4