summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2013-11-08 18:59:56 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2013-11-08 18:59:56 +0000
commitcd556eb26580e58c4b1220ba443890e9f8cda5ae (patch)
treec6c8df9fc00090d7eceda55997efe021c4ed84fa
parentf7a60a8e0148b16cd811472ac42b2b947be43ec6 (diff)
downloadbcm5719-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.td1
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td8
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp2
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp7
-rw-r--r--clang/test/CXX/class.access/class.friend/p3-cxx0x.cpp13
-rw-r--r--clang/test/CXX/temp/temp.decls/temp.friend/p5.cpp6
-rw-r--r--clang/test/SemaTemplate/friend-template.cpp17
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 {
OpenPOWER on IntegriCloud