Cope with use of the token '>>' inside a template argument list, e.g.,

  vector<vector<double>> Matrix;

In C++98/03, this token always means "right shift". However, if we're in
a context where we know that it can't mean "right shift", provide a
friendly reminder to put a space between the two >'s and then treat it
as two >'s as part of recovery.

In C++0x, this token is always broken into two '>' tokens.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65484 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index b6c2a71..d0808a5 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -56,16 +56,29 @@
 /// token.  This returns:
 ///
 static prec::Level getBinOpPrecedence(tok::TokenKind Kind, 
-                                      bool GreaterThanIsOperator) {
+                                      bool GreaterThanIsOperator,
+                                      bool CPlusPlus0x) {
   switch (Kind) {
   case tok::greater:
-    // The '>' token can act as either an operator or as the ending
-    // token for a template argument list.  
-    // FIXME: '>>' is similar, for error recovery and C++0x.
+    // C++ [temp.names]p3:
+    //   [...] When parsing a template-argument-list, the first
+    //   non-nested > is taken as the ending delimiter rather than a
+    //   greater-than operator. [...]
     if (GreaterThanIsOperator)
       return prec::Relational;
     return prec::Unknown;
       
+  case tok::greatergreater:
+    // C++0x [temp.names]p3:
+    //
+    //   [...] Similarly, the first non-nested >> is treated as two
+    //   consecutive but distinct > tokens, the first of which is
+    //   taken as the end of the template-argument-list and completes
+    //   the template-id. [...]
+    if (GreaterThanIsOperator || !CPlusPlus0x)
+      return prec::Shift;
+    return prec::Unknown;
+
   default:                        return prec::Unknown;
   case tok::comma:                return prec::Comma;
   case tok::equal:
@@ -90,8 +103,7 @@
   case tok::lessequal:
   case tok::less:
   case tok::greaterequal:         return prec::Relational;
-  case tok::lessless:
-  case tok::greatergreater:       return prec::Shift;
+  case tok::lessless:             return prec::Shift;
   case tok::plus:
   case tok::minus:                return prec::Additive;
   case tok::percent:
@@ -274,7 +286,9 @@
 /// LHS and has a precedence of at least MinPrec.
 Parser::OwningExprResult
 Parser::ParseRHSOfBinaryExpression(OwningExprResult LHS, unsigned MinPrec) {
-  unsigned NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator);
+  unsigned NextTokPrec = getBinOpPrecedence(Tok.getKind(), 
+                                            GreaterThanIsOperator,
+                                            getLang().CPlusPlus0x);
   SourceLocation ColonLoc;
 
   while (1) {
@@ -324,7 +338,8 @@
     // Remember the precedence of this operator and get the precedence of the
     // operator immediately to the right of the RHS.
     unsigned ThisPrec = NextTokPrec;
-    NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator);
+    NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator,
+                                     getLang().CPlusPlus0x);
 
     // Assignment and conditional expressions are right-associative.
     bool isRightAssoc = ThisPrec == prec::Conditional ||
@@ -343,7 +358,8 @@
       if (RHS.isInvalid())
         return move(RHS);
 
-      NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator);
+      NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator,
+                                       getLang().CPlusPlus0x);
     }
     assert(NextTokPrec <= ThisPrec && "Recursion didn't work!");