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:
Francois Pichet 2011-03-27 19:41:34 +00:00
parent 5f3601d35a
commit 4e7a2c09b2
6 changed files with 57 additions and 5 deletions

View File

@ -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 "

View File

@ -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

View File

@ -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 ");

View File

@ -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);

View File

@ -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}}
}

View File

@ -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>();
}