diff --git a/clang/include/clang/Parse/Action.h b/clang/include/clang/Parse/Action.h index 0cacfdbf142d..83fc0ae26305 100644 --- a/clang/include/clang/Parse/Action.h +++ b/clang/include/clang/Parse/Action.h @@ -1202,11 +1202,19 @@ public: return DeclPtrTy(); } - /// ActOnFriendDecl - This action is called when a friend declaration is - /// encountered. - virtual DeclPtrTy ActOnFriendDecl(Scope *S, - llvm::PointerUnion D, - bool IsDefinition) { + /// ActOnFriendFunctionDecl - Parsed a friend function declarator. + /// The name is actually a slight misnomer, because the declarator + /// is not necessarily a function declarator. + virtual DeclPtrTy ActOnFriendFunctionDecl(Scope *S, + Declarator &D, + bool IsDefinition, + MultiTemplateParamsArg TParams) { + return DeclPtrTy(); + } + + /// ActOnFriendTypeDecl - Parsed a friend type declaration. + virtual DeclPtrTy ActOnFriendTypeDecl(Scope *S, + const DeclSpec &DS) { return DeclPtrTy(); } diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp index 82b7da9f68e5..c34653ee425c 100644 --- a/clang/lib/Parse/ParseCXXInlineMethods.cpp +++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -34,7 +34,7 @@ Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D, DeclPtrTy FnD; if (D.getDeclSpec().isFriendSpecified()) // FIXME: Friend templates - FnD = Actions.ActOnFriendDecl(CurScope, &D, /*IsDefinition*/ true); + FnD = Actions.ActOnFriendFunctionDecl(CurScope, D, true, move(TemplateParams)); else // FIXME: pass template information through FnD = Actions.ActOnCXXMemberDeclarator(CurScope, AS, D, move(TemplateParams), 0, 0); diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index bb268e70c005..b9a0d6165e7e 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -1019,7 +1019,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate) return; - Actions.ActOnFriendDecl(CurScope, &DS, /*IsDefinition*/ false); + Actions.ActOnFriendTypeDecl(CurScope, DS); } else Actions.ParsedFreeStandingDeclSpec(CurScope, DS); @@ -1122,15 +1122,17 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // this call will *not* return the created decl; It will return null. // See Sema::ActOnCXXMemberDeclarator for details. + Action::MultiTemplateParamsArg TemplateParams(Actions, + TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->data() : 0, + TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->size() : 0); + DeclPtrTy ThisDecl; if (DS.isFriendSpecified()) { - // TODO: handle initializers, bitfields, 'delete', friend templates - ThisDecl = Actions.ActOnFriendDecl(CurScope, &DeclaratorInfo, - /*IsDefinition*/ false); + // TODO: handle initializers, bitfields, 'delete' + ThisDecl = Actions.ActOnFriendFunctionDecl(CurScope, DeclaratorInfo, + /*IsDefinition*/ false, + move(TemplateParams)); } else { - Action::MultiTemplateParamsArg TemplateParams(Actions, - TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->data() : 0, - TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->size() : 0); ThisDecl = Actions.ActOnCXXMemberDeclarator(CurScope, AS, DeclaratorInfo, move(TemplateParams), diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 873cc47d8913..d6bc6e51dddc 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -2245,12 +2245,9 @@ public: ExprArg AssertExpr, ExprArg AssertMessageExpr); - virtual DeclPtrTy ActOnFriendDecl(Scope *S, - llvm::PointerUnion D, - bool IsDefinition); - DeclPtrTy ActOnFriendTypeDecl(Scope *S, const DeclSpec& DS, - bool IsDefinition); - DeclPtrTy ActOnFriendFunctionDecl(Scope *S, Declarator& D, bool IsDefinition); + DeclPtrTy ActOnFriendTypeDecl(Scope *S, const DeclSpec &DS); + DeclPtrTy ActOnFriendFunctionDecl(Scope *S, Declarator &D, bool IsDefinition, + MultiTemplateParamsArg TemplateParams); QualType CheckConstructorDeclarator(Declarator &D, QualType R, FunctionDecl::StorageClass& SC); diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 97d7b2f76da9..79b017b33005 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -4008,18 +4008,8 @@ Sema::DeclPtrTy Sema::ActOnStaticAssertDeclaration(SourceLocation AssertLoc, return DeclPtrTy::make(Decl); } -Sema::DeclPtrTy Sema::ActOnFriendDecl(Scope *S, - llvm::PointerUnion DU, - bool IsDefinition) { - if (DU.is()) - return ActOnFriendFunctionDecl(S, *DU.get(), IsDefinition); - else - return ActOnFriendTypeDecl(S, *DU.get(), IsDefinition); -} - Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S, - const DeclSpec &DS, - bool IsDefinition) { + const DeclSpec &DS) { SourceLocation Loc = DS.getSourceRange().getBegin(); assert(DS.isFriendSpecified()); @@ -4056,17 +4046,13 @@ Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S, } } + bool IsDefinition = false; FriendDecl::FriendUnion FU = T.getTypePtr(); - // The parser doesn't quite handle - // friend class A { ... } - // optimally, because it might have been the (valid) prefix of - // friend class A { ... } foo(); - // So in a very particular set of circumstances, we need to adjust - // IsDefinition. - // - // Also, if we made a RecordDecl in ActOnTag, we want that to be the - // object of our friend declaration. + // We want to do a few things differently if the type was declared with + // a tag: specifically, we want to use the associated RecordDecl as + // the object of our friend declaration, and we want to disallow + // class definitions. switch (DS.getTypeSpecType()) { default: break; case DeclSpec::TST_class: @@ -4106,9 +4092,13 @@ Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S, return DeclPtrTy::make(FD); } -Sema::DeclPtrTy Sema::ActOnFriendFunctionDecl(Scope *S, - Declarator &D, - bool IsDefinition) { +Sema::DeclPtrTy +Sema::ActOnFriendFunctionDecl(Scope *S, + Declarator &D, + bool IsDefinition, + MultiTemplateParamsArg TemplateParams) { + // FIXME: do something with template parameters + const DeclSpec &DS = D.getDeclSpec(); assert(DS.isFriendSpecified());