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
This commit is contained in:
parent
6cdb26f2ad
commit
5ad4f1c811
9 changed files with 70 additions and 56 deletions
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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" }
|
||||
}
|
||||
|
|
29
gcc/testsuite/g++.dg/lookup/friend19.C
Normal file
29
gcc/testsuite/g++.dg/lookup/friend19.C
Normal file
|
@ -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());
|
||||
}
|
16
gcc/testsuite/g++.dg/lookup/friend20.C
Normal file
16
gcc/testsuite/g++.dg/lookup/friend20.C
Normal file
|
@ -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 ()
|
||||
{
|
||||
}
|
||||
};
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue