[cfe-commits] r164273 - in /cfe/trunk: include/clang/AST/DeclFriend.h include/clang/Basic/DiagnosticSemaKinds.td include/clang/Sema/Sema.h lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/CXX/class.access/class.friend/p3-cxx0x.cpp
Richard Smith
richard-llvm at metafoo.co.uk
Wed Sep 19 18:31:00 PDT 2012
Author: rsmith
Date: Wed Sep 19 20:31:00 2012
New Revision: 164273
URL: http://llvm.org/viewvc/llvm-project?rev=164273&view=rev
Log:
Per C++11 [class.friend]p3, the 'friend' keyword must appear first in a
non-function friend declaration. Patch by Josh Magee!
Modified:
cfe/trunk/include/clang/AST/DeclFriend.h
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/test/CXX/class.access/class.friend/p3-cxx0x.cpp
Modified: cfe/trunk/include/clang/AST/DeclFriend.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclFriend.h?rev=164273&r1=164272&r2=164273&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclFriend.h (original)
+++ cfe/trunk/include/clang/AST/DeclFriend.h Wed Sep 19 20:31:00 2012
@@ -104,7 +104,8 @@
/// Retrieves the source range for the friend declaration.
SourceRange getSourceRange() const LLVM_READONLY {
- /* FIXME: consider the case of templates wrt start of range. */
+ // FIXME: If this is a friend function declaration, the 'friend' keyword
+ // might not be the first token of the declaration.
if (NamedDecl *ND = getFriendDecl())
return SourceRange(getFriendLoc(), ND->getLocEnd());
else if (TypeSourceInfo *TInfo = getFriendType())
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=164273&r1=164272&r2=164273&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Sep 19 20:31:00 2012
@@ -807,6 +807,8 @@
"friend function definition cannot be qualified with '%0'">;
def err_friend_def_in_local_class : Error<
"friend function cannot be defined in a local class">;
+def err_friend_not_first_in_declaration : Error<
+ "'friend' must appear first in a non-function declaration">;
def err_abstract_type_in_decl : Error<
"%select{return|parameter|variable|field|ivar}0 type %1 is an abstract class">;
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=164273&r1=164272&r2=164273&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Sep 19 20:31:00 2012
@@ -4336,7 +4336,7 @@
SourceLocation RParenLoc,
bool Failed);
- FriendDecl *CheckFriendTypeDecl(SourceLocation Loc,
+ FriendDecl *CheckFriendTypeDecl(SourceLocation LocStart,
SourceLocation FriendLoc,
TypeSourceInfo *TSInfo);
Decl *ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=164273&r1=164272&r2=164273&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Sep 19 20:31:00 2012
@@ -9850,7 +9850,7 @@
/// \brief Perform semantic analysis of the given friend type declaration.
///
/// \returns A friend declaration that.
-FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation Loc,
+FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation LocStart,
SourceLocation FriendLoc,
TypeSourceInfo *TSInfo) {
assert(TSInfo && "NULL TypeSourceInfo for friend type declaration");
@@ -9889,7 +9889,7 @@
diag::warn_cxx98_compat_nonclass_type_friend :
diag::ext_nonclass_type_friend)
<< T
- << SourceRange(FriendLoc, TypeRange.getEnd());
+ << TypeRange;
}
} else if (T->getAs<EnumType>()) {
Diag(FriendLoc,
@@ -9897,18 +9897,22 @@
diag::warn_cxx98_compat_enum_friend :
diag::ext_enum_friend)
<< T
- << SourceRange(FriendLoc, TypeRange.getEnd());
+ << TypeRange;
}
- // C++0x [class.friend]p3:
+ // C++11 [class.friend]p3:
+ // A friend declaration that does not declare a function shall have one
+ // of the following forms:
+ // friend elaborated-type-specifier ;
+ // friend simple-type-specifier ;
+ // friend typename-specifier ;
+ if (getLangOpts().CPlusPlus0x && LocStart != FriendLoc)
+ Diag(FriendLoc, diag::err_friend_not_first_in_declaration) << T;
+
// If the type specifier in a friend declaration designates a (possibly
- // cv-qualified) class type, that class is declared as a friend; otherwise,
+ // cv-qualified) class type, that class is declared as a friend; otherwise,
// the friend declaration is ignored.
-
- // FIXME: C++0x has some syntactic restrictions on friend type declarations
- // in [class.friend]p3 that we do not implement.
-
- return FriendDecl::Create(Context, CurContext, Loc, TSInfo, FriendLoc);
+ return FriendDecl::Create(Context, CurContext, LocStart, TSInfo, FriendLoc);
}
/// Handle a friend tag declaration where the scope specifier was
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=164273&r1=164272&r2=164273&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Wed Sep 19 20:31:00 2012
@@ -510,7 +510,7 @@
if (!InstTy)
return 0;
- FriendDecl *FD = SemaRef.CheckFriendTypeDecl(D->getLocation(),
+ FriendDecl *FD = SemaRef.CheckFriendTypeDecl(D->getLocStart(),
D->getFriendLoc(), InstTy);
if (!FD)
return 0;
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=164273&r1=164272&r2=164273&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 Wed Sep 19 20:31:00 2012
@@ -27,3 +27,29 @@
X1<Y2> x1a;
X1<Y3> x1b;
X1<Y1> x1c; // expected-note{{in instantiation of template class 'X1<Y1>' requested here}}
+
+template<typename T>
+class A {
+ T x;
+public:
+ class foo {};
+ static int y;
+};
+
+struct {
+ // Ill-formed
+ int friend; // expected-error {{'friend' must appear first in a non-function declaration}}
+ unsigned friend int; // expected-error {{'friend' must appear first in a non-function declaration}}
+ const volatile friend int; // expected-error {{'friend' must appear first in a non-function declaration}}
+ int
+ friend; // expected-error {{'friend' must appear first in a non-function declaration}}
+
+ // OK
+ int friend foo(void);
+ friend int;
+ friend const volatile int;
+ friend
+
+ float;
+ template<typename T> friend class A<T>::foo;
+} a;
More information about the cfe-commits
mailing list