diff options
author | Nathan Sidwell <nathan@acm.org> | 2017-05-24 23:18:58 +0000 |
---|---|---|
committer | Nathan Sidwell <nathan@gcc.gnu.org> | 2017-05-24 23:18:58 +0000 |
commit | 5ad4f1c81153459ce6fc8c285a39c69e060ac604 (patch) | |
tree | 972e96ed5a394997a17ad54013af94cbed7ce7e7 | |
parent | 6cdb26f2adc716bff0d7cc9c0682501da77c5be8 (diff) | |
download | gcc-5ad4f1c81153459ce6fc8c285a39c69e060ac604.zip gcc-5ad4f1c81153459ce6fc8c285a39c69e060ac604.tar.gz gcc-5ad4f1c81153459ce6fc8c285a39c69e060ac604.tar.bz2 |
friend.c (do_friend): Remove check for existing decl.
cp/
* friend.c (do_friend): Remove check for existing decl.
* name-lookup.h (lookup_name_innermost_nonclass_level): Delete.
* name-lookup.c (push_local_binding): Directly look for binding.
(lookup_name_innermost_nonclass_level_1): Delete.
(lookup_name_innermost_nonclass_level): Delete.
testsuite/
* g++.dg/lookup/friend12.C: Adjust diagnostics.
* g++.dg/lookup/friend19.C: New.
* g++.dg/lookup/friend20.C: New.
From-SVN: r248435
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/friend.c | 21 | ||||
-rw-r--r-- | gcc/cp/name-lookup.c | 39 | ||||
-rw-r--r-- | gcc/cp/name-lookup.h | 1 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/lookup/friend12.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/lookup/friend19.C | 29 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/lookup/friend20.C | 16 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.jason/scoping12.C | 4 |
9 files changed, 70 insertions, 56 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index f396832..29c95c3 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,11 @@ 2017-05-24 Nathan Sidwell <nathan@acm.org> + * friend.c (do_friend): Remove check for existing decl. + * name-lookup.h (lookup_name_innermost_nonclass_level): Delete. + * name-lookup.c (push_local_binding): Directly look for binding. + (lookup_name_innermost_nonclass_level_1): Delete. + (lookup_name_innermost_nonclass_level): Delete. + * Make-lang.in (CXX_AND_OBJCXX_OBJS): Alphabetize. * cp-tree.h (cp_free_lang_data): Add extern. diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c index 194ee16..a3c2ed0 100644 --- a/gcc/cp/friend.c +++ b/gcc/cp/friend.c @@ -608,25 +608,8 @@ do_friend (tree ctype, tree declarator, tree decl, is instantiated. */ decl = push_template_decl_real (decl, /*is_friend=*/true); else if (current_function_decl) - { - /* This must be a local class. 11.5p11: - - If a friend declaration appears in a local class (9.8) and - the name specified is an unqualified name, a prior - declaration is looked up without considering scopes that - are outside the innermost enclosing non-class scope. For a - friend function declaration, if there is no prior - declaration, the program is ill-formed. */ - tree t = lookup_name_innermost_nonclass_level (DECL_NAME (decl)); - if (t) - decl = pushdecl (decl, /*is_friend=*/true); - else - { - error ("friend declaration %qD in local class without " - "prior declaration", decl); - return error_mark_node; - } - } + /* pushdecl will check there's a local decl already. */ + decl = pushdecl (decl, /*is_friend=*/true); else { /* We can't use pushdecl, as we might be in a template diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 88fd7ed..c689702 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -2103,7 +2103,13 @@ push_local_binding (tree id, tree decl, bool is_using) push_local_binding with a friend decl of a local class. */ b = innermost_nonclass_level (); - if (lookup_name_innermost_nonclass_level (id)) + cxx_binding *binding = NULL; + if (b->kind == sk_namespace) + binding = find_namespace_binding (current_namespace, id); + else + binding = find_local_binding (b, id); + + if (binding) { /* Supplement the existing binding. */ if (!supplement_binding (IDENTIFIER_BINDING (id), decl)) @@ -5430,37 +5436,6 @@ lookup_type_scope (tree name, tag_scope scope) return ret; } - -/* Similar to `lookup_name' but look only in the innermost non-class - binding level. */ - -static tree -lookup_name_innermost_nonclass_level_1 (tree name) -{ - cp_binding_level *b = innermost_nonclass_level (); - cxx_binding *binding = NULL; - - if (b->kind == sk_namespace) - binding = find_namespace_binding (current_namespace, name); - else - binding = find_local_binding (b, name); - - return binding ? binding->value : NULL_TREE; -} - -/* Wrapper for lookup_name_innermost_nonclass_level_1. */ - -tree -lookup_name_innermost_nonclass_level (tree name) -{ - tree ret; - bool subtime = timevar_cond_start (TV_NAME_LOOKUP); - ret = lookup_name_innermost_nonclass_level_1 (name); - timevar_cond_stop (TV_NAME_LOOKUP, subtime); - return ret; -} - - /* Returns true iff DECL is a block-scope extern declaration of a function or variable. */ diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h index f0df1c9..637599c 100644 --- a/gcc/cp/name-lookup.h +++ b/gcc/cp/name-lookup.h @@ -310,7 +310,6 @@ extern tree get_namespace_binding (tree ns, tree id); extern void set_global_binding (tree id, tree val); extern tree lookup_qualified_name (tree, tree, int, bool, /*hidden*/bool = false); 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<tree, va_gc> *, bool); extern bool pushdecl_class_level (tree); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index cc8e09d..84026e3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2017-05-24 Nathan Sidwell <nathan@acm.org> + + * g++.dg/lookup/friend12.C: Adjust diagnostics. + * g++.dg/lookup/friend19.C: New. + * g++.dg/lookup/friend20.C: New. + 2017-05-24 Jonathan Wakely <jwakely@redhat.com> PR c++/80544 diff --git a/gcc/testsuite/g++.dg/lookup/friend12.C b/gcc/testsuite/g++.dg/lookup/friend12.C index 98f508b..eb61fb5 100644 --- a/gcc/testsuite/g++.dg/lookup/friend12.C +++ b/gcc/testsuite/g++.dg/lookup/friend12.C @@ -2,9 +2,9 @@ void foo() { + extern void bar (int); // not the bar we are looking for struct A { - friend void bar(); // { dg-error "without prior declaration" } + friend void bar(); // { dg-error "without prior local declaration" } }; - bar(); // { dg-error "3:'bar' was not declared" } } diff --git a/gcc/testsuite/g++.dg/lookup/friend19.C b/gcc/testsuite/g++.dg/lookup/friend19.C new file mode 100644 index 0000000..346204b --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/friend19.C @@ -0,0 +1,29 @@ +// Make sure unhiding friends doesn't unhide similarly named friends + +struct X +{ + friend int foo (X); +}; + +struct Y +{ + friend int foo (Y); +}; + +void Baz () +{ + foo (X()); + foo (Y()); +} + +int foo (Y); +int foo (int); +// foo(X) still hidden + +void Bar () +{ + foo (X()); + foo (Y()); + ::foo (X()); // { dg-error "" } + ::foo (Y()); +} diff --git a/gcc/testsuite/g++.dg/lookup/friend20.C b/gcc/testsuite/g++.dg/lookup/friend20.C new file mode 100644 index 0000000..ecdc763 --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/friend20.C @@ -0,0 +1,16 @@ +// PR c++/80830 + +template <int> class a; +class b +{ + friend int operator>> (int, b); +}; +template <int c> int &operator>> (int &, a<c> &); +template <int = 3> class a +{ + friend int &operator>><> (int &, a &); + a<> + d () + { + } +}; diff --git a/gcc/testsuite/g++.old-deja/g++.jason/scoping12.C b/gcc/testsuite/g++.old-deja/g++.jason/scoping12.C index 35731e7..38915a7 100644 --- a/gcc/testsuite/g++.old-deja/g++.jason/scoping12.C +++ b/gcc/testsuite/g++.old-deja/g++.jason/scoping12.C @@ -2,9 +2,9 @@ void f () { struct A { - friend void g (); // { dg-error "without prior declaration" } + friend void g (); // { dg-error "without prior local declaration" } }; } void h () { - g (); // { dg-error "3:'g' was not declared" } no g in scope + g (); // { dg-error "3:'g' was not declared" } no g in scope } |