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
This commit is contained in:
Jason Merrill 2011-05-27 00:04:40 -04:00 committed by Jason Merrill
parent 5ac537d7b4
commit 866e414678
7 changed files with 90 additions and 9 deletions

View File

@ -1,5 +1,10 @@
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
* pt.c (convert_template_argument): Don't complain about using
injected-class-name as template template argument.

View File

@ -226,7 +226,14 @@ make_friend_class (tree type, tree friend_type, bool complain)
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;
}

View File

@ -17758,9 +17758,10 @@ cp_parser_member_declaration (cp_parser* parser)
{
/* If the `friend' keyword was present, the friend must
be introduced with a class-key. */
if (!declares_class_or_enum)
error_at (decl_spec_token_start->location,
"a class-key must be used when declaring a friend");
if (!declares_class_or_enum && cxx_dialect < cxx0x)
pedwarn (decl_spec_token_start->location, OPT_pedantic,
"in C++03 a class-key must be used "
"when declaring a friend");
/* In this case:
template <typename T> struct A {
@ -17769,10 +17770,12 @@ cp_parser_member_declaration (cp_parser* parser)
A<T>::B will be represented by a TYPENAME_TYPE, and
therefore not recognized by check_tag_decl. */
if (!type
&& decl_specifiers.type
&& TYPE_P (decl_specifiers.type))
type = decl_specifiers.type;
if (!type)
{
type = decl_specifiers.type;
if (type && TREE_CODE (type) == TYPE_DECL)
type = TREE_TYPE (type);
}
if (!type || !TYPE_P (type))
error_at (decl_spec_token_start->location,
"friend declaration does not name a class or "

View File

@ -8472,7 +8472,8 @@ instantiate_class_template_1 (tree type)
friend_type = TREE_TYPE (friend_type);
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

View File

@ -1,5 +1,8 @@
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/template/crash50.C: Adjust.
* g++.dg/template/static9.C: Adjust.

View File

@ -0,0 +1,22 @@
// 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

View File

@ -0,0 +1,40 @@
// 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;