Commit 87c465f5 by Kriang Lerdsuwanakij Committed by Kriang Lerdsuwanakij

Friend class name lookup 3/n, PR c++/3332

	Friend class name lookup 3/n, PR c++/3332
	* name-lookup.c (push_inner_scope, pop_inner_scope): New functions.
	(lookup_type_scope): Don't deal with name from user declaration
	specially.
	* name-lookup.h (push_inner_scope, pop_inner_scope): Add declarations.
	* parser.c (cp_parser_class_specifier): Use push_inner_scope and
	pop_inner_scope.

	* g++.dg/lookup/friend3.C: New test.
	* g++.dg/lookup/friend4.C: Likewise.
	* g++.dg/lookup/friend5.C: Likewise.

From-SVN: r91300
parent 29ef83de
2004-11-25 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net> 2004-11-25 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
Friend class name lookup 3/n, PR c++/3332
* name-lookup.c (push_inner_scope, pop_inner_scope): New functions.
(lookup_type_scope): Don't deal with name from user declaration
specially.
* name-lookup.h (push_inner_scope, pop_inner_scope): Add declarations.
* parser.c (cp_parser_class_specifier): Use push_inner_scope and
pop_inner_scope.
2004-11-25 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
Friend class name lookup 2/n, PR c++/14513, c++/15410 Friend class name lookup 2/n, PR c++/14513, c++/15410
* name-lookup.c (lookup_name_real): Simplify. * name-lookup.c (lookup_name_real): Simplify.
(lookup_type_scope): Add SCOPE parameter. Handle friend class (lookup_type_scope): Add SCOPE parameter. Handle friend class
......
...@@ -2542,8 +2542,10 @@ is_ancestor (tree root, tree child) ...@@ -2542,8 +2542,10 @@ is_ancestor (tree root, tree child)
} }
} }
/* Enter the class or namespace scope indicated by T. Returns TRUE iff /* Enter the class or namespace scope indicated by T suitable for
pop_scope should be called later to exit this scope. */ name lookup. T can be arbitrary scope, not necessary nested inside
the current scope. Returns TRUE iff pop_scope should be called
later to exit this scope. */
bool bool
push_scope (tree t) push_scope (tree t)
...@@ -2578,6 +2580,110 @@ pop_scope (tree t) ...@@ -2578,6 +2580,110 @@ pop_scope (tree t)
else if CLASS_TYPE_P (t) else if CLASS_TYPE_P (t)
pop_nested_class (); pop_nested_class ();
} }
/* Subroutine of push_inner_scope. */
static void
push_inner_scope_r (tree outer, tree inner)
{
tree prev;
if (outer == inner
|| (TREE_CODE (inner) != NAMESPACE_DECL && !CLASS_TYPE_P (inner)))
return;
prev = CP_DECL_CONTEXT (TREE_CODE (inner) == NAMESPACE_DECL ? inner : TYPE_NAME (inner));
if (outer != prev)
push_inner_scope_r (outer, prev);
if (TREE_CODE (inner) == NAMESPACE_DECL)
{
struct cp_binding_level *save_template_parm = 0;
/* Temporary take out template parameter scopes. They are saved
in reversed order in save_template_parm. */
while (current_binding_level->kind == sk_template_parms)
{
struct cp_binding_level *b = current_binding_level;
current_binding_level = b->level_chain;
b->level_chain = save_template_parm;
save_template_parm = b;
}
resume_scope (NAMESPACE_LEVEL (inner));
current_namespace = inner;
/* Restore template parameter scopes. */
while (save_template_parm)
{
struct cp_binding_level *b = save_template_parm;
save_template_parm = b->level_chain;
b->level_chain = current_binding_level;
current_binding_level = b;
}
}
else
pushclass (inner);
}
/* Enter the scope INNER from current scope. INNER must be a scope
nested inside current scope. This works with both name lookup and
pushing name into scope. In case a template parameter scope is present,
namespace is pushed under the template parameter scope according to
name lookup rule in 14.6.1/6.
Return the former current scope suitable for pop_inner_scope. */
tree
push_inner_scope (tree inner)
{
tree outer = current_scope ();
if (!outer)
outer = current_namespace;
push_inner_scope_r (outer, inner);
return outer;
}
/* Exit the current scope INNER back to scope OUTER. */
void
pop_inner_scope (tree outer, tree inner)
{
if (outer == inner
|| (TREE_CODE (inner) != NAMESPACE_DECL && !CLASS_TYPE_P (inner)))
return;
while (outer != inner)
{
if (TREE_CODE (inner) == NAMESPACE_DECL)
{
struct cp_binding_level *save_template_parm = 0;
/* Temporary take out template parameter scopes. They are saved
in reversed order in save_template_parm. */
while (current_binding_level->kind == sk_template_parms)
{
struct cp_binding_level *b = current_binding_level;
current_binding_level = b->level_chain;
b->level_chain = save_template_parm;
save_template_parm = b;
}
pop_namespace ();
/* Restore template parameter scopes. */
while (save_template_parm)
{
struct cp_binding_level *b = save_template_parm;
save_template_parm = b->level_chain;
b->level_chain = current_binding_level;
current_binding_level = b;
}
}
else
popclass ();
inner = CP_DECL_CONTEXT (TREE_CODE (inner) == NAMESPACE_DECL ? inner : TYPE_NAME (inner));
}
}
/* Do a pushlevel for class declarations. */ /* Do a pushlevel for class declarations. */
...@@ -4125,14 +4231,17 @@ lookup_name (tree name, int prefer_type) ...@@ -4125,14 +4231,17 @@ lookup_name (tree name, int prefer_type)
/* Look up NAME for type used in elaborated name specifier in /* Look up NAME for type used in elaborated name specifier in
the scopes given by SCOPE. SCOPE can be either TS_CURRENT or the scopes given by SCOPE. SCOPE can be either TS_CURRENT or
TS_WITHIN_ENCLOSING_NON_CLASS (possibly more scope is checked if TS_WITHIN_ENCLOSING_NON_CLASS. Although not implied by the
cleanup or template parameter scope is encountered). name, more scopes are checked if cleanup or template parameter
scope is encountered.
Unlike lookup_name_real, we make sure that NAME is actually Unlike lookup_name_real, we make sure that NAME is actually
declared in the desired scope, not from inheritance, using declared in the desired scope, not from inheritance, nor using
declaration, nor using directive. A TYPE_DECL best matching directive. For using declaration, there is DR138 still waiting
the NAME is returned. Catching error and issuing diagnostics to be resolved.
are caller's responsibility. */
A TYPE_DECL best matching the NAME is returned. Catching error
and issuing diagnostics are caller's responsibility. */
tree tree
lookup_type_scope (tree name, tag_scope scope) lookup_type_scope (tree name, tag_scope scope)
...@@ -4182,12 +4291,9 @@ lookup_type_scope (tree name, tag_scope scope) ...@@ -4182,12 +4291,9 @@ lookup_type_scope (tree name, tag_scope scope)
/* If this is the kind of thing we're looking for, we're done. /* If this is the kind of thing we're looking for, we're done.
Ignore names found via using declaration. See DR138 for Ignore names found via using declaration. See DR138 for
current status. */ current status. */
if (qualify_lookup (iter->type, LOOKUP_PREFER_TYPES) if (qualify_lookup (iter->type, LOOKUP_PREFER_TYPES))
&& (CP_DECL_CONTEXT (iter->type) == iter->scope->this_entity))
val = iter->type; val = iter->type;
else if (qualify_lookup (iter->value, LOOKUP_PREFER_TYPES) else if (qualify_lookup (iter->value, LOOKUP_PREFER_TYPES))
&& (CP_DECL_CONTEXT (iter->value)
== iter->scope->this_entity))
val = iter->value; val = iter->value;
} }
......
...@@ -306,6 +306,8 @@ extern void keep_next_level (bool); ...@@ -306,6 +306,8 @@ extern void keep_next_level (bool);
extern bool is_ancestor (tree, tree); extern bool is_ancestor (tree, tree);
extern bool push_scope (tree); extern bool push_scope (tree);
extern void pop_scope (tree); extern void pop_scope (tree);
extern tree push_inner_scope (tree);
extern void pop_inner_scope (tree, tree);
extern void push_binding_level (struct cp_binding_level *); extern void push_binding_level (struct cp_binding_level *);
extern void push_namespace (tree); extern void push_namespace (tree);
......
...@@ -12240,7 +12240,7 @@ cp_parser_class_specifier (cp_parser* parser) ...@@ -12240,7 +12240,7 @@ cp_parser_class_specifier (cp_parser* parser)
int has_trailing_semicolon; int has_trailing_semicolon;
bool nested_name_specifier_p; bool nested_name_specifier_p;
unsigned saved_num_template_parameter_lists; unsigned saved_num_template_parameter_lists;
bool pop_p = false; tree old_scope = NULL_TREE;
tree scope = NULL_TREE; tree scope = NULL_TREE;
push_deferring_access_checks (dk_no_deferred); push_deferring_access_checks (dk_no_deferred);
...@@ -12279,7 +12279,7 @@ cp_parser_class_specifier (cp_parser* parser) ...@@ -12279,7 +12279,7 @@ cp_parser_class_specifier (cp_parser* parser)
if (nested_name_specifier_p) if (nested_name_specifier_p)
{ {
scope = CP_DECL_CONTEXT (TYPE_MAIN_DECL (type)); scope = CP_DECL_CONTEXT (TYPE_MAIN_DECL (type));
pop_p = push_scope (scope); old_scope = push_inner_scope (scope);
} }
type = begin_class_definition (type); type = begin_class_definition (type);
...@@ -12304,8 +12304,8 @@ cp_parser_class_specifier (cp_parser* parser) ...@@ -12304,8 +12304,8 @@ cp_parser_class_specifier (cp_parser* parser)
} }
if (type != error_mark_node) if (type != error_mark_node)
type = finish_struct (type, attributes); type = finish_struct (type, attributes);
if (pop_p) if (nested_name_specifier_p)
pop_scope (scope); pop_inner_scope (old_scope, scope);
/* If this class is not itself within the scope of another class, /* If this class is not itself within the scope of another class,
then we need to parse the bodies of all of the queued function then we need to parse the bodies of all of the queued function
definitions. Note that the queued functions defined in a class definitions. Note that the queued functions defined in a class
......
2004-11-25 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net> 2004-11-25 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
Friend class name lookup 3/n, PR c++/3332
* g++.dg/lookup/friend3.C: New test.
* g++.dg/lookup/friend4.C: Likewise.
* g++.dg/lookup/friend5.C: Likewise.
2004-11-25 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
Friend class name lookup 2/n, PR c++/14513, c++/15410 Friend class name lookup 2/n, PR c++/14513, c++/15410
* g++.dg/lookup/friend2.C: New test. * g++.dg/lookup/friend2.C: New test.
* g++.dg/template/friend31.C: Likewise. * g++.dg/template/friend31.C: Likewise.
......
// Copyright (C) 2004 Free Software Foundation
// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
// { dg-do compile }
// Friend name lookup in class defined outside its namespace
namespace A {
class B;
class C;
}
class A::B {
friend class C;
typedef int i;
};
class A::C {
A::B::i j;
};
// Copyright (C) 2004 Free Software Foundation
// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
// { dg-do compile }
// Friend name lookup in class defined outside its namespace
// (Local class case)
void f() {
class A {
class B;
class C;
};
class A::B {
friend class C;
typedef int i;
};
class A::C {
A::B::i j;
};
}
// { dg-do compile }
// Origin: aroach@stoic.electriceyeball.com
// PR c++/3332: Friend function lookup in class defined outside its
// namespace
namespace N
{
class A;
}
class N::A
{
void x();
friend void func(void);
};
namespace N
{
void func(void);
}
void N::func(void)
{
N::A a;
a.x();
}
int main()
{
return 0;
}
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