Improve parser recovery when we encounter a dependent template name
that is missing the 'template' keyword, e.g., 

  t->getAs<T>()

where getAs is a member of an unknown specialization. C++ requires
that we treat "getAs" as a value, but that would fail to parse since T
is the name of a type. We would then fail at the '>', since a type
cannot be followed by a '>'.

This is a very common error for C++ programmers to make, especially
since GCC occasionally allows it when it shouldn't (as does Visual
C++). So, when we are in this case, we use tentative parsing to see if
the tokens starting at "<" can only be parsed as a template argument
list. If so, we produce a diagnostic with a fix-it that states that
the 'template' keyword is needed:

test/SemaTemplate/dependent-template-recover.cpp:5:8: error: 'template' keyword
      is required to treat 'getAs' as a dependent template name
    t->getAs<T>();
       ^
       template 

This is just a start of this patch; I'd like to apply the same
approach to everywhere that a template-id with dependent template name
can be parsed.

llvm-svn: 104406
diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp
index 9319781..8b9142c 100644
--- a/clang/lib/Parse/ParseTemplate.cpp
+++ b/clang/lib/Parse/ParseTemplate.cpp
@@ -902,10 +902,12 @@
     ConsumeToken(); // the identifier
     
     if (isEndOfTemplateArgument(Tok)) {
+      bool MemberOfUnknownSpecialization;
       TemplateNameKind TNK = Actions.isTemplateName(CurScope, SS, Name, 
                                                     /*ObjectType=*/0, 
                                                     /*EnteringContext=*/false, 
-                                                    Template);
+                                                    Template,
+                                                MemberOfUnknownSpecialization);
       if (TNK == TNK_Dependent_template_name || TNK == TNK_Type_template) {
         // We have an id-expression that refers to a class template or
         // (C++0x) template alias. 
@@ -966,6 +968,32 @@
                                 ExprArg.release(), Loc);
 }
 
+/// \brief Determine whether the current tokens can only be parsed as a 
+/// template argument list (starting with the '<') and never as a '<' 
+/// expression.
+bool Parser::IsTemplateArgumentList() {
+  struct AlwaysRevertAction : TentativeParsingAction {
+    AlwaysRevertAction(Parser &P) : TentativeParsingAction(P) { }
+    ~AlwaysRevertAction() { Revert(); }
+  } Tentative(*this);
+  
+  // '<'
+  if (!Tok.is(tok::less))
+    return false;
+  ConsumeToken();
+
+  // 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.is(tok::greater) || Tok.is(tok::comma);
+}
+
 /// ParseTemplateArgumentList - Parse a C++ template-argument-list
 /// (C++ [temp.names]). Returns true if there was an error.
 ///