[cfe-commits] r78332 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaDeclCXX.cpp test/CXX/class/class.friend/p1.cpp

John McCall rjmccall at apple.com
Thu Aug 6 13:49:32 PDT 2009


Author: rjmccall
Date: Thu Aug  6 15:49:32 2009
New Revision: 78332

URL: http://llvm.org/viewvc/llvm-project?rev=78332&view=rev
Log:
Permit a class to friend its members in C++0x, without restriction.
Permit a class to friend its class members in C++ 98, as long as extensions
are enabled (and even when they aren't, only give an extwarn about it).


Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/CXX/class/class.friend/p1.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=78332&r1=78331&r2=78332&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Aug  6 15:49:32 2009
@@ -299,6 +299,8 @@
   "friends can only be classes or functions">;
 def err_friend_is_member : Error<
   "friends cannot be members of the declaring class">;
+def extwarn_friend_inner_class : ExtWarn<
+  "C++ 98 does not allow inner classes as friends">;
 def err_unelaborated_friend_type : Error<
   "must specify '%select{class|union}0' in a friend "
   "%select{class|union}0 declaration">;

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=78332&r1=78331&r2=78332&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Aug  6 15:49:32 2009
@@ -3359,12 +3359,20 @@
       Diag(DS.getFriendSpecLoc(), diag::err_friend_decl_defines_class)
         << RD->getSourceRange();
 
-    // C++ [class.friend]p1: A friend of a class is a function or
-    //   class that is not a member of the class . . .
-    // Definitions currently get treated in a way that causes this
-    // error, so only report it if we didn't see a definition.
-    else if (RD->getDeclContext() == CurContext)
-      Diag(DS.getFriendSpecLoc(), diag::err_friend_is_member);
+    // C++98 [class.friend]p1: A friend of a class is a function
+    //   or class that is not a member of the class . . .
+    // But that's a silly restriction which nobody implements for
+    // inner classes, and C++0x removes it anyway, so we only report
+    // this 
+    // But no-one implements it that way, and C++0x removes this
+    // restriction, so we only report it (as a warning) if we're being
+    // pedantic.  Ideally this would real -pedantic mode 
+    // 
+    // Also, definitions currently get treated in a way that causes
+    // this error, so only report it if we didn't see a definition.
+    else if (RD->getDeclContext() == CurContext &&
+             !(getLangOptions().CPlusPlus0x || getLangOptions().GNUMode))
+      Diag(DS.getFriendSpecLoc(), diag::extwarn_friend_inner_class);
 
     return DeclPtrTy::make(RD);
   }
@@ -3468,7 +3476,10 @@
 
     // C++ [class.friend]p1: A friend of a class is a function or
     //   class that is not a member of the class . . .
-    if (FD && DC == CurContext)
+    // C++0x changes this for both friend types and functions.
+    // Most C++ 98 compilers do seem to give an error here, so
+    // we do, too.
+    if (FD && DC == CurContext && !getLangOptions().CPlusPlus0x)
       Diag(DS.getFriendSpecLoc(), diag::err_friend_is_member);
   }
 

Modified: cfe/trunk/test/CXX/class/class.friend/p1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class/class.friend/p1.cpp?rev=78332&r1=78331&r2=78332&view=diff

==============================================================================
--- cfe/trunk/test/CXX/class/class.friend/p1.cpp (original)
+++ cfe/trunk/test/CXX/class/class.friend/p1.cpp Thu Aug  6 15:49:32 2009
@@ -32,8 +32,8 @@
   void a_member();
   friend void A::a_member(); // expected-error {{ friends cannot be members of the declaring class }}
   friend void a_member(); // okay (because we ignore class scopes when looking up friends)
-  friend class A::AInner; // expected-error {{ friends cannot be members of the declaring class }}
-  friend class AInner; // expected-error {{ friends cannot be members of the declaring class }}
+  friend class A::AInner; // this is okay as an extension
+  friend class AInner; // okay, refers to ::AInner
 
   friend void Derived::missing_member(); // expected-error {{ no function named 'missing_member' with type 'void ()' was found in the specified scope }}
 





More information about the cfe-commits mailing list