diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-11-11 16:39:34 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-11-11 16:39:34 +0000 |
commit | 7bb87fca7d22a8a194d04188746b90f46512975f (patch) | |
tree | eb50a180a24ea30e45519b36021acd5512e3b218 /lib/Parse/ParseExprCXX.cpp | |
parent | d694485f9d6e3ea7b458df8241dfffd38f62aca8 (diff) |
Fix speculative parsing of dependent template names in
nested-name-specifiers so that they don't gobble the template name (or
operator-function-id) unless there is also a
template-argument-list. For example, given
T::template apply
we would previously consume both "template" and "apply" as part of
parsing the nested-name-specifier, then error when we see that there
is no "<" starting a template argument list. Now, we parse such
constructs tentatively, and back off if the "<" is not present. This
allows us to parse dependent template names as one would use them for,
e.g., template template parameters:
template<typename T, template<class> class X = T::template apply>
struct MetaSomething;
Also, test default arguments for template template parameters.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@86841 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse/ParseExprCXX.cpp')
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 43 |
1 files changed, 17 insertions, 26 deletions
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index a7e7648c1f..b2ecc9e827 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -109,52 +109,43 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, if (!HasScopeSpecifier && !ObjectType) break; + TentativeParsingAction TPA(*this); SourceLocation TemplateKWLoc = ConsumeToken(); UnqualifiedId TemplateName; if (Tok.is(tok::identifier)) { - TemplateName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation()); - - // If the next token is not '<', we may have a stray 'template' keyword. - // Complain and suggest removing the template keyword, but otherwise - // allow parsing to continue. - if (NextToken().isNot(tok::less)) { - Diag(NextToken().getLocation(), - diag::err_less_after_template_name_in_nested_name_spec) - << Tok.getIdentifierInfo()->getName() - << CodeModificationHint::CreateRemoval(SourceRange(TemplateKWLoc)); - break; - } - // Consume the identifier. + TemplateName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation()); ConsumeToken(); } else if (Tok.is(tok::kw_operator)) { if (ParseUnqualifiedIdOperator(SS, EnteringContext, ObjectType, - TemplateName)) + TemplateName)) { + TPA.Commit(); break; + } if (TemplateName.getKind() != UnqualifiedId::IK_OperatorFunctionId) { Diag(TemplateName.getSourceRange().getBegin(), diag::err_id_after_template_in_nested_name_spec) << TemplateName.getSourceRange(); - break; - } else if (Tok.isNot(tok::less)) { - std::string OperatorName = "operator "; - OperatorName += getOperatorSpelling( - TemplateName.OperatorFunctionId.Operator); - Diag(Tok.getLocation(), - diag::err_less_after_template_name_in_nested_name_spec) - << OperatorName - << TemplateName.getSourceRange(); + TPA.Commit(); break; } } else { - Diag(Tok.getLocation(), - diag::err_id_after_template_in_nested_name_spec) - << SourceRange(TemplateKWLoc); + TPA.Revert(); break; } + // If the next token is not '<', we have a qualified-id that refers + // to a template name, such as T::template apply, but is not a + // template-id. + if (Tok.isNot(tok::less)) { + TPA.Revert(); + break; + } + + // Commit to parsing the template-id. + TPA.Commit(); TemplateTy Template = Actions.ActOnDependentTemplateName(TemplateKWLoc, SS, TemplateName, ObjectType); |