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
This commit is contained in:
parent
29ef83dee9
commit
87c465f52c
@ -1,3 +1,13 @@
|
||||
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
|
||||
|
@ -2542,8 +2542,10 @@ is_ancestor (tree root, tree child)
|
||||
}
|
||||
}
|
||||
|
||||
/* Enter the class or namespace scope indicated by T. Returns TRUE iff
|
||||
pop_scope should be called later to exit this scope. */
|
||||
/* Enter the class or namespace scope indicated by T suitable for
|
||||
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
|
||||
push_scope (tree t)
|
||||
@ -2578,6 +2580,110 @@ pop_scope (tree t)
|
||||
else if CLASS_TYPE_P (t)
|
||||
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. */
|
||||
|
||||
@ -4125,14 +4231,17 @@ lookup_name (tree name, int prefer_type)
|
||||
|
||||
/* Look up NAME for type used in elaborated name specifier in
|
||||
the scopes given by SCOPE. SCOPE can be either TS_CURRENT or
|
||||
TS_WITHIN_ENCLOSING_NON_CLASS (possibly more scope is checked if
|
||||
cleanup or template parameter scope is encountered).
|
||||
TS_WITHIN_ENCLOSING_NON_CLASS. Although not implied by the
|
||||
name, more scopes are checked if cleanup or template parameter
|
||||
scope is encountered.
|
||||
|
||||
Unlike lookup_name_real, we make sure that NAME is actually
|
||||
declared in the desired scope, not from inheritance, using
|
||||
declaration, nor using directive. A TYPE_DECL best matching
|
||||
the NAME is returned. Catching error and issuing diagnostics
|
||||
are caller's responsibility. */
|
||||
declared in the desired scope, not from inheritance, nor using
|
||||
directive. For using declaration, there is DR138 still waiting
|
||||
to be resolved.
|
||||
|
||||
A TYPE_DECL best matching the NAME is returned. Catching error
|
||||
and issuing diagnostics are caller's responsibility. */
|
||||
|
||||
tree
|
||||
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.
|
||||
Ignore names found via using declaration. See DR138 for
|
||||
current status. */
|
||||
if (qualify_lookup (iter->type, LOOKUP_PREFER_TYPES)
|
||||
&& (CP_DECL_CONTEXT (iter->type) == iter->scope->this_entity))
|
||||
if (qualify_lookup (iter->type, LOOKUP_PREFER_TYPES))
|
||||
val = iter->type;
|
||||
else if (qualify_lookup (iter->value, LOOKUP_PREFER_TYPES)
|
||||
&& (CP_DECL_CONTEXT (iter->value)
|
||||
== iter->scope->this_entity))
|
||||
else if (qualify_lookup (iter->value, LOOKUP_PREFER_TYPES))
|
||||
val = iter->value;
|
||||
}
|
||||
|
||||
|
@ -306,6 +306,8 @@ extern void keep_next_level (bool);
|
||||
extern bool is_ancestor (tree, tree);
|
||||
extern bool push_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_namespace (tree);
|
||||
|
@ -12240,7 +12240,7 @@ cp_parser_class_specifier (cp_parser* parser)
|
||||
int has_trailing_semicolon;
|
||||
bool nested_name_specifier_p;
|
||||
unsigned saved_num_template_parameter_lists;
|
||||
bool pop_p = false;
|
||||
tree old_scope = NULL_TREE;
|
||||
tree scope = NULL_TREE;
|
||||
|
||||
push_deferring_access_checks (dk_no_deferred);
|
||||
@ -12279,7 +12279,7 @@ cp_parser_class_specifier (cp_parser* parser)
|
||||
if (nested_name_specifier_p)
|
||||
{
|
||||
scope = CP_DECL_CONTEXT (TYPE_MAIN_DECL (type));
|
||||
pop_p = push_scope (scope);
|
||||
old_scope = push_inner_scope (scope);
|
||||
}
|
||||
type = begin_class_definition (type);
|
||||
|
||||
@ -12304,8 +12304,8 @@ cp_parser_class_specifier (cp_parser* parser)
|
||||
}
|
||||
if (type != error_mark_node)
|
||||
type = finish_struct (type, attributes);
|
||||
if (pop_p)
|
||||
pop_scope (scope);
|
||||
if (nested_name_specifier_p)
|
||||
pop_inner_scope (old_scope, scope);
|
||||
/* 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
|
||||
definitions. Note that the queued functions defined in a class
|
||||
|
@ -1,3 +1,10 @@
|
||||
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
|
||||
|
19
gcc/testsuite/g++.dg/lookup/friend3.C
Normal file
19
gcc/testsuite/g++.dg/lookup/friend3.C
Normal file
@ -0,0 +1,19 @@
|
||||
// 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;
|
||||
};
|
22
gcc/testsuite/g++.dg/lookup/friend4.C
Normal file
22
gcc/testsuite/g++.dg/lookup/friend4.C
Normal file
@ -0,0 +1,22 @@
|
||||
// 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;
|
||||
};
|
||||
}
|
34
gcc/testsuite/g++.dg/lookup/friend5.C
Normal file
34
gcc/testsuite/g++.dg/lookup/friend5.C
Normal file
@ -0,0 +1,34 @@
|
||||
// { 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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user