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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@128387 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index 9aada07..82c73d0 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -370,6 +370,8 @@
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 "
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index b506dba..4c422cc 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -1108,7 +1108,8 @@
bool ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
ParsedType ObjectType,
bool EnteringContext,
- bool *MayBePseudoDestructor = 0);
+ bool *MayBePseudoDestructor = 0,
+ bool IsTypename = false);
//===--------------------------------------------------------------------===//
// C++ 5.2p1: C++ Casts
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 1f41f5d..385185e 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -60,7 +60,8 @@
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 @@
}
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 ");
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 5bf0abd..c5d5ef5 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -1037,7 +1037,8 @@
// 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);
diff --git a/test/FixIt/fixit.cpp b/test/FixIt/fixit.cpp
index 41b187b..ac74985 100644
--- a/test/FixIt/fixit.cpp
+++ b/test/FixIt/fixit.cpp
@@ -78,3 +78,22 @@
}
}
+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}}
+}
+
+
diff --git a/test/Parser/MicrosoftExtensions.cpp b/test/Parser/MicrosoftExtensions.cpp
index fd0d7d5..ec297f2 100644
--- a/test/Parser/MicrosoftExtensions.cpp
+++ b/test/Parser/MicrosoftExtensions.cpp
@@ -111,3 +111,27 @@
}
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>();
+}
+
+