diff options
Diffstat (limited to 'gcc/cp/name-lookup.c')
-rw-r--r-- | gcc/cp/name-lookup.c | 51 |
1 files changed, 41 insertions, 10 deletions
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 2b1f9fbf318..025a03cd9fa 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -392,6 +392,17 @@ pop_binding (tree id, tree decl) } } +/* Remove the bindings for the decls of the current level and leave + the current scope. */ + +void +pop_bindings_and_leave_scope (void) +{ + for (tree t = getdecls (); t; t = DECL_CHAIN (t)) + pop_binding (DECL_NAME (t), t); + leave_scope (); +} + /* Strip non dependent using declarations. */ tree @@ -2256,6 +2267,27 @@ pushdecl_with_scope (tree x, cp_binding_level *level, bool is_friend) 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 @@ -2313,11 +2345,9 @@ push_overloaded_decl_1 (tree decl, int flags, bool is_friend) if (TREE_CODE (tmp) == OVERLOAD && OVL_USED (tmp) && !(flags & PUSH_USING) - && compparms (TYPE_ARG_TYPES (TREE_TYPE (fn)), - TYPE_ARG_TYPES (TREE_TYPE (decl))) + && compparms_for_decl_and_using_decl (fn, decl) && ! decls_match (fn, decl)) - error ("%q#D conflicts with previous using declaration %q#D", - decl, fn); + diagnose_name_conflict (decl, fn); dup = duplicate_decls (decl, fn, is_friend); /* If DECL was a redeclaration of FN -- even an invalid @@ -2549,10 +2579,9 @@ do_nonmember_using_decl (tree scope, tree name, tree oldval, tree oldtype, if (new_fn == old_fn) /* The function already exists in the current namespace. */ break; - else if (OVL_USED (tmp1)) + else if (TREE_CODE (tmp1) == OVERLOAD && OVL_USED (tmp1)) continue; /* this is a using decl */ - else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (new_fn)), - TYPE_ARG_TYPES (TREE_TYPE (old_fn)))) + else if (compparms_for_decl_and_using_decl (new_fn, old_fn)) { gcc_assert (!DECL_ANTICIPATED (old_fn) || DECL_HIDDEN_FRIEND_P (old_fn)); @@ -2564,7 +2593,7 @@ do_nonmember_using_decl (tree scope, tree name, tree oldval, tree oldtype, break; else { - error ("%qD is already declared in this scope", name); + diagnose_name_conflict (new_fn, old_fn); break; } } @@ -3063,8 +3092,10 @@ push_class_level_binding_1 (tree name, tree x) if (name == error_mark_node) return false; - /* Check for invalid member names. */ - gcc_assert (TYPE_BEING_DEFINED (current_class_type)); + /* Check for invalid member names. But don't worry about a default + argument-scope lambda being pushed after the class is complete. */ + gcc_assert (TYPE_BEING_DEFINED (current_class_type) + || LAMBDA_TYPE_P (TREE_TYPE (decl))); /* Check that we're pushing into the right binding level. */ gcc_assert (current_class_type == class_binding_level->this_entity); |