[cfe-commits] r60387 - in /cfe/trunk: include/clang/Parse/Action.h include/clang/Parse/DeclSpec.h include/clang/Parse/Scope.h lib/Parse/ParseTemplate.cpp test/Parser/cxx-template-decl.cpp
Douglas Gregor
doug.gregor at gmail.com
Mon Dec 1 16:41:28 PST 2008
Author: dgregor
Date: Mon Dec 1 18:41:28 2008
New Revision: 60387
URL: http://llvm.org/viewvc/llvm-project?rev=60387&view=rev
Log:
A little more scaffolding for parsing templates:
- Template parameter scope to hold the template parameters
- Template parameter context for parsing declarators
- Actions for template type parameters and non-type template
parameters
Modified:
cfe/trunk/include/clang/Parse/Action.h
cfe/trunk/include/clang/Parse/DeclSpec.h
cfe/trunk/include/clang/Parse/Scope.h
cfe/trunk/lib/Parse/ParseTemplate.cpp
cfe/trunk/test/Parser/cxx-template-decl.cpp
Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=60387&r1=60386&r2=60387&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Mon Dec 1 18:41:28 2008
@@ -852,6 +852,37 @@
virtual void ActOnFinishCXXClassDef(DeclTy *TagDecl) {
}
+ //===---------------------------C++ Templates----------------------------===//
+
+ /// ActOnTypeParameter - Called when a C++ template type parameter
+ /// (e.g., "typename T") has been parsed. Typename specifies whether
+ /// the keyword "typename" was used to declare the type parameter
+ /// (otherwise, "class" was used), and KeyLoc is the location of the
+ /// "class" or "typename" keyword. ParamName is the name of the
+ /// 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.
+ virtual DeclTy *ActOnTypeParameter(Scope *S, bool Typename,
+ SourceLocation KeyLoc,
+ IdentifierInfo *ParamName,
+ SourceLocation ParamNameLoc) {
+ return 0;
+ }
+
+ /// ActOnTypeParameterDefault - Adds a default argument (the type
+ /// Default) to the given template type parameter (TypeParam).
+ virtual void ActOnTypeParameterDefault(DeclTy *TypeParam, TypeTy *Default) {
+ }
+
+ /// 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) {
+ return 0;
+ }
+
//===----------------------- Obj-C Declarations -------------------------===//
// ActOnStartClassInterface - this action is called immediately after parsing
Modified: cfe/trunk/include/clang/Parse/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/DeclSpec.h?rev=60387&r1=60386&r2=60387&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Parse/DeclSpec.h Mon Dec 1 18:41:28 2008
@@ -631,7 +631,8 @@
MemberContext, // Struct/Union field.
BlockContext, // Declaration within a block in a function.
ForContext, // Declaration within first part of a for loop.
- ConditionContext // Condition declaration in a C++ if/switch/while/for.
+ ConditionContext, // Condition declaration in a C++ if/switch/while/for.
+ TemplateParamContext // Within a template parameter list.
};
/// DeclaratorKind - The kind of declarator this represents.
@@ -743,9 +744,11 @@
}
/// mayOmitIdentifier - Return true if the identifier is either optional or
- /// not allowed. This is true for typenames and prototypes.
+ /// not allowed. This is true for typenames, prototypes, and template
+ /// parameter lists.
bool mayOmitIdentifier() const {
- return Context == TypeNameContext || Context == PrototypeContext;
+ return Context == TypeNameContext || Context == PrototypeContext ||
+ Context == TemplateParamContext;
}
/// mayHaveIdentifier - Return true if the identifier is either optional or
Modified: cfe/trunk/include/clang/Parse/Scope.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Scope.h?rev=60387&r1=60386&r2=60387&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Scope.h (original)
+++ cfe/trunk/include/clang/Parse/Scope.h Mon Dec 1 18:41:28 2008
@@ -54,7 +54,13 @@
/// Blocks serve as top-level scopes for some objects like labels, they
/// also prevent things like break and continue. BlockScopes have the
/// other flags set as well.
- BlockScope = 0x40
+ BlockScope = 0x40,
+
+ /// TemplateParamScope - This is a scope that corresponds to the
+ /// template parameters of a C++ template. Template parameter
+ /// scope starts at the 'template' keyword and ends when the
+ /// template declaration ends.
+ TemplateParamScope = 0x80
};
private:
/// The parent scope for this scope. This is null for the translation-unit
@@ -172,6 +178,12 @@
return false;
}
+ /// isTemplateParamScope - Return true if this scope is a C++
+ /// template parameter scope.
+ bool isTemplateParamScope() const {
+ return getFlags() & Scope::TemplateParamScope;
+ }
+
/// Init - This is used by the parser to implement scope caching.
///
void Init(Scope *Parent, unsigned ScopeFlags) {
Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=60387&r1=60386&r2=60387&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTemplate.cpp Mon Dec 1 18:41:28 2008
@@ -40,15 +40,19 @@
}
SourceLocation TemplateLoc = ConsumeToken();
- // Try to parse the template parameters, and the declaration if successful.
- if(ParseTemplateParameters(0)) {
- // For some reason, this is generating a compiler error when parsing the
- // declaration. Apparently, ParseDeclaration doesn't want to match a
- // function-definition, but will match a function declaration.
- // TODO: ParseDeclarationOrFunctionDefinition
- return ParseDeclaration(Context);
- }
- return 0;
+ // Enter template-parameter scope.
+ EnterScope(Scope::TemplateParamScope|Scope::DeclScope);
+
+ // Try to parse the template parameters, and the declaration if
+ // successful.
+ DeclTy *TemplateDecl = 0;
+ if(ParseTemplateParameters(0))
+ TemplateDecl = ParseDeclarationOrFunctionDefinition();
+
+ // Leave template-parameter scope.
+ ExitScope();
+
+ return TemplateDecl;
}
/// ParseTemplateParameters - Parses a template-parameter-list enclosed in
@@ -153,13 +157,19 @@
/// 'typename' identifier[opt]
/// 'typename' identifier[opt] '=' type-id
Parser::DeclTy *Parser::ParseTypeParameter() {
- SourceLocation keyLoc = ConsumeToken();
+ assert((Tok.is(tok::kw_class) || Tok.is(tok::kw_typename)) &&
+ "A type-parameter starts with 'class' or 'typename'");
+
+ // Consume the 'class' or 'typename' keyword.
+ bool TypenameKeyword = Tok.is(tok::kw_typename);
+ SourceLocation KeyLoc = ConsumeToken();
// Grab the template parameter name (if given)
- IdentifierInfo* paramName = 0;
+ SourceLocation NameLoc;
+ IdentifierInfo* ParamName = 0;
if(Tok.is(tok::identifier)) {
- paramName = Tok.getIdentifierInfo();
- ConsumeToken();
+ ParamName = Tok.getIdentifierInfo();
+ NameLoc = ConsumeToken();
} else if(Tok.is(tok::equal) || Tok.is(tok::comma) ||
Tok.is(tok::greater)) {
// Unnamed template parameter. Don't have to do anything here, just
@@ -169,17 +179,18 @@
return 0;
}
+ DeclTy *TypeParam = Actions.ActOnTypeParameter(CurScope, TypenameKeyword,
+ KeyLoc, ParamName, NameLoc);
+
// Grab a default type id (if given).
- TypeTy* defaultType = 0;
if(Tok.is(tok::equal)) {
- ConsumeToken();
- defaultType = ParseTypeName();
- if(!defaultType)
- return 0;
+ SourceLocation EqualLoc = ConsumeToken();
+ TypeTy *DefaultType = ParseTypeName();
+ if(DefaultType)
+ Actions.ActOnTypeParameterDefault(TypeParam, DefaultType);
}
- // FIXME: Add an action for type parameters.
- return 0;
+ return TypeParam;
}
/// ParseTemplateTemplateParameter - Handle the parsing of template
@@ -244,22 +255,21 @@
/// but that didn't work out to well. Instead, this tries to recrate the basic
/// parsing of parameter declarations, but tries to constrain it for template
/// parameters.
-/// FIXME: We need to make ParseParameterDeclaration work for non-type
-/// template parameters, too.
-Parser::DeclTy* Parser::ParseNonTypeTemplateParameter()
-{
- SourceLocation startLoc = Tok.getLocation();
+/// FIXME: We need to make a ParseParameterDeclaration that works for
+/// non-type template parameters and normal function parameters.
+Parser::DeclTy* Parser::ParseNonTypeTemplateParameter() {
+ SourceLocation StartLoc = Tok.getLocation();
// Parse the declaration-specifiers (i.e., the type).
- // FIXME:: The type should probably be restricted in some way... Not all
+ // FIXME: The type should probably be restricted in some way... Not all
// declarators (parts of declarators?) are accepted for parameters.
- DeclSpec ds;
- ParseDeclarationSpecifiers(ds);
+ DeclSpec DS;
+ ParseDeclarationSpecifiers(DS);
// Parse this as a typename.
- Declarator decl(ds, Declarator::TypeNameContext);
- ParseDeclarator(decl);
- if(ds.getTypeSpecType() == DeclSpec::TST_unspecified && !ds.getTypeRep()) {
+ Declarator ParamDecl(DS, Declarator::TemplateParamContext);
+ ParseDeclarator(ParamDecl);
+ if(DS.getTypeSpecType() == DeclSpec::TST_unspecified && !DS.getTypeRep()) {
// This probably shouldn't happen - and it's more of a Sema thing, but
// basically we didn't parse the type name because we couldn't associate
// it with an AST node. we should just skip to the comma or greater.
@@ -269,11 +279,8 @@
return 0;
}
- // If there's an identifier after the typename, parse that as part of the
- // declarator - or something.
- if(Tok.is(tok::identifier)) {
- ConsumeToken();
- }
+ // Create the parameter.
+ DeclTy *Param = Actions.ActOnNonTypeTemplateParameter(CurScope, ParamDecl);
// 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
@@ -283,6 +290,5 @@
SkipUntil(tok::comma, tok::greater, true, true);
}
- // FIXME: Add an action for non-type template parameters.
- return 0;
+ return Param;
}
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=60387&r1=60386&r2=60387&view=diff
==============================================================================
--- cfe/trunk/test/Parser/cxx-template-decl.cpp (original)
+++ cfe/trunk/test/Parser/cxx-template-decl.cpp Mon Dec 1 18:41:28 2008
@@ -13,9 +13,8 @@
template <typename T> void foo();
template <typename T, typename U> void foo();
-// TODO Implement ParseDeclarationOrFunction()
-// Template function definitions. Not done yet.
-// template <typename T> void foo() { }
+// Template function definitions.
+template <typename T> void foo() { }
// Template class (forward) declarations
template <typename T> struct A;
More information about the cfe-commits
mailing list