Commit 5ad4f1c8 by Nathan Sidwell Committed by Nathan Sidwell

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
parent 6cdb26f2
2017-05-24 Nathan Sidwell <nathan@acm.org> 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. * Make-lang.in (CXX_AND_OBJCXX_OBJS): Alphabetize.
* cp-tree.h (cp_free_lang_data): Add extern. * cp-tree.h (cp_free_lang_data): Add extern.
......
...@@ -608,27 +608,10 @@ do_friend (tree ctype, tree declarator, tree decl, ...@@ -608,27 +608,10 @@ do_friend (tree ctype, tree declarator, tree decl,
is instantiated. */ is instantiated. */
decl = push_template_decl_real (decl, /*is_friend=*/true); decl = push_template_decl_real (decl, /*is_friend=*/true);
else if (current_function_decl) else if (current_function_decl)
{ /* pushdecl will check there's a local decl already. */
/* 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); decl = pushdecl (decl, /*is_friend=*/true);
else else
{ {
error ("friend declaration %qD in local class without "
"prior declaration", decl);
return error_mark_node;
}
}
else
{
/* We can't use pushdecl, as we might be in a template /* We can't use pushdecl, as we might be in a template
class specialization, and pushdecl will insert an class specialization, and pushdecl will insert an
unqualified friend decl into the template parameter unqualified friend decl into the template parameter
......
...@@ -2103,7 +2103,13 @@ push_local_binding (tree id, tree decl, bool is_using) ...@@ -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. */ push_local_binding with a friend decl of a local class. */
b = innermost_nonclass_level (); 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. */ /* Supplement the existing binding. */
if (!supplement_binding (IDENTIFIER_BINDING (id), decl)) if (!supplement_binding (IDENTIFIER_BINDING (id), decl))
...@@ -5430,37 +5436,6 @@ lookup_type_scope (tree name, tag_scope scope) ...@@ -5430,37 +5436,6 @@ lookup_type_scope (tree name, tag_scope scope)
return ret; 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 /* Returns true iff DECL is a block-scope extern declaration of a function
or variable. */ or variable. */
......
...@@ -310,7 +310,6 @@ extern tree get_namespace_binding (tree ns, tree id); ...@@ -310,7 +310,6 @@ extern tree get_namespace_binding (tree ns, tree id);
extern void set_global_binding (tree id, tree val); extern void set_global_binding (tree id, tree val);
extern tree lookup_qualified_name (tree, tree, int, bool, /*hidden*/bool = false); extern tree lookup_qualified_name (tree, tree, int, bool, /*hidden*/bool = false);
extern tree lookup_name_nonclass (tree); extern tree lookup_name_nonclass (tree);
extern tree lookup_name_innermost_nonclass_level (tree);
extern bool is_local_extern (tree); extern bool is_local_extern (tree);
extern tree lookup_function_nonclass (tree, vec<tree, va_gc> *, bool); extern tree lookup_function_nonclass (tree, vec<tree, va_gc> *, bool);
extern bool pushdecl_class_level (tree); extern bool pushdecl_class_level (tree);
......
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> 2017-05-24 Jonathan Wakely <jwakely@redhat.com>
PR c++/80544 PR c++/80544
......
...@@ -2,9 +2,9 @@ ...@@ -2,9 +2,9 @@
void foo() void foo()
{ {
extern void bar (int); // not the bar we are looking for
struct A 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" }
} }
// 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());
}
// 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 ()
{
}
};
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
void f () void f ()
{ {
struct A { struct A {
friend void g (); // { dg-error "without prior declaration" } friend void g (); // { dg-error "without prior local declaration" }
}; };
} }
void h () { void h () {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment