forked from OSchip/llvm-project
Per C++11 [class.friend]p3, the 'friend' keyword must appear first in a
non-function friend declaration. Patch by Josh Magee! llvm-svn: 164273
This commit is contained in:
parent
b6d516e7bd
commit
a31a89a38e
|
@ -104,7 +104,8 @@ public:
|
|||
|
||||
/// 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())
|
||||
|
|
|
@ -807,6 +807,8 @@ def err_qualified_friend_def : Error<
|
|||
"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">;
|
||||
|
|
|
@ -4336,7 +4336,7 @@ public:
|
|||
SourceLocation RParenLoc,
|
||||
bool Failed);
|
||||
|
||||
FriendDecl *CheckFriendTypeDecl(SourceLocation Loc,
|
||||
FriendDecl *CheckFriendTypeDecl(SourceLocation LocStart,
|
||||
SourceLocation FriendLoc,
|
||||
TypeSourceInfo *TSInfo);
|
||||
Decl *ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS,
|
||||
|
|
|
@ -9850,7 +9850,7 @@ Decl *Sema::BuildStaticAssertDeclaration(SourceLocation StaticAssertLoc,
|
|||
/// \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 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation Loc,
|
|||
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 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation Loc,
|
|||
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
|
||||
|
|
|
@ -510,7 +510,7 @@ Decl *TemplateDeclInstantiator::VisitFriendDecl(FriendDecl *D) {
|
|||
if (!InstTy)
|
||||
return 0;
|
||||
|
||||
FriendDecl *FD = SemaRef.CheckFriendTypeDecl(D->getLocation(),
|
||||
FriendDecl *FD = SemaRef.CheckFriendTypeDecl(D->getLocStart(),
|
||||
D->getFriendLoc(), InstTy);
|
||||
if (!FD)
|
||||
return 0;
|
||||
|
|
|
@ -27,3 +27,29 @@ struct Y3 {
|
|||
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;
|
||||
|
|
Loading…
Reference in New Issue