From: Douglas Gregor Date: Tue, 23 Jun 2009 23:11:28 +0000 (+0000) Subject: Start propagating template parameter lists to the right places to X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e542c862bdf9a9bcb4f468be8fa6561372430611;p=clang Start propagating template parameter lists to the right places to handle function templates. There's no actual code for function templates yet, but at least we complain about typedef templates. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@74021 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 79a9efac85..d88451799b 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -651,6 +651,7 @@ def note_template_export_unsupported : Note< def err_template_outside_namespace_or_class_scope : Error< "templates can only be declared in namespace or class scope">; def err_template_linkage : Error<"templates must have C++ linkage">; +def err_template_typedef : Error<"a typedef cannot be a template">; def err_template_unnamed_class : Error< "cannot declare a class template with no name">; def err_template_param_list_different_arity : Error< diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index 8c85ba60ac..933a13803f 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -1453,6 +1453,18 @@ public: return DeclResult(); } + /// \brief Invoked when a declarator that has one or more template parameter + /// lists has been parsed. + /// + /// This action is similar to ActOnDeclarator(), except that the declaration + /// being created somehow involves a template, e.g., it is a template + /// declaration or specialization. + virtual DeclPtrTy ActOnTemplateDeclarator(Scope *S, + 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 7558793606..f6da612057 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -909,7 +909,8 @@ private: DeclGroupPtrTy ParseSimpleDeclaration(unsigned Context, SourceLocation &DeclEnd, bool RequireSemi = true); - DeclPtrTy ParseDeclarationAfterDeclarator(Declarator &D); + DeclPtrTy ParseDeclarationAfterDeclarator(Declarator &D, + const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo()); DeclGroupPtrTy ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D); DeclPtrTy ParseFunctionStatementBody(DeclPtrTy Decl); DeclPtrTy ParseFunctionTryBlock(DeclPtrTy Decl); diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 426f56f438..7153bad5ab 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -371,7 +371,8 @@ Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context, /// According to the standard grammar, =default and =delete are function /// definitions, but that definitely doesn't fit with the parser here. /// -Parser::DeclPtrTy Parser::ParseDeclarationAfterDeclarator(Declarator &D) { +Parser::DeclPtrTy Parser::ParseDeclarationAfterDeclarator(Declarator &D, + const ParsedTemplateInfo &TemplateInfo) { // If a simple-asm-expr is present, parse it. if (Tok.is(tok::kw_asm)) { SourceLocation Loc; @@ -393,7 +394,13 @@ Parser::DeclPtrTy Parser::ParseDeclarationAfterDeclarator(Declarator &D) { } // Inform the current actions module that we just parsed this declarator. - DeclPtrTy ThisDecl = Actions.ActOnDeclarator(CurScope, D); + DeclPtrTy ThisDecl = TemplateInfo.TemplateParams? + Actions.ActOnTemplateDeclarator(CurScope, + Action::MultiTemplateParamsArg(Actions, + TemplateInfo.TemplateParams->data(), + TemplateInfo.TemplateParams->size()), + D) + : Actions.ActOnDeclarator(CurScope, D); // Parse declarator '=' initializer. if (Tok.is(tok::equal)) { diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index eabe10f145..daf9500af8 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -170,7 +170,8 @@ Parser::ParseSingleDeclarationAfterTemplate( // If we have a declaration or declarator list, handle it. if (isDeclarationAfterDeclarator()) { // Parse this declaration. - DeclPtrTy ThisDecl = ParseDeclarationAfterDeclarator(DeclaratorInfo); + DeclPtrTy ThisDecl = ParseDeclarationAfterDeclarator(DeclaratorInfo, + TemplateInfo); if (Tok.is(tok::comma)) { Diag(Tok, diag::err_multiple_template_declarators) diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 3f96948c19..fe13b56eb0 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -421,9 +421,12 @@ public: virtual DeclSpec::TST isTagName(IdentifierInfo &II, Scope *S); virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D) { - return ActOnDeclarator(S, D, false); + return HandleDeclarator(S, D, MultiTemplateParamsArg(*this), false); } - DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D, bool IsFunctionDefinition); + + DeclPtrTy HandleDeclarator(Scope *S, Declarator &D, + MultiTemplateParamsArg TemplateParameterLists, + bool IsFunctionDefinition); void RegisterLocallyScopedExternCDecl(NamedDecl *ND, NamedDecl *PrevDecl, Scope *S); void DiagnoseFunctionSpecifiers(Declarator& D); @@ -437,6 +440,7 @@ public: bool &Redeclaration); NamedDecl* ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, QualType R, NamedDecl* PrevDecl, + MultiTemplateParamsArg TemplateParamLists, bool IsFunctionDefinition, bool &Redeclaration); void CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl, @@ -2068,6 +2072,10 @@ public: AttributeList *Attr, MultiTemplateParamsArg TemplateParameterLists); + virtual DeclPtrTy ActOnTemplateDeclarator(Scope *S, + 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 51a75b3146..10ab5c2d39 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1385,7 +1385,9 @@ static bool isNearlyMatchingFunction(ASTContext &Context, } Sema::DeclPtrTy -Sema::ActOnDeclarator(Scope *S, Declarator &D, bool IsFunctionDefinition) { +Sema::HandleDeclarator(Scope *S, Declarator &D, + MultiTemplateParamsArg TemplateParamLists, + bool IsFunctionDefinition) { DeclarationName Name = GetNameForDeclarator(D); // All of these full declarators require an identifier. If it doesn't have @@ -1500,9 +1502,15 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, bool IsFunctionDefinition) { bool Redeclaration = false; if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) { + if (TemplateParamLists.size()) { + Diag(D.getIdentifierLoc(), diag::err_template_typedef); + return DeclPtrTy(); + } + New = ActOnTypedefDeclarator(S, D, DC, R, PrevDecl, Redeclaration); } else if (R->isFunctionType()) { New = ActOnFunctionDeclarator(S, D, DC, R, PrevDecl, + move(TemplateParamLists), IsFunctionDefinition, Redeclaration); } else { New = ActOnVariableDeclarator(S, D, DC, R, PrevDecl, Redeclaration); @@ -1987,6 +1995,7 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl, NamedDecl* Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, QualType R, NamedDecl* PrevDecl, + MultiTemplateParamsArg TemplateParamLists, bool IsFunctionDefinition, bool &Redeclaration) { assert(R.getTypePtr()->isFunctionType()); @@ -2044,6 +2053,11 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, << R->getAsFunctionType()->getResultType(); D.setInvalidType(); } + + // Check that we can declare a template here. + if (TemplateParamLists.size() && + CheckTemplateDeclScope(S, TemplateParamLists)) + return 0; bool isVirtualOkay = false; FunctionDecl *NewFD; @@ -2987,7 +3001,9 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Scope *ParentScope = FnBodyScope->getParent(); - DeclPtrTy DP = ActOnDeclarator(ParentScope, D, /*IsFunctionDefinition=*/true); + DeclPtrTy DP = HandleDeclarator(ParentScope, D, + MultiTemplateParamsArg(*this), + /*IsFunctionDefinition=*/true); return ActOnStartOfFunctionDef(FnBodyScope, DP); } diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index e98ebb13f8..26e56733a1 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -2499,6 +2499,13 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, return DeclPtrTy::make(Specialization); } +Sema::DeclPtrTy +Sema::ActOnTemplateDeclarator(Scope *S, + MultiTemplateParamsArg TemplateParameterLists, + Declarator &D) { + return HandleDeclarator(S, D, move(TemplateParameterLists), false); +} + // Explicit instantiation of a class template specialization Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, diff --git a/test/SemaTemplate/template-decl-fail.cpp b/test/SemaTemplate/template-decl-fail.cpp new file mode 100644 index 0000000000..b136f6279d --- /dev/null +++ b/test/SemaTemplate/template-decl-fail.cpp @@ -0,0 +1,3 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template typedef T X; // expected-error{{typedef cannot be a template}}