From 17a7c1297ac8e1490d611d77d7e33863dfa3700a Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 24 Jun 2009 00:54:41 +0000 Subject: [PATCH] Make sure that the template parameter lists get from the parser down to ActOnFunctionDeclarator for function template definitions llvm-svn: 74040 --- clang/include/clang/Parse/Action.h | 8 ++++++++ clang/include/clang/Parse/Parser.h | 3 ++- clang/lib/Parse/ParseTemplate.cpp | 2 +- clang/lib/Parse/Parser.cpp | 11 +++++++++-- clang/lib/Sema/Sema.h | 4 ++++ clang/lib/Sema/SemaDecl.cpp | 2 ++ clang/lib/Sema/SemaTemplate.cpp | 21 +++++++++++++++++++++ clang/test/Parser/cxx-template-decl.cpp | 2 +- 8 files changed, 48 insertions(+), 5 deletions(-) diff --git a/clang/include/clang/Parse/Action.h b/clang/include/clang/Parse/Action.h index 933a13803f53..fa3160468e30 100644 --- a/clang/include/clang/Parse/Action.h +++ b/clang/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/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index f6da6120574e..890820123444 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/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/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp index daf9500af88d..ab359f4c5e06 100644 --- a/clang/lib/Parse/ParseTemplate.cpp +++ b/clang/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/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index a2a66f9255de..180484432230 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/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/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 23e12d80c989..699316efef67 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/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/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 7c4cb60fd585..c319f7f9698d 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/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/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 4ecb44c3c5f3..63696a13d3e0 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/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/clang/test/Parser/cxx-template-decl.cpp b/clang/test/Parser/cxx-template-decl.cpp index 75b26a98e44e..aaf3ee77a369 100644 --- a/clang/test/Parser/cxx-template-decl.cpp +++ b/clang/test/Parser/cxx-template-decl.cpp @@ -37,7 +37,7 @@ template