diff options
author | jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-01-22 19:50:37 +0000 |
---|---|---|
committer | jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-01-22 19:50:37 +0000 |
commit | 0bd414df9c57a5ae04871149d75557548728add5 (patch) | |
tree | d611d9e565111bcaa97ac42d5cbee302da3e523c /gcc/cp | |
parent | 624547f6e709bc2480f2bcd7a9eeb62b3161fe64 (diff) | |
download | gcc-0bd414df9c57a5ae04871149d75557548728add5.tar.gz |
PR c++/34912
* friend.c (do_friend): Check for prior declaration of a friend
function of a local class.
* name-lookup.c (lookup_name_innermost_nonclass_level):
No longer static.
* name-lookup.h: Declare it.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@131740 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/cp/friend.c | 24 | ||||
-rw-r--r-- | gcc/cp/name-lookup.c | 3 | ||||
-rw-r--r-- | gcc/cp/name-lookup.h | 1 |
4 files changed, 30 insertions, 7 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 235f7cb4b25..45297deda43 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2008-01-22 Jason Merrill <jason@redhat.com> + + PR c++/34912 + * friend.c (do_friend): Check for prior declaration of a friend + function of a local class. + * name-lookup.c (lookup_name_innermost_nonclass_level): + No longer static. + * name-lookup.h: Declare it. + 2008-01-22 Tom Tromey <tromey@redhat.com> PR c++/34829: diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c index 094501b109a..ffb0baaa600 100644 --- a/gcc/cp/friend.c +++ b/gcc/cp/friend.c @@ -526,11 +526,25 @@ 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, so pushdecl will be ok, and - insert an unqualified friend into the local scope - (rather than the containing namespace scope, which the - next choice will do). */ - decl = pushdecl_maybe_friend (decl, /*is_friend=*/true); + { + /* 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_maybe_friend (decl, /*is_friend=*/true); + 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 diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index c21940c0b51..ded1d2ec421 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -43,7 +43,6 @@ struct scope_binding { static cxx_scope *innermost_nonclass_level (void); static cxx_binding *binding_for_name (cxx_scope *, tree); -static tree lookup_name_innermost_nonclass_level (tree); static tree push_overloaded_decl (tree, int, bool); static bool lookup_using_namespace (tree, struct scope_binding *, tree, tree, int); @@ -4202,7 +4201,7 @@ lookup_type_scope (tree name, tag_scope scope) /* Similar to `lookup_name' but look only in the innermost non-class binding level. */ -static tree +tree lookup_name_innermost_nonclass_level (tree name) { struct cp_binding_level *b; diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h index 7da57be9f1f..a4c057e0be5 100644 --- a/gcc/cp/name-lookup.h +++ b/gcc/cp/name-lookup.h @@ -319,6 +319,7 @@ extern bool hidden_name_p (tree); extern tree remove_hidden_names (tree); extern tree lookup_qualified_name (tree, tree, bool, bool); extern tree lookup_name_nonclass (tree); +extern tree lookup_name_innermost_nonclass_level (tree); extern tree lookup_function_nonclass (tree, tree, bool); extern void push_local_binding (tree, tree, int); extern bool pushdecl_class_level (tree); |