From: Nathan Sidwell <nathan@acm.org>
To: GCC Patches <gcc-patches@gcc.gnu.org>
Subject: [C++ PATCH] Friend decls
Date: Thu, 25 May 2017 00:35:00 -0000 [thread overview]
Message-ID: <180e9612-ae0b-9e21-7624-4bb289ba5ae7@acm.org> (raw)
[-- Attachment #1: Type: text/plain, Size: 290 bytes --]
With pushdecl revamped, there's no need for do_friend to do some
checking with a local class friend. And therefore no need for the very
specialized lookup_name_innermost_nonclass_level.
push_local_binding will get some more cleanup soon.
Committed to trunk.
nathan
--
Nathan Sidwell
[-- Attachment #2: friend.diff --]
[-- Type: text/x-patch, Size: 6173 bytes --]
2017-05-24 Nathan Sidwell <nathan@acm.org>
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.
Index: cp/friend.c
===================================================================
--- cp/friend.c (revision 248432)
+++ cp/friend.c (working copy)
@@ -608,25 +608,8 @@ do_friend (tree ctype, tree declarator,
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
Index: cp/name-lookup.c
===================================================================
--- cp/name-lookup.c (revision 248432)
+++ cp/name-lookup.c (working copy)
@@ -2103,7 +2103,13 @@ push_local_binding (tree id, tree decl,
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
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. */
Index: cp/name-lookup.h
===================================================================
--- cp/name-lookup.h (revision 248432)
+++ cp/name-lookup.h (working copy)
@@ -310,7 +310,6 @@ extern tree get_namespace_binding (tree
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);
Index: testsuite/g++.dg/lookup/friend12.C
===================================================================
--- testsuite/g++.dg/lookup/friend12.C (revision 248422)
+++ testsuite/g++.dg/lookup/friend12.C (working copy)
@@ -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" }
}
Index: testsuite/g++.dg/lookup/friend19.C
===================================================================
--- testsuite/g++.dg/lookup/friend19.C (revision 0)
+++ testsuite/g++.dg/lookup/friend19.C (working copy)
@@ -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());
+}
Index: testsuite/g++.dg/lookup/friend20.C
===================================================================
--- testsuite/g++.dg/lookup/friend20.C (revision 0)
+++ testsuite/g++.dg/lookup/friend20.C (working copy)
@@ -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 ()
+ {
+ }
+};
Index: testsuite/g++.old-deja/g++.jason/scoping12.C
===================================================================
--- testsuite/g++.old-deja/g++.jason/scoping12.C (revision 248422)
+++ testsuite/g++.old-deja/g++.jason/scoping12.C (working copy)
@@ -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
}
reply other threads:[~2017-05-24 23:21 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=180e9612-ae0b-9e21-7624-4bb289ba5ae7@acm.org \
--to=nathan@acm.org \
--cc=gcc-patches@gcc.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).