diff options
author | John McCall <rjmccall@apple.com> | 2009-08-06 20:49:32 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2009-08-06 20:49:32 +0000 |
commit | 7f27d92006936b16a29ca0a5c442476b4f585b21 (patch) | |
tree | 864f0462ca869a66edbb72eb47a9790840d0d2af | |
parent | 1cf9ff87ee235ad252332a96699abdb32bd6facb (diff) |
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).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@78332 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 25 | ||||
-rw-r--r-- | test/CXX/class/class.friend/p1.cpp | 4 |
3 files changed, 22 insertions, 9 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index ee259123b2..17bf188bf3 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -299,6 +299,8 @@ def err_unexpected_friend : Error< "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">; diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 240fcd66d9..63b0b3d83d 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -3359,12 +3359,20 @@ Sema::DeclPtrTy Sema::ActOnFriendDecl(Scope *S, 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 @@ Sema::DeclPtrTy Sema::ActOnFriendDecl(Scope *S, // 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); } diff --git a/test/CXX/class/class.friend/p1.cpp b/test/CXX/class/class.friend/p1.cpp index a9265ede5a..80afe3e7a5 100644 --- a/test/CXX/class/class.friend/p1.cpp +++ b/test/CXX/class/class.friend/p1.cpp @@ -32,8 +32,8 @@ class A { 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 }} |