aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Parse/ParseExprCXX.cpp25
-rw-r--r--lib/Parse/ParseTemplate.cpp7
-rw-r--r--lib/Sema/SemaTemplate.cpp1
3 files changed, 32 insertions, 1 deletions
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 1588b69bda..0a909f626f 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/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/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 8b9142ce9b..c87ddad4e9 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/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/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index b4f9c3df8b..8ff637f2d1 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/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;