forked from OSchip/llvm-project
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
This commit is contained in:
parent
53ff992dde
commit
20c38a7c58
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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'}}
|
||||
|
|
|
@ -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}}
|
||||
|
|
Loading…
Reference in New Issue