[cfe-commits] r61413 - in /cfe/trunk: Driver/PrintParserCallbacks.cpp include/clang/AST/DeclCXX.h include/clang/Basic/DiagnosticKinds.def include/clang/Parse/Action.h include/clang/Parse/Ownership.h include/clang/Parse/Parser.h lib/AST/DeclCXX.cpp lib/Parse/ParseDecl.cpp lib/Parse/ParseDeclCXX.cpp lib/Parse/ParseTemplate.cpp lib/Parse/Parser.cpp lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaTemplate.cpp test/Parser/cxx-template-decl.cpp
Douglas Gregor
dgregor at apple.com
Tue Dec 23 18:52:10 PST 2008
Author: dgregor
Date: Tue Dec 23 20:52:09 2008
New Revision: 61413
URL: http://llvm.org/viewvc/llvm-project?rev=61413&view=rev
Log:
Keep track of template arguments when we parse them. Right now, we don't actually do anything with the template arguments, but they'll be used to create template declarations
Modified:
cfe/trunk/Driver/PrintParserCallbacks.cpp
cfe/trunk/include/clang/AST/DeclCXX.h
cfe/trunk/include/clang/Basic/DiagnosticKinds.def
cfe/trunk/include/clang/Parse/Action.h
cfe/trunk/include/clang/Parse/Ownership.h
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/lib/AST/DeclCXX.cpp
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Parse/ParseDeclCXX.cpp
cfe/trunk/lib/Parse/ParseTemplate.cpp
cfe/trunk/lib/Parse/Parser.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/test/Parser/cxx-template-decl.cpp
Modified: cfe/trunk/Driver/PrintParserCallbacks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/PrintParserCallbacks.cpp?rev=61413&r1=61412&r2=61413&view=diff
==============================================================================
--- cfe/trunk/Driver/PrintParserCallbacks.cpp (original)
+++ cfe/trunk/Driver/PrintParserCallbacks.cpp Tue Dec 23 20:52:09 2008
@@ -189,7 +189,8 @@
virtual DeclTy *ActOnTag(Scope *S, unsigned TagType, TagKind TK,
SourceLocation KWLoc, const CXXScopeSpec &SS,
IdentifierInfo *Name, SourceLocation NameLoc,
- AttributeList *Attr) {
+ AttributeList *Attr,
+ MultiTemplateParamsArg TemplateParameterLists) {
// TagType is an instance of DeclSpec::TST, indicating what kind of tag this
// is (struct/union/enum/class).
llvm::cout << __FUNCTION__ << "\n";
Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=61413&r1=61412&r2=61413&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Tue Dec 23 20:52:09 2008
@@ -945,6 +945,34 @@
void ReadInRec(llvm::Deserializer& D, ASTContext& C);
};
+/// TemplateParameterList - Stores a list of template parameters.
+class TemplateParameterList {
+ /// NumParams - The number of template parameters in this template
+ /// parameter list.
+ unsigned NumParams;
+
+ TemplateParameterList(Decl **Params, unsigned NumParams);
+
+public:
+ static TemplateParameterList *Create(ASTContext &C, Decl **Params,
+ unsigned NumParams);
+
+ /// iterator - Iterates through the template parameters in this list.
+ typedef Decl** iterator;
+
+ /// const_iterator - Iterates through the template parameters in this list.
+ typedef Decl* const* const_iterator;
+
+ iterator begin() { return reinterpret_cast<Decl **>(this + 1); }
+ const_iterator begin() const {
+ return reinterpret_cast<Decl * const *>(this + 1);
+ }
+ iterator end() { return begin() + NumParams; }
+ const_iterator end() const { return begin() + NumParams; }
+
+ unsigned size() const { return NumParams; }
+};
+
} // end namespace clang
#endif
Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=61413&r1=61412&r2=61413&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Tue Dec 23 20:52:09 2008
@@ -976,6 +976,8 @@
"declaration of %0 shadows template parameter")
DIAG(note_template_param_here, NOTE,
"template parameter is declared here")
+DIAG(note_template_export_unsupported, NOTE,
+ "exported templates are unsupported")
DIAG(err_unexpected_typedef, ERROR,
"unexpected type name %0: expected expression")
Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=61413&r1=61412&r2=61413&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Tue Dec 23 20:52:09 2008
@@ -63,6 +63,7 @@
typedef void BaseTy;
typedef void MemInitTy;
typedef void CXXScopeTy;
+ typedef void TemplateParamsTy;
typedef void TemplateArgTy;
/// Expr/Stmt/Type/BaseResult - Provide a unique type to wrap
@@ -90,6 +91,7 @@
/// Multiple expressions or statements as arguments.
typedef ASTMultiPtr<&ActionBase::DeleteExpr> MultiExprArg;
typedef ASTMultiPtr<&ActionBase::DeleteStmt> MultiStmtArg;
+ typedef ASTMultiPtr<&ActionBase::DeleteTemplateParams> MultiTemplateParamsArg;
typedef ASTMultiPtr<&ActionBase::DeleteTemplateArg> MultiTemplateArgArg;
// Utilities for Action implementations to return smart results.
@@ -303,7 +305,8 @@
virtual DeclTy *ActOnTag(Scope *S, unsigned TagType, TagKind TK,
SourceLocation KWLoc, const CXXScopeSpec &SS,
IdentifierInfo *Name, SourceLocation NameLoc,
- AttributeList *Attr) {
+ AttributeList *Attr,
+ MultiTemplateParamsArg TemplateParameterLists) {
// TagType is an instance of DeclSpec::TST, indicating what kind of tag this
// is (struct/union/enum/class).
return 0;
@@ -944,11 +947,15 @@
/// parameter (NULL indicates an unnamed template parameter) and
/// ParamName is the location of the parameter name (if any).
/// If the type parameter has a default argument, it will be added
- /// later via ActOnTypeParameterDefault.
+ /// later via ActOnTypeParameterDefault. Depth and Position provide
+ /// the number of enclosing templates (see
+ /// ActOnTemplateParameterList) and the number of previous
+ /// parameters within this template parameter list.
virtual DeclTy *ActOnTypeParameter(Scope *S, bool Typename,
SourceLocation KeyLoc,
IdentifierInfo *ParamName,
- SourceLocation ParamNameLoc) {
+ SourceLocation ParamNameLoc,
+ unsigned Depth, unsigned Position) {
return 0;
}
@@ -960,12 +967,54 @@
/// ActOnNonTypeTemplateParameter - Called when a C++ non-type
/// template parameter (e.g., "int Size" in "template<int Size>
/// class Array") has been parsed. S is the current scope and D is
- /// the parsed declarator.
- virtual DeclTy *ActOnNonTypeTemplateParameter(Scope *S, Declarator &D) {
+ /// the parsed declarator. Depth and Position provide
+ /// the number of enclosing templates (see
+ /// ActOnTemplateParameterList) and the number of previous
+ /// parameters within this template parameter list.
+ virtual DeclTy *ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
+ unsigned Depth,
+ unsigned Position) {
return 0;
}
-
+ /// ActOnTemplateParameterList - Called when a complete template
+ /// parameter list has been parsed, e.g.,
+ ///
+ /// @code
+ /// export template<typename T, T Size>
+ /// @endcode
+ ///
+ /// Depth is the number of enclosing template parameter lists. This
+ /// value does not include templates from outer scopes. For example:
+ ///
+ /// @code
+ /// template<typename T> // depth = 0
+ /// class A {
+ /// template<typename U> // depth = 0
+ /// class B;
+ /// };
+ ///
+ /// template<typename T> // depth = 0
+ /// template<typename U> // depth = 1
+ /// class A<T>::B { ... };
+ /// @endcode
+ ///
+ /// ExportLoc, if valid, is the position of the "export"
+ /// keyword. Otherwise, "export" was not specified.
+ /// TemplateLoc is the position of the template keyword, LAngleLoc
+ /// is the position of the left angle bracket, and RAngleLoc is the
+ /// position of the corresponding right angle bracket.
+ /// Params/NumParams provides the template parameters that were
+ /// parsed as part of the template-parameter-list.
+ virtual TemplateParamsTy *
+ ActOnTemplateParameterList(unsigned Depth,
+ SourceLocation ExportLoc,
+ SourceLocation TemplateLoc,
+ SourceLocation LAngleLoc,
+ DeclTy **Params, unsigned NumParams,
+ SourceLocation RAngleLoc) {
+ return 0;
+ }
//===----------------------- Obj-C Declarations -------------------------===//
Modified: cfe/trunk/include/clang/Parse/Ownership.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Ownership.h?rev=61413&r1=61412&r2=61413&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Ownership.h (original)
+++ cfe/trunk/include/clang/Parse/Ownership.h Tue Dec 23 20:52:09 2008
@@ -118,6 +118,7 @@
// what types are required to be identical for the actions.
typedef void ExprTy;
typedef void StmtTy;
+ typedef void TemplateParamsTy;
typedef void TemplateArgTy;
/// ActionResult - This structure is used while parsing/acting on
@@ -146,6 +147,7 @@
/// pointers need access to them.
virtual void DeleteExpr(ExprTy *E) {}
virtual void DeleteStmt(StmtTy *E) {}
+ virtual void DeleteTemplateParams(TemplateParamsTy *E) {}
virtual void DeleteTemplateArg(TemplateArgTy *E) {}
};
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=61413&r1=61412&r2=61413&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Tue Dec 23 20:52:09 2008
@@ -78,8 +78,11 @@
typedef Action::BaseTy BaseTy;
typedef Action::MemInitTy MemInitTy;
typedef Action::CXXScopeTy CXXScopeTy;
+ typedef Action::TemplateParamsTy TemplateParamsTy;
typedef Action::TemplateArgTy TemplateArgTy;
+ typedef llvm::SmallVector<TemplateParamsTy *, 4> TemplateParameterLists;
+
typedef Action::ExprResult ExprResult;
typedef Action::StmtResult StmtResult;
typedef Action::BaseResult BaseResult;
@@ -500,7 +503,8 @@
//===--------------------------------------------------------------------===//
// C99 6.9: External Definitions.
DeclTy *ParseExternalDeclaration();
- DeclTy *ParseDeclarationOrFunctionDefinition();
+ DeclTy *ParseDeclarationOrFunctionDefinition(
+ TemplateParameterLists *TemplateParams = 0);
DeclTy *ParseFunctionDefinition(Declarator &D);
void ParseKNRParamDeclarations(Declarator &D);
OwningExprResult ParseSimpleAsm();
@@ -751,9 +755,11 @@
DeclTy *ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D);
DeclTy *ParseFunctionStatementBody(DeclTy *Decl,
SourceLocation L, SourceLocation R);
- void ParseDeclarationSpecifiers(DeclSpec &DS);
+ void ParseDeclarationSpecifiers(DeclSpec &DS,
+ TemplateParameterLists *TemplateParams = 0);
bool MaybeParseTypeSpecifier(DeclSpec &DS, int &isInvalid,
- const char *&PrevSpec);
+ const char *&PrevSpec,
+ TemplateParameterLists *TemplateParams = 0);
void ParseSpecifierQualifierList(DeclSpec &DS);
void ParseObjCTypeQualifierList(ObjCDeclSpec &DS);
@@ -928,7 +934,8 @@
//===--------------------------------------------------------------------===//
// C++ 9: classes [class] and C structs/unions.
TypeTy *ParseClassName(const CXXScopeSpec *SS = 0);
- void ParseClassSpecifier(DeclSpec &DS);
+ void ParseClassSpecifier(DeclSpec &DS,
+ TemplateParameterLists *TemplateParams = 0);
void ParseCXXMemberSpecification(SourceLocation StartLoc, unsigned TagType,
DeclTy *TagDecl);
DeclTy *ParseCXXClassMemberDeclaration(AccessSpecifier AS);
@@ -948,14 +955,20 @@
//===--------------------------------------------------------------------===//
// C++ 14: Templates [temp]
+ typedef llvm::SmallVector<DeclTy *, 4> TemplateParameterList;
+
// C++ 14.1: Template Parameters [temp.param]
DeclTy *ParseTemplateDeclaration(unsigned Context);
- bool ParseTemplateParameters(DeclTy* TempDecl);
- bool ParseTemplateParameterList(DeclTy *TmpDecl);
- DeclTy *ParseTemplateParameter();
- DeclTy *ParseTypeParameter();
- DeclTy *ParseTemplateTemplateParameter();
- DeclTy *ParseNonTypeTemplateParameter();
+ bool ParseTemplateParameters(unsigned Depth,
+ TemplateParameterList &TemplateParams,
+ SourceLocation &LAngleLoc,
+ SourceLocation &RAngleLoc);
+ bool ParseTemplateParameterList(unsigned Depth,
+ TemplateParameterList &TemplateParams);
+ DeclTy *ParseTemplateParameter(unsigned Depth, unsigned Position);
+ DeclTy *ParseTypeParameter(unsigned Depth, unsigned Position);
+ DeclTy *ParseTemplateTemplateParameter(unsigned Depth, unsigned Position);
+ DeclTy *ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position);
// C++ 14.3: Template arguments [temp.arg]
typedef llvm::SmallVector<TemplateArgTy*, 8> TemplateArgList;
void AnnotateTemplateIdToken(DeclTy *Template, const CXXScopeSpec *SS = 0);
Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=61413&r1=61412&r2=61413&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Tue Dec 23 20:52:09 2008
@@ -37,6 +37,21 @@
return new (Mem) NonTypeTemplateParmDecl(DC, L, Id, T, TypeSpecStartLoc);
}
+TemplateParameterList::TemplateParameterList(Decl **Params, unsigned NumParams)
+ : NumParams(NumParams) {
+ for (unsigned Idx = 0; Idx < NumParams; ++Idx)
+ begin()[Idx] = Params[Idx];
+}
+
+TemplateParameterList *
+TemplateParameterList::Create(ASTContext &C, Decl **Params,
+ unsigned NumParams) {
+ unsigned Size = sizeof(TemplateParameterList) + sizeof(Decl *) * NumParams;
+ unsigned Align = llvm::AlignOf<TemplateParameterList>::Alignment;
+ void *Mem = C.getAllocator().Allocate(Size, Align);
+ return new (Mem) TemplateParameterList(Params, NumParams);
+}
+
CXXRecordDecl::CXXRecordDecl(TagKind TK, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id)
: RecordDecl(CXXRecord, TK, DC, L, Id),
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=61413&r1=61412&r2=61413&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Tue Dec 23 20:52:09 2008
@@ -419,7 +419,8 @@
/// [C++] 'virtual'
/// [C++] 'explicit'
///
-void Parser::ParseDeclarationSpecifiers(DeclSpec &DS)
+void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
+ TemplateParameterLists *TemplateParams)
{
DS.SetRangeStart(Tok.getLocation());
while (1) {
@@ -436,7 +437,7 @@
default:
// Try to parse a type-specifier; if we found one, continue. If it's not
// a type, this falls through.
- if (MaybeParseTypeSpecifier(DS, isInvalid, PrevSpec)) {
+ if (MaybeParseTypeSpecifier(DS, isInvalid, PrevSpec, TemplateParams)) {
continue;
}
@@ -661,7 +662,8 @@
/// [OBJC] class-name objc-protocol-refs[opt] [TODO]
/// [OBJC] typedef-name objc-protocol-refs[opt] [TODO]
bool Parser::MaybeParseTypeSpecifier(DeclSpec &DS, int& isInvalid,
- const char *&PrevSpec) {
+ const char *&PrevSpec,
+ TemplateParameterLists *TemplateParams) {
// Annotate typenames and C++ scope specifiers.
TryAnnotateTypeOrScopeToken();
@@ -748,7 +750,7 @@
case tok::kw_class:
case tok::kw_struct:
case tok::kw_union:
- ParseClassSpecifier(DS);
+ ParseClassSpecifier(DS, TemplateParams);
return true;
// enum-specifier:
@@ -1036,7 +1038,8 @@
else
TK = Action::TK_Reference;
DeclTy *TagDecl = Actions.ActOnTag(CurScope, DeclSpec::TST_enum, TK, StartLoc,
- SS, Name, NameLoc, Attr);
+ SS, Name, NameLoc, Attr,
+ Action::MultiTemplateParamsArg(Actions));
if (Tok.is(tok::l_brace))
ParseEnumBody(StartLoc, TagDecl);
Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=61413&r1=61412&r2=61413&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Tue Dec 23 20:52:09 2008
@@ -202,7 +202,8 @@
/// struct-or-union:
/// 'struct'
/// 'union'
-void Parser::ParseClassSpecifier(DeclSpec &DS) {
+void Parser::ParseClassSpecifier(DeclSpec &DS,
+ TemplateParameterLists *TemplateParams) {
assert((Tok.is(tok::kw_class) ||
Tok.is(tok::kw_struct) ||
Tok.is(tok::kw_union)) &&
@@ -258,8 +259,13 @@
}
// Parse the tag portion of this.
- DeclTy *TagDecl = Actions.ActOnTag(CurScope, TagType, TK, StartLoc, SS, Name,
- NameLoc, Attr);
+ DeclTy *TagDecl
+ = Actions.ActOnTag(CurScope, TagType, TK, StartLoc, SS, Name,
+ NameLoc, Attr,
+ Action::MultiTemplateParamsArg(
+ Actions,
+ TemplateParams? &(*TemplateParams)[0] : 0,
+ TemplateParams? TemplateParams->size() : 0));
// Parse the optional base clause (C++ only).
if (getLang().CPlusPlus && Tok.is(tok::colon)) {
Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=61413&r1=61412&r2=61413&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTemplate.cpp Tue Dec 23 20:52:09 2008
@@ -27,59 +27,94 @@
assert((Tok.is(tok::kw_export) || Tok.is(tok::kw_template)) &&
"Token does not start a template declaration.");
- // Consume the optional export token, if it exists, followed by the
- // namespace token.
- bool isExported = false;
- if(Tok.is(tok::kw_export)) {
- SourceLocation ExportLoc = ConsumeToken();
- if(!Tok.is(tok::kw_template)) {
+ // Enter template-parameter scope.
+ ParseScope TemplateParmScope(this, Scope::TemplateParamScope);
+
+ // Parse multiple levels of template headers within this template
+ // parameter scope, e.g.,
+ //
+ // template<typename T>
+ // template<typename U>
+ // class A<T>::B { ... };
+ //
+ // We parse multiple levels non-recursively so that we can build a
+ // single data structure containing all of the template parameter
+ // lists, and easily differentiate between the case above and:
+ //
+ // template<typename T>
+ // class A {
+ // template<typename U> class B;
+ // };
+ //
+ // In the first case, the action for declaring A<T>::B receives
+ // both template parameter lists. In the second case, the action for
+ // defining A<T>::B receives just the inner template parameter list
+ // (and retrieves the outer template parameter list from its
+ // context).
+ TemplateParameterLists ParamLists;
+ do {
+ // Consume the 'export', if any.
+ SourceLocation ExportLoc;
+ if (Tok.is(tok::kw_export)) {
+ ExportLoc = ConsumeToken();
+ }
+
+ // Consume the 'template', which should be here.
+ SourceLocation TemplateLoc;
+ if (Tok.is(tok::kw_template)) {
+ TemplateLoc = ConsumeToken();
+ } else {
Diag(Tok.getLocation(), diag::err_expected_template);
return 0;
}
- isExported = true;
- }
- SourceLocation TemplateLoc = ConsumeToken();
- // Enter template-parameter scope.
- ParseScope TemplateParmScope(this, Scope::TemplateParamScope);
+ // Parse the '<' template-parameter-list '>'
+ SourceLocation LAngleLoc, RAngleLoc;
+ TemplateParameterList TemplateParams;
+ ParseTemplateParameters(ParamLists.size(), TemplateParams, LAngleLoc,
+ RAngleLoc);
+
+ ParamLists.push_back(
+ Actions.ActOnTemplateParameterList(ParamLists.size(), ExportLoc,
+ TemplateLoc, LAngleLoc,
+ &TemplateParams[0],
+ TemplateParams.size(), RAngleLoc));
+ } while (Tok.is(tok::kw_export) || Tok.is(tok::kw_template));
- // Try to parse the template parameters, and the declaration if
- // successful.
- DeclTy *TemplateDecl = 0;
- if (Tok.is(tok::less) && NextToken().is(tok::greater)) {
- // This is a template specialization. Just consume the angle
- // brackets and parse the declaration or function definition that
- // follows.
- // FIXME: Record somehow that we're in an explicit specialization.
- ConsumeToken();
- ConsumeToken();
- TemplateParmScope.Exit();
- TemplateDecl = ParseDeclarationOrFunctionDefinition();
- } else {
- if(ParseTemplateParameters(0))
- TemplateDecl = ParseDeclarationOrFunctionDefinition();
- }
+ // Parse the actual template declaration.
+ DeclTy *TemplateDecl = ParseDeclarationOrFunctionDefinition(&ParamLists);
return TemplateDecl;
}
/// ParseTemplateParameters - Parses a template-parameter-list enclosed in
-/// angle brackets.
-bool Parser::ParseTemplateParameters(DeclTy* TmpDecl) {
+/// angle brackets. Depth is the depth of this
+/// template-parameter-list, which is the number of template headers
+/// directly enclosing this template header. TemplateParams is the
+/// current list of template parameters we're building. The template
+/// parameter we parse will be added to this list. LAngleLoc and
+/// RAngleLoc will receive the positions of the '<' and '>',
+/// respectively, that enclose this template parameter list.
+bool Parser::ParseTemplateParameters(unsigned Depth,
+ TemplateParameterList &TemplateParams,
+ SourceLocation &LAngleLoc,
+ SourceLocation &RAngleLoc) {
// Get the template parameter list.
if(!Tok.is(tok::less)) {
Diag(Tok.getLocation(), diag::err_expected_less_after) << "template";
return false;
}
- ConsumeToken();
+ LAngleLoc = ConsumeToken();
// Try to parse the template parameter list.
- if(ParseTemplateParameterList(0)) {
+ if (Tok.is(tok::greater))
+ RAngleLoc = ConsumeToken();
+ else if(ParseTemplateParameterList(Depth, TemplateParams)) {
if(!Tok.is(tok::greater)) {
Diag(Tok.getLocation(), diag::err_expected_greater);
return false;
}
- ConsumeToken();
+ RAngleLoc = ConsumeToken();
}
return true;
}
@@ -92,13 +127,14 @@
/// template-parameter-list: [C++ temp]
/// template-parameter
/// template-parameter-list ',' template-parameter
-bool Parser::ParseTemplateParameterList(DeclTy* TmpDecl) {
- // FIXME: For now, this is just going to consume the template parameters.
- // Eventually, we should pass the template decl AST node as a parameter and
- // apply template parameters as we find them.
+bool
+Parser::ParseTemplateParameterList(unsigned Depth,
+ TemplateParameterList &TemplateParams) {
while(1) {
- DeclTy* TmpParam = ParseTemplateParameter();
- if(!TmpParam) {
+ if (DeclTy* TmpParam
+ = ParseTemplateParameter(Depth, TemplateParams.size())) {
+ TemplateParams.push_back(TmpParam);
+ } else {
// If we failed to parse a template parameter, skip until we find
// a comma or closing brace.
SkipUntil(tok::comma, tok::greater, true, true);
@@ -137,20 +173,21 @@
/// 'typename' identifier[opt] '=' type-id
/// 'template' '<' template-parameter-list '>' 'class' identifier[opt]
/// 'template' '<' template-parameter-list '>' 'class' identifier[opt] = id-expression
-Parser::DeclTy *Parser::ParseTemplateParameter() {
+Parser::DeclTy *
+Parser::ParseTemplateParameter(unsigned Depth, unsigned Position) {
TryAnnotateCXXScopeToken();
if(Tok.is(tok::kw_class)
|| (Tok.is(tok::kw_typename) &&
NextToken().isNot(tok::annot_qualtypename))) {
- return ParseTypeParameter();
+ return ParseTypeParameter(Depth, Position);
} else if(Tok.is(tok::kw_template)) {
- return ParseTemplateTemplateParameter();
+ return ParseTemplateTemplateParameter(Depth, Position);
} else {
// If it's none of the above, then it must be a parameter declaration.
// NOTE: This will pick up errors in the closure of the template parameter
// list (e.g., template < ; Check here to implement >> style closures.
- return ParseNonTypeTemplateParameter();
+ return ParseNonTypeTemplateParameter(Depth, Position);
}
return 0;
}
@@ -164,7 +201,7 @@
/// 'class' identifier[opt] '=' type-id
/// 'typename' identifier[opt]
/// 'typename' identifier[opt] '=' type-id
-Parser::DeclTy *Parser::ParseTypeParameter() {
+Parser::DeclTy *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) {
assert((Tok.is(tok::kw_class) || Tok.is(tok::kw_typename)) &&
"A type-parameter starts with 'class' or 'typename'");
@@ -188,13 +225,13 @@
}
DeclTy *TypeParam = Actions.ActOnTypeParameter(CurScope, TypenameKeyword,
- KeyLoc, ParamName, NameLoc);
+ KeyLoc, ParamName, NameLoc,
+ Depth, Position);
// Grab a default type id (if given).
if(Tok.is(tok::equal)) {
SourceLocation EqualLoc = ConsumeToken();
- TypeTy *DefaultType = ParseTypeName();
- if(DefaultType)
+ if (TypeTy *DefaultType = ParseTypeName())
Actions.ActOnTypeParameterDefault(TypeParam, DefaultType);
}
@@ -207,12 +244,16 @@
/// type-parameter: [C++ temp.param]
/// 'template' '<' template-parameter-list '>' 'class' identifier[opt]
/// 'template' '<' template-parameter-list '>' 'class' identifier[opt] = id-expression
-Parser::DeclTy* Parser::ParseTemplateTemplateParameter() {
+Parser::DeclTy *
+Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
assert(Tok.is(tok::kw_template) && "Expected 'template' keyword");
// Handle the template <...> part.
SourceLocation TemplateLoc = ConsumeToken();
- if(!ParseTemplateParameters(0)) {
+ TemplateParameterList TemplateParams;
+ SourceLocation LParenLoc, RParenLoc;
+ if(!ParseTemplateParameters(Depth+1, TemplateParams, LParenLoc,
+ RParenLoc)) {
return 0;
}
@@ -265,7 +306,8 @@
/// parameters.
/// FIXME: We need to make a ParseParameterDeclaration that works for
/// non-type template parameters and normal function parameters.
-Parser::DeclTy* Parser::ParseNonTypeTemplateParameter() {
+Parser::DeclTy *
+Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
SourceLocation StartLoc = Tok.getLocation();
// Parse the declaration-specifiers (i.e., the type).
@@ -288,7 +330,8 @@
}
// Create the parameter.
- DeclTy *Param = Actions.ActOnNonTypeTemplateParameter(CurScope, ParamDecl);
+ DeclTy *Param = Actions.ActOnNonTypeTemplateParameter(CurScope, ParamDecl,
+ Depth, Position);
// Is there a default value? Parsing this can be fairly annoying because
// we have to stop on the first non-nested (paren'd) '>' as the closure
Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=61413&r1=61412&r2=61413&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Tue Dec 23 20:52:09 2008
@@ -373,7 +373,9 @@
/// ParseDeclarationOrFunctionDefinition - Parse either a function-definition or
/// a declaration. We can't tell which we have until we read up to the
-/// compound-statement in function-definition.
+/// compound-statement in function-definition. TemplateParams, if
+/// non-NULL, provides the template parameters when we're parsing a
+/// C++ template-declaration.
///
/// function-definition: [C99 6.9.1]
/// decl-specs declarator declaration-list[opt] compound-statement
@@ -385,10 +387,12 @@
/// [!C99] init-declarator-list ';' [TODO: warn in c99 mode]
/// [OMP] threadprivate-directive [TODO]
///
-Parser::DeclTy *Parser::ParseDeclarationOrFunctionDefinition() {
+Parser::DeclTy *
+Parser::ParseDeclarationOrFunctionDefinition(
+ TemplateParameterLists *TemplateParams) {
// Parse the common declaration-specifiers piece.
DeclSpec DS;
- ParseDeclarationSpecifiers(DS);
+ ParseDeclarationSpecifiers(DS, TemplateParams);
// C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
// declaration-specifiers init-declarator-list[opt] ';'
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=61413&r1=61412&r2=61413&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Dec 23 20:52:09 2008
@@ -307,7 +307,8 @@
virtual DeclTy *ActOnTag(Scope *S, unsigned TagType, TagKind TK,
SourceLocation KWLoc, const CXXScopeSpec &SS,
IdentifierInfo *Name, SourceLocation NameLoc,
- AttributeList *Attr);
+ AttributeList *Attr,
+ MultiTemplateParamsArg TemplateParameterLists);
virtual void ActOnDefs(Scope *S, DeclTy *TagD, SourceLocation DeclStart,
IdentifierInfo *ClassName,
@@ -1034,9 +1035,19 @@
virtual DeclTy *ActOnTypeParameter(Scope *S, bool Typename,
SourceLocation KeyLoc,
IdentifierInfo *ParamName,
- SourceLocation ParamNameLoc);
- virtual DeclTy *ActOnNonTypeTemplateParameter(Scope *S, Declarator &D);
-
+ SourceLocation ParamNameLoc,
+ unsigned Depth, unsigned Position);
+ virtual DeclTy *ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
+ unsigned Depth,
+ unsigned Position);
+ virtual TemplateParamsTy *
+ ActOnTemplateParameterList(unsigned Depth,
+ SourceLocation ExportLoc,
+ SourceLocation TemplateLoc,
+ SourceLocation LAngleLoc,
+ DeclTy **Params, unsigned NumParams,
+ SourceLocation RAngleLoc);
+
// Objective-C declarations.
virtual DeclTy *ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
IdentifierInfo *ClassName,
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=61413&r1=61412&r2=61413&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Dec 23 20:52:09 2008
@@ -2527,7 +2527,8 @@
Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK,
SourceLocation KWLoc, const CXXScopeSpec &SS,
IdentifierInfo *Name, SourceLocation NameLoc,
- AttributeList *Attr) {
+ AttributeList *Attr,
+ MultiTemplateParamsArg TemplateParameterLists) {
// If this is not a definition, it must have a name.
assert((Name != 0 || TK == TK_Definition) &&
"Nameless record must be a definition!");
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=61413&r1=61412&r2=61413&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Dec 23 20:52:09 2008
@@ -86,7 +86,8 @@
Sema::DeclTy *Sema::ActOnTypeParameter(Scope *S, bool Typename,
SourceLocation KeyLoc,
IdentifierInfo *ParamName,
- SourceLocation ParamNameLoc) {
+ SourceLocation ParamNameLoc,
+ unsigned Depth, unsigned Position) {
assert(S->isTemplateParamScope() &&
"Template type parameter not in template parameter scope!");
bool Invalid = false;
@@ -117,7 +118,9 @@
/// template parameter (e.g., "int Size" in "template<int Size>
/// class Array") has been parsed. S is the current scope and D is
/// the parsed declarator.
-Sema::DeclTy *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D) {
+Sema::DeclTy *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
+ unsigned Depth,
+ unsigned Position) {
QualType T = GetTypeForDeclarator(D, S);
assert(S->isTemplateParamScope() &&
@@ -145,3 +148,18 @@
}
return Param;
}
+
+/// ActOnTemplateParameterList - Builds a TemplateParameterList that
+/// contains the template parameters in Params/NumParams.
+Sema::TemplateParamsTy *
+Sema::ActOnTemplateParameterList(unsigned Depth,
+ SourceLocation ExportLoc,
+ SourceLocation TemplateLoc,
+ SourceLocation LAngleLoc,
+ DeclTy **Params, unsigned NumParams,
+ SourceLocation RAngleLoc) {
+ if (ExportLoc.isValid())
+ Diag(ExportLoc, diag::note_template_export_unsupported);
+
+ return TemplateParameterList::Create(Context, (Decl**)Params, NumParams);
+}
Modified: cfe/trunk/test/Parser/cxx-template-decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-template-decl.cpp?rev=61413&r1=61412&r2=61413&view=diff
==============================================================================
--- cfe/trunk/test/Parser/cxx-template-decl.cpp (original)
+++ cfe/trunk/test/Parser/cxx-template-decl.cpp Tue Dec 23 20:52:09 2008
@@ -3,7 +3,8 @@
// Errors
export class foo { }; // expected-error {{expected template}}
template x; // expected-error {{expected '<' after 'template'}}
-export template x; // expected-error {{expected '<' after 'template'}}
+export template x; // expected-error {{expected '<' after 'template'}} \
+ // expected-note {{exported templates are unsupported}}
template < ; // expected-error {{parse error}}
template <template X> ; // expected-error {{expected '<' after 'template'}}
template <template <typename> > ; // expected-error {{expected 'class' before '>'}}
More information about the cfe-commits
mailing list