aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse/ParseTemplate.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-11-11 01:00:40 +0000
committerDouglas Gregor <dgregor@apple.com>2009-11-11 01:00:40 +0000
commit788cd06cf8e868a67158aafec5de3a1f408d14f3 (patch)
tree840b782d099e23e673436d5984883230afe3849c /lib/Parse/ParseTemplate.cpp
parent5ee0aa715db363a7cdab112627fdd373f477b4df (diff)
Introduce a new representation for template template
parameters. Rather than storing them as either declarations (for the non-dependent case) or expressions (for the dependent case), we now (always) store them as TemplateNames. The primary change here is to add a new kind of TemplateArgument, which stores a TemplateName. However, making that change ripples to every switch on a TemplateArgument's kind, also affecting TemplateArgumentLocInfo/TemplateArgumentLoc, default template arguments for template template parameters, type-checking of template template arguments, etc. This change is light on testing. It should fix several pre-existing problems with template template parameters, such as: - the inability to use dependent template names as template template arguments - template template parameter default arguments cannot be instantiation However, there are enough pieces missing that more implementation is required before we can adequately test template template parameters. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@86777 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse/ParseTemplate.cpp')
-rw-r--r--lib/Parse/ParseTemplate.cpp163
1 files changed, 90 insertions, 73 deletions
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index cf7d511697..b5063ee44b 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -485,12 +485,17 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
// Get the a default value, if given.
if (Tok.is(tok::equal)) {
SourceLocation EqualLoc = ConsumeToken();
- OwningExprResult DefaultExpr = ParseCXXIdExpression();
- if (DefaultExpr.isInvalid())
+ ParsedTemplateArgument Default = ParseTemplateTemplateArgument();
+ if (Default.isInvalid()) {
+ Diag(Tok.getLocation(),
+ diag::err_default_template_template_parameter_not_template);
+ static tok::TokenKind EndToks[] = {
+ tok::comma, tok::greater, tok::greatergreater
+ };
+ SkipUntil(EndToks, 3, true, true);
return Param;
- else if (Param)
- Actions.ActOnTemplateTemplateParameterDefault(Param, EqualLoc,
- move(DefaultExpr));
+ } else if (Param)
+ Actions.ActOnTemplateTemplateParameterDefault(Param, EqualLoc, Default);
}
return Param;
@@ -808,33 +813,16 @@ static bool isEndOfTemplateArgument(Token Tok) {
Tok.is(tok::greatergreater);
}
-/// ParseTemplateArgument - Parse a C++ template argument (C++ [temp.names]).
-///
-/// template-argument: [C++ 14.2]
-/// constant-expression
-/// type-id
-/// id-expression
-ParsedTemplateArgument Parser::ParseTemplateArgument() {
- // C++ [temp.arg]p2:
- // In a template-argument, an ambiguity between a type-id and an
- // expression is resolved to a type-id, regardless of the form of
- // the corresponding template-parameter.
- //
- // Therefore, we initially try to parse a type-id.
- if (isCXXTypeId(TypeIdAsTemplateArgument)) {
- SourceLocation Loc = Tok.getLocation();
- TypeResult TypeArg = ParseTypeName();
- if (TypeArg.isInvalid())
- return ParsedTemplateArgument();
-
- return ParsedTemplateArgument(ParsedTemplateArgument::Type, TypeArg.get(),
- Loc);
- }
+/// \brief Parse a C++ template template argument.
+ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() {
+ if (!Tok.is(tok::identifier) && !Tok.is(tok::coloncolon) &&
+ !Tok.is(tok::annot_cxxscope))
+ return ParsedTemplateArgument();
// C++0x [temp.arg.template]p1:
// A template-argument for a template template-parameter shall be the name
// of a class template or a template alias, expressed as id-expression.
- //
+ //
// We perform some tentative parsing at this point, to determine whether
// we have an id-expression that refers to a class template or template
// alias. The grammar we tentatively parse is:
@@ -843,63 +831,92 @@ ParsedTemplateArgument Parser::ParseTemplateArgument() {
//
// followed by a token that terminates a template argument, such as ',',
// '>', or (in some cases) '>>'.
- if (Tok.is(tok::identifier) || Tok.is(tok::coloncolon) ||
- Tok.is(tok::annot_cxxscope)) {
- TentativeParsingAction TPA(*this);
- CXXScopeSpec SS; // nested-name-specifier, if present
- ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0,
- /*EnteringContext=*/false);
-
- if (SS.isSet() && Tok.is(tok::kw_template)) {
- // Parse the optional 'template' keyword following the
- // nested-name-specifier.
- SourceLocation TemplateLoc = ConsumeToken();
-
- if (Tok.is(tok::identifier)) {
- // We appear to have a dependent template name.
- UnqualifiedId Name;
- Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
- ConsumeToken(); // the identifier
-
- // If the next token signals the end of a template argument,
- // then we have a dependent template name that could be a template
- // template argument.
- if (isEndOfTemplateArgument(Tok)) {
- TemplateTy Template
- = Actions.ActOnDependentTemplateName(TemplateLoc, SS, Name,
- /*ObjectType=*/0);
- if (Template.get()) {
- TPA.Commit();
- return ParsedTemplateArgument(SS, Template, Name.StartLocation);
- }
- }
- }
- } else if (Tok.is(tok::identifier)) {
- // We may have a (non-dependent) template name.
- TemplateTy Template;
+ TentativeParsingAction TPA(*this);
+ CXXScopeSpec SS; // nested-name-specifier, if present
+ ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0,
+ /*EnteringContext=*/false);
+
+ if (SS.isSet() && Tok.is(tok::kw_template)) {
+ // Parse the optional 'template' keyword following the
+ // nested-name-specifier.
+ SourceLocation TemplateLoc = ConsumeToken();
+
+ if (Tok.is(tok::identifier)) {
+ // We appear to have a dependent template name.
UnqualifiedId Name;
Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
ConsumeToken(); // the identifier
-
+
+ // If the next token signals the end of a template argument,
+ // then we have a dependent template name that could be a template
+ // template argument.
if (isEndOfTemplateArgument(Tok)) {
- TemplateNameKind TNK = Actions.isTemplateName(CurScope, SS, Name,
- /*ObjectType=*/0,
- /*EnteringContext=*/false,
- Template);
- if (TNK == TNK_Dependent_template_name || TNK == TNK_Type_template) {
- // We have an id-expression that refers to a class template or
- // (C++0x) template alias.
+ TemplateTy Template
+ = Actions.ActOnDependentTemplateName(TemplateLoc, SS, Name,
+ /*ObjectType=*/0);
+ if (Template.get()) {
TPA.Commit();
return ParsedTemplateArgument(SS, Template, Name.StartLocation);
}
}
+ }
+ } else if (Tok.is(tok::identifier)) {
+ // We may have a (non-dependent) template name.
+ TemplateTy Template;
+ UnqualifiedId Name;
+ Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
+ ConsumeToken(); // the identifier
+
+ if (isEndOfTemplateArgument(Tok)) {
+ TemplateNameKind TNK = Actions.isTemplateName(CurScope, SS, Name,
+ /*ObjectType=*/0,
+ /*EnteringContext=*/false,
+ Template);
+ if (TNK == TNK_Dependent_template_name || TNK == TNK_Type_template) {
+ // We have an id-expression that refers to a class template or
+ // (C++0x) template alias.
+ TPA.Commit();
+ return ParsedTemplateArgument(SS, Template, Name.StartLocation);
+ }
}
+ }
+
+ // We don't have a template template argument; revert everything we have
+ // tentatively parsed.
+ TPA.Revert();
+
+ return ParsedTemplateArgument();
+}
+
+/// ParseTemplateArgument - Parse a C++ template argument (C++ [temp.names]).
+///
+/// template-argument: [C++ 14.2]
+/// constant-expression
+/// type-id
+/// id-expression
+ParsedTemplateArgument Parser::ParseTemplateArgument() {
+ // C++ [temp.arg]p2:
+ // In a template-argument, an ambiguity between a type-id and an
+ // expression is resolved to a type-id, regardless of the form of
+ // the corresponding template-parameter.
+ //
+ // Therefore, we initially try to parse a type-id.
+ if (isCXXTypeId(TypeIdAsTemplateArgument)) {
+ SourceLocation Loc = Tok.getLocation();
+ TypeResult TypeArg = ParseTypeName();
+ if (TypeArg.isInvalid())
+ return ParsedTemplateArgument();
- // We don't have a template template argument; revert everything we have
- // tentatively parsed.
- TPA.Revert();
+ return ParsedTemplateArgument(ParsedTemplateArgument::Type, TypeArg.get(),
+ Loc);
}
+ // Try to parse a template template argument.
+ ParsedTemplateArgument TemplateTemplateArgument
+ = ParseTemplateTemplateArgument();
+ if (!TemplateTemplateArgument.isInvalid())
+ return TemplateTemplateArgument;
+
// Parse a non-type template argument.
SourceLocation Loc = Tok.getLocation();
OwningExprResult ExprArg = ParseConstantExpression();