Issue a diagnostic if we see a templated friend declaration that we do not

support.

llvm-svn: 194273
This commit is contained in:
Richard Smith 2013-11-08 18:59:56 +00:00
parent f7a60a8e01
commit cd556eb265
7 changed files with 40 additions and 14 deletions

View File

@ -333,6 +333,7 @@ def UnknownAttributes : DiagGroup<"attributes">;
def IgnoredAttributes : DiagGroup<"ignored-attributes">; def IgnoredAttributes : DiagGroup<"ignored-attributes">;
def UnnamedTypeTemplateArgs : DiagGroup<"unnamed-type-template-args", def UnnamedTypeTemplateArgs : DiagGroup<"unnamed-type-template-args",
[CXX98CompatUnnamedTypeTemplateArgs]>; [CXX98CompatUnnamedTypeTemplateArgs]>;
def UnsupportedFriend : DiagGroup<"unsupported-friend">;
def UnusedArgument : DiagGroup<"unused-argument">; def UnusedArgument : DiagGroup<"unused-argument">;
def UnusedSanitizeArgument : DiagGroup<"unused-sanitize-argument">; def UnusedSanitizeArgument : DiagGroup<"unused-sanitize-argument">;
def UnusedCommandLineArgument : DiagGroup<"unused-command-line-argument", def UnusedCommandLineArgument : DiagGroup<"unused-command-line-argument",

View File

@ -914,6 +914,14 @@ def err_friend_not_first_in_declaration : Error<
"'friend' must appear first in a non-function declaration">; "'friend' must appear first in a non-function declaration">;
def err_using_decl_friend : Error< def err_using_decl_friend : Error<
"cannot befriend target of using declaration">; "cannot befriend target of using declaration">;
def warn_template_qualified_friend_unsupported : Warning<
"dependent nested name specifier '%0' for friend class declaration is "
"not supported; turning off access control for %1">,
InGroup<UnsupportedFriend>;
def warn_template_qualified_friend_ignored : Warning<
"dependent nested name specifier '%0' for friend template declaration is "
"not supported; ignoring this friend declaration">,
InGroup<UnsupportedFriend>;
def err_invalid_member_in_interface : Error< def err_invalid_member_in_interface : Error<
"%select{data member |non-public member function |static member function |" "%select{data member |non-public member function |static member function |"

View File

@ -11410,6 +11410,8 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
// Handle the case of a templated-scope friend class. e.g. // Handle the case of a templated-scope friend class. e.g.
// template <class T> class A<T>::B; // template <class T> class A<T>::B;
// FIXME: we don't support these right now. // FIXME: we don't support these right now.
Diag(NameLoc, diag::warn_template_qualified_friend_unsupported)
<< SS.getScopeRep() << SS.getRange() << cast<CXXRecordDecl>(CurContext);
ElaboratedTypeKeyword ETK = TypeWithKeyword::getKeywordForTagTypeKind(Kind); ElaboratedTypeKeyword ETK = TypeWithKeyword::getKeywordForTagTypeKind(Kind);
QualType T = Context.getDependentNameType(ETK, SS.getScopeRep(), Name); QualType T = Context.getDependentNameType(ETK, SS.getScopeRep(), Name);
TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T); TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T);

View File

@ -877,10 +877,11 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
// FIXME: Horrible, horrible hack! We can't currently represent this // FIXME: Horrible, horrible hack! We can't currently represent this
// in the AST, and historically we have just ignored such friend // in the AST, and historically we have just ignored such friend
// class templates, so don't complain here. // class templates, so don't complain here.
if (TUK != TUK_Friend) Diag(NameLoc, TUK == TUK_Friend
Diag(NameLoc, diag::err_template_qualified_declarator_no_match) ? diag::warn_template_qualified_friend_ignored
: diag::err_template_qualified_declarator_no_match)
<< SS.getScopeRep() << SS.getRange(); << SS.getScopeRep() << SS.getRange();
return true; return TUK != TUK_Friend;
} }
if (RequireCompleteDeclContext(SS, SemanticContext)) if (RequireCompleteDeclContext(SS, SemanticContext))

View File

@ -36,10 +36,17 @@ class A {
public: public:
class foo {}; class foo {};
static int y; static int y;
template <typename S> friend class B<S>::ty; template <typename S> friend class B<S>::ty; // expected-warning {{dependent nested name specifier 'B<S>::' for friend class declaration is not supported}}
}; };
template <typename T> class B { typedef int ty; }; template<typename T> class B { typedef int ty; };
template<> class B<int> {
class ty {
static int f(A<int> &a) { return a.y; } // ok, befriended
};
};
int f(A<char> &a) { return a.y; } // FIXME: should be an error
struct { struct {
// Ill-formed // Ill-formed
@ -56,7 +63,7 @@ struct {
friend friend
float; float;
template<typename T> friend class A<T>::foo; template<typename T> friend class A<T>::foo; // expected-warning {{not supported}}
} a; } a;
void testA() { (void)sizeof(A<int>); } void testA() { (void)sizeof(A<int>); }

View File

@ -1,5 +1,4 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s // RUN: %clang_cc1 -fsyntax-only -verify %s
// expected-no-diagnostics
namespace test0 { namespace test0 {
template <class T> class A { template <class T> class A {
@ -7,7 +6,8 @@ namespace test0 {
}; };
class B { class B {
template <class T> friend class A<T>::Member; template <class T> friend class A<T>::Member; // expected-warning {{not supported}}
int n;
}; };
A<int> a; A<int> a;
@ -68,7 +68,7 @@ namespace test3 {
template <class U> class C { template <class U> class C {
int i; int i;
template <class T> friend struct A<T>::Inner; template <class T> friend struct A<T>::Inner; // expected-warning {{not supported}}
}; };
template <class T> int A<T>::Inner::foo() { template <class T> int A<T>::Inner::foo() {

View File

@ -232,16 +232,23 @@ namespace PR10660 {
} }
namespace rdar11147355 { namespace rdar11147355 {
template <class T> template <class T>
struct A { struct A {
template <class U> class B; template <class U> class B;
template <class S> template <class U> friend class A<S>::B; template <class S> template <class U> friend class A<S>::B; // expected-warning {{dependent nested name specifier 'A<S>::' for friend template declaration is not supported; ignoring this friend declaration}}
private:
int n; // expected-note {{here}}
}; };
template <class S> template <class U> class A<S>::B { template <class S> template <class U> class A<S>::B {
}; public:
// FIXME: This should be permitted.
int f(A<S*> a) { return a.n; } // expected-error {{private}}
};
A<double>::B<double> ab; A<double>::B<double> ab;
A<double*> a;
int k = ab.f(a); // expected-note {{instantiation of}}
} }
namespace RedeclUnrelated { namespace RedeclUnrelated {