diff options
| author | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-11-08 18:59:56 +0000 |
|---|---|---|
| committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-11-08 18:59:56 +0000 |
| commit | cd556eb26580e58c4b1220ba443890e9f8cda5ae (patch) | |
| tree | c6c8df9fc00090d7eceda55997efe021c4ed84fa | |
| parent | f7a60a8e0148b16cd811472ac42b2b947be43ec6 (diff) | |
| download | bcm5719-llvm-cd556eb26580e58c4b1220ba443890e9f8cda5ae.tar.gz bcm5719-llvm-cd556eb26580e58c4b1220ba443890e9f8cda5ae.zip | |
Issue a diagnostic if we see a templated friend declaration that we do not
support.
llvm-svn: 194273
| -rw-r--r-- | clang/include/clang/Basic/DiagnosticGroups.td | 1 | ||||
| -rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 8 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 7 | ||||
| -rw-r--r-- | clang/test/CXX/class.access/class.friend/p3-cxx0x.cpp | 13 | ||||
| -rw-r--r-- | clang/test/CXX/temp/temp.decls/temp.friend/p5.cpp | 6 | ||||
| -rw-r--r-- | clang/test/SemaTemplate/friend-template.cpp | 17 |
7 files changed, 40 insertions, 14 deletions
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 67097a5774e..be9ea674d0d 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -333,6 +333,7 @@ def UnknownAttributes : DiagGroup<"attributes">; def IgnoredAttributes : DiagGroup<"ignored-attributes">; def UnnamedTypeTemplateArgs : DiagGroup<"unnamed-type-template-args", [CXX98CompatUnnamedTypeTemplateArgs]>; +def UnsupportedFriend : DiagGroup<"unsupported-friend">; def UnusedArgument : DiagGroup<"unused-argument">; def UnusedSanitizeArgument : DiagGroup<"unused-sanitize-argument">; def UnusedCommandLineArgument : DiagGroup<"unused-command-line-argument", diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 5f26a0013d6..dba3ca16527 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -914,6 +914,14 @@ def err_friend_not_first_in_declaration : Error< "'friend' must appear first in a non-function declaration">; def err_using_decl_friend : Error< "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< "%select{data member |non-public member function |static member function |" diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 8b04f8dfcf5..660641eec6c 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -11410,6 +11410,8 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, // Handle the case of a templated-scope friend class. e.g. // template <class T> class A<T>::B; // 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); QualType T = Context.getDependentNameType(ETK, SS.getScopeRep(), Name); TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 795774657c7..6d40e00b21a 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -877,10 +877,11 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, // FIXME: Horrible, horrible hack! We can't currently represent this // in the AST, and historically we have just ignored such friend // class templates, so don't complain here. - if (TUK != TUK_Friend) - Diag(NameLoc, diag::err_template_qualified_declarator_no_match) + Diag(NameLoc, TUK == TUK_Friend + ? diag::warn_template_qualified_friend_ignored + : diag::err_template_qualified_declarator_no_match) << SS.getScopeRep() << SS.getRange(); - return true; + return TUK != TUK_Friend; } if (RequireCompleteDeclContext(SS, SemanticContext)) diff --git a/clang/test/CXX/class.access/class.friend/p3-cxx0x.cpp b/clang/test/CXX/class.access/class.friend/p3-cxx0x.cpp index ea9d2ce697c..5a1ab49321d 100644 --- a/clang/test/CXX/class.access/class.friend/p3-cxx0x.cpp +++ b/clang/test/CXX/class.access/class.friend/p3-cxx0x.cpp @@ -36,10 +36,17 @@ class A { public: class foo {}; 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 { // Ill-formed @@ -56,7 +63,7 @@ struct { friend float; - template<typename T> friend class A<T>::foo; + template<typename T> friend class A<T>::foo; // expected-warning {{not supported}} } a; void testA() { (void)sizeof(A<int>); } diff --git a/clang/test/CXX/temp/temp.decls/temp.friend/p5.cpp b/clang/test/CXX/temp/temp.decls/temp.friend/p5.cpp index 77f071d52e6..b26abb64f83 100644 --- a/clang/test/CXX/temp/temp.decls/temp.friend/p5.cpp +++ b/clang/test/CXX/temp/temp.decls/temp.friend/p5.cpp @@ -1,5 +1,4 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -// expected-no-diagnostics namespace test0 { template <class T> class A { @@ -7,7 +6,8 @@ namespace test0 { }; 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; @@ -68,7 +68,7 @@ namespace test3 { template <class U> class C { 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() { diff --git a/clang/test/SemaTemplate/friend-template.cpp b/clang/test/SemaTemplate/friend-template.cpp index 8a478777eb7..e9b2b9b8e64 100644 --- a/clang/test/SemaTemplate/friend-template.cpp +++ b/clang/test/SemaTemplate/friend-template.cpp @@ -232,16 +232,23 @@ namespace PR10660 { } namespace rdar11147355 { - template <class T> + template <class T> struct A { 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 { - }; - + public: + // FIXME: This should be permitted. + int f(A<S*> a) { return a.n; } // expected-error {{private}} + }; + A<double>::B<double> ab; + A<double*> a; + int k = ab.f(a); // expected-note {{instantiation of}} } namespace RedeclUnrelated { |

