Improve recovery (error + fix-it) when parsing type dependent template name without the "template" keyword.
For example: typename C1<T>:: /*template*/ Iterator<0> pos; Also the error is downgraded to an ExtWarn in Microsoft mode. llvm-svn: 128387
This commit is contained in:
parent
5f3601d35a
commit
4e7a2c09b2
|
@ -370,6 +370,8 @@ def err_enum_template : Error<"enumeration cannot be a template">;
|
|||
|
||||
def err_missing_dependent_template_keyword : Error<
|
||||
"use 'template' keyword to treat '%0' as a dependent template name">;
|
||||
def war_missing_dependent_template_keyword : ExtWarn<
|
||||
"use 'template' keyword to treat '%0' as a dependent template name">;
|
||||
|
||||
def warn_static_inline_explicit_inst_ignored : Warning<
|
||||
"ignoring '%select{static|inline}0' keyword on explicit template "
|
||||
|
|
|
@ -1108,7 +1108,8 @@ private:
|
|||
bool ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
|
||||
ParsedType ObjectType,
|
||||
bool EnteringContext,
|
||||
bool *MayBePseudoDestructor = 0);
|
||||
bool *MayBePseudoDestructor = 0,
|
||||
bool IsTypename = false);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// C++ 5.2p1: C++ Casts
|
||||
|
|
|
@ -60,7 +60,8 @@ using namespace clang;
|
|||
bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
|
||||
ParsedType ObjectType,
|
||||
bool EnteringContext,
|
||||
bool *MayBePseudoDestructor) {
|
||||
bool *MayBePseudoDestructor,
|
||||
bool IsTypename) {
|
||||
assert(getLang().CPlusPlus &&
|
||||
"Call sites of this function should be guarded by checking for C++");
|
||||
|
||||
|
@ -314,12 +315,16 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
|
|||
}
|
||||
|
||||
if (MemberOfUnknownSpecialization && (ObjectType || SS.isSet()) &&
|
||||
IsTemplateArgumentList(1)) {
|
||||
(IsTypename || 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)
|
||||
unsigned DiagID = diag::err_missing_dependent_template_keyword;
|
||||
if (getLang().Microsoft)
|
||||
DiagID = diag::war_missing_dependent_template_keyword;
|
||||
|
||||
Diag(Tok.getLocation(), DiagID)
|
||||
<< II.getName()
|
||||
<< FixItHint::CreateInsertion(Tok.getLocation(), "template ");
|
||||
|
||||
|
|
|
@ -1037,7 +1037,8 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
|
|||
// simple-template-id
|
||||
SourceLocation TypenameLoc = ConsumeToken();
|
||||
CXXScopeSpec SS;
|
||||
if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/ParsedType(), false))
|
||||
if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/ParsedType(), false,
|
||||
0, /*IsTypename*/true))
|
||||
return true;
|
||||
if (!SS.isSet()) {
|
||||
Diag(Tok.getLocation(), diag::err_expected_qualified_after_typename);
|
||||
|
|
|
@ -78,3 +78,22 @@ void f() {
|
|||
}
|
||||
}
|
||||
|
||||
template <class A>
|
||||
class F1 {
|
||||
public:
|
||||
template <int B>
|
||||
class Iterator {
|
||||
};
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class F2 {
|
||||
typename F1<T>:: /*template*/ Iterator<0> Mypos; // expected-error {{use 'template' keyword to treat 'Iterator' as a dependent template name}}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void f(){
|
||||
typename F1<T>:: /*template*/ Iterator<0> Mypos; // expected-error {{use 'template' keyword to treat 'Iterator' as a dependent template name}}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -111,3 +111,27 @@ CtorCall& CtorCall::operator=(const CtorCall& that)
|
|||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class A>
|
||||
class C1 {
|
||||
public:
|
||||
template <int B>
|
||||
class Iterator {
|
||||
};
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class C2 {
|
||||
typename C1<T>:: /*template*/ Iterator<0> Mypos; // expected-warning {{use 'template' keyword to treat 'Iterator' as a dependent template name}}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void f(){
|
||||
typename C1<T>:: /*template*/ Iterator<0> Mypos; // expected-warning {{use 'template' keyword to treat 'Iterator' as a dependent template name}}
|
||||
}
|
||||
|
||||
int main() {
|
||||
f<int>();
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue