diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index 933a13803f..fa3160468e 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -1465,6 +1465,14 @@ public: return DeclPtrTy(); } + /// \brief Invoked when the parser is beginning to parse a function template + /// or function template specialization definition. + virtual DeclPtrTy ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope, + MultiTemplateParamsArg TemplateParameterLists, + Declarator &D) { + return DeclPtrTy(); + } + /// \brief Process the explicit instantiation of a class template /// specialization. /// diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index f6da612057..8908201234 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -636,7 +636,8 @@ private: DeclGroupPtrTy ParseDeclarationOrFunctionDefinition( AccessSpecifier AS = AS_none); - DeclPtrTy ParseFunctionDefinition(Declarator &D); + DeclPtrTy ParseFunctionDefinition(Declarator &D, + const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo()); void ParseKNRParamDeclarations(Declarator &D); // EndLoc, if non-NULL, is filled with the location of the last token of // the simple-asm. diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index daf9500af8..ab359f4c5e 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -201,7 +201,7 @@ Parser::ParseSingleDeclarationAfterTemplate( } return DeclPtrTy(); } - return ParseFunctionDefinition(DeclaratorInfo); + return ParseFunctionDefinition(DeclaratorInfo, TemplateInfo); } if (DeclaratorInfo.isFunctionDeclarator()) diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index a2a66f9255..1804844322 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -590,7 +590,8 @@ Parser::ParseDeclarationOrFunctionDefinition(AccessSpecifier AS) { /// [C++] function-definition: [C++ 8.4] /// decl-specifier-seq[opt] declarator function-try-block /// -Parser::DeclPtrTy Parser::ParseFunctionDefinition(Declarator &D) { +Parser::DeclPtrTy Parser::ParseFunctionDefinition(Declarator &D, + const ParsedTemplateInfo &TemplateInfo) { const DeclaratorChunk &FnTypeInfo = D.getTypeObject(0); assert(FnTypeInfo.Kind == DeclaratorChunk::Function && "This isn't a function declarator!"); @@ -632,7 +633,13 @@ Parser::DeclPtrTy Parser::ParseFunctionDefinition(Declarator &D) { // Tell the actions module that we have entered a function definition with the // specified Declarator for the function. - DeclPtrTy Res = Actions.ActOnStartOfFunctionDef(CurScope, D); + DeclPtrTy Res = TemplateInfo.TemplateParams? + Actions.ActOnStartOfFunctionTemplateDef(CurScope, + Action::MultiTemplateParamsArg(Actions, + TemplateInfo.TemplateParams->data(), + TemplateInfo.TemplateParams->size()), + D) + : Actions.ActOnStartOfFunctionDef(CurScope, D); if (Tok.is(tok::kw_try)) return ParseFunctionTryBlock(Res); diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 23e12d80c9..699316efef 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -2077,6 +2077,10 @@ public: MultiTemplateParamsArg TemplateParameterLists, Declarator &D); + virtual DeclPtrTy ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope, + MultiTemplateParamsArg TemplateParameterLists, + Declarator &D); + virtual DeclResult ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, unsigned TagSpec, diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 7c4cb60fd5..c319f7f969 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -3037,6 +3037,8 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, } Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) { + if (!D) + return D; FunctionDecl *FD = cast(D.getAs()); CurFunctionNeedsScopeChecking = false; diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 4ecb44c3c5..63696a13d3 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -2507,6 +2507,27 @@ Sema::ActOnTemplateDeclarator(Scope *S, return HandleDeclarator(S, D, move(TemplateParameterLists), false); } +Sema::DeclPtrTy +Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope, + MultiTemplateParamsArg TemplateParameterLists, + Declarator &D) { + assert(getCurFunctionDecl() == 0 && "Function parsing confused"); + assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function && + "Not a function declarator!"); + DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun; + + if (FTI.hasPrototype) { + // FIXME: Diagnose arguments without names in C. + } + + Scope *ParentScope = FnBodyScope->getParent(); + + DeclPtrTy DP = HandleDeclarator(ParentScope, D, + move(TemplateParameterLists), + /*IsFunctionDefinition=*/true); + return ActOnStartOfFunctionDef(FnBodyScope, DP); +} + // Explicit instantiation of a class template specialization Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, diff --git a/test/Parser/cxx-template-decl.cpp b/test/Parser/cxx-template-decl.cpp index 75b26a98e4..aaf3ee77a3 100644 --- a/test/Parser/cxx-template-decl.cpp +++ b/test/Parser/cxx-template-decl.cpp @@ -37,7 +37,7 @@ template