summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-06-23 23:11:28 +0000
committerDouglas Gregor <dgregor@apple.com>2009-06-23 23:11:28 +0000
commitb52fabb2a8c279da5084efd16930f3bef577a86b (patch)
treeeaab49c1ab8fdd4c2b84b7f3f0c9594a2ec3feb7 /clang
parent349db7bbcd183c743cc46fb385c1304a9211e793 (diff)
downloadbcm5719-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.td1
-rw-r--r--clang/include/clang/Parse/Action.h12
-rw-r--r--clang/include/clang/Parse/Parser.h3
-rw-r--r--clang/lib/Parse/ParseDecl.cpp11
-rw-r--r--clang/lib/Parse/ParseTemplate.cpp3
-rw-r--r--clang/lib/Sema/Sema.h12
-rw-r--r--clang/lib/Sema/SemaDecl.cpp20
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp7
-rw-r--r--clang/test/SemaTemplate/template-decl-fail.cpp3
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}}
OpenPOWER on IntegriCloud