Fix speculative parsing of dependent template names in
nested-name-specifiers so that they don't gobble the template name (or
operator-function-id) unless there is also a
template-argument-list. For example, given

  T::template apply

we would previously consume both "template" and "apply" as part of
parsing the nested-name-specifier, then error when we see that there
is no "<" starting a template argument list. Now, we parse such
constructs tentatively, and back off if the "<" is not present. This
allows us to parse dependent template names as one would use them for,
e.g., template template parameters:

  template<typename T, template<class> class X = T::template apply>
    struct MetaSomething;

Also, test default arguments for template template parameters.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@86841 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index a7e7648..b2ecc9e 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -109,52 +109,43 @@
       if (!HasScopeSpecifier && !ObjectType)
         break;
 
+      TentativeParsingAction TPA(*this);
       SourceLocation TemplateKWLoc = ConsumeToken();
       
       UnqualifiedId TemplateName;
       if (Tok.is(tok::identifier)) {
-        TemplateName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
-        
-        // If the next token is not '<', we may have a stray 'template' keyword.
-        // Complain and suggest removing the template keyword, but otherwise
-        // allow parsing to continue.
-        if (NextToken().isNot(tok::less)) {
-          Diag(NextToken().getLocation(),
-               diag::err_less_after_template_name_in_nested_name_spec)
-            << Tok.getIdentifierInfo()->getName()
-            << CodeModificationHint::CreateRemoval(SourceRange(TemplateKWLoc));
-          break;
-        }
-        
         // Consume the identifier.
+        TemplateName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
         ConsumeToken();
       } else if (Tok.is(tok::kw_operator)) {
         if (ParseUnqualifiedIdOperator(SS, EnteringContext, ObjectType, 
-                                       TemplateName))
+                                       TemplateName)) {
+          TPA.Commit();
           break;
+        }
         
         if (TemplateName.getKind() != UnqualifiedId::IK_OperatorFunctionId) {
           Diag(TemplateName.getSourceRange().getBegin(),
                diag::err_id_after_template_in_nested_name_spec)
             << TemplateName.getSourceRange();
-          break;
-        } else if (Tok.isNot(tok::less)) {
-          std::string OperatorName = "operator ";
-          OperatorName += getOperatorSpelling(
-                                      TemplateName.OperatorFunctionId.Operator);
-          Diag(Tok.getLocation(),
-               diag::err_less_after_template_name_in_nested_name_spec)
-            << OperatorName
-            << TemplateName.getSourceRange();
+          TPA.Commit();
           break;
         }
       } else {
-        Diag(Tok.getLocation(),
-             diag::err_id_after_template_in_nested_name_spec)
-          << SourceRange(TemplateKWLoc);
+        TPA.Revert();
         break;
       }
 
+      // If the next token is not '<', we have a qualified-id that refers
+      // to a template name, such as T::template apply, but is not a 
+      // template-id.
+      if (Tok.isNot(tok::less)) {
+        TPA.Revert();
+        break;
+      }        
+      
+      // Commit to parsing the template-id.
+      TPA.Commit();
       TemplateTy Template
         = Actions.ActOnDependentTemplateName(TemplateKWLoc, SS, TemplateName,
                                              ObjectType);