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 cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits