diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-05-21 23:43:39 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-05-21 23:43:39 +0000 |
commit | 20c38a7c5870d300a4d713c13ac5e761d61d04d7 (patch) | |
tree | 8dbe947280a848c69a762ab51387ceb3c59e0b76 /clang | |
parent | 53ff992dde7d169ab1334264d2c542478d6b3706 (diff) | |
download | bcm5719-llvm-20c38a7c5870d300a4d713c13ac5e761d61d04d7.tar.gz bcm5719-llvm-20c38a7c5870d300a4d713c13ac5e761d61d04d7.zip |
Improve recovery when we see a dependent template name that is missing
the required "template" keyword, using the same heuristics we do for
dependent template names in member access expressions, e.g.,
test/SemaTemplate/dependent-template-recover.cpp:11:8: error: use 'template'
keyword to treat 'getAs' as a dependent template name
T::getAs<U>();
^
template
Fixes PR5404.
llvm-svn: 104409
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/Parse/Parser.h | 2 | ||||
-rw-r--r-- | clang/lib/Parse/ParseExprCXX.cpp | 25 | ||||
-rw-r--r-- | clang/lib/Parse/ParseTemplate.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 1 | ||||
-rw-r--r-- | clang/test/SemaTemplate/dependent-base-classes.cpp | 2 | ||||
-rw-r--r-- | clang/test/SemaTemplate/dependent-template-recover.cpp | 3 |
6 files changed, 37 insertions, 3 deletions
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index ea263f94e13..646f84021dd 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -1463,7 +1463,7 @@ private: SourceLocation TemplateKWLoc = SourceLocation(), bool AllowTypeAnnotation = true); void AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS = 0); - bool IsTemplateArgumentList(); + bool IsTemplateArgumentList(unsigned Skip = 0); bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs); ParsedTemplateArgument ParseTemplateTemplateArgument(); ParsedTemplateArgument ParseTemplateArgument(); diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 1588b69bdaa..0a909f626ff 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -307,6 +307,31 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, SourceLocation(), false)) return true; continue; + } + + if (MemberOfUnknownSpecialization && (ObjectType || SS.isSet()) && + IsTemplateArgumentList(1)) { + // We have something like t::getAs<T>, where getAs is a + // member of an unknown specialization. However, this will only + // parse correctly as a template, so suggest the keyword 'template' + // before 'getAs' and treat this as a dependent template name. + Diag(Tok.getLocation(), diag::err_missing_dependent_template_keyword) + << II.getName() + << FixItHint::CreateInsertion(Tok.getLocation(), "template "); + + Template = Actions.ActOnDependentTemplateName(Tok.getLocation(), SS, + TemplateName, ObjectType, + EnteringContext); + if (!Template.get()) + return true; + + // Consume the identifier. + ConsumeToken(); + if (AnnotateTemplateIdToken(Template, TNK_Dependent_template_name, &SS, + TemplateName, SourceLocation(), false)) + return true; + + continue; } } diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp index 8b9142ce9bd..c87ddad4e9b 100644 --- a/clang/lib/Parse/ParseTemplate.cpp +++ b/clang/lib/Parse/ParseTemplate.cpp @@ -971,12 +971,17 @@ ParsedTemplateArgument Parser::ParseTemplateArgument() { /// \brief Determine whether the current tokens can only be parsed as a /// template argument list (starting with the '<') and never as a '<' /// expression. -bool Parser::IsTemplateArgumentList() { +bool Parser::IsTemplateArgumentList(unsigned Skip) { struct AlwaysRevertAction : TentativeParsingAction { AlwaysRevertAction(Parser &P) : TentativeParsingAction(P) { } ~AlwaysRevertAction() { Revert(); } } Tentative(*this); + while (Skip) { + ConsumeToken(); + --Skip; + } + // '<' if (!Tok.is(tok::less)) return false; diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index b4f9c3df8b4..8ff637f2d11 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -175,6 +175,7 @@ bool Sema::DiagnoseUnknownTemplateName(const IdentifierInfo &II, TemplateNameKind &SuggestedKind) { // We can't recover unless there's a dependent scope specifier preceding the // template name. + // FIXME: Typo correction? if (!SS || !SS->isSet() || !isDependentScopeSpecifier(*SS) || computeDeclContext(*SS)) return false; diff --git a/clang/test/SemaTemplate/dependent-base-classes.cpp b/clang/test/SemaTemplate/dependent-base-classes.cpp index d0dd9c98fa7..e64d62301ea 100644 --- a/clang/test/SemaTemplate/dependent-base-classes.cpp +++ b/clang/test/SemaTemplate/dependent-base-classes.cpp @@ -6,7 +6,7 @@ struct X0 : T::template apply<U> { }; template<typename T, typename U> -struct X1 : T::apply<U> { }; // expected-error{{missing 'template' keyword prior to dependent template name 'T::apply'}} +struct X1 : T::apply<U> { }; // expected-error{{use 'template' keyword to treat 'apply' as a dependent template name}} template<typename T> struct X2 : vector<T> { }; // expected-error{{unknown template name 'vector'}} diff --git a/clang/test/SemaTemplate/dependent-template-recover.cpp b/clang/test/SemaTemplate/dependent-template-recover.cpp index 632a11b2e06..e91ffb52539 100644 --- a/clang/test/SemaTemplate/dependent-template-recover.cpp +++ b/clang/test/SemaTemplate/dependent-template-recover.cpp @@ -8,6 +8,9 @@ struct X { t->operator+<U const, 1>(); // expected-error{{use 'template' keyword to treat 'operator +' as a dependent template name}} t->f1<int const, 2>(); // expected-error{{use 'template' keyword to treat 'f1' as a dependent template name}} + T::getAs<U>(); // expected-error{{use 'template' keyword to treat 'getAs' as a dependent template name}} + t->T::getAs<U>(); // expected-error{{use 'template' keyword to treat 'getAs' as a dependent template name}} + // FIXME: We can't recover from these yet (*t).f2<N>(); // expected-error{{expected expression}} (*t).f2<0>(); // expected-error{{expected expression}} |