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

Richard Smith richard-llvm at metafoo.co.uk
Fri Nov 8 10:59:56 PST 2013


Author: rsmith
Date: Fri Nov  8 12:59:56 2013
New Revision: 194273

URL: http://llvm.org/viewvc/llvm-project?rev=194273&view=rev
Log:
Issue a diagnostic if we see a templated friend declaration that we do not
support.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticGroups.td
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/test/CXX/class.access/class.friend/p3-cxx0x.cpp
    cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p5.cpp
    cfe/trunk/test/SemaTemplate/friend-template.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=194273&r1=194272&r2=194273&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Fri Nov  8 12:59:56 2013
@@ -333,6 +333,7 @@ def UnknownAttributes : DiagGroup<"attri
 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",

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=194273&r1=194272&r2=194273&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Nov  8 12:59:56 2013
@@ -914,6 +914,14 @@ def err_friend_not_first_in_declaration
   "'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 |"

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=194273&r1=194272&r2=194273&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Nov  8 12:59:56 2013
@@ -11410,6 +11410,8 @@ Decl *Sema::ActOnTemplatedFriendTag(Scop
   // 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);

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=194273&r1=194272&r2=194273&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Fri Nov  8 12:59:56 2013
@@ -877,10 +877,11 @@ Sema::CheckClassTemplate(Scope *S, unsig
       // 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))

Modified: cfe/trunk/test/CXX/class.access/class.friend/p3-cxx0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class.access/class.friend/p3-cxx0x.cpp?rev=194273&r1=194272&r2=194273&view=diff
==============================================================================
--- cfe/trunk/test/CXX/class.access/class.friend/p3-cxx0x.cpp (original)
+++ cfe/trunk/test/CXX/class.access/class.friend/p3-cxx0x.cpp Fri Nov  8 12:59:56 2013
@@ -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>); }

Modified: cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p5.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p5.cpp?rev=194273&r1=194272&r2=194273&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p5.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p5.cpp Fri Nov  8 12:59:56 2013
@@ -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() {

Modified: cfe/trunk/test/SemaTemplate/friend-template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/friend-template.cpp?rev=194273&r1=194272&r2=194273&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/friend-template.cpp (original)
+++ cfe/trunk/test/SemaTemplate/friend-template.cpp Fri Nov  8 12:59:56 2013
@@ -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 {





More information about the cfe-commits mailing list