Commit 866e4146 by Jason Merrill Committed by Jason Merrill

re PR c++/47721 ([C++0x] Updated friendship rules?)

	PR c++/47721
	* parser.c (cp_parser_member_declaration): Allow friend T.
	* friend.c (make_friend_class): Ignore non-classes.
	* pt.c (instantiate_class_template_1): Handle TEMPLATE_TYPE_PARM.

From-SVN: r174319
parent 5ac537d7
2011-05-26 Jason Merrill <jason@redhat.com> 2011-05-26 Jason Merrill <jason@redhat.com>
PR c++/47721
* parser.c (cp_parser_member_declaration): Allow friend T.
* friend.c (make_friend_class): Ignore non-classes.
* pt.c (instantiate_class_template_1): Handle TEMPLATE_TYPE_PARM.
DR 1004 DR 1004
* pt.c (convert_template_argument): Don't complain about using * pt.c (convert_template_argument): Don't complain about using
injected-class-name as template template argument. injected-class-name as template template argument.
......
...@@ -226,7 +226,14 @@ make_friend_class (tree type, tree friend_type, bool complain) ...@@ -226,7 +226,14 @@ make_friend_class (tree type, tree friend_type, bool complain)
if (! MAYBE_CLASS_TYPE_P (friend_type)) if (! MAYBE_CLASS_TYPE_P (friend_type))
{ {
error ("invalid type %qT declared %<friend%>", friend_type); /* N1791: If the type specifier in a friend declaration designates a
(possibly cv-qualified) class type, that class is declared as a
friend; otherwise, the friend declaration is ignored.
So don't complain in C++0x mode. */
if (cxx_dialect < cxx0x)
pedwarn (input_location, complain ? 0 : OPT_pedantic,
"invalid type %qT declared %<friend%>", friend_type);
return; return;
} }
......
...@@ -17758,9 +17758,10 @@ cp_parser_member_declaration (cp_parser* parser) ...@@ -17758,9 +17758,10 @@ cp_parser_member_declaration (cp_parser* parser)
{ {
/* If the `friend' keyword was present, the friend must /* If the `friend' keyword was present, the friend must
be introduced with a class-key. */ be introduced with a class-key. */
if (!declares_class_or_enum) if (!declares_class_or_enum && cxx_dialect < cxx0x)
error_at (decl_spec_token_start->location, pedwarn (decl_spec_token_start->location, OPT_pedantic,
"a class-key must be used when declaring a friend"); "in C++03 a class-key must be used "
"when declaring a friend");
/* In this case: /* In this case:
template <typename T> struct A { template <typename T> struct A {
...@@ -17769,10 +17770,12 @@ cp_parser_member_declaration (cp_parser* parser) ...@@ -17769,10 +17770,12 @@ cp_parser_member_declaration (cp_parser* parser)
A<T>::B will be represented by a TYPENAME_TYPE, and A<T>::B will be represented by a TYPENAME_TYPE, and
therefore not recognized by check_tag_decl. */ therefore not recognized by check_tag_decl. */
if (!type if (!type)
&& decl_specifiers.type {
&& TYPE_P (decl_specifiers.type)) type = decl_specifiers.type;
type = decl_specifiers.type; if (type && TREE_CODE (type) == TYPE_DECL)
type = TREE_TYPE (type);
}
if (!type || !TYPE_P (type)) if (!type || !TYPE_P (type))
error_at (decl_spec_token_start->location, error_at (decl_spec_token_start->location,
"friend declaration does not name a class or " "friend declaration does not name a class or "
......
...@@ -8472,7 +8472,8 @@ instantiate_class_template_1 (tree type) ...@@ -8472,7 +8472,8 @@ instantiate_class_template_1 (tree type)
friend_type = TREE_TYPE (friend_type); friend_type = TREE_TYPE (friend_type);
adjust_processing_template_decl = true; adjust_processing_template_decl = true;
} }
else if (TREE_CODE (friend_type) == TYPENAME_TYPE) else if (TREE_CODE (friend_type) == TYPENAME_TYPE
|| TREE_CODE (friend_type) == TEMPLATE_TYPE_PARM)
{ {
/* This could be either /* This could be either
......
2011-05-26 Jason Merrill <jason@redhat.com> 2011-05-26 Jason Merrill <jason@redhat.com>
* g++.dg/cpp0x/friend1.C: New.
* g++.dg/cpp0x/friend2.C: New.
* g++.dg/cpp0x/auto7.C: Update. * g++.dg/cpp0x/auto7.C: Update.
* g++.dg/template/crash50.C: Adjust. * g++.dg/template/crash50.C: Adjust.
* g++.dg/template/static9.C: Adjust. * g++.dg/template/static9.C: Adjust.
......
// From N1791
// { dg-options -std=c++0x }
class C;
typedef C Ct;
class X1 {
friend C; // OK: class C is a friend
};
class X2
{
friend Ct; // OK: class C is a friend
friend D; // { dg-error "" } no type-name D in scope
friend class D; // OK: elaborated-type-specifier declares new class
};
template <typename T> class R {
friend T;
};
R<C> rc; // class C is a friend of R<C>
R<int> Ri; // OK: "friend int;" is ignored
// PR c++/47721
// { dg-options -std=c++0x }
// template type parameter friend:
template<class W>
class Q
{
static const int I = 2;
public:
friend W;
};
struct B
{
int ar[Q<B>::I];
};
// bonus template template parameter friend:
template <class T> struct A;
template<template <class> class W>
class P
{
static const int I = 2;
public:
// I'm not sure this is well-formed, but I can't find anything
// that says otherwise.
template <class T> friend class W;
};
template <class T>
struct A
{
int ar[P<A>::I];
};
A<int> a;
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