Friend class name lookup 5/n PR c++/1016

Friend class name lookup 5/n
	PR c++/1016
	* cp-tree.h (pushtag): Adjust declaration.
	* decl.c (lookup_and_check_tag): Call lookup_type_scope if
	lookup_name fails.
	(xref_tag): Adjust call to pushtag.  Make hidden class visible.
	(start_enum): Adjust call to pushtag.
	* name-lookup.c (ambiguous_decl): Ignore hidden names.
	(qualify_lookup): Change return type to bool.
	(hidden_name_p): New function.
	(lookup_namespace_name, unqualified_namespace_lookup,
	lookup_name_real): Use it.
	(lookup_type_scope): Update comments.
	(maybe_process_template_type_declaration): Change parameter name
	from globalize to is_friend.
	(pushtag): Change globalize parameter of type int to tag_scope.
	Hide name if introduced by friend declaration.
	* name-lookup.h (hidden_name_p): Add declaration.
	* parser.c (cp_parser_lookup_name): Don't deal with hidden name
	here.
	* pt.c (push_template_decl_real): Make hidden class template
	visible.
	(lookup_template_class, instantiate_class_template): Adjust call
	to pushtag.
	* semantics.c (begin_class_definition): Likewise.
	* rtti.c (init_rtti_processing, build_dynamic_cast_1,
	tinfo_base_init, emit_support_tinfos): Use ts_current instead of
	ts_global.

	* g++.dg/lookup/hidden-class1.C: New test.
	* g++.dg/lookup/hidden-class2.C: Likewise.
	* g++.dg/lookup/hidden-class3.C: Likewise.
	* g++.dg/lookup/hidden-class4.C: Likewise.
	* g++.dg/lookup/hidden-class5.C: Likewise.
	* g++.dg/lookup/hidden-class6.C: Likewise.
	* g++.dg/lookup/hidden-class7.C: Likewise.
	* g++.dg/lookup/hidden-class8.C: Likewise.
	* g++.dg/lookup/hidden-class9.C: Likewise.
	* g++.dg/lookup/hidden-temp-class1.C: Likewise.
	* g++.dg/lookup/hidden-temp-class2.C: Likewise.
	* g++.dg/lookup/hidden-temp-class3.C: Likewise.
	* g++.dg/lookup/hidden-temp-class4.C: Likewise.
	* g++.dg/lookup/hidden-temp-class5.C: Likewise.
	* g++.dg/lookup/hidden-temp-class6.C: Likewise.
	* g++.dg/lookup/hidden-temp-class7.C: Likewise.
	* g++.dg/lookup/hidden-temp-class8.C: Likewise.
	* g++.dg/lookup/hidden-temp-class9.C: Likewise.
	* g++.dg/lookup/hidden-temp-class10.C: Likewise.
	* g++.dg/lookup/hidden-temp-class11.C: Likewise.

From-SVN: r96430
This commit is contained in:
Kriang Lerdsuwanakij 2005-03-14 14:33:54 +00:00 committed by Kriang Lerdsuwanakij
parent a21309013c
commit bd3d082ebe
30 changed files with 371 additions and 51 deletions

View File

@ -1,3 +1,34 @@
2005-03-14 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
Friend class name lookup 5/n
PR c++/1016
* cp-tree.h (pushtag): Adjust declaration.
* decl.c (lookup_and_check_tag): Call lookup_type_scope if
lookup_name fails.
(xref_tag): Adjust call to pushtag. Make hidden class visible.
(start_enum): Adjust call to pushtag.
* name-lookup.c (ambiguous_decl): Ignore hidden names.
(qualify_lookup): Change return type to bool.
(hidden_name_p): New function.
(lookup_namespace_name, unqualified_namespace_lookup,
lookup_name_real): Use it.
(lookup_type_scope): Update comments.
(maybe_process_template_type_declaration): Change parameter name
from globalize to is_friend.
(pushtag): Change globalize parameter of type int to tag_scope.
Hide name if introduced by friend declaration.
* name-lookup.h (hidden_name_p): Add declaration.
* parser.c (cp_parser_lookup_name): Don't deal with hidden name
here.
* pt.c (push_template_decl_real): Make hidden class template
visible.
(lookup_template_class, instantiate_class_template): Adjust call
to pushtag.
* semantics.c (begin_class_definition): Likewise.
* rtti.c (init_rtti_processing, build_dynamic_cast_1,
tinfo_base_init, emit_support_tinfos): Use ts_current instead of
ts_global.
2005-03-13 Mark Mitchell <mark@codesourcery.com>
PR c++/20157

View File

@ -3761,7 +3761,7 @@ extern void maybe_push_cleanup_level (tree);
extern void finish_scope (void);
extern void push_switch (tree);
extern void pop_switch (void);
extern tree pushtag (tree, tree, int);
extern tree pushtag (tree, tree, tag_scope);
extern tree make_anon_name (void);
extern int decls_match (tree, tree);
extern tree duplicate_decls (tree, tree);

View File

@ -9082,7 +9082,6 @@ check_elaborated_type_specifier (enum tag_types tag_code,
void f(class C); // No template header here
then the required template argument is missing. */
error ("template argument required for %<%s %T%>",
tag_name (tag_code),
DECL_NAME (CLASSTYPE_TI_TEMPLATE (type)));
@ -9104,7 +9103,19 @@ lookup_and_check_tag (enum tag_types tag_code, tree name,
tree t;
tree decl;
if (scope == ts_global)
decl = lookup_name (name, 2);
{
/* First try ordinary name lookup, ignoring hidden class name
injected via friend declaration. */
decl = lookup_name (name, 2);
/* If that fails, the name will be placed in the smallest
non-class, non-function-prototype scope according to 3.3.1/5.
We may already have a hidden name declared as friend in this
scope. So lookup again but not ignoring hidden name.
If we find one, that name will be made visible rather than
creating a new tag. */
if (!decl)
decl = lookup_type_scope (name, ts_within_enclosing_non_class);
}
else
decl = lookup_type_scope (name, scope);
@ -9264,8 +9275,7 @@ xref_tag (enum tag_types tag_code, tree name,
{
t = make_aggr_type (code);
TYPE_CONTEXT (t) = context;
/* pushtag only cares whether SCOPE is zero or not. */
t = pushtag (name, t, scope != ts_current);
t = pushtag (name, t, scope);
}
}
else
@ -9279,6 +9289,20 @@ xref_tag (enum tag_types tag_code, tree name,
error ("redeclaration of %qT as a non-template", t);
t = error_mark_node;
}
/* Make injected friend class visible. */
if (scope != ts_within_enclosing_non_class
&& hidden_name_p (TYPE_NAME (t)))
{
DECL_ANTICIPATED (TYPE_NAME (t)) = 0;
DECL_FRIEND_P (TYPE_NAME (t)) = 0;
if (TYPE_TEMPLATE_INFO (t))
{
DECL_ANTICIPATED (TYPE_TI_TEMPLATE (t)) = 0;
DECL_FRIEND_P (TYPE_TI_TEMPLATE (t)) = 0;
}
}
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
@ -9520,7 +9544,7 @@ start_enum (tree name)
name = make_anon_name ();
enumtype = make_node (ENUMERAL_TYPE);
enumtype = pushtag (name, enumtype, 0);
enumtype = pushtag (name, enumtype, /*tag_scope=*/ts_current);
}
return enumtype;

View File

@ -3296,12 +3296,13 @@ ambiguous_decl (tree name, struct scope_binding *old, cxx_binding *new,
case TEMPLATE_DECL:
/* If we expect types or namespaces, and not templates,
or this is not a template class. */
if (LOOKUP_QUALIFIERS_ONLY (flags)
&& !DECL_CLASS_TEMPLATE_P (val))
if ((LOOKUP_QUALIFIERS_ONLY (flags)
&& !DECL_CLASS_TEMPLATE_P (val))
|| hidden_name_p (val))
val = NULL_TREE;
break;
case TYPE_DECL:
if (LOOKUP_NAMESPACES_ONLY (flags))
if (LOOKUP_NAMESPACES_ONLY (flags) || hidden_name_p (val))
val = NULL_TREE;
break;
case NAMESPACE_DECL:
@ -3310,7 +3311,7 @@ ambiguous_decl (tree name, struct scope_binding *old, cxx_binding *new,
break;
case FUNCTION_DECL:
/* Ignore built-in functions that are still anticipated. */
if (LOOKUP_QUALIFIERS_ONLY (flags) || DECL_ANTICIPATED (val))
if (LOOKUP_QUALIFIERS_ONLY (flags) || hidden_name_p (val))
val = NULL_TREE;
break;
default:
@ -3382,21 +3383,35 @@ lookup_flags (int prefer_type, int namespaces_only)
}
/* Given a lookup that returned VAL, use FLAGS to decide if we want to
ignore it or not. Subroutine of lookup_name_real. */
ignore it or not. Subroutine of lookup_name_real and
lookup_type_scope. */
static tree
static bool
qualify_lookup (tree val, int flags)
{
if (val == NULL_TREE)
return val;
return false;
if ((flags & LOOKUP_PREFER_NAMESPACES) && TREE_CODE (val) == NAMESPACE_DECL)
return val;
return true;
if ((flags & LOOKUP_PREFER_TYPES)
&& (TREE_CODE (val) == TYPE_DECL || TREE_CODE (val) == TEMPLATE_DECL))
return val;
return true;
if (flags & (LOOKUP_PREFER_NAMESPACES | LOOKUP_PREFER_TYPES))
return NULL_TREE;
return val;
return false;
return true;
}
/* Given a lookup that returned VAL, decide if we want to ignore it or
not based on DECL_ANTICIPATED_P. */
bool
hidden_name_p (tree val)
{
if (DECL_P (val)
&& DECL_LANG_SPECIFIC (val)
&& DECL_ANTICIPATED (val))
return true;
return false;
}
/* Look up NAME in the NAMESPACE. */
@ -3467,10 +3482,9 @@ lookup_namespace_name (tree namespace, tree name)
if (TREE_CODE (val) == OVERLOAD && ! really_overloaded_fn (val))
val = OVL_FUNCTION (val);
/* Ignore built-in functions that haven't been prototyped yet. */
if (!val || !DECL_P(val)
|| !DECL_LANG_SPECIFIC(val)
|| !DECL_ANTICIPATED (val))
/* Ignore built-in functions and friends that haven't been declared
yet. */
if (!val || !hidden_name_p (val))
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
}
@ -3529,10 +3543,8 @@ unqualified_namespace_lookup (tree name, int flags)
if (b)
{
if (b->value && DECL_P (b->value)
&& DECL_LANG_SPECIFIC (b->value)
&& DECL_ANTICIPATED (b->value))
/* Ignore anticipated built-in functions. */
if (b->value && hidden_name_p (b->value))
/* Ignore anticipated built-in functions and friends. */
;
else
binding.value = b->value;
@ -3773,6 +3785,8 @@ innermost_non_namespace_value (tree name)
node of some kind representing its definition if there is only one
such declaration, or return a TREE_LIST with all the overloaded
definitions if there are many, or return 0 if it is undefined.
Hidden name, either friend declaration or built-in function, are
not ignored.
If PREFER_TYPE is > 0, we prefer TYPE_DECLs or namespaces.
If PREFER_TYPE is > 1, we reject non-type decls (e.g. namespaces).
@ -3837,10 +3851,12 @@ lookup_name_real (tree name, int prefer_type, int nonclass, bool block_p,
continue;
/* If this is the kind of thing we're looking for, we're done. */
if (qualify_lookup (iter->value, flags))
if (qualify_lookup (iter->value, flags)
&& !hidden_name_p (iter->value))
binding = iter->value;
else if ((flags & LOOKUP_PREFER_TYPES)
&& qualify_lookup (iter->type, flags))
&& qualify_lookup (iter->type, flags)
&& !hidden_name_p (iter->type))
binding = iter->type;
else
binding = NULL_TREE;
@ -3898,7 +3914,8 @@ lookup_name (tree name, int prefer_type)
Unlike lookup_name_real, we make sure that NAME is actually
declared in the desired scope, not from inheritance, nor using
directive. For using declaration, there is DR138 still waiting
to be resolved.
to be resolved. Hidden name coming from earlier an friend
declaration is also returned.
A TYPE_DECL best matching the NAME is returned. Catching error
and issuing diagnostics are caller's responsibility. */
@ -3948,9 +3965,7 @@ lookup_type_scope (tree name, tag_scope scope)
if (iter)
{
/* 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 this is the kind of thing we're looking for, we're done. */
if (qualify_lookup (iter->type, LOOKUP_PREFER_TYPES))
val = iter->type;
else if (qualify_lookup (iter->value, LOOKUP_PREFER_TYPES))
@ -4500,7 +4515,7 @@ push_using_directive (tree used)
processing. */
static tree
maybe_process_template_type_declaration (tree type, int globalize,
maybe_process_template_type_declaration (tree type, int is_friend,
cxx_scope *b)
{
tree decl = TYPE_NAME (type);
@ -4523,7 +4538,7 @@ maybe_process_template_type_declaration (tree type, int globalize,
push_template_decl_real, but we want the original value. */
tree name = DECL_NAME (decl);
decl = push_template_decl_real (decl, globalize);
decl = push_template_decl_real (decl, is_friend);
/* If the current binding level is the binding level for the
template parameters (see the comment in
begin_template_parm_list) and the enclosing level is a class
@ -4532,7 +4547,7 @@ maybe_process_template_type_declaration (tree type, int globalize,
friend case, push_template_decl will already have put the
friend into global scope, if appropriate. */
if (TREE_CODE (type) != ENUMERAL_TYPE
&& !globalize && b->kind == sk_template_parms
&& !is_friend && b->kind == sk_template_parms
&& b->level_chain->kind == sk_class)
{
finish_member_declaration (CLASSTYPE_TI_TEMPLATE (type));
@ -4563,7 +4578,7 @@ maybe_process_template_type_declaration (tree type, int globalize,
Returns TYPE upon success and ERROR_MARK_NODE otherwise. */
tree
pushtag (tree name, tree type, int globalize)
pushtag (tree name, tree type, tag_scope scope)
{
struct cp_binding_level *b;
@ -4580,7 +4595,7 @@ pushtag (tree name, tree type, int globalize)
template is instantiated. */
|| (b->kind == sk_template_parms && b->explicit_spec_p)
|| (b->kind == sk_class
&& (globalize
&& (scope != ts_current
/* We may be defining a new type in the initializer
of a static member variable. We allow this when
not pedantic, and it is particularly useful for
@ -4601,7 +4616,7 @@ pushtag (tree name, tree type, int globalize)
{
tree cs = current_scope ();
if (! globalize)
if (scope == ts_current)
context = cs;
else if (cs != NULL_TREE && TYPE_P (cs))
/* When declaring a friend class of a local class, we want
@ -4622,11 +4637,21 @@ pushtag (tree name, tree type, int globalize)
d = create_implicit_typedef (name, type);
DECL_CONTEXT (d) = FROB_CONTEXT (context);
if (scope == ts_within_enclosing_non_class)
{
/* This is a friend. Make this TYPE_DECL node hidden from
ordinary name lookup. Its corresponding TEMPLATE_DECL
will be marked in push_template_decl_real. */
retrofit_lang_decl (d);
DECL_ANTICIPATED (d) = 1;
DECL_FRIEND_P (d) = 1;
}
if (! in_class)
set_identifier_type_value_with_scope (name, d, b);
d = maybe_process_template_type_declaration (type,
globalize, b);
d = maybe_process_template_type_declaration
(type, scope == ts_within_enclosing_non_class, b);
if (d == error_mark_node)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);

View File

@ -315,6 +315,7 @@ extern tree lookup_name_real (tree, int, int, bool, int, int);
extern tree lookup_type_scope (tree, tag_scope);
extern tree namespace_binding (tree, tree);
extern void set_namespace_binding (tree, tree, tree);
extern bool hidden_name_p (tree);
extern tree lookup_namespace_name (tree, tree);
extern tree lookup_qualified_name (tree, tree, bool, bool);
extern tree lookup_name_nonclass (tree);

View File

@ -14382,10 +14382,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
}
/* If the lookup failed, let our caller know. */
if (!decl
|| decl == error_mark_node
|| (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_ANTICIPATED (decl)))
if (!decl || decl == error_mark_node)
return error_mark_node;
/* If it's a TREE_LIST, the result of the lookup was ambiguous. */

View File

@ -3132,6 +3132,13 @@ push_template_decl_real (tree decl, int is_friend)
tmpl = pushdecl_namespace_level (tmpl);
if (tmpl == error_mark_node)
return error_mark_node;
/* Hide template friend classes that haven't been declared yet. */
if (is_friend && TREE_CODE (decl) == TYPE_DECL)
{
DECL_ANTICIPATED (tmpl) = 1;
DECL_FRIEND_P (tmpl) = 1;
}
}
if (primary)
@ -4629,7 +4636,7 @@ lookup_template_class (tree d1,
/* A local class. Make sure the decl gets registered properly. */
if (context == current_function_decl)
pushtag (DECL_NAME (template), t, 0);
pushtag (DECL_NAME (template), t, /*tag_scope=*/ts_current);
}
/* If we called start_enum or pushtag above, this information
@ -5679,7 +5686,7 @@ instantiate_class_template (tree type)
tsubst_enum. */
if (name)
SET_IDENTIFIER_TYPE_VALUE (name, newtag);
pushtag (name, newtag, /*globalize=*/0);
pushtag (name, newtag, /*tag_scope=*/ts_current);
}
}
else if (TREE_CODE (t) == FUNCTION_DECL

View File

@ -113,7 +113,7 @@ init_rtti_processing (void)
push_namespace (std_identifier);
type_info_type = xref_tag (class_type, get_identifier ("type_info"),
/*tag_scope=*/ts_global, false);
/*tag_scope=*/ts_current, false);
pop_namespace ();
const_type_info_type_node
= build_qualified_type (type_info_type, TYPE_QUAL_CONST);
@ -624,7 +624,7 @@ build_dynamic_cast_1 (tree type, tree expr)
push_nested_namespace (ns);
tinfo_ptr = xref_tag (class_type,
get_identifier ("__class_type_info"),
/*tag_scope=*/ts_global, false);
/*tag_scope=*/ts_current, false);
tinfo_ptr = build_pointer_type
(build_qualified_type
@ -805,7 +805,7 @@ tinfo_base_init (tree desc, tree target)
push_nested_namespace (abi_node);
real_type = xref_tag (class_type, TINFO_REAL_NAME (desc),
/*tag_scope=*/ts_global, false);
/*tag_scope=*/ts_current, false);
pop_nested_namespace (abi_node);
if (!COMPLETE_TYPE_P (real_type))
@ -1337,7 +1337,7 @@ emit_support_tinfos (void)
push_nested_namespace (abi_node);
bltn_type = xref_tag (class_type,
get_identifier ("__fundamental_type_info"),
/*tag_scope=*/ts_global, false);
/*tag_scope=*/ts_current, false);
pop_nested_namespace (abi_node);
if (!COMPLETE_TYPE_P (bltn_type))
return;

View File

@ -2122,7 +2122,7 @@ begin_class_definition (tree t)
if (t == error_mark_node || ! IS_AGGR_TYPE (t))
{
t = make_aggr_type (RECORD_TYPE);
pushtag (make_anon_name (), t, 0);
pushtag (make_anon_name (), t, /*tag_scope=*/ts_current);
}
/* Update the location of the decl. */
@ -2131,7 +2131,7 @@ begin_class_definition (tree t)
if (TYPE_BEING_DEFINED (t))
{
t = make_aggr_type (TREE_CODE (t));
pushtag (TYPE_IDENTIFIER (t), t, 0);
pushtag (TYPE_IDENTIFIER (t), t, /*tag_scope=*/ts_current);
}
maybe_process_partial_specialization (t);
pushclass (t);

View File

@ -1,3 +1,28 @@
2005-03-14 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
Friend class name lookup 5/n
PR c++/1016
* g++.dg/lookup/hidden-class1.C: New test.
* g++.dg/lookup/hidden-class2.C: Likewise.
* g++.dg/lookup/hidden-class3.C: Likewise.
* g++.dg/lookup/hidden-class4.C: Likewise.
* g++.dg/lookup/hidden-class5.C: Likewise.
* g++.dg/lookup/hidden-class6.C: Likewise.
* g++.dg/lookup/hidden-class7.C: Likewise.
* g++.dg/lookup/hidden-class8.C: Likewise.
* g++.dg/lookup/hidden-class9.C: Likewise.
* g++.dg/lookup/hidden-temp-class1.C: Likewise.
* g++.dg/lookup/hidden-temp-class2.C: Likewise.
* g++.dg/lookup/hidden-temp-class3.C: Likewise.
* g++.dg/lookup/hidden-temp-class4.C: Likewise.
* g++.dg/lookup/hidden-temp-class5.C: Likewise.
* g++.dg/lookup/hidden-temp-class6.C: Likewise.
* g++.dg/lookup/hidden-temp-class7.C: Likewise.
* g++.dg/lookup/hidden-temp-class8.C: Likewise.
* g++.dg/lookup/hidden-temp-class9.C: Likewise.
* g++.dg/lookup/hidden-temp-class10.C: Likewise.
* g++.dg/lookup/hidden-temp-class11.C: Likewise.
2005-03-13 Mark Mitchell <mark@codesourcery.com>
PR c++/20157

View File

@ -0,0 +1,8 @@
// Copyright (C) 2005 Free Software Foundation
// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
// { dg-do compile }
class A {
friend class B;
B *b; // { dg-error "no type|expected" }
};

View File

@ -0,0 +1,9 @@
// Copyright (C) 2005 Free Software Foundation
// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
// { dg-do compile }
class A {
friend class B;
};
class B* b;

View File

@ -0,0 +1,10 @@
// Copyright (C) 2005 Free Software Foundation
// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
// { dg-do compile }
class A {
friend class B;
class B;
B *b;
};

View File

@ -0,0 +1,10 @@
// Copyright (C) 2005 Free Software Foundation
// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
// { dg-do compile }
class A {
friend class B;
};
class B *b;
B *c;

View File

@ -0,0 +1,9 @@
// Copyright (C) 2005 Free Software Foundation
// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
// { dg-do compile }
class A {
friend class B;
};
B* b; // { dg-error "expected" }

View File

@ -0,0 +1,14 @@
// { dg-do compile }
// Origin: Jay Cox <jaycox@gimp.org>
// PR c++/1016: Name lookup for injected friend class
class B;
namespace N {
class A {
friend class B;
B* b;
};
}

View File

@ -0,0 +1,13 @@
// Copyright (C) 2005 Free Software Foundation
// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
// { dg-do compile }
class A {
friend class B;
};
class C {
friend class B;
};
B *b; // { dg-error "expected" }

View File

@ -0,0 +1,12 @@
// Copyright (C) 2005 Free Software Foundation
// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
// { dg-do compile }
namespace N {
class A {
friend class B;
};
}
class N::B { // { dg-error "not name a class" }
};

View File

@ -0,0 +1,11 @@
// Copyright (C) 2005 Free Software Foundation
// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
// { dg-do compile }
namespace N {
class A {
friend class B;
};
}
using N::B; // { dg-error "declared" }

View File

@ -0,0 +1,8 @@
// Copyright (C) 2005 Free Software Foundation
// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
// { dg-do compile }
class A {
template <class T> friend class B;
B<int> *b; // { dg-error "no type|expected" }
};

View File

@ -0,0 +1,12 @@
// Copyright (C) 2005 Free Software Foundation
// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
// { dg-do compile }
namespace N {
class A {
template <class T> friend class B;
};
}
template <class T> class N::B { // { dg-error "not name a class" }
};

View File

@ -0,0 +1,11 @@
// Copyright (C) 2005 Free Software Foundation
// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
// { dg-do compile }
namespace N {
class A {
template <class T> friend class B;
};
}
using N::B; // { dg-error "declared" }

View File

@ -0,0 +1,9 @@
// Copyright (C) 2005 Free Software Foundation
// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
// { dg-do compile }
class A {
template <class T> friend class B;
};
class B* b; // { dg-error "argument required|invalid" }

View File

@ -0,0 +1,9 @@
// Copyright (C) 2005 Free Software Foundation
// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
// { dg-do compile }
class A {
template <class T> friend class B;
template <class T> class B;
B<int> *b;
};

View File

@ -0,0 +1,9 @@
// Copyright (C) 2005 Free Software Foundation
// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
// { dg-do compile }
class A {
template <class T> friend class B;
};
B<int> *b; // { dg-error "expected" }

View File

@ -0,0 +1,10 @@
// Copyright (C) 2005 Free Software Foundation
// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
// { dg-do compile }
class A {
template <class T> friend class B;
};
template <class T> class B;
B<int>* b;

View File

@ -0,0 +1,11 @@
// Copyright (C) 2005 Free Software Foundation
// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
// { dg-do compile }
class B;
namespace N {
class A {
template <class T> friend class B;
B* b;
};
}

View File

@ -0,0 +1,13 @@
// Copyright (C) 2005 Free Software Foundation
// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
// { dg-do compile }
class A {
template <class T> friend class B;
};
class C {
template <class T> friend class B;
};
B<int> *b; // { dg-error "expected" }

View File

@ -0,0 +1,11 @@
// Copyright (C) 2005 Free Software Foundation
// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
// { dg-do compile }
class A {
template <class T> friend class B;
};
class C {
friend class B; // { dg-error "argument required|friend" }
};

View File

@ -0,0 +1,11 @@
// Copyright (C) 2005 Free Software Foundation
// Contributed by Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
// { dg-do compile }
class A {
friend class B;
};
class C {
template <class T> friend class B; // { dg-error "not a template" }
};