diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-06-23 23:11:28 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-06-23 23:11:28 +0000 |
commit | b52fabb2a8c279da5084efd16930f3bef577a86b (patch) | |
tree | eaab49c1ab8fdd4c2b84b7f3f0c9594a2ec3feb7 /clang | |
parent | 349db7bbcd183c743cc46fb385c1304a9211e793 (diff) | |
download | bcm5719-llvm-b52fabb2a8c279da5084efd16930f3bef577a86b.tar.gz bcm5719-llvm-b52fabb2a8c279da5084efd16930f3bef577a86b.zip |
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.
llvm-svn: 74021
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 1 | ||||
-rw-r--r-- | clang/include/clang/Parse/Action.h | 12 | ||||
-rw-r--r-- | clang/include/clang/Parse/Parser.h | 3 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 11 | ||||
-rw-r--r-- | clang/lib/Parse/ParseTemplate.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Sema/Sema.h | 12 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 20 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 7 | ||||
-rw-r--r-- | clang/test/SemaTemplate/template-decl-fail.cpp | 3 |
9 files changed, 64 insertions, 8 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 79a9efac855..d88451799bf 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/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/clang/include/clang/Parse/Action.h b/clang/include/clang/Parse/Action.h index 8c85ba60ac2..933a13803f5 100644 --- a/clang/include/clang/Parse/Action.h +++ b/clang/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/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 75587936065..f6da6120574 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/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/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 426f56f4380..7153bad5abc 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/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/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp index eabe10f1450..daf9500af88 100644 --- a/clang/lib/Parse/ParseTemplate.cpp +++ b/clang/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/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 3f96948c19c..fe13b56eb0f 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/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/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 51a75b3146d..10ab5c2d397 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/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/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index e98ebb13f81..26e56733a13 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/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/clang/test/SemaTemplate/template-decl-fail.cpp b/clang/test/SemaTemplate/template-decl-fail.cpp new file mode 100644 index 00000000000..b136f6279d5 --- /dev/null +++ b/clang/test/SemaTemplate/template-decl-fail.cpp @@ -0,0 +1,3 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template<typename T> typedef T X; // expected-error{{typedef cannot be a template}} |