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
This commit is contained in:
Douglas Gregor 2009-06-23 23:11:28 +00:00
parent 349db7bbcd
commit b52fabb2a8
9 changed files with 64 additions and 8 deletions

View File

@ -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<

View File

@ -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.
///

View File

@ -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);

View File

@ -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)) {

View File

@ -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)

View File

@ -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,

View File

@ -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);
}

View File

@ -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,

View File

@ -0,0 +1,3 @@
// RUN: clang-cc -fsyntax-only -verify %s
template<typename T> typedef T X; // expected-error{{typedef cannot be a template}}