aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/DiagnosticParseKinds.td2
-rw-r--r--include/clang/Parse/Parser.h3
-rw-r--r--lib/Parse/ParseExprCXX.cpp11
-rw-r--r--lib/Parse/Parser.cpp3
-rw-r--r--test/FixIt/fixit.cpp19
-rw-r--r--test/Parser/MicrosoftExtensions.cpp24
6 files changed, 57 insertions, 5 deletions
diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index 9aada07121..82c73d0194 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -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 "
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index b506dba037..4c422cc4b6 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -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
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 1f41f5dbc5..385185eb3a 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -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 ");
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 5bf0abd6b7..c5d5ef536d 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -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);
diff --git a/test/FixIt/fixit.cpp b/test/FixIt/fixit.cpp
index 41b187b071..ac749859ea 100644
--- a/test/FixIt/fixit.cpp
+++ b/test/FixIt/fixit.cpp
@@ -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}}
+}
+
+
diff --git a/test/Parser/MicrosoftExtensions.cpp b/test/Parser/MicrosoftExtensions.cpp
index fd0d7d50d0..ec297f2701 100644
--- a/test/Parser/MicrosoftExtensions.cpp
+++ b/test/Parser/MicrosoftExtensions.cpp
@@ -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>();
+}
+
+