nikola created this revision.
nikola added a reviewer: rsmith.
nikola added a subscriber: cfe-commits.
Current diagnostic says "expected expression" or "reference to non-static
member function must be called". This should fix PR13566 and PR18995
http://reviews.llvm.org/D15509
Files:
lib/Parse/ParseTemplate.cpp
lib/Parse/RAIIObjectsForParser.h
test/SemaTemplate/dependent-template-recover.cpp
Index: test/SemaTemplate/dependent-template-recover.cpp
===================================================================
--- test/SemaTemplate/dependent-template-recover.cpp
+++ test/SemaTemplate/dependent-template-recover.cpp
@@ -11,12 +11,35 @@
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}}
+ (*t).f2<N>(); // expected-error{{use 'template' keyword to treat 'f2' as a dependent template name}}
+ (*t).f2<0>(); // expected-error{{use 'template' keyword to treat 'f2' as a dependent template name}}
}
};
+namespace PR13566 {
+template <typename T>
+struct S
+{
+ template <int N>
+ void foo();
+
+ template <int N>
+ void foo(int);
+};
+
+template <typename T>
+void bar()
+{
+ S<T> s;
+ s.foo<1>(); // expected-error{{use 'template' keyword to treat 'foo' as a dependent template name}}
+ s.foo<1>(0); // expected-error{{use 'template' keyword to treat 'foo' as a dependent template name}}
+}
+
+void instantiate() {
+ bar<int>();
+}
+}
+
namespace PR9401 {
// From GCC PR c++/45558
template <typename S, typename T>
Index: lib/Parse/RAIIObjectsForParser.h
===================================================================
--- lib/Parse/RAIIObjectsForParser.h
+++ lib/Parse/RAIIObjectsForParser.h
@@ -442,6 +442,18 @@
void skipToEnd();
};
+ /// \brief RAII object that suppresses all diagnostics
+ class SuppressAllDiagnostics {
+ DiagnosticsEngine &Diags;
+ bool OldVal;
+ public:
+ SuppressAllDiagnostics(DiagnosticsEngine &Diags) : Diags(Diags) {
+ OldVal = Diags.getSuppressAllDiagnostics();
+ Diags.setSuppressAllDiagnostics(true);
+ }
+ ~SuppressAllDiagnostics() { Diags.setSuppressAllDiagnostics(OldVal); }
+ };
+
} // end namespace clang
#endif
Index: lib/Parse/ParseTemplate.cpp
===================================================================
--- lib/Parse/ParseTemplate.cpp
+++ lib/Parse/ParseTemplate.cpp
@@ -1209,34 +1209,35 @@
ExprArg.get(), Loc);
}
-/// \brief Determine whether the current tokens can only be parsed as a
-/// template argument list (starting with the '<') and never as a '<'
-/// expression.
+/// \brief Determine whether the current tokens (starting with the '<') can be
+/// parsed as a template argument list
bool Parser::IsTemplateArgumentList(unsigned Skip) {
struct AlwaysRevertAction : TentativeParsingAction {
AlwaysRevertAction(Parser &P) : TentativeParsingAction(P) { }
~AlwaysRevertAction() { Revert(); }
} Tentative(*this);
-
+
while (Skip) {
ConsumeToken();
--Skip;
}
-
+
// '<'
if (!TryConsumeToken(tok::less))
return false;
// An empty template argument list.
if (Tok.is(tok::greater))
return true;
-
- // See whether we have declaration specifiers, which indicate a type.
- while (isCXXDeclarationSpecifier() == TPResult::True)
- ConsumeToken();
-
- // If we have a '>' or a ',' then this is a template argument list.
- return Tok.isOneOf(tok::greater, tok::comma);
+
+ SuppressAllDiagnostics S(Diags);
+ GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);
+ TemplateArgList TemplateArgs;
+ if (ParseTemplateArgumentList(TemplateArgs))
+ return false;
+
+ // Closing '>'
+ return Tok.is(tok::greater);
}
/// ParseTemplateArgumentList - Parse a C++ template-argument-list
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits